@open-mercato/core 0.4.2-canary-19703ca707 → 0.4.2-canary-470129ce32
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/dist/modules/customers/widgets/dashboard/customer-todos/widget.js +2 -1
- package/dist/modules/customers/widgets/dashboard/customer-todos/widget.js.map +2 -2
- package/dist/modules/customers/widgets/dashboard/new-customers/widget.js +2 -1
- package/dist/modules/customers/widgets/dashboard/new-customers/widget.js.map +2 -2
- package/dist/modules/customers/widgets/dashboard/new-deals/widget.js +2 -1
- package/dist/modules/customers/widgets/dashboard/new-deals/widget.js.map +2 -2
- package/dist/modules/customers/widgets/dashboard/next-interactions/widget.js +2 -1
- package/dist/modules/customers/widgets/dashboard/next-interactions/widget.js.map +2 -2
- package/dist/modules/dashboards/widgets/dashboard/aov-kpi/widget.js +2 -1
- package/dist/modules/dashboards/widgets/dashboard/aov-kpi/widget.js.map +2 -2
- package/dist/modules/dashboards/widgets/dashboard/new-customers-kpi/widget.js +2 -1
- package/dist/modules/dashboards/widgets/dashboard/new-customers-kpi/widget.js.map +2 -2
- package/dist/modules/dashboards/widgets/dashboard/orders-by-status/widget.js +2 -1
- package/dist/modules/dashboards/widgets/dashboard/orders-by-status/widget.js.map +2 -2
- package/dist/modules/dashboards/widgets/dashboard/orders-kpi/widget.js +2 -1
- package/dist/modules/dashboards/widgets/dashboard/orders-kpi/widget.js.map +2 -2
- package/dist/modules/dashboards/widgets/dashboard/pipeline-summary/widget.js +2 -1
- package/dist/modules/dashboards/widgets/dashboard/pipeline-summary/widget.js.map +2 -2
- package/dist/modules/dashboards/widgets/dashboard/revenue-kpi/widget.js +2 -1
- package/dist/modules/dashboards/widgets/dashboard/revenue-kpi/widget.js.map +2 -2
- package/dist/modules/dashboards/widgets/dashboard/revenue-trend/widget.js +2 -1
- package/dist/modules/dashboards/widgets/dashboard/revenue-trend/widget.js.map +2 -2
- package/dist/modules/dashboards/widgets/dashboard/sales-by-region/widget.js +2 -1
- package/dist/modules/dashboards/widgets/dashboard/sales-by-region/widget.js.map +2 -2
- package/dist/modules/dashboards/widgets/dashboard/top-customers/widget.js +2 -1
- package/dist/modules/dashboards/widgets/dashboard/top-customers/widget.js.map +2 -2
- package/dist/modules/dashboards/widgets/dashboard/top-products/widget.js +2 -1
- package/dist/modules/dashboards/widgets/dashboard/top-products/widget.js.map +2 -2
- package/dist/modules/directory/api/get/tenants/lookup.js +2 -0
- package/dist/modules/directory/api/get/tenants/lookup.js.map +2 -2
- package/dist/modules/notifications/migrations/Migration20260129082610.js +13 -0
- package/dist/modules/notifications/migrations/Migration20260129082610.js.map +7 -0
- package/dist/modules/query_index/cli.js +63 -7
- package/dist/modules/query_index/cli.js.map +2 -2
- package/package.json +2 -2
- package/src/modules/customers/widgets/dashboard/customer-todos/widget.ts +2 -2
- package/src/modules/customers/widgets/dashboard/new-customers/widget.ts +2 -2
- package/src/modules/customers/widgets/dashboard/new-deals/widget.ts +2 -2
- package/src/modules/customers/widgets/dashboard/next-interactions/widget.ts +2 -2
- package/src/modules/dashboards/widgets/dashboard/aov-kpi/widget.ts +2 -2
- package/src/modules/dashboards/widgets/dashboard/new-customers-kpi/widget.ts +2 -2
- package/src/modules/dashboards/widgets/dashboard/orders-by-status/widget.ts +2 -2
- package/src/modules/dashboards/widgets/dashboard/orders-kpi/widget.ts +2 -2
- package/src/modules/dashboards/widgets/dashboard/pipeline-summary/widget.ts +2 -2
- package/src/modules/dashboards/widgets/dashboard/revenue-kpi/widget.ts +2 -2
- package/src/modules/dashboards/widgets/dashboard/revenue-trend/widget.ts +2 -2
- package/src/modules/dashboards/widgets/dashboard/sales-by-region/widget.ts +2 -2
- package/src/modules/dashboards/widgets/dashboard/top-customers/widget.ts +2 -2
- package/src/modules/dashboards/widgets/dashboard/top-products/widget.ts +2 -2
- package/src/modules/directory/api/get/tenants/lookup.ts +2 -0
- package/src/modules/notifications/migrations/.snapshot-open-mercato.json +36 -0
- package/src/modules/notifications/migrations/Migration20260129082610.ts +13 -0
- package/src/modules/query_index/cli.ts +82 -13
|
@@ -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 { Knex } from 'knex'\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 } 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 { upsertIndexBatch, type AnyRow } from './lib/batch'\nimport { reindexEntity, DEFAULT_REINDEX_PARTITIONS } from './lib/reindexer'\nimport { purgeIndexScope } from './lib/purge'\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\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 knex: Knex\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 knex,\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 const encryptDoc = async (\n targetEntity: string,\n doc: Record<string, unknown>,\n scope: { organizationId: string | null; tenantId: string | null },\n ) => {\n try {\n return await encryptIndexDocForStorage(\n targetEntity,\n doc,\n { tenantId: scope.tenantId ?? null, organizationId: scope.organizationId ?? null },\n encryption,\n )\n } catch {\n return doc\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 try {\n return await decryptIndexDocForSearch(\n targetEntity,\n doc,\n { tenantId: scope.tenantId ?? null, organizationId: scope.organizationId ?? null },\n encryption,\n dekKeyCache,\n )\n } catch {\n return doc\n }\n }\n\n const filters: Record<string, unknown> = {}\n if (!global) {\n if (orgOverride !== undefined && supportsOrgFilter) filters.organization_id = orgOverride\n if (tenantOverride !== undefined && supportsTenantFilter) filters.tenant_id = tenantOverride\n }\n if (!includeDeleted && supportsDeletedFilter) filters.deleted_at = null\n\n const baseQuery = knex(tableName).where(filters)\n\n if (recordId) {\n const row = await baseQuery.clone().where({ id: recordId }).first<AnyRow>()\n if (!row) return { processed: 0, matched: 0 }\n const bar = createProgressBar(progressLabel ?? `Rebuilding ${entityType}`, 1)\n await upsertIndexBatch(knex, entityType, [row], { orgId: orgOverride, tenantId: tenantOverride }, { encryptDoc, decryptDoc })\n bar.update(1)\n bar.complete()\n return { processed: 1, matched: 1 }\n }\n\n const countRow = await baseQuery.clone().count<{ count: string }>({ count: '*' }).first()\n const totalRaw = countRow?.count ?? (countRow as any)?.['count(*)']\n const total = totalRaw ? 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 cursorOffset = effectiveOffset\n let remaining = limitValue\n\n while (processed < intended) {\n const chunkLimit = remaining !== undefined ? Math.min(batchSize, remaining) : batchSize\n const chunk = await baseQuery\n .clone()\n .select('*')\n .orderBy('id')\n .limit(chunkLimit)\n .offset(cursorOffset)\n if (!chunk.length) break\n\n await upsertIndexBatch(knex, entityType, chunk as AnyRow[], {\n orgId: orgOverride,\n tenantId: tenantOverride,\n }, { encryptDoc, decryptDoc })\n\n processed += 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 return { processed, matched: intended }\n}\n\nasync function getColumnSet(knex: Knex, tableName: string): Promise<Set<string>> {\n try {\n const info = await knex(tableName).columnInfo()\n return new Set(Object.keys(info).map((key) => key.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\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 knex = em.getConnection().getKnex()\n const tableName = resolveEntityTableName(em, entity)\n const columns = await getColumnSet(knex, 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 knex,\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 knex = em.getConnection().getKnex()\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(knex, 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 knex,\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 progressState = new Map<number, { last: number }>()\n const renderProgress = (part: number, entityId: string, info: { processed: number; total: number }) => {\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 (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(`Reindexing ${entity}${label}`, info.total) as ProgressBarHandle\n }\n progressBar?.update(info.processed)\n } else {\n renderProgress(part, entity, info)\n }\n },\n })\n if (progressBar) {\n (progressBar as ProgressBarHandle).complete()\n }\n 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 const totalProcessed = stats.reduce((acc, value) => acc + value, 0)\n console.log(`Finished ${entity}: processed ${totalProcessed} row(s) across ${partitionTargets.length} partition(s)`)\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 progressState = new Map<number, { last: number }>()\n const renderProgress = (part: number, entityId: string, info: { processed: number; total: number }) => {\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 (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 {\n renderProgress(part, id, info)\n }\n },\n })\n if (progressBar) {\n (progressBar as ProgressBarHandle).complete()\n }\n 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 const totalProcessed = partitionResults.reduce((acc, value) => acc + value, 0)\n console.log(` -> ${id} complete: processed ${totalProcessed} row(s) across ${partitionTargets.length} partition(s)`)\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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",
|
|
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 { Knex } from 'knex'\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 } 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 { upsertIndexBatch, type AnyRow } from './lib/batch'\nimport { reindexEntity, DEFAULT_REINDEX_PARTITIONS } from './lib/reindexer'\nimport { purgeIndexScope } from './lib/purge'\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 knex: Knex\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 knex,\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 const encryptDoc = async (\n targetEntity: string,\n doc: Record<string, unknown>,\n scope: { organizationId: string | null; tenantId: string | null },\n ) => {\n try {\n return await encryptIndexDocForStorage(\n targetEntity,\n doc,\n { tenantId: scope.tenantId ?? null, organizationId: scope.organizationId ?? null },\n encryption,\n )\n } catch {\n return doc\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 try {\n return await decryptIndexDocForSearch(\n targetEntity,\n doc,\n { tenantId: scope.tenantId ?? null, organizationId: scope.organizationId ?? null },\n encryption,\n dekKeyCache,\n )\n } catch {\n return doc\n }\n }\n\n const filters: Record<string, unknown> = {}\n if (!global) {\n if (orgOverride !== undefined && supportsOrgFilter) filters.organization_id = orgOverride\n if (tenantOverride !== undefined && supportsTenantFilter) filters.tenant_id = tenantOverride\n }\n if (!includeDeleted && supportsDeletedFilter) filters.deleted_at = null\n\n const baseQuery = knex(tableName).where(filters)\n\n if (recordId) {\n const row = await baseQuery.clone().where({ id: recordId }).first<AnyRow>()\n if (!row) return { processed: 0, matched: 0 }\n const bar = createProgressBar(progressLabel ?? `Rebuilding ${entityType}`, 1)\n await upsertIndexBatch(knex, entityType, [row], { orgId: orgOverride, tenantId: tenantOverride }, { encryptDoc, decryptDoc })\n bar.update(1)\n bar.complete()\n return { processed: 1, matched: 1 }\n }\n\n const countRow = await baseQuery.clone().count<{ count: string }>({ count: '*' }).first()\n const totalRaw = countRow?.count ?? (countRow as any)?.['count(*)']\n const total = totalRaw ? 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 cursorOffset = effectiveOffset\n let remaining = limitValue\n\n while (processed < intended) {\n const chunkLimit = remaining !== undefined ? Math.min(batchSize, remaining) : batchSize\n const chunk = await baseQuery\n .clone()\n .select('*')\n .orderBy('id')\n .limit(chunkLimit)\n .offset(cursorOffset)\n if (!chunk.length) break\n\n await upsertIndexBatch(knex, entityType, chunk as AnyRow[], {\n orgId: orgOverride,\n tenantId: tenantOverride,\n }, { encryptDoc, decryptDoc })\n\n processed += 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 return { processed, matched: intended }\n}\n\nasync function getColumnSet(knex: Knex, tableName: string): Promise<Set<string>> {\n try {\n const info = await knex(tableName).columnInfo()\n return new Set(Object.keys(info).map((key) => key.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\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 knex = em.getConnection().getKnex()\n const tableName = resolveEntityTableName(em, entity)\n const columns = await getColumnSet(knex, 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 knex,\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 knex = em.getConnection().getKnex()\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(knex, 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 knex,\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 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 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 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 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
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@open-mercato/core",
|
|
3
|
-
"version": "0.4.2-canary-
|
|
3
|
+
"version": "0.4.2-canary-470129ce32",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -207,7 +207,7 @@
|
|
|
207
207
|
}
|
|
208
208
|
},
|
|
209
209
|
"dependencies": {
|
|
210
|
-
"@open-mercato/shared": "0.4.2-canary-
|
|
210
|
+
"@open-mercato/shared": "0.4.2-canary-470129ce32",
|
|
211
211
|
"@xyflow/react": "^12.6.0",
|
|
212
212
|
"date-fns": "^4.1.0",
|
|
213
213
|
"date-fns-tz": "^3.2.0"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type
|
|
2
|
-
import CustomerTodosWidget from './widget.client'
|
|
1
|
+
import { lazyDashboardWidget, type DashboardWidgetModule } from '@open-mercato/shared/modules/dashboard/widgets'
|
|
3
2
|
import { DEFAULT_SETTINGS, hydrateCustomerTodoSettings, type CustomerTodoWidgetSettings } from './config'
|
|
3
|
+
const CustomerTodosWidget = lazyDashboardWidget(() => import('./widget.client'))
|
|
4
4
|
|
|
5
5
|
const widget: DashboardWidgetModule<CustomerTodoWidgetSettings> = {
|
|
6
6
|
metadata: {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type
|
|
2
|
-
import CustomerNewCustomersWidget from './widget.client'
|
|
1
|
+
import { lazyDashboardWidget, type DashboardWidgetModule } from '@open-mercato/shared/modules/dashboard/widgets'
|
|
3
2
|
import { DEFAULT_SETTINGS, hydrateNewCustomersSettings, type CustomerNewCustomersSettings } from './config'
|
|
3
|
+
const CustomerNewCustomersWidget = lazyDashboardWidget(() => import('./widget.client'))
|
|
4
4
|
|
|
5
5
|
const widget: DashboardWidgetModule<CustomerNewCustomersSettings> = {
|
|
6
6
|
metadata: {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type
|
|
2
|
-
import CustomerNewDealsWidget from './widget.client'
|
|
1
|
+
import { lazyDashboardWidget, type DashboardWidgetModule } from '@open-mercato/shared/modules/dashboard/widgets'
|
|
3
2
|
import { DEFAULT_SETTINGS, hydrateNewDealsSettings, type CustomerNewDealsSettings } from './config'
|
|
3
|
+
const CustomerNewDealsWidget = lazyDashboardWidget(() => import('./widget.client'))
|
|
4
4
|
|
|
5
5
|
const widget: DashboardWidgetModule<CustomerNewDealsSettings> = {
|
|
6
6
|
metadata: {
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import type
|
|
2
|
-
import CustomerNextInteractionsWidget from './widget.client'
|
|
1
|
+
import { lazyDashboardWidget, type DashboardWidgetModule } from '@open-mercato/shared/modules/dashboard/widgets'
|
|
3
2
|
import {
|
|
4
3
|
DEFAULT_SETTINGS,
|
|
5
4
|
hydrateNextInteractionsSettings,
|
|
6
5
|
type CustomerNextInteractionsSettings,
|
|
7
6
|
} from './config'
|
|
7
|
+
const CustomerNextInteractionsWidget = lazyDashboardWidget(() => import('./widget.client'))
|
|
8
8
|
|
|
9
9
|
const widget: DashboardWidgetModule<CustomerNextInteractionsSettings> = {
|
|
10
10
|
metadata: {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type
|
|
2
|
-
import AovKpiWidget from './widget.client'
|
|
1
|
+
import { lazyDashboardWidget, type DashboardWidgetModule } from '@open-mercato/shared/modules/dashboard/widgets'
|
|
3
2
|
import { DEFAULT_SETTINGS, hydrateSettings, type AovKpiSettings } from './config'
|
|
3
|
+
const AovKpiWidget = lazyDashboardWidget(() => import('./widget.client'))
|
|
4
4
|
|
|
5
5
|
const widget: DashboardWidgetModule<AovKpiSettings> = {
|
|
6
6
|
metadata: {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type
|
|
2
|
-
import NewCustomersKpiWidget from './widget.client'
|
|
1
|
+
import { lazyDashboardWidget, type DashboardWidgetModule } from '@open-mercato/shared/modules/dashboard/widgets'
|
|
3
2
|
import { DEFAULT_SETTINGS, hydrateSettings, type NewCustomersKpiSettings } from './config'
|
|
3
|
+
const NewCustomersKpiWidget = lazyDashboardWidget(() => import('./widget.client'))
|
|
4
4
|
|
|
5
5
|
const widget: DashboardWidgetModule<NewCustomersKpiSettings> = {
|
|
6
6
|
metadata: {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type
|
|
2
|
-
import OrdersByStatusWidget from './widget.client'
|
|
1
|
+
import { lazyDashboardWidget, type DashboardWidgetModule } from '@open-mercato/shared/modules/dashboard/widgets'
|
|
3
2
|
import { DEFAULT_SETTINGS, hydrateSettings, type OrdersByStatusSettings } from './config'
|
|
3
|
+
const OrdersByStatusWidget = lazyDashboardWidget(() => import('./widget.client'))
|
|
4
4
|
|
|
5
5
|
const widget: DashboardWidgetModule<OrdersByStatusSettings> = {
|
|
6
6
|
metadata: {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type
|
|
2
|
-
import OrdersKpiWidget from './widget.client'
|
|
1
|
+
import { lazyDashboardWidget, type DashboardWidgetModule } from '@open-mercato/shared/modules/dashboard/widgets'
|
|
3
2
|
import { DEFAULT_SETTINGS, hydrateSettings, type OrdersKpiSettings } from './config'
|
|
3
|
+
const OrdersKpiWidget = lazyDashboardWidget(() => import('./widget.client'))
|
|
4
4
|
|
|
5
5
|
const widget: DashboardWidgetModule<OrdersKpiSettings> = {
|
|
6
6
|
metadata: {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type
|
|
2
|
-
import PipelineSummaryWidget from './widget.client'
|
|
1
|
+
import { lazyDashboardWidget, type DashboardWidgetModule } from '@open-mercato/shared/modules/dashboard/widgets'
|
|
3
2
|
import { DEFAULT_SETTINGS, hydrateSettings, type PipelineSummarySettings } from './config'
|
|
3
|
+
const PipelineSummaryWidget = lazyDashboardWidget(() => import('./widget.client'))
|
|
4
4
|
|
|
5
5
|
const widget: DashboardWidgetModule<PipelineSummarySettings> = {
|
|
6
6
|
metadata: {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type
|
|
2
|
-
import RevenueKpiWidget from './widget.client'
|
|
1
|
+
import { lazyDashboardWidget, type DashboardWidgetModule } from '@open-mercato/shared/modules/dashboard/widgets'
|
|
3
2
|
import { DEFAULT_SETTINGS, hydrateSettings, type RevenueKpiSettings } from './config'
|
|
3
|
+
const RevenueKpiWidget = lazyDashboardWidget(() => import('./widget.client'))
|
|
4
4
|
|
|
5
5
|
const widget: DashboardWidgetModule<RevenueKpiSettings> = {
|
|
6
6
|
metadata: {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type
|
|
2
|
-
import RevenueTrendWidget from './widget.client'
|
|
1
|
+
import { lazyDashboardWidget, type DashboardWidgetModule } from '@open-mercato/shared/modules/dashboard/widgets'
|
|
3
2
|
import { DEFAULT_SETTINGS, hydrateSettings, type RevenueTrendSettings } from './config'
|
|
3
|
+
const RevenueTrendWidget = lazyDashboardWidget(() => import('./widget.client'))
|
|
4
4
|
|
|
5
5
|
const widget: DashboardWidgetModule<RevenueTrendSettings> = {
|
|
6
6
|
metadata: {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type
|
|
2
|
-
import SalesByRegionWidget from './widget.client'
|
|
1
|
+
import { lazyDashboardWidget, type DashboardWidgetModule } from '@open-mercato/shared/modules/dashboard/widgets'
|
|
3
2
|
import { DEFAULT_SETTINGS, hydrateSettings, type SalesByRegionSettings } from './config'
|
|
3
|
+
const SalesByRegionWidget = lazyDashboardWidget(() => import('./widget.client'))
|
|
4
4
|
|
|
5
5
|
const widget: DashboardWidgetModule<SalesByRegionSettings> = {
|
|
6
6
|
metadata: {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type
|
|
2
|
-
import TopCustomersWidget from './widget.client'
|
|
1
|
+
import { lazyDashboardWidget, type DashboardWidgetModule } from '@open-mercato/shared/modules/dashboard/widgets'
|
|
3
2
|
import { DEFAULT_SETTINGS, hydrateSettings, type TopCustomersSettings } from './config'
|
|
3
|
+
const TopCustomersWidget = lazyDashboardWidget(() => import('./widget.client'))
|
|
4
4
|
|
|
5
5
|
const widget: DashboardWidgetModule<TopCustomersSettings> = {
|
|
6
6
|
metadata: {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type
|
|
2
|
-
import TopProductsWidget from './widget.client'
|
|
1
|
+
import { lazyDashboardWidget, type DashboardWidgetModule } from '@open-mercato/shared/modules/dashboard/widgets'
|
|
3
2
|
import { DEFAULT_SETTINGS, hydrateSettings, type TopProductsSettings } from './config'
|
|
3
|
+
const TopProductsWidget = lazyDashboardWidget(() => import('./widget.client'))
|
|
4
4
|
|
|
5
5
|
const widget: DashboardWidgetModule<TopProductsSettings> = {
|
|
6
6
|
metadata: {
|
|
@@ -34,6 +34,42 @@
|
|
|
34
34
|
"nullable": false,
|
|
35
35
|
"mappedType": "text"
|
|
36
36
|
},
|
|
37
|
+
"title_key": {
|
|
38
|
+
"name": "title_key",
|
|
39
|
+
"type": "text",
|
|
40
|
+
"unsigned": false,
|
|
41
|
+
"autoincrement": false,
|
|
42
|
+
"primary": false,
|
|
43
|
+
"nullable": true,
|
|
44
|
+
"mappedType": "text"
|
|
45
|
+
},
|
|
46
|
+
"body_key": {
|
|
47
|
+
"name": "body_key",
|
|
48
|
+
"type": "text",
|
|
49
|
+
"unsigned": false,
|
|
50
|
+
"autoincrement": false,
|
|
51
|
+
"primary": false,
|
|
52
|
+
"nullable": true,
|
|
53
|
+
"mappedType": "text"
|
|
54
|
+
},
|
|
55
|
+
"title_variables": {
|
|
56
|
+
"name": "title_variables",
|
|
57
|
+
"type": "jsonb",
|
|
58
|
+
"unsigned": false,
|
|
59
|
+
"autoincrement": false,
|
|
60
|
+
"primary": false,
|
|
61
|
+
"nullable": true,
|
|
62
|
+
"mappedType": "json"
|
|
63
|
+
},
|
|
64
|
+
"body_variables": {
|
|
65
|
+
"name": "body_variables",
|
|
66
|
+
"type": "jsonb",
|
|
67
|
+
"unsigned": false,
|
|
68
|
+
"autoincrement": false,
|
|
69
|
+
"primary": false,
|
|
70
|
+
"nullable": true,
|
|
71
|
+
"mappedType": "json"
|
|
72
|
+
},
|
|
37
73
|
"title": {
|
|
38
74
|
"name": "title",
|
|
39
75
|
"type": "text",
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { Migration } from '@mikro-orm/migrations';
|
|
2
|
+
|
|
3
|
+
export class Migration20260129082610 extends Migration {
|
|
4
|
+
|
|
5
|
+
override async up(): Promise<void> {
|
|
6
|
+
this.addSql(`alter table "notifications" add column if not exists "title_key" text null, add column if not exists "body_key" text null, add column if not exists "title_variables" jsonb null, add column if not exists "body_variables" jsonb null;`);
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
override async down(): Promise<void> {
|
|
10
|
+
this.addSql(`alter table "notifications" drop column if exists "title_key", drop column if exists "body_key", drop column if exists "title_variables", drop column if exists "body_variables";`);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
}
|