@open-mercato/core 0.6.7-develop.6785.1.1dd7cfac55 → 0.6.7-develop.6795.1.8a3f27921c

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 (196) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/dist/generated/entities.ids.generated.js +1 -0
  3. package/dist/generated/entities.ids.generated.js.map +2 -2
  4. package/dist/modules/auth/backend/settings/page.js +14 -9
  5. package/dist/modules/auth/backend/settings/page.js.map +2 -2
  6. package/dist/modules/customers/cli.js +17 -7
  7. package/dist/modules/customers/cli.js.map +2 -2
  8. package/dist/modules/customers/components/detail/ScheduleActivityDialog.js +229 -216
  9. package/dist/modules/customers/components/detail/ScheduleActivityDialog.js.map +2 -2
  10. package/dist/modules/customers/search.js +50 -29
  11. package/dist/modules/customers/search.js.map +2 -2
  12. package/dist/modules/data_sync/api/mappings/[id]/route.js +22 -9
  13. package/dist/modules/data_sync/api/mappings/[id]/route.js.map +2 -2
  14. package/dist/modules/data_sync/api/mappings/route.js +13 -4
  15. package/dist/modules/data_sync/api/mappings/route.js.map +2 -2
  16. package/dist/modules/data_sync/api/options.js +7 -2
  17. package/dist/modules/data_sync/api/options.js.map +2 -2
  18. package/dist/modules/data_sync/api/run.js +7 -2
  19. package/dist/modules/data_sync/api/run.js.map +2 -2
  20. package/dist/modules/data_sync/api/runs/[id]/cancel.js +8 -3
  21. package/dist/modules/data_sync/api/runs/[id]/cancel.js.map +2 -2
  22. package/dist/modules/data_sync/api/runs/[id]/retry.js +7 -2
  23. package/dist/modules/data_sync/api/runs/[id]/retry.js.map +2 -2
  24. package/dist/modules/data_sync/api/runs/[id]/route.js +8 -3
  25. package/dist/modules/data_sync/api/runs/[id]/route.js.map +2 -2
  26. package/dist/modules/data_sync/api/runs.js +7 -2
  27. package/dist/modules/data_sync/api/runs.js.map +2 -2
  28. package/dist/modules/data_sync/api/schedules/[id]/route.js +19 -6
  29. package/dist/modules/data_sync/api/schedules/[id]/route.js.map +2 -2
  30. package/dist/modules/data_sync/api/schedules/route.js +13 -4
  31. package/dist/modules/data_sync/api/schedules/route.js.map +2 -2
  32. package/dist/modules/data_sync/api/validate.js +9 -4
  33. package/dist/modules/data_sync/api/validate.js.map +2 -2
  34. package/dist/modules/design_system/acl.js +9 -0
  35. package/dist/modules/design_system/acl.js.map +7 -0
  36. package/dist/modules/design_system/backend/design-system/page.js +11 -0
  37. package/dist/modules/design_system/backend/design-system/page.js.map +7 -0
  38. package/dist/modules/design_system/backend/design-system/page.meta.js +15 -0
  39. package/dist/modules/design_system/backend/design-system/page.meta.js.map +7 -0
  40. package/dist/modules/design_system/gallery/components/CodeSnippet.js +52 -0
  41. package/dist/modules/design_system/gallery/components/CodeSnippet.js.map +7 -0
  42. package/dist/modules/design_system/gallery/components/EntryCard.js +63 -0
  43. package/dist/modules/design_system/gallery/components/EntryCard.js.map +7 -0
  44. package/dist/modules/design_system/gallery/components/GalleryShell.js +163 -0
  45. package/dist/modules/design_system/gallery/components/GalleryShell.js.map +7 -0
  46. package/dist/modules/design_system/gallery/components/VariantPreview.js +9 -0
  47. package/dist/modules/design_system/gallery/components/VariantPreview.js.map +7 -0
  48. package/dist/modules/design_system/gallery/entries/banners.js +186 -0
  49. package/dist/modules/design_system/gallery/entries/banners.js.map +7 -0
  50. package/dist/modules/design_system/gallery/entries/buttons.js +361 -0
  51. package/dist/modules/design_system/gallery/entries/buttons.js.map +7 -0
  52. package/dist/modules/design_system/gallery/entries/charts.js +457 -0
  53. package/dist/modules/design_system/gallery/entries/charts.js.map +7 -0
  54. package/dist/modules/design_system/gallery/entries/dates.js +306 -0
  55. package/dist/modules/design_system/gallery/entries/dates.js.map +7 -0
  56. package/dist/modules/design_system/gallery/entries/detail.js +358 -0
  57. package/dist/modules/design_system/gallery/entries/detail.js.map +7 -0
  58. package/dist/modules/design_system/gallery/entries/display.js +785 -0
  59. package/dist/modules/design_system/gallery/entries/display.js.map +7 -0
  60. package/dist/modules/design_system/gallery/entries/feedback.js +658 -0
  61. package/dist/modules/design_system/gallery/entries/feedback.js.map +7 -0
  62. package/dist/modules/design_system/gallery/entries/filters.js +505 -0
  63. package/dist/modules/design_system/gallery/entries/filters.js.map +7 -0
  64. package/dist/modules/design_system/gallery/entries/foundations.js +453 -0
  65. package/dist/modules/design_system/gallery/entries/foundations.js.map +7 -0
  66. package/dist/modules/design_system/gallery/entries/icons.js +140 -0
  67. package/dist/modules/design_system/gallery/entries/icons.js.map +7 -0
  68. package/dist/modules/design_system/gallery/entries/inputs.js +1217 -0
  69. package/dist/modules/design_system/gallery/entries/inputs.js.map +7 -0
  70. package/dist/modules/design_system/gallery/entries/messages.js +334 -0
  71. package/dist/modules/design_system/gallery/entries/messages.js.map +7 -0
  72. package/dist/modules/design_system/gallery/entries/navigation.js +475 -0
  73. package/dist/modules/design_system/gallery/entries/navigation.js.map +7 -0
  74. package/dist/modules/design_system/gallery/entries/notifications.js +257 -0
  75. package/dist/modules/design_system/gallery/entries/notifications.js.map +7 -0
  76. package/dist/modules/design_system/gallery/entries/overlays.js +576 -0
  77. package/dist/modules/design_system/gallery/entries/overlays.js.map +7 -0
  78. package/dist/modules/design_system/gallery/entries/scaffolding.js +378 -0
  79. package/dist/modules/design_system/gallery/entries/scaffolding.js.map +7 -0
  80. package/dist/modules/design_system/gallery/entries/schedule.js +297 -0
  81. package/dist/modules/design_system/gallery/entries/schedule.js.map +7 -0
  82. package/dist/modules/design_system/gallery/registry.js +139 -0
  83. package/dist/modules/design_system/gallery/registry.js.map +7 -0
  84. package/dist/modules/design_system/gallery/types.js +1 -0
  85. package/dist/modules/design_system/gallery/types.js.map +7 -0
  86. package/dist/modules/design_system/index.js +9 -0
  87. package/dist/modules/design_system/index.js.map +7 -0
  88. package/dist/modules/design_system/setup.js +14 -0
  89. package/dist/modules/design_system/setup.js.map +7 -0
  90. package/dist/modules/inbox_ops/search.js +15 -4
  91. package/dist/modules/inbox_ops/search.js.map +2 -2
  92. package/dist/modules/integrations/api/[id]/credentials/route.js +11 -5
  93. package/dist/modules/integrations/api/[id]/credentials/route.js.map +2 -2
  94. package/dist/modules/integrations/api/[id]/health/route.js +6 -3
  95. package/dist/modules/integrations/api/[id]/health/route.js.map +2 -2
  96. package/dist/modules/integrations/api/[id]/route.js +6 -3
  97. package/dist/modules/integrations/api/[id]/route.js.map +2 -2
  98. package/dist/modules/integrations/api/[id]/state/route.js +6 -3
  99. package/dist/modules/integrations/api/[id]/state/route.js.map +2 -2
  100. package/dist/modules/integrations/api/[id]/version/route.js +6 -3
  101. package/dist/modules/integrations/api/[id]/version/route.js.map +2 -2
  102. package/dist/modules/integrations/api/logs/route.js +6 -3
  103. package/dist/modules/integrations/api/logs/route.js.map +2 -2
  104. package/dist/modules/integrations/api/route.js +6 -3
  105. package/dist/modules/integrations/api/route.js.map +2 -2
  106. package/dist/modules/integrations/api/umes-read.js +2 -2
  107. package/dist/modules/integrations/api/umes-read.js.map +2 -2
  108. package/dist/modules/integrations/lib/organization-scope.js +2 -9
  109. package/dist/modules/integrations/lib/organization-scope.js.map +2 -2
  110. package/dist/modules/messages/search.js +10 -5
  111. package/dist/modules/messages/search.js.map +2 -2
  112. package/dist/modules/query_index/data/entities.js +2 -1
  113. package/dist/modules/query_index/data/entities.js.map +2 -2
  114. package/dist/modules/query_index/lib/engine.js +32 -50
  115. package/dist/modules/query_index/lib/engine.js.map +2 -2
  116. package/dist/modules/query_index/migrations/Migration20260731105052_query_index.js +17 -0
  117. package/dist/modules/query_index/migrations/Migration20260731105052_query_index.js.map +7 -0
  118. package/generated/entities.ids.generated.ts +1 -0
  119. package/package.json +16 -16
  120. package/src/modules/auth/backend/settings/page.tsx +17 -8
  121. package/src/modules/customers/cli.ts +17 -7
  122. package/src/modules/customers/components/detail/ScheduleActivityDialog.tsx +24 -13
  123. package/src/modules/customers/i18n/de.json +17 -0
  124. package/src/modules/customers/i18n/en.json +17 -0
  125. package/src/modules/customers/i18n/es.json +17 -0
  126. package/src/modules/customers/i18n/pl.json +17 -0
  127. package/src/modules/customers/search.ts +59 -27
  128. package/src/modules/data_sync/AGENTS.md +1 -0
  129. package/src/modules/data_sync/api/mappings/[id]/route.ts +22 -9
  130. package/src/modules/data_sync/api/mappings/route.ts +13 -4
  131. package/src/modules/data_sync/api/options.ts +7 -2
  132. package/src/modules/data_sync/api/run.ts +7 -2
  133. package/src/modules/data_sync/api/runs/[id]/cancel.ts +8 -3
  134. package/src/modules/data_sync/api/runs/[id]/retry.ts +7 -2
  135. package/src/modules/data_sync/api/runs/[id]/route.ts +8 -3
  136. package/src/modules/data_sync/api/runs.ts +7 -2
  137. package/src/modules/data_sync/api/schedules/[id]/route.ts +19 -6
  138. package/src/modules/data_sync/api/schedules/route.ts +13 -4
  139. package/src/modules/data_sync/api/validate.ts +9 -4
  140. package/src/modules/design_system/AGENTS.md +34 -0
  141. package/src/modules/design_system/acl.ts +5 -0
  142. package/src/modules/design_system/backend/design-system/page.meta.ts +11 -0
  143. package/src/modules/design_system/backend/design-system/page.tsx +14 -0
  144. package/src/modules/design_system/gallery/components/CodeSnippet.tsx +55 -0
  145. package/src/modules/design_system/gallery/components/EntryCard.tsx +95 -0
  146. package/src/modules/design_system/gallery/components/GalleryShell.tsx +206 -0
  147. package/src/modules/design_system/gallery/components/VariantPreview.tsx +15 -0
  148. package/src/modules/design_system/gallery/entries/banners.tsx +226 -0
  149. package/src/modules/design_system/gallery/entries/buttons.tsx +422 -0
  150. package/src/modules/design_system/gallery/entries/charts.tsx +518 -0
  151. package/src/modules/design_system/gallery/entries/dates.tsx +325 -0
  152. package/src/modules/design_system/gallery/entries/detail.tsx +403 -0
  153. package/src/modules/design_system/gallery/entries/display.tsx +893 -0
  154. package/src/modules/design_system/gallery/entries/feedback.tsx +746 -0
  155. package/src/modules/design_system/gallery/entries/filters.tsx +570 -0
  156. package/src/modules/design_system/gallery/entries/foundations.tsx +529 -0
  157. package/src/modules/design_system/gallery/entries/icons.tsx +168 -0
  158. package/src/modules/design_system/gallery/entries/inputs.tsx +1516 -0
  159. package/src/modules/design_system/gallery/entries/messages.tsx +339 -0
  160. package/src/modules/design_system/gallery/entries/navigation.tsx +573 -0
  161. package/src/modules/design_system/gallery/entries/notifications.tsx +285 -0
  162. package/src/modules/design_system/gallery/entries/overlays.tsx +677 -0
  163. package/src/modules/design_system/gallery/entries/scaffolding.tsx +430 -0
  164. package/src/modules/design_system/gallery/entries/schedule.tsx +307 -0
  165. package/src/modules/design_system/gallery/registry.ts +152 -0
  166. package/src/modules/design_system/gallery/types.ts +32 -0
  167. package/src/modules/design_system/i18n/.hardcoded-allowlist.json +71 -0
  168. package/src/modules/design_system/i18n/de.json +46 -0
  169. package/src/modules/design_system/i18n/en.json +46 -0
  170. package/src/modules/design_system/i18n/es.json +46 -0
  171. package/src/modules/design_system/i18n/pl.json +46 -0
  172. package/src/modules/design_system/index.ts +7 -0
  173. package/src/modules/design_system/setup.ts +12 -0
  174. package/src/modules/inbox_ops/i18n/de.json +3 -0
  175. package/src/modules/inbox_ops/i18n/en.json +3 -0
  176. package/src/modules/inbox_ops/i18n/es.json +3 -0
  177. package/src/modules/inbox_ops/i18n/pl.json +3 -0
  178. package/src/modules/inbox_ops/search.ts +20 -4
  179. package/src/modules/integrations/api/[id]/credentials/route.ts +11 -5
  180. package/src/modules/integrations/api/[id]/health/route.ts +6 -3
  181. package/src/modules/integrations/api/[id]/route.ts +6 -3
  182. package/src/modules/integrations/api/[id]/state/route.ts +6 -3
  183. package/src/modules/integrations/api/[id]/version/route.ts +6 -3
  184. package/src/modules/integrations/api/logs/route.ts +6 -3
  185. package/src/modules/integrations/api/route.ts +6 -3
  186. package/src/modules/integrations/api/umes-read.ts +2 -2
  187. package/src/modules/integrations/lib/organization-scope.ts +5 -25
  188. package/src/modules/messages/i18n/de.json +2 -0
  189. package/src/modules/messages/i18n/en.json +2 -0
  190. package/src/modules/messages/i18n/es.json +2 -0
  191. package/src/modules/messages/i18n/pl.json +2 -0
  192. package/src/modules/messages/search.ts +11 -5
  193. package/src/modules/query_index/data/entities.ts +7 -0
  194. package/src/modules/query_index/lib/engine.ts +40 -63
  195. package/src/modules/query_index/migrations/.snapshot-open-mercato.json +12 -0
  196. package/src/modules/query_index/migrations/Migration20260731105052_query_index.ts +35 -0
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../../src/modules/data_sync/api/schedules/%5Bid%5D/route.ts"],
4
- "sourcesContent": ["import { NextResponse } from 'next/server'\nimport { z } from 'zod'\nimport { getAuthFromRequest } from '@open-mercato/shared/lib/auth/server'\nimport { createRequestContainer } from '@open-mercato/shared/lib/di/container'\nimport { readJsonSafe } from '@open-mercato/shared/lib/http/readJsonSafe'\nimport { readOptimisticLockExpected } from '@open-mercato/shared/lib/crud/optimistic-lock-command'\nimport { isCrudHttpError } from '@open-mercato/shared/lib/crud/errors'\nimport { updateSyncScheduleSchema } from '../../../data/validators'\nimport type { SyncScheduleService } from '../../../lib/sync-schedule-service'\nimport { serializeSchedule } from '../serialize'\nimport {\n runCrudMutationGuardAfterSuccess,\n validateCrudMutationGuard,\n} from '@open-mercato/shared/lib/crud/mutation-guard'\n\nconst paramsSchema = z.object({\n id: z.string().uuid(),\n})\n\nexport const metadata = {\n GET: { requireAuth: true, requireFeatures: ['data_sync.configure'] },\n PUT: { requireAuth: true, requireFeatures: ['data_sync.configure'] },\n DELETE: { requireAuth: true, requireFeatures: ['data_sync.configure'] },\n}\n\nexport const openApi = {\n tags: ['DataSync'],\n summary: 'Manage a sync schedule',\n}\n\nexport async function GET(req: Request, ctx: { params?: Promise<{ id?: string }> | { id?: string } }) {\n const auth = await getAuthFromRequest(req)\n if (!auth?.tenantId || !auth.orgId) {\n return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })\n }\n\n const rawParams = (ctx.params && typeof (ctx.params as Promise<unknown>).then === 'function')\n ? await (ctx.params as Promise<{ id?: string }>)\n : (ctx.params as { id?: string } | undefined)\n\n const parsedParams = paramsSchema.safeParse(rawParams)\n if (!parsedParams.success) {\n return NextResponse.json({ error: 'Invalid schedule id' }, { status: 400 })\n }\n\n const container = await createRequestContainer()\n const scheduleService = container.resolve('dataSyncScheduleService') as SyncScheduleService\n const schedule = await scheduleService.getById(parsedParams.data.id, {\n organizationId: auth.orgId as string,\n tenantId: auth.tenantId,\n })\n\n if (!schedule) {\n return NextResponse.json({ error: 'Schedule not found' }, { status: 404 })\n }\n\n return NextResponse.json(serializeSchedule(schedule))\n}\n\nexport async function PUT(req: Request, ctx: { params?: Promise<{ id?: string }> | { id?: string } }) {\n const auth = await getAuthFromRequest(req)\n if (!auth?.tenantId || !auth.orgId) {\n return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })\n }\n\n const rawParams = (ctx.params && typeof (ctx.params as Promise<unknown>).then === 'function')\n ? await (ctx.params as Promise<{ id?: string }>)\n : (ctx.params as { id?: string } | undefined)\n\n const parsedParams = paramsSchema.safeParse(rawParams)\n if (!parsedParams.success) {\n return NextResponse.json({ error: 'Invalid schedule id' }, { status: 400 })\n }\n\n const payload = await readJsonSafe(req)\n const parsed = updateSyncScheduleSchema.safeParse(payload)\n if (!parsed.success) {\n return NextResponse.json({ error: 'Invalid payload', details: parsed.error.flatten() }, { status: 422 })\n }\n\n const container = await createRequestContainer()\n const scheduleService = container.resolve('dataSyncScheduleService') as SyncScheduleService\n const scope = { organizationId: auth.orgId as string, tenantId: auth.tenantId }\n const current = await scheduleService.getById(parsedParams.data.id, scope)\n\n if (!current) {\n return NextResponse.json({ error: 'Schedule not found' }, { status: 404 })\n }\n\n const guardResult = await validateCrudMutationGuard(container, {\n tenantId: auth.tenantId,\n organizationId: scope.organizationId,\n userId: auth.sub,\n resourceKind: 'data_sync.schedule',\n resourceId: current.id,\n operation: 'update',\n requestMethod: req.method,\n requestHeaders: req.headers,\n mutationPayload: parsed.data,\n })\n if (guardResult && !guardResult.ok) {\n return NextResponse.json(guardResult.body, { status: guardResult.status })\n }\n\n try {\n const schedule = await scheduleService.saveSchedule({\n id: current.id,\n integrationId: parsed.data.integrationId ?? current.integrationId,\n entityType: parsed.data.entityType ?? current.entityType,\n direction: parsed.data.direction ?? current.direction,\n scheduleType: parsed.data.scheduleType ?? current.scheduleType,\n scheduleValue: parsed.data.scheduleValue ?? current.scheduleValue,\n timezone: parsed.data.timezone ?? current.timezone,\n fullSync: parsed.data.fullSync ?? current.fullSync,\n isEnabled: parsed.data.isEnabled ?? current.isEnabled,\n expectedUpdatedAt: readOptimisticLockExpected(req),\n }, scope, container)\n\n if (guardResult?.ok && guardResult.shouldRunAfterSuccess) {\n await runCrudMutationGuardAfterSuccess(container, {\n tenantId: auth.tenantId,\n organizationId: scope.organizationId,\n userId: auth.sub,\n resourceKind: 'data_sync.schedule',\n resourceId: schedule.id,\n operation: 'update',\n requestMethod: req.method,\n requestHeaders: req.headers,\n metadata: guardResult.metadata ?? null,\n })\n }\n return NextResponse.json(serializeSchedule(schedule))\n } catch (error) {\n if (isCrudHttpError(error)) {\n return NextResponse.json(error.body, { status: error.status })\n }\n const message = error instanceof Error ? error.message : 'Failed to update sync schedule'\n return NextResponse.json({ error: message }, { status: 422 })\n }\n}\n\nexport async function DELETE(req: Request, ctx: { params?: Promise<{ id?: string }> | { id?: string } }) {\n const auth = await getAuthFromRequest(req)\n if (!auth?.tenantId || !auth.orgId) {\n return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })\n }\n\n const rawParams = (ctx.params && typeof (ctx.params as Promise<unknown>).then === 'function')\n ? await (ctx.params as Promise<{ id?: string }>)\n : (ctx.params as { id?: string } | undefined)\n\n const parsedParams = paramsSchema.safeParse(rawParams)\n if (!parsedParams.success) {\n return NextResponse.json({ error: 'Invalid schedule id' }, { status: 400 })\n }\n\n const container = await createRequestContainer()\n const scheduleService = container.resolve('dataSyncScheduleService') as SyncScheduleService\n const scope = { organizationId: auth.orgId as string, tenantId: auth.tenantId }\n\n const guardResult = await validateCrudMutationGuard(container, {\n tenantId: auth.tenantId,\n organizationId: scope.organizationId,\n userId: auth.sub,\n resourceKind: 'data_sync.schedule',\n resourceId: parsedParams.data.id,\n operation: 'delete',\n requestMethod: req.method,\n requestHeaders: req.headers,\n mutationPayload: null,\n })\n if (guardResult && !guardResult.ok) {\n return NextResponse.json(guardResult.body, { status: guardResult.status })\n }\n\n try {\n const deleted = await scheduleService.deleteSchedule(\n parsedParams.data.id,\n scope,\n container,\n readOptimisticLockExpected(req),\n )\n\n if (!deleted) {\n return NextResponse.json({ error: 'Schedule not found' }, { status: 404 })\n }\n\n if (guardResult?.ok && guardResult.shouldRunAfterSuccess) {\n await runCrudMutationGuardAfterSuccess(container, {\n tenantId: auth.tenantId,\n organizationId: scope.organizationId,\n userId: auth.sub,\n resourceKind: 'data_sync.schedule',\n resourceId: parsedParams.data.id,\n operation: 'delete',\n requestMethod: req.method,\n requestHeaders: req.headers,\n metadata: guardResult.metadata ?? null,\n })\n }\n\n return NextResponse.json({ deleted: true })\n } catch (error) {\n if (isCrudHttpError(error)) {\n return NextResponse.json(error.body, { status: error.status })\n }\n const message = error instanceof Error ? error.message : 'Failed to delete sync schedule'\n return NextResponse.json({ error: message }, { status: 422 })\n }\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { NextResponse } from 'next/server'\nimport { z } from 'zod'\nimport { getAuthFromRequest } from '@open-mercato/shared/lib/auth/server'\nimport { organizationScopeRequiredResponse, resolveActiveOrganizationId } from '@open-mercato/shared/lib/auth/organizationScope'\nimport { createRequestContainer } from '@open-mercato/shared/lib/di/container'\nimport { readJsonSafe } from '@open-mercato/shared/lib/http/readJsonSafe'\nimport { readOptimisticLockExpected } from '@open-mercato/shared/lib/crud/optimistic-lock-command'\nimport { isCrudHttpError } from '@open-mercato/shared/lib/crud/errors'\nimport { updateSyncScheduleSchema } from '../../../data/validators'\nimport type { SyncScheduleService } from '../../../lib/sync-schedule-service'\nimport { serializeSchedule } from '../serialize'\nimport {\n runCrudMutationGuardAfterSuccess,\n validateCrudMutationGuard,\n} from '@open-mercato/shared/lib/crud/mutation-guard'\n\nconst paramsSchema = z.object({\n id: z.string().uuid(),\n})\n\nexport const metadata = {\n GET: { requireAuth: true, requireFeatures: ['data_sync.configure'] },\n PUT: { requireAuth: true, requireFeatures: ['data_sync.configure'] },\n DELETE: { requireAuth: true, requireFeatures: ['data_sync.configure'] },\n}\n\nexport const openApi = {\n tags: ['DataSync'],\n summary: 'Manage a sync schedule',\n}\n\nexport async function GET(req: Request, ctx: { params?: Promise<{ id?: string }> | { id?: string } }) {\n const auth = await getAuthFromRequest(req)\n if (!auth?.tenantId) {\n return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })\n }\n const organizationId = resolveActiveOrganizationId(auth)\n if (!organizationId) {\n return organizationScopeRequiredResponse()\n }\n\n const rawParams = (ctx.params && typeof (ctx.params as Promise<unknown>).then === 'function')\n ? await (ctx.params as Promise<{ id?: string }>)\n : (ctx.params as { id?: string } | undefined)\n\n const parsedParams = paramsSchema.safeParse(rawParams)\n if (!parsedParams.success) {\n return NextResponse.json({ error: 'Invalid schedule id' }, { status: 400 })\n }\n\n const container = await createRequestContainer()\n const scheduleService = container.resolve('dataSyncScheduleService') as SyncScheduleService\n const schedule = await scheduleService.getById(parsedParams.data.id, {\n organizationId,\n tenantId: auth.tenantId,\n })\n\n if (!schedule) {\n return NextResponse.json({ error: 'Schedule not found' }, { status: 404 })\n }\n\n return NextResponse.json(serializeSchedule(schedule))\n}\n\nexport async function PUT(req: Request, ctx: { params?: Promise<{ id?: string }> | { id?: string } }) {\n const auth = await getAuthFromRequest(req)\n if (!auth?.tenantId) {\n return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })\n }\n const organizationId = resolveActiveOrganizationId(auth)\n if (!organizationId) {\n return organizationScopeRequiredResponse()\n }\n\n const rawParams = (ctx.params && typeof (ctx.params as Promise<unknown>).then === 'function')\n ? await (ctx.params as Promise<{ id?: string }>)\n : (ctx.params as { id?: string } | undefined)\n\n const parsedParams = paramsSchema.safeParse(rawParams)\n if (!parsedParams.success) {\n return NextResponse.json({ error: 'Invalid schedule id' }, { status: 400 })\n }\n\n const payload = await readJsonSafe(req)\n const parsed = updateSyncScheduleSchema.safeParse(payload)\n if (!parsed.success) {\n return NextResponse.json({ error: 'Invalid payload', details: parsed.error.flatten() }, { status: 422 })\n }\n\n const container = await createRequestContainer()\n const scheduleService = container.resolve('dataSyncScheduleService') as SyncScheduleService\n const scope = { organizationId, tenantId: auth.tenantId }\n const current = await scheduleService.getById(parsedParams.data.id, scope)\n\n if (!current) {\n return NextResponse.json({ error: 'Schedule not found' }, { status: 404 })\n }\n\n const guardResult = await validateCrudMutationGuard(container, {\n tenantId: auth.tenantId,\n organizationId: scope.organizationId,\n userId: auth.sub,\n resourceKind: 'data_sync.schedule',\n resourceId: current.id,\n operation: 'update',\n requestMethod: req.method,\n requestHeaders: req.headers,\n mutationPayload: parsed.data,\n })\n if (guardResult && !guardResult.ok) {\n return NextResponse.json(guardResult.body, { status: guardResult.status })\n }\n\n try {\n const schedule = await scheduleService.saveSchedule({\n id: current.id,\n integrationId: parsed.data.integrationId ?? current.integrationId,\n entityType: parsed.data.entityType ?? current.entityType,\n direction: parsed.data.direction ?? current.direction,\n scheduleType: parsed.data.scheduleType ?? current.scheduleType,\n scheduleValue: parsed.data.scheduleValue ?? current.scheduleValue,\n timezone: parsed.data.timezone ?? current.timezone,\n fullSync: parsed.data.fullSync ?? current.fullSync,\n isEnabled: parsed.data.isEnabled ?? current.isEnabled,\n expectedUpdatedAt: readOptimisticLockExpected(req),\n }, scope, container)\n\n if (guardResult?.ok && guardResult.shouldRunAfterSuccess) {\n await runCrudMutationGuardAfterSuccess(container, {\n tenantId: auth.tenantId,\n organizationId: scope.organizationId,\n userId: auth.sub,\n resourceKind: 'data_sync.schedule',\n resourceId: schedule.id,\n operation: 'update',\n requestMethod: req.method,\n requestHeaders: req.headers,\n metadata: guardResult.metadata ?? null,\n })\n }\n return NextResponse.json(serializeSchedule(schedule))\n } catch (error) {\n if (isCrudHttpError(error)) {\n return NextResponse.json(error.body, { status: error.status })\n }\n const message = error instanceof Error ? error.message : 'Failed to update sync schedule'\n return NextResponse.json({ error: message }, { status: 422 })\n }\n}\n\nexport async function DELETE(req: Request, ctx: { params?: Promise<{ id?: string }> | { id?: string } }) {\n const auth = await getAuthFromRequest(req)\n if (!auth?.tenantId) {\n return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })\n }\n const organizationId = resolveActiveOrganizationId(auth)\n if (!organizationId) {\n return organizationScopeRequiredResponse()\n }\n\n const rawParams = (ctx.params && typeof (ctx.params as Promise<unknown>).then === 'function')\n ? await (ctx.params as Promise<{ id?: string }>)\n : (ctx.params as { id?: string } | undefined)\n\n const parsedParams = paramsSchema.safeParse(rawParams)\n if (!parsedParams.success) {\n return NextResponse.json({ error: 'Invalid schedule id' }, { status: 400 })\n }\n\n const container = await createRequestContainer()\n const scheduleService = container.resolve('dataSyncScheduleService') as SyncScheduleService\n const scope = { organizationId, tenantId: auth.tenantId }\n\n const guardResult = await validateCrudMutationGuard(container, {\n tenantId: auth.tenantId,\n organizationId: scope.organizationId,\n userId: auth.sub,\n resourceKind: 'data_sync.schedule',\n resourceId: parsedParams.data.id,\n operation: 'delete',\n requestMethod: req.method,\n requestHeaders: req.headers,\n mutationPayload: null,\n })\n if (guardResult && !guardResult.ok) {\n return NextResponse.json(guardResult.body, { status: guardResult.status })\n }\n\n try {\n const deleted = await scheduleService.deleteSchedule(\n parsedParams.data.id,\n scope,\n container,\n readOptimisticLockExpected(req),\n )\n\n if (!deleted) {\n return NextResponse.json({ error: 'Schedule not found' }, { status: 404 })\n }\n\n if (guardResult?.ok && guardResult.shouldRunAfterSuccess) {\n await runCrudMutationGuardAfterSuccess(container, {\n tenantId: auth.tenantId,\n organizationId: scope.organizationId,\n userId: auth.sub,\n resourceKind: 'data_sync.schedule',\n resourceId: parsedParams.data.id,\n operation: 'delete',\n requestMethod: req.method,\n requestHeaders: req.headers,\n metadata: guardResult.metadata ?? null,\n })\n }\n\n return NextResponse.json({ deleted: true })\n } catch (error) {\n if (isCrudHttpError(error)) {\n return NextResponse.json(error.body, { status: error.status })\n }\n const message = error instanceof Error ? error.message : 'Failed to delete sync schedule'\n return NextResponse.json({ error: message }, { status: 422 })\n }\n}\n"],
5
+ "mappings": "AAAA,SAAS,oBAAoB;AAC7B,SAAS,SAAS;AAClB,SAAS,0BAA0B;AACnC,SAAS,mCAAmC,mCAAmC;AAC/E,SAAS,8BAA8B;AACvC,SAAS,oBAAoB;AAC7B,SAAS,kCAAkC;AAC3C,SAAS,uBAAuB;AAChC,SAAS,gCAAgC;AAEzC,SAAS,yBAAyB;AAClC;AAAA,EACE;AAAA,EACA;AAAA,OACK;AAEP,MAAM,eAAe,EAAE,OAAO;AAAA,EAC5B,IAAI,EAAE,OAAO,EAAE,KAAK;AACtB,CAAC;AAEM,MAAM,WAAW;AAAA,EACtB,KAAK,EAAE,aAAa,MAAM,iBAAiB,CAAC,qBAAqB,EAAE;AAAA,EACnE,KAAK,EAAE,aAAa,MAAM,iBAAiB,CAAC,qBAAqB,EAAE;AAAA,EACnE,QAAQ,EAAE,aAAa,MAAM,iBAAiB,CAAC,qBAAqB,EAAE;AACxE;AAEO,MAAM,UAAU;AAAA,EACrB,MAAM,CAAC,UAAU;AAAA,EACjB,SAAS;AACX;AAEA,eAAsB,IAAI,KAAc,KAA8D;AACpG,QAAM,OAAO,MAAM,mBAAmB,GAAG;AACzC,MAAI,CAAC,MAAM,UAAU;AACnB,WAAO,aAAa,KAAK,EAAE,OAAO,eAAe,GAAG,EAAE,QAAQ,IAAI,CAAC;AAAA,EACrE;AACA,QAAM,iBAAiB,4BAA4B,IAAI;AACvD,MAAI,CAAC,gBAAgB;AACnB,WAAO,kCAAkC;AAAA,EAC3C;AAEA,QAAM,YAAa,IAAI,UAAU,OAAQ,IAAI,OAA4B,SAAS,aAC9E,MAAO,IAAI,SACV,IAAI;AAET,QAAM,eAAe,aAAa,UAAU,SAAS;AACrD,MAAI,CAAC,aAAa,SAAS;AACzB,WAAO,aAAa,KAAK,EAAE,OAAO,sBAAsB,GAAG,EAAE,QAAQ,IAAI,CAAC;AAAA,EAC5E;AAEA,QAAM,YAAY,MAAM,uBAAuB;AAC/C,QAAM,kBAAkB,UAAU,QAAQ,yBAAyB;AACnE,QAAM,WAAW,MAAM,gBAAgB,QAAQ,aAAa,KAAK,IAAI;AAAA,IACnE;AAAA,IACA,UAAU,KAAK;AAAA,EACjB,CAAC;AAED,MAAI,CAAC,UAAU;AACb,WAAO,aAAa,KAAK,EAAE,OAAO,qBAAqB,GAAG,EAAE,QAAQ,IAAI,CAAC;AAAA,EAC3E;AAEA,SAAO,aAAa,KAAK,kBAAkB,QAAQ,CAAC;AACtD;AAEA,eAAsB,IAAI,KAAc,KAA8D;AACpG,QAAM,OAAO,MAAM,mBAAmB,GAAG;AACzC,MAAI,CAAC,MAAM,UAAU;AACnB,WAAO,aAAa,KAAK,EAAE,OAAO,eAAe,GAAG,EAAE,QAAQ,IAAI,CAAC;AAAA,EACrE;AACA,QAAM,iBAAiB,4BAA4B,IAAI;AACvD,MAAI,CAAC,gBAAgB;AACnB,WAAO,kCAAkC;AAAA,EAC3C;AAEA,QAAM,YAAa,IAAI,UAAU,OAAQ,IAAI,OAA4B,SAAS,aAC9E,MAAO,IAAI,SACV,IAAI;AAET,QAAM,eAAe,aAAa,UAAU,SAAS;AACrD,MAAI,CAAC,aAAa,SAAS;AACzB,WAAO,aAAa,KAAK,EAAE,OAAO,sBAAsB,GAAG,EAAE,QAAQ,IAAI,CAAC;AAAA,EAC5E;AAEA,QAAM,UAAU,MAAM,aAAa,GAAG;AACtC,QAAM,SAAS,yBAAyB,UAAU,OAAO;AACzD,MAAI,CAAC,OAAO,SAAS;AACnB,WAAO,aAAa,KAAK,EAAE,OAAO,mBAAmB,SAAS,OAAO,MAAM,QAAQ,EAAE,GAAG,EAAE,QAAQ,IAAI,CAAC;AAAA,EACzG;AAEA,QAAM,YAAY,MAAM,uBAAuB;AAC/C,QAAM,kBAAkB,UAAU,QAAQ,yBAAyB;AACnE,QAAM,QAAQ,EAAE,gBAAgB,UAAU,KAAK,SAAS;AACxD,QAAM,UAAU,MAAM,gBAAgB,QAAQ,aAAa,KAAK,IAAI,KAAK;AAEzE,MAAI,CAAC,SAAS;AACZ,WAAO,aAAa,KAAK,EAAE,OAAO,qBAAqB,GAAG,EAAE,QAAQ,IAAI,CAAC;AAAA,EAC3E;AAEA,QAAM,cAAc,MAAM,0BAA0B,WAAW;AAAA,IAC7D,UAAU,KAAK;AAAA,IACf,gBAAgB,MAAM;AAAA,IACtB,QAAQ,KAAK;AAAA,IACb,cAAc;AAAA,IACd,YAAY,QAAQ;AAAA,IACpB,WAAW;AAAA,IACX,eAAe,IAAI;AAAA,IACnB,gBAAgB,IAAI;AAAA,IACpB,iBAAiB,OAAO;AAAA,EAC1B,CAAC;AACD,MAAI,eAAe,CAAC,YAAY,IAAI;AAClC,WAAO,aAAa,KAAK,YAAY,MAAM,EAAE,QAAQ,YAAY,OAAO,CAAC;AAAA,EAC3E;AAEA,MAAI;AACF,UAAM,WAAW,MAAM,gBAAgB,aAAa;AAAA,MAClD,IAAI,QAAQ;AAAA,MACZ,eAAe,OAAO,KAAK,iBAAiB,QAAQ;AAAA,MACpD,YAAY,OAAO,KAAK,cAAc,QAAQ;AAAA,MAC9C,WAAW,OAAO,KAAK,aAAa,QAAQ;AAAA,MAC5C,cAAc,OAAO,KAAK,gBAAgB,QAAQ;AAAA,MAClD,eAAe,OAAO,KAAK,iBAAiB,QAAQ;AAAA,MACpD,UAAU,OAAO,KAAK,YAAY,QAAQ;AAAA,MAC1C,UAAU,OAAO,KAAK,YAAY,QAAQ;AAAA,MAC1C,WAAW,OAAO,KAAK,aAAa,QAAQ;AAAA,MAC5C,mBAAmB,2BAA2B,GAAG;AAAA,IACnD,GAAG,OAAO,SAAS;AAEnB,QAAI,aAAa,MAAM,YAAY,uBAAuB;AACxD,YAAM,iCAAiC,WAAW;AAAA,QAChD,UAAU,KAAK;AAAA,QACf,gBAAgB,MAAM;AAAA,QACtB,QAAQ,KAAK;AAAA,QACb,cAAc;AAAA,QACd,YAAY,SAAS;AAAA,QACrB,WAAW;AAAA,QACX,eAAe,IAAI;AAAA,QACnB,gBAAgB,IAAI;AAAA,QACpB,UAAU,YAAY,YAAY;AAAA,MACpC,CAAC;AAAA,IACH;AACA,WAAO,aAAa,KAAK,kBAAkB,QAAQ,CAAC;AAAA,EACtD,SAAS,OAAO;AACd,QAAI,gBAAgB,KAAK,GAAG;AAC1B,aAAO,aAAa,KAAK,MAAM,MAAM,EAAE,QAAQ,MAAM,OAAO,CAAC;AAAA,IAC/D;AACA,UAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU;AACzD,WAAO,aAAa,KAAK,EAAE,OAAO,QAAQ,GAAG,EAAE,QAAQ,IAAI,CAAC;AAAA,EAC9D;AACF;AAEA,eAAsB,OAAO,KAAc,KAA8D;AACvG,QAAM,OAAO,MAAM,mBAAmB,GAAG;AACzC,MAAI,CAAC,MAAM,UAAU;AACnB,WAAO,aAAa,KAAK,EAAE,OAAO,eAAe,GAAG,EAAE,QAAQ,IAAI,CAAC;AAAA,EACrE;AACA,QAAM,iBAAiB,4BAA4B,IAAI;AACvD,MAAI,CAAC,gBAAgB;AACnB,WAAO,kCAAkC;AAAA,EAC3C;AAEA,QAAM,YAAa,IAAI,UAAU,OAAQ,IAAI,OAA4B,SAAS,aAC9E,MAAO,IAAI,SACV,IAAI;AAET,QAAM,eAAe,aAAa,UAAU,SAAS;AACrD,MAAI,CAAC,aAAa,SAAS;AACzB,WAAO,aAAa,KAAK,EAAE,OAAO,sBAAsB,GAAG,EAAE,QAAQ,IAAI,CAAC;AAAA,EAC5E;AAEA,QAAM,YAAY,MAAM,uBAAuB;AAC/C,QAAM,kBAAkB,UAAU,QAAQ,yBAAyB;AACnE,QAAM,QAAQ,EAAE,gBAAgB,UAAU,KAAK,SAAS;AAExD,QAAM,cAAc,MAAM,0BAA0B,WAAW;AAAA,IAC7D,UAAU,KAAK;AAAA,IACf,gBAAgB,MAAM;AAAA,IACtB,QAAQ,KAAK;AAAA,IACb,cAAc;AAAA,IACd,YAAY,aAAa,KAAK;AAAA,IAC9B,WAAW;AAAA,IACX,eAAe,IAAI;AAAA,IACnB,gBAAgB,IAAI;AAAA,IACpB,iBAAiB;AAAA,EACnB,CAAC;AACD,MAAI,eAAe,CAAC,YAAY,IAAI;AAClC,WAAO,aAAa,KAAK,YAAY,MAAM,EAAE,QAAQ,YAAY,OAAO,CAAC;AAAA,EAC3E;AAEA,MAAI;AACF,UAAM,UAAU,MAAM,gBAAgB;AAAA,MACpC,aAAa,KAAK;AAAA,MAClB;AAAA,MACA;AAAA,MACA,2BAA2B,GAAG;AAAA,IAChC;AAEA,QAAI,CAAC,SAAS;AACZ,aAAO,aAAa,KAAK,EAAE,OAAO,qBAAqB,GAAG,EAAE,QAAQ,IAAI,CAAC;AAAA,IAC3E;AAEA,QAAI,aAAa,MAAM,YAAY,uBAAuB;AACxD,YAAM,iCAAiC,WAAW;AAAA,QAChD,UAAU,KAAK;AAAA,QACf,gBAAgB,MAAM;AAAA,QACtB,QAAQ,KAAK;AAAA,QACb,cAAc;AAAA,QACd,YAAY,aAAa,KAAK;AAAA,QAC9B,WAAW;AAAA,QACX,eAAe,IAAI;AAAA,QACnB,gBAAgB,IAAI;AAAA,QACpB,UAAU,YAAY,YAAY;AAAA,MACpC,CAAC;AAAA,IACH;AAEA,WAAO,aAAa,KAAK,EAAE,SAAS,KAAK,CAAC;AAAA,EAC5C,SAAS,OAAO;AACd,QAAI,gBAAgB,KAAK,GAAG;AAC1B,aAAO,aAAa,KAAK,MAAM,MAAM,EAAE,QAAQ,MAAM,OAAO,CAAC;AAAA,IAC/D;AACA,UAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU;AACzD,WAAO,aAAa,KAAK,EAAE,OAAO,QAAQ,GAAG,EAAE,QAAQ,IAAI,CAAC;AAAA,EAC9D;AACF;",
6
6
  "names": []
