@open-mercato/core 0.10.1-develop.8004.1.a8a79ee43f → 0.10.1-develop.8022.1.b6753de892
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 +1 -1
- package/dist/modules/audit_logs/components/AuditLogsActions.js +80 -50
- package/dist/modules/audit_logs/components/AuditLogsActions.js.map +3 -3
- package/dist/modules/audit_logs/lib/rowPresentation.js +82 -0
- package/dist/modules/audit_logs/lib/rowPresentation.js.map +7 -0
- package/dist/modules/catalog/commands/variants.js +89 -16
- package/dist/modules/catalog/commands/variants.js.map +2 -2
- package/dist/modules/catalog/seed/examples.js +7 -0
- package/dist/modules/catalog/seed/examples.js.map +2 -2
- package/dist/modules/customers/api/interactions/route.js +2 -2
- package/dist/modules/customers/api/interactions/route.js.map +2 -2
- package/dist/modules/customers/components/detail/AssignRoleDialog.js +10 -21
- package/dist/modules/customers/components/detail/AssignRoleDialog.js.map +2 -2
- package/dist/modules/customers/migrations/Migration20260825140000_customers.js +17 -10
- package/dist/modules/customers/migrations/Migration20260825140000_customers.js.map +2 -2
- package/dist/modules/entities/cli.js +138 -66
- package/dist/modules/entities/cli.js.map +3 -3
- package/dist/modules/promotions/commands/codes.js +18 -3
- package/dist/modules/promotions/commands/codes.js.map +2 -2
- package/dist/modules/query_index/cli.js +17 -1
- package/dist/modules/query_index/cli.js.map +2 -2
- package/dist/modules/query_index/lib/reindexer.js +23 -5
- package/dist/modules/query_index/lib/reindexer.js.map +2 -2
- package/dist/modules/sales/commands/configuration.js +30 -16
- package/dist/modules/sales/commands/configuration.js.map +2 -2
- package/dist/modules/sales/components/documents/AddressesSection.js +36 -15
- package/dist/modules/sales/components/documents/AddressesSection.js.map +2 -2
- package/dist/modules/sales/seed/examples.js +35 -6
- package/dist/modules/sales/seed/examples.js.map +2 -2
- package/package.json +7 -7
- package/src/modules/audit_logs/components/AuditLogsActions.tsx +85 -48
- package/src/modules/audit_logs/i18n/de.json +16 -0
- package/src/modules/audit_logs/i18n/en.json +16 -0
- package/src/modules/audit_logs/i18n/es.json +16 -0
- package/src/modules/audit_logs/i18n/ko.json +16 -0
- package/src/modules/audit_logs/i18n/pl.json +16 -0
- package/src/modules/audit_logs/lib/rowPresentation.ts +92 -0
- package/src/modules/catalog/commands/variants.ts +96 -17
- package/src/modules/catalog/seed/examples.ts +7 -0
- package/src/modules/customers/api/interactions/route.ts +2 -2
- package/src/modules/customers/components/detail/AssignRoleDialog.tsx +9 -12
- package/src/modules/customers/i18n/de.json +2 -1
- package/src/modules/customers/i18n/en.json +2 -1
- package/src/modules/customers/i18n/es.json +2 -1
- package/src/modules/customers/i18n/ko.json +2 -1
- package/src/modules/customers/i18n/pl.json +2 -1
- package/src/modules/customers/migrations/Migration20260825140000_customers.ts +21 -10
- package/src/modules/entities/cli.ts +144 -65
- package/src/modules/promotions/commands/codes.ts +19 -4
- package/src/modules/query_index/cli.ts +17 -1
- package/src/modules/query_index/lib/reindexer.ts +55 -6
- package/src/modules/sales/commands/configuration.ts +35 -16
- package/src/modules/sales/components/documents/AddressesSection.tsx +51 -20
- package/src/modules/sales/i18n/de.json +3 -0
- package/src/modules/sales/i18n/en.json +3 -0
- package/src/modules/sales/i18n/es.json +3 -0
- package/src/modules/sales/i18n/ko.json +3 -0
- package/src/modules/sales/i18n/pl.json +4 -1
- package/src/modules/sales/seed/examples.ts +41 -6
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/modules/promotions/commands/codes.ts"],
|
|
4
|
-
"sourcesContent": ["import { z } from 'zod'\nimport { registerCommand } from '@open-mercato/shared/lib/commands'\nimport type { CommandHandler, CommandRuntimeContext } from '@open-mercato/shared/lib/commands'\nimport { emitCrudSideEffects, emitCrudUndoSideEffects } from '@open-mercato/shared/lib/commands/helpers'\nimport { withAtomicFlush } from '@open-mercato/shared/lib/commands/flush'\nimport { runCrudCommandWrite } from '@open-mercato/shared/lib/commands/runCrudCommandWrite'\nimport { ensureOrganizationScope, ensureTenantScope } from '@open-mercato/shared/lib/commands/scope'\nimport { extractUndoPayload } from '@open-mercato/shared/lib/commands/undo'\nimport type { DataEngine } from '@open-mercato/shared/lib/data/engine'\nimport { CrudHttpError, notFound } from '@open-mercato/shared/lib/crud/errors'\nimport type { CrudEventsConfig, CrudIndexerConfig } from '@open-mercato/shared/lib/crud/types'\nimport { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'\nimport { createLogger } from '@open-mercato/shared/lib/logger'\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport { E } from '#generated/entities.ids.generated'\nimport {\n Code,\n GeneratedCode,\n type PromotionCodeType,\n type PromotionCodeUsageMode,\n} from '../data/entities'\nimport { assertPromotionScopeOrNotFound } from './shared'\nimport {\n codeReservationReleaseSchema,\n codeReserveInputSchema,\n codeUseInputSchema,\n promotionCodeCreateSchema,\n promotionCodeUpdateSchema,\n promotionCodeDeleteSchema,\n type PromotionCodeCreateInput,\n type PromotionCodeUpdateInput,\n type PromotionCodeDeleteInput,\n} from '../data/validators'\nimport { PromotionCodeService, type PromotionsCodeScope } from '../lib/code-service'\nimport type { PromotionCodeGenerationService } from '../services/code-generation'\nimport type { CodeReservationResult, CodeUseResult } from '../lib/types'\n\nconst codesLogger = createLogger('promotions').child({ component: 'code-commands' })\n\n// SPEC-055 \u00A7Amendment A.2a: `reserveCode`, `releaseCode` and `useCode` are \"financially\n// or budget consequential writes\" and go through the command pattern the same as\n// `Promotion`/`Code` CRUD. `validateCode`/`extendReservation` are deliberately NOT here\n// \u2014 \u00A7A.2a names exactly five commands for the whole of Phase 3\n// (`reserve`/`release`/`use`/`usage.register`/`usage.revert`; the last two are Step\n// 6.3's), and the spec explicitly calls `validateCode`/`extendReservation` plain\n// reads/housekeeping with no mutation to command-wrap.\n//\n// Each command wraps `lib/code-service.ts`'s `PromotionCodeService` \u2014 the actual\n// resolution/locking/transaction logic lives there (\u00A7Code Lifecycle,\n// \u00A7Promotion Usage Lifecycle's row-lock correction applied to `codes/use`); this file\n// only resolves the command-runtime scope/EntityManager and dispatches to it, same split\n// as `commands/promotions.ts`'s thin command bodies around `data/validators.ts` schemas.\n\n// Mirrors `commands/promotions.ts`'s `resolveActorScope` \u2014 a code operation's\n// tenant/organization scope is always the caller's own actor scope (never a\n// client-supplied value), resolved from `ctx.auth`/`ctx.selectedOrganizationId`.\nfunction resolveActorScope(ctx: CommandRuntimeContext): PromotionsCodeScope {\n const tenantId = ctx.auth?.tenantId ?? null\n const organizationId = ctx.selectedOrganizationId ?? ctx.auth?.orgId ?? null\n if (!tenantId || !organizationId) {\n throw new CrudHttpError(400, {\n error: '[internal] Tenant and organization scope are required for a promotion code operation',\n })\n }\n ensureTenantScope(ctx, tenantId)\n ensureOrganizationScope(ctx, organizationId)\n return { tenantId, organizationId }\n}\n\n// `ctx.transactionalEm`, when set, is an already-open (possibly ambient \u2014 e.g.\n// `checkout`'s own) transaction this command MUST reuse rather than opening its own\n// (\u00A7Promotion Usage Lifecycle's row-lock correction depends on this for `codes/use`:\n// locking inside the SAME transaction as the caller is what makes the lock effective\n// whether the call is top-level or nested). Otherwise fork the request `em`, same\n// precedent as every other command in this module.\nfunction resolveCommandEm(ctx: CommandRuntimeContext): EntityManager {\n return ctx.transactionalEm ?? (ctx.container.resolve('em') as EntityManager).fork()\n}\n\nfunction resolveCodeService(ctx: CommandRuntimeContext): PromotionCodeService {\n return ctx.container.resolve('promotionCodeService') as PromotionCodeService\n}\n\nconst reserveCodeCommand: CommandHandler<unknown, CodeReservationResult> = {\n id: 'promotions.code.reserve',\n async execute(rawInput, ctx) {\n const parsed = codeReserveInputSchema.parse(rawInput)\n const scope = resolveActorScope(ctx)\n const em = resolveCommandEm(ctx)\n return resolveCodeService(ctx).reserveCode(em, parsed, scope)\n },\n}\n\nconst releaseCodeCommand: CommandHandler<unknown, { ok: true }> = {\n id: 'promotions.code.release',\n async execute(rawInput, ctx) {\n const parsed = codeReservationReleaseSchema.parse(rawInput)\n const scope = resolveActorScope(ctx)\n const em = resolveCommandEm(ctx)\n await resolveCodeService(ctx).releaseCode(em, parsed.codeId, parsed.cartId, scope)\n return { ok: true }\n },\n}\n\nconst useCodeCommand: CommandHandler<unknown, CodeUseResult> = {\n id: 'promotions.code.use',\n async execute(rawInput, ctx) {\n const parsed = codeUseInputSchema.parse(rawInput)\n const scope = resolveActorScope(ctx)\n const em = resolveCommandEm(ctx)\n return resolveCodeService(ctx).useCode(em, parsed, scope)\n },\n}\n\n// ---------------------------------------------------------------------------\n// Code CRUD (\u00A7Implementation Plan Phase 3 Step 3 \"commands/codes.ts \u2014 code CRUD with\n// undo, events\" \u2014 not built by Step 6.2, which only covered the reserve/release/use\n// commands above; Release 4 PLAN.md Step 6.4 closes that gap since `api/codes/route.ts`\n// needs it). Mirrors `commands/promotions.ts`'s create/update/delete shape exactly \u2014\n// command-driven writes, `runCrudCommandWrite`/`withAtomicFlush` for atomicity,\n// `emitCrudSideEffects`/`emitCrudUndoSideEffects` wired to the already-declared\n// `promotions.code.created/updated/deleted` events (`events.ts`) \u2014 so `api/codes/route.ts`\n// can follow `api/route.ts`'s own `makeCrudRoute` template literally.\n// ---------------------------------------------------------------------------\n\nconst CODE_ENTITY_ID = E.promotions.code\n\nconst codeCrudIndexer: CrudIndexerConfig<Code> = {\n entityType: CODE_ENTITY_ID,\n}\n\nconst codeCrudEvents: CrudEventsConfig<Code> = {\n module: 'promotions',\n entity: 'code',\n persistent: true,\n buildPayload: (ctx) => ({\n id: ctx.identifiers.id,\n organizationId: ctx.identifiers.organizationId,\n tenantId: ctx.identifiers.tenantId,\n }),\n}\n\nconst codeCommandOutputSchema = z.object({ codeId: z.string().uuid() })\n\ntype CodeSnapshot = {\n id: string\n organizationId: string\n tenantId: string\n name: string\n type: PromotionCodeType\n code: string | null\n prefix: string | null\n suffix: string | null\n length: number | null\n amount: number | null\n generated: number\n used: number\n usage: PromotionCodeUsageMode\n usageAmount: number | null\n usagePerCustomer: number | null\n active: boolean\n updatedAt: string\n}\n\n// Delete-only extension of `CodeSnapshot` (rev \u2014 the generic `prepare()` return type is\n// `{ before?: unknown }`, so any extra data a specific command's undo needs must live\n// INSIDE the snapshot object itself, not as a sibling key \u2014 see\n// `@open-mercato/shared/lib/commands/types.ts`'s `CommandLogBuilderArgs.snapshots` shape).\ntype CodeDeleteSnapshot = CodeSnapshot & { activeGeneratedCodeIds: string[] }\n\ntype CodeUndoPayload = {\n before?: CodeSnapshot | CodeDeleteSnapshot | null\n after?: CodeSnapshot | null\n}\n\nfunction toCodeSnapshot(code: Code): CodeSnapshot {\n return {\n id: code.id,\n organizationId: code.organizationId,\n tenantId: code.tenantId,\n name: code.name,\n type: code.type,\n code: code.code ?? null,\n prefix: code.prefix ?? null,\n suffix: code.suffix ?? null,\n length: code.length ?? null,\n amount: code.amount ?? null,\n generated: code.generated,\n used: code.used,\n usage: code.usage,\n usageAmount: code.usageAmount ?? null,\n usagePerCustomer: code.usagePerCustomer ?? null,\n active: code.active,\n updatedAt: code.updatedAt.toISOString(),\n }\n}\n\nfunction getCodeIdentifiers(code: Code) {\n return { id: code.id, organizationId: code.organizationId, tenantId: code.tenantId }\n}\n\nasync function loadCode(em: EntityManager, id: string): Promise<Code | null> {\n return em.findOne(Code, { id, deletedAt: null })\n}\n\n// Mirrors `commands/promotions.ts`'s `resolveActorScope` \u2014 a new code's scope is always\n// the caller's own actor scope, never a client-supplied value.\nfunction resolveCodeActorScope(ctx: CommandRuntimeContext): PromotionsCodeScope {\n const tenantId = ctx.auth?.tenantId ?? null\n const organizationId = ctx.selectedOrganizationId ?? ctx.auth?.orgId ?? null\n if (!tenantId || !organizationId) {\n throw new CrudHttpError(400, {\n error: '[internal] Tenant and organization scope are required to create a promotion code',\n })\n }\n return { tenantId, organizationId }\n}\n\nconst createCodeCommand: CommandHandler<PromotionCodeCreateInput, { codeId: string }> = {\n id: 'promotions.code.create',\n outputSchema: codeCommandOutputSchema,\n async execute(rawInput, ctx) {\n const parsed = promotionCodeCreateSchema.parse(rawInput)\n const scope = resolveCodeActorScope(ctx)\n ensureTenantScope(ctx, scope.tenantId)\n ensureOrganizationScope(ctx, scope.organizationId)\n\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const code = em.create(Code, {\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n name: parsed.name,\n type: parsed.type,\n code: parsed.code ?? null,\n prefix: parsed.prefix ?? null,\n suffix: parsed.suffix ?? null,\n length: parsed.length ?? null,\n amount: parsed.amount ?? null,\n usage: parsed.usage,\n usageAmount: parsed.usageAmount ?? null,\n usagePerCustomer: parsed.usagePerCustomer ?? null,\n active: parsed.active,\n })\n em.persist(code)\n await em.flush()\n\n const dataEngine = ctx.container.resolve('dataEngine') as DataEngine\n await emitCrudSideEffects({\n dataEngine,\n action: 'created',\n entity: code,\n identifiers: getCodeIdentifiers(code),\n events: codeCrudEvents,\n indexer: codeCrudIndexer,\n })\n\n // \u00A7API Contracts `POST /api/promotions/codes`: \"for dynamic type, triggers\n // generation worker.\" Fired after the row has committed and its CRUD side effects\n // ran \u2014 a transient enqueue failure must not fail the create itself; the admin can\n // retry generation via `POST /codes/[id]/generate`.\n if (code.type === 'dynamic') {\n try {\n const generationService = ctx.container.resolve('promotionCodeGenerationService') as PromotionCodeGenerationService\n await generationService.triggerGeneration(code.id, scope)\n } catch (err) {\n codesLogger.warn('[internal] promotions.code.create failed to trigger code generation', { codeId: code.id, err })\n }\n }\n\n return { codeId: code.id }\n },\n captureAfter: async (_input, result, ctx) => {\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const code = await loadCode(em, result.codeId)\n return code ? toCodeSnapshot(code) : null\n },\n buildLog: async ({ result, snapshots }) => {\n const { translate } = await resolveTranslations()\n const after = snapshots.after as CodeSnapshot | undefined\n return {\n actionLabel: translate('promotions.audit.code.create', 'Create promotional code'),\n resourceKind: 'promotions.code',\n resourceId: result.codeId,\n tenantId: after?.tenantId ?? null,\n organizationId: after?.organizationId ?? null,\n snapshotAfter: after ?? null,\n payload: {\n undo: { after: after ?? null } satisfies CodeUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<CodeUndoPayload>(logEntry)\n const after = payload?.after\n if (!after) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const code = await em.findOne(Code, { id: after.id })\n if (!code) return\n\n // `promotion_generated_codes.code_id` carries `ON DELETE CASCADE` (\u00A7Data Models), so\n // removing the Code row also removes every generated code minted for it.\n em.remove(code)\n await em.flush()\n\n const dataEngine = ctx.container.resolve('dataEngine') as DataEngine\n await emitCrudUndoSideEffects({\n dataEngine,\n action: 'deleted',\n entity: code,\n identifiers: getCodeIdentifiers(code),\n events: codeCrudEvents,\n indexer: codeCrudIndexer,\n })\n },\n}\n\nconst updateCodeCommand: CommandHandler<PromotionCodeUpdateInput, { codeId: string }> = {\n id: 'promotions.code.update',\n outputSchema: codeCommandOutputSchema,\n async prepare(rawInput, ctx) {\n const parsed = promotionCodeUpdateSchema.parse(rawInput)\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const code = await loadCode(em, parsed.id)\n return code ? { before: toCodeSnapshot(code) } : null\n },\n async execute(rawInput, ctx) {\n const parsed = promotionCodeUpdateSchema.parse(rawInput)\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const code = await loadCode(em, parsed.id)\n if (!code) throw notFound('Promotion code not found')\n assertPromotionScopeOrNotFound(ctx, code)\n\n await runCrudCommandWrite({\n ctx,\n em,\n entityId: CODE_ENTITY_ID,\n action: 'updated',\n scope: { tenantId: code.tenantId, organizationId: code.organizationId },\n events: codeCrudEvents,\n indexer: codeCrudIndexer,\n sideEffect: () => ({\n entity: code,\n identifiers: getCodeIdentifiers(code),\n }),\n phases: [\n () => {\n if (parsed.name !== undefined) code.name = parsed.name\n if (parsed.type !== undefined) code.type = parsed.type\n if (parsed.code !== undefined) code.code = parsed.code ?? null\n if (parsed.prefix !== undefined) code.prefix = parsed.prefix ?? null\n if (parsed.suffix !== undefined) code.suffix = parsed.suffix ?? null\n if (parsed.length !== undefined) code.length = parsed.length ?? null\n if (parsed.amount !== undefined) code.amount = parsed.amount ?? null\n if (parsed.usage !== undefined) code.usage = parsed.usage\n if (parsed.usageAmount !== undefined) code.usageAmount = parsed.usageAmount ?? null\n if (parsed.usagePerCustomer !== undefined) code.usagePerCustomer = parsed.usagePerCustomer ?? null\n if (parsed.active !== undefined) code.active = parsed.active\n },\n ],\n })\n\n return { codeId: code.id }\n },\n captureAfter: async (_input, result, ctx) => {\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const code = await loadCode(em, result.codeId)\n return code ? toCodeSnapshot(code) : null\n },\n buildLog: async ({ result, snapshots, ctx }) => {\n const before = snapshots.before as CodeSnapshot | undefined\n if (!before) return null\n const { translate } = await resolveTranslations()\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const code = await loadCode(em, result.codeId)\n const after = code ? toCodeSnapshot(code) : null\n return {\n actionLabel: translate('promotions.audit.code.update', 'Update promotional code'),\n resourceKind: 'promotions.code',\n resourceId: before.id,\n tenantId: before.tenantId,\n organizationId: before.organizationId,\n snapshotBefore: before,\n snapshotAfter: after,\n payload: {\n undo: { before, after } satisfies CodeUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<CodeUndoPayload>(logEntry)\n const before = payload?.before\n if (!before) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const code = await em.findOne(Code, { id: before.id })\n if (!code) return\n\n await withAtomicFlush(\n em,\n [\n () => {\n code.name = before.name\n code.type = before.type\n code.code = before.code\n code.prefix = before.prefix\n code.suffix = before.suffix\n code.length = before.length\n code.amount = before.amount\n code.usage = before.usage\n code.usageAmount = before.usageAmount\n code.usagePerCustomer = before.usagePerCustomer\n code.active = before.active\n },\n ],\n { transaction: true, label: 'promotions.code.update.undo' },\n )\n\n const dataEngine = ctx.container.resolve('dataEngine') as DataEngine\n await emitCrudUndoSideEffects({\n dataEngine,\n action: 'updated',\n entity: code,\n identifiers: getCodeIdentifiers(code),\n events: codeCrudEvents,\n indexer: codeCrudIndexer,\n })\n },\n}\n\nconst deleteCodeCommand: CommandHandler<PromotionCodeDeleteInput, { codeId: string }> = {\n id: 'promotions.code.delete',\n outputSchema: codeCommandOutputSchema,\n async prepare(rawInput, ctx) {\n const parsed = promotionCodeDeleteSchema.parse(rawInput)\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const code = await loadCode(em, parsed.id)\n if (!code) return null\n // \u00A7API Contracts `DELETE /api/promotions/codes`: \"deactivates generated codes.\"\n // Captured here, before the mutation, so undo restores EXACTLY the rows THIS delete\n // deactivated \u2014 not every generated row for the code, some of which may already be\n // inactive for an unrelated reason (e.g. `codes/use` spending them).\n const activeGeneratedCodeIds = (\n await em.find(GeneratedCode, {\n codeId: code.id,\n tenantId: code.tenantId,\n organizationId: code.organizationId,\n active: true,\n })\n ).map((row) => row.id)\n return { before: { ...toCodeSnapshot(code), activeGeneratedCodeIds } satisfies CodeDeleteSnapshot }\n },\n async execute(rawInput, ctx) {\n const parsed = promotionCodeDeleteSchema.parse(rawInput)\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const code = await loadCode(em, parsed.id)\n if (!code) throw notFound('Promotion code not found')\n assertPromotionScopeOrNotFound(ctx, code)\n\n // \u00A7Data Models / \u00A7API Contracts: soft-delete the `Code` row AND explicitly\n // deactivate its already-generated codes. Decision (documented, not left implicit):\n // `resolveCodeByString`'s parent-code lookup already filters `deletedAt: null`, so a\n // soft-deleted code's generated rows are unreachable through the normal resolution\n // path regardless of this flag \u2014 but the explicit flip keeps the admin UI's own\n // generated-codes panel accurate and matches `codes/use`'s identical `active`\n // semantics, rather than relying on that implicit effect alone.\n await withAtomicFlush(\n em,\n [\n () => {\n code.deletedAt = new Date()\n },\n async () => {\n await em.nativeUpdate(\n GeneratedCode,\n { codeId: code.id, tenantId: code.tenantId, organizationId: code.organizationId },\n { active: false },\n )\n },\n ],\n { transaction: true, label: 'promotions.code.delete' },\n )\n\n const dataEngine = ctx.container.resolve('dataEngine') as DataEngine\n await emitCrudSideEffects({\n dataEngine,\n action: 'deleted',\n entity: code,\n identifiers: getCodeIdentifiers(code),\n events: codeCrudEvents,\n indexer: codeCrudIndexer,\n })\n\n return { codeId: code.id }\n },\n buildLog: async ({ snapshots }) => {\n const before = snapshots.before as CodeDeleteSnapshot | undefined\n if (!before) return null\n const { translate } = await resolveTranslations()\n return {\n actionLabel: translate('promotions.audit.code.delete', 'Delete promotional code'),\n resourceKind: 'promotions.code',\n resourceId: before.id,\n tenantId: before.tenantId,\n organizationId: before.organizationId,\n snapshotBefore: before,\n payload: {\n undo: { before } satisfies CodeUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<CodeUndoPayload>(logEntry)\n const before = payload?.before as CodeDeleteSnapshot | undefined\n if (!before) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const code = await em.findOne(Code, { id: before.id })\n if (!code) return\n\n await withAtomicFlush(\n em,\n [\n () => {\n code.deletedAt = null\n },\n async () => {\n if (before.activeGeneratedCodeIds.length) {\n await em.nativeUpdate(GeneratedCode, { id: { $in: before.activeGeneratedCodeIds } }, { active: true })\n }\n },\n ],\n { transaction: true, label: 'promotions.code.delete.undo' },\n )\n\n const dataEngine = ctx.container.resolve('dataEngine') as DataEngine\n await emitCrudUndoSideEffects({\n dataEngine,\n // Restoring a soft-deleted row re-adds it to the index/cache \u2014 same semantics as\n // `created` on the forward path (mirrors `commands/promotions.ts`'s delete undo).\n action: 'created',\n entity: code,\n identifiers: getCodeIdentifiers(code),\n events: codeCrudEvents,\n indexer: codeCrudIndexer,\n })\n },\n}\n\nregisterCommand(reserveCodeCommand)\nregisterCommand(releaseCodeCommand)\nregisterCommand(useCodeCommand)\nregisterCommand(createCodeCommand)\nregisterCommand(updateCodeCommand)\nregisterCommand(deleteCodeCommand)\n\nexport {\n reserveCodeCommand,\n releaseCodeCommand,\n useCodeCommand,\n createCodeCommand,\n updateCodeCommand,\n deleteCodeCommand,\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["import { z } from 'zod'\nimport { registerCommand } from '@open-mercato/shared/lib/commands'\nimport type { CommandHandler, CommandRuntimeContext } from '@open-mercato/shared/lib/commands'\nimport { emitCrudSideEffects, emitCrudUndoSideEffects } from '@open-mercato/shared/lib/commands/helpers'\nimport { withAtomicFlush } from '@open-mercato/shared/lib/commands/flush'\nimport { runCrudCommandWrite } from '@open-mercato/shared/lib/commands/runCrudCommandWrite'\nimport { ensureOrganizationScope, ensureTenantScope } from '@open-mercato/shared/lib/commands/scope'\nimport { extractUndoPayload } from '@open-mercato/shared/lib/commands/undo'\nimport type { DataEngine } from '@open-mercato/shared/lib/data/engine'\nimport { CrudHttpError, notFound } from '@open-mercato/shared/lib/crud/errors'\nimport type { CrudEventsConfig, CrudIndexerConfig } from '@open-mercato/shared/lib/crud/types'\nimport { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'\nimport { createLogger } from '@open-mercato/shared/lib/logger'\nimport { LockMode } from '@mikro-orm/core'\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport { E } from '#generated/entities.ids.generated'\nimport {\n Code,\n GeneratedCode,\n type PromotionCodeType,\n type PromotionCodeUsageMode,\n} from '../data/entities'\nimport { assertPromotionScopeOrNotFound } from './shared'\nimport {\n codeReservationReleaseSchema,\n codeReserveInputSchema,\n codeUseInputSchema,\n promotionCodeCreateSchema,\n promotionCodeUpdateSchema,\n promotionCodeDeleteSchema,\n type PromotionCodeCreateInput,\n type PromotionCodeUpdateInput,\n type PromotionCodeDeleteInput,\n} from '../data/validators'\nimport { PromotionCodeService, hasRemainingGlobalUses, type PromotionsCodeScope } from '../lib/code-service'\nimport type { PromotionCodeGenerationService } from '../services/code-generation'\nimport type { CodeReservationResult, CodeUseResult } from '../lib/types'\n\nconst codesLogger = createLogger('promotions').child({ component: 'code-commands' })\n\n// SPEC-055 \u00A7Amendment A.2a: `reserveCode`, `releaseCode` and `useCode` are \"financially\n// or budget consequential writes\" and go through the command pattern the same as\n// `Promotion`/`Code` CRUD. `validateCode`/`extendReservation` are deliberately NOT here\n// \u2014 \u00A7A.2a names exactly five commands for the whole of Phase 3\n// (`reserve`/`release`/`use`/`usage.register`/`usage.revert`; the last two are Step\n// 6.3's), and the spec explicitly calls `validateCode`/`extendReservation` plain\n// reads/housekeeping with no mutation to command-wrap.\n//\n// Each command wraps `lib/code-service.ts`'s `PromotionCodeService` \u2014 the actual\n// resolution/locking/transaction logic lives there (\u00A7Code Lifecycle,\n// \u00A7Promotion Usage Lifecycle's row-lock correction applied to `codes/use`); this file\n// only resolves the command-runtime scope/EntityManager and dispatches to it, same split\n// as `commands/promotions.ts`'s thin command bodies around `data/validators.ts` schemas.\n\n// Mirrors `commands/promotions.ts`'s `resolveActorScope` \u2014 a code operation's\n// tenant/organization scope is always the caller's own actor scope (never a\n// client-supplied value), resolved from `ctx.auth`/`ctx.selectedOrganizationId`.\nfunction resolveActorScope(ctx: CommandRuntimeContext): PromotionsCodeScope {\n const tenantId = ctx.auth?.tenantId ?? null\n const organizationId = ctx.selectedOrganizationId ?? ctx.auth?.orgId ?? null\n if (!tenantId || !organizationId) {\n throw new CrudHttpError(400, {\n error: '[internal] Tenant and organization scope are required for a promotion code operation',\n })\n }\n ensureTenantScope(ctx, tenantId)\n ensureOrganizationScope(ctx, organizationId)\n return { tenantId, organizationId }\n}\n\n// `ctx.transactionalEm`, when set, is an already-open (possibly ambient \u2014 e.g.\n// `checkout`'s own) transaction this command MUST reuse rather than opening its own\n// (\u00A7Promotion Usage Lifecycle's row-lock correction depends on this for `codes/use`:\n// locking inside the SAME transaction as the caller is what makes the lock effective\n// whether the call is top-level or nested). Otherwise fork the request `em`, same\n// precedent as every other command in this module.\nfunction resolveCommandEm(ctx: CommandRuntimeContext): EntityManager {\n return ctx.transactionalEm ?? (ctx.container.resolve('em') as EntityManager).fork()\n}\n\nfunction resolveCodeService(ctx: CommandRuntimeContext): PromotionCodeService {\n return ctx.container.resolve('promotionCodeService') as PromotionCodeService\n}\n\nconst reserveCodeCommand: CommandHandler<unknown, CodeReservationResult> = {\n id: 'promotions.code.reserve',\n async execute(rawInput, ctx) {\n const parsed = codeReserveInputSchema.parse(rawInput)\n const scope = resolveActorScope(ctx)\n const em = resolveCommandEm(ctx)\n return resolveCodeService(ctx).reserveCode(em, parsed, scope)\n },\n}\n\nconst releaseCodeCommand: CommandHandler<unknown, { ok: true }> = {\n id: 'promotions.code.release',\n async execute(rawInput, ctx) {\n const parsed = codeReservationReleaseSchema.parse(rawInput)\n const scope = resolveActorScope(ctx)\n const em = resolveCommandEm(ctx)\n await resolveCodeService(ctx).releaseCode(em, parsed.codeId, parsed.cartId, scope)\n return { ok: true }\n },\n}\n\nconst useCodeCommand: CommandHandler<unknown, CodeUseResult> = {\n id: 'promotions.code.use',\n async execute(rawInput, ctx) {\n const parsed = codeUseInputSchema.parse(rawInput)\n const scope = resolveActorScope(ctx)\n const em = resolveCommandEm(ctx)\n return resolveCodeService(ctx).useCode(em, parsed, scope)\n },\n}\n\n// ---------------------------------------------------------------------------\n// Code CRUD (\u00A7Implementation Plan Phase 3 Step 3 \"commands/codes.ts \u2014 code CRUD with\n// undo, events\" \u2014 not built by Step 6.2, which only covered the reserve/release/use\n// commands above; Release 4 PLAN.md Step 6.4 closes that gap since `api/codes/route.ts`\n// needs it). Mirrors `commands/promotions.ts`'s create/update/delete shape exactly \u2014\n// command-driven writes, `runCrudCommandWrite`/`withAtomicFlush` for atomicity,\n// `emitCrudSideEffects`/`emitCrudUndoSideEffects` wired to the already-declared\n// `promotions.code.created/updated/deleted` events (`events.ts`) \u2014 so `api/codes/route.ts`\n// can follow `api/route.ts`'s own `makeCrudRoute` template literally.\n// ---------------------------------------------------------------------------\n\nconst CODE_ENTITY_ID = E.promotions.code\n\nconst codeCrudIndexer: CrudIndexerConfig<Code> = {\n entityType: CODE_ENTITY_ID,\n}\n\nconst codeCrudEvents: CrudEventsConfig<Code> = {\n module: 'promotions',\n entity: 'code',\n persistent: true,\n buildPayload: (ctx) => ({\n id: ctx.identifiers.id,\n organizationId: ctx.identifiers.organizationId,\n tenantId: ctx.identifiers.tenantId,\n }),\n}\n\nconst codeCommandOutputSchema = z.object({ codeId: z.string().uuid() })\n\ntype CodeSnapshot = {\n id: string\n organizationId: string\n tenantId: string\n name: string\n type: PromotionCodeType\n code: string | null\n prefix: string | null\n suffix: string | null\n length: number | null\n amount: number | null\n generated: number\n used: number\n usage: PromotionCodeUsageMode\n usageAmount: number | null\n usagePerCustomer: number | null\n active: boolean\n updatedAt: string\n}\n\n// Delete-only extension of `CodeSnapshot` (rev \u2014 the generic `prepare()` return type is\n// `{ before?: unknown }`, so any extra data a specific command's undo needs must live\n// INSIDE the snapshot object itself, not as a sibling key \u2014 see\n// `@open-mercato/shared/lib/commands/types.ts`'s `CommandLogBuilderArgs.snapshots` shape).\ntype CodeDeleteSnapshot = CodeSnapshot & { activeGeneratedCodeIds: string[] }\n\ntype CodeUndoPayload = {\n before?: CodeSnapshot | CodeDeleteSnapshot | null\n after?: CodeSnapshot | null\n}\n\nfunction toCodeSnapshot(code: Code): CodeSnapshot {\n return {\n id: code.id,\n organizationId: code.organizationId,\n tenantId: code.tenantId,\n name: code.name,\n type: code.type,\n code: code.code ?? null,\n prefix: code.prefix ?? null,\n suffix: code.suffix ?? null,\n length: code.length ?? null,\n amount: code.amount ?? null,\n generated: code.generated,\n used: code.used,\n usage: code.usage,\n usageAmount: code.usageAmount ?? null,\n usagePerCustomer: code.usagePerCustomer ?? null,\n active: code.active,\n updatedAt: code.updatedAt.toISOString(),\n }\n}\n\nfunction getCodeIdentifiers(code: Code) {\n return { id: code.id, organizationId: code.organizationId, tenantId: code.tenantId }\n}\n\nasync function loadCode(em: EntityManager, id: string): Promise<Code | null> {\n return em.findOne(Code, { id, deletedAt: null })\n}\n\nfunction resolveUndoActiveFlag(code: Code, before: CodeSnapshot): boolean {\n if (!before.active || code.type !== 'static') return before.active\n const redeemedSinceUpdate = code.used > before.used\n return !redeemedSinceUpdate || hasRemainingGlobalUses(code)\n}\n\n// Mirrors `commands/promotions.ts`'s `resolveActorScope` \u2014 a new code's scope is always\n// the caller's own actor scope, never a client-supplied value.\nfunction resolveCodeActorScope(ctx: CommandRuntimeContext): PromotionsCodeScope {\n const tenantId = ctx.auth?.tenantId ?? null\n const organizationId = ctx.selectedOrganizationId ?? ctx.auth?.orgId ?? null\n if (!tenantId || !organizationId) {\n throw new CrudHttpError(400, {\n error: '[internal] Tenant and organization scope are required to create a promotion code',\n })\n }\n return { tenantId, organizationId }\n}\n\nconst createCodeCommand: CommandHandler<PromotionCodeCreateInput, { codeId: string }> = {\n id: 'promotions.code.create',\n outputSchema: codeCommandOutputSchema,\n async execute(rawInput, ctx) {\n const parsed = promotionCodeCreateSchema.parse(rawInput)\n const scope = resolveCodeActorScope(ctx)\n ensureTenantScope(ctx, scope.tenantId)\n ensureOrganizationScope(ctx, scope.organizationId)\n\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const code = em.create(Code, {\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n name: parsed.name,\n type: parsed.type,\n code: parsed.code ?? null,\n prefix: parsed.prefix ?? null,\n suffix: parsed.suffix ?? null,\n length: parsed.length ?? null,\n amount: parsed.amount ?? null,\n usage: parsed.usage,\n usageAmount: parsed.usageAmount ?? null,\n usagePerCustomer: parsed.usagePerCustomer ?? null,\n active: parsed.active,\n })\n em.persist(code)\n await em.flush()\n\n const dataEngine = ctx.container.resolve('dataEngine') as DataEngine\n await emitCrudSideEffects({\n dataEngine,\n action: 'created',\n entity: code,\n identifiers: getCodeIdentifiers(code),\n events: codeCrudEvents,\n indexer: codeCrudIndexer,\n })\n\n // \u00A7API Contracts `POST /api/promotions/codes`: \"for dynamic type, triggers\n // generation worker.\" Fired after the row has committed and its CRUD side effects\n // ran \u2014 a transient enqueue failure must not fail the create itself; the admin can\n // retry generation via `POST /codes/[id]/generate`.\n if (code.type === 'dynamic') {\n try {\n const generationService = ctx.container.resolve('promotionCodeGenerationService') as PromotionCodeGenerationService\n await generationService.triggerGeneration(code.id, scope)\n } catch (err) {\n codesLogger.warn('[internal] promotions.code.create failed to trigger code generation', { codeId: code.id, err })\n }\n }\n\n return { codeId: code.id }\n },\n captureAfter: async (_input, result, ctx) => {\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const code = await loadCode(em, result.codeId)\n return code ? toCodeSnapshot(code) : null\n },\n buildLog: async ({ result, snapshots }) => {\n const { translate } = await resolveTranslations()\n const after = snapshots.after as CodeSnapshot | undefined\n return {\n actionLabel: translate('promotions.audit.code.create', 'Create promotional code'),\n resourceKind: 'promotions.code',\n resourceId: result.codeId,\n tenantId: after?.tenantId ?? null,\n organizationId: after?.organizationId ?? null,\n snapshotAfter: after ?? null,\n payload: {\n undo: { after: after ?? null } satisfies CodeUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<CodeUndoPayload>(logEntry)\n const after = payload?.after\n if (!after) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const code = await em.findOne(Code, { id: after.id })\n if (!code) return\n\n // `promotion_generated_codes.code_id` carries `ON DELETE CASCADE` (\u00A7Data Models), so\n // removing the Code row also removes every generated code minted for it.\n em.remove(code)\n await em.flush()\n\n const dataEngine = ctx.container.resolve('dataEngine') as DataEngine\n await emitCrudUndoSideEffects({\n dataEngine,\n action: 'deleted',\n entity: code,\n identifiers: getCodeIdentifiers(code),\n events: codeCrudEvents,\n indexer: codeCrudIndexer,\n })\n },\n}\n\nconst updateCodeCommand: CommandHandler<PromotionCodeUpdateInput, { codeId: string }> = {\n id: 'promotions.code.update',\n outputSchema: codeCommandOutputSchema,\n async prepare(rawInput, ctx) {\n const parsed = promotionCodeUpdateSchema.parse(rawInput)\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const code = await loadCode(em, parsed.id)\n return code ? { before: toCodeSnapshot(code) } : null\n },\n async execute(rawInput, ctx) {\n const parsed = promotionCodeUpdateSchema.parse(rawInput)\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const code = await loadCode(em, parsed.id)\n if (!code) throw notFound('Promotion code not found')\n assertPromotionScopeOrNotFound(ctx, code)\n\n await runCrudCommandWrite({\n ctx,\n em,\n entityId: CODE_ENTITY_ID,\n action: 'updated',\n scope: { tenantId: code.tenantId, organizationId: code.organizationId },\n events: codeCrudEvents,\n indexer: codeCrudIndexer,\n sideEffect: () => ({\n entity: code,\n identifiers: getCodeIdentifiers(code),\n }),\n phases: [\n () => {\n if (parsed.name !== undefined) code.name = parsed.name\n if (parsed.type !== undefined) code.type = parsed.type\n if (parsed.code !== undefined) code.code = parsed.code ?? null\n if (parsed.prefix !== undefined) code.prefix = parsed.prefix ?? null\n if (parsed.suffix !== undefined) code.suffix = parsed.suffix ?? null\n if (parsed.length !== undefined) code.length = parsed.length ?? null\n if (parsed.amount !== undefined) code.amount = parsed.amount ?? null\n if (parsed.usage !== undefined) code.usage = parsed.usage\n if (parsed.usageAmount !== undefined) code.usageAmount = parsed.usageAmount ?? null\n if (parsed.usagePerCustomer !== undefined) code.usagePerCustomer = parsed.usagePerCustomer ?? null\n if (parsed.active !== undefined) code.active = parsed.active\n },\n ],\n })\n\n return { codeId: code.id }\n },\n captureAfter: async (_input, result, ctx) => {\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const code = await loadCode(em, result.codeId)\n return code ? toCodeSnapshot(code) : null\n },\n buildLog: async ({ result, snapshots, ctx }) => {\n const before = snapshots.before as CodeSnapshot | undefined\n if (!before) return null\n const { translate } = await resolveTranslations()\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const code = await loadCode(em, result.codeId)\n const after = code ? toCodeSnapshot(code) : null\n return {\n actionLabel: translate('promotions.audit.code.update', 'Update promotional code'),\n resourceKind: 'promotions.code',\n resourceId: before.id,\n tenantId: before.tenantId,\n organizationId: before.organizationId,\n snapshotBefore: before,\n snapshotAfter: after,\n payload: {\n undo: { before, after } satisfies CodeUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<CodeUndoPayload>(logEntry)\n const before = payload?.before\n if (!before) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n let code = null as Code | null\n\n await withAtomicFlush(\n em,\n [\n async () => {\n code = await em.findOne(\n Code,\n { id: before.id, tenantId: before.tenantId, organizationId: before.organizationId },\n { lockMode: LockMode.PESSIMISTIC_WRITE },\n )\n },\n () => {\n if (!code) return\n code.name = before.name\n code.type = before.type\n code.code = before.code\n code.prefix = before.prefix\n code.suffix = before.suffix\n code.length = before.length\n code.amount = before.amount\n code.usage = before.usage\n code.usageAmount = before.usageAmount\n code.usagePerCustomer = before.usagePerCustomer\n code.active = resolveUndoActiveFlag(code, before)\n },\n ],\n { transaction: true, label: 'promotions.code.update.undo' },\n )\n if (!code) return\n\n const dataEngine = ctx.container.resolve('dataEngine') as DataEngine\n await emitCrudUndoSideEffects({\n dataEngine,\n action: 'updated',\n entity: code,\n identifiers: getCodeIdentifiers(code),\n events: codeCrudEvents,\n indexer: codeCrudIndexer,\n })\n },\n}\n\nconst deleteCodeCommand: CommandHandler<PromotionCodeDeleteInput, { codeId: string }> = {\n id: 'promotions.code.delete',\n outputSchema: codeCommandOutputSchema,\n async prepare(rawInput, ctx) {\n const parsed = promotionCodeDeleteSchema.parse(rawInput)\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const code = await loadCode(em, parsed.id)\n if (!code) return null\n // \u00A7API Contracts `DELETE /api/promotions/codes`: \"deactivates generated codes.\"\n // Captured here, before the mutation, so undo restores EXACTLY the rows THIS delete\n // deactivated \u2014 not every generated row for the code, some of which may already be\n // inactive for an unrelated reason (e.g. `codes/use` spending them).\n const activeGeneratedCodeIds = (\n await em.find(GeneratedCode, {\n codeId: code.id,\n tenantId: code.tenantId,\n organizationId: code.organizationId,\n active: true,\n })\n ).map((row) => row.id)\n return { before: { ...toCodeSnapshot(code), activeGeneratedCodeIds } satisfies CodeDeleteSnapshot }\n },\n async execute(rawInput, ctx) {\n const parsed = promotionCodeDeleteSchema.parse(rawInput)\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const code = await loadCode(em, parsed.id)\n if (!code) throw notFound('Promotion code not found')\n assertPromotionScopeOrNotFound(ctx, code)\n\n // \u00A7Data Models / \u00A7API Contracts: soft-delete the `Code` row AND explicitly\n // deactivate its already-generated codes. Decision (documented, not left implicit):\n // `resolveCodeByString`'s parent-code lookup already filters `deletedAt: null`, so a\n // soft-deleted code's generated rows are unreachable through the normal resolution\n // path regardless of this flag \u2014 but the explicit flip keeps the admin UI's own\n // generated-codes panel accurate and matches `codes/use`'s identical `active`\n // semantics, rather than relying on that implicit effect alone.\n await withAtomicFlush(\n em,\n [\n () => {\n code.deletedAt = new Date()\n },\n async () => {\n await em.nativeUpdate(\n GeneratedCode,\n { codeId: code.id, tenantId: code.tenantId, organizationId: code.organizationId },\n { active: false },\n )\n },\n ],\n { transaction: true, label: 'promotions.code.delete' },\n )\n\n const dataEngine = ctx.container.resolve('dataEngine') as DataEngine\n await emitCrudSideEffects({\n dataEngine,\n action: 'deleted',\n entity: code,\n identifiers: getCodeIdentifiers(code),\n events: codeCrudEvents,\n indexer: codeCrudIndexer,\n })\n\n return { codeId: code.id }\n },\n buildLog: async ({ snapshots }) => {\n const before = snapshots.before as CodeDeleteSnapshot | undefined\n if (!before) return null\n const { translate } = await resolveTranslations()\n return {\n actionLabel: translate('promotions.audit.code.delete', 'Delete promotional code'),\n resourceKind: 'promotions.code',\n resourceId: before.id,\n tenantId: before.tenantId,\n organizationId: before.organizationId,\n snapshotBefore: before,\n payload: {\n undo: { before } satisfies CodeUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<CodeUndoPayload>(logEntry)\n const before = payload?.before as CodeDeleteSnapshot | undefined\n if (!before) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const code = await em.findOne(Code, { id: before.id })\n if (!code) return\n\n await withAtomicFlush(\n em,\n [\n () => {\n code.deletedAt = null\n },\n async () => {\n if (before.activeGeneratedCodeIds.length) {\n await em.nativeUpdate(GeneratedCode, { id: { $in: before.activeGeneratedCodeIds } }, { active: true })\n }\n },\n ],\n { transaction: true, label: 'promotions.code.delete.undo' },\n )\n\n const dataEngine = ctx.container.resolve('dataEngine') as DataEngine\n await emitCrudUndoSideEffects({\n dataEngine,\n // Restoring a soft-deleted row re-adds it to the index/cache \u2014 same semantics as\n // `created` on the forward path (mirrors `commands/promotions.ts`'s delete undo).\n action: 'created',\n entity: code,\n identifiers: getCodeIdentifiers(code),\n events: codeCrudEvents,\n indexer: codeCrudIndexer,\n })\n },\n}\n\nregisterCommand(reserveCodeCommand)\nregisterCommand(releaseCodeCommand)\nregisterCommand(useCodeCommand)\nregisterCommand(createCodeCommand)\nregisterCommand(updateCodeCommand)\nregisterCommand(deleteCodeCommand)\n\nexport {\n reserveCodeCommand,\n releaseCodeCommand,\n useCodeCommand,\n createCodeCommand,\n updateCodeCommand,\n deleteCodeCommand,\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -13,7 +13,7 @@ import {
|
|
|
13
13
|
createEmptyUpsertIndexBatchResult,
|
|
14
14
|
mergeUpsertIndexBatchResults
|
|
15
15
|
} from "./lib/batch.js";
|
|
16
|
-
import { reindexEntity, DEFAULT_REINDEX_PARTITIONS } from "./lib/reindexer.js";
|
|
16
|
+
import { reindexEntity, isTenantlessReindexTarget, DEFAULT_REINDEX_PARTITIONS } from "./lib/reindexer.js";
|
|
17
17
|
function warnIfReindexRefused(entityType, result) {
|
|
18
18
|
if (!result.refused) return;
|
|
19
19
|
const detail = result.refused === "no-tenant-column" ? "the source table has no tenant_id column and the entity type is not declared tenant-global" : result.refused === "declared-global-but-org-scoped" ? "the entity type is declared tenant-global but its table carries an organization_id column" : "the source table's columns could not be read, so no scope could be proven (usually transient)";
|
|
@@ -755,6 +755,22 @@ const reindex = {
|
|
|
755
755
|
console.log(`[${idx + 1}/${entityIds.length}] Purging existing index rows for ${id}...`);
|
|
756
756
|
await purgeIndexScope(baseEm, { entityType: id, organizationId: orgId, tenantId });
|
|
757
757
|
}
|
|
758
|
+
if (tenantId != null && await isTenantlessReindexTarget(baseEm, id)) {
|
|
759
|
+
console.log(`[${idx + 1}/${entityIds.length}] Skipping ${id}: its table has no tenant_id column, so it is not tenant-scoped`);
|
|
760
|
+
await recordIndexerLog(
|
|
761
|
+
{ em: baseEm },
|
|
762
|
+
{
|
|
763
|
+
source: "query_index",
|
|
764
|
+
handler: "cli:query_index.reindex",
|
|
765
|
+
message: `Reindex skipped for ${id}: not tenant-scoped`,
|
|
766
|
+
entityType: id,
|
|
767
|
+
tenantId,
|
|
768
|
+
organizationId: orgId ?? null,
|
|
769
|
+
details: { skipped: "no-tenant-column" }
|
|
770
|
+
}
|
|
771
|
+
).catch(() => void 0);
|
|
772
|
+
continue;
|
|
773
|
+
}
|
|
758
774
|
console.log(
|
|
759
775
|
`[${idx + 1}/${entityIds.length}] Reindexing ${id}${force ? " (forced)" : ""} in ${partitionTargets.length} partition(s)...`
|
|
760
776
|
);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/modules/query_index/cli.ts"],
|
|
4
|
-
"sourcesContent": ["import type { ModuleCli } from '@open-mercato/shared/modules/registry'\nimport { createRequestContainer } from '@open-mercato/shared/lib/di/container'\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport { type Kysely, sql } from 'kysely'\nimport { createProgressBar } from '@open-mercato/shared/lib/cli/progress'\nimport { resolveTenantEncryptionService } from '@open-mercato/shared/lib/encryption/customFieldValues'\nimport { decryptIndexDocForSearch, encryptIndexDocForStorage } from '@open-mercato/shared/lib/encryption/indexDoc'\nimport { parseBooleanToken } from '@open-mercato/shared/lib/boolean'\n\ntype ProgressBarHandle = {\n update(completed: number): void\n complete(): void\n}\nimport { resolveEntityTableName, resolveRegisteredEntityTableName } from '@open-mercato/shared/lib/query/engine'\nimport { recordIndexerError } from '@open-mercato/shared/lib/indexers/error-log'\nimport { recordIndexerLog } from '@open-mercato/shared/lib/indexers/status-log'\nimport {\n upsertIndexBatch,\n assertIndexBatchWritesLanded,\n createEmptyUpsertIndexBatchResult,\n mergeUpsertIndexBatchResults,\n type AnyRow,\n} from './lib/batch'\nimport { reindexEntity, DEFAULT_REINDEX_PARTITIONS } from './lib/reindexer'\nimport type { ReindexJobResult } from './lib/reindexer'\n\n/**\n * A refused sweep returns processed 0 / total 0, which the progress reporting below prints\n * as `0 / 0 (0.00%)` - indistinguishable from a run that found nothing. Say why instead.\n */\nfunction warnIfReindexRefused(entityType: string, result: ReindexJobResult): void {\n if (!result.refused) return\n const detail = result.refused === 'no-tenant-column'\n ? 'the source table has no tenant_id column and the entity type is not declared tenant-global'\n : result.refused === 'declared-global-but-org-scoped'\n ? 'the entity type is declared tenant-global but its table carries an organization_id column'\n : \"the source table's columns could not be read, so no scope could be proven (usually transient)\"\n console.warn(` -> ${entityType}: reindex REFUSED, nothing was indexed - ${detail}`)\n}\nimport { purgeIndexScope } from './lib/purge'\nimport { refreshCoverageSnapshot } from './lib/coverage'\nimport { flattenSystemEntityIds } from '@open-mercato/shared/lib/entities/system-entities'\nimport type { VectorIndexService } from '@open-mercato/search/vector'\n\ntype ParsedArgs = Record<string, string | boolean>\n\ntype PartitionProgressInfo = { processed: number; total: number }\n\nfunction isIndexerVerbose(): boolean {\n const parsed = parseBooleanToken(process.env.OM_INDEXER_VERBOSE ?? '')\n return parsed === true\n}\n\nfunction createGroupedProgress(label: string, partitionTargets: number[]) {\n const totals = new Map<number, number>()\n const processed = new Map<number, number>()\n let bar: ProgressBarHandle | null = null\n\n const getTotals = () => {\n let total = 0\n let done = 0\n for (const value of totals.values()) total += value\n for (const value of processed.values()) done += value\n return { total, done }\n }\n\n const tryInitBar = () => {\n if (bar) return\n if (totals.size < partitionTargets.length) return\n const { total } = getTotals()\n if (total <= 0) return\n bar = createProgressBar(label, total) as ProgressBarHandle\n }\n\n return {\n onProgress(partition: number, info: PartitionProgressInfo) {\n processed.set(partition, info.processed)\n if (!totals.has(partition)) totals.set(partition, info.total)\n tryInitBar()\n if (!bar) return\n const { done } = getTotals()\n bar.update(done)\n },\n complete() {\n if (bar) bar.complete()\n },\n getTotals,\n }\n}\n\nfunction parseArgs(rest: string[]): ParsedArgs {\n const args: ParsedArgs = {}\n for (let i = 0; i < rest.length; i += 1) {\n const part = rest[i]\n if (!part?.startsWith('--')) continue\n const [rawKey, rawValue] = part.slice(2).split('=')\n if (!rawKey) continue\n if (rawValue !== undefined) {\n args[rawKey] = rawValue\n } else if (i + 1 < rest.length && !rest[i + 1]!.startsWith('--')) {\n args[rawKey] = rest[i + 1]!\n i += 1\n } else {\n args[rawKey] = true\n }\n }\n return args\n}\n\nfunction stringOption(args: ParsedArgs, ...keys: string[]): string | undefined {\n for (const key of keys) {\n const raw = args[key]\n if (typeof raw !== 'string') continue\n const trimmed = raw.trim()\n if (trimmed.length > 0) return trimmed\n }\n return undefined\n}\n\nfunction numberOption(args: ParsedArgs, ...keys: string[]): number | undefined {\n for (const key of keys) {\n const raw = args[key]\n if (typeof raw === 'number') return raw\n if (typeof raw === 'string') {\n const parsed = Number(raw)\n if (Number.isFinite(parsed)) return parsed\n }\n }\n return undefined\n}\n\nfunction flagEnabled(args: ParsedArgs, ...keys: string[]): boolean {\n for (const key of keys) {\n const raw = args[key]\n if (raw === undefined) continue\n if (raw === true) return true\n if (raw === false) continue\n if (typeof raw === 'string') {\n const trimmed = raw.trim()\n if (!trimmed) return true\n const parsed = parseBooleanToken(trimmed)\n return parsed === null ? true : parsed\n }\n }\n return false\n}\n\nfunction toPositiveInt(value: number | undefined): number | undefined {\n if (value === undefined) return undefined\n const n = Math.floor(value)\n if (!Number.isFinite(n) || n <= 0) return undefined\n return n\n}\n\nfunction toNonNegativeInt(value: number | undefined, fallback = 0): number {\n if (value === undefined) return fallback\n const n = Math.floor(value)\n if (!Number.isFinite(n) || n < 0) return fallback\n return n\n}\n\nconst DEFAULT_BATCH_SIZE = 200\n\ntype RebuildExecutionOptions = {\n em: EntityManager\n db: Kysely<any>\n entityType: string\n tableName: string\n orgOverride?: string\n tenantOverride?: string\n global: boolean\n includeDeleted: boolean\n limit?: number\n offset: number\n recordId?: string\n batchSize: number\n progressLabel?: string\n supportsOrgFilter: boolean\n supportsTenantFilter: boolean\n supportsDeletedFilter: boolean\n}\n\ntype RebuildResult = {\n processed: number\n matched: number\n}\nasync function rebuildEntityIndexes(options: RebuildExecutionOptions): Promise<RebuildResult> {\n const {\n em,\n db,\n entityType,\n tableName,\n orgOverride,\n tenantOverride,\n global,\n includeDeleted,\n limit,\n offset,\n recordId,\n batchSize,\n progressLabel,\n supportsOrgFilter,\n supportsTenantFilter,\n supportsDeletedFilter,\n } = options\n\n const encryption = resolveTenantEncryptionService(em as any)\n const dekKeyCache = new Map<string | null, string | null>()\n\n // Neither helper swallows failures: upsertIndexBatch treats a failed encrypt as a\n // failed row (writing the plaintext document instead would break encryption at rest)\n // and records a failed decrypt against fulltext.\n const encryptDoc = async (\n targetEntity: string,\n doc: Record<string, unknown>,\n scope: { organizationId: string | null; tenantId: string | null },\n ) => {\n return await encryptIndexDocForStorage(\n targetEntity,\n doc,\n { tenantId: scope.tenantId ?? null, organizationId: scope.organizationId ?? null },\n encryption,\n )\n }\n\n const decryptDoc = async (\n targetEntity: string,\n doc: Record<string, unknown>,\n scope: { organizationId: string | null; tenantId: string | null },\n ) => {\n return await decryptIndexDocForSearch(\n targetEntity,\n doc,\n { tenantId: scope.tenantId ?? null, organizationId: scope.organizationId ?? null },\n encryption,\n dekKeyCache,\n )\n }\n\n const applyFilters = <QB extends { where: (...args: any[]) => QB }>(q: QB): QB => {\n let chain = q\n if (!global) {\n if (orgOverride !== undefined && supportsOrgFilter) {\n chain = chain.where('organization_id' as any, '=', orgOverride)\n }\n if (tenantOverride !== undefined && supportsTenantFilter) {\n chain = chain.where('tenant_id' as any, '=', tenantOverride)\n }\n }\n if (!includeDeleted && supportsDeletedFilter) {\n chain = chain.where('deleted_at' as any, 'is', null as any)\n }\n return chain\n }\n\n if (recordId) {\n const row = await applyFilters(\n db.selectFrom(tableName as any).selectAll() as any,\n )\n .where('id' as any, '=', recordId)\n .executeTakeFirst() as AnyRow | undefined\n if (!row) return { processed: 0, matched: 0 }\n const bar = createProgressBar(progressLabel ?? `Rebuilding ${entityType}`, 1)\n const singleResult = await upsertIndexBatch(db, entityType, [row], { orgId: orgOverride, tenantId: tenantOverride }, { encryptDoc, decryptDoc })\n bar.update(singleResult.written)\n bar.complete()\n assertIndexBatchWritesLanded(entityType, singleResult)\n return { processed: singleResult.written, matched: 1 }\n }\n\n const countRow = await applyFilters(\n db.selectFrom(tableName as any).select(sql<string>`count(*)`.as('count')) as any,\n ).executeTakeFirst() as { count: string | number } | undefined\n const totalRaw = countRow?.count\n const total = totalRaw != null ? Number(totalRaw) : 0\n const effectiveOffset = Math.max(0, offset)\n const matchedWithoutLimit = Math.max(0, total - effectiveOffset)\n const limitValue = toPositiveInt(limit)\n const intended = limitValue !== undefined ? Math.min(matchedWithoutLimit, limitValue) : matchedWithoutLimit\n if (!Number.isFinite(intended) || intended <= 0) {\n return { processed: 0, matched: 0 }\n }\n\n const bar = createProgressBar(progressLabel ?? `Rebuilding ${entityType}`, intended)\n let processed = 0\n let fetched = 0\n let cursorOffset = effectiveOffset\n let remaining = limitValue\n const writeTotals = createEmptyUpsertIndexBatchResult()\n\n while (fetched < intended) {\n const chunkLimit = remaining !== undefined ? Math.min(batchSize, remaining) : batchSize\n const chunk = await applyFilters(\n db\n .selectFrom(tableName as any)\n .selectAll()\n .orderBy('id' as any)\n .limit(chunkLimit)\n .offset(cursorOffset) as any,\n ).execute() as AnyRow[]\n if (!chunk.length) break\n\n const chunkResult = await upsertIndexBatch(db, entityType, chunk as AnyRow[], {\n orgId: orgOverride,\n tenantId: tenantOverride,\n }, { encryptDoc, decryptDoc })\n mergeUpsertIndexBatchResults(writeTotals, chunkResult)\n\n processed += chunkResult.written\n fetched += chunk.length\n cursorOffset += chunk.length\n if (remaining !== undefined) remaining -= chunk.length\n bar.update(processed)\n if (remaining !== undefined && remaining <= 0) break\n }\n\n if (processed < intended) {\n bar.update(processed)\n }\n bar.complete()\n // After bar.complete() so the terminal is left in a sane state before we throw.\n assertIndexBatchWritesLanded(entityType, writeTotals)\n return { processed, matched: intended }\n}\n\nasync function getColumnSet(db: Kysely<any>, tableName: string): Promise<Set<string>> {\n try {\n const rows = await db\n .selectFrom('information_schema.columns' as any)\n .select(['column_name' as any])\n .where(sql<boolean>`table_schema = current_schema()`)\n .where('table_name' as any, '=', tableName)\n .execute() as Array<{ column_name: string }>\n return new Set(rows.map((row) => String(row.column_name).toLowerCase()))\n } catch {\n return new Set<string>()\n }\n}\n\ntype ScopeDescriptor = {\n global: boolean\n orgId?: string\n tenantId?: string\n includeDeleted: boolean\n supportsOrg: boolean\n supportsTenant: boolean\n supportsDeleted: boolean\n}\n\nfunction describeScope(scope: ScopeDescriptor): string {\n const parts: string[] = []\n if (scope.global) parts.push('global')\n if (!scope.global && scope.orgId && scope.supportsOrg) parts.push(`org=${scope.orgId}`)\n if (!scope.global && scope.tenantId && scope.supportsTenant) parts.push(`tenant=${scope.tenantId}`)\n if (!scope.includeDeleted && scope.supportsDeleted) parts.push('active-only')\n return parts.length ? ` (${parts.join(' ')})` : ''\n}\n\n/**\n * Above this many missing records the anti-join stops being the cheaper option and the\n * repair falls back to a full single-partition rebuild of the entity.\n */\nconst MAX_TARGETED_REPAIR_RECORDS = 5000\n\n/**\n * List the base records in scope that have no live index row, so a repair rebuilds only\n * what is actually missing instead of re-upserting the whole entity for a one-row gap.\n */\nasync function findUnindexedRecordIds(\n db: Kysely<any>,\n options: {\n entityType: string\n tableName: string\n tenantId?: string | null\n organizationId?: string | null\n limit: number\n },\n): Promise<string[]> {\n const columns = await getColumnSet(db, options.tableName)\n let query = db\n .selectFrom(`${options.tableName} as b` as any)\n .select('b.id' as any)\n .where(({ not, exists, selectFrom }: any) =>\n not(exists(\n selectFrom('entity_indexes as ei' as any)\n .select(sql`1`.as('one'))\n .whereRef('ei.entity_id' as any, '=', sql`b.id::text`)\n .where('ei.entity_type' as any, '=', options.entityType)\n .where('ei.deleted_at' as any, 'is', null as any),\n )),\n )\n .limit(options.limit)\n if (columns.has('deleted_at')) query = query.where('b.deleted_at' as any, 'is', null as any)\n if (options.tenantId != null && columns.has('tenant_id')) {\n query = query.where('b.tenant_id' as any, '=', options.tenantId)\n }\n if (options.organizationId != null && columns.has('organization_id')) {\n query = query.where('b.organization_id' as any, '=', options.organizationId)\n }\n const rows = await query.execute() as Array<{ id: unknown }>\n return rows.map((row) => String(row.id))\n}\n\n/**\n * Recount the scope from the database after a reindex and rebuild whatever is still\n * missing. Runs unconditionally so `mercato init` (and any scripted reindex) cannot finish\n * leaving a gap that a human has to notice and repair by hand from the Query Indexes\n * screen. When counts already agree this is two COUNT queries; when they do not, the\n * repair is scoped to the records the anti-join says are actually missing.\n */\nasync function verifyAndRepairIndexCoverage(\n em: EntityManager,\n options: {\n entityType: string\n tenantId?: string | null\n organizationId?: string | null\n batchSize?: number\n },\n): Promise<void> {\n const scope = {\n entityType: options.entityType,\n tenantId: options.tenantId ?? null,\n organizationId: options.organizationId ?? null,\n withDeleted: false,\n }\n\n let counts: { baseCount: number; indexedCount: number } | null = null\n try {\n counts = await refreshCoverageSnapshot(em, scope)\n } catch (error) {\n console.warn(\n ` -> ${options.entityType}: coverage verification skipped (${error instanceof Error ? error.message : String(error)})`,\n )\n return\n }\n if (!counts) return\n if (counts.indexedCount > counts.baseCount) {\n // Legitimate for entities whose base table cannot express the scope, since a per-tenant\n // reindex stamps its own scope onto every row. Surfaced rather than repaired: a rebuild\n // cannot remove the surplus, and the over-count would otherwise mask a real shortfall.\n console.warn(\n ` -> ${options.entityType}: ${counts.indexedCount} index rows for ${counts.baseCount} records \u2014 not repairable by reindexing`,\n )\n return\n }\n if (counts.indexedCount === counts.baseCount) return\n\n const db = (em as any).getKysely() as Kysely<any>\n let tableName: string | null = null\n try {\n tableName = resolveRegisteredEntityTableName(em as any, options.entityType)\n } catch {\n tableName = null\n }\n\n const missingIds = tableName\n ? await findUnindexedRecordIds(db, {\n entityType: options.entityType,\n tableName,\n tenantId: options.tenantId ?? null,\n organizationId: options.organizationId ?? null,\n limit: MAX_TARGETED_REPAIR_RECORDS + 1,\n }).catch(() => null)\n : null\n\n const targeted = missingIds && missingIds.length > 0 && missingIds.length <= MAX_TARGETED_REPAIR_RECORDS\n console.log(\n ` -> ${options.entityType}: ${counts.indexedCount}/${counts.baseCount} indexed after reindex \u2014 repairing`\n + `${targeted ? ` ${missingIds!.length} missing record(s)` : ' the whole entity'}...`,\n )\n\n try {\n if (targeted) {\n const columns = await getColumnSet(db, tableName!)\n for (const recordId of missingIds!) {\n await rebuildEntityIndexes({\n em,\n db,\n entityType: options.entityType,\n tableName: tableName!,\n orgOverride: options.organizationId ?? undefined,\n tenantOverride: options.tenantId ?? undefined,\n global: false,\n includeDeleted: false,\n offset: 0,\n recordId,\n batchSize: 1,\n supportsOrgFilter: columns.has('organization_id'),\n supportsTenantFilter: columns.has('tenant_id'),\n supportsDeletedFilter: columns.has('deleted_at'),\n })\n }\n } else {\n const repairResult = await reindexEntity(em, {\n entityType: options.entityType,\n tenantId: options.tenantId,\n organizationId: options.organizationId,\n force: false,\n batchSize: options.batchSize,\n emitVectorizeEvents: false,\n resetCoverage: false,\n })\n warnIfReindexRefused(options.entityType, repairResult)\n }\n } catch (error) {\n console.warn(\n ` -> ${options.entityType}: repair pass failed (${error instanceof Error ? error.message : String(error)})`,\n )\n return\n }\n\n const after = await refreshCoverageSnapshot(em, scope).catch(() => null)\n if (after && after.indexedCount < after.baseCount) {\n console.warn(\n ` -> ${options.entityType}: still ${after.indexedCount}/${after.baseCount} indexed after repair`,\n )\n } else {\n console.log(` -> ${options.entityType}: coverage repaired`)\n }\n}\n\nconst rebuild: ModuleCli = {\n command: 'rebuild',\n async run(rest) {\n const args = parseArgs(rest)\n const entity = stringOption(args, 'entity', 'e')\n if (!entity) {\n console.error(\n 'Usage: mercato query_index rebuild --entity <module:entity> [--record <id>] [--org <id>] [--tenant <id>] [--global] [--withDeleted] [--limit <n>] [--offset <n>]',\n )\n return\n }\n\n const globalFlag = flagEnabled(args, 'global')\n const includeDeleted = flagEnabled(args, 'withDeleted')\n const orgId = stringOption(args, 'org', 'organizationId')\n const tenantId = stringOption(args, 'tenant', 'tenantId')\n const recordId = stringOption(args, 'record', 'recordId', 'id')\n const limit = toPositiveInt(numberOption(args, 'limit'))\n const offset = toNonNegativeInt(numberOption(args, 'offset'))\n const batchSize = toPositiveInt(numberOption(args, 'batch', 'chunk', 'size')) ?? DEFAULT_BATCH_SIZE\n\n const container = await createRequestContainer()\n const em = (container.resolve('em') as EntityManager)\n try {\n const db = em.getKysely<any>()\n const tableName = resolveEntityTableName(em, entity)\n const columns = await getColumnSet(db, tableName)\n const supportsOrg = columns.has('organization_id')\n const supportsTenant = columns.has('tenant_id')\n const supportsDeleted = columns.has('deleted_at')\n\n if (!globalFlag && orgId && !supportsOrg) {\n console.warn(`[query_index] ${entity} does not expose organization_id, ignoring --org filter`)\n }\n if (!globalFlag && tenantId && !supportsTenant) {\n console.warn(`[query_index] ${entity} does not expose tenant_id, ignoring --tenant filter`)\n }\n if (!includeDeleted && !supportsDeleted) {\n console.warn(`[query_index] ${entity} does not expose deleted_at, cannot skip deleted rows`)\n }\n\n const result = await rebuildEntityIndexes({\n em,\n db,\n entityType: entity,\n tableName,\n orgOverride: orgId,\n tenantOverride: tenantId,\n global: globalFlag,\n includeDeleted,\n limit,\n offset,\n recordId,\n batchSize,\n progressLabel: recordId ? `Rebuilding ${entity} record ${recordId}` : `Rebuilding ${entity}`,\n supportsOrgFilter: supportsOrg,\n supportsTenantFilter: supportsTenant,\n supportsDeletedFilter: supportsDeleted,\n })\n\n if (recordId) {\n if (result.processed === 0) {\n console.log(`No matching row found for ${entity} with id ${recordId}`)\n } else {\n console.log(`Rebuilt index for ${entity} record ${recordId}`)\n }\n return\n }\n\n const scopeLabel = describeScope({\n global: globalFlag,\n orgId,\n tenantId,\n includeDeleted,\n supportsOrg,\n supportsTenant,\n supportsDeleted,\n })\n\n if (result.matched === 0) {\n console.log(`No rows matched filters for ${entity}${scopeLabel}`)\n return\n }\n\n console.log(`Rebuilt ${result.processed} row(s) for ${entity}${scopeLabel}`)\n } catch (error) {\n await recordIndexerError(\n { em },\n {\n source: 'query_index',\n handler: 'cli:query_index.rebuild',\n error,\n entityType: entity,\n recordId,\n tenantId,\n organizationId: orgId,\n payload: { args },\n },\n )\n throw error\n } finally {\n if (typeof (container as any)?.dispose === 'function') {\n await (container as any).dispose()\n }\n }\n },\n}\n\nconst rebuildAll: ModuleCli = {\n command: 'rebuild-all',\n async run(rest) {\n const args = parseArgs(rest)\n const globalFlag = flagEnabled(args, 'global')\n const includeDeleted = flagEnabled(args, 'withDeleted')\n const orgId = stringOption(args, 'org', 'organizationId')\n const tenantId = stringOption(args, 'tenant', 'tenantId')\n const limit = toPositiveInt(numberOption(args, 'limit'))\n const offset = toNonNegativeInt(numberOption(args, 'offset'))\n const batchSize = toPositiveInt(numberOption(args, 'batch', 'chunk', 'size')) ?? DEFAULT_BATCH_SIZE\n const recordId = stringOption(args, 'record', 'recordId', 'id')\n if (recordId) {\n console.error('`rebuild-all` does not support --record. Use `mercato query_index rebuild --record <id>` instead.')\n return\n }\n\n const container = await createRequestContainer()\n const em = (container.resolve('em') as EntityManager)\n try {\n const db = em.getKysely<any>()\n\n const { getEntityIds } = await import('@open-mercato/shared/lib/encryption/entityIds')\n const entityIds = flattenSystemEntityIds(getEntityIds() as Record<string, Record<string, string>>)\n if (!entityIds.length) {\n console.log('No entity definitions registered for query indexing.')\n return\n }\n\n let totalProcessed = 0\n for (let idx = 0; idx < entityIds.length; idx += 1) {\n const entity = entityIds[idx]!\n const tableName = resolveEntityTableName(em, entity)\n const columns = await getColumnSet(db, tableName)\n const supportsOrg = columns.has('organization_id')\n const supportsTenant = columns.has('tenant_id')\n const supportsDeleted = columns.has('deleted_at')\n\n if (!globalFlag && orgId && !supportsOrg) {\n console.warn(`[query_index] ${entity} does not expose organization_id, ignoring --org filter`)\n }\n if (!globalFlag && tenantId && !supportsTenant) {\n console.warn(`[query_index] ${entity} does not expose tenant_id, ignoring --tenant filter`)\n }\n if (!includeDeleted && !supportsDeleted) {\n console.warn(`[query_index] ${entity} does not expose deleted_at, cannot skip deleted rows`)\n }\n\n const scopeLabel = describeScope({\n global: globalFlag,\n orgId,\n tenantId,\n includeDeleted,\n supportsOrg,\n supportsTenant,\n supportsDeleted,\n })\n\n console.log(`[${idx + 1}/${entityIds.length}] Rebuilding ${entity}${scopeLabel}`)\n const result = await rebuildEntityIndexes({\n em,\n db,\n entityType: entity,\n tableName,\n orgOverride: orgId,\n tenantOverride: tenantId,\n global: globalFlag,\n includeDeleted,\n limit,\n offset,\n batchSize,\n supportsOrgFilter: supportsOrg,\n supportsTenantFilter: supportsTenant,\n supportsDeletedFilter: supportsDeleted,\n })\n totalProcessed += result.processed\n if (result.matched === 0) {\n console.log(' -> no rows matched filters')\n } else {\n console.log(` -> processed ${result.processed} row(s)`)\n }\n }\n\n console.log(`Finished rebuilding all query indexes (processed ${totalProcessed} row(s))`)\n } catch (error) {\n await recordIndexerError(\n { em },\n {\n source: 'query_index',\n handler: 'cli:query_index.rebuild-all',\n error,\n tenantId,\n organizationId: orgId,\n payload: { args },\n },\n )\n throw error\n } finally {\n if (typeof (container as any)?.dispose === 'function') {\n await (container as any).dispose()\n }\n }\n },\n}\n\nconst reindex: ModuleCli = {\n command: 'reindex',\n async run(rest) {\n const args = parseArgs(rest)\n const entity = stringOption(args, 'entity', 'e')\n const orgId = stringOption(args, 'org', 'organizationId')\n const tenantId = stringOption(args, 'tenant', 'tenantId')\n const force = flagEnabled(args, 'force', 'full')\n const batchSize = toPositiveInt(numberOption(args, 'batch', 'chunk', 'size'))\n const partitionsOption = toPositiveInt(numberOption(args, 'partitions', 'partitionCount', 'parallel'))\n const partitionIndexOptionRaw = numberOption(args, 'partition', 'partitionIndex')\n const resetCoverageFlag = flagEnabled(args, 'resetCoverage')\n const skipResetCoverageFlag = flagEnabled(args, 'skipResetCoverage', 'noResetCoverage')\n const skipPurge = flagEnabled(args, 'skipPurge', 'noPurge')\n\n const container = await createRequestContainer()\n const baseEm = (container.resolve('em') as EntityManager)\n const partitionIndexOption =\n partitionIndexOptionRaw === undefined ? undefined : toNonNegativeInt(partitionIndexOptionRaw, 0)\n const partitionCount = Math.max(\n 1,\n partitionsOption ?? DEFAULT_REINDEX_PARTITIONS,\n )\n\n if (partitionIndexOption !== undefined && partitionIndexOption >= partitionCount) {\n console.error(`partitionIndex (${partitionIndexOption}) must be < partitionCount (${partitionCount})`)\n if (typeof (container as any)?.dispose === 'function') {\n await (container as any).dispose()\n }\n return\n }\n\n const partitionTargets =\n partitionIndexOption !== undefined\n ? [partitionIndexOption]\n : Array.from({ length: partitionCount }, (_, idx) => idx)\n\n const shouldResetCoverage = (partition: number): boolean => {\n if (resetCoverageFlag) return true\n if (skipResetCoverageFlag) return false\n if (partitionIndexOption !== undefined) return partitionIndexOption === 0\n return partition === partitionTargets[0]\n }\n\n try {\n if (entity) {\n await recordIndexerLog(\n { em: baseEm },\n {\n source: 'query_index',\n handler: 'cli:query_index.reindex',\n message: `Reindex started for ${entity}`,\n entityType: entity,\n tenantId: tenantId ?? null,\n organizationId: orgId ?? null,\n details: {\n force,\n partitions: partitionTargets.length,\n partitionCount,\n partitionIndex: partitionIndexOption ?? null,\n skipPurge,\n },\n },\n ).catch(() => undefined)\n if (!skipPurge) {\n console.log(`Purging existing index rows for ${entity}...`)\n await purgeIndexScope(baseEm, { entityType: entity, organizationId: orgId, tenantId })\n }\n console.log(`Reindexing ${entity}${force ? ' (forced)' : ''} in ${partitionTargets.length} partition(s)...`)\n const verbose = isIndexerVerbose()\n const progressState = verbose ? new Map<number, { last: number }>() : null\n const groupedProgress =\n !verbose && partitionTargets.length > 1\n ? createGroupedProgress(`Reindexing ${entity}`, partitionTargets)\n : null\n const renderProgress = (part: number, entityId: string, info: PartitionProgressInfo) => {\n if (!progressState) return\n const state = progressState.get(part) ?? { last: 0 }\n const now = Date.now()\n if (now - state.last < 1000 && info.processed < info.total) return\n state.last = now\n progressState.set(part, state)\n const percent = info.total > 0 ? ((info.processed / info.total) * 100).toFixed(2) : '0.00'\n console.log(\n ` [${entityId}] partition ${part + 1}/${partitionCount}: ${info.processed.toLocaleString()} / ${info.total.toLocaleString()} (${percent}%)`,\n )\n }\n\n const stats = await Promise.all(\n partitionTargets.map(async (part, idx) => {\n const label = partitionTargets.length > 1 ? ` [partition ${part + 1}/${partitionCount}]` : ''\n if (partitionTargets.length === 1) {\n console.log(` -> processing${label}`)\n } else if (verbose && idx === 0) {\n console.log(` -> processing partitions in parallel (count=${partitionTargets.length})`)\n }\n const partitionContainer = await createRequestContainer()\n const partitionEm = partitionContainer.resolve<EntityManager>('em')\n let partitionVectorService: VectorIndexService | null = null\n try {\n partitionVectorService = partitionContainer.resolve<VectorIndexService>('vectorIndexService')\n } catch {\n partitionVectorService = null\n }\n try {\n let progressBar: ProgressBarHandle | null = null\n const useBar = partitionTargets.length === 1\n const partitionStats = await reindexEntity(partitionEm, {\n entityType: entity,\n tenantId,\n organizationId: orgId,\n force,\n batchSize,\n emitVectorizeEvents: false,\n partitionCount,\n partitionIndex: part,\n resetCoverage: shouldResetCoverage(part),\n vectorService: partitionVectorService,\n onProgress(info) {\n if (useBar) {\n if (info.total > 0 && !progressBar) {\n progressBar = createProgressBar(\n `Reindexing ${entity}${label}`,\n info.total,\n ) as ProgressBarHandle\n }\n progressBar?.update(info.processed)\n } else if (groupedProgress) {\n groupedProgress.onProgress(part, info)\n } else {\n renderProgress(part, entity, info)\n }\n },\n })\n if (progressBar) {\n (progressBar as ProgressBarHandle).complete()\n }\n warnIfReindexRefused(entity, partitionStats)\n if (!useBar && groupedProgress) {\n groupedProgress.onProgress(part, { processed: partitionStats.processed, total: partitionStats.total })\n } else if (!useBar) {\n renderProgress(part, entity, { processed: partitionStats.processed, total: partitionStats.total })\n } else {\n console.log(\n ` processed ${partitionStats.processed} row(s)${partitionStats.total ? ` (base ${partitionStats.total})` : ''}`,\n )\n }\n return partitionStats.processed\n } finally {\n if (typeof (partitionContainer as any)?.dispose === 'function') {\n await (partitionContainer as any).dispose()\n }\n }\n }),\n )\n groupedProgress?.complete()\n const totalProcessed = stats.reduce((acc, value) => acc + value, 0)\n console.log(`Finished ${entity}: processed ${totalProcessed} row(s) across ${partitionTargets.length} partition(s)`)\n if (partitionIndexOption === undefined) {\n await verifyAndRepairIndexCoverage(baseEm, {\n entityType: entity,\n tenantId,\n organizationId: orgId,\n batchSize,\n })\n }\n await recordIndexerLog(\n { em: baseEm },\n {\n source: 'query_index',\n handler: 'cli:query_index.reindex',\n message: `Reindex completed for ${entity}`,\n entityType: entity,\n tenantId: tenantId ?? null,\n organizationId: orgId ?? null,\n details: {\n processed: totalProcessed,\n partitions: partitionTargets.length,\n partitionCount,\n partitionIndex: partitionIndexOption ?? null,\n },\n },\n ).catch(() => undefined)\n return\n }\n\n const { getEntityIds } = await import('@open-mercato/shared/lib/encryption/entityIds')\n const entityIds = flattenSystemEntityIds(getEntityIds() as Record<string, Record<string, string>>)\n if (!entityIds.length) {\n console.log('No entity definitions registered for query indexing.')\n return\n }\n for (let idx = 0; idx < entityIds.length; idx += 1) {\n const id = entityIds[idx]!\n await recordIndexerLog(\n { em: baseEm },\n {\n source: 'query_index',\n handler: 'cli:query_index.reindex',\n message: `Reindex started for ${id}`,\n entityType: id,\n tenantId: tenantId ?? null,\n organizationId: orgId ?? null,\n details: {\n force,\n partitions: partitionTargets.length,\n partitionCount,\n partitionIndex: partitionIndexOption ?? null,\n skipPurge,\n },\n },\n ).catch(() => undefined)\n if (!skipPurge) {\n console.log(`[${idx + 1}/${entityIds.length}] Purging existing index rows for ${id}...`)\n await purgeIndexScope(baseEm, { entityType: id, organizationId: orgId, tenantId })\n }\n console.log(\n `[${idx + 1}/${entityIds.length}] Reindexing ${id}${force ? ' (forced)' : ''} in ${partitionTargets.length} partition(s)...`,\n )\n const verbose = isIndexerVerbose()\n const progressState = verbose ? new Map<number, { last: number }>() : null\n const groupedProgress =\n !verbose && partitionTargets.length > 1\n ? createGroupedProgress(`Reindexing ${id}`, partitionTargets)\n : null\n const renderProgress = (part: number, entityId: string, info: PartitionProgressInfo) => {\n if (!progressState) return\n const state = progressState.get(part) ?? { last: 0 }\n const now = Date.now()\n if (now - state.last < 1000 && info.processed < info.total) return\n state.last = now\n progressState.set(part, state)\n const percent = info.total > 0 ? ((info.processed / info.total) * 100).toFixed(2) : '0.00'\n console.log(\n ` [${entityId}] partition ${part + 1}/${partitionCount}: ${info.processed.toLocaleString()} / ${info.total.toLocaleString()} (${percent}%)`,\n )\n }\n\n const partitionResults = await Promise.all(\n partitionTargets.map(async (part, partitionIdx) => {\n const label = partitionTargets.length > 1 ? ` [partition ${part + 1}/${partitionCount}]` : ''\n if (partitionTargets.length === 1) {\n console.log(` -> processing${label}`)\n } else if (verbose && partitionIdx === 0) {\n console.log(` -> processing partitions in parallel (count=${partitionTargets.length})`)\n }\n const partitionContainer = await createRequestContainer()\n const partitionEm = partitionContainer.resolve<EntityManager>('em')\n let partitionVectorService: VectorIndexService | null = null\n try {\n partitionVectorService = partitionContainer.resolve<VectorIndexService>('vectorIndexService')\n } catch {\n partitionVectorService = null\n }\n try {\n let progressBar: ProgressBarHandle | null = null\n const useBar = partitionTargets.length === 1\n const result = await reindexEntity(partitionEm, {\n entityType: id,\n tenantId,\n organizationId: orgId,\n force,\n batchSize,\n emitVectorizeEvents: false,\n partitionCount,\n partitionIndex: part,\n resetCoverage: shouldResetCoverage(part),\n vectorService: partitionVectorService,\n onProgress(info) {\n if (useBar) {\n if (info.total > 0 && !progressBar) {\n progressBar = createProgressBar(`Reindexing ${id}${label}`, info.total) as ProgressBarHandle\n }\n progressBar?.update(info.processed)\n } else if (groupedProgress) {\n groupedProgress.onProgress(part, info)\n } else {\n renderProgress(part, id, info)\n }\n },\n })\n if (progressBar) {\n (progressBar as ProgressBarHandle).complete()\n }\n warnIfReindexRefused(id, result)\n if (!useBar && groupedProgress) {\n groupedProgress.onProgress(part, { processed: result.processed, total: result.total })\n } else if (!useBar) {\n renderProgress(part, id, { processed: result.processed, total: result.total })\n } else {\n console.log(\n ` processed ${result.processed} row(s)${result.total ? ` (base ${result.total})` : ''}`,\n )\n }\n return result.processed\n } finally {\n if (typeof (partitionContainer as any)?.dispose === 'function') {\n await (partitionContainer as any).dispose()\n }\n }\n }),\n )\n groupedProgress?.complete()\n const totalProcessed = partitionResults.reduce((acc, value) => acc + value, 0)\n console.log(` -> ${id} complete: processed ${totalProcessed} row(s) across ${partitionTargets.length} partition(s)`)\n if (partitionIndexOption === undefined) {\n await verifyAndRepairIndexCoverage(baseEm, {\n entityType: id,\n tenantId,\n organizationId: orgId,\n batchSize,\n })\n }\n await recordIndexerLog(\n { em: baseEm },\n {\n source: 'query_index',\n handler: 'cli:query_index.reindex',\n message: `Reindex completed for ${id}`,\n entityType: id,\n tenantId: tenantId ?? null,\n organizationId: orgId ?? null,\n details: {\n processed: totalProcessed,\n partitions: partitionTargets.length,\n partitionCount,\n partitionIndex: partitionIndexOption ?? null,\n },\n },\n ).catch(() => undefined)\n }\n console.log(`Finished reindexing ${entityIds.length} entities`)\n } catch (error) {\n const targetLabel = entity ?? 'multiple entities'\n await recordIndexerLog(\n { em: baseEm },\n {\n source: 'query_index',\n handler: 'cli:query_index.reindex',\n level: 'warn',\n message: `Reindex failed for ${targetLabel}`,\n entityType: entity ?? null,\n tenantId: tenantId ?? null,\n organizationId: orgId ?? null,\n details: {\n error: error instanceof Error ? error.message : String(error),\n },\n },\n ).catch(() => undefined)\n await recordIndexerError(\n { em: baseEm },\n {\n source: 'query_index',\n handler: 'cli:query_index.reindex',\n error,\n entityType: entity ?? null,\n tenantId,\n organizationId: orgId ?? null,\n payload: {\n args,\n partitionTargets,\n partitionCount,\n partitionIndex: partitionIndexOption,\n force,\n skipPurge,\n },\n },\n )\n throw error\n } finally {\n if (typeof (container as any)?.dispose === 'function') {\n await (container as any).dispose()\n }\n }\n },\n}\n\nconst purge: ModuleCli = {\n command: 'purge',\n async run(rest) {\n const args = parseArgs(rest)\n const entity = stringOption(args, 'entity', 'e')\n const orgId = stringOption(args, 'org', 'organizationId')\n const tenantId = stringOption(args, 'tenant', 'tenantId')\n\n const container = await createRequestContainer()\n let em: EntityManager | null = null\n try {\n em = (container.resolve('em') as EntityManager)\n } catch {\n em = null\n }\n\n try {\n const bus = container.resolve('eventBus') as {\n emitEvent(event: string, payload: any, options?: any): Promise<void>\n }\n if (entity) {\n await bus.emitEvent(\n 'query_index.purge',\n { entityType: entity, organizationId: orgId, tenantId },\n { persistent: true },\n )\n await recordIndexerLog(\n { em: em ?? undefined },\n {\n source: 'query_index',\n handler: 'cli:query_index.purge',\n message: `Purge requested for ${entity}`,\n entityType: entity,\n tenantId: tenantId ?? null,\n organizationId: orgId ?? null,\n },\n ).catch(() => undefined)\n console.log(`Scheduled purge for ${entity}`)\n return\n }\n\n const { getEntityIds } = await import('@open-mercato/shared/lib/encryption/entityIds')\n const entityIds = flattenSystemEntityIds(getEntityIds() as Record<string, Record<string, string>>)\n for (const id of entityIds) {\n await bus.emitEvent(\n 'query_index.purge',\n { entityType: id, organizationId: orgId, tenantId },\n { persistent: true },\n )\n await recordIndexerLog(\n { em: em ?? undefined },\n {\n source: 'query_index',\n handler: 'cli:query_index.purge',\n message: `Purge requested for ${id}`,\n entityType: id,\n tenantId: tenantId ?? null,\n organizationId: orgId ?? null,\n details: { mode: 'bulk' },\n },\n ).catch(() => undefined)\n }\n console.log(`Scheduled purge for ${entityIds.length} entities`)\n } catch (error) {\n await recordIndexerLog(\n { em: em ?? undefined },\n {\n source: 'query_index',\n handler: 'cli:query_index.purge',\n level: 'warn',\n message: `Purge scheduling failed${entity ? ` for ${entity}` : ''}`,\n entityType: entity ?? null,\n tenantId: tenantId ?? null,\n organizationId: orgId ?? null,\n details: { error: error instanceof Error ? error.message : String(error) },\n },\n ).catch(() => undefined)\n await recordIndexerError(\n { em: em ?? undefined },\n {\n source: 'query_index',\n handler: 'cli:query_index.purge',\n error,\n entityType: entity ?? null,\n tenantId,\n organizationId: orgId,\n payload: { args },\n },\n )\n throw error\n } finally {\n if (typeof (container as any)?.dispose === 'function') {\n await (container as any).dispose()\n }\n }\n },\n}\n\nexport default [rebuild, rebuildAll, reindex, purge]\n"],
|
|
5
|
-
"mappings": "AACA,SAAS,8BAA8B;AAEvC,SAAsB,WAAW;AACjC,SAAS,yBAAyB;AAClC,SAAS,sCAAsC;AAC/C,SAAS,0BAA0B,iCAAiC;AACpE,SAAS,yBAAyB;AAMlC,SAAS,wBAAwB,wCAAwC;AACzE,SAAS,0BAA0B;AACnC,SAAS,wBAAwB;AACjC;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAEK;AACP,SAAS,eAAe,kCAAkC;AAO1D,SAAS,qBAAqB,YAAoB,QAAgC;AAChF,MAAI,CAAC,OAAO,QAAS;AACrB,QAAM,SAAS,OAAO,YAAY,qBAC9B,+FACA,OAAO,YAAY,mCACjB,8FACA;AACN,UAAQ,KAAK,QAAQ,UAAU,4CAA4C,MAAM,EAAE;AACrF;AACA,SAAS,uBAAuB;AAChC,SAAS,+BAA+B;AACxC,SAAS,8BAA8B;AAOvC,SAAS,mBAA4B;AACnC,QAAM,SAAS,kBAAkB,QAAQ,IAAI,sBAAsB,EAAE;AACrE,SAAO,WAAW;AACpB;AAEA,SAAS,sBAAsB,OAAe,kBAA4B;AACxE,QAAM,SAAS,oBAAI,IAAoB;AACvC,QAAM,YAAY,oBAAI,IAAoB;AAC1C,MAAI,MAAgC;AAEpC,QAAM,YAAY,MAAM;AACtB,QAAI,QAAQ;AACZ,QAAI,OAAO;AACX,eAAW,SAAS,OAAO,OAAO,EAAG,UAAS;AAC9C,eAAW,SAAS,UAAU,OAAO,EAAG,SAAQ;AAChD,WAAO,EAAE,OAAO,KAAK;AAAA,EACvB;AAEA,QAAM,aAAa,MAAM;AACvB,QAAI,IAAK;AACT,QAAI,OAAO,OAAO,iBAAiB,OAAQ;AAC3C,UAAM,EAAE,MAAM,IAAI,UAAU;AAC5B,QAAI,SAAS,EAAG;AAChB,UAAM,kBAAkB,OAAO,KAAK;AAAA,EACtC;AAEA,SAAO;AAAA,IACL,WAAW,WAAmB,MAA6B;AACzD,gBAAU,IAAI,WAAW,KAAK,SAAS;AACvC,UAAI,CAAC,OAAO,IAAI,SAAS,EAAG,QAAO,IAAI,WAAW,KAAK,KAAK;AAC5D,iBAAW;AACX,UAAI,CAAC,IAAK;AACV,YAAM,EAAE,KAAK,IAAI,UAAU;AAC3B,UAAI,OAAO,IAAI;AAAA,IACjB;AAAA,IACA,WAAW;AACT,UAAI,IAAK,KAAI,SAAS;AAAA,IACxB;AAAA,IACA;AAAA,EACF;AACF;AAEA,SAAS,UAAU,MAA4B;AAC7C,QAAM,OAAmB,CAAC;AAC1B,WAAS,IAAI,GAAG,IAAI,KAAK,QAAQ,KAAK,GAAG;AACvC,UAAM,OAAO,KAAK,CAAC;AACnB,QAAI,CAAC,MAAM,WAAW,IAAI,EAAG;AAC7B,UAAM,CAAC,QAAQ,QAAQ,IAAI,KAAK,MAAM,CAAC,EAAE,MAAM,GAAG;AAClD,QAAI,CAAC,OAAQ;AACb,QAAI,aAAa,QAAW;AAC1B,WAAK,MAAM,IAAI;AAAA,IACjB,WAAW,IAAI,IAAI,KAAK,UAAU,CAAC,KAAK,IAAI,CAAC,EAAG,WAAW,IAAI,GAAG;AAChE,WAAK,MAAM,IAAI,KAAK,IAAI,CAAC;AACzB,WAAK;AAAA,IACP,OAAO;AACL,WAAK,MAAM,IAAI;AAAA,IACjB;AAAA,EACF;AACA,SAAO;AACT;AAEA,SAAS,aAAa,SAAqB,MAAoC;AAC7E,aAAW,OAAO,MAAM;AACtB,UAAM,MAAM,KAAK,GAAG;AACpB,QAAI,OAAO,QAAQ,SAAU;AAC7B,UAAM,UAAU,IAAI,KAAK;AACzB,QAAI,QAAQ,SAAS,EAAG,QAAO;AAAA,EACjC;AACA,SAAO;AACT;AAEA,SAAS,aAAa,SAAqB,MAAoC;AAC7E,aAAW,OAAO,MAAM;AACtB,UAAM,MAAM,KAAK,GAAG;AACpB,QAAI,OAAO,QAAQ,SAAU,QAAO;AACpC,QAAI,OAAO,QAAQ,UAAU;AAC3B,YAAM,SAAS,OAAO,GAAG;AACzB,UAAI,OAAO,SAAS,MAAM,EAAG,QAAO;AAAA,IACtC;AAAA,EACF;AACA,SAAO;AACT;AAEA,SAAS,YAAY,SAAqB,MAAyB;AACjE,aAAW,OAAO,MAAM;AACtB,UAAM,MAAM,KAAK,GAAG;AACpB,QAAI,QAAQ,OAAW;AACvB,QAAI,QAAQ,KAAM,QAAO;AACzB,QAAI,QAAQ,MAAO;AACnB,QAAI,OAAO,QAAQ,UAAU;AAC3B,YAAM,UAAU,IAAI,KAAK;AACzB,UAAI,CAAC,QAAS,QAAO;AACrB,YAAM,SAAS,kBAAkB,OAAO;AACxC,aAAO,WAAW,OAAO,OAAO;AAAA,IAClC;AAAA,EACF;AACA,SAAO;AACT;AAEA,SAAS,cAAc,OAA+C;AACpE,MAAI,UAAU,OAAW,QAAO;AAChC,QAAM,IAAI,KAAK,MAAM,KAAK;AAC1B,MAAI,CAAC,OAAO,SAAS,CAAC,KAAK,KAAK,EAAG,QAAO;AAC1C,SAAO;AACT;AAEA,SAAS,iBAAiB,OAA2B,WAAW,GAAW;AACzE,MAAI,UAAU,OAAW,QAAO;AAChC,QAAM,IAAI,KAAK,MAAM,KAAK;AAC1B,MAAI,CAAC,OAAO,SAAS,CAAC,KAAK,IAAI,EAAG,QAAO;AACzC,SAAO;AACT;AAEA,MAAM,qBAAqB;AAyB3B,eAAe,qBAAqB,SAA0D;AAC5F,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,IAAI;AAEJ,QAAM,aAAa,+BAA+B,EAAS;AAC3D,QAAM,cAAc,oBAAI,IAAkC;AAK1D,QAAM,aAAa,OACjB,cACA,KACA,UACG;AACH,WAAO,MAAM;AAAA,MACX;AAAA,MACA;AAAA,MACA,EAAE,UAAU,MAAM,YAAY,MAAM,gBAAgB,MAAM,kBAAkB,KAAK;AAAA,MACjF;AAAA,IACF;AAAA,EACF;AAEA,QAAM,aAAa,OACjB,cACA,KACA,UACG;AACH,WAAO,MAAM;AAAA,MACX;AAAA,MACA;AAAA,MACA,EAAE,UAAU,MAAM,YAAY,MAAM,gBAAgB,MAAM,kBAAkB,KAAK;AAAA,MACjF;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAEA,QAAM,eAAe,CAA+C,MAAc;AAChF,QAAI,QAAQ;AACZ,QAAI,CAAC,QAAQ;AACX,UAAI,gBAAgB,UAAa,mBAAmB;AAClD,gBAAQ,MAAM,MAAM,mBAA0B,KAAK,WAAW;AAAA,MAChE;AACA,UAAI,mBAAmB,UAAa,sBAAsB;AACxD,gBAAQ,MAAM,MAAM,aAAoB,KAAK,cAAc;AAAA,MAC7D;AAAA,IACF;AACA,QAAI,CAAC,kBAAkB,uBAAuB;AAC5C,cAAQ,MAAM,MAAM,cAAqB,MAAM,IAAW;AAAA,IAC5D;AACA,WAAO;AAAA,EACT;AAEA,MAAI,UAAU;AACZ,UAAM,MAAM,MAAM;AAAA,MAChB,GAAG,WAAW,SAAgB,EAAE,UAAU;AAAA,IAC5C,EACG,MAAM,MAAa,KAAK,QAAQ,EAChC,iBAAiB;AACpB,QAAI,CAAC,IAAK,QAAO,EAAE,WAAW,GAAG,SAAS,EAAE;AAC5C,UAAMA,OAAM,kBAAkB,iBAAiB,cAAc,UAAU,IAAI,CAAC;AAC5E,UAAM,eAAe,MAAM,iBAAiB,IAAI,YAAY,CAAC,GAAG,GAAG,EAAE,OAAO,aAAa,UAAU,eAAe,GAAG,EAAE,YAAY,WAAW,CAAC;AAC/I,IAAAA,KAAI,OAAO,aAAa,OAAO;AAC/B,IAAAA,KAAI,SAAS;AACb,iCAA6B,YAAY,YAAY;AACrD,WAAO,EAAE,WAAW,aAAa,SAAS,SAAS,EAAE;AAAA,EACvD;AAEA,QAAM,WAAW,MAAM;AAAA,IACrB,GAAG,WAAW,SAAgB,EAAE,OAAO,cAAsB,GAAG,OAAO,CAAC;AAAA,EAC1E,EAAE,iBAAiB;AACnB,QAAM,WAAW,UAAU;AAC3B,QAAM,QAAQ,YAAY,OAAO,OAAO,QAAQ,IAAI;AACpD,QAAM,kBAAkB,KAAK,IAAI,GAAG,MAAM;AAC1C,QAAM,sBAAsB,KAAK,IAAI,GAAG,QAAQ,eAAe;AAC/D,QAAM,aAAa,cAAc,KAAK;AACtC,QAAM,WAAW,eAAe,SAAY,KAAK,IAAI,qBAAqB,UAAU,IAAI;AACxF,MAAI,CAAC,OAAO,SAAS,QAAQ,KAAK,YAAY,GAAG;AAC/C,WAAO,EAAE,WAAW,GAAG,SAAS,EAAE;AAAA,EACpC;AAEA,QAAM,MAAM,kBAAkB,iBAAiB,cAAc,UAAU,IAAI,QAAQ;AACnF,MAAI,YAAY;AAChB,MAAI,UAAU;AACd,MAAI,eAAe;AACnB,MAAI,YAAY;AAChB,QAAM,cAAc,kCAAkC;AAEtD,SAAO,UAAU,UAAU;AACzB,UAAM,aAAa,cAAc,SAAY,KAAK,IAAI,WAAW,SAAS,IAAI;AAC9E,UAAM,QAAQ,MAAM;AAAA,MAClB,GACG,WAAW,SAAgB,EAC3B,UAAU,EACV,QAAQ,IAAW,EACnB,MAAM,UAAU,EAChB,OAAO,YAAY;AAAA,IACxB,EAAE,QAAQ;AACV,QAAI,CAAC,MAAM,OAAQ;AAEnB,UAAM,cAAc,MAAM,iBAAiB,IAAI,YAAY,OAAmB;AAAA,MAC5E,OAAO;AAAA,MACP,UAAU;AAAA,IACZ,GAAG,EAAE,YAAY,WAAW,CAAC;AAC7B,iCAA6B,aAAa,WAAW;AAErD,iBAAa,YAAY;AACzB,eAAW,MAAM;AACjB,oBAAgB,MAAM;AACtB,QAAI,cAAc,OAAW,cAAa,MAAM;AAChD,QAAI,OAAO,SAAS;AACpB,QAAI,cAAc,UAAa,aAAa,EAAG;AAAA,EACjD;AAEA,MAAI,YAAY,UAAU;AACxB,QAAI,OAAO,SAAS;AAAA,EACtB;AACA,MAAI,SAAS;AAEb,+BAA6B,YAAY,WAAW;AACpD,SAAO,EAAE,WAAW,SAAS,SAAS;AACxC;AAEA,eAAe,aAAa,IAAiB,WAAyC;AACpF,MAAI;AACF,UAAM,OAAO,MAAM,GAChB,WAAW,4BAAmC,EAC9C,OAAO,CAAC,aAAoB,CAAC,EAC7B,MAAM,oCAA6C,EACnD,MAAM,cAAqB,KAAK,SAAS,EACzC,QAAQ;AACX,WAAO,IAAI,IAAI,KAAK,IAAI,CAAC,QAAQ,OAAO,IAAI,WAAW,EAAE,YAAY,CAAC,CAAC;AAAA,EACzE,QAAQ;AACN,WAAO,oBAAI,IAAY;AAAA,EACzB;AACF;AAYA,SAAS,cAAc,OAAgC;AACrD,QAAM,QAAkB,CAAC;AACzB,MAAI,MAAM,OAAQ,OAAM,KAAK,QAAQ;AACrC,MAAI,CAAC,MAAM,UAAU,MAAM,SAAS,MAAM,YAAa,OAAM,KAAK,OAAO,MAAM,KAAK,EAAE;AACtF,MAAI,CAAC,MAAM,UAAU,MAAM,YAAY,MAAM,eAAgB,OAAM,KAAK,UAAU,MAAM,QAAQ,EAAE;AAClG,MAAI,CAAC,MAAM,kBAAkB,MAAM,gBAAiB,OAAM,KAAK,aAAa;AAC5E,SAAO,MAAM,SAAS,KAAK,MAAM,KAAK,GAAG,CAAC,MAAM;AAClD;AAMA,MAAM,8BAA8B;AAMpC,eAAe,uBACb,IACA,SAOmB;AACnB,QAAM,UAAU,MAAM,aAAa,IAAI,QAAQ,SAAS;AACxD,MAAI,QAAQ,GACT,WAAW,GAAG,QAAQ,SAAS,OAAc,EAC7C,OAAO,MAAa,EACpB;AAAA,IAAM,CAAC,EAAE,KAAK,QAAQ,WAAW,MAChC,IAAI;AAAA,MACF,WAAW,sBAA6B,EACrC,OAAO,OAAO,GAAG,KAAK,CAAC,EACvB,SAAS,gBAAuB,KAAK,eAAe,EACpD,MAAM,kBAAyB,KAAK,QAAQ,UAAU,EACtD,MAAM,iBAAwB,MAAM,IAAW;AAAA,IACpD,CAAC;AAAA,EACH,EACC,MAAM,QAAQ,KAAK;AACtB,MAAI,QAAQ,IAAI,YAAY,EAAG,SAAQ,MAAM,MAAM,gBAAuB,MAAM,IAAW;AAC3F,MAAI,QAAQ,YAAY,QAAQ,QAAQ,IAAI,WAAW,GAAG;AACxD,YAAQ,MAAM,MAAM,eAAsB,KAAK,QAAQ,QAAQ;AAAA,EACjE;AACA,MAAI,QAAQ,kBAAkB,QAAQ,QAAQ,IAAI,iBAAiB,GAAG;AACpE,YAAQ,MAAM,MAAM,qBAA4B,KAAK,QAAQ,cAAc;AAAA,EAC7E;AACA,QAAM,OAAO,MAAM,MAAM,QAAQ;AACjC,SAAO,KAAK,IAAI,CAAC,QAAQ,OAAO,IAAI,EAAE,CAAC;AACzC;AASA,eAAe,6BACb,IACA,SAMe;AACf,QAAM,QAAQ;AAAA,IACZ,YAAY,QAAQ;AAAA,IACpB,UAAU,QAAQ,YAAY;AAAA,IAC9B,gBAAgB,QAAQ,kBAAkB;AAAA,IAC1C,aAAa;AAAA,EACf;AAEA,MAAI,SAA6D;AACjE,MAAI;AACF,aAAS,MAAM,wBAAwB,IAAI,KAAK;AAAA,EAClD,SAAS,OAAO;AACd,YAAQ;AAAA,MACN,QAAQ,QAAQ,UAAU,oCAAoC,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC;AAAA,IACtH;AACA;AAAA,EACF;AACA,MAAI,CAAC,OAAQ;AACb,MAAI,OAAO,eAAe,OAAO,WAAW;AAI1C,YAAQ;AAAA,MACN,QAAQ,QAAQ,UAAU,KAAK,OAAO,YAAY,mBAAmB,OAAO,SAAS;AAAA,IACvF;AACA;AAAA,EACF;AACA,MAAI,OAAO,iBAAiB,OAAO,UAAW;AAE9C,QAAM,KAAM,GAAW,UAAU;AACjC,MAAI,YAA2B;AAC/B,MAAI;AACF,gBAAY,iCAAiC,IAAW,QAAQ,UAAU;AAAA,EAC5E,QAAQ;AACN,gBAAY;AAAA,EACd;AAEA,QAAM,aAAa,YACf,MAAM,uBAAuB,IAAI;AAAA,IACjC,YAAY,QAAQ;AAAA,IACpB;AAAA,IACA,UAAU,QAAQ,YAAY;AAAA,IAC9B,gBAAgB,QAAQ,kBAAkB;AAAA,IAC1C,OAAO,8BAA8B;AAAA,EACvC,CAAC,EAAE,MAAM,MAAM,IAAI,IACjB;AAEJ,QAAM,WAAW,cAAc,WAAW,SAAS,KAAK,WAAW,UAAU;AAC7E,UAAQ;AAAA,IACN,QAAQ,QAAQ,UAAU,KAAK,OAAO,YAAY,IAAI,OAAO,SAAS,0CACjE,WAAW,IAAI,WAAY,MAAM,uBAAuB,mBAAmB;AAAA,EAClF;AAEA,MAAI;AACF,QAAI,UAAU;AACZ,YAAM,UAAU,MAAM,aAAa,IAAI,SAAU;AACjD,iBAAW,YAAY,YAAa;AAClC,cAAM,qBAAqB;AAAA,UACzB;AAAA,UACA;AAAA,UACA,YAAY,QAAQ;AAAA,UACpB;AAAA,UACA,aAAa,QAAQ,kBAAkB;AAAA,UACvC,gBAAgB,QAAQ,YAAY;AAAA,UACpC,QAAQ;AAAA,UACR,gBAAgB;AAAA,UAChB,QAAQ;AAAA,UACR;AAAA,UACA,WAAW;AAAA,UACX,mBAAmB,QAAQ,IAAI,iBAAiB;AAAA,UAChD,sBAAsB,QAAQ,IAAI,WAAW;AAAA,UAC7C,uBAAuB,QAAQ,IAAI,YAAY;AAAA,QACjD,CAAC;AAAA,MACH;AAAA,IACF,OAAO;AACL,YAAM,eAAe,MAAM,cAAc,IAAI;AAAA,QAC3C,YAAY,QAAQ;AAAA,QACpB,UAAU,QAAQ;AAAA,QAClB,gBAAgB,QAAQ;AAAA,QACxB,OAAO;AAAA,QACP,WAAW,QAAQ;AAAA,QACnB,qBAAqB;AAAA,QACrB,eAAe;AAAA,MACjB,CAAC;AACD,2BAAqB,QAAQ,YAAY,YAAY;AAAA,IACvD;AAAA,EACF,SAAS,OAAO;AACd,YAAQ;AAAA,MACN,QAAQ,QAAQ,UAAU,yBAAyB,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC;AAAA,IAC3G;AACA;AAAA,EACF;AAEA,QAAM,QAAQ,MAAM,wBAAwB,IAAI,KAAK,EAAE,MAAM,MAAM,IAAI;AACvE,MAAI,SAAS,MAAM,eAAe,MAAM,WAAW;AACjD,YAAQ;AAAA,MACN,QAAQ,QAAQ,UAAU,WAAW,MAAM,YAAY,IAAI,MAAM,SAAS;AAAA,IAC5E;AAAA,EACF,OAAO;AACL,YAAQ,IAAI,QAAQ,QAAQ,UAAU,qBAAqB;AAAA,EAC7D;AACF;AAEA,MAAM,UAAqB;AAAA,EACzB,SAAS;AAAA,EACT,MAAM,IAAI,MAAM;AACd,UAAM,OAAO,UAAU,IAAI;AAC3B,UAAM,SAAS,aAAa,MAAM,UAAU,GAAG;AAC/C,QAAI,CAAC,QAAQ;AACX,cAAQ;AAAA,QACN;AAAA,MACF;AACA;AAAA,IACF;AAEA,UAAM,aAAa,YAAY,MAAM,QAAQ;AAC7C,UAAM,iBAAiB,YAAY,MAAM,aAAa;AACtD,UAAM,QAAQ,aAAa,MAAM,OAAO,gBAAgB;AACxD,UAAM,WAAW,aAAa,MAAM,UAAU,UAAU;AACxD,UAAM,WAAW,aAAa,MAAM,UAAU,YAAY,IAAI;AAC9D,UAAM,QAAQ,cAAc,aAAa,MAAM,OAAO,CAAC;AACvD,UAAM,SAAS,iBAAiB,aAAa,MAAM,QAAQ,CAAC;AAC5D,UAAM,YAAY,cAAc,aAAa,MAAM,SAAS,SAAS,MAAM,CAAC,KAAK;AAEjF,UAAM,YAAY,MAAM,uBAAuB;AAC/C,UAAM,KAAM,UAAU,QAAQ,IAAI;AAClC,QAAI;AACF,YAAM,KAAK,GAAG,UAAe;AAC7B,YAAM,YAAY,uBAAuB,IAAI,MAAM;AACnD,YAAM,UAAU,MAAM,aAAa,IAAI,SAAS;AAChD,YAAM,cAAc,QAAQ,IAAI,iBAAiB;AACjD,YAAM,iBAAiB,QAAQ,IAAI,WAAW;AAC9C,YAAM,kBAAkB,QAAQ,IAAI,YAAY;AAEhD,UAAI,CAAC,cAAc,SAAS,CAAC,aAAa;AACxC,gBAAQ,KAAK,iBAAiB,MAAM,yDAAyD;AAAA,MAC/F;AACA,UAAI,CAAC,cAAc,YAAY,CAAC,gBAAgB;AAC9C,gBAAQ,KAAK,iBAAiB,MAAM,sDAAsD;AAAA,MAC5F;AACA,UAAI,CAAC,kBAAkB,CAAC,iBAAiB;AACvC,gBAAQ,KAAK,iBAAiB,MAAM,uDAAuD;AAAA,MAC7F;AAEA,YAAM,SAAS,MAAM,qBAAqB;AAAA,QACxC;AAAA,QACA;AAAA,QACA,YAAY;AAAA,QACZ;AAAA,QACA,aAAa;AAAA,QACb,gBAAgB;AAAA,QAChB,QAAQ;AAAA,QACR;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA,eAAe,WAAW,cAAc,MAAM,WAAW,QAAQ,KAAK,cAAc,MAAM;AAAA,QAC1F,mBAAmB;AAAA,QACnB,sBAAsB;AAAA,QACtB,uBAAuB;AAAA,MACzB,CAAC;AAED,UAAI,UAAU;AACZ,YAAI,OAAO,cAAc,GAAG;AAC1B,kBAAQ,IAAI,6BAA6B,MAAM,YAAY,QAAQ,EAAE;AAAA,QACvE,OAAO;AACL,kBAAQ,IAAI,qBAAqB,MAAM,WAAW,QAAQ,EAAE;AAAA,QAC9D;AACA;AAAA,MACF;AAEA,YAAM,aAAa,cAAc;AAAA,QAC/B,QAAQ;AAAA,QACR;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF,CAAC;AAED,UAAI,OAAO,YAAY,GAAG;AACxB,gBAAQ,IAAI,+BAA+B,MAAM,GAAG,UAAU,EAAE;AAChE;AAAA,MACF;AAEA,cAAQ,IAAI,WAAW,OAAO,SAAS,eAAe,MAAM,GAAG,UAAU,EAAE;AAAA,IAC7E,SAAS,OAAO;AACd,YAAM;AAAA,QACJ,EAAE,GAAG;AAAA,QACL;AAAA,UACE,QAAQ;AAAA,UACR,SAAS;AAAA,UACT;AAAA,UACA,YAAY;AAAA,UACZ;AAAA,UACA;AAAA,UACA,gBAAgB;AAAA,UAChB,SAAS,EAAE,KAAK;AAAA,QAClB;AAAA,MACF;AACA,YAAM;AAAA,IACR,UAAE;AACA,UAAI,OAAQ,WAAmB,YAAY,YAAY;AACrD,cAAO,UAAkB,QAAQ;AAAA,MACnC;AAAA,IACF;AAAA,EACF;AACF;AAEA,MAAM,aAAwB;AAAA,EAC5B,SAAS;AAAA,EACT,MAAM,IAAI,MAAM;AACd,UAAM,OAAO,UAAU,IAAI;AAC3B,UAAM,aAAa,YAAY,MAAM,QAAQ;AAC7C,UAAM,iBAAiB,YAAY,MAAM,aAAa;AACtD,UAAM,QAAQ,aAAa,MAAM,OAAO,gBAAgB;AACxD,UAAM,WAAW,aAAa,MAAM,UAAU,UAAU;AACxD,UAAM,QAAQ,cAAc,aAAa,MAAM,OAAO,CAAC;AACvD,UAAM,SAAS,iBAAiB,aAAa,MAAM,QAAQ,CAAC;AAC5D,UAAM,YAAY,cAAc,aAAa,MAAM,SAAS,SAAS,MAAM,CAAC,KAAK;AACjF,UAAM,WAAW,aAAa,MAAM,UAAU,YAAY,IAAI;AAC9D,QAAI,UAAU;AACZ,cAAQ,MAAM,mGAAmG;AACjH;AAAA,IACF;AAEA,UAAM,YAAY,MAAM,uBAAuB;AAC/C,UAAM,KAAM,UAAU,QAAQ,IAAI;AAClC,QAAI;AACF,YAAM,KAAK,GAAG,UAAe;AAE7B,YAAM,EAAE,aAAa,IAAI,MAAM,OAAO,+CAA+C;AACrF,YAAM,YAAY,uBAAuB,aAAa,CAA2C;AACjG,UAAI,CAAC,UAAU,QAAQ;AACrB,gBAAQ,IAAI,sDAAsD;AAClE;AAAA,MACF;AAEA,UAAI,iBAAiB;AACrB,eAAS,MAAM,GAAG,MAAM,UAAU,QAAQ,OAAO,GAAG;AAClD,cAAM,SAAS,UAAU,GAAG;AAC5B,cAAM,YAAY,uBAAuB,IAAI,MAAM;AACnD,cAAM,UAAU,MAAM,aAAa,IAAI,SAAS;AAChD,cAAM,cAAc,QAAQ,IAAI,iBAAiB;AACjD,cAAM,iBAAiB,QAAQ,IAAI,WAAW;AAC9C,cAAM,kBAAkB,QAAQ,IAAI,YAAY;AAEhD,YAAI,CAAC,cAAc,SAAS,CAAC,aAAa;AACxC,kBAAQ,KAAK,iBAAiB,MAAM,yDAAyD;AAAA,QAC/F;AACA,YAAI,CAAC,cAAc,YAAY,CAAC,gBAAgB;AAC9C,kBAAQ,KAAK,iBAAiB,MAAM,sDAAsD;AAAA,QAC5F;AACA,YAAI,CAAC,kBAAkB,CAAC,iBAAiB;AACvC,kBAAQ,KAAK,iBAAiB,MAAM,uDAAuD;AAAA,QAC7F;AAEA,cAAM,aAAa,cAAc;AAAA,UAC/B,QAAQ;AAAA,UACR;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,QACF,CAAC;AAED,gBAAQ,IAAI,IAAI,MAAM,CAAC,IAAI,UAAU,MAAM,gBAAgB,MAAM,GAAG,UAAU,EAAE;AAChF,cAAM,SAAS,MAAM,qBAAqB;AAAA,UACxC;AAAA,UACA;AAAA,UACA,YAAY;AAAA,UACZ;AAAA,UACA,aAAa;AAAA,UACb,gBAAgB;AAAA,UAChB,QAAQ;AAAA,UACR;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA,mBAAmB;AAAA,UACnB,sBAAsB;AAAA,UACtB,uBAAuB;AAAA,QACzB,CAAC;AACD,0BAAkB,OAAO;AACzB,YAAI,OAAO,YAAY,GAAG;AACxB,kBAAQ,IAAI,8BAA8B;AAAA,QAC5C,OAAO;AACL,kBAAQ,IAAI,kBAAkB,OAAO,SAAS,SAAS;AAAA,QACzD;AAAA,MACF;AAEA,cAAQ,IAAI,oDAAoD,cAAc,UAAU;AAAA,IAC1F,SAAS,OAAO;AACd,YAAM;AAAA,QACJ,EAAE,GAAG;AAAA,QACL;AAAA,UACE,QAAQ;AAAA,UACR,SAAS;AAAA,UACT;AAAA,UACA;AAAA,UACA,gBAAgB;AAAA,UAChB,SAAS,EAAE,KAAK;AAAA,QAClB;AAAA,MACF;AACA,YAAM;AAAA,IACR,UAAE;AACA,UAAI,OAAQ,WAAmB,YAAY,YAAY;AACrD,cAAO,UAAkB,QAAQ;AAAA,MACnC;AAAA,IACF;AAAA,EACF;AACF;AAEA,MAAM,UAAqB;AAAA,EACzB,SAAS;AAAA,EACT,MAAM,IAAI,MAAM;AACd,UAAM,OAAO,UAAU,IAAI;AAC3B,UAAM,SAAS,aAAa,MAAM,UAAU,GAAG;AAC/C,UAAM,QAAQ,aAAa,MAAM,OAAO,gBAAgB;AACxD,UAAM,WAAW,aAAa,MAAM,UAAU,UAAU;AACxD,UAAM,QAAQ,YAAY,MAAM,SAAS,MAAM;AAC/C,UAAM,YAAY,cAAc,aAAa,MAAM,SAAS,SAAS,MAAM,CAAC;AAC5E,UAAM,mBAAmB,cAAc,aAAa,MAAM,cAAc,kBAAkB,UAAU,CAAC;AACrG,UAAM,0BAA0B,aAAa,MAAM,aAAa,gBAAgB;AAChF,UAAM,oBAAoB,YAAY,MAAM,eAAe;AAC3D,UAAM,wBAAwB,YAAY,MAAM,qBAAqB,iBAAiB;AACtF,UAAM,YAAY,YAAY,MAAM,aAAa,SAAS;AAE1D,UAAM,YAAY,MAAM,uBAAuB;AAC/C,UAAM,SAAU,UAAU,QAAQ,IAAI;AACtC,UAAM,uBACJ,4BAA4B,SAAY,SAAY,iBAAiB,yBAAyB,CAAC;AACjG,UAAM,iBAAiB,KAAK;AAAA,MAC1B;AAAA,MACA,oBAAoB;AAAA,IACtB;AAEA,QAAI,yBAAyB,UAAa,wBAAwB,gBAAgB;AAChF,cAAQ,MAAM,mBAAmB,oBAAoB,+BAA+B,cAAc,GAAG;AACrG,UAAI,OAAQ,WAAmB,YAAY,YAAY;AACrD,cAAO,UAAkB,QAAQ;AAAA,MACnC;AACA;AAAA,IACF;AAEA,UAAM,mBACJ,yBAAyB,SACrB,CAAC,oBAAoB,IACrB,MAAM,KAAK,EAAE,QAAQ,eAAe,GAAG,CAAC,GAAG,QAAQ,GAAG;AAE5D,UAAM,sBAAsB,CAAC,cAA+B;AAC1D,UAAI,kBAAmB,QAAO;AAC9B,UAAI,sBAAuB,QAAO;AAClC,UAAI,yBAAyB,OAAW,QAAO,yBAAyB;AACxE,aAAO,cAAc,iBAAiB,CAAC;AAAA,IACzC;AAEA,QAAI;AACF,UAAI,QAAQ;AACV,cAAM;AAAA,UACJ,EAAE,IAAI,OAAO;AAAA,UACb;AAAA,YACE,QAAQ;AAAA,YACR,SAAS;AAAA,YACT,SAAS,uBAAuB,MAAM;AAAA,YACtC,YAAY;AAAA,YACZ,UAAU,YAAY;AAAA,YACtB,gBAAgB,SAAS;AAAA,YACzB,SAAS;AAAA,cACP;AAAA,cACA,YAAY,iBAAiB;AAAA,cAC7B;AAAA,cACA,gBAAgB,wBAAwB;AAAA,cACxC;AAAA,YACF;AAAA,UACF;AAAA,QACF,EAAE,MAAM,MAAM,MAAS;AACvB,YAAI,CAAC,WAAW;AACd,kBAAQ,IAAI,mCAAmC,MAAM,KAAK;AAC1D,gBAAM,gBAAgB,QAAQ,EAAE,YAAY,QAAQ,gBAAgB,OAAO,SAAS,CAAC;AAAA,QACvF;AACA,gBAAQ,IAAI,cAAc,MAAM,GAAG,QAAQ,cAAc,EAAE,OAAO,iBAAiB,MAAM,kBAAkB;AAC3G,cAAM,UAAU,iBAAiB;AACjC,cAAM,gBAAgB,UAAU,oBAAI,IAA8B,IAAI;AACtE,cAAM,kBACJ,CAAC,WAAW,iBAAiB,SAAS,IAClC,sBAAsB,cAAc,MAAM,IAAI,gBAAgB,IAC9D;AACN,cAAM,iBAAiB,CAAC,MAAc,UAAkB,SAAgC;AACtF,cAAI,CAAC,cAAe;AACpB,gBAAM,QAAQ,cAAc,IAAI,IAAI,KAAK,EAAE,MAAM,EAAE;AACnD,gBAAM,MAAM,KAAK,IAAI;AACrB,cAAI,MAAM,MAAM,OAAO,OAAQ,KAAK,YAAY,KAAK,MAAO;AAC5D,gBAAM,OAAO;AACb,wBAAc,IAAI,MAAM,KAAK;AAC7B,gBAAM,UAAU,KAAK,QAAQ,KAAM,KAAK,YAAY,KAAK,QAAS,KAAK,QAAQ,CAAC,IAAI;AACpF,kBAAQ;AAAA,YACN,SAAS,QAAQ,eAAe,OAAO,CAAC,IAAI,cAAc,KAAK,KAAK,UAAU,eAAe,CAAC,MAAM,KAAK,MAAM,eAAe,CAAC,KAAK,OAAO;AAAA,UAC7I;AAAA,QACF;AAEA,cAAM,QAAQ,MAAM,QAAQ;AAAA,UAC1B,iBAAiB,IAAI,OAAO,MAAM,QAAQ;AACxC,kBAAM,QAAQ,iBAAiB,SAAS,IAAI,eAAe,OAAO,CAAC,IAAI,cAAc,MAAM;AAC3F,gBAAI,iBAAiB,WAAW,GAAG;AACjC,sBAAQ,IAAI,kBAAkB,KAAK,EAAE;AAAA,YACvC,WAAW,WAAW,QAAQ,GAAG;AAC/B,sBAAQ,IAAI,iDAAiD,iBAAiB,MAAM,GAAG;AAAA,YACzF;AACA,kBAAM,qBAAqB,MAAM,uBAAuB;AACxD,kBAAM,cAAc,mBAAmB,QAAuB,IAAI;AAClE,gBAAI,yBAAoD;AACxD,gBAAI;AACF,uCAAyB,mBAAmB,QAA4B,oBAAoB;AAAA,YAC9F,QAAQ;AACN,uCAAyB;AAAA,YAC3B;AACA,gBAAI;AACF,kBAAI,cAAwC;AAC5C,oBAAM,SAAS,iBAAiB,WAAW;AAC3C,oBAAM,iBAAiB,MAAM,cAAc,aAAa;AAAA,gBACtD,YAAY;AAAA,gBACZ;AAAA,gBACA,gBAAgB;AAAA,gBAChB;AAAA,gBACA;AAAA,gBACA,qBAAqB;AAAA,gBACrB;AAAA,gBACA,gBAAgB;AAAA,gBAChB,eAAe,oBAAoB,IAAI;AAAA,gBACvC,eAAe;AAAA,gBACf,WAAW,MAAM;AACf,sBAAI,QAAQ;AACV,wBAAI,KAAK,QAAQ,KAAK,CAAC,aAAa;AAClC,oCAAc;AAAA,wBACZ,cAAc,MAAM,GAAG,KAAK;AAAA,wBAC5B,KAAK;AAAA,sBACP;AAAA,oBACF;AACA,iCAAa,OAAO,KAAK,SAAS;AAAA,kBACpC,WAAW,iBAAiB;AAC1B,oCAAgB,WAAW,MAAM,IAAI;AAAA,kBACvC,OAAO;AACL,mCAAe,MAAM,QAAQ,IAAI;AAAA,kBACnC;AAAA,gBACF;AAAA,cACF,CAAC;AACD,kBAAI,aAAa;AACf,gBAAC,YAAkC,SAAS;AAAA,cAC9C;AACA,mCAAqB,QAAQ,cAAc;AAC3C,kBAAI,CAAC,UAAU,iBAAiB;AAC9B,gCAAgB,WAAW,MAAM,EAAE,WAAW,eAAe,WAAW,OAAO,eAAe,MAAM,CAAC;AAAA,cACvG,WAAW,CAAC,QAAQ;AAClB,+BAAe,MAAM,QAAQ,EAAE,WAAW,eAAe,WAAW,OAAO,eAAe,MAAM,CAAC;AAAA,cACnG,OAAO;AACL,wBAAQ;AAAA,kBACN,kBAAkB,eAAe,SAAS,UAAU,eAAe,QAAQ,UAAU,eAAe,KAAK,MAAM,EAAE;AAAA,gBACnH;AAAA,cACF;AACA,qBAAO,eAAe;AAAA,YACxB,UAAE;AACA,kBAAI,OAAQ,oBAA4B,YAAY,YAAY;AAC9D,sBAAO,mBAA2B,QAAQ;AAAA,cAC5C;AAAA,YACF;AAAA,UACF,CAAC;AAAA,QACH;AACA,yBAAiB,SAAS;AAC1B,cAAM,iBAAiB,MAAM,OAAO,CAAC,KAAK,UAAU,MAAM,OAAO,CAAC;AAClE,gBAAQ,IAAI,YAAY,MAAM,eAAe,cAAc,kBAAkB,iBAAiB,MAAM,eAAe;AACnH,YAAI,yBAAyB,QAAW;AACtC,gBAAM,6BAA6B,QAAQ;AAAA,YACzC,YAAY;AAAA,YACZ;AAAA,YACA,gBAAgB;AAAA,YAChB;AAAA,UACF,CAAC;AAAA,QACH;AACA,cAAM;AAAA,UACJ,EAAE,IAAI,OAAO;AAAA,UACb;AAAA,YACE,QAAQ;AAAA,YACR,SAAS;AAAA,YACT,SAAS,yBAAyB,MAAM;AAAA,YACxC,YAAY;AAAA,YACZ,UAAU,YAAY;AAAA,YACtB,gBAAgB,SAAS;AAAA,YACzB,SAAS;AAAA,cACP,WAAW;AAAA,cACX,YAAY,iBAAiB;AAAA,cAC7B;AAAA,cACA,gBAAgB,wBAAwB;AAAA,YAC1C;AAAA,UACF;AAAA,QACF,EAAE,MAAM,MAAM,MAAS;AACvB;AAAA,MACF;AAEA,YAAM,EAAE,aAAa,IAAI,MAAM,OAAO,+CAA+C;AACrF,YAAM,YAAY,uBAAuB,aAAa,CAA2C;AACjG,UAAI,CAAC,UAAU,QAAQ;AACrB,gBAAQ,IAAI,sDAAsD;AAClE;AAAA,MACF;AACA,eAAS,MAAM,GAAG,MAAM,UAAU,QAAQ,OAAO,GAAG;AAClD,cAAM,KAAK,UAAU,GAAG;AACxB,cAAM;AAAA,UACJ,EAAE,IAAI,OAAO;AAAA,UACb;AAAA,YACE,QAAQ;AAAA,YACR,SAAS;AAAA,YACT,SAAS,uBAAuB,EAAE;AAAA,YAClC,YAAY;AAAA,YACZ,UAAU,YAAY;AAAA,YACtB,gBAAgB,SAAS;AAAA,YACzB,SAAS;AAAA,cACP;AAAA,cACA,YAAY,iBAAiB;AAAA,cAC7B;AAAA,cACA,gBAAgB,wBAAwB;AAAA,cACxC;AAAA,YACF;AAAA,UACF;AAAA,QACF,EAAE,MAAM,MAAM,MAAS;AACvB,YAAI,CAAC,WAAW;AACd,kBAAQ,IAAI,IAAI,MAAM,CAAC,IAAI,UAAU,MAAM,qCAAqC,EAAE,KAAK;AACvF,gBAAM,gBAAgB,QAAQ,EAAE,YAAY,IAAI,gBAAgB,OAAO,SAAS,CAAC;AAAA,QACnF;AACA,gBAAQ;AAAA,UACN,IAAI,MAAM,CAAC,IAAI,UAAU,MAAM,gBAAgB,EAAE,GAAG,QAAQ,cAAc,EAAE,OAAO,iBAAiB,MAAM;AAAA,QAC5G;AACA,cAAM,UAAU,iBAAiB;AACjC,cAAM,gBAAgB,UAAU,oBAAI,IAA8B,IAAI;AACtE,cAAM,kBACJ,CAAC,WAAW,iBAAiB,SAAS,IAClC,sBAAsB,cAAc,EAAE,IAAI,gBAAgB,IAC1D;AACN,cAAM,iBAAiB,CAAC,MAAc,UAAkB,SAAgC;AACtF,cAAI,CAAC,cAAe;AACpB,gBAAM,QAAQ,cAAc,IAAI,IAAI,KAAK,EAAE,MAAM,EAAE;AACnD,gBAAM,MAAM,KAAK,IAAI;AACrB,cAAI,MAAM,MAAM,OAAO,OAAQ,KAAK,YAAY,KAAK,MAAO;AAC5D,gBAAM,OAAO;AACb,wBAAc,IAAI,MAAM,KAAK;AAC7B,gBAAM,UAAU,KAAK,QAAQ,KAAM,KAAK,YAAY,KAAK,QAAS,KAAK,QAAQ,CAAC,IAAI;AACpF,kBAAQ;AAAA,YACN,SAAS,QAAQ,eAAe,OAAO,CAAC,IAAI,cAAc,KAAK,KAAK,UAAU,eAAe,CAAC,MAAM,KAAK,MAAM,eAAe,CAAC,KAAK,OAAO;AAAA,UAC7I;AAAA,QACF;AAEA,cAAM,mBAAmB,MAAM,QAAQ;AAAA,UACrC,iBAAiB,IAAI,OAAO,MAAM,iBAAiB;AACjD,kBAAM,QAAQ,iBAAiB,SAAS,IAAI,eAAe,OAAO,CAAC,IAAI,cAAc,MAAM;AAC3F,gBAAI,iBAAiB,WAAW,GAAG;AACjC,sBAAQ,IAAI,kBAAkB,KAAK,EAAE;AAAA,YACvC,WAAW,WAAW,iBAAiB,GAAG;AACxC,sBAAQ,IAAI,iDAAiD,iBAAiB,MAAM,GAAG;AAAA,YACzF;AACA,kBAAM,qBAAqB,MAAM,uBAAuB;AACxD,kBAAM,cAAc,mBAAmB,QAAuB,IAAI;AAClE,gBAAI,yBAAoD;AACxD,gBAAI;AACF,uCAAyB,mBAAmB,QAA4B,oBAAoB;AAAA,YAC9F,QAAQ;AACN,uCAAyB;AAAA,YAC3B;AACA,gBAAI;AACF,kBAAI,cAAwC;AAC5C,oBAAM,SAAS,iBAAiB,WAAW;AAC3C,oBAAM,SAAS,MAAM,cAAc,aAAa;AAAA,gBAC9C,YAAY;AAAA,gBACZ;AAAA,gBACA,gBAAgB;AAAA,gBAChB;AAAA,gBACA;AAAA,gBACA,qBAAqB;AAAA,gBACrB;AAAA,gBACA,gBAAgB;AAAA,gBAChB,eAAe,oBAAoB,IAAI;AAAA,gBACvC,eAAe;AAAA,gBACf,WAAW,MAAM;AACf,sBAAI,QAAQ;AACV,wBAAI,KAAK,QAAQ,KAAK,CAAC,aAAa;AAClC,oCAAc,kBAAkB,cAAc,EAAE,GAAG,KAAK,IAAI,KAAK,KAAK;AAAA,oBACxE;AACA,iCAAa,OAAO,KAAK,SAAS;AAAA,kBACpC,WAAW,iBAAiB;AAC1B,oCAAgB,WAAW,MAAM,IAAI;AAAA,kBACvC,OAAO;AACL,mCAAe,MAAM,IAAI,IAAI;AAAA,kBAC/B;AAAA,gBACF;AAAA,cACF,CAAC;AACD,kBAAI,aAAa;AACf,gBAAC,YAAkC,SAAS;AAAA,cAC9C;AACA,mCAAqB,IAAI,MAAM;AAC/B,kBAAI,CAAC,UAAU,iBAAiB;AAC9B,gCAAgB,WAAW,MAAM,EAAE,WAAW,OAAO,WAAW,OAAO,OAAO,MAAM,CAAC;AAAA,cACvF,WAAW,CAAC,QAAQ;AAClB,+BAAe,MAAM,IAAI,EAAE,WAAW,OAAO,WAAW,OAAO,OAAO,MAAM,CAAC;AAAA,cAC/E,OAAO;AACL,wBAAQ;AAAA,kBACN,kBAAkB,OAAO,SAAS,UAAU,OAAO,QAAQ,UAAU,OAAO,KAAK,MAAM,EAAE;AAAA,gBAC3F;AAAA,cACF;AACA,qBAAO,OAAO;AAAA,YAChB,UAAE;AACA,kBAAI,OAAQ,oBAA4B,YAAY,YAAY;AAC9D,sBAAO,mBAA2B,QAAQ;AAAA,cAC5C;AAAA,YACF;AAAA,UACF,CAAC;AAAA,QACH;AACA,yBAAiB,SAAS;AAC1B,cAAM,iBAAiB,iBAAiB,OAAO,CAAC,KAAK,UAAU,MAAM,OAAO,CAAC;AAC7E,gBAAQ,IAAI,QAAQ,EAAE,wBAAwB,cAAc,kBAAkB,iBAAiB,MAAM,eAAe;AACpH,YAAI,yBAAyB,QAAW;AACtC,gBAAM,6BAA6B,QAAQ;AAAA,YACzC,YAAY;AAAA,YACZ;AAAA,YACA,gBAAgB;AAAA,YAChB;AAAA,UACF,CAAC;AAAA,QACH;AACA,cAAM;AAAA,UACJ,EAAE,IAAI,OAAO;AAAA,UACb;AAAA,YACE,QAAQ;AAAA,YACR,SAAS;AAAA,YACT,SAAS,yBAAyB,EAAE;AAAA,YACpC,YAAY;AAAA,YACZ,UAAU,YAAY;AAAA,YACtB,gBAAgB,SAAS;AAAA,YACzB,SAAS;AAAA,cACP,WAAW;AAAA,cACX,YAAY,iBAAiB;AAAA,cAC7B;AAAA,cACA,gBAAgB,wBAAwB;AAAA,YAC1C;AAAA,UACF;AAAA,QACF,EAAE,MAAM,MAAM,MAAS;AAAA,MACzB;AACA,cAAQ,IAAI,uBAAuB,UAAU,MAAM,WAAW;AAAA,IAChE,SAAS,OAAO;AACd,YAAM,cAAc,UAAU;AAC9B,YAAM;AAAA,QACJ,EAAE,IAAI,OAAO;AAAA,QACb;AAAA,UACE,QAAQ;AAAA,UACR,SAAS;AAAA,UACT,OAAO;AAAA,UACP,SAAS,sBAAsB,WAAW;AAAA,UAC1C,YAAY,UAAU;AAAA,UACtB,UAAU,YAAY;AAAA,UACtB,gBAAgB,SAAS;AAAA,UACzB,SAAS;AAAA,YACP,OAAO,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAAA,UAC9D;AAAA,QACF;AAAA,MACF,EAAE,MAAM,MAAM,MAAS;AACvB,YAAM;AAAA,QACJ,EAAE,IAAI,OAAO;AAAA,QACb;AAAA,UACE,QAAQ;AAAA,UACR,SAAS;AAAA,UACT;AAAA,UACA,YAAY,UAAU;AAAA,UACtB;AAAA,UACA,gBAAgB,SAAS;AAAA,UACzB,SAAS;AAAA,YACP;AAAA,YACA;AAAA,YACA;AAAA,YACA,gBAAgB;AAAA,YAChB;AAAA,YACA;AAAA,UACF;AAAA,QACF;AAAA,MACF;AACA,YAAM;AAAA,IACR,UAAE;AACA,UAAI,OAAQ,WAAmB,YAAY,YAAY;AACrD,cAAO,UAAkB,QAAQ;AAAA,MACnC;AAAA,IACF;AAAA,EACF;AACF;AAEA,MAAM,QAAmB;AAAA,EACvB,SAAS;AAAA,EACT,MAAM,IAAI,MAAM;AACd,UAAM,OAAO,UAAU,IAAI;AAC3B,UAAM,SAAS,aAAa,MAAM,UAAU,GAAG;AAC/C,UAAM,QAAQ,aAAa,MAAM,OAAO,gBAAgB;AACxD,UAAM,WAAW,aAAa,MAAM,UAAU,UAAU;AAExD,UAAM,YAAY,MAAM,uBAAuB;AAC/C,QAAI,KAA2B;AAC/B,QAAI;AACF,WAAM,UAAU,QAAQ,IAAI;AAAA,IAC9B,QAAQ;AACN,WAAK;AAAA,IACP;AAEA,QAAI;AACF,YAAM,MAAM,UAAU,QAAQ,UAAU;AAGxC,UAAI,QAAQ;AACV,cAAM,IAAI;AAAA,UACR;AAAA,UACA,EAAE,YAAY,QAAQ,gBAAgB,OAAO,SAAS;AAAA,UACtD,EAAE,YAAY,KAAK;AAAA,QACrB;AACA,cAAM;AAAA,UACJ,EAAE,IAAI,MAAM,OAAU;AAAA,UACtB;AAAA,YACE,QAAQ;AAAA,YACR,SAAS;AAAA,YACT,SAAS,uBAAuB,MAAM;AAAA,YACtC,YAAY;AAAA,YACZ,UAAU,YAAY;AAAA,YACtB,gBAAgB,SAAS;AAAA,UAC3B;AAAA,QACF,EAAE,MAAM,MAAM,MAAS;AACvB,gBAAQ,IAAI,uBAAuB,MAAM,EAAE;AAC3C;AAAA,MACF;AAEA,YAAM,EAAE,aAAa,IAAI,MAAM,OAAO,+CAA+C;AACrF,YAAM,YAAY,uBAAuB,aAAa,CAA2C;AACjG,iBAAW,MAAM,WAAW;AAC1B,cAAM,IAAI;AAAA,UACR;AAAA,UACA,EAAE,YAAY,IAAI,gBAAgB,OAAO,SAAS;AAAA,UAClD,EAAE,YAAY,KAAK;AAAA,QACrB;AACA,cAAM;AAAA,UACJ,EAAE,IAAI,MAAM,OAAU;AAAA,UACtB;AAAA,YACE,QAAQ;AAAA,YACR,SAAS;AAAA,YACT,SAAS,uBAAuB,EAAE;AAAA,YAClC,YAAY;AAAA,YACZ,UAAU,YAAY;AAAA,YACtB,gBAAgB,SAAS;AAAA,YACzB,SAAS,EAAE,MAAM,OAAO;AAAA,UAC1B;AAAA,QACF,EAAE,MAAM,MAAM,MAAS;AAAA,MACzB;AACA,cAAQ,IAAI,uBAAuB,UAAU,MAAM,WAAW;AAAA,IAChE,SAAS,OAAO;AACd,YAAM;AAAA,QACJ,EAAE,IAAI,MAAM,OAAU;AAAA,QACtB;AAAA,UACE,QAAQ;AAAA,UACR,SAAS;AAAA,UACT,OAAO;AAAA,UACP,SAAS,0BAA0B,SAAS,QAAQ,MAAM,KAAK,EAAE;AAAA,UACjE,YAAY,UAAU;AAAA,UACtB,UAAU,YAAY;AAAA,UACtB,gBAAgB,SAAS;AAAA,UACzB,SAAS,EAAE,OAAO,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,EAAE;AAAA,QAC3E;AAAA,MACF,EAAE,MAAM,MAAM,MAAS;AACvB,YAAM;AAAA,QACJ,EAAE,IAAI,MAAM,OAAU;AAAA,QACtB;AAAA,UACE,QAAQ;AAAA,UACR,SAAS;AAAA,UACT;AAAA,UACA,YAAY,UAAU;AAAA,UACtB;AAAA,UACA,gBAAgB;AAAA,UAChB,SAAS,EAAE,KAAK;AAAA,QAClB;AAAA,MACF;AACA,YAAM;AAAA,IACR,UAAE;AACA,UAAI,OAAQ,WAAmB,YAAY,YAAY;AACrD,cAAO,UAAkB,QAAQ;AAAA,MACnC;AAAA,IACF;AAAA,EACF;AACF;AAEA,IAAO,cAAQ,CAAC,SAAS,YAAY,SAAS,KAAK;",
|
|
4
|
+
"sourcesContent": ["import type { ModuleCli } from '@open-mercato/shared/modules/registry'\nimport { createRequestContainer } from '@open-mercato/shared/lib/di/container'\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport { type Kysely, sql } from 'kysely'\nimport { createProgressBar } from '@open-mercato/shared/lib/cli/progress'\nimport { resolveTenantEncryptionService } from '@open-mercato/shared/lib/encryption/customFieldValues'\nimport { decryptIndexDocForSearch, encryptIndexDocForStorage } from '@open-mercato/shared/lib/encryption/indexDoc'\nimport { parseBooleanToken } from '@open-mercato/shared/lib/boolean'\n\ntype ProgressBarHandle = {\n update(completed: number): void\n complete(): void\n}\nimport { resolveEntityTableName, resolveRegisteredEntityTableName } from '@open-mercato/shared/lib/query/engine'\nimport { recordIndexerError } from '@open-mercato/shared/lib/indexers/error-log'\nimport { recordIndexerLog } from '@open-mercato/shared/lib/indexers/status-log'\nimport {\n upsertIndexBatch,\n assertIndexBatchWritesLanded,\n createEmptyUpsertIndexBatchResult,\n mergeUpsertIndexBatchResults,\n type AnyRow,\n} from './lib/batch'\nimport { reindexEntity, isTenantlessReindexTarget, DEFAULT_REINDEX_PARTITIONS } from './lib/reindexer'\nimport type { ReindexJobResult } from './lib/reindexer'\n\n/**\n * A refused sweep returns processed 0 / total 0, which the progress reporting below prints\n * as `0 / 0 (0.00%)` - indistinguishable from a run that found nothing. Say why instead.\n */\nfunction warnIfReindexRefused(entityType: string, result: ReindexJobResult): void {\n if (!result.refused) return\n const detail = result.refused === 'no-tenant-column'\n ? 'the source table has no tenant_id column and the entity type is not declared tenant-global'\n : result.refused === 'declared-global-but-org-scoped'\n ? 'the entity type is declared tenant-global but its table carries an organization_id column'\n : \"the source table's columns could not be read, so no scope could be proven (usually transient)\"\n console.warn(` -> ${entityType}: reindex REFUSED, nothing was indexed - ${detail}`)\n}\nimport { purgeIndexScope } from './lib/purge'\nimport { refreshCoverageSnapshot } from './lib/coverage'\nimport { flattenSystemEntityIds } from '@open-mercato/shared/lib/entities/system-entities'\nimport type { VectorIndexService } from '@open-mercato/search/vector'\n\ntype ParsedArgs = Record<string, string | boolean>\n\ntype PartitionProgressInfo = { processed: number; total: number }\n\nfunction isIndexerVerbose(): boolean {\n const parsed = parseBooleanToken(process.env.OM_INDEXER_VERBOSE ?? '')\n return parsed === true\n}\n\nfunction createGroupedProgress(label: string, partitionTargets: number[]) {\n const totals = new Map<number, number>()\n const processed = new Map<number, number>()\n let bar: ProgressBarHandle | null = null\n\n const getTotals = () => {\n let total = 0\n let done = 0\n for (const value of totals.values()) total += value\n for (const value of processed.values()) done += value\n return { total, done }\n }\n\n const tryInitBar = () => {\n if (bar) return\n if (totals.size < partitionTargets.length) return\n const { total } = getTotals()\n if (total <= 0) return\n bar = createProgressBar(label, total) as ProgressBarHandle\n }\n\n return {\n onProgress(partition: number, info: PartitionProgressInfo) {\n processed.set(partition, info.processed)\n if (!totals.has(partition)) totals.set(partition, info.total)\n tryInitBar()\n if (!bar) return\n const { done } = getTotals()\n bar.update(done)\n },\n complete() {\n if (bar) bar.complete()\n },\n getTotals,\n }\n}\n\nfunction parseArgs(rest: string[]): ParsedArgs {\n const args: ParsedArgs = {}\n for (let i = 0; i < rest.length; i += 1) {\n const part = rest[i]\n if (!part?.startsWith('--')) continue\n const [rawKey, rawValue] = part.slice(2).split('=')\n if (!rawKey) continue\n if (rawValue !== undefined) {\n args[rawKey] = rawValue\n } else if (i + 1 < rest.length && !rest[i + 1]!.startsWith('--')) {\n args[rawKey] = rest[i + 1]!\n i += 1\n } else {\n args[rawKey] = true\n }\n }\n return args\n}\n\nfunction stringOption(args: ParsedArgs, ...keys: string[]): string | undefined {\n for (const key of keys) {\n const raw = args[key]\n if (typeof raw !== 'string') continue\n const trimmed = raw.trim()\n if (trimmed.length > 0) return trimmed\n }\n return undefined\n}\n\nfunction numberOption(args: ParsedArgs, ...keys: string[]): number | undefined {\n for (const key of keys) {\n const raw = args[key]\n if (typeof raw === 'number') return raw\n if (typeof raw === 'string') {\n const parsed = Number(raw)\n if (Number.isFinite(parsed)) return parsed\n }\n }\n return undefined\n}\n\nfunction flagEnabled(args: ParsedArgs, ...keys: string[]): boolean {\n for (const key of keys) {\n const raw = args[key]\n if (raw === undefined) continue\n if (raw === true) return true\n if (raw === false) continue\n if (typeof raw === 'string') {\n const trimmed = raw.trim()\n if (!trimmed) return true\n const parsed = parseBooleanToken(trimmed)\n return parsed === null ? true : parsed\n }\n }\n return false\n}\n\nfunction toPositiveInt(value: number | undefined): number | undefined {\n if (value === undefined) return undefined\n const n = Math.floor(value)\n if (!Number.isFinite(n) || n <= 0) return undefined\n return n\n}\n\nfunction toNonNegativeInt(value: number | undefined, fallback = 0): number {\n if (value === undefined) return fallback\n const n = Math.floor(value)\n if (!Number.isFinite(n) || n < 0) return fallback\n return n\n}\n\nconst DEFAULT_BATCH_SIZE = 200\n\ntype RebuildExecutionOptions = {\n em: EntityManager\n db: Kysely<any>\n entityType: string\n tableName: string\n orgOverride?: string\n tenantOverride?: string\n global: boolean\n includeDeleted: boolean\n limit?: number\n offset: number\n recordId?: string\n batchSize: number\n progressLabel?: string\n supportsOrgFilter: boolean\n supportsTenantFilter: boolean\n supportsDeletedFilter: boolean\n}\n\ntype RebuildResult = {\n processed: number\n matched: number\n}\nasync function rebuildEntityIndexes(options: RebuildExecutionOptions): Promise<RebuildResult> {\n const {\n em,\n db,\n entityType,\n tableName,\n orgOverride,\n tenantOverride,\n global,\n includeDeleted,\n limit,\n offset,\n recordId,\n batchSize,\n progressLabel,\n supportsOrgFilter,\n supportsTenantFilter,\n supportsDeletedFilter,\n } = options\n\n const encryption = resolveTenantEncryptionService(em as any)\n const dekKeyCache = new Map<string | null, string | null>()\n\n // Neither helper swallows failures: upsertIndexBatch treats a failed encrypt as a\n // failed row (writing the plaintext document instead would break encryption at rest)\n // and records a failed decrypt against fulltext.\n const encryptDoc = async (\n targetEntity: string,\n doc: Record<string, unknown>,\n scope: { organizationId: string | null; tenantId: string | null },\n ) => {\n return await encryptIndexDocForStorage(\n targetEntity,\n doc,\n { tenantId: scope.tenantId ?? null, organizationId: scope.organizationId ?? null },\n encryption,\n )\n }\n\n const decryptDoc = async (\n targetEntity: string,\n doc: Record<string, unknown>,\n scope: { organizationId: string | null; tenantId: string | null },\n ) => {\n return await decryptIndexDocForSearch(\n targetEntity,\n doc,\n { tenantId: scope.tenantId ?? null, organizationId: scope.organizationId ?? null },\n encryption,\n dekKeyCache,\n )\n }\n\n const applyFilters = <QB extends { where: (...args: any[]) => QB }>(q: QB): QB => {\n let chain = q\n if (!global) {\n if (orgOverride !== undefined && supportsOrgFilter) {\n chain = chain.where('organization_id' as any, '=', orgOverride)\n }\n if (tenantOverride !== undefined && supportsTenantFilter) {\n chain = chain.where('tenant_id' as any, '=', tenantOverride)\n }\n }\n if (!includeDeleted && supportsDeletedFilter) {\n chain = chain.where('deleted_at' as any, 'is', null as any)\n }\n return chain\n }\n\n if (recordId) {\n const row = await applyFilters(\n db.selectFrom(tableName as any).selectAll() as any,\n )\n .where('id' as any, '=', recordId)\n .executeTakeFirst() as AnyRow | undefined\n if (!row) return { processed: 0, matched: 0 }\n const bar = createProgressBar(progressLabel ?? `Rebuilding ${entityType}`, 1)\n const singleResult = await upsertIndexBatch(db, entityType, [row], { orgId: orgOverride, tenantId: tenantOverride }, { encryptDoc, decryptDoc })\n bar.update(singleResult.written)\n bar.complete()\n assertIndexBatchWritesLanded(entityType, singleResult)\n return { processed: singleResult.written, matched: 1 }\n }\n\n const countRow = await applyFilters(\n db.selectFrom(tableName as any).select(sql<string>`count(*)`.as('count')) as any,\n ).executeTakeFirst() as { count: string | number } | undefined\n const totalRaw = countRow?.count\n const total = totalRaw != null ? Number(totalRaw) : 0\n const effectiveOffset = Math.max(0, offset)\n const matchedWithoutLimit = Math.max(0, total - effectiveOffset)\n const limitValue = toPositiveInt(limit)\n const intended = limitValue !== undefined ? Math.min(matchedWithoutLimit, limitValue) : matchedWithoutLimit\n if (!Number.isFinite(intended) || intended <= 0) {\n return { processed: 0, matched: 0 }\n }\n\n const bar = createProgressBar(progressLabel ?? `Rebuilding ${entityType}`, intended)\n let processed = 0\n let fetched = 0\n let cursorOffset = effectiveOffset\n let remaining = limitValue\n const writeTotals = createEmptyUpsertIndexBatchResult()\n\n while (fetched < intended) {\n const chunkLimit = remaining !== undefined ? Math.min(batchSize, remaining) : batchSize\n const chunk = await applyFilters(\n db\n .selectFrom(tableName as any)\n .selectAll()\n .orderBy('id' as any)\n .limit(chunkLimit)\n .offset(cursorOffset) as any,\n ).execute() as AnyRow[]\n if (!chunk.length) break\n\n const chunkResult = await upsertIndexBatch(db, entityType, chunk as AnyRow[], {\n orgId: orgOverride,\n tenantId: tenantOverride,\n }, { encryptDoc, decryptDoc })\n mergeUpsertIndexBatchResults(writeTotals, chunkResult)\n\n processed += chunkResult.written\n fetched += chunk.length\n cursorOffset += chunk.length\n if (remaining !== undefined) remaining -= chunk.length\n bar.update(processed)\n if (remaining !== undefined && remaining <= 0) break\n }\n\n if (processed < intended) {\n bar.update(processed)\n }\n bar.complete()\n // After bar.complete() so the terminal is left in a sane state before we throw.\n assertIndexBatchWritesLanded(entityType, writeTotals)\n return { processed, matched: intended }\n}\n\nasync function getColumnSet(db: Kysely<any>, tableName: string): Promise<Set<string>> {\n try {\n const rows = await db\n .selectFrom('information_schema.columns' as any)\n .select(['column_name' as any])\n .where(sql<boolean>`table_schema = current_schema()`)\n .where('table_name' as any, '=', tableName)\n .execute() as Array<{ column_name: string }>\n return new Set(rows.map((row) => String(row.column_name).toLowerCase()))\n } catch {\n return new Set<string>()\n }\n}\n\ntype ScopeDescriptor = {\n global: boolean\n orgId?: string\n tenantId?: string\n includeDeleted: boolean\n supportsOrg: boolean\n supportsTenant: boolean\n supportsDeleted: boolean\n}\n\nfunction describeScope(scope: ScopeDescriptor): string {\n const parts: string[] = []\n if (scope.global) parts.push('global')\n if (!scope.global && scope.orgId && scope.supportsOrg) parts.push(`org=${scope.orgId}`)\n if (!scope.global && scope.tenantId && scope.supportsTenant) parts.push(`tenant=${scope.tenantId}`)\n if (!scope.includeDeleted && scope.supportsDeleted) parts.push('active-only')\n return parts.length ? ` (${parts.join(' ')})` : ''\n}\n\n/**\n * Above this many missing records the anti-join stops being the cheaper option and the\n * repair falls back to a full single-partition rebuild of the entity.\n */\nconst MAX_TARGETED_REPAIR_RECORDS = 5000\n\n/**\n * List the base records in scope that have no live index row, so a repair rebuilds only\n * what is actually missing instead of re-upserting the whole entity for a one-row gap.\n */\nasync function findUnindexedRecordIds(\n db: Kysely<any>,\n options: {\n entityType: string\n tableName: string\n tenantId?: string | null\n organizationId?: string | null\n limit: number\n },\n): Promise<string[]> {\n const columns = await getColumnSet(db, options.tableName)\n let query = db\n .selectFrom(`${options.tableName} as b` as any)\n .select('b.id' as any)\n .where(({ not, exists, selectFrom }: any) =>\n not(exists(\n selectFrom('entity_indexes as ei' as any)\n .select(sql`1`.as('one'))\n .whereRef('ei.entity_id' as any, '=', sql`b.id::text`)\n .where('ei.entity_type' as any, '=', options.entityType)\n .where('ei.deleted_at' as any, 'is', null as any),\n )),\n )\n .limit(options.limit)\n if (columns.has('deleted_at')) query = query.where('b.deleted_at' as any, 'is', null as any)\n if (options.tenantId != null && columns.has('tenant_id')) {\n query = query.where('b.tenant_id' as any, '=', options.tenantId)\n }\n if (options.organizationId != null && columns.has('organization_id')) {\n query = query.where('b.organization_id' as any, '=', options.organizationId)\n }\n const rows = await query.execute() as Array<{ id: unknown }>\n return rows.map((row) => String(row.id))\n}\n\n/**\n * Recount the scope from the database after a reindex and rebuild whatever is still\n * missing. Runs unconditionally so `mercato init` (and any scripted reindex) cannot finish\n * leaving a gap that a human has to notice and repair by hand from the Query Indexes\n * screen. When counts already agree this is two COUNT queries; when they do not, the\n * repair is scoped to the records the anti-join says are actually missing.\n */\nasync function verifyAndRepairIndexCoverage(\n em: EntityManager,\n options: {\n entityType: string\n tenantId?: string | null\n organizationId?: string | null\n batchSize?: number\n },\n): Promise<void> {\n const scope = {\n entityType: options.entityType,\n tenantId: options.tenantId ?? null,\n organizationId: options.organizationId ?? null,\n withDeleted: false,\n }\n\n let counts: { baseCount: number; indexedCount: number } | null = null\n try {\n counts = await refreshCoverageSnapshot(em, scope)\n } catch (error) {\n console.warn(\n ` -> ${options.entityType}: coverage verification skipped (${error instanceof Error ? error.message : String(error)})`,\n )\n return\n }\n if (!counts) return\n if (counts.indexedCount > counts.baseCount) {\n // Legitimate for entities whose base table cannot express the scope, since a per-tenant\n // reindex stamps its own scope onto every row. Surfaced rather than repaired: a rebuild\n // cannot remove the surplus, and the over-count would otherwise mask a real shortfall.\n console.warn(\n ` -> ${options.entityType}: ${counts.indexedCount} index rows for ${counts.baseCount} records \u2014 not repairable by reindexing`,\n )\n return\n }\n if (counts.indexedCount === counts.baseCount) return\n\n const db = (em as any).getKysely() as Kysely<any>\n let tableName: string | null = null\n try {\n tableName = resolveRegisteredEntityTableName(em as any, options.entityType)\n } catch {\n tableName = null\n }\n\n const missingIds = tableName\n ? await findUnindexedRecordIds(db, {\n entityType: options.entityType,\n tableName,\n tenantId: options.tenantId ?? null,\n organizationId: options.organizationId ?? null,\n limit: MAX_TARGETED_REPAIR_RECORDS + 1,\n }).catch(() => null)\n : null\n\n const targeted = missingIds && missingIds.length > 0 && missingIds.length <= MAX_TARGETED_REPAIR_RECORDS\n console.log(\n ` -> ${options.entityType}: ${counts.indexedCount}/${counts.baseCount} indexed after reindex \u2014 repairing`\n + `${targeted ? ` ${missingIds!.length} missing record(s)` : ' the whole entity'}...`,\n )\n\n try {\n if (targeted) {\n const columns = await getColumnSet(db, tableName!)\n for (const recordId of missingIds!) {\n await rebuildEntityIndexes({\n em,\n db,\n entityType: options.entityType,\n tableName: tableName!,\n orgOverride: options.organizationId ?? undefined,\n tenantOverride: options.tenantId ?? undefined,\n global: false,\n includeDeleted: false,\n offset: 0,\n recordId,\n batchSize: 1,\n supportsOrgFilter: columns.has('organization_id'),\n supportsTenantFilter: columns.has('tenant_id'),\n supportsDeletedFilter: columns.has('deleted_at'),\n })\n }\n } else {\n const repairResult = await reindexEntity(em, {\n entityType: options.entityType,\n tenantId: options.tenantId,\n organizationId: options.organizationId,\n force: false,\n batchSize: options.batchSize,\n emitVectorizeEvents: false,\n resetCoverage: false,\n })\n warnIfReindexRefused(options.entityType, repairResult)\n }\n } catch (error) {\n console.warn(\n ` -> ${options.entityType}: repair pass failed (${error instanceof Error ? error.message : String(error)})`,\n )\n return\n }\n\n const after = await refreshCoverageSnapshot(em, scope).catch(() => null)\n if (after && after.indexedCount < after.baseCount) {\n console.warn(\n ` -> ${options.entityType}: still ${after.indexedCount}/${after.baseCount} indexed after repair`,\n )\n } else {\n console.log(` -> ${options.entityType}: coverage repaired`)\n }\n}\n\nconst rebuild: ModuleCli = {\n command: 'rebuild',\n async run(rest) {\n const args = parseArgs(rest)\n const entity = stringOption(args, 'entity', 'e')\n if (!entity) {\n console.error(\n 'Usage: mercato query_index rebuild --entity <module:entity> [--record <id>] [--org <id>] [--tenant <id>] [--global] [--withDeleted] [--limit <n>] [--offset <n>]',\n )\n return\n }\n\n const globalFlag = flagEnabled(args, 'global')\n const includeDeleted = flagEnabled(args, 'withDeleted')\n const orgId = stringOption(args, 'org', 'organizationId')\n const tenantId = stringOption(args, 'tenant', 'tenantId')\n const recordId = stringOption(args, 'record', 'recordId', 'id')\n const limit = toPositiveInt(numberOption(args, 'limit'))\n const offset = toNonNegativeInt(numberOption(args, 'offset'))\n const batchSize = toPositiveInt(numberOption(args, 'batch', 'chunk', 'size')) ?? DEFAULT_BATCH_SIZE\n\n const container = await createRequestContainer()\n const em = (container.resolve('em') as EntityManager)\n try {\n const db = em.getKysely<any>()\n const tableName = resolveEntityTableName(em, entity)\n const columns = await getColumnSet(db, tableName)\n const supportsOrg = columns.has('organization_id')\n const supportsTenant = columns.has('tenant_id')\n const supportsDeleted = columns.has('deleted_at')\n\n if (!globalFlag && orgId && !supportsOrg) {\n console.warn(`[query_index] ${entity} does not expose organization_id, ignoring --org filter`)\n }\n if (!globalFlag && tenantId && !supportsTenant) {\n console.warn(`[query_index] ${entity} does not expose tenant_id, ignoring --tenant filter`)\n }\n if (!includeDeleted && !supportsDeleted) {\n console.warn(`[query_index] ${entity} does not expose deleted_at, cannot skip deleted rows`)\n }\n\n const result = await rebuildEntityIndexes({\n em,\n db,\n entityType: entity,\n tableName,\n orgOverride: orgId,\n tenantOverride: tenantId,\n global: globalFlag,\n includeDeleted,\n limit,\n offset,\n recordId,\n batchSize,\n progressLabel: recordId ? `Rebuilding ${entity} record ${recordId}` : `Rebuilding ${entity}`,\n supportsOrgFilter: supportsOrg,\n supportsTenantFilter: supportsTenant,\n supportsDeletedFilter: supportsDeleted,\n })\n\n if (recordId) {\n if (result.processed === 0) {\n console.log(`No matching row found for ${entity} with id ${recordId}`)\n } else {\n console.log(`Rebuilt index for ${entity} record ${recordId}`)\n }\n return\n }\n\n const scopeLabel = describeScope({\n global: globalFlag,\n orgId,\n tenantId,\n includeDeleted,\n supportsOrg,\n supportsTenant,\n supportsDeleted,\n })\n\n if (result.matched === 0) {\n console.log(`No rows matched filters for ${entity}${scopeLabel}`)\n return\n }\n\n console.log(`Rebuilt ${result.processed} row(s) for ${entity}${scopeLabel}`)\n } catch (error) {\n await recordIndexerError(\n { em },\n {\n source: 'query_index',\n handler: 'cli:query_index.rebuild',\n error,\n entityType: entity,\n recordId,\n tenantId,\n organizationId: orgId,\n payload: { args },\n },\n )\n throw error\n } finally {\n if (typeof (container as any)?.dispose === 'function') {\n await (container as any).dispose()\n }\n }\n },\n}\n\nconst rebuildAll: ModuleCli = {\n command: 'rebuild-all',\n async run(rest) {\n const args = parseArgs(rest)\n const globalFlag = flagEnabled(args, 'global')\n const includeDeleted = flagEnabled(args, 'withDeleted')\n const orgId = stringOption(args, 'org', 'organizationId')\n const tenantId = stringOption(args, 'tenant', 'tenantId')\n const limit = toPositiveInt(numberOption(args, 'limit'))\n const offset = toNonNegativeInt(numberOption(args, 'offset'))\n const batchSize = toPositiveInt(numberOption(args, 'batch', 'chunk', 'size')) ?? DEFAULT_BATCH_SIZE\n const recordId = stringOption(args, 'record', 'recordId', 'id')\n if (recordId) {\n console.error('`rebuild-all` does not support --record. Use `mercato query_index rebuild --record <id>` instead.')\n return\n }\n\n const container = await createRequestContainer()\n const em = (container.resolve('em') as EntityManager)\n try {\n const db = em.getKysely<any>()\n\n const { getEntityIds } = await import('@open-mercato/shared/lib/encryption/entityIds')\n const entityIds = flattenSystemEntityIds(getEntityIds() as Record<string, Record<string, string>>)\n if (!entityIds.length) {\n console.log('No entity definitions registered for query indexing.')\n return\n }\n\n let totalProcessed = 0\n for (let idx = 0; idx < entityIds.length; idx += 1) {\n const entity = entityIds[idx]!\n const tableName = resolveEntityTableName(em, entity)\n const columns = await getColumnSet(db, tableName)\n const supportsOrg = columns.has('organization_id')\n const supportsTenant = columns.has('tenant_id')\n const supportsDeleted = columns.has('deleted_at')\n\n if (!globalFlag && orgId && !supportsOrg) {\n console.warn(`[query_index] ${entity} does not expose organization_id, ignoring --org filter`)\n }\n if (!globalFlag && tenantId && !supportsTenant) {\n console.warn(`[query_index] ${entity} does not expose tenant_id, ignoring --tenant filter`)\n }\n if (!includeDeleted && !supportsDeleted) {\n console.warn(`[query_index] ${entity} does not expose deleted_at, cannot skip deleted rows`)\n }\n\n const scopeLabel = describeScope({\n global: globalFlag,\n orgId,\n tenantId,\n includeDeleted,\n supportsOrg,\n supportsTenant,\n supportsDeleted,\n })\n\n console.log(`[${idx + 1}/${entityIds.length}] Rebuilding ${entity}${scopeLabel}`)\n const result = await rebuildEntityIndexes({\n em,\n db,\n entityType: entity,\n tableName,\n orgOverride: orgId,\n tenantOverride: tenantId,\n global: globalFlag,\n includeDeleted,\n limit,\n offset,\n batchSize,\n supportsOrgFilter: supportsOrg,\n supportsTenantFilter: supportsTenant,\n supportsDeletedFilter: supportsDeleted,\n })\n totalProcessed += result.processed\n if (result.matched === 0) {\n console.log(' -> no rows matched filters')\n } else {\n console.log(` -> processed ${result.processed} row(s)`)\n }\n }\n\n console.log(`Finished rebuilding all query indexes (processed ${totalProcessed} row(s))`)\n } catch (error) {\n await recordIndexerError(\n { em },\n {\n source: 'query_index',\n handler: 'cli:query_index.rebuild-all',\n error,\n tenantId,\n organizationId: orgId,\n payload: { args },\n },\n )\n throw error\n } finally {\n if (typeof (container as any)?.dispose === 'function') {\n await (container as any).dispose()\n }\n }\n },\n}\n\nconst reindex: ModuleCli = {\n command: 'reindex',\n async run(rest) {\n const args = parseArgs(rest)\n const entity = stringOption(args, 'entity', 'e')\n const orgId = stringOption(args, 'org', 'organizationId')\n const tenantId = stringOption(args, 'tenant', 'tenantId')\n const force = flagEnabled(args, 'force', 'full')\n const batchSize = toPositiveInt(numberOption(args, 'batch', 'chunk', 'size'))\n const partitionsOption = toPositiveInt(numberOption(args, 'partitions', 'partitionCount', 'parallel'))\n const partitionIndexOptionRaw = numberOption(args, 'partition', 'partitionIndex')\n const resetCoverageFlag = flagEnabled(args, 'resetCoverage')\n const skipResetCoverageFlag = flagEnabled(args, 'skipResetCoverage', 'noResetCoverage')\n const skipPurge = flagEnabled(args, 'skipPurge', 'noPurge')\n\n const container = await createRequestContainer()\n const baseEm = (container.resolve('em') as EntityManager)\n const partitionIndexOption =\n partitionIndexOptionRaw === undefined ? undefined : toNonNegativeInt(partitionIndexOptionRaw, 0)\n const partitionCount = Math.max(\n 1,\n partitionsOption ?? DEFAULT_REINDEX_PARTITIONS,\n )\n\n if (partitionIndexOption !== undefined && partitionIndexOption >= partitionCount) {\n console.error(`partitionIndex (${partitionIndexOption}) must be < partitionCount (${partitionCount})`)\n if (typeof (container as any)?.dispose === 'function') {\n await (container as any).dispose()\n }\n return\n }\n\n const partitionTargets =\n partitionIndexOption !== undefined\n ? [partitionIndexOption]\n : Array.from({ length: partitionCount }, (_, idx) => idx)\n\n const shouldResetCoverage = (partition: number): boolean => {\n if (resetCoverageFlag) return true\n if (skipResetCoverageFlag) return false\n if (partitionIndexOption !== undefined) return partitionIndexOption === 0\n return partition === partitionTargets[0]\n }\n\n try {\n if (entity) {\n await recordIndexerLog(\n { em: baseEm },\n {\n source: 'query_index',\n handler: 'cli:query_index.reindex',\n message: `Reindex started for ${entity}`,\n entityType: entity,\n tenantId: tenantId ?? null,\n organizationId: orgId ?? null,\n details: {\n force,\n partitions: partitionTargets.length,\n partitionCount,\n partitionIndex: partitionIndexOption ?? null,\n skipPurge,\n },\n },\n ).catch(() => undefined)\n if (!skipPurge) {\n console.log(`Purging existing index rows for ${entity}...`)\n await purgeIndexScope(baseEm, { entityType: entity, organizationId: orgId, tenantId })\n }\n console.log(`Reindexing ${entity}${force ? ' (forced)' : ''} in ${partitionTargets.length} partition(s)...`)\n const verbose = isIndexerVerbose()\n const progressState = verbose ? new Map<number, { last: number }>() : null\n const groupedProgress =\n !verbose && partitionTargets.length > 1\n ? createGroupedProgress(`Reindexing ${entity}`, partitionTargets)\n : null\n const renderProgress = (part: number, entityId: string, info: PartitionProgressInfo) => {\n if (!progressState) return\n const state = progressState.get(part) ?? { last: 0 }\n const now = Date.now()\n if (now - state.last < 1000 && info.processed < info.total) return\n state.last = now\n progressState.set(part, state)\n const percent = info.total > 0 ? ((info.processed / info.total) * 100).toFixed(2) : '0.00'\n console.log(\n ` [${entityId}] partition ${part + 1}/${partitionCount}: ${info.processed.toLocaleString()} / ${info.total.toLocaleString()} (${percent}%)`,\n )\n }\n\n const stats = await Promise.all(\n partitionTargets.map(async (part, idx) => {\n const label = partitionTargets.length > 1 ? ` [partition ${part + 1}/${partitionCount}]` : ''\n if (partitionTargets.length === 1) {\n console.log(` -> processing${label}`)\n } else if (verbose && idx === 0) {\n console.log(` -> processing partitions in parallel (count=${partitionTargets.length})`)\n }\n const partitionContainer = await createRequestContainer()\n const partitionEm = partitionContainer.resolve<EntityManager>('em')\n let partitionVectorService: VectorIndexService | null = null\n try {\n partitionVectorService = partitionContainer.resolve<VectorIndexService>('vectorIndexService')\n } catch {\n partitionVectorService = null\n }\n try {\n let progressBar: ProgressBarHandle | null = null\n const useBar = partitionTargets.length === 1\n const partitionStats = await reindexEntity(partitionEm, {\n entityType: entity,\n tenantId,\n organizationId: orgId,\n force,\n batchSize,\n emitVectorizeEvents: false,\n partitionCount,\n partitionIndex: part,\n resetCoverage: shouldResetCoverage(part),\n vectorService: partitionVectorService,\n onProgress(info) {\n if (useBar) {\n if (info.total > 0 && !progressBar) {\n progressBar = createProgressBar(\n `Reindexing ${entity}${label}`,\n info.total,\n ) as ProgressBarHandle\n }\n progressBar?.update(info.processed)\n } else if (groupedProgress) {\n groupedProgress.onProgress(part, info)\n } else {\n renderProgress(part, entity, info)\n }\n },\n })\n if (progressBar) {\n (progressBar as ProgressBarHandle).complete()\n }\n warnIfReindexRefused(entity, partitionStats)\n if (!useBar && groupedProgress) {\n groupedProgress.onProgress(part, { processed: partitionStats.processed, total: partitionStats.total })\n } else if (!useBar) {\n renderProgress(part, entity, { processed: partitionStats.processed, total: partitionStats.total })\n } else {\n console.log(\n ` processed ${partitionStats.processed} row(s)${partitionStats.total ? ` (base ${partitionStats.total})` : ''}`,\n )\n }\n return partitionStats.processed\n } finally {\n if (typeof (partitionContainer as any)?.dispose === 'function') {\n await (partitionContainer as any).dispose()\n }\n }\n }),\n )\n groupedProgress?.complete()\n const totalProcessed = stats.reduce((acc, value) => acc + value, 0)\n console.log(`Finished ${entity}: processed ${totalProcessed} row(s) across ${partitionTargets.length} partition(s)`)\n if (partitionIndexOption === undefined) {\n await verifyAndRepairIndexCoverage(baseEm, {\n entityType: entity,\n tenantId,\n organizationId: orgId,\n batchSize,\n })\n }\n await recordIndexerLog(\n { em: baseEm },\n {\n source: 'query_index',\n handler: 'cli:query_index.reindex',\n message: `Reindex completed for ${entity}`,\n entityType: entity,\n tenantId: tenantId ?? null,\n organizationId: orgId ?? null,\n details: {\n processed: totalProcessed,\n partitions: partitionTargets.length,\n partitionCount,\n partitionIndex: partitionIndexOption ?? null,\n },\n },\n ).catch(() => undefined)\n return\n }\n\n const { getEntityIds } = await import('@open-mercato/shared/lib/encryption/entityIds')\n const entityIds = flattenSystemEntityIds(getEntityIds() as Record<string, Record<string, string>>)\n if (!entityIds.length) {\n console.log('No entity definitions registered for query indexing.')\n return\n }\n for (let idx = 0; idx < entityIds.length; idx += 1) {\n const id = entityIds[idx]!\n await recordIndexerLog(\n { em: baseEm },\n {\n source: 'query_index',\n handler: 'cli:query_index.reindex',\n message: `Reindex started for ${id}`,\n entityType: id,\n tenantId: tenantId ?? null,\n organizationId: orgId ?? null,\n details: {\n force,\n partitions: partitionTargets.length,\n partitionCount,\n partitionIndex: partitionIndexOption ?? null,\n skipPurge,\n },\n },\n ).catch(() => undefined)\n if (!skipPurge) {\n console.log(`[${idx + 1}/${entityIds.length}] Purging existing index rows for ${id}...`)\n await purgeIndexScope(baseEm, { entityType: id, organizationId: orgId, tenantId })\n }\n if (tenantId != null && await isTenantlessReindexTarget(baseEm, id)) {\n console.log(`[${idx + 1}/${entityIds.length}] Skipping ${id}: its table has no tenant_id column, so it is not tenant-scoped`)\n await recordIndexerLog(\n { em: baseEm },\n {\n source: 'query_index',\n handler: 'cli:query_index.reindex',\n message: `Reindex skipped for ${id}: not tenant-scoped`,\n entityType: id,\n tenantId,\n organizationId: orgId ?? null,\n details: { skipped: 'no-tenant-column' },\n },\n ).catch(() => undefined)\n continue\n }\n console.log(\n `[${idx + 1}/${entityIds.length}] Reindexing ${id}${force ? ' (forced)' : ''} in ${partitionTargets.length} partition(s)...`,\n )\n const verbose = isIndexerVerbose()\n const progressState = verbose ? new Map<number, { last: number }>() : null\n const groupedProgress =\n !verbose && partitionTargets.length > 1\n ? createGroupedProgress(`Reindexing ${id}`, partitionTargets)\n : null\n const renderProgress = (part: number, entityId: string, info: PartitionProgressInfo) => {\n if (!progressState) return\n const state = progressState.get(part) ?? { last: 0 }\n const now = Date.now()\n if (now - state.last < 1000 && info.processed < info.total) return\n state.last = now\n progressState.set(part, state)\n const percent = info.total > 0 ? ((info.processed / info.total) * 100).toFixed(2) : '0.00'\n console.log(\n ` [${entityId}] partition ${part + 1}/${partitionCount}: ${info.processed.toLocaleString()} / ${info.total.toLocaleString()} (${percent}%)`,\n )\n }\n\n const partitionResults = await Promise.all(\n partitionTargets.map(async (part, partitionIdx) => {\n const label = partitionTargets.length > 1 ? ` [partition ${part + 1}/${partitionCount}]` : ''\n if (partitionTargets.length === 1) {\n console.log(` -> processing${label}`)\n } else if (verbose && partitionIdx === 0) {\n console.log(` -> processing partitions in parallel (count=${partitionTargets.length})`)\n }\n const partitionContainer = await createRequestContainer()\n const partitionEm = partitionContainer.resolve<EntityManager>('em')\n let partitionVectorService: VectorIndexService | null = null\n try {\n partitionVectorService = partitionContainer.resolve<VectorIndexService>('vectorIndexService')\n } catch {\n partitionVectorService = null\n }\n try {\n let progressBar: ProgressBarHandle | null = null\n const useBar = partitionTargets.length === 1\n const result = await reindexEntity(partitionEm, {\n entityType: id,\n tenantId,\n organizationId: orgId,\n force,\n batchSize,\n emitVectorizeEvents: false,\n partitionCount,\n partitionIndex: part,\n resetCoverage: shouldResetCoverage(part),\n vectorService: partitionVectorService,\n onProgress(info) {\n if (useBar) {\n if (info.total > 0 && !progressBar) {\n progressBar = createProgressBar(`Reindexing ${id}${label}`, info.total) as ProgressBarHandle\n }\n progressBar?.update(info.processed)\n } else if (groupedProgress) {\n groupedProgress.onProgress(part, info)\n } else {\n renderProgress(part, id, info)\n }\n },\n })\n if (progressBar) {\n (progressBar as ProgressBarHandle).complete()\n }\n warnIfReindexRefused(id, result)\n if (!useBar && groupedProgress) {\n groupedProgress.onProgress(part, { processed: result.processed, total: result.total })\n } else if (!useBar) {\n renderProgress(part, id, { processed: result.processed, total: result.total })\n } else {\n console.log(\n ` processed ${result.processed} row(s)${result.total ? ` (base ${result.total})` : ''}`,\n )\n }\n return result.processed\n } finally {\n if (typeof (partitionContainer as any)?.dispose === 'function') {\n await (partitionContainer as any).dispose()\n }\n }\n }),\n )\n groupedProgress?.complete()\n const totalProcessed = partitionResults.reduce((acc, value) => acc + value, 0)\n console.log(` -> ${id} complete: processed ${totalProcessed} row(s) across ${partitionTargets.length} partition(s)`)\n if (partitionIndexOption === undefined) {\n await verifyAndRepairIndexCoverage(baseEm, {\n entityType: id,\n tenantId,\n organizationId: orgId,\n batchSize,\n })\n }\n await recordIndexerLog(\n { em: baseEm },\n {\n source: 'query_index',\n handler: 'cli:query_index.reindex',\n message: `Reindex completed for ${id}`,\n entityType: id,\n tenantId: tenantId ?? null,\n organizationId: orgId ?? null,\n details: {\n processed: totalProcessed,\n partitions: partitionTargets.length,\n partitionCount,\n partitionIndex: partitionIndexOption ?? null,\n },\n },\n ).catch(() => undefined)\n }\n console.log(`Finished reindexing ${entityIds.length} entities`)\n } catch (error) {\n const targetLabel = entity ?? 'multiple entities'\n await recordIndexerLog(\n { em: baseEm },\n {\n source: 'query_index',\n handler: 'cli:query_index.reindex',\n level: 'warn',\n message: `Reindex failed for ${targetLabel}`,\n entityType: entity ?? null,\n tenantId: tenantId ?? null,\n organizationId: orgId ?? null,\n details: {\n error: error instanceof Error ? error.message : String(error),\n },\n },\n ).catch(() => undefined)\n await recordIndexerError(\n { em: baseEm },\n {\n source: 'query_index',\n handler: 'cli:query_index.reindex',\n error,\n entityType: entity ?? null,\n tenantId,\n organizationId: orgId ?? null,\n payload: {\n args,\n partitionTargets,\n partitionCount,\n partitionIndex: partitionIndexOption,\n force,\n skipPurge,\n },\n },\n )\n throw error\n } finally {\n if (typeof (container as any)?.dispose === 'function') {\n await (container as any).dispose()\n }\n }\n },\n}\n\nconst purge: ModuleCli = {\n command: 'purge',\n async run(rest) {\n const args = parseArgs(rest)\n const entity = stringOption(args, 'entity', 'e')\n const orgId = stringOption(args, 'org', 'organizationId')\n const tenantId = stringOption(args, 'tenant', 'tenantId')\n\n const container = await createRequestContainer()\n let em: EntityManager | null = null\n try {\n em = (container.resolve('em') as EntityManager)\n } catch {\n em = null\n }\n\n try {\n const bus = container.resolve('eventBus') as {\n emitEvent(event: string, payload: any, options?: any): Promise<void>\n }\n if (entity) {\n await bus.emitEvent(\n 'query_index.purge',\n { entityType: entity, organizationId: orgId, tenantId },\n { persistent: true },\n )\n await recordIndexerLog(\n { em: em ?? undefined },\n {\n source: 'query_index',\n handler: 'cli:query_index.purge',\n message: `Purge requested for ${entity}`,\n entityType: entity,\n tenantId: tenantId ?? null,\n organizationId: orgId ?? null,\n },\n ).catch(() => undefined)\n console.log(`Scheduled purge for ${entity}`)\n return\n }\n\n const { getEntityIds } = await import('@open-mercato/shared/lib/encryption/entityIds')\n const entityIds = flattenSystemEntityIds(getEntityIds() as Record<string, Record<string, string>>)\n for (const id of entityIds) {\n await bus.emitEvent(\n 'query_index.purge',\n { entityType: id, organizationId: orgId, tenantId },\n { persistent: true },\n )\n await recordIndexerLog(\n { em: em ?? undefined },\n {\n source: 'query_index',\n handler: 'cli:query_index.purge',\n message: `Purge requested for ${id}`,\n entityType: id,\n tenantId: tenantId ?? null,\n organizationId: orgId ?? null,\n details: { mode: 'bulk' },\n },\n ).catch(() => undefined)\n }\n console.log(`Scheduled purge for ${entityIds.length} entities`)\n } catch (error) {\n await recordIndexerLog(\n { em: em ?? undefined },\n {\n source: 'query_index',\n handler: 'cli:query_index.purge',\n level: 'warn',\n message: `Purge scheduling failed${entity ? ` for ${entity}` : ''}`,\n entityType: entity ?? null,\n tenantId: tenantId ?? null,\n organizationId: orgId ?? null,\n details: { error: error instanceof Error ? error.message : String(error) },\n },\n ).catch(() => undefined)\n await recordIndexerError(\n { em: em ?? undefined },\n {\n source: 'query_index',\n handler: 'cli:query_index.purge',\n error,\n entityType: entity ?? null,\n tenantId,\n organizationId: orgId,\n payload: { args },\n },\n )\n throw error\n } finally {\n if (typeof (container as any)?.dispose === 'function') {\n await (container as any).dispose()\n }\n }\n },\n}\n\nexport default [rebuild, rebuildAll, reindex, purge]\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["bar"]
|
|
7
7
|
}
|