create-mercato-app 0.4.6-develop-e321a4e2a1 → 0.4.6-main-24e64eef39

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.
Files changed (40) hide show
  1. package/bin/create-mercato-app +2 -2
  2. package/package.json +1 -1
  3. package/template/src/app/(backend)/backend/[...slug]/page.tsx +2 -6
  4. package/template/src/app/(backend)/backend/layout.tsx +27 -30
  5. package/template/src/bootstrap.ts +0 -4
  6. package/template/src/components/ClientBootstrap.tsx +5 -2
  7. package/template/src/modules/example/api/todos/route.ts +1 -1
  8. package/template/src/modules/example/backend/umes-handlers/page.tsx +1 -1
  9. package/template/src/modules/example/data/enrichers.ts +4 -32
  10. package/template/src/modules/example/data/entities.ts +0 -28
  11. package/template/src/modules/example/data/validators.ts +0 -22
  12. package/template/src/modules/example/i18n/de.json +10 -88
  13. package/template/src/modules/example/i18n/en.json +10 -88
  14. package/template/src/modules/example/i18n/es.json +10 -88
  15. package/template/src/modules/example/i18n/pl.json +10 -88
  16. package/template/src/modules/example/widgets/__tests__/injection-table.test.ts +6 -39
  17. package/template/src/modules/example/widgets/injection/catalog-seo-report/widget.client.tsx +1 -1
  18. package/template/src/modules/example/widgets/injection/crud-validation/widget.client.tsx +13 -13
  19. package/template/src/modules/example/widgets/injection/crud-validation/widget.ts +0 -3
  20. package/template/src/modules/example/widgets/injection-table.ts +1 -54
  21. package/template/src/app/(backend)/backend/__tests__/backend-require-features.test.tsx +0 -108
  22. package/template/src/components/ComponentOverridesBootstrap.tsx +0 -20
  23. package/template/src/modules/example/__integration__/TC-UMES-004.spec.ts +0 -337
  24. package/template/src/modules/example/__integration__/TC-UMES-006.spec.ts +0 -55
  25. package/template/src/modules/example/__integration__/meta.ts +0 -3
  26. package/template/src/modules/example/api/customer-priorities/route.ts +0 -154
  27. package/template/src/modules/example/api/interceptors.ts +0 -174
  28. package/template/src/modules/example/backend/umes-extensions/page.meta.ts +0 -24
  29. package/template/src/modules/example/backend/umes-extensions/page.tsx +0 -365
  30. package/template/src/modules/example/backend/umes-integrations/page.meta.ts +0 -25
  31. package/template/src/modules/example/backend/umes-integrations/page.tsx +0 -301
  32. package/template/src/modules/example/migrations/Migration20260226161000_example.ts +0 -15
  33. package/template/src/modules/example/widgets/components.ts +0 -23
  34. package/template/src/modules/example/widgets/injection/customer-priority-bulk-actions/widget.ts +0 -67
  35. package/template/src/modules/example/widgets/injection/customer-priority-column/widget.ts +0 -23
  36. package/template/src/modules/example/widgets/injection/customer-priority-detail/widget.client.tsx +0 -136
  37. package/template/src/modules/example/widgets/injection/customer-priority-detail/widget.ts +0 -13
  38. package/template/src/modules/example/widgets/injection/customer-priority-field/widget.ts +0 -68
  39. package/template/src/modules/example/widgets/injection/customer-priority-filter/widget.ts +0 -25
  40. package/template/src/modules/example/widgets/injection/customer-priority-row-action/widget.ts +0 -26
@@ -6,7 +6,7 @@
6
6
 
7
7
  import { existsSync } from 'node:fs';
8
8
  import { join, dirname } from 'node:path';
9
- import { fileURLToPath, pathToFileURL } from 'node:url';
9
+ import { fileURLToPath } from 'node:url';
10
10
 
11
11
  const __dirname = dirname(fileURLToPath(import.meta.url));
12
12
  const distIndex = join(__dirname, '..', 'dist', 'index.js');
@@ -18,4 +18,4 @@ if (!existsSync(distIndex)) {
18
18
  }
19
19
 
20
20
  // Import the actual CLI
21
- await import(pathToFileURL(distIndex).href);
21
+ await import(distIndex);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-mercato-app",
3
- "version": "0.4.6-develop-e321a4e2a1",
3
+ "version": "0.4.6-main-24e64eef39",
4
4
  "type": "module",
5
5
  "description": "Create a new Open Mercato application",
6
6
  "main": "./dist/index.js",
@@ -7,7 +7,6 @@ import { ApplyBreadcrumb } from '@open-mercato/ui/backend/AppShell'
7
7
  import { createRequestContainer } from '@open-mercato/shared/lib/di/container'
8
8
  import { resolveFeatureCheckContext } from '@open-mercato/core/modules/directory/utils/organizationScope'
9
9
  import type { RbacService } from '@open-mercato/core/modules/auth/services/rbacService'
10
- import { ComponentReplacementHandles, resolveRegisteredComponent } from '@open-mercato/shared/modules/widgets/component-registry'
11
10
 
12
11
  type Awaitable<T> = T | Promise<T>
13
12
 
