@open-mercato/core 0.6.5-develop.4476.1.644044a657 → 0.6.5-develop.4477.1.7a250f91b8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,4 +1,4 @@
1
- [build:core] found 2927 entry points
1
+ [build:core] found 2928 entry points
2
2
  [build:core] built successfully
3
3
  [build:core:generated] found 184 entry points
4
4
  [build:core:generated] built successfully
@@ -9,11 +9,11 @@ const workflowDefinitionFormSchema = z.object({
9
9
  enabled: z.boolean(),
10
10
  effectiveFrom: z.string().optional().nullable(),
11
11
  effectiveTo: z.string().optional().nullable(),
12
- metadata: z.object({
13
- tags: z.array(z.string()).optional(),
14
- category: z.string().max(50).optional(),
15
- icon: z.string().max(50).optional()
16
- }).optional().nullable(),
12
+ // Flat dot-path keys mirror the field ids so CrudForm's non-strict
13
+ // schema.safeParse keeps them instead of stripping them before onSubmit.
14
+ "metadata.category": z.string().max(50).optional(),
15
+ "metadata.tags": z.array(z.string()).optional(),
16
+ "metadata.icon": z.string().max(50).optional(),
17
17
  steps: z.array(z.any()),
18
18
  transitions: z.array(z.any()),
19
19
  triggers: z.array(z.any()).default([])
@@ -26,11 +26,9 @@ const defaultFormValues = {
26
26
  enabled: true,
27
27
  effectiveFrom: null,
28
28
  effectiveTo: null,
29
- metadata: {
30
- tags: [],
31
- category: "",
32
- icon: ""
33
- },
29
+ "metadata.category": "",
30
+ "metadata.tags": [],
31
+ "metadata.icon": "",
34
32
  steps: [],
35
33
  transitions: [],
36
34
  triggers: []
@@ -169,6 +167,7 @@ function createFormGroups(t, StepsEditorComponent, TransitionsEditorComponent) {
169
167
  }
170
168
  import { toDateInputValue } from "@open-mercato/shared/lib/date/format";
171
169
  function parseWorkflowToFormValues(workflow) {
170
+ const metadata = workflow.metadata || {};
172
171
  return {
173
172
  workflowId: workflow.workflowId || "",
174
173
  workflowName: workflow.workflowName || "",
@@ -177,7 +176,10 @@ function parseWorkflowToFormValues(workflow) {
177
176
  enabled: workflow.enabled ?? true,
178
177
  effectiveFrom: toDateInputValue(workflow.effectiveFrom),
179
178
  effectiveTo: toDateInputValue(workflow.effectiveTo),
180
- metadata: workflow.metadata || { tags: [], category: "", icon: "" },
179
+ // Hydrate the flat dot-path keys the CrudForm inputs actually read.
180
+ "metadata.category": metadata.category || "",
181
+ "metadata.tags": Array.isArray(metadata.tags) ? metadata.tags : [],
182
+ "metadata.icon": metadata.icon || "",
181
183
  steps: workflow.definition?.steps || [],
182
184
  transitions: workflow.definition?.transitions || [],
183
185
  triggers: workflow.definition?.triggers || []
@@ -185,6 +187,14 @@ function parseWorkflowToFormValues(workflow) {
185
187
  }
186
188
  function buildWorkflowPayload(values) {
187
189
  const triggers = values.triggers ?? [];
190
+ const category = (values["metadata.category"] || "").trim();
191
+ const icon = (values["metadata.icon"] || "").trim();
192
+ const tags = Array.isArray(values["metadata.tags"]) ? values["metadata.tags"] : [];
193
+ const metadata = {
194
+ tags,
195
+ ...category ? { category } : {},
196
+ ...icon ? { icon } : {}
197
+ };
188
198
  return {
189
199
  workflowId: values.workflowId,
190
200
  workflowName: values.workflowName,
@@ -193,7 +203,7 @@ function buildWorkflowPayload(values) {
193
203
  enabled: values.enabled,
194
204
  effectiveFrom: values.effectiveFrom || null,
195
205
  effectiveTo: values.effectiveTo || null,
196
- metadata: values.metadata || null,
206
+ metadata,
197
207
  definition: {
198
208
  steps: values.steps,
199
209
  transitions: values.transitions,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/modules/workflows/components/formConfig.tsx"],
4
- "sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport { z } from 'zod'\nimport type { CrudField, CrudFormGroup } from '@open-mercato/ui/backend/CrudForm'\nimport type { WorkflowDefinitionTrigger } from '../data/entities'\n\n/**\n * Form Values Type\n * Represents the structure of form data for creating/editing workflow definitions\n */\nexport type WorkflowDefinitionFormValues = {\n workflowId: string\n workflowName: string\n description?: string | null\n version: number\n enabled: boolean\n effectiveFrom?: string | null\n effectiveTo?: string | null\n metadata?: {\n tags?: string[]\n category?: string\n icon?: string\n } | null\n steps: any[]\n transitions: any[]\n triggers: WorkflowDefinitionTrigger[]\n}\n\n/**\n * Form Validation Schema\n * Extends the API schema with additional client-side validation\n */\nexport const workflowDefinitionFormSchema = z.object({\n workflowId: z.string()\n .min(1, 'Workflow ID is required')\n .max(100, 'Workflow ID must be 100 characters or less')\n .regex(/^[a-z0-9_.-]+$/, 'Workflow ID must contain only lowercase letters, numbers, hyphens, underscores, and dots'),\n workflowName: z.string()\n .min(1, 'Workflow name is required')\n .max(200, 'Workflow name must be 200 characters or less'),\n description: z.string()\n .max(5000, 'Description must be 5000 characters or less')\n .optional()\n .nullable(),\n version: z.number().int().min(1),\n enabled: z.boolean(),\n effectiveFrom: z.string().optional().nullable(),\n effectiveTo: z.string().optional().nullable(),\n metadata: z.object({\n tags: z.array(z.string()).optional(),\n category: z.string().max(50).optional(),\n icon: z.string().max(50).optional(),\n }).optional().nullable(),\n steps: z.array(z.any()),\n transitions: z.array(z.any()),\n triggers: z.array(z.any()).default([]),\n})\n\n/**\n * Default Form Values\n */\nexport const defaultFormValues: WorkflowDefinitionFormValues = {\n workflowId: '',\n workflowName: '',\n description: null,\n version: 1,\n enabled: true,\n effectiveFrom: null,\n effectiveTo: null,\n metadata: {\n tags: [],\n category: '',\n icon: '',\n },\n steps: [],\n transitions: [],\n triggers: [],\n}\n\n/**\n * Create Field Definitions\n * Returns field configurations for the CrudForm\n */\nexport function createFieldDefinitions(t: (key: string) => string): CrudField[] {\n return [\n {\n id: 'workflowId',\n label: t('workflows.form.workflowId'),\n type: 'text',\n required: true,\n placeholder: t('workflows.form.placeholders.workflowId'),\n description: t('workflows.form.descriptions.workflowId'),\n },\n {\n id: 'workflowName',\n label: t('workflows.form.workflowName'),\n type: 'text',\n required: true,\n placeholder: t('workflows.form.placeholders.workflowName'),\n },\n {\n id: 'description',\n label: t('workflows.form.description'),\n type: 'textarea',\n placeholder: t('workflows.form.placeholders.description'),\n },\n {\n id: 'version',\n label: t('workflows.form.version'),\n type: 'number',\n required: true,\n description: t('workflows.form.descriptions.version'),\n },\n {\n id: 'enabled',\n label: t('workflows.form.enabled'),\n type: 'checkbox',\n description: t('workflows.form.descriptions.enabled'),\n },\n {\n id: 'effectiveFrom',\n label: t('workflows.form.effectiveFrom'),\n type: 'date',\n description: t('workflows.form.descriptions.effectiveFrom'),\n },\n {\n id: 'effectiveTo',\n label: t('workflows.form.effectiveTo'),\n type: 'date',\n description: t('workflows.form.descriptions.effectiveTo'),\n },\n {\n id: 'metadata.category',\n label: t('workflows.form.category'),\n type: 'text',\n placeholder: t('workflows.form.placeholders.category'),\n },\n {\n id: 'metadata.tags',\n label: t('workflows.form.tags'),\n type: 'tags',\n placeholder: t('workflows.form.placeholders.tags'),\n description: t('workflows.form.descriptions.tags'),\n },\n {\n id: 'metadata.icon',\n label: t('workflows.form.icon'),\n type: 'text',\n placeholder: t('workflows.form.placeholders.icon'),\n description: t('workflows.form.descriptions.icon'),\n },\n ]\n}\n\n/**\n * Create Form Groups\n * Returns grouped layout configuration for the CrudForm\n */\nexport function createFormGroups(\n t: (key: string) => string,\n StepsEditorComponent: React.ComponentType<any>,\n TransitionsEditorComponent: React.ComponentType<any>\n): CrudFormGroup[] {\n // Wrapper components to adapt CrudForm props\n const StepsEditorWrapper = (props: { value: any; setValue: (v: any) => void; error?: string; values?: any }) => {\n return <StepsEditorComponent value={props.value} onChange={props.setValue} error={props.error} />\n }\n\n const TransitionsEditorWrapper = (props: { value: any; setValue: (v: any) => void; error?: string; values?: any }) => {\n // Pass the steps from values (all form values) so transitions can reference them\n return <TransitionsEditorComponent value={props.value} onChange={props.setValue} steps={props.values?.steps || []} error={props.error} />\n }\n\n return [\n {\n id: 'basic',\n title: t('workflows.form.groups.basic'),\n column: 1,\n fields: [\n 'workflowId',\n 'workflowName',\n 'description',\n 'version',\n 'enabled',\n ],\n },\n {\n id: 'metadata',\n title: t('workflows.form.groups.metadata'),\n column: 1,\n fields: [\n 'metadata.category',\n 'metadata.tags',\n 'metadata.icon',\n 'effectiveFrom',\n 'effectiveTo',\n ],\n },\n {\n id: 'steps',\n title: t('workflows.form.groups.steps'),\n column: 1,\n fields: [\n {\n id: 'steps',\n label: t('workflows.form.stepsLabel'),\n type: 'custom',\n required: true,\n component: StepsEditorWrapper,\n },\n ],\n },\n {\n id: 'transitions',\n title: t('workflows.form.groups.transitions'),\n column: 1,\n fields: [\n {\n id: 'transitions',\n label: t('workflows.form.transitionsLabel'),\n type: 'custom',\n required: true,\n component: TransitionsEditorWrapper,\n },\n ],\n },\n ]\n}\n\nimport { toDateInputValue } from '@open-mercato/shared/lib/date/format'\n\n/**\n * Parse workflow definition to form values\n */\nexport function parseWorkflowToFormValues(workflow: any): WorkflowDefinitionFormValues {\n return {\n workflowId: workflow.workflowId || '',\n workflowName: workflow.workflowName || '',\n description: workflow.description || null,\n version: workflow.version || 1,\n enabled: workflow.enabled ?? true,\n effectiveFrom: toDateInputValue(workflow.effectiveFrom),\n effectiveTo: toDateInputValue(workflow.effectiveTo),\n metadata: workflow.metadata || { tags: [], category: '', icon: '' },\n steps: workflow.definition?.steps || [],\n transitions: workflow.definition?.transitions || [],\n triggers: workflow.definition?.triggers || [],\n }\n}\n\n/**\n * Build API payload from form values\n */\nexport function buildWorkflowPayload(values: WorkflowDefinitionFormValues) {\n const triggers = values.triggers ?? []\n return {\n workflowId: values.workflowId,\n workflowName: values.workflowName,\n description: values.description || null,\n version: values.version,\n enabled: values.enabled,\n effectiveFrom: values.effectiveFrom || null,\n effectiveTo: values.effectiveTo || null,\n metadata: values.metadata || null,\n definition: {\n steps: values.steps,\n transitions: values.transitions,\n ...(triggers.length > 0 ? { triggers } : {}),\n },\n }\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport { z } from 'zod'\nimport type { CrudField, CrudFormGroup } from '@open-mercato/ui/backend/CrudForm'\nimport type { WorkflowDefinitionTrigger } from '../data/entities'\n\n/**\n * Form Values Type\n * Represents the structure of form data for creating/editing workflow definitions\n */\nexport type WorkflowDefinitionFormValues = {\n workflowId: string\n workflowName: string\n description?: string | null\n version: number\n enabled: boolean\n effectiveFrom?: string | null\n effectiveTo?: string | null\n // Metadata fields are declared on the form with dot-path ids\n // (`metadata.category`, `metadata.tags`, `metadata.icon`). CrudForm only\n // collapses dot-paths for injected/custom fields, so declared base fields are\n // carried as flat keys end-to-end; buildWorkflowPayload reassembles them into\n // the nested metadata object the API expects. See issue #2503.\n 'metadata.category'?: string\n 'metadata.tags'?: string[]\n 'metadata.icon'?: string\n steps: any[]\n transitions: any[]\n triggers: WorkflowDefinitionTrigger[]\n}\n\n/**\n * Form Validation Schema\n * Extends the API schema with additional client-side validation\n */\nexport const workflowDefinitionFormSchema = z.object({\n workflowId: z.string()\n .min(1, 'Workflow ID is required')\n .max(100, 'Workflow ID must be 100 characters or less')\n .regex(/^[a-z0-9_.-]+$/, 'Workflow ID must contain only lowercase letters, numbers, hyphens, underscores, and dots'),\n workflowName: z.string()\n .min(1, 'Workflow name is required')\n .max(200, 'Workflow name must be 200 characters or less'),\n description: z.string()\n .max(5000, 'Description must be 5000 characters or less')\n .optional()\n .nullable(),\n version: z.number().int().min(1),\n enabled: z.boolean(),\n effectiveFrom: z.string().optional().nullable(),\n effectiveTo: z.string().optional().nullable(),\n // Flat dot-path keys mirror the field ids so CrudForm's non-strict\n // schema.safeParse keeps them instead of stripping them before onSubmit.\n 'metadata.category': z.string().max(50).optional(),\n 'metadata.tags': z.array(z.string()).optional(),\n 'metadata.icon': z.string().max(50).optional(),\n steps: z.array(z.any()),\n transitions: z.array(z.any()),\n triggers: z.array(z.any()).default([]),\n})\n\n/**\n * Default Form Values\n */\nexport const defaultFormValues: WorkflowDefinitionFormValues = {\n workflowId: '',\n workflowName: '',\n description: null,\n version: 1,\n enabled: true,\n effectiveFrom: null,\n effectiveTo: null,\n 'metadata.category': '',\n 'metadata.tags': [],\n 'metadata.icon': '',\n steps: [],\n transitions: [],\n triggers: [],\n}\n\n/**\n * Create Field Definitions\n * Returns field configurations for the CrudForm\n */\nexport function createFieldDefinitions(t: (key: string) => string): CrudField[] {\n return [\n {\n id: 'workflowId',\n label: t('workflows.form.workflowId'),\n type: 'text',\n required: true,\n placeholder: t('workflows.form.placeholders.workflowId'),\n description: t('workflows.form.descriptions.workflowId'),\n },\n {\n id: 'workflowName',\n label: t('workflows.form.workflowName'),\n type: 'text',\n required: true,\n placeholder: t('workflows.form.placeholders.workflowName'),\n },\n {\n id: 'description',\n label: t('workflows.form.description'),\n type: 'textarea',\n placeholder: t('workflows.form.placeholders.description'),\n },\n {\n id: 'version',\n label: t('workflows.form.version'),\n type: 'number',\n required: true,\n description: t('workflows.form.descriptions.version'),\n },\n {\n id: 'enabled',\n label: t('workflows.form.enabled'),\n type: 'checkbox',\n description: t('workflows.form.descriptions.enabled'),\n },\n {\n id: 'effectiveFrom',\n label: t('workflows.form.effectiveFrom'),\n type: 'date',\n description: t('workflows.form.descriptions.effectiveFrom'),\n },\n {\n id: 'effectiveTo',\n label: t('workflows.form.effectiveTo'),\n type: 'date',\n description: t('workflows.form.descriptions.effectiveTo'),\n },\n {\n id: 'metadata.category',\n label: t('workflows.form.category'),\n type: 'text',\n placeholder: t('workflows.form.placeholders.category'),\n },\n {\n id: 'metadata.tags',\n label: t('workflows.form.tags'),\n type: 'tags',\n placeholder: t('workflows.form.placeholders.tags'),\n description: t('workflows.form.descriptions.tags'),\n },\n {\n id: 'metadata.icon',\n label: t('workflows.form.icon'),\n type: 'text',\n placeholder: t('workflows.form.placeholders.icon'),\n description: t('workflows.form.descriptions.icon'),\n },\n ]\n}\n\n/**\n * Create Form Groups\n * Returns grouped layout configuration for the CrudForm\n */\nexport function createFormGroups(\n t: (key: string) => string,\n StepsEditorComponent: React.ComponentType<any>,\n TransitionsEditorComponent: React.ComponentType<any>\n): CrudFormGroup[] {\n // Wrapper components to adapt CrudForm props\n const StepsEditorWrapper = (props: { value: any; setValue: (v: any) => void; error?: string; values?: any }) => {\n return <StepsEditorComponent value={props.value} onChange={props.setValue} error={props.error} />\n }\n\n const TransitionsEditorWrapper = (props: { value: any; setValue: (v: any) => void; error?: string; values?: any }) => {\n // Pass the steps from values (all form values) so transitions can reference them\n return <TransitionsEditorComponent value={props.value} onChange={props.setValue} steps={props.values?.steps || []} error={props.error} />\n }\n\n return [\n {\n id: 'basic',\n title: t('workflows.form.groups.basic'),\n column: 1,\n fields: [\n 'workflowId',\n 'workflowName',\n 'description',\n 'version',\n 'enabled',\n ],\n },\n {\n id: 'metadata',\n title: t('workflows.form.groups.metadata'),\n column: 1,\n fields: [\n 'metadata.category',\n 'metadata.tags',\n 'metadata.icon',\n 'effectiveFrom',\n 'effectiveTo',\n ],\n },\n {\n id: 'steps',\n title: t('workflows.form.groups.steps'),\n column: 1,\n fields: [\n {\n id: 'steps',\n label: t('workflows.form.stepsLabel'),\n type: 'custom',\n required: true,\n component: StepsEditorWrapper,\n },\n ],\n },\n {\n id: 'transitions',\n title: t('workflows.form.groups.transitions'),\n column: 1,\n fields: [\n {\n id: 'transitions',\n label: t('workflows.form.transitionsLabel'),\n type: 'custom',\n required: true,\n component: TransitionsEditorWrapper,\n },\n ],\n },\n ]\n}\n\nimport { toDateInputValue } from '@open-mercato/shared/lib/date/format'\n\n/**\n * Parse workflow definition to form values\n */\nexport function parseWorkflowToFormValues(workflow: any): WorkflowDefinitionFormValues {\n const metadata = workflow.metadata || {}\n return {\n workflowId: workflow.workflowId || '',\n workflowName: workflow.workflowName || '',\n description: workflow.description || null,\n version: workflow.version || 1,\n enabled: workflow.enabled ?? true,\n effectiveFrom: toDateInputValue(workflow.effectiveFrom),\n effectiveTo: toDateInputValue(workflow.effectiveTo),\n // Hydrate the flat dot-path keys the CrudForm inputs actually read.\n 'metadata.category': metadata.category || '',\n 'metadata.tags': Array.isArray(metadata.tags) ? metadata.tags : [],\n 'metadata.icon': metadata.icon || '',\n steps: workflow.definition?.steps || [],\n transitions: workflow.definition?.transitions || [],\n triggers: workflow.definition?.triggers || [],\n }\n}\n\n/**\n * Build API payload from form values\n */\nexport function buildWorkflowPayload(values: WorkflowDefinitionFormValues) {\n const triggers = values.triggers ?? []\n // Collapse the flat dot-path keys back into the nested metadata object the API\n // expects. Empty category/icon are dropped so they don't persist as blanks.\n const category = (values['metadata.category'] || '').trim()\n const icon = (values['metadata.icon'] || '').trim()\n const tags = Array.isArray(values['metadata.tags']) ? values['metadata.tags'] : []\n const metadata = {\n tags,\n ...(category ? { category } : {}),\n ...(icon ? { icon } : {}),\n }\n return {\n workflowId: values.workflowId,\n workflowName: values.workflowName,\n description: values.description || null,\n version: values.version,\n enabled: values.enabled,\n effectiveFrom: values.effectiveFrom || null,\n effectiveTo: values.effectiveTo || null,\n metadata,\n definition: {\n steps: values.steps,\n transitions: values.transitions,\n ...(triggers.length > 0 ? { triggers } : {}),\n },\n }\n}\n"],
5
+ "mappings": ";AAuKW;AApKX,SAAS,SAAS;AAiCX,MAAM,+BAA+B,EAAE,OAAO;AAAA,EACnD,YAAY,EAAE,OAAO,EAClB,IAAI,GAAG,yBAAyB,EAChC,IAAI,KAAK,4CAA4C,EACrD,MAAM,kBAAkB,0FAA0F;AAAA,EACrH,cAAc,EAAE,OAAO,EACpB,IAAI,GAAG,2BAA2B,EAClC,IAAI,KAAK,8CAA8C;AAAA,EAC1D,aAAa,EAAE,OAAO,EACnB,IAAI,KAAM,6CAA6C,EACvD,SAAS,EACT,SAAS;AAAA,EACZ,SAAS,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC;AAAA,EAC/B,SAAS,EAAE,QAAQ;AAAA,EACnB,eAAe,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS;AAAA,EAC9C,aAAa,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS;AAAA;AAAA;AAAA,EAG5C,qBAAqB,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE,SAAS;AAAA,EACjD,iBAAiB,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,SAAS;AAAA,EAC9C,iBAAiB,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE,SAAS;AAAA,EAC7C,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC;AAAA,EACtB,aAAa,EAAE,MAAM,EAAE,IAAI,CAAC;AAAA,EAC5B,UAAU,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,QAAQ,CAAC,CAAC;AACvC,CAAC;AAKM,MAAM,oBAAkD;AAAA,EAC7D,YAAY;AAAA,EACZ,cAAc;AAAA,EACd,aAAa;AAAA,EACb,SAAS;AAAA,EACT,SAAS;AAAA,EACT,eAAe;AAAA,EACf,aAAa;AAAA,EACb,qBAAqB;AAAA,EACrB,iBAAiB,CAAC;AAAA,EAClB,iBAAiB;AAAA,EACjB,OAAO,CAAC;AAAA,EACR,aAAa,CAAC;AAAA,EACd,UAAU,CAAC;AACb;AAMO,SAAS,uBAAuB,GAAyC;AAC9E,SAAO;AAAA,IACL;AAAA,MACE,IAAI;AAAA,MACJ,OAAO,EAAE,2BAA2B;AAAA,MACpC,MAAM;AAAA,MACN,UAAU;AAAA,MACV,aAAa,EAAE,wCAAwC;AAAA,MACvD,aAAa,EAAE,wCAAwC;AAAA,IACzD;AAAA,IACA;AAAA,MACE,IAAI;AAAA,MACJ,OAAO,EAAE,6BAA6B;AAAA,MACtC,MAAM;AAAA,MACN,UAAU;AAAA,MACV,aAAa,EAAE,0CAA0C;AAAA,IAC3D;AAAA,IACA;AAAA,MACE,IAAI;AAAA,MACJ,OAAO,EAAE,4BAA4B;AAAA,MACrC,MAAM;AAAA,MACN,aAAa,EAAE,yCAAyC;AAAA,IAC1D;AAAA,IACA;AAAA,MACE,IAAI;AAAA,MACJ,OAAO,EAAE,wBAAwB;AAAA,MACjC,MAAM;AAAA,MACN,UAAU;AAAA,MACV,aAAa,EAAE,qCAAqC;AAAA,IACtD;AAAA,IACA;AAAA,MACE,IAAI;AAAA,MACJ,OAAO,EAAE,wBAAwB;AAAA,MACjC,MAAM;AAAA,MACN,aAAa,EAAE,qCAAqC;AAAA,IACtD;AAAA,IACA;AAAA,MACE,IAAI;AAAA,MACJ,OAAO,EAAE,8BAA8B;AAAA,MACvC,MAAM;AAAA,MACN,aAAa,EAAE,2CAA2C;AAAA,IAC5D;AAAA,IACA;AAAA,MACE,IAAI;AAAA,MACJ,OAAO,EAAE,4BAA4B;AAAA,MACrC,MAAM;AAAA,MACN,aAAa,EAAE,yCAAyC;AAAA,IAC1D;AAAA,IACA;AAAA,MACE,IAAI;AAAA,MACJ,OAAO,EAAE,yBAAyB;AAAA,MAClC,MAAM;AAAA,MACN,aAAa,EAAE,sCAAsC;AAAA,IACvD;AAAA,IACA;AAAA,MACE,IAAI;AAAA,MACJ,OAAO,EAAE,qBAAqB;AAAA,MAC9B,MAAM;AAAA,MACN,aAAa,EAAE,kCAAkC;AAAA,MACjD,aAAa,EAAE,kCAAkC;AAAA,IACnD;AAAA,IACA;AAAA,MACE,IAAI;AAAA,MACJ,OAAO,EAAE,qBAAqB;AAAA,MAC9B,MAAM;AAAA,MACN,aAAa,EAAE,kCAAkC;AAAA,MACjD,aAAa,EAAE,kCAAkC;AAAA,IACnD;AAAA,EACF;AACF;AAMO,SAAS,iBACd,GACA,sBACA,4BACiB;AAEjB,QAAM,qBAAqB,CAAC,UAAoF;AAC9G,WAAO,oBAAC,wBAAqB,OAAO,MAAM,OAAO,UAAU,MAAM,UAAU,OAAO,MAAM,OAAO;AAAA,EACjG;AAEA,QAAM,2BAA2B,CAAC,UAAoF;AAEpH,WAAO,oBAAC,8BAA2B,OAAO,MAAM,OAAO,UAAU,MAAM,UAAU,OAAO,MAAM,QAAQ,SAAS,CAAC,GAAG,OAAO,MAAM,OAAO;AAAA,EACzI;AAEA,SAAO;AAAA,IACL;AAAA,MACE,IAAI;AAAA,MACJ,OAAO,EAAE,6BAA6B;AAAA,MACtC,QAAQ;AAAA,MACR,QAAQ;AAAA,QACN;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAAA,IACA;AAAA,MACE,IAAI;AAAA,MACJ,OAAO,EAAE,gCAAgC;AAAA,MACzC,QAAQ;AAAA,MACR,QAAQ;AAAA,QACN;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAAA,IACA;AAAA,MACE,IAAI;AAAA,MACJ,OAAO,EAAE,6BAA6B;AAAA,MACtC,QAAQ;AAAA,MACR,QAAQ;AAAA,QACN;AAAA,UACE,IAAI;AAAA,UACJ,OAAO,EAAE,2BAA2B;AAAA,UACpC,MAAM;AAAA,UACN,UAAU;AAAA,UACV,WAAW;AAAA,QACb;AAAA,MACF;AAAA,IACF;AAAA,IACA;AAAA,MACE,IAAI;AAAA,MACJ,OAAO,EAAE,mCAAmC;AAAA,MAC5C,QAAQ;AAAA,MACR,QAAQ;AAAA,QACN;AAAA,UACE,IAAI;AAAA,UACJ,OAAO,EAAE,iCAAiC;AAAA,UAC1C,MAAM;AAAA,UACN,UAAU;AAAA,UACV,WAAW;AAAA,QACb;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;AAEA,SAAS,wBAAwB;AAK1B,SAAS,0BAA0B,UAA6C;AACrF,QAAM,WAAW,SAAS,YAAY,CAAC;AACvC,SAAO;AAAA,IACL,YAAY,SAAS,cAAc;AAAA,IACnC,cAAc,SAAS,gBAAgB;AAAA,IACvC,aAAa,SAAS,eAAe;AAAA,IACrC,SAAS,SAAS,WAAW;AAAA,IAC7B,SAAS,SAAS,WAAW;AAAA,IAC7B,eAAe,iBAAiB,SAAS,aAAa;AAAA,IACtD,aAAa,iBAAiB,SAAS,WAAW;AAAA;AAAA,IAElD,qBAAqB,SAAS,YAAY;AAAA,IAC1C,iBAAiB,MAAM,QAAQ,SAAS,IAAI,IAAI,SAAS,OAAO,CAAC;AAAA,IACjE,iBAAiB,SAAS,QAAQ;AAAA,IAClC,OAAO,SAAS,YAAY,SAAS,CAAC;AAAA,IACtC,aAAa,SAAS,YAAY,eAAe,CAAC;AAAA,IAClD,UAAU,SAAS,YAAY,YAAY,CAAC;AAAA,EAC9C;AACF;AAKO,SAAS,qBAAqB,QAAsC;AACzE,QAAM,WAAW,OAAO,YAAY,CAAC;AAGrC,QAAM,YAAY,OAAO,mBAAmB,KAAK,IAAI,KAAK;AAC1D,QAAM,QAAQ,OAAO,eAAe,KAAK,IAAI,KAAK;AAClD,QAAM,OAAO,MAAM,QAAQ,OAAO,eAAe,CAAC,IAAI,OAAO,eAAe,IAAI,CAAC;AACjF,QAAM,WAAW;AAAA,IACf;AAAA,IACA,GAAI,WAAW,EAAE,SAAS,IAAI,CAAC;AAAA,IAC/B,GAAI,OAAO,EAAE,KAAK,IAAI,CAAC;AAAA,EACzB;AACA,SAAO;AAAA,IACL,YAAY,OAAO;AAAA,IACnB,cAAc,OAAO;AAAA,IACrB,aAAa,OAAO,eAAe;AAAA,IACnC,SAAS,OAAO;AAAA,IAChB,SAAS,OAAO;AAAA,IAChB,eAAe,OAAO,iBAAiB;AAAA,IACvC,aAAa,OAAO,eAAe;AAAA,IACnC;AAAA,IACA,YAAY;AAAA,MACV,OAAO,OAAO;AAAA,MACd,aAAa,OAAO;AAAA,MACpB,GAAI,SAAS,SAAS,IAAI,EAAE,SAAS,IAAI,CAAC;AAAA,IAC5C;AAAA,EACF;AACF;",
6
6
  "names": []
7
7
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@open-mercato/core",
3
- "version": "0.6.5-develop.4476.1.644044a657",
3
+ "version": "0.6.5-develop.4477.1.7a250f91b8",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "scripts": {
@@ -244,16 +244,16 @@
244
244
  "zod": "^4.4.3"
245
245
  },
246
246
  "peerDependencies": {
247
- "@open-mercato/ai-assistant": "0.6.5-develop.4476.1.644044a657",
248
- "@open-mercato/shared": "0.6.5-develop.4476.1.644044a657",
249
- "@open-mercato/ui": "0.6.5-develop.4476.1.644044a657",
247
+ "@open-mercato/ai-assistant": "0.6.5-develop.4477.1.7a250f91b8",
248
+ "@open-mercato/shared": "0.6.5-develop.4477.1.7a250f91b8",
249
+ "@open-mercato/ui": "0.6.5-develop.4477.1.7a250f91b8",
250
250
  "react": "^19.0.0",
251
251
  "react-dom": "^19.0.0"
252
252
  },
253
253
  "devDependencies": {
254
- "@open-mercato/ai-assistant": "0.6.5-develop.4476.1.644044a657",
255
- "@open-mercato/shared": "0.6.5-develop.4476.1.644044a657",
256
- "@open-mercato/ui": "0.6.5-develop.4476.1.644044a657",
254
+ "@open-mercato/ai-assistant": "0.6.5-develop.4477.1.7a250f91b8",
255
+ "@open-mercato/shared": "0.6.5-develop.4477.1.7a250f91b8",
256
+ "@open-mercato/ui": "0.6.5-develop.4477.1.7a250f91b8",
257
257
  "@testing-library/dom": "^10.4.1",
258
258
  "@testing-library/jest-dom": "^6.9.1",
259
259
  "@testing-library/react": "^16.3.1",
@@ -17,11 +17,14 @@ export type WorkflowDefinitionFormValues = {
17
17
  enabled: boolean
18
18
  effectiveFrom?: string | null
19
19
  effectiveTo?: string | null
20
- metadata?: {
21
- tags?: string[]
22
- category?: string
23
- icon?: string
24
- } | null
20
+ // Metadata fields are declared on the form with dot-path ids
21
+ // (`metadata.category`, `metadata.tags`, `metadata.icon`). CrudForm only
22
+ // collapses dot-paths for injected/custom fields, so declared base fields are
23
+ // carried as flat keys end-to-end; buildWorkflowPayload reassembles them into
24
+ // the nested metadata object the API expects. See issue #2503.
25
+ 'metadata.category'?: string
26
+ 'metadata.tags'?: string[]
27
+ 'metadata.icon'?: string
25
28
  steps: any[]
26
29
  transitions: any[]
27
30
  triggers: WorkflowDefinitionTrigger[]
@@ -47,11 +50,11 @@ export const workflowDefinitionFormSchema = z.object({
47
50
  enabled: z.boolean(),
48
51
  effectiveFrom: z.string().optional().nullable(),
49
52
  effectiveTo: z.string().optional().nullable(),
50
- metadata: z.object({
51
- tags: z.array(z.string()).optional(),
52
- category: z.string().max(50).optional(),
53
- icon: z.string().max(50).optional(),
54
- }).optional().nullable(),
53
+ // Flat dot-path keys mirror the field ids so CrudForm's non-strict
54
+ // schema.safeParse keeps them instead of stripping them before onSubmit.
55
+ 'metadata.category': z.string().max(50).optional(),
56
+ 'metadata.tags': z.array(z.string()).optional(),
57
+ 'metadata.icon': z.string().max(50).optional(),
55
58
  steps: z.array(z.any()),
56
59
  transitions: z.array(z.any()),
57
60
  triggers: z.array(z.any()).default([]),
@@ -68,11 +71,9 @@ export const defaultFormValues: WorkflowDefinitionFormValues = {
68
71
  enabled: true,
69
72
  effectiveFrom: null,
70
73
  effectiveTo: null,
71
- metadata: {
72
- tags: [],
73
- category: '',
74
- icon: '',
75
- },
74
+ 'metadata.category': '',
75
+ 'metadata.tags': [],
76
+ 'metadata.icon': '',
76
77
  steps: [],
77
78
  transitions: [],
78
79
  triggers: [],
@@ -234,6 +235,7 @@ import { toDateInputValue } from '@open-mercato/shared/lib/date/format'
234
235
  * Parse workflow definition to form values
235
236
  */
236
237
  export function parseWorkflowToFormValues(workflow: any): WorkflowDefinitionFormValues {
238
+ const metadata = workflow.metadata || {}
237
239
  return {
238
240
  workflowId: workflow.workflowId || '',
239
241
  workflowName: workflow.workflowName || '',
@@ -242,7 +244,10 @@ export function parseWorkflowToFormValues(workflow: any): WorkflowDefinitionForm
242
244
  enabled: workflow.enabled ?? true,
243
245
  effectiveFrom: toDateInputValue(workflow.effectiveFrom),
244
246
  effectiveTo: toDateInputValue(workflow.effectiveTo),
245
- metadata: workflow.metadata || { tags: [], category: '', icon: '' },
247
+ // Hydrate the flat dot-path keys the CrudForm inputs actually read.
248
+ 'metadata.category': metadata.category || '',
249
+ 'metadata.tags': Array.isArray(metadata.tags) ? metadata.tags : [],
250
+ 'metadata.icon': metadata.icon || '',
246
251
  steps: workflow.definition?.steps || [],
247
252
  transitions: workflow.definition?.transitions || [],
248
253
  triggers: workflow.definition?.triggers || [],
@@ -254,6 +259,16 @@ export function parseWorkflowToFormValues(workflow: any): WorkflowDefinitionForm
254
259
  */
255
260
  export function buildWorkflowPayload(values: WorkflowDefinitionFormValues) {
256
261
  const triggers = values.triggers ?? []
262
+ // Collapse the flat dot-path keys back into the nested metadata object the API
263
+ // expects. Empty category/icon are dropped so they don't persist as blanks.
264
+ const category = (values['metadata.category'] || '').trim()
265
+ const icon = (values['metadata.icon'] || '').trim()
266
+ const tags = Array.isArray(values['metadata.tags']) ? values['metadata.tags'] : []
267
+ const metadata = {
268
+ tags,
269
+ ...(category ? { category } : {}),
270
+ ...(icon ? { icon } : {}),
271
+ }
257
272
  return {
258
273
  workflowId: values.workflowId,
259
274
  workflowName: values.workflowName,
@@ -262,7 +277,7 @@ export function buildWorkflowPayload(values: WorkflowDefinitionFormValues) {
262
277
  enabled: values.enabled,
263
278
  effectiveFrom: values.effectiveFrom || null,
264
279
  effectiveTo: values.effectiveTo || null,
265
- metadata: values.metadata || null,
280
+ metadata,
266
281
  definition: {
267
282
  steps: values.steps,
268
283
  transitions: values.transitions,