7
7
  }
@@ -1,5 +1,6 @@
1
1
  import { NextResponse } from "next/server";
2
2
  import { getAuthFromRequest } from "@open-mercato/shared/lib/auth/server";
3
+ import { organizationScopeRequiredResponse, resolveActiveOrganizationId } from "@open-mercato/shared/lib/auth/organizationScope";
3
4
  import { createRequestContainer } from "@open-mercato/shared/lib/di/container";
4
5
  import { readJsonSafe } from "@open-mercato/shared/lib/http/readJsonSafe";
5
6
  import { createSyncScheduleSchema, listSyncSchedulesQuerySchema } from "../../data/validators.js";
@@ -20,9 +21,13 @@ const openApi = {
20
21
  };
21
22
  async function GET(req) {
22
23
  const auth = await getAuthFromRequest(req);
23
- if (!auth?.tenantId || !auth.orgId) {
24
+ if (!auth?.tenantId) {
24
25
  return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
25
26
  }
27
+ const organizationId = resolveActiveOrganizationId(auth);
28
+ if (!organizationId) {
29
+ return organizationScopeRequiredResponse();
30
+ }
26
31
  const url = new URL(req.url);
27
32
  const parsed = listSyncSchedulesQuerySchema.safeParse({
28
33
  integrationId: url.searchParams.get("integrationId") ?? void 0,
@@ -36,7 +41,7 @@ async function GET(req) {
36
41
  }
37
42
  const container = await createRequestContainer();
38
43
  const scheduleService = container.resolve("dataSyncScheduleService");
39
- const scope = { organizationId: auth.orgId, tenantId: auth.tenantId };
44
+ const scope = { organizationId, tenantId: auth.tenantId };
40
45
  const { items, total } = await scheduleService.listSchedules(parsed.data, scope);
41
46
  return NextResponse.json({
42
47
  items: items.map(serializeSchedule),
@@ -48,9 +53,13 @@ async function GET(req) {
48
53
  }
49
54
  async function POST(req) {
50
55
  const auth = await getAuthFromRequest(req);
51
- if (!auth?.tenantId || !auth.orgId) {
56
+ if (!auth?.tenantId) {
52
57
  return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
53
58
  }
59
+ const organizationId = resolveActiveOrganizationId(auth);
60
+ if (!organizationId) {
61
+ return organizationScopeRequiredResponse();
62
+ }
54
63
  const payload = await readJsonSafe(req);
55
64
  const parsed = createSyncScheduleSchema.safeParse(payload);
56
65
  if (!parsed.success) {
@@ -58,7 +67,7 @@ async function POST(req) {
58
67
  }
59
68
  const container = await createRequestContainer();
60
69
  const scheduleService = container.resolve("dataSyncScheduleService");
61
- const scope = { organizationId: auth.orgId, tenantId: auth.tenantId };
70
+ const scope = { organizationId, tenantId: auth.tenantId };
62
71
  const guardResult = await validateCrudMutationGuard(container, {
63
72
  tenantId: auth.tenantId,
64
73
  organizationId: scope.organizationId,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../src/modules/data_sync/api/schedules/route.ts"],
4
- "sourcesContent": ["import { NextResponse } from 'next/server'\nimport { getAuthFromRequest } from '@open-mercato/shared/lib/auth/server'\nimport { createRequestContainer } from '@open-mercato/shared/lib/di/container'\nimport { readJsonSafe } from '@open-mercato/shared/lib/http/readJsonSafe'\nimport { createSyncScheduleSchema, listSyncSchedulesQuerySchema } from '../../data/validators'\nimport type { SyncScheduleService } from '../../lib/sync-schedule-service'\nimport { serializeSchedule } from './serialize'\nimport { readOptimisticLockExpected } from '@open-mercato/shared/lib/crud/optimistic-lock-command'\nimport { isCrudHttpError } from '@open-mercato/shared/lib/crud/errors'\nimport {\n runCrudMutationGuardAfterSuccess,\n validateCrudMutationGuard,\n} from '@open-mercato/shared/lib/crud/mutation-guard'\n\nexport const metadata = {\n GET: { requireAuth: true, requireFeatures: ['data_sync.configure'] },\n POST: { requireAuth: true, requireFeatures: ['data_sync.configure'] },\n}\n\nexport const openApi = {\n tags: ['DataSync'],\n summary: 'List or create sync schedules',\n}\n\nexport async function GET(req: Request) {\n const auth = await getAuthFromRequest(req)\n if (!auth?.tenantId || !auth.orgId) {\n return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })\n }\n\n const url = new URL(req.url)\n const parsed = listSyncSchedulesQuerySchema.safeParse({\n integrationId: url.searchParams.get('integrationId') ?? undefined,\n entityType: url.searchParams.get('entityType') ?? undefined,\n direction: url.searchParams.get('direction') ?? undefined,\n page: url.searchParams.get('page') ?? undefined,\n pageSize: url.searchParams.get('pageSize') ?? undefined,\n })\n\n if (!parsed.success) {\n return NextResponse.json({ error: 'Invalid query', details: parsed.error.flatten() }, { status: 400 })\n }\n\n const container = await createRequestContainer()\n const scheduleService = container.resolve('dataSyncScheduleService') as SyncScheduleService\n const scope = { organizationId: auth.orgId as string, tenantId: auth.tenantId }\n const { items, total } = await scheduleService.listSchedules(parsed.data, scope)\n\n return NextResponse.json({\n items: items.map(serializeSchedule),\n total,\n page: parsed.data.page,\n pageSize: parsed.data.pageSize,\n totalPages: Math.max(1, Math.ceil(total / parsed.data.pageSize)),\n })\n}\n\nexport async function POST(req: Request) {\n const auth = await getAuthFromRequest(req)\n if (!auth?.tenantId || !auth.orgId) {\n return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })\n }\n\n const payload = await readJsonSafe(req)\n const parsed = createSyncScheduleSchema.safeParse(payload)\n if (!parsed.success) {\n return NextResponse.json({ error: 'Invalid payload', details: parsed.error.flatten() }, { status: 422 })\n }\n\n const container = await createRequestContainer()\n const scheduleService = container.resolve('dataSyncScheduleService') as SyncScheduleService\n const scope = { organizationId: auth.orgId as string, tenantId: auth.tenantId }\n\n const guardResult = await validateCrudMutationGuard(container, {\n tenantId: auth.tenantId,\n organizationId: scope.organizationId,\n userId: auth.sub,\n resourceKind: 'data_sync.schedule',\n resourceId: scope.organizationId,\n operation: 'create',\n requestMethod: req.method,\n requestHeaders: req.headers,\n mutationPayload: parsed.data,\n })\n if (guardResult && !guardResult.ok) {\n return NextResponse.json(guardResult.body, { status: guardResult.status })\n }\n\n try {\n const schedule = await scheduleService.saveSchedule({\n ...parsed.data,\n expectedUpdatedAt: readOptimisticLockExpected(req),\n }, scope, container)\n\n if (guardResult?.ok && guardResult.shouldRunAfterSuccess) {\n await runCrudMutationGuardAfterSuccess(container, {\n tenantId: auth.tenantId,\n organizationId: scope.organizationId,\n userId: auth.sub,\n resourceKind: 'data_sync.schedule',\n resourceId: schedule.id,\n operation: 'create',\n requestMethod: req.method,\n requestHeaders: req.headers,\n metadata: guardResult.metadata ?? null,\n })\n }\n\n return NextResponse.json(serializeSchedule(schedule), { status: 201 })\n } catch (error) {\n if (isCrudHttpError(error)) {\n return NextResponse.json(error.body, { status: error.status })\n }\n const message = error instanceof Error ? error.message : 'Failed to save sync schedule'\n return NextResponse.json({ error: message }, { status: 422 })\n }\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { NextResponse } from 'next/server'\nimport { getAuthFromRequest } from '@open-mercato/shared/lib/auth/server'\nimport { organizationScopeRequiredResponse, resolveActiveOrganizationId } from '@open-mercato/shared/lib/auth/organizationScope'\nimport { createRequestContainer } from '@open-mercato/shared/lib/di/container'\nimport { readJsonSafe } from '@open-mercato/shared/lib/http/readJsonSafe'\nimport { createSyncScheduleSchema, listSyncSchedulesQuerySchema } from '../../data/validators'\nimport type { SyncScheduleService } from '../../lib/sync-schedule-service'\nimport { serializeSchedule } from './serialize'\nimport { readOptimisticLockExpected } from '@open-mercato/shared/lib/crud/optimistic-lock-command'\nimport { isCrudHttpError } from '@open-mercato/shared/lib/crud/errors'\nimport {\n runCrudMutationGuardAfterSuccess,\n validateCrudMutationGuard,\n} from '@open-mercato/shared/lib/crud/mutation-guard'\n\nexport const metadata = {\n GET: { requireAuth: true, requireFeatures: ['data_sync.configure'] },\n POST: { requireAuth: true, requireFeatures: ['data_sync.configure'] },\n}\n\nexport const openApi = {\n tags: ['DataSync'],\n summary: 'List or create sync schedules',\n}\n\nexport async function GET(req: Request) {\n const auth = await getAuthFromRequest(req)\n if (!auth?.tenantId) {\n return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })\n }\n const organizationId = resolveActiveOrganizationId(auth)\n if (!organizationId) {\n return organizationScopeRequiredResponse()\n }\n\n const url = new URL(req.url)\n const parsed = listSyncSchedulesQuerySchema.safeParse({\n integrationId: url.searchParams.get('integrationId') ?? undefined,\n entityType: url.searchParams.get('entityType') ?? undefined,\n direction: url.searchParams.get('direction') ?? undefined,\n page: url.searchParams.get('page') ?? undefined,\n pageSize: url.searchParams.get('pageSize') ?? undefined,\n })\n\n if (!parsed.success) {\n return NextResponse.json({ error: 'Invalid query', details: parsed.error.flatten() }, { status: 400 })\n }\n\n const container = await createRequestContainer()\n const scheduleService = container.resolve('dataSyncScheduleService') as SyncScheduleService\n const scope = { organizationId, tenantId: auth.tenantId }\n const { items, total } = await scheduleService.listSchedules(parsed.data, scope)\n\n return NextResponse.json({\n items: items.map(serializeSchedule),\n total,\n page: parsed.data.page,\n pageSize: parsed.data.pageSize,\n totalPages: Math.max(1, Math.ceil(total / parsed.data.pageSize)),\n })\n}\n\nexport async function POST(req: Request) {\n const auth = await getAuthFromRequest(req)\n if (!auth?.tenantId) {\n return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })\n }\n const organizationId = resolveActiveOrganizationId(auth)\n if (!organizationId) {\n return organizationScopeRequiredResponse()\n }\n\n const payload = await readJsonSafe(req)\n const parsed = createSyncScheduleSchema.safeParse(payload)\n if (!parsed.success) {\n return NextResponse.json({ error: 'Invalid payload', details: parsed.error.flatten() }, { status: 422 })\n }\n\n const container = await createRequestContainer()\n const scheduleService = container.resolve('dataSyncScheduleService') as SyncScheduleService\n const scope = { organizationId, tenantId: auth.tenantId }\n\n const guardResult = await validateCrudMutationGuard(container, {\n tenantId: auth.tenantId,\n organizationId: scope.organizationId,\n userId: auth.sub,\n resourceKind: 'data_sync.schedule',\n resourceId: scope.organizationId,\n operation: 'create',\n requestMethod: req.method,\n requestHeaders: req.headers,\n mutationPayload: parsed.data,\n })\n if (guardResult && !guardResult.ok) {\n return NextResponse.json(guardResult.body, { status: guardResult.status })\n }\n\n try {\n const schedule = await scheduleService.saveSchedule({\n ...parsed.data,\n expectedUpdatedAt: readOptimisticLockExpected(req),\n }, scope, container)\n\n if (guardResult?.ok && guardResult.shouldRunAfterSuccess) {\n await runCrudMutationGuardAfterSuccess(container, {\n tenantId: auth.tenantId,\n organizationId: scope.organizationId,\n userId: auth.sub,\n resourceKind: 'data_sync.schedule',\n resourceId: schedule.id,\n operation: 'create',\n requestMethod: req.method,\n requestHeaders: req.headers,\n metadata: guardResult.metadata ?? null,\n })\n }\n\n return NextResponse.json(serializeSchedule(schedule), { status: 201 })\n } catch (error) {\n if (isCrudHttpError(error)) {\n return NextResponse.json(error.body, { status: error.status })\n }\n const message = error instanceof Error ? error.message : 'Failed to save sync schedule'\n return NextResponse.json({ error: message }, { status: 422 })\n }\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -1,5 +1,6 @@
1
1
  import { NextResponse } from "next/server";
2
2
  import { getAuthFromRequest } from "@open-mercato/shared/lib/auth/server";
3
+ import { organizationScopeRequiredResponse, resolveActiveOrganizationId } from "@open-mercato/shared/lib/auth/organizationScope";
3
4
  import { createRequestContainer } from "@open-mercato/shared/lib/di/container";
4
5
  import { getIntegration } from "@open-mercato/shared/modules/integrations/types";
5
6
  import { validateConnectionSchema } from "../data/validators.js";
@@ -13,9 +14,13 @@ const openApi = {
13
14
  };
14
15
  async function POST(req) {
15
16
  const auth = await getAuthFromRequest(req);
16
- if (!auth?.tenantId || !auth.orgId) {
17
+ if (!auth?.tenantId) {
17
18
  return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
18
19
  }
20
+ const organizationId = resolveActiveOrganizationId(auth);
21
+ if (!organizationId) {
22
+ return organizationScopeRequiredResponse();
23
+ }
19
24
  const parsed = validateConnectionSchema.safeParse(await req.json());
20
25
  if (!parsed.success) {
21
26
  return NextResponse.json({ error: "Invalid payload", details: parsed.error.flatten() }, { status: 422 });
@@ -31,7 +36,7 @@ async function POST(req) {
31
36
  const container = await createRequestContainer();
32
37
  const credentialsService = container.resolve("integrationCredentialsService");
33
38
  const credentials = await credentialsService.resolve(integration.id, {
34
- organizationId: auth.orgId,
39
+ organizationId,
35
40
  tenantId: auth.tenantId
36
41
  });
37
42
  if (!credentials) {
@@ -40,7 +45,7 @@ async function POST(req) {
40
45
  const mapping = await adapter.getMapping({
41
46
  entityType: parsed.data.entityType,
42
47
  scope: {
43
- organizationId: auth.orgId,
48
+ organizationId,
44
49
  tenantId: auth.tenantId
45
50
  }
46
51
  });
@@ -52,7 +57,7 @@ async function POST(req) {
52
57
  credentials,
53
58
  mapping,
54
59
  scope: {
55
- organizationId: auth.orgId,
60
+ organizationId,
56
61
  tenantId: auth.tenantId
57
62
  }
58
63
  });
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/modules/data_sync/api/validate.ts"],
4
- "sourcesContent": ["import { NextResponse } from 'next/server'\nimport { getAuthFromRequest } from '@open-mercato/shared/lib/auth/server'\nimport { createRequestContainer } from '@open-mercato/shared/lib/di/container'\nimport { getIntegration } from '@open-mercato/shared/modules/integrations/types'\nimport type { CredentialsService } from '../../integrations/lib/credentials-service'\nimport { validateConnectionSchema } from '../data/validators'\nimport { getDataSyncAdapter } from '../lib/adapter-registry'\n\nexport const metadata = {\n POST: { requireAuth: true, requireFeatures: ['data_sync.configure'] },\n}\n\nexport const openApi = {\n tags: ['DataSync'],\n summary: 'Validate sync connection',\n}\n\nexport async function POST(req: Request) {\n const auth = await getAuthFromRequest(req)\n if (!auth?.tenantId || !auth.orgId) {\n return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })\n }\n\n const parsed = validateConnectionSchema.safeParse(await req.json())\n if (!parsed.success) {\n return NextResponse.json({ error: 'Invalid payload', details: parsed.error.flatten() }, { status: 422 })\n }\n\n const integration = getIntegration(parsed.data.integrationId)\n if (!integration?.providerKey) {\n return NextResponse.json({ ok: false, message: 'Integration or providerKey not found' }, { status: 404 })\n }\n\n const adapter = getDataSyncAdapter(integration.providerKey)\n if (!adapter) {\n return NextResponse.json({ ok: false, message: 'No registered sync adapter for provider' }, { status: 404 })\n }\n\n const container = await createRequestContainer()\n const credentialsService = container.resolve('integrationCredentialsService') as CredentialsService\n const credentials = await credentialsService.resolve(integration.id, {\n organizationId: auth.orgId as string,\n tenantId: auth.tenantId,\n })\n\n if (!credentials) {\n return NextResponse.json({ ok: false, message: 'Missing credentials' }, { status: 422 })\n }\n\n const mapping = await adapter.getMapping({\n entityType: parsed.data.entityType,\n scope: {\n organizationId: auth.orgId as string,\n tenantId: auth.tenantId,\n },\n })\n\n if (!adapter.validateConnection) {\n return NextResponse.json({ ok: true, message: 'Adapter does not implement active connection validation' })\n }\n\n const result = await adapter.validateConnection({\n entityType: parsed.data.entityType,\n credentials,\n mapping,\n scope: {\n organizationId: auth.orgId as string,\n tenantId: auth.tenantId,\n },\n })\n\n return NextResponse.json(result, { status: result.ok ? 200 : 422 })\n}\n"],
5
- "mappings": "AAAA,SAAS,oBAAoB;AAC7B,SAAS,0BAA0B;AACnC,SAAS,8BAA8B;AACvC,SAAS,sBAAsB;AAE/B,SAAS,gCAAgC;AACzC,SAAS,0BAA0B;AAE5B,MAAM,WAAW;AAAA,EACtB,MAAM,EAAE,aAAa,MAAM,iBAAiB,CAAC,qBAAqB,EAAE;AACtE;AAEO,MAAM,UAAU;AAAA,EACrB,MAAM,CAAC,UAAU;AAAA,EACjB,SAAS;AACX;AAEA,eAAsB,KAAK,KAAc;AACvC,QAAM,OAAO,MAAM,mBAAmB,GAAG;AACzC,MAAI,CAAC,MAAM,YAAY,CAAC,KAAK,OAAO;AAClC,WAAO,aAAa,KAAK,EAAE,OAAO,eAAe,GAAG,EAAE,QAAQ,IAAI,CAAC;AAAA,EACrE;AAEA,QAAM,SAAS,yBAAyB,UAAU,MAAM,IAAI,KAAK,CAAC;AAClE,MAAI,CAAC,OAAO,SAAS;AACnB,WAAO,aAAa,KAAK,EAAE,OAAO,mBAAmB,SAAS,OAAO,MAAM,QAAQ,EAAE,GAAG,EAAE,QAAQ,IAAI,CAAC;AAAA,EACzG;AAEA,QAAM,cAAc,eAAe,OAAO,KAAK,aAAa;AAC5D,MAAI,CAAC,aAAa,aAAa;AAC7B,WAAO,aAAa,KAAK,EAAE,IAAI,OAAO,SAAS,uCAAuC,GAAG,EAAE,QAAQ,IAAI,CAAC;AAAA,EAC1G;AAEA,QAAM,UAAU,mBAAmB,YAAY,WAAW;AAC1D,MAAI,CAAC,SAAS;AACZ,WAAO,aAAa,KAAK,EAAE,IAAI,OAAO,SAAS,0CAA0C,GAAG,EAAE,QAAQ,IAAI,CAAC;AAAA,EAC7G;AAEA,QAAM,YAAY,MAAM,uBAAuB;AAC/C,QAAM,qBAAqB,UAAU,QAAQ,+BAA+B;AAC5E,QAAM,cAAc,MAAM,mBAAmB,QAAQ,YAAY,IAAI;AAAA,IACnE,gBAAgB,KAAK;AAAA,IACrB,UAAU,KAAK;AAAA,EACjB,CAAC;AAED,MAAI,CAAC,aAAa;AAChB,WAAO,aAAa,KAAK,EAAE,IAAI,OAAO,SAAS,sBAAsB,GAAG,EAAE,QAAQ,IAAI,CAAC;AAAA,EACzF;AAEA,QAAM,UAAU,MAAM,QAAQ,WAAW;AAAA,IACvC,YAAY,OAAO,KAAK;AAAA,IACxB,OAAO;AAAA,MACL,gBAAgB,KAAK;AAAA,MACrB,UAAU,KAAK;AAAA,IACjB;AAAA,EACF,CAAC;AAED,MAAI,CAAC,QAAQ,oBAAoB;AAC/B,WAAO,aAAa,KAAK,EAAE,IAAI,MAAM,SAAS,0DAA0D,CAAC;AAAA,EAC3G;AAEA,QAAM,SAAS,MAAM,QAAQ,mBAAmB;AAAA,IAC9C,YAAY,OAAO,KAAK;AAAA,IACxB;AAAA,IACA;AAAA,IACA,OAAO;AAAA,MACL,gBAAgB,KAAK;AAAA,MACrB,UAAU,KAAK;AAAA,IACjB;AAAA,EACF,CAAC;AAED,SAAO,aAAa,KAAK,QAAQ,EAAE,QAAQ,OAAO,KAAK,MAAM,IAAI,CAAC;AACpE;",
4
+ "sourcesContent": ["import { NextResponse } from 'next/server'\nimport { getAuthFromRequest } from '@open-mercato/shared/lib/auth/server'\nimport { organizationScopeRequiredResponse, resolveActiveOrganizationId } from '@open-mercato/shared/lib/auth/organizationScope'\nimport { createRequestContainer } from '@open-mercato/shared/lib/di/container'\nimport { getIntegration } from '@open-mercato/shared/modules/integrations/types'\nimport type { CredentialsService } from '../../integrations/lib/credentials-service'\nimport { validateConnectionSchema } from '../data/validators'\nimport { getDataSyncAdapter } from '../lib/adapter-registry'\n\nexport const metadata = {\n POST: { requireAuth: true, requireFeatures: ['data_sync.configure'] },\n}\n\nexport const openApi = {\n tags: ['DataSync'],\n summary: 'Validate sync connection',\n}\n\nexport async function POST(req: Request) {\n const auth = await getAuthFromRequest(req)\n if (!auth?.tenantId) {\n return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })\n }\n const organizationId = resolveActiveOrganizationId(auth)\n if (!organizationId) {\n return organizationScopeRequiredResponse()\n }\n\n const parsed = validateConnectionSchema.safeParse(await req.json())\n if (!parsed.success) {\n return NextResponse.json({ error: 'Invalid payload', details: parsed.error.flatten() }, { status: 422 })\n }\n\n const integration = getIntegration(parsed.data.integrationId)\n if (!integration?.providerKey) {\n return NextResponse.json({ ok: false, message: 'Integration or providerKey not found' }, { status: 404 })\n }\n\n const adapter = getDataSyncAdapter(integration.providerKey)\n if (!adapter) {\n return NextResponse.json({ ok: false, message: 'No registered sync adapter for provider' }, { status: 404 })\n }\n\n const container = await createRequestContainer()\n const credentialsService = container.resolve('integrationCredentialsService') as CredentialsService\n const credentials = await credentialsService.resolve(integration.id, {\n organizationId,\n tenantId: auth.tenantId,\n })\n\n if (!credentials) {\n return NextResponse.json({ ok: false, message: 'Missing credentials' }, { status: 422 })\n }\n\n const mapping = await adapter.getMapping({\n entityType: parsed.data.entityType,\n scope: {\n organizationId,\n tenantId: auth.tenantId,\n },\n })\n\n if (!adapter.validateConnection) {\n return NextResponse.json({ ok: true, message: 'Adapter does not implement active connection validation' })\n }\n\n const result = await adapter.validateConnection({\n entityType: parsed.data.entityType,\n credentials,\n mapping,\n scope: {\n organizationId,\n tenantId: auth.tenantId,\n },\n })\n\n return NextResponse.json(result, { status: result.ok ? 200 : 422 })\n}\n"],
5
+ "mappings": "AAAA,SAAS,oBAAoB;AAC7B,SAAS,0BAA0B;AACnC,SAAS,mCAAmC,mCAAmC;AAC/E,SAAS,8BAA8B;AACvC,SAAS,sBAAsB;AAE/B,SAAS,gCAAgC;AACzC,SAAS,0BAA0B;AAE5B,MAAM,WAAW;AAAA,EACtB,MAAM,EAAE,aAAa,MAAM,iBAAiB,CAAC,qBAAqB,EAAE;AACtE;AAEO,MAAM,UAAU;AAAA,EACrB,MAAM,CAAC,UAAU;AAAA,EACjB,SAAS;AACX;AAEA,eAAsB,KAAK,KAAc;AACvC,QAAM,OAAO,MAAM,mBAAmB,GAAG;AACzC,MAAI,CAAC,MAAM,UAAU;AACnB,WAAO,aAAa,KAAK,EAAE,OAAO,eAAe,GAAG,EAAE,QAAQ,IAAI,CAAC;AAAA,EACrE;AACA,QAAM,iBAAiB,4BAA4B,IAAI;AACvD,MAAI,CAAC,gBAAgB;AACnB,WAAO,kCAAkC;AAAA,EAC3C;AAEA,QAAM,SAAS,yBAAyB,UAAU,MAAM,IAAI,KAAK,CAAC;AAClE,MAAI,CAAC,OAAO,SAAS;AACnB,WAAO,aAAa,KAAK,EAAE,OAAO,mBAAmB,SAAS,OAAO,MAAM,QAAQ,EAAE,GAAG,EAAE,QAAQ,IAAI,CAAC;AAAA,EACzG;AAEA,QAAM,cAAc,eAAe,OAAO,KAAK,aAAa;AAC5D,MAAI,CAAC,aAAa,aAAa;AAC7B,WAAO,aAAa,KAAK,EAAE,IAAI,OAAO,SAAS,uCAAuC,GAAG,EAAE,QAAQ,IAAI,CAAC;AAAA,EAC1G;AAEA,QAAM,UAAU,mBAAmB,YAAY,WAAW;AAC1D,MAAI,CAAC,SAAS;AACZ,WAAO,aAAa,KAAK,EAAE,IAAI,OAAO,SAAS,0CAA0C,GAAG,EAAE,QAAQ,IAAI,CAAC;AAAA,EAC7G;AAEA,QAAM,YAAY,MAAM,uBAAuB;AAC/C,QAAM,qBAAqB,UAAU,QAAQ,+BAA+B;AAC5E,QAAM,cAAc,MAAM,mBAAmB,QAAQ,YAAY,IAAI;AAAA,IACnE;AAAA,IACA,UAAU,KAAK;AAAA,EACjB,CAAC;AAED,MAAI,CAAC,aAAa;AAChB,WAAO,aAAa,KAAK,EAAE,IAAI,OAAO,SAAS,sBAAsB,GAAG,EAAE,QAAQ,IAAI,CAAC;AAAA,EACzF;AAEA,QAAM,UAAU,MAAM,QAAQ,WAAW;AAAA,IACvC,YAAY,OAAO,KAAK;AAAA,IACxB,OAAO;AAAA,MACL;AAAA,MACA,UAAU,KAAK;AAAA,IACjB;AAAA,EACF,CAAC;AAED,MAAI,CAAC,QAAQ,oBAAoB;AAC/B,WAAO,aAAa,KAAK,EAAE,IAAI,MAAM,SAAS,0DAA0D,CAAC;AAAA,EAC3G;AAEA,QAAM,SAAS,MAAM,QAAQ,mBAAmB;AAAA,IAC9C,YAAY,OAAO,KAAK;AAAA,IACxB;AAAA,IACA;AAAA,IACA,OAAO;AAAA,MACL;AAAA,MACA,UAAU,KAAK;AAAA,IACjB;AAAA,EACF,CAAC;AAED,SAAO,aAAa,KAAK,QAAQ,EAAE,QAAQ,OAAO,KAAK,MAAM,IAAI,CAAC;AACpE;",
6
6
  "names": []
7
7
  }
@@ -0,0 +1,9 @@
1
+ const features = [
2
+ { id: "design_system.view", title: "View the design system gallery", module: "design_system" }
3
+ ];
4
+ var acl_default = features;
5
+ export {
6
+ acl_default as default,
7
+ features
8
+ };
9
+ //# sourceMappingURL=acl.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/modules/design_system/acl.ts"],
4
+ "sourcesContent": ["export const features = [\n { id: 'design_system.view', title: 'View the design system gallery', module: 'design_system' },\n]\n\nexport default features\n"],
5
+ "mappings": "AAAO,MAAM,WAAW;AAAA,EACtB,EAAE,IAAI,sBAAsB,OAAO,kCAAkC,QAAQ,gBAAgB;AAC/F;AAEA,IAAO,cAAQ;",
6
+ "names": []
7
+ }
@@ -0,0 +1,11 @@
1
+ "use client";
2
+ import { jsx } from "react/jsx-runtime";
3
+ import { Page, PageBody } from "@open-mercato/ui/backend/Page";
4
+ import { GalleryShell } from "../../gallery/components/GalleryShell.js";
5
+ function DesignSystemGalleryPage() {
6
+ return /* @__PURE__ */ jsx(Page, { children: /* @__PURE__ */ jsx(PageBody, { children: /* @__PURE__ */ jsx(GalleryShell, {}) }) });
7
+ }
8
+ export {
9
+ DesignSystemGalleryPage as default
10
+ };
11
+ //# sourceMappingURL=page.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../src/modules/design_system/backend/design-system/page.tsx"],
4
+ "sourcesContent": ["\"use client\"\n\nimport { Page, PageBody } from '@open-mercato/ui/backend/Page'\nimport { GalleryShell } from '../../gallery/components/GalleryShell'\n\nexport default function DesignSystemGalleryPage() {\n return (\n <Page>\n <PageBody>\n <GalleryShell />\n </PageBody>\n </Page>\n )\n}\n"],
5
+ "mappings": ";AASQ;AAPR,SAAS,MAAM,gBAAgB;AAC/B,SAAS,oBAAoB;AAEd,SAAR,0BAA2C;AAChD,SACE,oBAAC,QACC,8BAAC,YACC,8BAAC,gBAAa,GAChB,GACF;AAEJ;",
6
+ "names": []
7
+ }
@@ -0,0 +1,15 @@
1
+ const metadata = {
2
+ requireAuth: true,
3
+ requireFeatures: ["design_system.view"],
4
+ pageTitle: "Design system",
5
+ pageTitleKey: "design_system.nav.title",
6
+ pageGroup: "Developer",
7
+ pageGroupKey: "design_system.nav.group",
8
+ pageOrder: 900,
9
+ icon: "shapes",
10
+ breadcrumb: [{ label: "Design system", labelKey: "design_system.nav.title" }]
11
+ };
12
+ export {
13
+ metadata
14
+ };
15
+ //# sourceMappingURL=page.meta.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../src/modules/design_system/backend/design-system/page.meta.ts"],
4
+ "sourcesContent": ["export const metadata = {\n requireAuth: true,\n requireFeatures: ['design_system.view'],\n pageTitle: 'Design system',\n pageTitleKey: 'design_system.nav.title',\n pageGroup: 'Developer',\n pageGroupKey: 'design_system.nav.group',\n pageOrder: 900,\n icon: 'shapes',\n breadcrumb: [{ label: 'Design system', labelKey: 'design_system.nav.title' }],\n}\n"],
5
+ "mappings": "AAAO,MAAM,WAAW;AAAA,EACtB,aAAa;AAAA,EACb,iBAAiB,CAAC,oBAAoB;AAAA,EACtC,WAAW;AAAA,EACX,cAAc;AAAA,EACd,WAAW;AAAA,EACX,cAAc;AAAA,EACd,WAAW;AAAA,EACX,MAAM;AAAA,EACN,YAAY,CAAC,EAAE,OAAO,iBAAiB,UAAU,0BAA0B,CAAC;AAC9E;",
6
+ "names": []
7
+ }
@@ -0,0 +1,52 @@
1
+ "use client";
2
+ import { jsx, jsxs } from "react/jsx-runtime";
3
+ import * as React from "react";
4
+ import { Copy } from "lucide-react";
5
+ import { useT } from "@open-mercato/shared/lib/i18n/context";
6
+ import { IconButton } from "@open-mercato/ui/primitives/icon-button";
7
+ import { flash } from "@open-mercato/ui/backend/FlashMessages";
8
+ function CodeSnippet({ code }) {
9
+ const t = useT();
10
+ const copyLabel = t("design_system.gallery.copy", "Copy code");
11
+ const onCopy = React.useCallback(async () => {
12
+ try {
13
+ if (navigator.clipboard) {
14
+ await navigator.clipboard.writeText(code);
15
+ } else {
16
+ const holder = document.createElement("textarea");
17
+ holder.value = code;
18
+ holder.setAttribute("readonly", "");
19
+ holder.style.position = "fixed";
20
+ holder.style.opacity = "0";
21
+ document.body.appendChild(holder);
22
+ holder.select();
23
+ const copied = document.execCommand("copy");
24
+ holder.remove();
25
+ if (!copied) throw new Error("[internal] execCommand copy failed");
26
+ }
27
+ flash(t("design_system.gallery.copied", "Snippet copied to clipboard"), "success");
28
+ } catch {
29
+ flash(t("design_system.gallery.copyFailed", "Could not copy the snippet"), "error");
30
+ }
31
+ }, [code, t]);
32
+ return /* @__PURE__ */ jsxs("div", { className: "relative rounded-md border border-border bg-muted/50", children: [
33
+ /* @__PURE__ */ jsx("pre", { className: "overflow-x-auto p-3 pr-12 text-xs leading-relaxed", children: /* @__PURE__ */ jsx("code", { children: code }) }),
34
+ /* @__PURE__ */ jsx(
35
+ IconButton,
36
+ {
37
+ type: "button",
38
+ variant: "ghost",
39
+ size: "sm",
40
+ className: "absolute right-1.5 top-1.5",
41
+ "aria-label": copyLabel,
42
+ title: copyLabel,
43
+ onClick: onCopy,
44
+ children: /* @__PURE__ */ jsx(Copy, {})
45
+ }
46
+ )
47
+ ] });
48
+ }
49
+ export {
50
+ CodeSnippet
51
+ };
52
+ //# sourceMappingURL=CodeSnippet.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../src/modules/design_system/gallery/components/CodeSnippet.tsx"],
4
+ "sourcesContent": ["'use client'\n\nimport * as React from 'react'\nimport { Copy } from 'lucide-react'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { IconButton } from '@open-mercato/ui/primitives/icon-button'\nimport { flash } from '@open-mercato/ui/backend/FlashMessages'\n\nexport function CodeSnippet({ code }: { code: string }) {\n const t = useT()\n const copyLabel = t('design_system.gallery.copy', 'Copy code')\n\n const onCopy = React.useCallback(async () => {\n try {\n if (navigator.clipboard) {\n await navigator.clipboard.writeText(code)\n } else {\n // Non-secure contexts (plain-HTTP self-hosted installs) have no\n // navigator.clipboard \u2014 fall back to the legacy selection API.\n const holder = document.createElement('textarea')\n holder.value = code\n holder.setAttribute('readonly', '')\n holder.style.position = 'fixed'\n holder.style.opacity = '0'\n document.body.appendChild(holder)\n holder.select()\n const copied = document.execCommand('copy')\n holder.remove()\n if (!copied) throw new Error('[internal] execCommand copy failed')\n }\n flash(t('design_system.gallery.copied', 'Snippet copied to clipboard'), 'success')\n } catch {\n flash(t('design_system.gallery.copyFailed', 'Could not copy the snippet'), 'error')\n }\n }, [code, t])\n\n return (\n <div className=\"relative rounded-md border border-border bg-muted/50\">\n <pre className=\"overflow-x-auto p-3 pr-12 text-xs leading-relaxed\">\n <code>{code}</code>\n </pre>\n <IconButton\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n className=\"absolute right-1.5 top-1.5\"\n aria-label={copyLabel}\n title={copyLabel}\n onClick={onCopy}\n >\n <Copy />\n </IconButton>\n </div>\n )\n}\n"],
5
+ "mappings": ";AAqCI,SAEI,KAFJ;AAnCJ,YAAY,WAAW;AACvB,SAAS,YAAY;AACrB,SAAS,YAAY;AACrB,SAAS,kBAAkB;AAC3B,SAAS,aAAa;AAEf,SAAS,YAAY,EAAE,KAAK,GAAqB;AACtD,QAAM,IAAI,KAAK;AACf,QAAM,YAAY,EAAE,8BAA8B,WAAW;AAE7D,QAAM,SAAS,MAAM,YAAY,YAAY;AAC3C,QAAI;AACF,UAAI,UAAU,WAAW;AACvB,cAAM,UAAU,UAAU,UAAU,IAAI;AAAA,MAC1C,OAAO;AAGL,cAAM,SAAS,SAAS,cAAc,UAAU;AAChD,eAAO,QAAQ;AACf,eAAO,aAAa,YAAY,EAAE;AAClC,eAAO,MAAM,WAAW;AACxB,eAAO,MAAM,UAAU;AACvB,iBAAS,KAAK,YAAY,MAAM;AAChC,eAAO,OAAO;AACd,cAAM,SAAS,SAAS,YAAY,MAAM;AAC1C,eAAO,OAAO;AACd,YAAI,CAAC,OAAQ,OAAM,IAAI,MAAM,oCAAoC;AAAA,MACnE;AACA,YAAM,EAAE,gCAAgC,6BAA6B,GAAG,SAAS;AAAA,IACnF,QAAQ;AACN,YAAM,EAAE,oCAAoC,4BAA4B,GAAG,OAAO;AAAA,IACpF;AAAA,EACF,GAAG,CAAC,MAAM,CAAC,CAAC;AAEZ,SACE,qBAAC,SAAI,WAAU,wDACb;AAAA,wBAAC,SAAI,WAAU,qDACb,8BAAC,UAAM,gBAAK,GACd;AAAA,IACA;AAAA,MAAC;AAAA;AAAA,QACC,MAAK;AAAA,QACL,SAAQ;AAAA,QACR,MAAK;AAAA,QACL,WAAU;AAAA,QACV,cAAY;AAAA,QACZ,OAAO;AAAA,QACP,SAAS;AAAA,QAET,8BAAC,QAAK;AAAA;AAAA,IACR;AAAA,KACF;AAEJ;",
6
+ "names": []
7
+ }
@@ -0,0 +1,63 @@
1
+ "use client";
2
+ import { jsx, jsxs } from "react/jsx-runtime";
3
+ import { Check, ExternalLink, X } from "lucide-react";
4
+ import { useT } from "@open-mercato/shared/lib/i18n/context";
5
+ import { LinkButton } from "@open-mercato/ui/primitives/link-button";
6
+ import { DS_DOCS_URL, figmaNodeUrl } from "../registry.js";
7
+ import { VariantPreview } from "./VariantPreview.js";
8
+ import { CodeSnippet } from "./CodeSnippet.js";
9
+ function EntryCard({ entry }) {
10
+ const t = useT();
11
+ return /* @__PURE__ */ jsxs(
12
+ "section",
13
+ {
14
+ id: `gallery-entry-${entry.id}`,
15
+ "aria-labelledby": `gallery-entry-${entry.id}-title`,
16
+ className: "scroll-mt-4 space-y-4 rounded-lg border border-border bg-card p-4",
17
+ children: [
18
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2 sm:flex-row sm:items-start sm:justify-between", children: [
19
+ /* @__PURE__ */ jsxs("div", { className: "min-w-0 space-y-1", children: [
20
+ /* @__PURE__ */ jsx("h3", { id: `gallery-entry-${entry.id}-title`, className: "text-base font-semibold leading-tight", children: entry.title }),
21
+ entry.descriptionKey ? /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: t(entry.descriptionKey, entry.title) }) : null,
22
+ /* @__PURE__ */ jsx("code", { className: "block truncate text-xs text-muted-foreground", children: entry.importPath })
23
+ ] }),
24
+ /* @__PURE__ */ jsxs("div", { className: "flex shrink-0 items-center gap-3", children: [
25
+ entry.figmaNodeId ? /* @__PURE__ */ jsx(LinkButton, { asChild: true, size: "sm", children: /* @__PURE__ */ jsxs("a", { href: figmaNodeUrl(entry.figmaNodeId), target: "_blank", rel: "noreferrer", children: [
26
+ t("design_system.gallery.openInFigma", "Open in Figma"),
27
+ /* @__PURE__ */ jsx(ExternalLink, {})
28
+ ] }) }) : null,
29
+ entry.docsAnchor ? /* @__PURE__ */ jsx(LinkButton, { asChild: true, size: "sm", variant: "gray", children: /* @__PURE__ */ jsxs("a", { href: `${DS_DOCS_URL}${entry.docsAnchor}`, target: "_blank", rel: "noreferrer", children: [
30
+ t("design_system.gallery.viewDocs", "View docs"),
31
+ /* @__PURE__ */ jsx(ExternalLink, {})
32
+ ] }) }) : null
33
+ ] })
34
+ ] }),
35
+ entry.usage && (entry.usage.do?.length || entry.usage.dont?.length) ? /* @__PURE__ */ jsxs("div", { className: "grid gap-4 rounded-md border border-border bg-muted/30 p-4 sm:grid-cols-2", children: [
36
+ entry.usage.do?.length ? /* @__PURE__ */ jsxs("div", { className: "space-y-1.5", children: [
37
+ /* @__PURE__ */ jsx("div", { className: "text-xs font-medium uppercase tracking-wider text-muted-foreground", children: t("design_system.gallery.usageDo", "Do") }),
38
+ /* @__PURE__ */ jsx("ul", { className: "space-y-1.5", children: entry.usage.do.map((rule) => /* @__PURE__ */ jsxs("li", { className: "flex items-start gap-2 text-sm text-foreground", children: [
39
+ /* @__PURE__ */ jsx(Check, { "aria-hidden": true, className: "mt-0.5 size-3.5 shrink-0 text-status-success-icon" }),
40
+ /* @__PURE__ */ jsx("span", { children: rule })
41
+ ] }, rule)) })
42
+ ] }) : null,
43
+ entry.usage.dont?.length ? /* @__PURE__ */ jsxs("div", { className: "space-y-1.5", children: [
44
+ /* @__PURE__ */ jsx("div", { className: "text-xs font-medium uppercase tracking-wider text-muted-foreground", children: t("design_system.gallery.usageDont", "Don't") }),
45
+ /* @__PURE__ */ jsx("ul", { className: "space-y-1.5", children: entry.usage.dont.map((rule) => /* @__PURE__ */ jsxs("li", { className: "flex items-start gap-2 text-sm text-foreground", children: [
46
+ /* @__PURE__ */ jsx(X, { "aria-hidden": true, className: "mt-0.5 size-3.5 shrink-0 text-status-error-icon" }),
47
+ /* @__PURE__ */ jsx("span", { children: rule })
48
+ ] }, rule)) })
49
+ ] }) : null
50
+ ] }) : null,
51
+ /* @__PURE__ */ jsx("div", { className: "space-y-4", children: entry.variants.map((variant) => /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
52
+ /* @__PURE__ */ jsx("div", { className: "text-sm font-medium text-foreground", children: variant.title }),
53
+ /* @__PURE__ */ jsx(VariantPreview, { children: variant.render() }),
54
+ /* @__PURE__ */ jsx(CodeSnippet, { code: variant.code })
55
+ ] }, variant.id)) })
56
+ ]
57
+ }
58
+ );
59
+ }
60
+ export {
61
+ EntryCard
62
+ };
63
+ //# sourceMappingURL=EntryCard.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../src/modules/design_system/gallery/components/EntryCard.tsx"],
4
+ "sourcesContent": ["'use client'\n\nimport * as React from 'react'\nimport { Check, ExternalLink, X } from 'lucide-react'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { LinkButton } from '@open-mercato/ui/primitives/link-button'\nimport type { GalleryEntry } from '../types'\nimport { DS_DOCS_URL, figmaNodeUrl } from '../registry'\nimport { VariantPreview } from './VariantPreview'\nimport { CodeSnippet } from './CodeSnippet'\n\nexport function EntryCard({ entry }: { entry: GalleryEntry }) {\n const t = useT()\n\n return (\n <section\n id={`gallery-entry-${entry.id}`}\n aria-labelledby={`gallery-entry-${entry.id}-title`}\n className=\"scroll-mt-4 space-y-4 rounded-lg border border-border bg-card p-4\"\n >\n <div className=\"flex flex-col gap-2 sm:flex-row sm:items-start sm:justify-between\">\n <div className=\"min-w-0 space-y-1\">\n <h3 id={`gallery-entry-${entry.id}-title`} className=\"text-base font-semibold leading-tight\">\n {entry.title}\n </h3>\n {entry.descriptionKey ? (\n <p className=\"text-sm text-muted-foreground\">{t(entry.descriptionKey, entry.title)}</p>\n ) : null}\n <code className=\"block truncate text-xs text-muted-foreground\">{entry.importPath}</code>\n </div>\n <div className=\"flex shrink-0 items-center gap-3\">\n {entry.figmaNodeId ? (\n <LinkButton asChild size=\"sm\">\n <a href={figmaNodeUrl(entry.figmaNodeId)} target=\"_blank\" rel=\"noreferrer\">\n {t('design_system.gallery.openInFigma', 'Open in Figma')}\n <ExternalLink />\n </a>\n </LinkButton>\n ) : null}\n {entry.docsAnchor ? (\n <LinkButton asChild size=\"sm\" variant=\"gray\">\n <a href={`${DS_DOCS_URL}${entry.docsAnchor}`} target=\"_blank\" rel=\"noreferrer\">\n {t('design_system.gallery.viewDocs', 'View docs')}\n <ExternalLink />\n </a>\n </LinkButton>\n ) : null}\n </div>\n </div>\n {entry.usage && (entry.usage.do?.length || entry.usage.dont?.length) ? (\n <div className=\"grid gap-4 rounded-md border border-border bg-muted/30 p-4 sm:grid-cols-2\">\n {entry.usage.do?.length ? (\n <div className=\"space-y-1.5\">\n <div className=\"text-xs font-medium uppercase tracking-wider text-muted-foreground\">\n {t('design_system.gallery.usageDo', 'Do')}\n </div>\n <ul className=\"space-y-1.5\">\n {entry.usage.do.map((rule) => (\n <li key={rule} className=\"flex items-start gap-2 text-sm text-foreground\">\n <Check aria-hidden className=\"mt-0.5 size-3.5 shrink-0 text-status-success-icon\" />\n <span>{rule}</span>\n </li>\n ))}\n </ul>\n </div>\n ) : null}\n {entry.usage.dont?.length ? (\n <div className=\"space-y-1.5\">\n <div className=\"text-xs font-medium uppercase tracking-wider text-muted-foreground\">\n {t('design_system.gallery.usageDont', \"Don't\")}\n </div>\n <ul className=\"space-y-1.5\">\n {entry.usage.dont.map((rule) => (\n <li key={rule} className=\"flex items-start gap-2 text-sm text-foreground\">\n <X aria-hidden className=\"mt-0.5 size-3.5 shrink-0 text-status-error-icon\" />\n <span>{rule}</span>\n </li>\n ))}\n </ul>\n </div>\n ) : null}\n </div>\n ) : null}\n <div className=\"space-y-4\">\n {entry.variants.map((variant) => (\n <div key={variant.id} className=\"space-y-2\">\n <div className=\"text-sm font-medium text-foreground\">{variant.title}</div>\n <VariantPreview>{variant.render()}</VariantPreview>\n <CodeSnippet code={variant.code} />\n </div>\n ))}\n </div>\n </section>\n )\n}\n"],
5
+ "mappings": ";AAqBQ,SACE,KADF;AAlBR,SAAS,OAAO,cAAc,SAAS;AACvC,SAAS,YAAY;AACrB,SAAS,kBAAkB;AAE3B,SAAS,aAAa,oBAAoB;AAC1C,SAAS,sBAAsB;AAC/B,SAAS,mBAAmB;AAErB,SAAS,UAAU,EAAE,MAAM,GAA4B;AAC5D,QAAM,IAAI,KAAK;AAEf,SACE;AAAA,IAAC;AAAA;AAAA,MACC,IAAI,iBAAiB,MAAM,EAAE;AAAA,MAC7B,mBAAiB,iBAAiB,MAAM,EAAE;AAAA,MAC1C,WAAU;AAAA,MAEV;AAAA,6BAAC,SAAI,WAAU,qEACb;AAAA,+BAAC,SAAI,WAAU,qBACb;AAAA,gCAAC,QAAG,IAAI,iBAAiB,MAAM,EAAE,UAAU,WAAU,yCAClD,gBAAM,OACT;AAAA,YACC,MAAM,iBACL,oBAAC,OAAE,WAAU,iCAAiC,YAAE,MAAM,gBAAgB,MAAM,KAAK,GAAE,IACjF;AAAA,YACJ,oBAAC,UAAK,WAAU,gDAAgD,gBAAM,YAAW;AAAA,aACnF;AAAA,UACA,qBAAC,SAAI,WAAU,oCACZ;AAAA,kBAAM,cACL,oBAAC,cAAW,SAAO,MAAC,MAAK,MACvB,+BAAC,OAAE,MAAM,aAAa,MAAM,WAAW,GAAG,QAAO,UAAS,KAAI,cAC3D;AAAA,gBAAE,qCAAqC,eAAe;AAAA,cACvD,oBAAC,gBAAa;AAAA,eAChB,GACF,IACE;AAAA,YACH,MAAM,aACL,oBAAC,cAAW,SAAO,MAAC,MAAK,MAAK,SAAQ,QACpC,+BAAC,OAAE,MAAM,GAAG,WAAW,GAAG,MAAM,UAAU,IAAI,QAAO,UAAS,KAAI,cAC/D;AAAA,gBAAE,kCAAkC,WAAW;AAAA,cAChD,oBAAC,gBAAa;AAAA,eAChB,GACF,IACE;AAAA,aACN;AAAA,WACF;AAAA,QACC,MAAM,UAAU,MAAM,MAAM,IAAI,UAAU,MAAM,MAAM,MAAM,UAC3D,qBAAC,SAAI,WAAU,6EACZ;AAAA,gBAAM,MAAM,IAAI,SACf,qBAAC,SAAI,WAAU,eACb;AAAA,gCAAC,SAAI,WAAU,sEACZ,YAAE,iCAAiC,IAAI,GAC1C;AAAA,YACA,oBAAC,QAAG,WAAU,eACX,gBAAM,MAAM,GAAG,IAAI,CAAC,SACnB,qBAAC,QAAc,WAAU,kDACvB;AAAA,kCAAC,SAAM,eAAW,MAAC,WAAU,qDAAoD;AAAA,cACjF,oBAAC,UAAM,gBAAK;AAAA,iBAFL,IAGT,CACD,GACH;AAAA,aACF,IACE;AAAA,UACH,MAAM,MAAM,MAAM,SACjB,qBAAC,SAAI,WAAU,eACb;AAAA,gCAAC,SAAI,WAAU,sEACZ,YAAE,mCAAmC,OAAO,GAC/C;AAAA,YACA,oBAAC,QAAG,WAAU,eACX,gBAAM,MAAM,KAAK,IAAI,CAAC,SACrB,qBAAC,QAAc,WAAU,kDACvB;AAAA,kCAAC,KAAE,eAAW,MAAC,WAAU,mDAAkD;AAAA,cAC3E,oBAAC,UAAM,gBAAK;AAAA,iBAFL,IAGT,CACD,GACH;AAAA,aACF,IACE;AAAA,WACN,IACE;AAAA,QACJ,oBAAC,SAAI,WAAU,aACZ,gBAAM,SAAS,IAAI,CAAC,YACnB,qBAAC,SAAqB,WAAU,aAC9B;AAAA,8BAAC,SAAI,WAAU,uCAAuC,kBAAQ,OAAM;AAAA,UACpE,oBAAC,kBAAgB,kBAAQ,OAAO,GAAE;AAAA,UAClC,oBAAC,eAAY,MAAM,QAAQ,MAAM;AAAA,aAHzB,QAAQ,EAIlB,CACD,GACH;AAAA;AAAA;AAAA,EACF;AAEJ;",
6
+ "names": []
7
+ }