@@ -48,15 +47,12 @@ export default async function BackendCatchAll(props: { params: Awaitable<{ slug?
48
47
  if (!ok) redirect('/login?requireFeature=' + encodeURIComponent(features.join(',')))
49
48
  }
50
49
  }
51
- const pageHandle = ComponentReplacementHandles.page(pathname)
52
- const Component = resolveRegisteredComponent(pageHandle, match.route.Component)
50
+ const Component = match.route.Component
53
51
 
54
52
  return (
55
53
  <>
56
54
  <ApplyBreadcrumb breadcrumb={match.route.breadcrumb} title={match.route.title} titleKey={match.route.titleKey} />
57
- <div data-component-handle={pageHandle}>
58
- <Component params={match.params} />
59
- </div>
55
+ <Component params={match.params} />
60
56
  </>
61
57
  )
62
58
  }
@@ -38,7 +38,6 @@ import { APP_VERSION } from '@open-mercato/shared/lib/version'
38
38
  import { PageInjectionBoundary } from '@open-mercato/ui/backend/injection/PageInjectionBoundary'
39
39
  import { AiAssistantIntegration, AiChatHeaderButton } from '@open-mercato/ai-assistant/frontend'
40
40
  import { CustomEntity } from '@open-mercato/core/modules/entities/data/entities'
41
- import { ComponentOverridesBootstrap } from '@/components/ComponentOverridesBootstrap'
42
41
 
43
42
  type NavItem = {
44
43
  href: string
@@ -384,36 +383,34 @@ export default async function BackendLayout({ children, params }: { children: Re
384
383
  <>
385
384
  <Script async src="https://w.appzi.io/w.js?token=TtIV6" strategy="afterInteractive" />
386
385
  <I18nProvider locale={locale} dict={dict}>
387
- <ComponentOverridesBootstrap>
388
- <AiAssistantIntegration
389
- tenantId={auth?.tenantId ?? null}
390
- organizationId={auth?.orgId ?? null}
386
+ <AiAssistantIntegration
387
+ tenantId={auth?.tenantId ?? null}
388
+ organizationId={auth?.orgId ?? null}
389
+ >
390
+ <AppShell
391
+ key={path}
392
+ productName={productName}
393
+ email={auth?.email}
394
+ groups={groups}
395
+ currentTitle={currentTitle}
396
+ breadcrumb={breadcrumb}
397
+ sidebarCollapsedDefault={initialCollapsed}
398
+ rightHeaderSlot={rightHeaderContent}
399
+ mobileSidebarSlot={mobileSidebarContent}
400
+ adminNavApi="/api/auth/admin/nav"
401
+ version={APP_VERSION}
402
+ settingsPathPrefixes={settingsPathPrefixes}
403
+ settingsSections={filteredSettingsSections}
404
+ settingsSectionTitle={translate('backend.nav.settings', 'Settings')}
405
+ profileSections={profileSections}
406
+ profileSectionTitle={translate('profile.page.title', 'Profile')}
407
+ profilePathPrefixes={profilePathPrefixes}
391
408
  >
392
- <AppShell
393
- key={path}
394
- productName={productName}
395
- email={auth?.email}
396
- groups={groups}
397
- currentTitle={currentTitle}
398
- breadcrumb={breadcrumb}
399
- sidebarCollapsedDefault={initialCollapsed}
400
- rightHeaderSlot={rightHeaderContent}
401
- mobileSidebarSlot={mobileSidebarContent}
402
- adminNavApi="/api/auth/admin/nav"
403
- version={APP_VERSION}
404
- settingsPathPrefixes={settingsPathPrefixes}
405
- settingsSections={filteredSettingsSections}
406
- settingsSectionTitle={translate('backend.nav.settings', 'Settings')}
407
- profileSections={profileSections}
408
- profileSectionTitle={translate('profile.page.title', 'Profile')}
409
- profilePathPrefixes={profilePathPrefixes}
410
- >
411
- <PageInjectionBoundary path={path} context={injectionContext}>
412
- {children}
413
- </PageInjectionBoundary>
414
- </AppShell>
415
- </AiAssistantIntegration>
416
- </ComponentOverridesBootstrap>
409
+ <PageInjectionBoundary path={path} context={injectionContext}>
410
+ {children}
411
+ </PageInjectionBoundary>
412
+ </AppShell>
413
+ </AiAssistantIntegration>
417
414
  </I18nProvider>
418
415
  </>
419
416
  )
@@ -44,8 +44,6 @@ import { eventModuleConfigs, allEvents } from '@/.mercato/generated/events.gener
44
44
  import { registerEventModuleConfigs } from '@open-mercato/shared/modules/events'
45
45
  import { analyticsModuleConfigs } from '@/.mercato/generated/analytics.generated'
46
46
  import { enricherEntries } from '@/.mercato/generated/enrichers.generated'
47
- import { interceptorEntries } from '@/.mercato/generated/interceptors.generated'
48
- import { componentOverrideEntries } from '@/.mercato/generated/component-overrides.generated'
49
47
  import { messageTypes } from '@/.mercato/generated/message-types.generated'
50
48
  import { messageObjectTypes } from '@/.mercato/generated/message-objects.generated'
51
49
  import { registerMessageTypes } from '@open-mercato/core/modules/messages/lib/message-types-registry'
@@ -72,8 +70,6 @@ export const bootstrap = createBootstrap({
72
70
  searchModuleConfigs,
73
71
  analyticsModuleConfigs,
74
72
  enricherEntries,
75
- interceptorEntries,
76
- componentOverrideEntries,
77
73
  })
78
74
 
79
75
  export { isBootstrapped }
@@ -11,8 +11,8 @@ import { dashboardWidgetEntries } from '@/.mercato/generated/dashboard-widgets.g
11
11
  import { registerDashboardWidgets } from '@open-mercato/ui/backend/dashboard/widgetRegistry'
12
12
  // Side-effect: registers translatable fields for client-side TranslationManager
13
13
  import '@/.mercato/generated/translations-fields.generated'
14
- // Side-effect: configures message UI component and object type registries on the client.
15
- import '@/.mercato/generated/messages.client.generated'
14
+ import { getMessageUiComponentRegistry } from '@/.mercato/generated/messages.client.generated'
15
+ import { configureMessageUiComponentRegistry } from '@open-mercato/core/modules/messages/components/utils/typeUiRegistry'
16
16
 
17
17
  let _clientBootstrapped = false
18
18
 
@@ -27,6 +27,9 @@ function clientBootstrap() {
27
27
 
28
28
  // Register dashboard widgets
29
29
  registerDashboardWidgets(dashboardWidgetEntries)
30
+
31
+ // Configure message UI components from generated client registry.
32
+ configureMessageUiComponentRegistry(getMessageUiComponentRegistry())
30
33
  }
31
34
 
32
35
  export function ClientBootstrapProvider({ children }: { children: React.ReactNode }) {
@@ -34,7 +34,7 @@ const querySchema = z
34
34
  organizationId: z.string().uuid().optional(),
35
35
  createdFrom: z.string().optional(),
36
36
  createdTo: z.string().optional(),
37
- format: z.enum(['json', 'csv']).optional(),
37
+ format: z.enum(['json', 'csv']).optional().default('json'),
38
38
  })
39
39
  .passthrough()
40
40
 
@@ -15,7 +15,7 @@ function print(value: unknown) {
15
15
  return JSON.stringify(value ?? null)
16
16
  }
17
17
 
18
- const hintClassName = 'inline-flex items-center rounded-md border border-amber-500/40 bg-amber-50 dark:bg-amber-400/10 px-2 py-1 text-xs text-amber-800 dark:text-amber-100/90'
18
+ const hintClassName = 'inline-flex items-center rounded-md border border-amber-400/40 bg-amber-400/10 px-2 py-1 text-xs text-amber-100/90'
19
19
 
20
20
  type CustomerRecord = {
21
21
  id?: string
@@ -6,7 +6,7 @@
6
6
  */
7
7
 
8
8
  import type { ResponseEnricher, EnricherContext } from '@open-mercato/shared/lib/crud/response-enricher'
9
- import { ExampleCustomerPriority, Todo } from './entities'
9
+ import { Todo } from './entities'
10
10
 
11
11
  type CustomerRecord = Record<string, unknown> & { id: string }
12
12
 
@@ -14,7 +14,6 @@ type TodoEnrichment = {
14
14
  _example: {
15
15
  todoCount: number
16
16
  openTodoCount: number
17
- priority: 'low' | 'normal' | 'high' | 'critical'
18
17
  }
19
18
  }
20
19
 
@@ -53,7 +52,7 @@ const customerTodoCountEnricher: ResponseEnricher<CustomerRecord, TodoEnrichment
53
52
  priority: 10,
54
53
  timeout: 2000,
55
54
  fallback: {
56
- _example: { todoCount: 0, openTodoCount: 0, priority: 'normal' },
55
+ _example: { todoCount: 0, openTodoCount: 0 },
57
56
  },
58
57
 
59
58
  async enrichOne(record, context) {
@@ -65,20 +64,10 @@ const customerTodoCountEnricher: ResponseEnricher<CustomerRecord, TodoEnrichment
65
64
  })
66
65
  const statsByBucket = buildBucketStats(todos)
67
66
  const scoped = statsByBucket.get(getPersonBucket(record.id)) ?? { todoCount: 0, openTodoCount: 0 }
68
- const priority = await em.findOne(ExampleCustomerPriority, {
69
- customerId: record.id,
70
- organizationId: context.organizationId,
71
- tenantId: context.tenantId,
72
- deletedAt: null,
73
- }, { orderBy: { updatedAt: 'desc', createdAt: 'desc' } })
74
67
 
75
68
  return {
76
69
  ...record,
77
- _example: {
78
- todoCount: scoped.todoCount,
79
- openTodoCount: scoped.openTodoCount,
80
- priority: (priority?.priority as TodoEnrichment['_example']['priority']) ?? 'normal',
81
- },
70
+ _example: { todoCount: scoped.todoCount, openTodoCount: scoped.openTodoCount },
82
71
  }
83
72
  },
