/
githubmirror
/
novu
Обзор
Документация
Войти
/
githubmirror
/
novu
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
next
libs/application-generic/src/utils/create-schema.ts
207 строк
7 KB
Pawan Jain
feat(dashboard): support actor variables in step content editor fixes NV-8143 (#11709)
30 июн 2026, 18:37
Не верифицирован
30 июн 2026, 18:37
71c8456
Код
Авторство
О чём код?
import { JsonSchemaFormatEnum, JsonSchemaTypeEnum } from '@novu/dal'; import { SeverityLevelEnum } from '@novu/shared'; import { JSONSchemaDto } from '../dtos/json-schema.dto'; function determineSchemaType(value: unknown): JSONSchemaDto { if (value === null) { return { type: JsonSchemaTypeEnum.NULL }; } if (Array.isArray(value)) { return { type: JsonSchemaTypeEnum.ARRAY, items: value.length > 0 ? determineSchemaType(value[0]) : { type: JsonSchemaTypeEnum.ARRAY }, }; } switch (typeof value) { case 'string': return { type: JsonSchemaTypeEnum.STRING, default: value }; case 'number': return { type: JsonSchemaTypeEnum.NUMBER, default: value }; case 'boolean': return { type: JsonSchemaTypeEnum.BOOLEAN, default: value }; case 'object': return { type: JsonSchemaTypeEnum.OBJECT, properties: Object.entries(value).reduce( (acc, [key, val]) => { acc[key] = determineSchemaType(val); return acc; }, {} as { [key: string]: JSONSchemaDto } ), required: Object.keys(value), }; default: return { type: JsonSchemaTypeEnum.NULL }; } } export function buildVariablesSchema(object: unknown) { const schema: JSONSchemaDto = { type: JsonSchemaTypeEnum.OBJECT, properties: {}, required: [], additionalProperties: true, }; if (object) { for (const [key, value] of Object.entries(object)) { if (schema.properties && schema.required) { schema.properties[key] = determineSchemaType(value); schema.required.push(key); } } } return schema; } export const buildActorSchema = (actor: unknown) => { const subscriberSchema = buildSubscriberSchema(actor); return { ...subscriberSchema, description: 'Schema representing the actor entity sent during workflow trigger', }; }; export const buildSubscriberSchema = (subscriber: unknown) => { return { type: JsonSchemaTypeEnum.OBJECT, description: 'Schema representing the subscriber entity', properties: { firstName: { type: JsonSchemaTypeEnum.STRING, description: "Subscriber's first name" }, lastName: { type: JsonSchemaTypeEnum.STRING, description: "Subscriber's last name" }, email: { type: JsonSchemaTypeEnum.STRING, description: "Subscriber's email address" }, phone: { type: JsonSchemaTypeEnum.STRING, description: "Subscriber's phone number (optional)" }, avatar: { type: JsonSchemaTypeEnum.STRING, description: "URL to the subscriber's avatar image (optional)" }, locale: { type: JsonSchemaTypeEnum.STRING, description: 'Locale for the subscriber (optional)' }, timezone: { type: JsonSchemaTypeEnum.STRING, description: 'Timezone for the subscriber (optional)' }, subscriberId: { type: JsonSchemaTypeEnum.STRING, description: 'Unique identifier for the subscriber' }, isOnline: { type: JsonSchemaTypeEnum.BOOLEAN, description: 'Indicates if the subscriber is online (optional)', }, lastOnlineAt: { type: JsonSchemaTypeEnum.STRING, format: JsonSchemaFormatEnum.DATETIME, description: 'The last time the subscriber was online (optional)', }, data: buildVariablesSchema( subscriber && typeof subscriber === 'object' && 'data' in subscriber ? subscriber.data : {} ), }, required: ['subscriberId'], additionalProperties: false, }; }; export const buildWorkflowSchema = () => { return { type: JsonSchemaTypeEnum.OBJECT, description: 'Schema representing the workflow entity', properties: { workflowId: { type: JsonSchemaTypeEnum.STRING, description: 'Workflow identifier' }, name: { type: JsonSchemaTypeEnum.STRING, description: 'Name of the workflow' }, description: { type: JsonSchemaTypeEnum.STRING, description: 'Description of the workflow' }, tags: { type: JsonSchemaTypeEnum.ARRAY, items: { type: JsonSchemaTypeEnum.STRING } }, severity: { type: JsonSchemaTypeEnum.STRING, enum: [...Object.values(SeverityLevelEnum)], enumName: 'SeverityLevelEnum', description: 'Severity of the workflow', }, }, required: ['workflowId', 'name'], }; }; export const buildEnvSchema = (envVars: Record<string, string>): JSONSchemaDto => { const properties: Record<string, JSONSchemaDto> = {}; for (const key of Object.keys(envVars)) { properties[key] = { type: JsonSchemaTypeEnum.STRING, description: `Environment variable: ${key}` }; } return { type: JsonSchemaTypeEnum.OBJECT, description: 'Environment variables accessible in workflow templates', properties, required: [], additionalProperties: false, }; }; export const buildContextSchema = (context?: unknown) => { const baseSchema = { type: JsonSchemaTypeEnum.OBJECT, description: 'Context data passed at trigger time following ContextPayload structure', properties: {} as Record<string, JSONSchemaDto>, required: [], additionalProperties: { type: JsonSchemaTypeEnum.OBJECT, description: 'Context value - can be accessed as string or object', properties: { id: { type: JsonSchemaTypeEnum.STRING, description: 'Context identifier', }, data: { type: JsonSchemaTypeEnum.OBJECT, description: 'Additional context data', properties: {}, additionalProperties: true, }, }, required: [], additionalProperties: false, }, }; // If no context data provided, return the base schema with additionalProperties if (!context || typeof context !== 'object' || Object.keys(context).length === 0) { return baseSchema; } // Build specific properties for each context entity const contextProperties: Record<string, JSONSchemaDto> = {}; for (const [entityType, entityValue] of Object.entries(context)) { if (entityValue && typeof entityValue === 'object') { const entity = entityValue as Record<string, unknown>; // Each context entity should have id and data properties const entitySchema: JSONSchemaDto = { type: JsonSchemaTypeEnum.OBJECT, properties: { id: { type: JsonSchemaTypeEnum.STRING, description: 'Context identifier', }, data: entity.data && typeof entity.data === 'object' ? buildVariablesSchema(entity.data) // Dynamic schema for entity.data : { type: JsonSchemaTypeEnum.OBJECT, description: 'Additional context data', additionalProperties: true, }, }, required: ['id'], additionalProperties: false, // Only allow id and data }; contextProperties[entityType] = entitySchema; } } // Return schema with both specific properties AND additionalProperties for new entities return { ...baseSchema, properties: contextProperties, }; };