Some checks are pending
Bidi Control Character Guard / bidi-control-guard (push) Waiting to run
Circular Dependency Check / Check for new circular dependencies (push) Waiting to run
Citus Migration Smoke / Combined migrations on single-node Citus (push) Waiting to run
E2E Fresh Install Tests / fresh-install-e2e (push) Waiting to run
ext-v2 guardrails / Run ext-v2 guard and ESLint (push) Waiting to run
Integration Tests / Check for relevant changes (push) Waiting to run
Integration Tests / ${{ (github.event_name == 'schedule' || github.event.inputs.suite == 'full') && 'Full integration suite' || 'Tier-1 integration subset' }} (push) Blocked by required conditions
Mobile checks / Mobile lint + typecheck (push) Waiting to run
Mobile checks / Mobile unit tests (push) Waiting to run
Mobile checks / Mobile dependency audit (report) (push) Waiting to run
Mobile checks / Mobile reproducibility checks (push) Waiting to run
Secrets guard (env backups) / Ensure no tracked env backup files (push) Waiting to run
Temporal Readiness / fast-readiness (push) Waiting to run
Temporal Readiness / docker-parity (push) Waiting to run
TypeScript Type Check / Nx affected typecheck (push) Waiting to run
Unit Tests / Skipped-test budget (push) Waiting to run
Unit Tests / Nx affected unit tests (push) Waiting to run
Unit Tests / Server unit coverage (informational) (push) Waiting to run
Validate Tenant Management Schema / Check for relevant changes (push) Waiting to run
Validate Tenant Management Schema / Validate Tenant Management Schema (push) Blocked by required conditions
EE Workflows Build Guard / ee-workflows-build-guard (push) Waiting to run
Excluded: .git, node_modules, secrets/, compose.env, assemblyscript tgz Source: /opt/alga-psa on psa.joliet.tech
111 lines
3.4 KiB
TypeScript
111 lines
3.4 KiB
TypeScript
import type { ZodSchema, ZodTypeAny } from 'zod';
|
|
import {
|
|
jsonDescription,
|
|
zodToJsonSchema,
|
|
type Options,
|
|
type PostProcessCallback,
|
|
} from 'zod-to-json-schema';
|
|
|
|
export type WorkflowPickerJsonSchemaMetadata = {
|
|
'x-workflow-picker-kind'?: string;
|
|
'x-workflow-picker-dependencies'?: string[];
|
|
'x-workflow-picker-fixed-value-hint'?: string;
|
|
'x-workflow-picker-allow-dynamic-reference'?: boolean;
|
|
};
|
|
|
|
export type WorkflowEditorKind = 'text' | 'picker' | 'color' | 'json' | 'custom';
|
|
export type WorkflowEditorInlineMode = 'input' | 'textarea' | 'picker-summary' | 'swatch';
|
|
export type WorkflowEditorDialogMode = 'large-text';
|
|
|
|
export type WorkflowEditorSoftEnumMetadata = {
|
|
component: 'soft-enum-combobox';
|
|
suggestionKind: 'workflow-data-store-namespace' | 'workflow-entity-type' | 'workflow-link-relation';
|
|
suggestionActionIds?: string[];
|
|
namespaceField?: string;
|
|
curatedValues?: string[];
|
|
allowCustomValue?: boolean;
|
|
};
|
|
|
|
export type WorkflowEditorJsonSchemaMetadata = {
|
|
kind: WorkflowEditorKind;
|
|
inline?: {
|
|
mode: WorkflowEditorInlineMode;
|
|
};
|
|
dialog?: {
|
|
mode: WorkflowEditorDialogMode;
|
|
};
|
|
dependencies?: string[];
|
|
allowsDynamicReference?: boolean;
|
|
fixedValueHint?: string;
|
|
picker?: {
|
|
resource: string;
|
|
};
|
|
softEnum?: WorkflowEditorSoftEnumMetadata;
|
|
};
|
|
|
|
export type WorkflowJsonSchemaMetadata = WorkflowPickerJsonSchemaMetadata & {
|
|
'x-workflow-editor'?: WorkflowEditorJsonSchemaMetadata;
|
|
};
|
|
|
|
type WorkflowJsonSchemaDescriptionPayload = WorkflowJsonSchemaMetadata & {
|
|
description?: string;
|
|
};
|
|
|
|
const hasWorkflowJsonSchemaMetadata = (metadata: WorkflowJsonSchemaDescriptionPayload): boolean =>
|
|
Object.values(metadata).some((value) => value !== undefined);
|
|
|
|
export const buildWorkflowJsonDescription = (
|
|
description: string | undefined,
|
|
metadata: WorkflowJsonSchemaMetadata = {}
|
|
): string => {
|
|
const payload: WorkflowJsonSchemaDescriptionPayload = {
|
|
description,
|
|
...metadata,
|
|
};
|
|
|
|
if (!hasWorkflowJsonSchemaMetadata(payload)) {
|
|
return description ?? '';
|
|
}
|
|
|
|
return JSON.stringify(payload);
|
|
};
|
|
|
|
export const withWorkflowJsonSchemaMetadata = <T extends ZodTypeAny>(
|
|
schema: T,
|
|
description: string,
|
|
metadata: WorkflowJsonSchemaMetadata = {}
|
|
): T => schema.describe(buildWorkflowJsonDescription(description, metadata)) as T;
|
|
|
|
export const buildWorkflowJsonSchemaPostProcess = (
|
|
next?: PostProcessCallback
|
|
): PostProcessCallback => {
|
|
return (jsonSchema, def, refs) => {
|
|
const described = jsonDescription(jsonSchema, def, refs);
|
|
return next ? next(described, def, refs) : described;
|
|
};
|
|
};
|
|
|
|
export const zodToWorkflowJsonSchema = (
|
|
schema: ZodSchema<unknown>,
|
|
options?: string | Partial<Options>
|
|
): Record<string, unknown> => {
|
|
// Inline subschemas instead of emitting `$ref`s. The designer's field editor
|
|
// does not resolve `$ref`, so a schema reused across fields (e.g. links.upsert's
|
|
// `left`/`right` both using entityRefSchema) would otherwise render the second
|
|
// occurrence as an unresolved ref (shown as a bare "string").
|
|
if (typeof options === 'string') {
|
|
return zodToJsonSchema(schema, {
|
|
name: options,
|
|
$refStrategy: 'none',
|
|
postProcess: buildWorkflowJsonSchemaPostProcess(),
|
|
}) as Record<string, unknown>;
|
|
}
|
|
|
|
const nextPostProcess = options?.postProcess;
|
|
return zodToJsonSchema(schema, {
|
|
$refStrategy: 'none',
|
|
...options,
|
|
postProcess: buildWorkflowJsonSchemaPostProcess(nextPostProcess),
|
|
}) as Record<string, unknown>;
|
|
};
|