84
73
 
@@ -90,27 +79,10 @@ const customerTodoCountEnricher: ResponseEnricher<CustomerRecord, TodoEnrichment
90
79
  deletedAt: null,
91
80
  })
92
81
  const statsByBucket = buildBucketStats(todos)
93
- const customerIds = records.map((record) => record.id)
94
- const priorities: ExampleCustomerPriority[] = customerIds.length > 0
95
- ? await em.find(ExampleCustomerPriority, {
96
- customerId: { $in: customerIds },
97
- organizationId: context.organizationId,
98
- tenantId: context.tenantId,
99
- deletedAt: null,
100
- }, { orderBy: { updatedAt: 'desc', createdAt: 'desc' } })
101
- : []
102
- const priorityByCustomerId = new Map<string, ExampleCustomerPriority['priority']>()
103
- for (const entry of priorities) {
104
- if (priorityByCustomerId.has(entry.customerId)) continue
105
- priorityByCustomerId.set(entry.customerId, entry.priority)
106
- }
107
82
 
108
83
  return records.map((record) => ({
109
84
  ...record,
110
- _example: {
111
- ...(statsByBucket.get(getPersonBucket(record.id)) ?? { todoCount: 0, openTodoCount: 0 }),
112
- priority: (priorityByCustomerId.get(record.id) as TodoEnrichment['_example']['priority'] | undefined) ?? 'normal',
113
- },
85
+ _example: statsByBucket.get(getPersonBucket(record.id)) ?? { todoCount: 0, openTodoCount: 0 },
114
86
  }))
