@open-mercato/core 0.6.6-develop.6542.1.fee3e68aa6 → 0.6.6-develop.6551.1.1511bfa890
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.
- package/.turbo/turbo-build.log +2 -2
- package/dist/generated/entities/gateway_session_initialization/index.js +23 -0
- package/dist/generated/entities/gateway_session_initialization/index.js.map +7 -0
- package/dist/generated/entities.ids.generated.js +1 -0
- package/dist/generated/entities.ids.generated.js.map +2 -2
- package/dist/generated/entity-fields-registry.js +12 -0
- package/dist/generated/entity-fields-registry.js.map +2 -2
- package/dist/modules/api_keys/api/keys/route.js +7 -4
- package/dist/modules/api_keys/api/keys/route.js.map +2 -2
- package/dist/modules/attachments/components/AttachmentContentPreview.js +6 -35
- package/dist/modules/attachments/components/AttachmentContentPreview.js.map +2 -2
- package/dist/modules/audit_logs/backend/audit-logs/page.js +14 -24
- package/dist/modules/audit_logs/backend/audit-logs/page.js.map +2 -2
- package/dist/modules/auth/api/autologin.js +85 -0
- package/dist/modules/auth/api/autologin.js.map +7 -0
- package/dist/modules/auth/lib/autologin.js +19 -0
- package/dist/modules/auth/lib/autologin.js.map +7 -0
- package/dist/modules/customer_accounts/api/admin/roles/[id]/acl.js +1 -0
- package/dist/modules/customer_accounts/api/admin/roles/[id]/acl.js.map +2 -2
- package/dist/modules/customer_accounts/api/admin/roles/[id].js +17 -3
- package/dist/modules/customer_accounts/api/admin/roles/[id].js.map +2 -2
- package/dist/modules/customer_accounts/api/portal/users/[id]/roles.js +6 -1
- package/dist/modules/customer_accounts/api/portal/users/[id]/roles.js.map +2 -2
- package/dist/modules/customer_accounts/api/portal/users-invite.js +6 -1
- package/dist/modules/customer_accounts/api/portal/users-invite.js.map +2 -2
- package/dist/modules/customer_accounts/services/customerInvitationService.js +1 -0
- package/dist/modules/customer_accounts/services/customerInvitationService.js.map +2 -2
- package/dist/modules/customer_accounts/services/customerRbacService.js +6 -1
- package/dist/modules/customer_accounts/services/customerRbacService.js.map +2 -2
- package/dist/modules/customers/backend/customers/deals/pipeline/components/ViewTabsRow.js +2 -2
- package/dist/modules/customers/backend/customers/deals/pipeline/components/ViewTabsRow.js.map +2 -2
- package/dist/modules/customers/components/detail/CompanyDetailTabs.js +27 -37
- package/dist/modules/customers/components/detail/CompanyDetailTabs.js.map +2 -2
- package/dist/modules/customers/components/detail/DealDetailTabs.js +23 -35
- package/dist/modules/customers/components/detail/DealDetailTabs.js.map +2 -2
- package/dist/modules/customers/components/detail/DetailTabsLayout.js +6 -21
- package/dist/modules/customers/components/detail/DetailTabsLayout.js.map +2 -2
- package/dist/modules/customers/components/detail/MobilePersonDetail.js +26 -32
- package/dist/modules/customers/components/detail/MobilePersonDetail.js.map +2 -2
- package/dist/modules/customers/components/detail/PersonDetailTabs.js +29 -39
- package/dist/modules/customers/components/detail/PersonDetailTabs.js.map +2 -2
- package/dist/modules/dictionaries/commands/entries.js +7 -14
- package/dist/modules/dictionaries/commands/entries.js.map +2 -2
- package/dist/modules/dictionaries/commands/entry-operations.js +7 -16
- package/dist/modules/dictionaries/commands/entry-operations.js.map +2 -2
- package/dist/modules/dictionaries/commands/factory.js +9 -3
- package/dist/modules/dictionaries/commands/factory.js.map +2 -2
- package/dist/modules/feature_toggles/api/check/boolean/route.js +0 -14
- package/dist/modules/feature_toggles/api/check/boolean/route.js.map +2 -2
- package/dist/modules/feature_toggles/defaults.json +8 -0
- package/dist/modules/integrations/backend/integrations/[id]/page.js +9 -80
- package/dist/modules/integrations/backend/integrations/[id]/page.js.map +2 -2
- package/dist/modules/payment_gateways/data/entities.js +45 -0
- package/dist/modules/payment_gateways/data/entities.js.map +2 -2
- package/dist/modules/payment_gateways/lib/gateway-service.js +173 -38
- package/dist/modules/payment_gateways/lib/gateway-service.js.map +3 -3
- package/dist/modules/payment_gateways/lib/session-idempotency.js +104 -0
- package/dist/modules/payment_gateways/lib/session-idempotency.js.map +7 -0
- package/dist/modules/payment_gateways/migrations/Migration20260709220938_payment_gateways.js +11 -0
- package/dist/modules/payment_gateways/migrations/Migration20260709220938_payment_gateways.js.map +7 -0
- package/dist/modules/planner/backend/planner/availability-rulesets/[id]/page.js +16 -14
- package/dist/modules/planner/backend/planner/availability-rulesets/[id]/page.js.map +2 -2
- package/dist/modules/planner/components/AvailabilityRulesEditor.js +18 -30
- package/dist/modules/planner/components/AvailabilityRulesEditor.js.map +2 -2
- package/dist/modules/resources/backend/resources/resources/[id]/page.js +24 -24
- package/dist/modules/resources/backend/resources/resources/[id]/page.js.map +2 -2
- package/dist/modules/sales/backend/sales/channels/create/page.js +6 -0
- package/dist/modules/sales/backend/sales/channels/create/page.js.map +2 -2
- package/dist/modules/sales/backend/sales/channels/create/page.meta.js +2 -0
- package/dist/modules/sales/backend/sales/channels/create/page.meta.js.map +2 -2
- package/dist/modules/sales/backend/sales/channels/offers/page.js +6 -0
- package/dist/modules/sales/backend/sales/channels/offers/page.js.map +2 -2
- package/dist/modules/sales/backend/sales/channels/offers/page.meta.js +2 -0
- package/dist/modules/sales/backend/sales/channels/offers/page.meta.js.map +2 -2
- package/dist/modules/sales/backend/sales/channels/page.js +6 -0
- package/dist/modules/sales/backend/sales/channels/page.js.map +2 -2
- package/dist/modules/sales/backend/sales/channels/page.meta.js +2 -0
- package/dist/modules/sales/backend/sales/channels/page.meta.js.map +2 -2
- package/dist/modules/sales/backend/sales/documents/[id]/page.js +6 -4
- package/dist/modules/sales/backend/sales/documents/[id]/page.js.map +2 -2
- package/dist/modules/sales/components/SalesChannelsDisabledNotice.js +15 -0
- package/dist/modules/sales/components/SalesChannelsDisabledNotice.js.map +7 -0
- package/dist/modules/sales/components/documents/SalesDocumentForm.js +7 -3
- package/dist/modules/sales/components/documents/SalesDocumentForm.js.map +2 -2
- package/dist/modules/sales/components/documents/SalesDocumentsTable.js +10 -8
- package/dist/modules/sales/components/documents/SalesDocumentsTable.js.map +2 -2
- package/dist/modules/sales/components/useSalesChannelsEnabled.js +44 -0
- package/dist/modules/sales/components/useSalesChannelsEnabled.js.map +7 -0
- package/dist/modules/sales/lib/salesChannelsToggle.js +18 -0
- package/dist/modules/sales/lib/salesChannelsToggle.js.map +7 -0
- package/dist/modules/sales/lib/salesChannelsToggleId.js +5 -0
- package/dist/modules/sales/lib/salesChannelsToggleId.js.map +7 -0
- package/dist/modules/staff/backend/staff/team-members/[id]/page.js +22 -25
- package/dist/modules/staff/backend/staff/team-members/[id]/page.js.map +2 -2
- package/dist/modules/staff/backend/staff/teams/[id]/edit/page.js +12 -14
- package/dist/modules/staff/backend/staff/teams/[id]/edit/page.js.map +2 -2
- package/dist/modules/staff/lib/timesheets-projects-ui/SavedViewTabs.js +10 -29
- package/dist/modules/staff/lib/timesheets-projects-ui/SavedViewTabs.js.map +2 -2
- package/dist/modules/sync_excel/lib/adapters/customers.js +19 -20
- package/dist/modules/sync_excel/lib/adapters/customers.js.map +2 -2
- package/dist/modules/sync_excel/lib/parser.js +185 -0
- package/dist/modules/sync_excel/lib/parser.js.map +2 -2
- package/dist/modules/sync_excel/lib/upload-storage.js +20 -1
- package/dist/modules/sync_excel/lib/upload-storage.js.map +2 -2
- package/generated/entities/gateway_session_initialization/index.ts +10 -0
- package/generated/entities.ids.generated.ts +1 -0
- package/generated/entity-fields-registry.ts +12 -0
- package/package.json +7 -7
- package/src/modules/api_keys/api/keys/route.ts +9 -4
- package/src/modules/attachments/components/AttachmentContentPreview.tsx +9 -44
- package/src/modules/audit_logs/backend/audit-logs/page.tsx +12 -22
- package/src/modules/auth/api/autologin.ts +100 -0
- package/src/modules/auth/lib/autologin.ts +36 -0
- package/src/modules/customer_accounts/api/admin/roles/[id]/acl.ts +1 -0
- package/src/modules/customer_accounts/api/admin/roles/[id].ts +17 -3
- package/src/modules/customer_accounts/api/portal/users/[id]/roles.ts +6 -1
- package/src/modules/customer_accounts/api/portal/users-invite.ts +6 -1
- package/src/modules/customer_accounts/services/customerInvitationService.ts +1 -0
- package/src/modules/customer_accounts/services/customerRbacService.ts +9 -2
- package/src/modules/customers/backend/customers/deals/pipeline/components/ViewTabsRow.tsx +6 -2
- package/src/modules/customers/components/detail/CompanyDetailTabs.tsx +27 -49
- package/src/modules/customers/components/detail/DealDetailTabs.tsx +24 -49
- package/src/modules/customers/components/detail/DetailTabsLayout.tsx +13 -24
- package/src/modules/customers/components/detail/MobilePersonDetail.tsx +25 -31
- package/src/modules/customers/components/detail/PersonDetailTabs.tsx +29 -50
- package/src/modules/dictionaries/commands/entries.ts +7 -16
- package/src/modules/dictionaries/commands/entry-operations.ts +8 -18
- package/src/modules/dictionaries/commands/factory.ts +8 -2
- package/src/modules/feature_toggles/api/check/boolean/route.ts +0 -15
- package/src/modules/feature_toggles/defaults.json +8 -0
- package/src/modules/integrations/backend/integrations/[id]/page.tsx +16 -59
- package/src/modules/payment_gateways/data/entities.ts +39 -0
- package/src/modules/payment_gateways/lib/gateway-service.ts +211 -40
- package/src/modules/payment_gateways/lib/session-idempotency.ts +142 -0
- package/src/modules/payment_gateways/migrations/.snapshot-open-mercato.json +236 -0
- package/src/modules/payment_gateways/migrations/Migration20260709220938_payment_gateways.ts +10 -0
- package/src/modules/planner/backend/planner/availability-rulesets/[id]/page.tsx +14 -20
- package/src/modules/planner/components/AvailabilityRulesEditor.tsx +16 -34
- package/src/modules/resources/backend/resources/resources/[id]/page.tsx +27 -37
- package/src/modules/sales/backend/sales/channels/create/page.meta.ts +3 -0
- package/src/modules/sales/backend/sales/channels/create/page.tsx +7 -0
- package/src/modules/sales/backend/sales/channels/offers/page.meta.ts +3 -0
- package/src/modules/sales/backend/sales/channels/offers/page.tsx +7 -0
- package/src/modules/sales/backend/sales/channels/page.meta.ts +4 -0
- package/src/modules/sales/backend/sales/channels/page.tsx +7 -0
- package/src/modules/sales/backend/sales/documents/[id]/page.tsx +7 -5
- package/src/modules/sales/components/SalesChannelsDisabledNotice.tsx +21 -0
- package/src/modules/sales/components/documents/SalesDocumentForm.tsx +7 -3
- package/src/modules/sales/components/documents/SalesDocumentsTable.tsx +10 -8
- package/src/modules/sales/components/useSalesChannelsEnabled.ts +59 -0
- package/src/modules/sales/i18n/de.json +1 -0
- package/src/modules/sales/i18n/en.json +1 -0
- package/src/modules/sales/i18n/es.json +1 -0
- package/src/modules/sales/i18n/pl.json +1 -0
- package/src/modules/sales/lib/salesChannelsToggle.ts +26 -0
- package/src/modules/sales/lib/salesChannelsToggleId.ts +1 -0
- package/src/modules/staff/backend/staff/team-members/[id]/page.tsx +25 -34
- package/src/modules/staff/backend/staff/teams/[id]/edit/page.tsx +11 -17
- package/src/modules/staff/lib/timesheets-projects-ui/SavedViewTabs.tsx +11 -28
- package/src/modules/sync_excel/lib/adapters/customers.ts +20 -22
- package/src/modules/sync_excel/lib/parser.ts +245 -0
- package/src/modules/sync_excel/lib/upload-storage.ts +23 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/modules/dictionaries/commands/factory.ts"],
|
|
4
|
-
"sourcesContent": ["import type { EntityManager } from '@mikro-orm/postgresql'\nimport { Dictionary, DictionaryEntry } from '@open-mercato/core/modules/dictionaries/data/entities'\nimport {\n normalizeDictionaryValue,\n sanitizeDictionaryColor,\n sanitizeDictionaryIcon,\n} from '@open-mercato/core/modules/dictionaries/lib/utils'\nimport {\n registerCommand,\n type CommandHandler,\n type CommandRuntimeContext,\n} from '@open-mercato/shared/lib/commands'\nimport { extractUndoPayload } from '@open-mercato/shared/lib/commands/undo'\nimport { buildChanges, requireId } from '@open-mercato/shared/lib/commands/helpers'\nimport { CrudHttpError } from '@open-mercato/shared/lib/crud/errors'\nimport { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'\nimport type { z } from 'zod'\nimport { findOneWithDecryption } from '@open-mercato/shared/lib/encryption/find'\n\ntype DictionaryScope = {\n tenantId: string\n organizationId: string\n}\n\nexport type DictionaryEntrySnapshot = {\n id: string\n dictionaryId: string\n dictionaryKey: string\n organizationId: string\n tenantId: string\n value: string\n label: string\n color: string | null\n icon: string | null\n createdAt: string\n updatedAt: string\n position?: number\n isDefault?: boolean\n}\n\nexport type DictionaryEntryUndoPayload = {\n before?: DictionaryEntrySnapshot | null\n after?: DictionaryEntrySnapshot | null\n}\n\nconst ENTRY_CHANGE_KEYS = ['value', 'label', 'color', 'icon', 'position', 'isDefault'] as const\n\ntype ResolveDictionaryForCreate<TCreate> = (options: {\n em: EntityManager\n ctx: CommandRuntimeContext\n parsed: TCreate\n}) => Promise<{ dictionary: Dictionary; scope: DictionaryScope }>\n\ntype ResolveEntry<TInput> = (options: {\n em: EntityManager\n ctx: CommandRuntimeContext\n id: string\n parsed?: TInput\n}) => Promise<{ entry: DictionaryEntry; dictionary: Dictionary; scope: DictionaryScope }>\n\ntype EnsureDictionaryForUndo = (options: {\n em: EntityManager\n ctx: CommandRuntimeContext\n snapshot: DictionaryEntrySnapshot\n}) => Promise<Dictionary | null>\n\ntype EnsureScopeFn = (ctx: CommandRuntimeContext, scope: DictionaryScope) => void\n\ntype DictionaryEntryCommandLabels = {\n singular?: string\n create?: string\n update?: string\n delete?: string\n}\n\nexport type DictionaryEntryCommandConfig<TCreate, TUpdate> = {\n commandPrefix: string\n resourceKind: string\n translationKeyPrefix?: string\n createSchema: z.ZodType<TCreate>\n updateSchema: z.ZodType<TUpdate>\n resolveDictionaryForCreate: ResolveDictionaryForCreate<TCreate>\n resolveEntry: ResolveEntry<TUpdate>\n ensureScope?: EnsureScopeFn\n ensureDictionaryForUndo?: EnsureDictionaryForUndo\n duplicateError?: string\n labels?: DictionaryEntryCommandLabels\n}\n\nfunction toScopeEnsurer(fn: EnsureScopeFn | undefined): EnsureScopeFn {\n return typeof fn === 'function' ? fn : () => {}\n}\n\nasync function loadSnapshot(em: EntityManager, id: string): Promise<DictionaryEntrySnapshot | null> {\n const entry = await findOneWithDecryption(em, DictionaryEntry, id, { populate: ['dictionary'] })\n if (!entry) return null\n return {\n id: entry.id,\n dictionaryId: entry.dictionary.id,\n dictionaryKey: entry.dictionary.key,\n organizationId: entry.organizationId,\n tenantId: entry.tenantId,\n value: entry.value,\n label: entry.label,\n color: entry.color ?? null,\n icon: entry.icon ?? null,\n position: entry.position ?? 0,\n isDefault: entry.isDefault ?? false,\n createdAt:\n entry.createdAt instanceof Date\n ? entry.createdAt.toISOString()\n : new Date(entry.createdAt).toISOString(),\n updatedAt:\n entry.updatedAt instanceof Date\n ? entry.updatedAt.toISOString()\n : new Date(entry.updatedAt).toISOString(),\n }\n}\n\nfunction applySnapshot(entry: DictionaryEntry, snapshot: DictionaryEntrySnapshot): void {\n entry.value = snapshot.value\n entry.normalizedValue = normalizeDictionaryValue(snapshot.value)\n entry.label = snapshot.label\n entry.color = snapshot.color ?? null\n entry.icon = snapshot.icon ?? null\n if (snapshot.position !== undefined) entry.position = snapshot.position\n if (snapshot.isDefault !== undefined) entry.isDefault = snapshot.isDefault\n entry.organizationId = snapshot.organizationId\n entry.tenantId = snapshot.tenantId\n entry.createdAt = new Date(snapshot.createdAt)\n entry.updatedAt = new Date(snapshot.updatedAt)\n}\n\nfunction ensureDictionaryForUndoFactory(\n fallback?: EnsureDictionaryForUndo\n): EnsureDictionaryForUndo {\n if (fallback) return fallback\n return async ({ em, snapshot }) => {\n const dictionary = await em.findOne(Dictionary, snapshot.dictionaryId)\n return dictionary ?? null\n }\n}\n\nfunction getDuplicateError(config: DictionaryEntryCommandConfig<any, any>): string {\n return config.duplicateError ?? 'Value already exists in this dictionary.'\n}\n\nfunction sanitizeCreatePayload(input: any): {\n value: string\n normalized: string\n label: string\n color: string | null\n icon: string | null\n position: number | undefined\n} {\n const rawValue = typeof input?.value === 'string' ? input.value.trim() : ''\n if (!rawValue) {\n throw new CrudHttpError(400, { error: 'Dictionary entry value is required.' })\n }\n const normalized = normalizeDictionaryValue(rawValue)\n const rawLabel = typeof input?.label === 'string' ? input.label.trim() : ''\n const label = rawLabel || rawValue\n const color = sanitizeDictionaryColor(input?.color ?? null)\n const icon = sanitizeDictionaryIcon(input?.icon ?? null)\n const position = typeof input?.position === 'number' ? input.position : undefined\n return { value: rawValue, normalized, label, color, icon, position }\n}\n\nfunction sanitizeUpdatePayload(input: any): {\n value?: string\n normalized?: string\n label?: string\n color?: string | null\n icon?: string | null\n position?: number\n isDefault?: boolean\n} {\n const payload: {\n value?: string\n normalized?: string\n label?: string\n color?: string | null\n icon?: string | null\n position?: number\n isDefault?: boolean\n } = {}\n if (Object.prototype.hasOwnProperty.call(input, 'value')) {\n const rawValue = typeof input?.value === 'string' ? input.value.trim() : ''\n if (!rawValue) {\n throw new CrudHttpError(400, { error: 'Dictionary entry value is required.' })\n }\n payload.value = rawValue\n payload.normalized = normalizeDictionaryValue(rawValue)\n }\n if (Object.prototype.hasOwnProperty.call(input, 'label')) {\n const rawLabel = typeof input?.label === 'string' ? input.label.trim() : ''\n payload.label = rawLabel\n }\n if (Object.prototype.hasOwnProperty.call(input, 'color')) {\n payload.color = sanitizeDictionaryColor(input?.color ?? null)\n }\n if (Object.prototype.hasOwnProperty.call(input, 'icon')) {\n payload.icon = sanitizeDictionaryIcon(input?.icon ?? null)\n }\n if (Object.prototype.hasOwnProperty.call(input, 'position')) {\n const rawPosition = typeof input?.position === 'number' ? input.position : undefined\n if (rawPosition !== undefined) {\n payload.position = rawPosition\n }\n }\n if (Object.prototype.hasOwnProperty.call(input, 'isDefault')) {\n payload.isDefault = typeof input?.isDefault === 'boolean' ? input.isDefault : undefined\n }\n return payload\n}\n\nexport function registerDictionaryEntryCommands<TCreate, TUpdate>(\n config: DictionaryEntryCommandConfig<TCreate, TUpdate>\n): void {\n const scopeEnsurer = toScopeEnsurer(config.ensureScope)\n const ensureDictionaryForUndo = ensureDictionaryForUndoFactory(config.ensureDictionaryForUndo)\n const translationKeyPrefix = config.translationKeyPrefix ?? config.commandPrefix\n const fallbackSingular = config.labels?.singular ?? 'Dictionary entry'\n const fallbackCreate = config.labels?.create ?? `Create ${fallbackSingular}`\n const fallbackUpdate = config.labels?.update ?? `Update ${fallbackSingular}`\n const fallbackDelete = config.labels?.delete ?? `Delete ${fallbackSingular}`\n const duplicateMessage = getDuplicateError(config)\n\n const createCommand: CommandHandler<\n ReturnType<typeof config.createSchema['parse']>,\n { entryId: string }\n > = {\n id: `${config.commandPrefix}.create`,\n async execute(rawInput, ctx) {\n const parsed = config.createSchema.parse(rawInput)\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const { dictionary, scope } = await config.resolveDictionaryForCreate({ em, ctx, parsed })\n scopeEnsurer(ctx, scope)\n\n const { value, normalized, label, color, icon, position } = sanitizeCreatePayload(parsed)\n const duplicate = await em.findOne(DictionaryEntry, {\n dictionary,\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n normalizedValue: normalized,\n })\n if (duplicate) {\n throw new CrudHttpError(409, { error: duplicateMessage })\n }\n\n const entry = em.create(DictionaryEntry, {\n dictionary,\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n value,\n normalizedValue: normalized,\n label,\n color,\n icon,\n ...(position !== undefined ? { position } : {}),\n createdAt: new Date(),\n updatedAt: new Date(),\n })\n em.persist(entry)\n await em.flush()\n return { entryId: entry.id }\n },\n captureAfter: async (_input, result, ctx) => {\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n return loadSnapshot(em, result.entryId)\n },\n buildLog: async ({ result, snapshots }) => {\n const after = snapshots.after as DictionaryEntrySnapshot | undefined\n if (!after) return null\n const { translate } = await resolveTranslations()\n return {\n actionLabel: translate(`${translationKeyPrefix}.audit.create`, fallbackCreate),\n resourceKind: config.resourceKind,\n resourceId: result.entryId,\n tenantId: after.tenantId,\n organizationId: after.organizationId,\n snapshotAfter: after,\n payload: {\n undo: { after } satisfies DictionaryEntryUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const undo = extractUndoPayload<DictionaryEntryUndoPayload>(logEntry)\n const after =\n undo?.after ??\n (logEntry?.snapshotAfter as DictionaryEntrySnapshot | null | undefined) ??\n null\n if (!after) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n scopeEnsurer(ctx, { tenantId: after.tenantId, organizationId: after.organizationId })\n const entry = await em.findOne(DictionaryEntry, after.id)\n if (entry) {\n await em.remove(entry).flush()\n return\n }\n await em.nativeDelete(DictionaryEntry, { id: after.id })\n },\n}\n\n const updateCommand: CommandHandler<\n ReturnType<typeof config.updateSchema['parse']>,\n { entryId: string }\n > = {\n id: `${config.commandPrefix}.update`,\n async prepare(input, ctx) {\n const id = requireId(input, 'Dictionary entry id is required')\n const em = (ctx.container.resolve('em') as EntityManager)\n const snapshot = await loadSnapshot(em, id)\n if (snapshot) {\n scopeEnsurer(ctx, { tenantId: snapshot.tenantId, organizationId: snapshot.organizationId })\n }\n return snapshot ? { before: snapshot } : {}\n },\n async execute(rawInput, ctx) {\n const parsed = config.updateSchema.parse(rawInput)\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const id = requireId(parsed, 'Dictionary entry id is required')\n const { entry, dictionary, scope } = await config.resolveEntry({ em, ctx, id, parsed })\n scopeEnsurer(ctx, scope)\n\n const updates = sanitizeUpdatePayload(parsed)\n if (updates.value !== undefined && updates.normalized !== undefined) {\n if (updates.normalized !== entry.normalizedValue) {\n const duplicate = await em.findOne(DictionaryEntry, {\n dictionary,\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n normalizedValue: updates.normalized,\n id: { $ne: entry.id },\n } as any)\n if (duplicate) {\n throw new CrudHttpError(409, { error: duplicateMessage })\n }\n entry.value = updates.value\n entry.normalizedValue = updates.normalized\n if (updates.label === undefined) {\n entry.label = entry.value\n }\n }\n }\n if (updates.label !== undefined) {\n entry.label = updates.label || entry.value\n }\n if (Object.prototype.hasOwnProperty.call(updates, 'color')) {\n entry.color = updates.color ?? null\n }\n if (Object.prototype.hasOwnProperty.call(updates, 'icon')) {\n entry.icon = updates.icon ?? null\n }\n if (updates.position !== undefined) {\n entry.position = updates.position\n }\n if (updates.isDefault !== undefined) {\n entry.isDefault = updates.isDefault\n }\n await em.flush()\n return { entryId: entry.id }\n },\n captureAfter: async (_input, result, ctx) => {\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n return loadSnapshot(em, result.entryId)\n },\n buildLog: async ({ snapshots }) => {\n const before = snapshots.before as DictionaryEntrySnapshot | undefined\n const after = snapshots.after as DictionaryEntrySnapshot | undefined\n if (!before || !after) return null\n const { translate } = await resolveTranslations()\n return {\n actionLabel: translate(`${translationKeyPrefix}.audit.update`, fallbackUpdate),\n resourceKind: config.resourceKind,\n resourceId: before.id,\n tenantId: before.tenantId,\n organizationId: before.organizationId,\n snapshotBefore: before,\n snapshotAfter: after,\n changes: buildChanges(\n before as Record<string, unknown>,\n after as Record<string, unknown>,\n ENTRY_CHANGE_KEYS,\n ),\n payload: {\n undo: { before, after } satisfies DictionaryEntryUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const undo = extractUndoPayload<DictionaryEntryUndoPayload>(logEntry)\n const before =\n undo?.before ??\n (logEntry?.snapshotBefore as DictionaryEntrySnapshot | null | undefined) ??\n null\n if (!before) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n scopeEnsurer(ctx, { tenantId: before.tenantId, organizationId: before.organizationId })\n const dictionary = await ensureDictionaryForUndo({ em, ctx, snapshot: before })\n if (!dictionary) return\n let entry = await em.findOne(DictionaryEntry, before.id)\n if (!entry) {\n entry = em.create(DictionaryEntry, {\n id: before.id,\n dictionary,\n tenantId: before.tenantId,\n organizationId: before.organizationId,\n value: before.value,\n normalizedValue: normalizeDictionaryValue(before.value),\n label: before.label,\n color: before.color,\n icon: before.icon,\n createdAt: new Date(before.createdAt),\n updatedAt: new Date(before.updatedAt),\n })\n em.persist(entry)\n } else {\n entry.dictionary = dictionary\n applySnapshot(entry, before)\n }\n await em.flush()\n },\n }\n\n const deleteCommand: CommandHandler<\n { body?: Record<string, unknown>; query?: Record<string, unknown> },\n { entryId: string }\n > = {\n id: `${config.commandPrefix}.delete`,\n async prepare(input, ctx) {\n const id = requireId(input, 'Dictionary entry id is required')\n const em = (ctx.container.resolve('em') as EntityManager)\n const snapshot = await loadSnapshot(em, id)\n if (snapshot) {\n scopeEnsurer(ctx, { tenantId: snapshot.tenantId, organizationId: snapshot.organizationId })\n }\n return snapshot ? { before: snapshot } : {}\n },\n async execute(input, ctx) {\n const id = requireId(input, 'Dictionary entry id is required')\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const { entry, scope } = await config.resolveEntry({ em, ctx, id })\n scopeEnsurer(ctx, scope)\n em.remove(entry)\n await em.flush()\n return { entryId: id }\n },\n buildLog: async ({ snapshots }) => {\n const before = snapshots.before as DictionaryEntrySnapshot | undefined\n if (!before) return null\n const { translate } = await resolveTranslations()\n return {\n actionLabel: translate(`${translationKeyPrefix}.audit.delete`, fallbackDelete),\n resourceKind: config.resourceKind,\n resourceId: before.id,\n tenantId: before.tenantId,\n organizationId: before.organizationId,\n snapshotBefore: before,\n payload: {\n undo: { before } satisfies DictionaryEntryUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const undo = extractUndoPayload<DictionaryEntryUndoPayload>(logEntry)\n const before =\n undo?.before ??\n (logEntry?.snapshotBefore as DictionaryEntrySnapshot | null | undefined) ??\n null\n if (!before) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n scopeEnsurer(ctx, { tenantId: before.tenantId, organizationId: before.organizationId })\n const dictionary = await ensureDictionaryForUndo({ em, ctx, snapshot: before })\n if (!dictionary) return\n let entry = await em.findOne(DictionaryEntry, before.id)\n if (!entry) {\n entry = em.create(DictionaryEntry, {\n id: before.id,\n dictionary,\n tenantId: before.tenantId,\n organizationId: before.organizationId,\n value: before.value,\n normalizedValue: normalizeDictionaryValue(before.value),\n label: before.label,\n color: before.color,\n icon: before.icon,\n createdAt: new Date(before.createdAt),\n updatedAt: new Date(before.updatedAt),\n })\n em.persist(entry)\n } else {\n entry.dictionary = dictionary\n applySnapshot(entry, before)\n }\n await em.flush()\n },\n }\n\n registerCommand(createCommand)\n registerCommand(updateCommand)\n registerCommand(deleteCommand)\n}\n"],
|
|
5
|
-
"mappings": "AACA,SAAS,YAAY,uBAAuB;AAC5C;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP;AAAA,EACE;AAAA,OAGK;AACP,SAAS,0BAA0B;AACnC,SAAS,cAAc,iBAAiB;AACxC,SAAS,qBAAqB;AAC9B,SAAS,2BAA2B;AAEpC,SAAS,6BAA6B;
|
|
4
|
+
"sourcesContent": ["import type { EntityManager } from '@mikro-orm/postgresql'\nimport { Dictionary, DictionaryEntry } from '@open-mercato/core/modules/dictionaries/data/entities'\nimport {\n normalizeDictionaryValue,\n sanitizeDictionaryColor,\n sanitizeDictionaryIcon,\n} from '@open-mercato/core/modules/dictionaries/lib/utils'\nimport {\n registerCommand,\n type CommandHandler,\n type CommandRuntimeContext,\n} from '@open-mercato/shared/lib/commands'\nimport { extractUndoPayload } from '@open-mercato/shared/lib/commands/undo'\nimport { buildChanges, requireId } from '@open-mercato/shared/lib/commands/helpers'\nimport { ensureOrganizationScope, ensureTenantScope } from '@open-mercato/shared/lib/commands/scope'\nimport { CrudHttpError } from '@open-mercato/shared/lib/crud/errors'\nimport { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'\nimport type { z } from 'zod'\nimport { findOneWithDecryption } from '@open-mercato/shared/lib/encryption/find'\n\ntype DictionaryScope = {\n tenantId: string\n organizationId: string\n}\n\nexport function ensureDictionaryEntryScope(ctx: CommandRuntimeContext, scope: DictionaryScope): void {\n ensureTenantScope(ctx, scope.tenantId)\n ensureOrganizationScope(ctx, scope.organizationId)\n}\n\nexport type DictionaryEntrySnapshot = {\n id: string\n dictionaryId: string\n dictionaryKey: string\n organizationId: string\n tenantId: string\n value: string\n label: string\n color: string | null\n icon: string | null\n createdAt: string\n updatedAt: string\n position?: number\n isDefault?: boolean\n}\n\nexport type DictionaryEntryUndoPayload = {\n before?: DictionaryEntrySnapshot | null\n after?: DictionaryEntrySnapshot | null\n}\n\nconst ENTRY_CHANGE_KEYS = ['value', 'label', 'color', 'icon', 'position', 'isDefault'] as const\n\ntype ResolveDictionaryForCreate<TCreate> = (options: {\n em: EntityManager\n ctx: CommandRuntimeContext\n parsed: TCreate\n}) => Promise<{ dictionary: Dictionary; scope: DictionaryScope }>\n\ntype ResolveEntry<TInput> = (options: {\n em: EntityManager\n ctx: CommandRuntimeContext\n id: string\n parsed?: TInput\n}) => Promise<{ entry: DictionaryEntry; dictionary: Dictionary; scope: DictionaryScope }>\n\ntype EnsureDictionaryForUndo = (options: {\n em: EntityManager\n ctx: CommandRuntimeContext\n snapshot: DictionaryEntrySnapshot\n}) => Promise<Dictionary | null>\n\ntype EnsureScopeFn = (ctx: CommandRuntimeContext, scope: DictionaryScope) => void\n\ntype DictionaryEntryCommandLabels = {\n singular?: string\n create?: string\n update?: string\n delete?: string\n}\n\nexport type DictionaryEntryCommandConfig<TCreate, TUpdate> = {\n commandPrefix: string\n resourceKind: string\n translationKeyPrefix?: string\n createSchema: z.ZodType<TCreate>\n updateSchema: z.ZodType<TUpdate>\n resolveDictionaryForCreate: ResolveDictionaryForCreate<TCreate>\n resolveEntry: ResolveEntry<TUpdate>\n ensureScope?: EnsureScopeFn\n ensureDictionaryForUndo?: EnsureDictionaryForUndo\n duplicateError?: string\n labels?: DictionaryEntryCommandLabels\n}\n\nexport function toScopeEnsurer(fn: EnsureScopeFn | undefined): EnsureScopeFn {\n return typeof fn === 'function' ? fn : ensureDictionaryEntryScope\n}\n\nasync function loadSnapshot(em: EntityManager, id: string): Promise<DictionaryEntrySnapshot | null> {\n const entry = await findOneWithDecryption(em, DictionaryEntry, id, { populate: ['dictionary'] })\n if (!entry) return null\n return {\n id: entry.id,\n dictionaryId: entry.dictionary.id,\n dictionaryKey: entry.dictionary.key,\n organizationId: entry.organizationId,\n tenantId: entry.tenantId,\n value: entry.value,\n label: entry.label,\n color: entry.color ?? null,\n icon: entry.icon ?? null,\n position: entry.position ?? 0,\n isDefault: entry.isDefault ?? false,\n createdAt:\n entry.createdAt instanceof Date\n ? entry.createdAt.toISOString()\n : new Date(entry.createdAt).toISOString(),\n updatedAt:\n entry.updatedAt instanceof Date\n ? entry.updatedAt.toISOString()\n : new Date(entry.updatedAt).toISOString(),\n }\n}\n\nfunction applySnapshot(entry: DictionaryEntry, snapshot: DictionaryEntrySnapshot): void {\n entry.value = snapshot.value\n entry.normalizedValue = normalizeDictionaryValue(snapshot.value)\n entry.label = snapshot.label\n entry.color = snapshot.color ?? null\n entry.icon = snapshot.icon ?? null\n if (snapshot.position !== undefined) entry.position = snapshot.position\n if (snapshot.isDefault !== undefined) entry.isDefault = snapshot.isDefault\n entry.organizationId = snapshot.organizationId\n entry.tenantId = snapshot.tenantId\n entry.createdAt = new Date(snapshot.createdAt)\n entry.updatedAt = new Date(snapshot.updatedAt)\n}\n\nfunction ensureDictionaryForUndoFactory(\n fallback?: EnsureDictionaryForUndo\n): EnsureDictionaryForUndo {\n if (fallback) return fallback\n return async ({ em, snapshot }) => {\n const dictionary = await em.findOne(Dictionary, snapshot.dictionaryId)\n return dictionary ?? null\n }\n}\n\nfunction getDuplicateError(config: DictionaryEntryCommandConfig<any, any>): string {\n return config.duplicateError ?? 'Value already exists in this dictionary.'\n}\n\nfunction sanitizeCreatePayload(input: any): {\n value: string\n normalized: string\n label: string\n color: string | null\n icon: string | null\n position: number | undefined\n} {\n const rawValue = typeof input?.value === 'string' ? input.value.trim() : ''\n if (!rawValue) {\n throw new CrudHttpError(400, { error: 'Dictionary entry value is required.' })\n }\n const normalized = normalizeDictionaryValue(rawValue)\n const rawLabel = typeof input?.label === 'string' ? input.label.trim() : ''\n const label = rawLabel || rawValue\n const color = sanitizeDictionaryColor(input?.color ?? null)\n const icon = sanitizeDictionaryIcon(input?.icon ?? null)\n const position = typeof input?.position === 'number' ? input.position : undefined\n return { value: rawValue, normalized, label, color, icon, position }\n}\n\nfunction sanitizeUpdatePayload(input: any): {\n value?: string\n normalized?: string\n label?: string\n color?: string | null\n icon?: string | null\n position?: number\n isDefault?: boolean\n} {\n const payload: {\n value?: string\n normalized?: string\n label?: string\n color?: string | null\n icon?: string | null\n position?: number\n isDefault?: boolean\n } = {}\n if (Object.prototype.hasOwnProperty.call(input, 'value')) {\n const rawValue = typeof input?.value === 'string' ? input.value.trim() : ''\n if (!rawValue) {\n throw new CrudHttpError(400, { error: 'Dictionary entry value is required.' })\n }\n payload.value = rawValue\n payload.normalized = normalizeDictionaryValue(rawValue)\n }\n if (Object.prototype.hasOwnProperty.call(input, 'label')) {\n const rawLabel = typeof input?.label === 'string' ? input.label.trim() : ''\n payload.label = rawLabel\n }\n if (Object.prototype.hasOwnProperty.call(input, 'color')) {\n payload.color = sanitizeDictionaryColor(input?.color ?? null)\n }\n if (Object.prototype.hasOwnProperty.call(input, 'icon')) {\n payload.icon = sanitizeDictionaryIcon(input?.icon ?? null)\n }\n if (Object.prototype.hasOwnProperty.call(input, 'position')) {\n const rawPosition = typeof input?.position === 'number' ? input.position : undefined\n if (rawPosition !== undefined) {\n payload.position = rawPosition\n }\n }\n if (Object.prototype.hasOwnProperty.call(input, 'isDefault')) {\n payload.isDefault = typeof input?.isDefault === 'boolean' ? input.isDefault : undefined\n }\n return payload\n}\n\nexport function registerDictionaryEntryCommands<TCreate, TUpdate>(\n config: DictionaryEntryCommandConfig<TCreate, TUpdate>\n): void {\n const scopeEnsurer = toScopeEnsurer(config.ensureScope)\n const ensureDictionaryForUndo = ensureDictionaryForUndoFactory(config.ensureDictionaryForUndo)\n const translationKeyPrefix = config.translationKeyPrefix ?? config.commandPrefix\n const fallbackSingular = config.labels?.singular ?? 'Dictionary entry'\n const fallbackCreate = config.labels?.create ?? `Create ${fallbackSingular}`\n const fallbackUpdate = config.labels?.update ?? `Update ${fallbackSingular}`\n const fallbackDelete = config.labels?.delete ?? `Delete ${fallbackSingular}`\n const duplicateMessage = getDuplicateError(config)\n\n const createCommand: CommandHandler<\n ReturnType<typeof config.createSchema['parse']>,\n { entryId: string }\n > = {\n id: `${config.commandPrefix}.create`,\n async execute(rawInput, ctx) {\n const parsed = config.createSchema.parse(rawInput)\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const { dictionary, scope } = await config.resolveDictionaryForCreate({ em, ctx, parsed })\n scopeEnsurer(ctx, scope)\n\n const { value, normalized, label, color, icon, position } = sanitizeCreatePayload(parsed)\n const duplicate = await em.findOne(DictionaryEntry, {\n dictionary,\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n normalizedValue: normalized,\n })\n if (duplicate) {\n throw new CrudHttpError(409, { error: duplicateMessage })\n }\n\n const entry = em.create(DictionaryEntry, {\n dictionary,\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n value,\n normalizedValue: normalized,\n label,\n color,\n icon,\n ...(position !== undefined ? { position } : {}),\n createdAt: new Date(),\n updatedAt: new Date(),\n })\n em.persist(entry)\n await em.flush()\n return { entryId: entry.id }\n },\n captureAfter: async (_input, result, ctx) => {\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n return loadSnapshot(em, result.entryId)\n },\n buildLog: async ({ result, snapshots }) => {\n const after = snapshots.after as DictionaryEntrySnapshot | undefined\n if (!after) return null\n const { translate } = await resolveTranslations()\n return {\n actionLabel: translate(`${translationKeyPrefix}.audit.create`, fallbackCreate),\n resourceKind: config.resourceKind,\n resourceId: result.entryId,\n tenantId: after.tenantId,\n organizationId: after.organizationId,\n snapshotAfter: after,\n payload: {\n undo: { after } satisfies DictionaryEntryUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const undo = extractUndoPayload<DictionaryEntryUndoPayload>(logEntry)\n const after =\n undo?.after ??\n (logEntry?.snapshotAfter as DictionaryEntrySnapshot | null | undefined) ??\n null\n if (!after) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n scopeEnsurer(ctx, { tenantId: after.tenantId, organizationId: after.organizationId })\n const entry = await em.findOne(DictionaryEntry, after.id)\n if (entry) {\n await em.remove(entry).flush()\n return\n }\n await em.nativeDelete(DictionaryEntry, { id: after.id })\n },\n}\n\n const updateCommand: CommandHandler<\n ReturnType<typeof config.updateSchema['parse']>,\n { entryId: string }\n > = {\n id: `${config.commandPrefix}.update`,\n async prepare(input, ctx) {\n const id = requireId(input, 'Dictionary entry id is required')\n const em = (ctx.container.resolve('em') as EntityManager)\n const snapshot = await loadSnapshot(em, id)\n if (snapshot) {\n scopeEnsurer(ctx, { tenantId: snapshot.tenantId, organizationId: snapshot.organizationId })\n }\n return snapshot ? { before: snapshot } : {}\n },\n async execute(rawInput, ctx) {\n const parsed = config.updateSchema.parse(rawInput)\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const id = requireId(parsed, 'Dictionary entry id is required')\n const { entry, dictionary, scope } = await config.resolveEntry({ em, ctx, id, parsed })\n scopeEnsurer(ctx, scope)\n\n const updates = sanitizeUpdatePayload(parsed)\n if (updates.value !== undefined && updates.normalized !== undefined) {\n if (updates.normalized !== entry.normalizedValue) {\n const duplicate = await em.findOne(DictionaryEntry, {\n dictionary,\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n normalizedValue: updates.normalized,\n id: { $ne: entry.id },\n } as any)\n if (duplicate) {\n throw new CrudHttpError(409, { error: duplicateMessage })\n }\n entry.value = updates.value\n entry.normalizedValue = updates.normalized\n if (updates.label === undefined) {\n entry.label = entry.value\n }\n }\n }\n if (updates.label !== undefined) {\n entry.label = updates.label || entry.value\n }\n if (Object.prototype.hasOwnProperty.call(updates, 'color')) {\n entry.color = updates.color ?? null\n }\n if (Object.prototype.hasOwnProperty.call(updates, 'icon')) {\n entry.icon = updates.icon ?? null\n }\n if (updates.position !== undefined) {\n entry.position = updates.position\n }\n if (updates.isDefault !== undefined) {\n entry.isDefault = updates.isDefault\n }\n await em.flush()\n return { entryId: entry.id }\n },\n captureAfter: async (_input, result, ctx) => {\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n return loadSnapshot(em, result.entryId)\n },\n buildLog: async ({ snapshots }) => {\n const before = snapshots.before as DictionaryEntrySnapshot | undefined\n const after = snapshots.after as DictionaryEntrySnapshot | undefined\n if (!before || !after) return null\n const { translate } = await resolveTranslations()\n return {\n actionLabel: translate(`${translationKeyPrefix}.audit.update`, fallbackUpdate),\n resourceKind: config.resourceKind,\n resourceId: before.id,\n tenantId: before.tenantId,\n organizationId: before.organizationId,\n snapshotBefore: before,\n snapshotAfter: after,\n changes: buildChanges(\n before as Record<string, unknown>,\n after as Record<string, unknown>,\n ENTRY_CHANGE_KEYS,\n ),\n payload: {\n undo: { before, after } satisfies DictionaryEntryUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const undo = extractUndoPayload<DictionaryEntryUndoPayload>(logEntry)\n const before =\n undo?.before ??\n (logEntry?.snapshotBefore as DictionaryEntrySnapshot | null | undefined) ??\n null\n if (!before) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n scopeEnsurer(ctx, { tenantId: before.tenantId, organizationId: before.organizationId })\n const dictionary = await ensureDictionaryForUndo({ em, ctx, snapshot: before })\n if (!dictionary) return\n let entry = await em.findOne(DictionaryEntry, before.id)\n if (!entry) {\n entry = em.create(DictionaryEntry, {\n id: before.id,\n dictionary,\n tenantId: before.tenantId,\n organizationId: before.organizationId,\n value: before.value,\n normalizedValue: normalizeDictionaryValue(before.value),\n label: before.label,\n color: before.color,\n icon: before.icon,\n createdAt: new Date(before.createdAt),\n updatedAt: new Date(before.updatedAt),\n })\n em.persist(entry)\n } else {\n entry.dictionary = dictionary\n applySnapshot(entry, before)\n }\n await em.flush()\n },\n }\n\n const deleteCommand: CommandHandler<\n { body?: Record<string, unknown>; query?: Record<string, unknown> },\n { entryId: string }\n > = {\n id: `${config.commandPrefix}.delete`,\n async prepare(input, ctx) {\n const id = requireId(input, 'Dictionary entry id is required')\n const em = (ctx.container.resolve('em') as EntityManager)\n const snapshot = await loadSnapshot(em, id)\n if (snapshot) {\n scopeEnsurer(ctx, { tenantId: snapshot.tenantId, organizationId: snapshot.organizationId })\n }\n return snapshot ? { before: snapshot } : {}\n },\n async execute(input, ctx) {\n const id = requireId(input, 'Dictionary entry id is required')\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const { entry, scope } = await config.resolveEntry({ em, ctx, id })\n scopeEnsurer(ctx, scope)\n em.remove(entry)\n await em.flush()\n return { entryId: id }\n },\n buildLog: async ({ snapshots }) => {\n const before = snapshots.before as DictionaryEntrySnapshot | undefined\n if (!before) return null\n const { translate } = await resolveTranslations()\n return {\n actionLabel: translate(`${translationKeyPrefix}.audit.delete`, fallbackDelete),\n resourceKind: config.resourceKind,\n resourceId: before.id,\n tenantId: before.tenantId,\n organizationId: before.organizationId,\n snapshotBefore: before,\n payload: {\n undo: { before } satisfies DictionaryEntryUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const undo = extractUndoPayload<DictionaryEntryUndoPayload>(logEntry)\n const before =\n undo?.before ??\n (logEntry?.snapshotBefore as DictionaryEntrySnapshot | null | undefined) ??\n null\n if (!before) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n scopeEnsurer(ctx, { tenantId: before.tenantId, organizationId: before.organizationId })\n const dictionary = await ensureDictionaryForUndo({ em, ctx, snapshot: before })\n if (!dictionary) return\n let entry = await em.findOne(DictionaryEntry, before.id)\n if (!entry) {\n entry = em.create(DictionaryEntry, {\n id: before.id,\n dictionary,\n tenantId: before.tenantId,\n organizationId: before.organizationId,\n value: before.value,\n normalizedValue: normalizeDictionaryValue(before.value),\n label: before.label,\n color: before.color,\n icon: before.icon,\n createdAt: new Date(before.createdAt),\n updatedAt: new Date(before.updatedAt),\n })\n em.persist(entry)\n } else {\n entry.dictionary = dictionary\n applySnapshot(entry, before)\n }\n await em.flush()\n },\n }\n\n registerCommand(createCommand)\n registerCommand(updateCommand)\n registerCommand(deleteCommand)\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -12,20 +12,6 @@ async function GET(req) {
|
|
|
12
12
|
if (!identifier) {
|
|
13
13
|
return NextResponse.json({ error: "Missing required parameter: identifier" }, { status: 400 });
|
|
14
14
|
}
|
|
15
|
-
if (auth.isSuperAdmin === true) {
|
|
16
|
-
return NextResponse.json({
|
|
17
|
-
ok: true,
|
|
18
|
-
value: true,
|
|
19
|
-
resolution: {
|
|
20
|
-
valueType: "boolean",
|
|
21
|
-
value: true,
|
|
22
|
-
source: "override",
|
|
23
|
-
toggleId: "superadmin",
|
|
24
|
-
identifier,
|
|
25
|
-
tenantId: "superadmin"
|
|
26
|
-
}
|
|
27
|
-
});
|
|
28
|
-
}
|
|
29
15
|
const container = await createRequestContainer();
|
|
30
16
|
const { scope } = await resolveFeatureCheckContext({
|
|
31
17
|
container,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../../src/modules/feature_toggles/api/check/boolean/route.ts"],
|
|
4
|
-
"sourcesContent": ["import { getAuthFromRequest } from \"@open-mercato/shared/lib/auth/server\"\nimport { createRequestContainer } from \"@open-mercato/shared/lib/di/container\"\nimport { NextResponse } from \"next/server\"\nimport { resolveFeatureCheckContext } from \"@open-mercato/core/modules/directory/utils/organizationScope\"\nimport { FeatureTogglesService } from \"../../../lib/feature-flag-check\"\nimport { featureTogglesTag, checkResponseSchema, featureToggleErrorSchema } from \"../../openapi\"\nimport type { OpenApiRouteDoc } from '@open-mercato/shared/lib/openapi'\nimport { z } from 'zod'\n\nexport async function GET(req: Request) {\n const auth = await getAuthFromRequest(req)\n if (!auth) return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })\n\n const url = new URL(req.url)\n const identifier = url.searchParams.get('identifier')\n\n if (!identifier) {\n return NextResponse.json({ error: 'Missing required parameter: identifier' }, { status: 400 })\n }\n\n
|
|
5
|
-
"mappings": "AAAA,SAAS,0BAA0B;AACnC,SAAS,8BAA8B;AACvC,SAAS,oBAAoB;AAC7B,SAAS,kCAAkC;AAE3C,SAAS,mBAAmB,qBAAqB,gCAAgC;AAEjF,SAAS,SAAS;AAElB,eAAsB,IAAI,KAAc;AACpC,QAAM,OAAO,MAAM,mBAAmB,GAAG;AACzC,MAAI,CAAC,KAAM,QAAO,aAAa,KAAK,EAAE,OAAO,eAAe,GAAG,EAAE,QAAQ,IAAI,CAAC;AAE9E,QAAM,MAAM,IAAI,IAAI,IAAI,GAAG;AAC3B,QAAM,aAAa,IAAI,aAAa,IAAI,YAAY;AAEpD,MAAI,CAAC,YAAY;AACb,WAAO,aAAa,KAAK,EAAE,OAAO,yCAAyC,GAAG,EAAE,QAAQ,IAAI,CAAC;AAAA,EACjG;AAEA,
|
|
4
|
+
"sourcesContent": ["import { getAuthFromRequest } from \"@open-mercato/shared/lib/auth/server\"\nimport { createRequestContainer } from \"@open-mercato/shared/lib/di/container\"\nimport { NextResponse } from \"next/server\"\nimport { resolveFeatureCheckContext } from \"@open-mercato/core/modules/directory/utils/organizationScope\"\nimport { FeatureTogglesService } from \"../../../lib/feature-flag-check\"\nimport { featureTogglesTag, checkResponseSchema, featureToggleErrorSchema } from \"../../openapi\"\nimport type { OpenApiRouteDoc } from '@open-mercato/shared/lib/openapi'\nimport { z } from 'zod'\n\nexport async function GET(req: Request) {\n const auth = await getAuthFromRequest(req)\n if (!auth) return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })\n\n const url = new URL(req.url)\n const identifier = url.searchParams.get('identifier')\n\n if (!identifier) {\n return NextResponse.json({ error: 'Missing required parameter: identifier' }, { status: 400 })\n }\n\n const container = await createRequestContainer()\n const { scope } = await resolveFeatureCheckContext({\n container,\n auth,\n request: req\n })\n\n if (!scope.tenantId) {\n return NextResponse.json({ error: 'Tenant context required. Please select a tenant.' }, { status: 400 })\n }\n\n const featureTogglesService = container.resolve('featureTogglesService') as FeatureTogglesService\n const result = await featureTogglesService.getBoolConfig(identifier, scope.tenantId)\n\n if (!result.ok) {\n return NextResponse.json(result, { status: result.error.code === \"MISSING_TOGGLE\" ? 404 : 400 })\n }\n\n return NextResponse.json(result)\n}\n\nconst routeMetadata = {\n GET: { requireAuth: true },\n}\n\nexport const metadata = routeMetadata\n\nexport const openApi: OpenApiRouteDoc = {\n tag: featureTogglesTag,\n summary: 'Check feature toggle status',\n methods: {\n GET: {\n summary: 'Check if feature is enabled',\n description: 'Checks if a feature toggle is enabled for the current context.',\n query: z.object({\n identifier: z.string().describe('Feature toggle identifier'),\n }),\n responses: [\n { status: 200, description: 'Feature status', schema: checkResponseSchema },\n ],\n errors: [\n { status: 400, description: 'Bad Request', schema: featureToggleErrorSchema },\n { status: 401, description: 'Unauthorized', schema: featureToggleErrorSchema },\n { status: 404, description: 'Tenant not found', schema: featureToggleErrorSchema },\n ],\n },\n },\n}\n"],
|
|
5
|
+
"mappings": "AAAA,SAAS,0BAA0B;AACnC,SAAS,8BAA8B;AACvC,SAAS,oBAAoB;AAC7B,SAAS,kCAAkC;AAE3C,SAAS,mBAAmB,qBAAqB,gCAAgC;AAEjF,SAAS,SAAS;AAElB,eAAsB,IAAI,KAAc;AACpC,QAAM,OAAO,MAAM,mBAAmB,GAAG;AACzC,MAAI,CAAC,KAAM,QAAO,aAAa,KAAK,EAAE,OAAO,eAAe,GAAG,EAAE,QAAQ,IAAI,CAAC;AAE9E,QAAM,MAAM,IAAI,IAAI,IAAI,GAAG;AAC3B,QAAM,aAAa,IAAI,aAAa,IAAI,YAAY;AAEpD,MAAI,CAAC,YAAY;AACb,WAAO,aAAa,KAAK,EAAE,OAAO,yCAAyC,GAAG,EAAE,QAAQ,IAAI,CAAC;AAAA,EACjG;AAEA,QAAM,YAAY,MAAM,uBAAuB;AAC/C,QAAM,EAAE,MAAM,IAAI,MAAM,2BAA2B;AAAA,IAC/C;AAAA,IACA;AAAA,IACA,SAAS;AAAA,EACb,CAAC;AAED,MAAI,CAAC,MAAM,UAAU;AACjB,WAAO,aAAa,KAAK,EAAE,OAAO,mDAAmD,GAAG,EAAE,QAAQ,IAAI,CAAC;AAAA,EAC3G;AAEA,QAAM,wBAAwB,UAAU,QAAQ,uBAAuB;AACvE,QAAM,SAAS,MAAM,sBAAsB,cAAc,YAAY,MAAM,QAAQ;AAEnF,MAAI,CAAC,OAAO,IAAI;AACZ,WAAO,aAAa,KAAK,QAAQ,EAAE,QAAQ,OAAO,MAAM,SAAS,mBAAmB,MAAM,IAAI,CAAC;AAAA,EACnG;AAEA,SAAO,aAAa,KAAK,MAAM;AACnC;AAEA,MAAM,gBAAgB;AAAA,EAClB,KAAK,EAAE,aAAa,KAAK;AAC7B;AAEO,MAAM,WAAW;AAEjB,MAAM,UAA2B;AAAA,EACpC,KAAK;AAAA,EACL,SAAS;AAAA,EACT,SAAS;AAAA,IACL,KAAK;AAAA,MACD,SAAS;AAAA,MACT,aAAa;AAAA,MACb,OAAO,EAAE,OAAO;AAAA,QACZ,YAAY,EAAE,OAAO,EAAE,SAAS,2BAA2B;AAAA,MAC/D,CAAC;AAAA,MACD,WAAW;AAAA,QACP,EAAE,QAAQ,KAAK,aAAa,kBAAkB,QAAQ,oBAAoB;AAAA,MAC9E;AAAA,MACA,QAAQ;AAAA,QACJ,EAAE,QAAQ,KAAK,aAAa,eAAe,QAAQ,yBAAyB;AAAA,QAC5E,EAAE,QAAQ,KAAK,aAAa,gBAAgB,QAAQ,yBAAyB;AAAA,QAC7E,EAAE,QAAQ,KAAK,aAAa,oBAAoB,QAAQ,yBAAyB;AAAA,MACrF;AAAA,IACJ;AAAA,EACJ;AACJ;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -16,6 +16,14 @@
|
|
|
16
16
|
"type": "string",
|
|
17
17
|
"defaultValue": "Free shipping on orders over $50"
|
|
18
18
|
},
|
|
19
|
+
{
|
|
20
|
+
"identifier": "sales_channels_enabled",
|
|
21
|
+
"name": "Sales Channels",
|
|
22
|
+
"description": "Show sales channel pickers, filters, and management UI. Disable for tenants that do not use sales channels.",
|
|
23
|
+
"category": "sales",
|
|
24
|
+
"type": "boolean",
|
|
25
|
+
"defaultValue": true
|
|
26
|
+
},
|
|
19
27
|
{
|
|
20
28
|
"identifier": "order_review_threshold",
|
|
21
29
|
"name": "Order Review Threshold",
|
|
@@ -922,86 +922,15 @@ function IntegrationDetailPage({ params }) {
|
|
|
922
922
|
},
|
|
923
923
|
widget.widgetId
|
|
924
924
|
)) }) : null,
|
|
925
|
-
/* @__PURE__ */ jsxs(Tabs, { value: activeTab, onValueChange: handleTabChange, className: "space-y-5", children: [
|
|
926
|
-
/* @__PURE__ */ jsxs(TabsList, { className: "
|
|
927
|
-
showCredentialsTab ? /* @__PURE__ */ jsx(
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
/* @__PURE__ */ jsx("span", { children: t("integrations.detail.tabs.credentials") })
|
|
935
|
-
] })
|
|
936
|
-
}
|
|
937
|
-
) : null,
|
|
938
|
-
leadingInjectedTab ? /* @__PURE__ */ jsx(
|
|
939
|
-
TabsTrigger,
|
|
940
|
-
{
|
|
941
|
-
value: leadingInjectedTab.id,
|
|
942
|
-
className: "mr-8 h-auto rounded-none border-b-2 border-transparent bg-transparent px-0 py-2.5 text-sm font-medium text-muted-foreground shadow-none transition-colors hover:bg-transparent hover:text-foreground aria-selected:border-accent-indigo aria-selected:bg-transparent aria-selected:text-foreground aria-selected:shadow-none last:mr-0",
|
|
943
|
-
children: /* @__PURE__ */ jsxs("span", { className: "inline-flex items-center gap-2", children: [
|
|
944
|
-
/* @__PURE__ */ jsx(Settings, { className: "h-4 w-4" }),
|
|
945
|
-
/* @__PURE__ */ jsx("span", { children: leadingInjectedTab.label })
|
|
946
|
-
] })
|
|
947
|
-
}
|
|
948
|
-
) : null,
|
|
949
|
-
showVersionTab ? /* @__PURE__ */ jsx(
|
|
950
|
-
TabsTrigger,
|
|
951
|
-
{
|
|
952
|
-
value: "version",
|
|
953
|
-
className: "mr-8 h-auto rounded-none border-b-2 border-transparent bg-transparent px-0 py-2.5 text-sm font-medium text-muted-foreground shadow-none transition-colors hover:bg-transparent hover:text-foreground aria-selected:border-accent-indigo aria-selected:bg-transparent aria-selected:text-foreground aria-selected:shadow-none last:mr-0",
|
|
954
|
-
children: /* @__PURE__ */ jsxs("span", { className: "inline-flex items-center gap-2", children: [
|
|
955
|
-
/* @__PURE__ */ jsx(RefreshCw, { className: "h-4 w-4" }),
|
|
956
|
-
/* @__PURE__ */ jsx("span", { children: t("integrations.detail.tabs.version") })
|
|
957
|
-
] })
|
|
958
|
-
}
|
|
959
|
-
) : null,
|
|
960
|
-
showDataSyncScheduleTab ? /* @__PURE__ */ jsx(
|
|
961
|
-
TabsTrigger,
|
|
962
|
-
{
|
|
963
|
-
value: "data-sync-schedule",
|
|
964
|
-
className: "mr-8 h-auto rounded-none border-b-2 border-transparent bg-transparent px-0 py-2.5 text-sm font-medium text-muted-foreground shadow-none transition-colors hover:bg-transparent hover:text-foreground aria-selected:border-accent-indigo aria-selected:bg-transparent aria-selected:text-foreground aria-selected:shadow-none last:mr-0",
|
|
965
|
-
children: /* @__PURE__ */ jsxs("span", { className: "inline-flex items-center gap-2", children: [
|
|
966
|
-
/* @__PURE__ */ jsx(Calendar, { className: "h-4 w-4" }),
|
|
967
|
-
/* @__PURE__ */ jsx("span", { children: t("data_sync.integrationTab.title", "Sync schedules") })
|
|
968
|
-
] })
|
|
969
|
-
}
|
|
970
|
-
) : null,
|
|
971
|
-
showHealthTab ? /* @__PURE__ */ jsx(
|
|
972
|
-
TabsTrigger,
|
|
973
|
-
{
|
|
974
|
-
value: "health",
|
|
975
|
-
className: "mr-8 h-auto rounded-none border-b-2 border-transparent bg-transparent px-0 py-2.5 text-sm font-medium text-muted-foreground shadow-none transition-colors hover:bg-transparent hover:text-foreground aria-selected:border-accent-indigo aria-selected:bg-transparent aria-selected:text-foreground aria-selected:shadow-none last:mr-0",
|
|
976
|
-
children: /* @__PURE__ */ jsxs("span", { className: "inline-flex items-center gap-2", children: [
|
|
977
|
-
/* @__PURE__ */ jsx(Activity, { className: "h-4 w-4" }),
|
|
978
|
-
/* @__PURE__ */ jsx("span", { children: t("integrations.detail.tabs.health") })
|
|
979
|
-
] })
|
|
980
|
-
}
|
|
981
|
-
) : null,
|
|
982
|
-
showLogsTab ? /* @__PURE__ */ jsx(
|
|
983
|
-
TabsTrigger,
|
|
984
|
-
{
|
|
985
|
-
value: "logs",
|
|
986
|
-
className: "mr-8 h-auto rounded-none border-b-2 border-transparent bg-transparent px-0 py-2.5 text-sm font-medium text-muted-foreground shadow-none transition-colors hover:bg-transparent hover:text-foreground aria-selected:border-accent-indigo aria-selected:bg-transparent aria-selected:text-foreground aria-selected:shadow-none last:mr-0",
|
|
987
|
-
children: /* @__PURE__ */ jsxs("span", { className: "inline-flex items-center gap-2", children: [
|
|
988
|
-
/* @__PURE__ */ jsx(FileText, { className: "h-4 w-4" }),
|
|
989
|
-
/* @__PURE__ */ jsx("span", { children: t("integrations.detail.tabs.logs") })
|
|
990
|
-
] })
|
|
991
|
-
}
|
|
992
|
-
) : null,
|
|
993
|
-
trailingInjectedTabs.map((tab) => /* @__PURE__ */ jsx(
|
|
994
|
-
TabsTrigger,
|
|
995
|
-
{
|
|
996
|
-
value: tab.id,
|
|
997
|
-
className: "mr-8 h-auto rounded-none border-b-2 border-transparent bg-transparent px-0 py-2.5 text-sm font-medium text-muted-foreground shadow-none transition-colors hover:bg-transparent hover:text-foreground aria-selected:border-accent-indigo aria-selected:bg-transparent aria-selected:text-foreground aria-selected:shadow-none last:mr-0",
|
|
998
|
-
children: /* @__PURE__ */ jsxs("span", { className: "inline-flex items-center gap-2", children: [
|
|
999
|
-
/* @__PURE__ */ jsx(Settings, { className: "h-4 w-4" }),
|
|
1000
|
-
/* @__PURE__ */ jsx("span", { children: tab.label })
|
|
1001
|
-
] })
|
|
1002
|
-
},
|
|
1003
|
-
tab.id
|
|
1004
|
-
))
|
|
925
|
+
/* @__PURE__ */ jsxs(Tabs, { value: activeTab, onValueChange: handleTabChange, variant: "underline", className: "space-y-5", children: [
|
|
926
|
+
/* @__PURE__ */ jsxs(TabsList, { className: "w-full overflow-x-auto", children: [
|
|
927
|
+
showCredentialsTab ? /* @__PURE__ */ jsx(TabsTrigger, { value: "credentials", leading: /* @__PURE__ */ jsx(Key, { className: "h-4 w-4" }), children: t("integrations.detail.tabs.credentials") }) : null,
|
|
928
|
+
leadingInjectedTab ? /* @__PURE__ */ jsx(TabsTrigger, { value: leadingInjectedTab.id, leading: /* @__PURE__ */ jsx(Settings, { className: "h-4 w-4" }), children: leadingInjectedTab.label }) : null,
|
|
929
|
+
showVersionTab ? /* @__PURE__ */ jsx(TabsTrigger, { value: "version", leading: /* @__PURE__ */ jsx(RefreshCw, { className: "h-4 w-4" }), children: t("integrations.detail.tabs.version") }) : null,
|
|
930
|
+
showDataSyncScheduleTab ? /* @__PURE__ */ jsx(TabsTrigger, { value: "data-sync-schedule", leading: /* @__PURE__ */ jsx(Calendar, { className: "h-4 w-4" }), children: t("data_sync.integrationTab.title", "Sync schedules") }) : null,
|
|
931
|
+
showHealthTab ? /* @__PURE__ */ jsx(TabsTrigger, { value: "health", leading: /* @__PURE__ */ jsx(Activity, { className: "h-4 w-4" }), children: t("integrations.detail.tabs.health") }) : null,
|
|
932
|
+
showLogsTab ? /* @__PURE__ */ jsx(TabsTrigger, { value: "logs", leading: /* @__PURE__ */ jsx(FileText, { className: "h-4 w-4" }), children: t("integrations.detail.tabs.logs") }) : null,
|
|
933
|
+
trailingInjectedTabs.map((tab) => /* @__PURE__ */ jsx(TabsTrigger, { value: tab.id, leading: /* @__PURE__ */ jsx(Settings, { className: "h-4 w-4" }), children: tab.label }, tab.id))
|
|
1005
934
|
] }),
|
|
1006
935
|
showCredentialsTab ? /* @__PURE__ */ jsx(TabsContent, { value: "credentials", className: "mt-0", children: /* @__PURE__ */ jsxs("section", { className: "space-y-4 rounded-lg border bg-card p-6", children: [
|
|
1007
936
|
detail.bundle ? /* @__PURE__ */ jsx("div", { className: "rounded-lg border border-status-info-border bg-status-info-bg p-3 text-sm text-status-info-text", children: t("integrations.detail.credentials.bundleShared", { bundle: detail.bundle.title }) }) : null,
|