115
87
  },
116
88
  }
@@ -42,31 +42,3 @@ export class Todo {
42
42
  @Property({ name: 'deleted_at', type: Date, nullable: true })
43
43
  deletedAt?: Date | null
44
44
  }
45
-
46
- @Entity({ tableName: 'example_customer_priorities' })
47
- export class ExampleCustomerPriority {
48
- @PrimaryKey({ type: 'uuid', defaultRaw: 'gen_random_uuid()' })
49
- id!: string
50
-
51
- @Property({ name: 'customer_id', type: 'uuid' })
52
- customerId!: string
53
-
54
- /** Customer priority level. Valid values: 'low' | 'normal' | 'high' | 'critical'. */
55
- @Property({ type: 'text', default: 'normal' })
56
- priority: 'low' | 'normal' | 'high' | 'critical' = 'normal'
57
-
58
- @Property({ name: 'tenant_id', type: 'uuid' })
59
- tenantId!: string
60
-
61
- @Property({ name: 'organization_id', type: 'uuid' })
62
- organizationId!: string
63
-
64
- @Property({ name: 'created_at', type: Date, onCreate: () => new Date() })
65
- createdAt: Date = new Date()
66
-
67
- @Property({ name: 'updated_at', type: Date, onUpdate: () => new Date() })
68
- updatedAt: Date = new Date()
69
-
70
- @Property({ name: 'deleted_at', type: Date, nullable: true })
71
- deletedAt?: Date | null
72
- }
@@ -5,25 +5,3 @@ export const exampleItemCreateSchema = z.object({
5
5
  })
6
6
 
7
7
  export type ExampleItemCreateInput = z.infer<typeof exampleItemCreateSchema>
8
-
9
- export const customerPriorityValueSchema = z.enum(['low', 'normal', 'high', 'critical'])
10
-
11
- export const customerPriorityCreateSchema = z.object({
12
- customerId: z.string().uuid(),
13
- priority: customerPriorityValueSchema.default('normal'),
14
- })
15
-
16
- export const customerPriorityUpdateSchema = z.object({
17
- id: z.string().uuid(),
18
- customerId: z.string().uuid().optional(),
19
- priority: customerPriorityValueSchema.optional(),
20
- })
21
-
22
- export const customerPriorityListSchema = z.object({
23
- id: z.string().uuid().optional(),
24
- customerId: z.string().uuid().optional(),
25
- page: z.coerce.number().min(1).default(1),
26
- pageSize: z.coerce.number().min(1).max(100).default(50),
27
- sortField: z.enum(['id', 'customer_id', 'priority', 'created_at']).optional().default('created_at'),
28
- sortDir: z.enum(['asc', 'desc']).optional().default('desc'),
29
- })
@@ -6,27 +6,8 @@
6
6
  "example.manageEntities": "Verwalte Beispiel-Entitäten.",
7
7
  "example.menu.quickAddTodo": "Schnell Aufgabe anlegen",
8
8
  "example.menu.todosShortcut": "Beispielaufgaben",
9
- "example.menu.umesExtensions": "Phase E-H handlers",
10
- "example.menu.umesIntegrations": "Phase L integrations",
11
- "example.messageObjects.notFound": "Nicht gefunden",
12
- "example.messageObjects.todo.title": "To-do",
13
9
  "example.moduleTitle": "Beispielmodul",
14
10
  "example.nav.group": "Beispiel",
15
- "example.priority.action.open": "Kunde öffnen",
16
- "example.priority.bulk.setNormal": "Priorität auf Normal setzen",
17
- "example.priority.column": "Beispielpriorität",
18
- "example.priority.critical": "Kritisch",
19
- "example.priority.detail.description": "Priorität für diesen Kundeneintrag festlegen.",
20
- "example.priority.detail.error.load": "Priorität konnte nicht geladen werden.",
21
- "example.priority.detail.error.save": "Priorität konnte nicht gespeichert werden.",
22
- "example.priority.detail.label": "Kundenpriorität",
23
- "example.priority.detail.loading": "Priorität wird geladen...",
24
- "example.priority.detail.saving": "Priorität wird gespeichert...",
25
- "example.priority.field": "Priorität",
26
- "example.priority.filter": "Priorität",
27
- "example.priority.high": "Hoch",
28
- "example.priority.low": "Niedrig",
29
- "example.priority.normal": "Normal",
30
11
  "example.publicPage": "Öffentliche Beispielseite.",
31
12
  "example.salesTodos.tabLabel": "Aufgaben (Beispiel)",
32
13
  "example.todos.create.title": "To-do erstellen",
@@ -74,43 +55,6 @@
74
55
  "example.todos.table.organization.none": "Keine Organisation",
75
56
  "example.todos.table.organization.unknown": "Unbekannt",
76
57
  "example.todos.table.title": "Allgemeine Aufgaben",
77
- "example.umes.extensions.description": "Validierungsseite für API-Interceptoren, DataTable/CrudForm-Erweiterungsoberflächen und Ersetzungs-Handles.",
78
- "example.umes.extensions.form.note": "Notiz",
79
- "example.umes.extensions.form.title": "Titel",
80
- "example.umes.extensions.hintHeading": "What should be visible and how it should work",
81
- "example.umes.extensions.phaseE.description": "Run the full probe suite: metadata merge, wildcard route matching, query revalidation, timeout fail-closed, and crash fail-closed.",
82
- "example.umes.extensions.phaseE.hint1": "1. `default` probe: must return `_example.interceptor` metadata in `/api/example/todos` response.",
83
- "example.umes.extensions.phaseE.hint2": "2. `wildcard` probe: must return `_example.wildcardProbe=true` for wildcard route interceptor.",
84
- "example.umes.extensions.phaseE.hint3": "3. `bad-query` probe: must fail with HTTP `400` (route schema revalidation after interceptor rewrite).",
85
- "example.umes.extensions.phaseE.hint4": "4. `timeout` probe: must fail closed with HTTP `504`.",
86
- "example.umes.extensions.phaseE.hint5": "5. `crash` probe: must fail closed with HTTP `500`.",
87
- "example.umes.extensions.phaseE.hint6": "Note: red network entries for probes 3-5 are expected and indicate correct fail-closed behavior.",
88
- "example.umes.extensions.phaseE.missing": "Eine oder mehrere Interceptor-Prüfungen fehlgeschlagen. Zeilen unten überprüfen.",
89
- "example.umes.extensions.phaseE.run": "Interceptor-Sonde ausführen",
90
- "example.umes.extensions.phaseE.title": "Phase E — API-Interceptoren",
91
- "example.umes.extensions.phaseF.description": "This table exposes `replacementHandle` and known component handles. Use it to validate replacement registration and then verify injected columns/actions on Customers list.",
92
- "example.umes.extensions.phaseF.expect": "Expect: injected column, row action, filters, and bulk action.",
93
- "example.umes.extensions.phaseF.hint1": "1. On `/backend/customers/people` table: column `Example priority` should be visible.",
94
- "example.umes.extensions.phaseF.hint2": "2. In filters drawer: select filter `Priority` should be visible.",
95
- "example.umes.extensions.phaseF.hint3": "3. In row actions menu: action `Open customer` should be visible.",
96
- "example.umes.extensions.phaseF.hint4": "4. After selecting rows: bulk action `Set normal priority` should update priorities via API.",
97
- "example.umes.extensions.phaseF.openCustomers": "Open customers table",
98
- "example.umes.extensions.phaseF.title": "Phase F — DataTable-Erweiterungen",
99
- "example.umes.extensions.phaseG.description": "This harness keeps the injected widget active on `crud-form:example.todo`. Submit once to confirm the field/event pipeline executes.",
100
- "example.umes.extensions.phaseG.hint1": "1. Injected widget card `Example Injection Widget` should be visible above form fields.",
101
- "example.umes.extensions.phaseG.hint2": "2. Saving valid form should update `submitResult` below the form.",
102
- "example.umes.extensions.phaseG.hint3": "3. In customer detail form (`/backend/customers/people/:id`), injected `_example.priority` field should persist via onSave handler.",
103
- "example.umes.extensions.phaseG.title": "Phase G — CrudForm-Feldeinspeisung",
104
- "example.umes.extensions.phaseH.description": "Active replacement handles in this area: page, DataTable, CrudForm, and the `ui.detail:NotesSection` wrapper declared in `example/widgets/components.ts`.",
105
- "example.umes.extensions.phaseH.hint1": "1. This page root should expose `data-component-handle=\"page:/backend/umes-extensions\"`.",
106
- "example.umes.extensions.phaseH.hint2": "2. Handles list table should expose `data-table:example.umes.extensions` replacement handle.",
107
- "example.umes.extensions.phaseH.hint3": "3. Form should expose `crud-form:example.todo` replacement handle.",
108
- "example.umes.extensions.phaseH.hint4": "4. Customer detail notes section should render wrapped border from `ExampleNotesSectionWrapper`.",
109
- "example.umes.extensions.phaseH.title": "Phase H — Komponentenersetzung",
110
- "example.umes.extensions.table.handle": "Handle",
111
- "example.umes.extensions.table.label": "Bezeichnung",
112
- "example.umes.extensions.table.title": "Ersetzungs-Handles",
113
- "example.umes.extensions.title": "UMES Phasen E-H Erweiterungen",
114
58
  "example.umes.handlers.actions.emitServerEvent": "Server todo.created auslösen",
115
59
  "example.umes.handlers.actions.loadBlockedSaveExample": "Blockiertes-Speichern-Beispiel laden",
116
60
  "example.umes.handlers.actions.loadTransformSaveExample": "Transform-Speichern-Beispiel laden",
@@ -183,38 +127,6 @@
183
127
  "example.umes.handlers.title": "Phase A-D Handler",
184
128
  "example.umes.handlers.validation.titleRequired": "Titel ist erforderlich.",
185
129
  "example.umes.handlers.widgetHidden": "Widget ist derzeit ausgeblendet (Sichtbarkeitsstatus: false)",
186
- "example.umes.integrations.badges.cycle": "Cycle statuses",
187
- "example.umes.integrations.badges.description": "Four status badge renderers with fixed loaders demonstrating healthy, warning, error, and unknown states.",
188
- "example.umes.integrations.badges.hint1": "1. Four badges should render with colored dots (green, yellow, red, gray).",
189
- "example.umes.integrations.badges.hint2": "2. Hovering over badges with tooltips should show the tooltip text.",
190
- "example.umes.integrations.badges.hint3": "3. Clicking `Cycle statuses` should rotate all badge statuses forward.",
191
- "example.umes.integrations.badges.title": "L.2 Status Badge Injection",
192
- "example.umes.integrations.description": "Validation page for Phase L integration extensions: multi-step wizard, status badges, external ID mapping, and integration registry.",
193
- "example.umes.integrations.externalIds.description": "ExternalIdsWidget renders mock integration mappings for Shopify and Stripe.",
194
- "example.umes.integrations.externalIds.hint1": "1. Two integration rows should display: Shopify (synced, green dot) and Stripe (pending, yellow dot).",
195
- "example.umes.integrations.externalIds.hint2": "2. Shopify row should show an external link icon.",
196
- "example.umes.integrations.externalIds.hint3": "3. Each row shows the external ID in a monospace code badge.",
197
- "example.umes.integrations.externalIds.title": "L.3 External ID Mapping Display",
198
- "example.umes.integrations.hintHeading": "What should be visible and how it should work",
199
- "example.umes.integrations.registry.description": "Demonstrates registerIntegration(), getAllIntegrations(), and getIntegrationTitle() from the shared registry.",
200
- "example.umes.integrations.registry.hint1": "1. Two integrations should be registered on mount (sync_shopify, gateway_stripe).",
201
- "example.umes.integrations.registry.hint2": "2. `getIntegrationTitle('sync_shopify')` should return 'Shopify' (not the raw ID).",
202
- "example.umes.integrations.registry.hint3": "3. `getIntegrationTitle('unknown_id')` should fall back to 'unknown_id'.",
203
- "example.umes.integrations.registry.title": "L.4 Integration Registry",
204
- "example.umes.integrations.title": "UMES Phase L — Integration Extensions",
205
- "example.umes.integrations.wizard.description": "Complete the 3-step wizard to validate step navigation, per-step validation, and onComplete callback.",
206
- "example.umes.integrations.wizard.hint1": "1. Step indicator should show 3 numbered circles with connecting lines.",
207
- "example.umes.integrations.wizard.hint2": "2. Step 1 requires both `apiKey` and `apiSecret` — leaving them empty should show validation error.",
208
- "example.umes.integrations.wizard.hint3": "3. Completing all steps should display the accumulated wizard data below.",
209
- "example.umes.integrations.wizard.step1.description": "Enter API credentials for the external system.",
210
- "example.umes.integrations.wizard.step1.label": "Credentials",
211
- "example.umes.integrations.wizard.step2.description": "Configure synchronization direction.",
212
- "example.umes.integrations.wizard.step2.label": "Scope",
213
- "example.umes.integrations.wizard.step3.description": "Set the sync frequency.",
214
- "example.umes.integrations.wizard.step3.label": "Schedule",
215
- "example.umes.integrations.wizard.title": "L.1 Multi-Step Wizard Widget",
216
- "example.umes.integrations.wizard.validationError": "Both API key and API secret are required.",
217
- "example.umes.integrations.wizard.wizardTitle": "Integration Setup Wizard",
218
130
  "example.widgets.catalogSeoReport.edit": "Bearbeiten",
219
131
  "example.widgets.catalogSeoReport.error": "SEO-Bericht konnte nicht geladen werden.",
220
132
  "example.widgets.catalogSeoReport.example": "Beispiel",
@@ -248,5 +160,15 @@
248
160
  "example.widgets.todo.settings.showCompleted": "Erledigte Einträge anzeigen",
249
161
  "example.widgets.todo.state.allCaughtUp": "Alles erledigt!",
250
162
  "example.widgets.todo.state.empty": "Keine To-dos gefunden.",
163
+ "example.umes.next.form.group": "Testfelder für rekursive Widgets",
164
+ "example.umes.next.form.title": "Phase J — Formular für rekursive Widgets",
165
+ "example.umes.next.page.description": "Demonstriert UMES-Folgephasen einschließlich rekursiver Widget-Erweiterbarkeit (Phase J).",
166
+ "example.umes.next.page.title": "UMES Nächste Phasen",
167
+ "example.umes.next.phaseJ.label": "Rekursive Widget-Injektion",
168
+ "example.umes.next.readiness.description": "Live-Bereitschaft für UMES-Folgephasen. Erkanntes Addon bedeutet, dass der rekursive Injektionspunkt funktioniert.",
169
+ "example.umes.next.readiness.title": "Phasenbereitschaft",
170
+ "example.umes.next.recursive.description": "Ein Widget (crud-validation) deklariert einen eigenen InjectionSpot. Ein anderes Widget (crud-validation-addon) injiziert sich dort hinein und erzeugt eine geschichtete Komposition.",
171
+ "example.umes.next.recursive.spotLabel": "Injektionspunkt:",
172
+ "example.umes.next.recursive.title": "Phase J — Rekursive Widget-Erweiterbarkeit",
251
173
  "example.workPlan.nav.group": "Arbeitsplan"
252
174
  }
@@ -6,27 +6,8 @@
6
6
  "example.manageEntities": "Manage example entities.",
7
7
  "example.menu.quickAddTodo": "Quick Add Todo",
8
8
  "example.menu.todosShortcut": "Example Todos",
9
- "example.menu.umesExtensions": "Phase E-H handlers",
10
- "example.menu.umesIntegrations": "Phase L integrations",
11
- "example.messageObjects.notFound": "Not found",
12
- "example.messageObjects.todo.title": "Todo",
13
9
  "example.moduleTitle": "Example Module",
14
10
  "example.nav.group": "Example",
15
- "example.priority.action.open": "Open customer",
16
- "example.priority.bulk.setNormal": "Set normal priority",
17
- "example.priority.column": "Example priority",
18
- "example.priority.critical": "Critical",
19
- "example.priority.detail.description": "Set priority for this customer record.",
20
- "example.priority.detail.error.load": "Failed to load priority.",
21
- "example.priority.detail.error.save": "Failed to save priority.",
22
- "example.priority.detail.label": "Customer priority",
23
- "example.priority.detail.loading": "Loading priority...",
24
- "example.priority.detail.saving": "Saving priority...",
25
- "example.priority.field": "Priority",
26
- "example.priority.filter": "Priority",
27
- "example.priority.high": "High",
28
- "example.priority.low": "Low",
29
- "example.priority.normal": "Normal",
30
11
  "example.publicPage": "Public example page.",
31
12
  "example.salesTodos.tabLabel": "Todos (example)",
32
13
  "example.todos.create.title": "Create Todo",
@@ -74,43 +55,6 @@
74
55
  "example.todos.table.organization.none": "No organization",
75
56
  "example.todos.table.organization.unknown": "Unknown",
76
57
  "example.todos.table.title": "General tasks",
77
- "example.umes.extensions.description": "Validation page for API interceptors, DataTable/CrudForm extension surfaces, and replacement handles.",
78
- "example.umes.extensions.form.note": "Note",
79
- "example.umes.extensions.form.title": "Title",
80
- "example.umes.extensions.hintHeading": "What should be visible and how it should work",
81
- "example.umes.extensions.phaseE.description": "Run the full probe suite: metadata merge, wildcard route matching, query revalidation, timeout fail-closed, and crash fail-closed.",
82
- "example.umes.extensions.phaseE.hint1": "1. `default` probe: must return `_example.interceptor` metadata in `/api/example/todos` response.",
83
- "example.umes.extensions.phaseE.hint2": "2. `wildcard` probe: must return `_example.wildcardProbe=true` for wildcard route interceptor.",
84
- "example.umes.extensions.phaseE.hint3": "3. `bad-query` probe: must fail with HTTP `400` (route schema revalidation after interceptor rewrite).",
85
- "example.umes.extensions.phaseE.hint4": "4. `timeout` probe: must fail closed with HTTP `504`.",
86
- "example.umes.extensions.phaseE.hint5": "5. `crash` probe: must fail closed with HTTP `500`.",
87
- "example.umes.extensions.phaseE.hint6": "Note: red network entries for probes 3-5 are expected and indicate correct fail-closed behavior.",
88
- "example.umes.extensions.phaseE.missing": "One or more interceptor checks failed. Review rows below.",
89
- "example.umes.extensions.phaseE.run": "Run interceptor probe",
90
- "example.umes.extensions.phaseE.title": "Phase E — API interceptors",
91
- "example.umes.extensions.phaseF.description": "This table exposes `replacementHandle` and known component handles. Use it to validate replacement registration and then verify injected columns/actions on Customers list.",
92
- "example.umes.extensions.phaseF.expect": "Expect: injected column, row action, filters, and bulk action.",
93
- "example.umes.extensions.phaseF.hint1": "1. On `/backend/customers/people` table: column `Example priority` should be visible.",
94
- "example.umes.extensions.phaseF.hint2": "2. In filters drawer: select filter `Priority` should be visible.",
95
- "example.umes.extensions.phaseF.hint3": "3. In row actions menu: action `Open customer` should be visible.",
96
- "example.umes.extensions.phaseF.hint4": "4. After selecting rows: bulk action `Set normal priority` should update priorities via API.",
97
- "example.umes.extensions.phaseF.openCustomers": "Open customers table",
98
- "example.umes.extensions.phaseF.title": "Phase F — DataTable extensions",
99
- "example.umes.extensions.phaseG.description": "This harness keeps the injected widget active on `crud-form:example.todo`. Submit once to confirm the field/event pipeline executes.",
100
- "example.umes.extensions.phaseG.hint1": "1. Injected widget card `Example Injection Widget` should be visible above form fields.",
101
- "example.umes.extensions.phaseG.hint2": "2. Saving valid form should update `submitResult` below the form.",
102
- "example.umes.extensions.phaseG.hint3": "3. In customer detail form (`/backend/customers/people/:id`), injected `_example.priority` field should persist via onSave handler.",
103
- "example.umes.extensions.phaseG.title": "Phase G — CrudForm field injection",
104
- "example.umes.extensions.phaseH.description": "Active replacement handles in this area: page, DataTable, CrudForm, and the `ui.detail:NotesSection` wrapper declared in `example/widgets/components.ts`.",
105
- "example.umes.extensions.phaseH.hint1": "1. This page root should expose `data-component-handle=\"page:/backend/umes-extensions\"`.",
106
- "example.umes.extensions.phaseH.hint2": "2. Handles list table should expose `data-table:example.umes.extensions` replacement handle.",
107
- "example.umes.extensions.phaseH.hint3": "3. Form should expose `crud-form:example.todo` replacement handle.",
108
- "example.umes.extensions.phaseH.hint4": "4. Customer detail notes section should render wrapped border from `ExampleNotesSectionWrapper`.",
109
- "example.umes.extensions.phaseH.title": "Phase H — Component replacement",
110
- "example.umes.extensions.table.handle": "Handle",
111
- "example.umes.extensions.table.label": "Label",
112
- "example.umes.extensions.table.title": "Replacement Handles",
113
- "example.umes.extensions.title": "UMES Phase E-H Extensions",
114
58
  "example.umes.handlers.actions.emitServerEvent": "Emit server todo.created",
115
59
  "example.umes.handlers.actions.loadBlockedSaveExample": "Load blocked-save example",
116
60
  "example.umes.handlers.actions.loadTransformSaveExample": "Load transform-save example",
@@ -183,38 +127,6 @@
183
127
  "example.umes.handlers.title": "Phase A-D handlers",
184
128
  "example.umes.handlers.validation.titleRequired": "Title is required.",
185
129
  "example.umes.handlers.widgetHidden": "Widget currently hidden (visibility state: false)",
186
- "example.umes.integrations.badges.cycle": "Cycle statuses",
187
- "example.umes.integrations.badges.description": "Four status badge renderers with fixed loaders demonstrating healthy, warning, error, and unknown states.",
188
- "example.umes.integrations.badges.hint1": "1. Four badges should render with colored dots (green, yellow, red, gray).",
189
- "example.umes.integrations.badges.hint2": "2. Hovering over badges with tooltips should show the tooltip text.",
190
- "example.umes.integrations.badges.hint3": "3. Clicking `Cycle statuses` should rotate all badge statuses forward.",
191
- "example.umes.integrations.badges.title": "L.2 Status Badge Injection",
192
- "example.umes.integrations.description": "Validation page for Phase L integration extensions: multi-step wizard, status badges, external ID mapping, and integration registry.",
193
- "example.umes.integrations.externalIds.description": "ExternalIdsWidget renders mock integration mappings for Shopify and Stripe.",
194
- "example.umes.integrations.externalIds.hint1": "1. Two integration rows should display: Shopify (synced, green dot) and Stripe (pending, yellow dot).",
195
- "example.umes.integrations.externalIds.hint2": "2. Shopify row should show an external link icon.",
196
- "example.umes.integrations.externalIds.hint3": "3. Each row shows the external ID in a monospace code badge.",
197
- "example.umes.integrations.externalIds.title": "L.3 External ID Mapping Display",
198
- "example.umes.integrations.hintHeading": "What should be visible and how it should work",
199
- "example.umes.integrations.registry.description": "Demonstrates registerIntegration(), getAllIntegrations(), and getIntegrationTitle() from the shared registry.",
200
- "example.umes.integrations.registry.hint1": "1. Two integrations should be registered on mount (sync_shopify, gateway_stripe).",
201
- "example.umes.integrations.registry.hint2": "2. `getIntegrationTitle('sync_shopify')` should return 'Shopify' (not the raw ID).",
202
- "example.umes.integrations.registry.hint3": "3. `getIntegrationTitle('unknown_id')` should fall back to 'unknown_id'.",
203
- "example.umes.integrations.registry.title": "L.4 Integration Registry",
204
- "example.umes.integrations.title": "UMES Phase L — Integration Extensions",
205
- "example.umes.integrations.wizard.description": "Complete the 3-step wizard to validate step navigation, per-step validation, and onComplete callback.",
206
- "example.umes.integrations.wizard.hint1": "1. Step indicator should show 3 numbered circles with connecting lines.",
207
- "example.umes.integrations.wizard.hint2": "2. Step 1 requires both `apiKey` and `apiSecret` — leaving them empty should show validation error.",
208
- "example.umes.integrations.wizard.hint3": "3. Completing all steps should display the accumulated wizard data below.",
209
- "example.umes.integrations.wizard.step1.description": "Enter API credentials for the external system.",
210
- "example.umes.integrations.wizard.step1.label": "Credentials",
211
- "example.umes.integrations.wizard.step2.description": "Configure synchronization direction.",
212
- "example.umes.integrations.wizard.step2.label": "Scope",
213
- "example.umes.integrations.wizard.step3.description": "Set the sync frequency.",
214
- "example.umes.integrations.wizard.step3.label": "Schedule",
215
- "example.umes.integrations.wizard.title": "L.1 Multi-Step Wizard Widget",
216
- "example.umes.integrations.wizard.validationError": "Both API key and API secret are required.",
217
- "example.umes.integrations.wizard.wizardTitle": "Integration Setup Wizard",
218
130
  "example.widgets.catalogSeoReport.edit": "Edit",
219
131
  "example.widgets.catalogSeoReport.error": "Failed to load SEO report.",
220
132
  "example.widgets.catalogSeoReport.example": "Example",
@@ -248,5 +160,15 @@
248
160
  "example.widgets.todo.settings.showCompleted": "Show completed items",
249
161
  "example.widgets.todo.state.allCaughtUp": "All caught up!",
250
162
  "example.widgets.todo.state.empty": "No todos found.",
163
+ "example.umes.next.form.group": "Recursive widget test fields",
164
+ "example.umes.next.form.title": "Phase J — Recursive widget form",
165
+ "example.umes.next.page.description": "Demonstrates UMES next phases including recursive widget extensibility (Phase J).",
166
+ "example.umes.next.page.title": "UMES Next Phases",
167
+ "example.umes.next.phaseJ.label": "Recursive widget injection",
168
+ "example.umes.next.readiness.description": "Live readiness for UMES next phases. Addon detected means the recursive injection spot is working.",
169
+ "example.umes.next.readiness.title": "Phase readiness",
170
+ "example.umes.next.recursive.description": "A widget (crud-validation) declares its own InjectionSpot. Another widget (crud-validation-addon) injects into it, creating a layered composition.",
171
+ "example.umes.next.recursive.spotLabel": "Injection spot:",
172
+ "example.umes.next.recursive.title": "Phase J — Recursive widget extensibility",
251
173
  "example.workPlan.nav.group": "Work plan"
252
174
  }