@gzl10/nexus-backend 0.19.0 → 0.20.0
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/claude-commands/nexus-docs.md +2 -2
- package/claude-commands/nexus-update-tutorial-app.md +2 -2
- package/claude-commands/nexus-update-tutorial-plugin.md +1 -1
- package/dist/cli.js +264 -403
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +684 -714
- package/dist/index.js.map +1 -1
- package/dist/main.js +679 -709
- package/dist/main.js.map +1 -1
- package/dist/migration-helpers/index.js +388 -526
- package/dist/migration-helpers/index.js.map +1 -1
- package/dist/testing/index.js.map +1 -1
- package/package.json +2 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/testing/test-helpers.ts","../../src/db/filter-helpers.ts","../../src/db/memory-adapter.ts","../../src/core/cache/lru-cache.ts","../../src/core/cache/managed-cache.ts","../../src/db/query-helpers.ts","../../src/core/errors/error-codes.ts","../../src/testing/core-tables.ts","../../src/core/errors/app-error.ts","../../src/testing/test-db.ts"],"sourcesContent":["/**\n * Test helpers for runtime services\n */\n\nimport { vi } from 'vitest'\nimport type { Knex } from 'knex'\nimport type {\n ModuleContext,\n CollectionEntityDefinition,\n SingleEntityDefinition,\n EventEntityDefinition,\n ActionDefinition,\n // ConfigEntityDefinition absorbed into SingleEntityDefinition\n // TempEntityDefinition absorbed into CollectionEntityDefinition\n ViewEntityDefinition,\n ExternalEntityDefinition,\n ComputedEntityDefinition,\n TreeEntityDefinition,\n DagEntityDefinition,\n DatabaseAdapter\n} from '@gzl10/nexus-sdk'\nimport { createInMemoryAdapter } from '../db/memory-adapter.js'\nimport { ManagedCacheImpl } from '../core/cache/managed-cache.js'\nimport { applySearchFilter, getSearchableFields, getPagination, buildPaginatedResult } from '../db/query-helpers.js'\nimport { ErrorCodes } from '../core/errors/error-codes.js'\n\n// Mock error classes\nclass AppError extends Error {\n constructor(message: string, public statusCode: number = 500) {\n super(message)\n this.name = 'AppError'\n }\n}\n\nclass NotFoundError extends Error {\n constructor(resource = 'Resource') {\n super(`${resource} not found`)\n this.name = 'NotFoundError'\n }\n}\n\nclass UnauthorizedError extends Error {\n constructor(message = 'Unauthorized') {\n super(message)\n this.name = 'UnauthorizedError'\n }\n}\n\nclass ForbiddenError extends Error {\n constructor(message = 'Forbidden') {\n super(message)\n this.name = 'ForbiddenError'\n }\n}\n\nclass ConflictError extends Error {\n constructor(message = 'Conflict') {\n super(message)\n this.name = 'ConflictError'\n }\n}\n\nclass ValidationError extends Error {\n public details: Array<{ path: string; message: string; code?: string; interpolation?: Record<string, string | number> }>\n\n constructor(message = 'Validation failed', details: Array<{ path: string; message: string; code?: string; interpolation?: Record<string, string | number> }> = []) {\n super(message)\n this.name = 'ValidationError'\n this.details = details\n }\n}\n\ninterface MockQueryBuilderState {\n _data: unknown[]\n _whereClauses: Array<{ column: string; value: unknown; operator?: string }>\n _whereInClauses: Array<{ column: string; values: unknown[] }>\n _whereNotInClauses: Array<{ column: string; values: unknown[] }>\n _whereNotClauses: Array<{ column: string; value: unknown }>\n _whereNullClauses: string[]\n _whereNotNullClauses: string[]\n _orderBy: { column: string; direction: string } | null\n _limit: number | null\n _offset: number | null\n _insertData: unknown\n _updateData: unknown\n _deleted: boolean\n where: (column: string, operatorOrValue: unknown, value?: unknown) => MockQueryBuilderState\n whereNot: (column: string, value: unknown) => MockQueryBuilderState\n whereIn: (column: string, values: unknown[]) => MockQueryBuilderState\n whereNotIn: (column: string, values: unknown[]) => MockQueryBuilderState\n whereNull: (column: string) => MockQueryBuilderState\n whereNotNull: (column: string) => MockQueryBuilderState\n whereBetween: () => MockQueryBuilderState\n orderBy: (column: string, direction?: string) => MockQueryBuilderState\n limit: (n: number) => MockQueryBuilderState\n offset: (n: number) => MockQueryBuilderState\n select: () => MockQueryBuilderState\n join: () => MockQueryBuilderState\n leftJoin: () => MockQueryBuilderState\n groupBy: () => MockQueryBuilderState\n andWhere: () => MockQueryBuilderState\n orWhere: () => MockQueryBuilderState\n returning: () => MockQueryBuilderState\n clone: () => Knex.QueryBuilder\n count: () => { first: ReturnType<typeof vi.fn> }\n first: () => Promise<unknown>\n insert: (data: unknown) => Promise<number[]>\n update: (data: unknown) => Promise<number>\n delete: () => Promise<number>\n then: (resolve: (value: unknown) => void) => void\n [key: string]: unknown\n}\n\n/**\n * Create mock Knex query builder\n */\nexport function createMockQueryBuilder(data: unknown[] = []) {\n const mockQb: MockQueryBuilderState = {\n _data: [...data],\n _whereClauses: [] as Array<{ column: string; value: unknown; operator?: string }>,\n _whereInClauses: [] as Array<{ column: string; values: unknown[] }>,\n _whereNotInClauses: [] as Array<{ column: string; values: unknown[] }>,\n _whereNotClauses: [] as Array<{ column: string; value: unknown }>,\n _whereNullClauses: [] as string[],\n _whereNotNullClauses: [] as string[],\n _orderBy: null as { column: string; direction: string } | null,\n _limit: null as number | null,\n _offset: null as number | null,\n _insertData: null as unknown,\n _updateData: null as unknown,\n _deleted: false,\n\n where(column: string, operatorOrValue: unknown, value?: unknown) {\n if (value !== undefined) {\n // 3-arg form: where(column, operator, value)\n mockQb._whereClauses = [...(mockQb._whereClauses as Array<{ column: string; value: unknown; operator?: string }>), { column, operator: operatorOrValue as string, value }]\n } else {\n // 2-arg form: where(column, value)\n mockQb._whereClauses = [...(mockQb._whereClauses as Array<{ column: string; value: unknown; operator?: string }>), { column, value: operatorOrValue }]\n }\n return mockQb\n },\n\n whereNot(column: string, value: unknown) {\n mockQb._whereNotClauses = [...(mockQb._whereNotClauses as Array<{ column: string; value: unknown }>), { column, value }]\n return mockQb\n },\n\n whereIn(column: string, values: unknown[]) {\n mockQb._whereInClauses = [...(mockQb._whereInClauses as Array<{ column: string; values: unknown[] }>), { column, values }]\n return mockQb\n },\n\n whereNotIn(column: string, values: unknown[]) {\n mockQb._whereNotInClauses = [...(mockQb._whereNotInClauses as Array<{ column: string; values: unknown[] }>), { column, values }]\n return mockQb\n },\n\n whereNull(column: string) {\n mockQb._whereNullClauses = [...(mockQb._whereNullClauses as string[]), column]\n return mockQb\n },\n\n whereNotNull(column: string) {\n mockQb._whereNotNullClauses = [...(mockQb._whereNotNullClauses as string[]), column]\n return mockQb\n },\n\n whereBetween() {\n return mockQb\n },\n\n orderBy(column: string, direction = 'asc') {\n mockQb._orderBy = { column, direction }\n return mockQb\n },\n\n limit(n: number) {\n mockQb._limit = n\n return mockQb\n },\n\n offset(n: number) {\n mockQb._offset = n\n return mockQb\n },\n\n select() {\n return mockQb\n },\n\n join() {\n return mockQb\n },\n\n leftJoin() {\n return mockQb\n },\n\n groupBy() {\n return mockQb\n },\n\n andWhere() {\n return mockQb\n },\n\n orWhere() {\n return mockQb\n },\n\n returning() {\n return mockQb\n },\n\n clone() {\n return createMockQueryBuilder(mockQb._data as unknown[])\n },\n\n count() {\n return {\n first: vi.fn().mockResolvedValue({ count: (mockQb._data as unknown[]).length })\n }\n },\n\n async first() {\n let result = applyFilters(mockQb._data as Record<string, unknown>[], mockQb)\n\n // Apply orderBy if set\n if (mockQb._orderBy) {\n const { column, direction } = mockQb._orderBy as { column: string; direction: string }\n result = [...result].sort((a, b) => {\n const aVal = String(a[column] ?? '')\n const bVal = String(b[column] ?? '')\n return direction === 'asc'\n ? aVal.localeCompare(bVal)\n : bVal.localeCompare(aVal)\n })\n }\n\n return result[0] ?? undefined\n },\n\n async insert(data: unknown) {\n mockQb._insertData = data\n return [1]\n },\n\n async update(data: unknown) {\n mockQb._updateData = data\n return 1\n },\n\n async delete() {\n mockQb._deleted = true\n return 1\n },\n\n then(resolve: (value: unknown) => void) {\n const filtered = applyFilters(mockQb._data as Record<string, unknown>[], mockQb)\n let result = filtered\n\n if (mockQb._orderBy) {\n const { column, direction } = mockQb._orderBy as { column: string; direction: string }\n result = [...result].sort((a, b) => {\n const aVal = String(a[column] ?? '')\n const bVal = String(b[column] ?? '')\n return direction === 'asc'\n ? aVal.localeCompare(bVal)\n : bVal.localeCompare(aVal)\n })\n }\n\n if (mockQb._offset !== null) {\n result = result.slice(mockQb._offset as number)\n }\n\n if (mockQb._limit !== null) {\n result = result.slice(0, mockQb._limit as number)\n }\n\n resolve(result)\n }\n }\n\n return mockQb as unknown as Knex.QueryBuilder\n}\n\nfunction applyFilters(data: Record<string, unknown>[], qb: MockQueryBuilderState): Record<string, unknown>[] {\n let result = [...data]\n\n // Apply where clauses (supports 2-arg equality and 3-arg operator forms)\n for (const clause of qb._whereClauses as Array<{ column: string; value: unknown; operator?: string }>) {\n if (clause.operator) {\n // 3-arg form: where(column, operator, value)\n result = result.filter(item => {\n const itemVal = item[clause.column]\n switch (clause.operator) {\n case '>': return (itemVal as number) > (clause.value as number)\n case '>=': return (itemVal as number) >= (clause.value as number)\n case '<': return (itemVal as number) < (clause.value as number)\n case '<=': return (itemVal as number) <= (clause.value as number)\n case 'like': {\n const pattern = String(clause.value)\n const str = String(itemVal ?? '')\n if (pattern.startsWith('%') && pattern.endsWith('%'))\n return str.toLowerCase().includes(pattern.slice(1, -1).toLowerCase())\n if (pattern.startsWith('%'))\n return str.toLowerCase().endsWith(pattern.slice(1).toLowerCase())\n if (pattern.endsWith('%'))\n return str.toLowerCase().startsWith(pattern.slice(0, -1).toLowerCase())\n return str === pattern\n }\n default: return itemVal === clause.value\n }\n })\n } else {\n // 2-arg form: where(column, value) — equality\n result = result.filter(item => item[clause.column] === clause.value)\n }\n }\n\n // Apply whereNot clauses\n for (const clause of qb._whereNotClauses as Array<{ column: string; value: unknown }>) {\n result = result.filter(item => item[clause.column] !== clause.value)\n }\n\n // Apply whereIn clauses\n for (const clause of qb._whereInClauses as Array<{ column: string; values: unknown[] }>) {\n result = result.filter(item => clause.values.includes(item[clause.column]))\n }\n\n // Apply whereNotIn clauses\n for (const clause of qb._whereNotInClauses as Array<{ column: string; values: unknown[] }>) {\n result = result.filter(item => !clause.values.includes(item[clause.column]))\n }\n\n // Apply whereNull clauses\n for (const column of qb._whereNullClauses as string[]) {\n result = result.filter(item => item[column] === null || item[column] === undefined)\n }\n\n // Apply whereNotNull clauses\n for (const column of qb._whereNotNullClauses as string[]) {\n result = result.filter(item => item[column] !== null && item[column] !== undefined)\n }\n\n return result\n}\n\n/**\n * Create mock Knex instance\n */\nexport function createMockDb(tableData: Record<string, unknown[]> = {}) {\n const mockDb = vi.fn((table: string) => {\n return createMockQueryBuilder(tableData[table] ?? [])\n }) as unknown as Knex\n\n // Add schema property for migrations\n ;(mockDb as unknown as Record<string, unknown>)['schema'] = {\n hasTable: vi.fn().mockResolvedValue(false),\n createTable: vi.fn().mockResolvedValue(undefined)\n }\n\n // Add raw method\n ;(mockDb as unknown as Record<string, unknown>)['raw'] = vi.fn().mockReturnValue({\n then: (resolve: (v: unknown) => void) => resolve([])\n })\n\n // Add transaction method\n ;(mockDb as unknown as Record<string, unknown>)['transaction'] = vi.fn().mockImplementation(async (callback: (trx: unknown) => Promise<void>) => {\n // Create a trx mock that works like the db mock\n const trxMock = vi.fn((table: string) => {\n return createMockQueryBuilder(tableData[table] ?? [])\n })\n await callback(trxMock)\n })\n\n return mockDb\n}\n\n/**\n * Create mock DbContext with the new structure.\n * Wraps a Knex mock in the full DbContext interface.\n */\nexport function createMockDbContext(tableData: Record<string, unknown[]> = {}): ModuleContext['db'] {\n const mockKnex = createMockDb(tableData)\n\n return {\n knex: mockKnex,\n adapter: {\n findMany: vi.fn().mockResolvedValue({ items: [], total: 0, page: 1, limit: 20, totalPages: 0, hasNext: false }),\n findOne: vi.fn().mockResolvedValue(null),\n findById: vi.fn().mockResolvedValue(null),\n count: vi.fn().mockResolvedValue(0),\n insert: vi.fn().mockResolvedValue({}),\n update: vi.fn().mockResolvedValue({}),\n delete: vi.fn().mockResolvedValue(true),\n transaction: vi.fn().mockImplementation(async (fn: (adapter: unknown) => Promise<void>) => fn({}))\n },\n schema: {\n hasTable: vi.fn().mockResolvedValue(false),\n hasColumn: vi.fn().mockResolvedValue(false),\n getColumns: vi.fn().mockResolvedValue([]),\n createTable: vi.fn().mockResolvedValue(undefined),\n alterTable: vi.fn().mockResolvedValue(undefined),\n dropTable: vi.fn().mockResolvedValue(undefined),\n addTimestamps: vi.fn().mockResolvedValue(undefined),\n addAuditFields: vi.fn().mockResolvedValue(undefined),\n addColumnIfMissing: vi.fn().mockResolvedValue(false),\n raw: {}\n },\n t: (name: string) => name,\n addTimestamps: vi.fn(),\n addAuditFieldsIfMissing: vi.fn(),\n addSoftDeleteFieldIfMissing: vi.fn(),\n addConfigDefaultField: vi.fn(),\n addColumnIfMissing: vi.fn(),\n nowTimestamp: () => new Date().toISOString(),\n formatTimestamp: (_db: unknown, date?: Date) => (date ?? new Date()).toISOString(),\n applySearchFilter,\n getPagination,\n buildPaginatedResult,\n getSearchableFields\n } as unknown as ModuleContext['db']\n}\n\n/**\n * Options for createMockContext, extending ModuleContext overrides with\n * plugin-specific helpers.\n */\ninterface MockContextOptions extends Partial<ModuleContext> {\n pluginCode?: string\n}\n\n/**\n * Create mock ModuleContext\n * Provides sensible defaults for all context properties.\n * Use overrides to customize specific properties per test.\n *\n * Structure matches the new ModuleContext interface:\n * - ctx.core: logger, errors, generateId, crypto, socket, etc.\n * - ctx.db: knex, adapter, schema, helper functions\n * - ctx.engine: module/plugin introspection\n * - ctx.services: inter-module service registry\n * - ctx.adapters: external data source adapters\n *\n * @param overrides - Partial ModuleContext overrides plus optional pluginCode\n * for table name prefixing via ctx.db.t()\n */\nexport function createMockContext(overrides: MockContextOptions = {}): ModuleContext {\n let idCounter = 0\n\n // Extract pluginCode before spreading into ModuleContext\n const { pluginCode, ...rest } = overrides as MockContextOptions\n const t = pluginCode\n ? (name: string) => `${pluginCode}_${name}`\n : (name: string) => name\n\n // Service registry (private, exposed via API)\n const services: Record<string, unknown> = {}\n\n // Adapter registry (private, exposed via API)\n // Pre-register 'temp' adapter with InMemoryAdapter for TempService tests\n const tempAdapter = createInMemoryAdapter()\n const adapters: Record<string, { data: unknown; schema?: unknown }> = {\n temp: { data: tempAdapter }\n }\n\n // Handle legacy override pattern: if overrides.db is a function (Knex mock),\n // wrap it in the new DbContext structure for backwards compatibility\n let processedOverrides = { ...rest }\n if (rest.db && typeof rest.db === 'function') {\n // It's a raw Knex mock, wrap it in DbContext structure\n const knexMock = rest.db as unknown as Knex\n processedOverrides = {\n ...rest,\n db: {\n knex: knexMock,\n adapter: {\n findMany: vi.fn().mockResolvedValue({ items: [], total: 0, page: 1, limit: 20, totalPages: 0, hasNext: false }),\n findOne: vi.fn().mockResolvedValue(null),\n findById: vi.fn().mockResolvedValue(null),\n count: vi.fn().mockResolvedValue(0),\n insert: vi.fn().mockResolvedValue({}),\n update: vi.fn().mockResolvedValue({}),\n delete: vi.fn().mockResolvedValue(true),\n transaction: vi.fn().mockImplementation(async (fn: (adapter: unknown) => Promise<void>) => fn({}))\n },\n schema: {\n hasTable: vi.fn().mockResolvedValue(false),\n hasColumn: vi.fn().mockResolvedValue(false),\n getColumns: vi.fn().mockResolvedValue([]),\n createTable: vi.fn().mockResolvedValue(undefined),\n alterTable: vi.fn().mockResolvedValue(undefined),\n dropTable: vi.fn().mockResolvedValue(undefined),\n addTimestamps: vi.fn().mockResolvedValue(undefined),\n addAuditFields: vi.fn().mockResolvedValue(undefined),\n addColumnIfMissing: vi.fn().mockResolvedValue(false),\n raw: {}\n },\n t,\n addTimestamps: vi.fn(),\n addAuditFieldsIfMissing: vi.fn(),\n addSoftDeleteFieldIfMissing: vi.fn(),\n addConfigDefaultField: vi.fn(),\n addColumnIfMissing: vi.fn(),\n nowTimestamp: () => new Date().toISOString(),\n formatTimestamp: (_db: unknown, date?: Date) => (date ?? new Date()).toISOString(),\n applySearchFilter,\n getPagination,\n buildPaginatedResult,\n getSearchableFields,\n getKnex: () => knexMock,\n // Legacy: ctx.db.raw → now ctx.db.knex.raw\n raw: (knexMock as unknown as { raw: unknown }).raw\n } as unknown as ModuleContext['db']\n }\n }\n\n // Mock Knex instance\n const mockKnex = createMockDb()\n\n // Mock logger\n const mockLogger = {\n info: vi.fn(),\n warn: vi.fn(),\n error: vi.fn(),\n debug: vi.fn(),\n trace: vi.fn(),\n fatal: vi.fn(),\n child: vi.fn().mockReturnThis()\n }\n\n // Mock schema adapter\n const mockSchemaAdapter = {\n hasTable: vi.fn().mockResolvedValue(false),\n hasColumn: vi.fn().mockResolvedValue(false),\n getColumns: vi.fn().mockResolvedValue([]),\n createTable: vi.fn().mockResolvedValue(undefined),\n alterTable: vi.fn().mockResolvedValue(undefined),\n dropTable: vi.fn().mockResolvedValue(undefined),\n addTimestamps: vi.fn().mockResolvedValue(undefined),\n addAuditFields: vi.fn().mockResolvedValue(undefined),\n addColumnIfMissing: vi.fn().mockResolvedValue(false),\n raw: {}\n }\n\n // Mock database adapter\n const mockDbAdapter = {\n findMany: vi.fn().mockResolvedValue({ items: [], total: 0, page: 1, limit: 20, totalPages: 0, hasNext: false }),\n findOne: vi.fn().mockResolvedValue(null),\n findById: vi.fn().mockResolvedValue(null),\n count: vi.fn().mockResolvedValue(0),\n insert: vi.fn().mockResolvedValue({}),\n update: vi.fn().mockResolvedValue({}),\n delete: vi.fn().mockResolvedValue(true),\n transaction: vi.fn().mockImplementation(async (fn: (adapter: unknown) => Promise<void>) => fn({}))\n }\n\n return {\n // =========================================================================\n // Core Context: logger, errors, crypto, socket, events, middleware\n // =========================================================================\n core: {\n logger: mockLogger as unknown as ModuleContext['core']['logger'],\n errors: {\n AppError,\n NotFoundError,\n UnauthorizedError,\n ForbiddenError,\n ConflictError,\n ValidationError,\n codes: ErrorCodes\n },\n crypto: {\n hashPassword: vi.fn().mockResolvedValue('$2b$12$mockhash'),\n verifyPassword: vi.fn().mockResolvedValue(true),\n DUMMY_HASH: '$2b$12$dummyhashfordummypasswordcheck'\n },\n socket: {\n getIO: vi.fn().mockReturnValue({}),\n isInitialized: vi.fn().mockReturnValue(false),\n isUserConnected: vi.fn().mockReturnValue(false),\n getUserSocketCount: vi.fn().mockReturnValue(0),\n getConnectedUsers: vi.fn().mockReturnValue([])\n },\n sse: {\n sendEvent: vi.fn(),\n close: vi.fn()\n },\n abilities: {} as ModuleContext['core']['abilities'],\n events: {\n emit: vi.fn(),\n emitEvent: vi.fn(),\n emitAsync: vi.fn().mockResolvedValue(undefined),\n on: vi.fn(),\n off: vi.fn()\n },\n middleware: {} as ModuleContext['core']['middleware'],\n createRouter: vi.fn(),\n generateId: () => `test-id-${++idCounter}`,\n generateIdByType: (type?: string) => {\n if (type === 'auto' || type === 'custom' || type === 'pattern') return undefined\n return `test-id-${++idCounter}`\n },\n getLibPath: () => '/tmp',\n getProjectPath: () => '/tmp',\n cache: (() => {\n const caches = new Map<string, ManagedCacheImpl<any>>()\n return {\n create: vi.fn().mockImplementation((name: string, opts?: any) => {\n const cache = new ManagedCacheImpl(name, opts)\n caches.set(name, cache)\n return cache\n }),\n getOrCreate: vi.fn().mockImplementation((name: string, opts?: any) => {\n if (caches.has(name)) return caches.get(name)!\n const cache = new ManagedCacheImpl(name, opts)\n caches.set(name, cache)\n return cache\n }),\n get: vi.fn().mockImplementation((name: string) => caches.get(name)),\n clearAll: vi.fn(),\n stats: vi.fn().mockReturnValue({}),\n destroy: vi.fn()\n }\n })(),\n safeJsonParse: <T>(jsonString: string, fallback: T): T => {\n try {\n return JSON.parse(jsonString) as T\n } catch {\n return fallback\n }\n }\n } as unknown as ModuleContext['core'],\n\n // =========================================================================\n // Database Context: knex, adapter, schema, helper functions\n // =========================================================================\n db: {\n knex: mockKnex,\n adapter: mockDbAdapter as unknown as ModuleContext['db']['adapter'],\n schema: mockSchemaAdapter as unknown as ModuleContext['db']['schema'],\n t,\n addTimestamps: vi.fn(),\n addAuditFieldsIfMissing: vi.fn(),\n addSoftDeleteFieldIfMissing: vi.fn(),\n addConfigDefaultField: vi.fn(),\n addColumnIfMissing: vi.fn(),\n nowTimestamp: () => new Date().toISOString(),\n formatTimestamp: (_db: unknown, date?: Date) => (date ?? new Date()).toISOString(),\n applySearchFilter,\n getPagination,\n buildPaginatedResult,\n getSearchableFields,\n getKnex: () => mockKnex,\n // Legacy: ctx.db.raw → now ctx.db.knex.raw\n raw: (mockKnex as unknown as { raw: unknown }).raw\n } as unknown as ModuleContext['db'],\n\n // =========================================================================\n // Runtime Context: entity service/controller/router factories\n // =========================================================================\n runtime: {\n createEntityService: vi.fn(),\n createEntityController: vi.fn(),\n createEntityRouter: vi.fn()\n } as unknown as ModuleContext['runtime'],\n\n // =========================================================================\n // Config Context: env vars and resolved NexusConfig\n // =========================================================================\n config: {} as ModuleContext['config'],\n\n // =========================================================================\n // Engine Context: module/plugin introspection\n // =========================================================================\n engine: {\n getModules: vi.fn().mockReturnValue([]),\n getPlugins: vi.fn().mockReturnValue([]),\n getModuleSubjects: vi.fn().mockReturnValue([]),\n getRegisteredSubjects: vi.fn().mockReturnValue([])\n } as unknown as ModuleContext['engine'],\n\n // =========================================================================\n // Services Context: inter-module service registry\n // =========================================================================\n services: {\n register(name: string, service: unknown): void {\n services[name] = service\n },\n get<T>(serviceName: string): T {\n const service = services[serviceName]\n if (!service) {\n throw new Error(`Service \"${serviceName}\" not initialized.`)\n }\n return service as T\n },\n getOptional<T>(serviceName: string): T | undefined {\n return services[serviceName] as T | undefined\n },\n has(serviceName: string): boolean {\n return !!services[serviceName]\n }\n } as unknown as ModuleContext['services'],\n\n // =========================================================================\n // Adapters Context: external data source adapters\n // =========================================================================\n adapters: {\n register(name: string, dataAdapter: unknown, schemaAdapter?: unknown): void {\n adapters[name] = { data: dataAdapter, schema: schemaAdapter }\n },\n get(name: string) {\n const pair = adapters[name]\n if (!pair) {\n throw new Error(`Adapter \"${name}\" not found`)\n }\n return pair.data\n },\n getSchema(name: string) {\n const pair = adapters[name]\n return pair?.schema\n },\n has(name: string): boolean {\n return name in adapters\n }\n } as unknown as ModuleContext['adapters'],\n\n // =========================================================================\n // Root-level shortcut\n // =========================================================================\n createRouter: vi.fn(),\n\n // Semantic events API (NEX-161)\n events: {\n notify: vi.fn(),\n query: vi.fn().mockResolvedValue([]),\n command: vi.fn().mockResolvedValue(undefined),\n on: vi.fn(),\n off: vi.fn(),\n once: vi.fn(),\n onAny: vi.fn(),\n },\n\n // =========================================================================\n // Legacy API compatibility - deprecated, use new API instead\n // =========================================================================\n\n // Legacy: ctx.logger → now ctx.core.logger\n logger: mockLogger as unknown as ModuleContext['core']['logger'],\n\n // Legacy: ctx.errors → now ctx.core.errors\n errors: {\n AppError,\n NotFoundError,\n UnauthorizedError,\n ForbiddenError,\n ConflictError,\n ValidationError,\n codes: ErrorCodes\n },\n\n // Legacy: ctx.registerService → now ctx.services.register\n registerService(name: string, service: unknown): void {\n services[name] = service\n },\n getService<T>(serviceName: string): T {\n const service = services[serviceName]\n if (!service) {\n throw new Error(`Service \"${serviceName}\" not initialized.`)\n }\n return service as T\n },\n getOptionalService<T>(serviceName: string): T | undefined {\n return services[serviceName] as T | undefined\n },\n hasService(serviceName: string): boolean {\n return !!services[serviceName]\n },\n registerAdapter(name: string, dataAdapter: unknown, schemaAdapter?: unknown): void {\n adapters[name] = { data: dataAdapter, schema: schemaAdapter }\n },\n getAdapter(name: string) {\n const pair = adapters[name]\n if (!pair) {\n throw new Error(`Adapter \"${name}\" not found`)\n }\n return pair.data\n },\n hasAdapter(name: string): boolean {\n return name in adapters\n },\n\n ...processedOverrides\n } as ModuleContext\n}\n\n// === Entity Definition Factories ===\n\nexport function createCollectionDefinition(\n overrides: Partial<CollectionEntityDefinition> = {}\n): CollectionEntityDefinition {\n return {\n type: 'collection',\n table: 'test_items',\n label: 'Test Items',\n labelField: 'name',\n timestamps: true,\n fields: {\n id: {\n label: 'ID',\n input: 'text',\n hidden: true,\n db: { type: 'string', size: 26, nullable: false }\n },\n name: {\n label: 'Name',\n input: 'text',\n db: { type: 'string', size: 100, nullable: false }\n }\n },\n ...overrides\n }\n}\n\nexport function createSingleDefinition(\n overrides: Partial<SingleEntityDefinition> = {}\n): SingleEntityDefinition {\n return {\n type: 'single',\n key: 'test_settings',\n label: 'Test Settings',\n defaults: { theme: 'light', language: 'en' },\n fields: {\n theme: {\n label: 'Theme',\n input: 'select',\n db: { type: 'string', size: 20, nullable: false }\n },\n language: {\n label: 'Language',\n input: 'select',\n db: { type: 'string', size: 10, nullable: false }\n }\n },\n ...overrides\n }\n}\n\nexport function createReferenceDefinition(\n overrides: Partial<CollectionEntityDefinition> = {}\n): CollectionEntityDefinition {\n return {\n type: 'collection',\n table: 'ref_countries',\n label: 'Countries',\n labelField: 'name',\n seed: [\n { id: 'ES', code: 'ES', name: 'Spain' },\n { id: 'US', code: 'US', name: 'United States' },\n { id: 'MX', code: 'MX', name: 'Mexico' }\n ],\n fields: {\n id: {\n label: 'ID',\n input: 'text',\n hidden: true,\n db: { type: 'string', size: 10, nullable: false }\n },\n code: {\n label: 'Code',\n input: 'text',\n db: { type: 'string', size: 10, nullable: false }\n },\n name: {\n label: 'Name',\n input: 'text',\n db: { type: 'string', size: 100, nullable: false }\n }\n },\n ...overrides\n }\n}\n\nexport function createEventDefinition(\n overrides: Partial<EventEntityDefinition> = {}\n): EventEntityDefinition {\n return {\n type: 'event',\n table: 'evt_audit_logs',\n label: 'Audit Logs',\n labelField: 'action',\n immutable: true,\n defaultSort: { field: 'created_at', order: 'desc' as const },\n retention: { days: 90, maxRows: 10000 },\n fields: {\n id: {\n label: 'ID',\n input: 'text',\n hidden: true,\n db: { type: 'string', size: 26, nullable: false }\n },\n action: {\n label: 'Action',\n input: 'text',\n db: { type: 'string', size: 50, nullable: false }\n },\n user_id: {\n label: 'User',\n input: 'text',\n db: { type: 'string', size: 26, nullable: true }\n },\n created_at: {\n label: 'Created At',\n input: 'datetime',\n db: { type: 'datetime', nullable: false }\n }\n },\n ...overrides\n }\n}\n\n/** @deprecated Config absorbed into Single. Use createSingleDefinition with scopeField instead. */\nexport function createConfigDefinition(\n overrides: Partial<SingleEntityDefinition> = {}\n): SingleEntityDefinition {\n return {\n type: 'config',\n key: 'cfg_module_settings',\n label: 'Module Settings',\n scopeField: 'module_name',\n defaults: { enabled: true, maxItems: 100 },\n fields: {\n module_name: {\n label: 'Module',\n input: 'text',\n db: { type: 'string', size: 50, nullable: false }\n },\n enabled: {\n label: 'Enabled',\n input: 'checkbox',\n db: { type: 'boolean', nullable: false }\n },\n maxItems: {\n label: 'Max Items',\n input: 'number',\n db: { type: 'integer', nullable: false }\n }\n },\n ...overrides\n }\n}\n\n/** @deprecated Temp absorbed into Collection. Use createCollectionDefinition with retention instead. */\nexport function createTempDefinition(\n overrides: Partial<CollectionEntityDefinition> = {}\n): CollectionEntityDefinition {\n return {\n type: 'temp',\n table: 'tmp_sessions',\n label: 'Sessions',\n labelField: 'token',\n retention: { seconds: 3600, expiresField: 'expires_at' }, // 1 hour\n fields: {\n id: {\n label: 'ID',\n input: 'text',\n hidden: true,\n db: { type: 'string', size: 26, nullable: false }\n },\n token: {\n label: 'Token',\n input: 'text',\n db: { type: 'string', size: 256, nullable: false }\n },\n expires_at: {\n label: 'Expires At',\n input: 'datetime',\n db: { type: 'datetime', nullable: false }\n }\n },\n ...overrides\n }\n}\n\nexport function createViewDefinition(\n overrides: Partial<ViewEntityDefinition> = {}\n): ViewEntityDefinition {\n return {\n type: 'view',\n table: 'vw_user_stats',\n label: 'User Stats',\n labelField: 'user_id',\n query: 'SELECT user_id, COUNT(*) as count FROM posts GROUP BY user_id',\n fields: {\n user_id: {\n label: 'User',\n input: 'text',\n db: { type: 'string', size: 26, nullable: false }\n },\n count: {\n label: 'Count',\n input: 'number',\n db: { type: 'integer', nullable: false }\n }\n },\n ...overrides\n }\n}\n\nexport function createExternalDefinition(\n overrides: Partial<ExternalEntityDefinition> = {}\n): ExternalEntityDefinition {\n return {\n type: 'external',\n adapter: 'test-api',\n table: 'external_items', // Resource ID in external system\n label: 'External Items',\n labelField: 'title',\n cache: { ttl: 300 },\n fields: {\n id: {\n label: 'ID',\n input: 'text',\n hidden: true,\n db: { type: 'string', size: 26, nullable: false }\n },\n title: {\n label: 'Title',\n input: 'text',\n db: { type: 'string', size: 200, nullable: false }\n }\n },\n ...overrides\n }\n}\n\n/** @deprecated Use createComputedDefinition with sources instead */\nexport function createVirtualDefinition(\n overrides: Partial<ComputedEntityDefinition> = {}\n): ComputedEntityDefinition {\n return createComputedDefinition({\n sources: ['source_a', 'source_b'],\n resolver: (sources) => {\n const combined = [\n ...(sources['source_a'] ?? []),\n ...(sources['source_b'] ?? [])\n ]\n return combined\n },\n compute: undefined,\n ...overrides\n })\n}\n\nexport function createComputedDefinition(\n overrides: Partial<ComputedEntityDefinition> = {}\n): ComputedEntityDefinition {\n return {\n type: 'computed',\n label: 'Computed Stats',\n compute: vi.fn().mockResolvedValue([\n { id: '1', metric: 'users', value: 100 },\n { id: '2', metric: 'posts', value: 500 }\n ]),\n cache: { ttl: 60 },\n fields: {\n id: {\n label: 'ID',\n input: 'text',\n hidden: true,\n db: { type: 'string', size: 26, nullable: false }\n },\n metric: {\n label: 'Metric',\n input: 'text',\n db: { type: 'string', size: 50, nullable: false }\n },\n value: {\n label: 'Value',\n input: 'number',\n db: { type: 'integer', nullable: false }\n }\n },\n ...overrides\n }\n}\n\n// === Mock DatabaseAdapter Factory ===\n\n/**\n * Creates a mock DatabaseAdapter for testing external services.\n * All methods are vi.fn() mocks with sensible defaults.\n */\nexport function createMockDatabaseAdapter(overrides: Partial<DatabaseAdapter> = {}): DatabaseAdapter {\n return {\n findMany: vi.fn().mockResolvedValue({\n items: [\n { id: 'ext-1', title: 'External Item 1' },\n { id: 'ext-2', title: 'External Item 2' }\n ],\n total: 2,\n page: 1,\n limit: 20,\n totalPages: 1,\n hasNext: false\n }),\n findOne: vi.fn().mockResolvedValue(null),\n findById: vi.fn().mockResolvedValue({ id: 'ext-1', title: 'External Item 1' }),\n count: vi.fn().mockResolvedValue(2),\n insert: vi.fn().mockResolvedValue({ id: 'ext-new', title: 'Created' }),\n update: vi.fn().mockResolvedValue({ id: 'ext-1', title: 'Updated' }),\n delete: vi.fn().mockResolvedValue(true),\n transaction: vi.fn().mockImplementation(async (fn) => fn({} as DatabaseAdapter)),\n raw: vi.fn().mockResolvedValue([]),\n ...overrides\n }\n}\n\n// === Tree and DAG Definition Factories ===\n\nexport function createTreeDefinition(\n overrides: Partial<TreeEntityDefinition> = {}\n): TreeEntityDefinition {\n return {\n type: 'tree',\n table: 'tree_categories',\n label: 'Categories',\n labelField: 'name',\n timestamps: true,\n seed: [\n { id: 'root', name: 'Root Category', parent_id: null }\n ],\n fields: {\n id: {\n label: 'ID',\n input: 'text',\n hidden: true,\n db: { type: 'string', size: 26, nullable: false }\n },\n name: {\n label: 'Name',\n input: 'text',\n db: { type: 'string', size: 100, nullable: false }\n }\n // parent_id is auto-injected by TreeService\n },\n ...overrides\n }\n}\n\nexport function createDagDefinition(\n overrides: Partial<DagEntityDefinition> = {}\n): DagEntityDefinition {\n return {\n type: 'dag',\n table: 'dag_tags',\n label: 'Tags',\n labelField: 'name',\n timestamps: true,\n seed: [\n { id: 'root', name: 'Root Tag' }\n ],\n fields: {\n id: {\n label: 'ID',\n input: 'text',\n hidden: true,\n db: { type: 'string', size: 26, nullable: false }\n },\n name: {\n label: 'Name',\n input: 'text',\n db: { type: 'string', size: 100, nullable: false }\n }\n },\n ...overrides\n }\n}\n\n// === Action Definition Factory ===\n\nexport function createActionDefinition(\n overrides: Partial<ActionDefinition> = {}\n): ActionDefinition {\n return {\n key: 'test_action',\n label: 'Test Action',\n scope: 'row',\n method: 'POST',\n handler: async () => ({ success: true }),\n ...overrides\n }\n}\n","/**\n * Query filter helpers.\n *\n * Shared logic for applying filters to Knex queries.\n * Used by both KnexAdapter and BaseService for DRY.\n */\n\nimport type { Knex } from 'knex'\nimport type { FilterOperators } from '@gzl10/nexus-sdk'\n\n/**\n * Escape LIKE wildcard characters (%, _, \\) in user input.\n * Prevents wildcard injection in $contains, $startswith, $endswith operators.\n */\nexport function escapeLikeWildcards(value: string): string {\n return value.replace(/[%_\\\\]/g, '\\\\$&')\n}\n\n/**\n * Apply filters to a Knex query builder.\n *\n * Supports:\n * - Simple equality: `{ name: 'John' }`\n * - Operators: `{ age: { $gte: 18 } }`\n * - Array shorthand for $in: `{ status: ['active', 'pending'] }`\n * - Null check: `{ deletedAt: null }`\n *\n * @example\n * let qb = db('users')\n * qb = applyFilters(qb, { status: 'active', age: { $gte: 18 } })\n */\nexport function applyFilters(qb: Knex.QueryBuilder, filters: Record<string, unknown>): Knex.QueryBuilder {\n for (const [key, value] of Object.entries(filters)) {\n if (value === undefined) continue\n\n // $or: OR logic between filter groups\n if (key === '$or') {\n if (Array.isArray(value) && value.length > 0) {\n qb.where(function () {\n for (const group of value as Record<string, unknown>[]) {\n this.orWhere(function () {\n applyFilters(this, group)\n })\n }\n })\n }\n continue\n }\n\n // Null value - direct comparison\n if (value === null) {\n qb.whereNull(key)\n continue\n }\n\n // Empty string - skip\n if (value === '') continue\n\n // Array shorthand for $in\n if (Array.isArray(value) && value.length > 0) {\n qb.whereIn(key, value as (string | number)[])\n continue\n }\n\n // Object with operators\n if (typeof value === 'object' && !Array.isArray(value)) {\n applyFilterOperators(qb, key, value as FilterOperators)\n continue\n }\n\n // Simple equality\n qb.where(key, value)\n }\n return qb\n}\n\n/**\n * Apply filter operators for a single field.\n *\n * Supported operators:\n * - $eq: Equal\n * - $ne: Not equal\n * - $gt: Greater than\n * - $gte: Greater than or equal\n * - $lt: Less than\n * - $lte: Less than or equal\n * - $contains: LIKE %val%\n * - $startswith: LIKE val%\n * - $endswith: LIKE %val\n * - $in: IN (array)\n * - $nin: NOT IN (array)\n * - $isnull: IS NULL / IS NOT NULL\n */\nexport function applyFilterOperators(qb: Knex.QueryBuilder, field: string, operators: FilterOperators): void {\n for (const [op, val] of Object.entries(operators)) {\n if (val === undefined) continue\n\n switch (op) {\n case '$eq':\n if (val === null) qb.whereNull(field)\n else qb.where(field, val)\n break\n\n case '$ne':\n if (val === null) qb.whereNotNull(field)\n else qb.whereNot(field, val)\n break\n\n case '$gt':\n qb.where(field, '>', val)\n break\n\n case '$gte':\n qb.where(field, '>=', val)\n break\n\n case '$lt':\n qb.where(field, '<', val)\n break\n\n case '$lte':\n qb.where(field, '<=', val)\n break\n\n case '$contains':\n qb.where(field, 'like', `%${escapeLikeWildcards(String(val))}%`)\n break\n\n case '$startswith':\n qb.where(field, 'like', `${escapeLikeWildcards(String(val))}%`)\n break\n\n case '$endswith':\n qb.where(field, 'like', `%${escapeLikeWildcards(String(val))}`)\n break\n\n case '$in':\n if (Array.isArray(val) && val.length > 0) {\n qb.whereIn(field, val as (string | number)[])\n }\n break\n\n case '$nin':\n if (Array.isArray(val) && val.length > 0) {\n qb.whereNotIn(field, val as (string | number)[])\n }\n break\n\n case '$isnull':\n if (val === true) qb.whereNull(field)\n else if (val === false) qb.whereNotNull(field)\n break\n\n case '$between':\n if (Array.isArray(val) && val.length === 2) {\n qb.whereBetween(field, val as [string | number | Date, string | number | Date])\n }\n break\n }\n }\n}\n\n// ============================================================================\n// In-Memory Filter Helpers\n// ============================================================================\n\n/**\n * Apply filters in memory to an array of items.\n *\n * Supports same operators as Knex version:\n * $eq, $ne, $gt, $gte, $lt, $lte, $contains, $startswith, $endswith, $in, $nin, $isnull\n *\n * @example\n * const filtered = applyInMemoryFilters(users, { status: 'active', age: { $gte: 18 } })\n */\nexport function applyInMemoryFilters<T = unknown>(items: T[], filters: Record<string, unknown>): T[] {\n return items.filter(item => {\n const record = item as Record<string, unknown>\n return matchRecordFilters(record, filters)\n })\n}\n\n/**\n * Check if a single record matches all filters (AND logic).\n * Extracted for reuse by $or groups.\n */\nfunction matchRecordFilters(record: Record<string, unknown>, filters: Record<string, unknown>): boolean {\n for (const [key, value] of Object.entries(filters)) {\n if (value === undefined) continue\n\n // $or: at least one group must match\n if (key === '$or') {\n if (Array.isArray(value) && value.length > 0) {\n const orMatch = (value as Record<string, unknown>[]).some(group =>\n matchRecordFilters(record, group)\n )\n if (!orMatch) return false\n }\n continue\n }\n\n const itemValue = record[key]\n\n // Null value - check if field is null\n if (value === null) {\n if (itemValue !== null && itemValue !== undefined) return false\n continue\n }\n\n // Empty string - skip\n if (value === '') continue\n\n // Array shorthand for $in\n if (Array.isArray(value)) {\n // Empty array = no filter (return all)\n if (value.length === 0) continue\n if (!value.includes(itemValue)) return false\n continue\n }\n\n // Object with operators\n if (typeof value === 'object' && !Array.isArray(value)) {\n if (!matchFilterOperators(itemValue, value as FilterOperators)) return false\n continue\n }\n\n // Simple equality\n if (itemValue !== value) return false\n }\n\n return true\n}\n\n/**\n * Match filter operators against a single value (in-memory).\n */\nexport function matchFilterOperators(itemValue: unknown, operators: FilterOperators): boolean {\n for (const [op, val] of Object.entries(operators)) {\n if (val === undefined) continue\n\n switch (op) {\n case '$eq':\n if (val === null) {\n if (itemValue !== null && itemValue !== undefined) return false\n } else if (itemValue !== val) return false\n break\n\n case '$ne':\n if (val === null) {\n if (itemValue === null || itemValue === undefined) return false\n } else if (itemValue === val) return false\n break\n\n case '$gt':\n if (typeof itemValue !== 'number' && typeof itemValue !== 'string') return false\n if (!(itemValue > val)) return false\n break\n\n case '$gte':\n if (typeof itemValue !== 'number' && typeof itemValue !== 'string') return false\n if (!(itemValue >= val)) return false\n break\n\n case '$lt':\n if (typeof itemValue !== 'number' && typeof itemValue !== 'string') return false\n if (!(itemValue < val)) return false\n break\n\n case '$lte':\n if (typeof itemValue !== 'number' && typeof itemValue !== 'string') return false\n if (!(itemValue <= val)) return false\n break\n\n case '$contains':\n if (typeof itemValue !== 'string' || typeof val !== 'string') return false\n if (!itemValue.toLowerCase().includes(val.toLowerCase())) return false\n break\n\n case '$startswith':\n if (typeof itemValue !== 'string' || typeof val !== 'string') return false\n if (!itemValue.toLowerCase().startsWith(val.toLowerCase())) return false\n break\n\n case '$endswith':\n if (typeof itemValue !== 'string' || typeof val !== 'string') return false\n if (!itemValue.toLowerCase().endsWith(val.toLowerCase())) return false\n break\n\n case '$in':\n if (!Array.isArray(val) || val.length === 0) break\n if (!val.includes(itemValue)) return false\n break\n\n case '$nin':\n if (!Array.isArray(val) || val.length === 0) break\n if (val.includes(itemValue)) return false\n break\n\n case '$isnull':\n if (val === true && itemValue !== null && itemValue !== undefined) return false\n if (val === false && (itemValue === null || itemValue === undefined)) return false\n break\n\n case '$between':\n if (!Array.isArray(val) || val.length !== 2) break\n if (typeof itemValue !== 'number' && typeof itemValue !== 'string') return false\n if (!(itemValue >= val[0] && itemValue <= val[1])) return false\n break\n }\n }\n return true\n}\n","/**\n * In-Memory adapter with TTL support.\n *\n * Used exclusively by TempService for temporary entities with automatic expiration.\n * Persistent entities (collection, reference, etc.) use Knex SQLite :memory: instead.\n */\n\nimport type {\n DatabaseAdapter,\n PaginatedResult,\n EntityQuery\n} from '@gzl10/nexus-sdk'\nimport { applyInMemoryFilters } from './filter-helpers.js'\n\nconst DEFAULT_PAGE = 1\nconst DEFAULT_LIMIT = 20\nconst DEFAULT_MAX_LIMIT = 10000\n\nfunction generateId(): string {\n return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, c => {\n const r = Math.random() * 16 | 0\n const v = c === 'x' ? r : (r & 0x3 | 0x8)\n return v.toString(16)\n })\n}\n\ninterface StoredRecord {\n id: string\n created_at: string\n updated_at: string\n [key: string]: unknown\n}\n\ninterface TtlMetadata {\n expiresAt: number\n timerId: ReturnType<typeof setTimeout>\n}\n\nexport class InMemoryAdapter implements DatabaseAdapter {\n private tables: Map<string, Map<string, StoredRecord>> = new Map()\n private ttlMap: Map<string, TtlMetadata> = new Map()\n\n get raw(): unknown {\n return this.tables\n }\n\n clear(): void {\n for (const metadata of this.ttlMap.values()) {\n clearTimeout(metadata.timerId)\n }\n this.ttlMap.clear()\n this.tables.clear()\n }\n\n clearTable(table: string): void {\n this.tables.delete(table)\n }\n\n seed<T extends Record<string, unknown>>(table: string, records: T[]): void {\n const tableData = this.getOrCreateTable(table)\n for (const record of records) {\n const id = (record['id'] as string) || generateId()\n const now = new Date().toISOString()\n tableData.set(id, {\n ...record,\n id,\n created_at: (record['created_at'] as string) || now,\n updated_at: (record['updated_at'] as string) || now\n })\n }\n }\n\n private getOrCreateTable(table: string): Map<string, StoredRecord> {\n let tableData = this.tables.get(table)\n if (!tableData) {\n tableData = new Map()\n this.tables.set(table, tableData)\n }\n return tableData\n }\n\n // ---- DatabaseAdapter interface ----\n\n async findMany<T = unknown>(table: string, query?: EntityQuery): Promise<PaginatedResult<T>> {\n const maxLimit = query?.maxLimit ?? DEFAULT_MAX_LIMIT\n const page = Math.max(1, query?.page ?? DEFAULT_PAGE)\n const limit = Math.min(maxLimit, Math.max(1, query?.limit ?? DEFAULT_LIMIT))\n const offset = (page - 1) * limit\n\n const tableData = this.tables.get(table)\n if (!tableData) {\n return { items: [], total: 0, page, limit, totalPages: 0, hasNext: false }\n }\n\n let items = Array.from(tableData.values()) as T[]\n\n // Apply filters\n if (query?.filters) {\n items = applyInMemoryFilters(items, query.filters)\n }\n\n // Basic sorting\n if (query?.sort) {\n const sortField = query.sort\n const order = query.order ?? 'asc'\n items.sort((a, b) => {\n const aVal = (a as Record<string, unknown>)[sortField]\n const bVal = (b as Record<string, unknown>)[sortField]\n if (aVal === bVal) return 0\n if (aVal === null || aVal === undefined) return 1\n if (bVal === null || bVal === undefined) return -1\n const comparison = aVal < bVal ? -1 : 1\n return order === 'asc' ? comparison : -comparison\n })\n }\n\n const total = items.length\n items = items.slice(offset, offset + limit)\n const totalPages = Math.ceil(total / limit)\n\n return { items, total, page, limit, totalPages, hasNext: page < totalPages }\n }\n\n async findOne<T = unknown>(table: string, filters: Record<string, unknown>): Promise<T | null> {\n const tableData = this.tables.get(table)\n if (!tableData) return null\n for (const record of tableData.values()) {\n const match = Object.entries(filters).every(([k, v]) => record[k] === v)\n if (match) return record as T\n }\n return null\n }\n\n async findById<T = unknown>(table: string, id: string): Promise<T | null> {\n const tableData = this.tables.get(table)\n if (!tableData) return null\n return (tableData.get(id) as T) ?? null\n }\n\n async count(table: string, filters?: Record<string, unknown>): Promise<number> {\n const tableData = this.tables.get(table)\n if (!tableData) return 0\n if (!filters || Object.keys(filters).length === 0) return tableData.size\n const items = applyInMemoryFilters(Array.from(tableData.values()), filters)\n return items.length\n }\n\n async insert<T = unknown>(table: string, data: Record<string, unknown>): Promise<T> {\n const tableData = this.getOrCreateTable(table)\n const id = (data['id'] as string) || generateId()\n const now = new Date().toISOString()\n const record: StoredRecord = { ...data, id, created_at: now, updated_at: now }\n tableData.set(id, record)\n return record as T\n }\n\n async update<T = unknown>(table: string, id: string, data: Record<string, unknown>): Promise<T> {\n const tableData = this.tables.get(table)\n if (!tableData) throw new Error(`Table \"${table}\" not found`)\n const existing = tableData.get(id)\n if (!existing) throw new Error(`Record \"${id}\" not found in table \"${table}\"`)\n const updated: StoredRecord = {\n ...existing, ...data,\n id,\n created_at: existing.created_at,\n updated_at: new Date().toISOString()\n }\n tableData.set(id, updated)\n return updated as T\n }\n\n async delete(table: string, id: string): Promise<boolean> {\n const tableData = this.tables.get(table)\n if (!tableData) return false\n return tableData.delete(id)\n }\n\n async transaction<T>(fn: (trx: DatabaseAdapter) => Promise<T>): Promise<T> {\n return fn(this)\n }\n\n // ---- TTL Methods ----\n\n private getTtlKey(table: string, id: string): string {\n return `${table}:${id}`\n }\n\n async insertWithTtl<T = unknown>(table: string, data: Record<string, unknown>, ttlSeconds: number): Promise<T> {\n const tableData = this.getOrCreateTable(table)\n const id = (data['id'] as string) || generateId()\n const now = new Date().toISOString()\n const expires_at = new Date(Date.now() + ttlSeconds * 1000).toISOString()\n const record: StoredRecord = { ...data, id, created_at: now, updated_at: now, expires_at }\n tableData.set(id, record)\n\n const ttlKey = this.getTtlKey(table, id)\n const timerId = setTimeout(() => this.deleteWithTtlCleanup(table, id), ttlSeconds * 1000)\n this.ttlMap.set(ttlKey, { expiresAt: Date.now() + ttlSeconds * 1000, timerId })\n\n return record as T\n }\n\n private deleteWithTtlCleanup(table: string, id: string): void {\n const tableData = this.tables.get(table)\n if (tableData) tableData.delete(id)\n const ttlKey = this.getTtlKey(table, id)\n const metadata = this.ttlMap.get(ttlKey)\n if (metadata) {\n clearTimeout(metadata.timerId)\n this.ttlMap.delete(ttlKey)\n }\n }\n\n async setTtl(table: string, id: string, ttlSeconds: number): Promise<boolean> {\n const tableData = this.tables.get(table)\n if (!tableData) return false\n const record = tableData.get(id)\n if (!record) return false\n\n record['expires_at'] = new Date(Date.now() + ttlSeconds * 1000).toISOString()\n record['updated_at'] = new Date().toISOString()\n\n const ttlKey = this.getTtlKey(table, id)\n const existing = this.ttlMap.get(ttlKey)\n if (existing) clearTimeout(existing.timerId)\n\n const timerId = setTimeout(() => this.deleteWithTtlCleanup(table, id), ttlSeconds * 1000)\n this.ttlMap.set(ttlKey, { expiresAt: Date.now() + ttlSeconds * 1000, timerId })\n return true\n }\n\n async getTtl(table: string, id: string): Promise<number> {\n const tableData = this.tables.get(table)\n if (!tableData || !tableData.has(id)) return -2\n\n const ttlKey = this.getTtlKey(table, id)\n const metadata = this.ttlMap.get(ttlKey)\n if (!metadata) return -1\n\n const remainingMs = metadata.expiresAt - Date.now()\n return remainingMs <= 0 ? -2 : Math.ceil(remainingMs / 1000)\n }\n\n async cleanupExpiredIds(_table: string): Promise<number> {\n return 0\n }\n}\n\nexport function createInMemoryAdapter(): InMemoryAdapter {\n return new InMemoryAdapter()\n}\n","/**\n * LRU Cache - Least Recently Used cache with TTL support\n *\n * Features:\n * - LRU eviction when max entries reached\n * - TTL expiration per entry\n * - Hit/miss statistics\n * - Prefix-based deletion for invalidation\n */\n\nimport type { CacheStats } from '@gzl10/nexus-sdk'\nexport type { CacheStats }\n\ninterface CacheEntry<T> {\n data: T\n expires: number\n}\n\nexport interface LRUCacheOptions {\n /** Maximum number of entries (default: 100) */\n maxEntries?: number\n /** Default TTL in seconds (default: 60) */\n defaultTTL?: number\n}\n\nexport class LRUCache<T = unknown> {\n private cache: Map<string, CacheEntry<T>>\n private readonly maxEntries: number\n private readonly defaultTTL: number\n\n private hits = 0\n private misses = 0\n\n constructor(options?: LRUCacheOptions) {\n this.cache = new Map()\n this.maxEntries = options?.maxEntries ?? 100\n this.defaultTTL = options?.defaultTTL ?? 60\n }\n\n /**\n * Get value from cache\n * Returns null if not found or expired\n * Moves entry to end (most recently used)\n */\n get(key: string): T | null {\n const entry = this.cache.get(key)\n\n if (!entry) {\n this.misses++\n return null\n }\n\n // Check expiration\n if (entry.expires > 0 && entry.expires < Date.now()) {\n this.cache.delete(key)\n this.misses++\n return null\n }\n\n // Move to end (most recently used)\n this.cache.delete(key)\n this.cache.set(key, entry)\n\n this.hits++\n return entry.data\n }\n\n /**\n * Set value in cache\n * Evicts oldest entry if max entries reached\n * @param ttl TTL in seconds (0 = no expiration, undefined = use default)\n */\n set(key: string, data: T, ttl?: number): void {\n // Delete existing to update position\n this.cache.delete(key)\n\n // Evict oldest if at capacity\n if (this.cache.size >= this.maxEntries) {\n const oldestKey = this.cache.keys().next().value\n if (oldestKey) {\n this.cache.delete(oldestKey)\n }\n }\n\n const actualTTL = ttl ?? this.defaultTTL\n const expires = actualTTL > 0 ? Date.now() + actualTTL * 1000 : 0\n\n this.cache.set(key, { data, expires })\n }\n\n /**\n * Delete specific key\n */\n delete(key: string): boolean {\n return this.cache.delete(key)\n }\n\n /**\n * Delete all keys matching prefix\n * @returns Number of deleted entries\n */\n deleteByPrefix(prefix: string): number {\n let deleted = 0\n for (const key of this.cache.keys()) {\n if (key.startsWith(prefix)) {\n this.cache.delete(key)\n deleted++\n }\n }\n return deleted\n }\n\n /**\n * Clear all entries\n */\n clear(): void {\n this.cache.clear()\n }\n\n /**\n * Check if key exists and is not expired\n */\n has(key: string): boolean {\n const entry = this.cache.get(key)\n if (!entry) return false\n if (entry.expires > 0 && entry.expires < Date.now()) {\n this.cache.delete(key)\n return false\n }\n return true\n }\n\n /**\n * Get current size\n */\n get size(): number {\n return this.cache.size\n }\n\n /**\n * Get cache statistics\n */\n getStats(): CacheStats {\n const total = this.hits + this.misses\n return {\n hits: this.hits,\n misses: this.misses,\n hitRate: total > 0 ? this.hits / total : 0,\n size: this.cache.size,\n maxEntries: this.maxEntries\n }\n }\n\n /**\n * Reset statistics\n */\n resetStats(): void {\n this.hits = 0\n this.misses = 0\n }\n\n /**\n * Prune expired entries\n * Call periodically to clean up memory\n */\n prune(): number {\n const now = Date.now()\n let pruned = 0\n\n for (const [key, entry] of this.cache.entries()) {\n if (entry.expires > 0 && entry.expires < now) {\n this.cache.delete(key)\n pruned++\n }\n }\n\n return pruned\n }\n}\n","import type { ManagedCache, CacheOptions, CacheStats } from '@gzl10/nexus-sdk'\nimport { LRUCache } from './lru-cache.js'\n\n/**\n * Thin wrapper over LRUCache implementing the ManagedCache SDK contract.\n * Adds name tracking and delegates to addRules callback for invalidation.\n */\nexport class ManagedCacheImpl<T = unknown> implements ManagedCache<T> {\n private cache: LRUCache<T>\n private onAddRules?: (events: string[]) => void\n\n constructor(\n public readonly name: string,\n options?: CacheOptions,\n onAddRules?: (events: string[]) => void\n ) {\n this.cache = new LRUCache<T>({\n maxEntries: options?.maxEntries,\n defaultTTL: options?.defaultTTL\n })\n this.onAddRules = onAddRules\n }\n\n async get(key: string): Promise<T | null> {\n return this.cache.get(key)\n }\n\n async set(key: string, value: T, ttl?: number): Promise<void> {\n this.cache.set(key, value, ttl)\n }\n\n async delete(key: string): Promise<boolean> {\n return this.cache.delete(key)\n }\n\n async deleteByPrefix(prefix: string): Promise<number> {\n return this.cache.deleteByPrefix(prefix)\n }\n\n async has(key: string): Promise<boolean> {\n return this.cache.has(key)\n }\n\n async clear(): Promise<void> {\n this.cache.clear()\n }\n\n getStats(): CacheStats {\n return this.cache.getStats()\n }\n\n resetStats(): void {\n this.cache.resetStats()\n }\n\n addInvalidationRules(events: string[]): void {\n this.onAddRules?.(events)\n }\n\n async prune(): Promise<number> {\n return this.cache.prune()\n }\n\n async getSize(): Promise<number> {\n return this.cache.size\n }\n}\n","/**\n * Query builder helpers for common operations\n */\nimport type { Knex } from 'knex'\nimport type { EntityDefinition, EntityQuery, PaginatedResult } from '@gzl10/nexus-sdk'\n\nconst DEFAULT_PAGE = 1\nconst DEFAULT_LIMIT = 20\nexport const DEFAULT_MAX_LIMIT = 100\n\nexport interface PaginationParams {\n page: number\n limit: number\n offset: number\n}\n\n/**\n * Extract pagination parameters from query.\n * Validates and normalizes page/limit values.\n */\nexport function getPagination(query?: EntityQuery): PaginationParams {\n const maxLimit = query?.maxLimit ?? DEFAULT_MAX_LIMIT\n const page = Math.max(1, query?.page ?? DEFAULT_PAGE)\n const limit = Math.min(maxLimit, Math.max(1, query?.limit ?? DEFAULT_LIMIT))\n const offset = (page - 1) * limit\n return { page, limit, offset }\n}\n\n/**\n * Build a PaginatedResult from items and total count.\n */\nexport function buildPaginatedResult<T>(\n items: T[],\n total: number,\n pagination: PaginationParams\n): PaginatedResult<T> {\n const { page, limit } = pagination\n const totalPages = Math.ceil(total / limit)\n return {\n items,\n total,\n page,\n limit,\n totalPages,\n hasNext: page < totalPages\n }\n}\n\n/**\n * Get searchable field names from entity definition\n */\nexport function getSearchableFields(definition: EntityDefinition): string[] {\n return Object.entries(definition.fields ?? {})\n .filter(([_, f]) => f.meta?.searchable === true)\n .map(([name]) => name)\n}\n\n/**\n * Apply search filter to query builder based on entity definition.\n * Searches in fields with meta.searchable: true, or falls back to labelField.\n */\nexport function applySearchFilter(\n qb: Knex.QueryBuilder,\n definition: EntityDefinition,\n search: string\n): Knex.QueryBuilder {\n const searchableFields = getSearchableFields(definition)\n\n // Fallback to labelField if no searchable fields\n if (searchableFields.length === 0 && 'labelField' in definition && definition.labelField) {\n searchableFields.push(definition.labelField as string)\n }\n\n // Apply OR search across all searchable fields\n if (searchableFields.length > 0) {\n const searchPattern = `%${search}%`\n qb.where(function () {\n for (const field of searchableFields) {\n this.orWhere(field, 'like', searchPattern)\n }\n })\n }\n\n return qb\n}\n","/**\n * Error codes for i18n-friendly error handling.\n * Frontend translates these codes to localized messages.\n *\n * Format: CATEGORY_ACTION_REASON\n *\n * Categories: AUTH, USER, ROLE, VALIDATION, STORAGE, PERMISSION, RESOURCE, SYSTEM\n */\nexport const ErrorCodes = {\n // Auth\n AUTH_INVALID_CREDENTIALS: 'AUTH_INVALID_CREDENTIALS',\n AUTH_TOKEN_EXPIRED: 'AUTH_TOKEN_EXPIRED',\n AUTH_TOKEN_INVALID: 'AUTH_TOKEN_INVALID',\n AUTH_TOKEN_REQUIRED: 'AUTH_TOKEN_REQUIRED',\n AUTH_OTP_REQUIRED: 'AUTH_OTP_REQUIRED',\n AUTH_OTP_INVALID: 'AUTH_OTP_INVALID',\n AUTH_REFRESH_TOKEN_REQUIRED: 'AUTH_REFRESH_TOKEN_REQUIRED',\n AUTH_REFRESH_TOKEN_INVALID: 'AUTH_REFRESH_TOKEN_INVALID',\n AUTH_REFRESH_TOKEN_EXPIRED: 'AUTH_REFRESH_TOKEN_EXPIRED',\n AUTH_SESSION_NOT_FOUND: 'AUTH_SESSION_NOT_FOUND',\n AUTH_SESSION_SELF_REVOKE: 'AUTH_SESSION_SELF_REVOKE',\n AUTH_VERIFICATION_CODE_INVALID: 'AUTH_VERIFICATION_CODE_INVALID',\n AUTH_REGISTRATION_DISABLED: 'AUTH_REGISTRATION_DISABLED',\n AUTH_AUTO_CREATE_DISABLED: 'AUTH_AUTO_CREATE_DISABLED',\n\n // User\n USER_NOT_FOUND: 'USER_NOT_FOUND',\n USER_EMAIL_EXISTS: 'USER_EMAIL_EXISTS',\n USER_NOT_AUTHENTICATED: 'USER_NOT_AUTHENTICATED',\n\n // Role\n ROLE_NOT_FOUND: 'ROLE_NOT_FOUND',\n ROLE_NAME_EXISTS: 'ROLE_NAME_EXISTS',\n ROLE_SYSTEM_PROTECTED: 'ROLE_SYSTEM_PROTECTED',\n ROLE_HAS_USERS: 'ROLE_HAS_USERS',\n ROLE_DEFAULT_NOT_FOUND: 'ROLE_DEFAULT_NOT_FOUND',\n\n // Permission\n PERMISSION_DENIED: 'PERMISSION_DENIED',\n\n // Validation\n VALIDATION_ERROR: 'VALIDATION_ERROR',\n VALIDATION_FIELD_REQUIRED: 'VALIDATION_FIELD_REQUIRED',\n VALIDATION_FIELD_INVALID: 'VALIDATION_FIELD_INVALID',\n VALIDATION_JSON_MALFORMED: 'VALIDATION_JSON_MALFORMED',\n\n // Storage\n STORAGE_FILE_NOT_FOUND: 'STORAGE_FILE_NOT_FOUND',\n STORAGE_FILE_TOO_LARGE: 'STORAGE_FILE_TOO_LARGE',\n STORAGE_FILE_TYPE_NOT_ALLOWED: 'STORAGE_FILE_TYPE_NOT_ALLOWED',\n STORAGE_PAYLOAD_TOO_LARGE: 'STORAGE_PAYLOAD_TOO_LARGE',\n\n // Resource (generic)\n RESOURCE_NOT_FOUND: 'RESOURCE_NOT_FOUND',\n RESOURCE_CONFLICT: 'RESOURCE_CONFLICT',\n RESOURCE_CREATE_NOT_SUPPORTED: 'RESOURCE_CREATE_NOT_SUPPORTED',\n RESOURCE_UPDATE_NOT_SUPPORTED: 'RESOURCE_UPDATE_NOT_SUPPORTED',\n RESOURCE_DELETE_NOT_SUPPORTED: 'RESOURCE_DELETE_NOT_SUPPORTED',\n\n // Module\n MODULE_NOT_FOUND: 'MODULE_NOT_FOUND',\n\n // HTTP standard\n NOT_FOUND: 'NOT_FOUND',\n AUTH_UNAUTHORIZED: 'AUTH_UNAUTHORIZED',\n\n // Database\n DB_CONSTRAINT_UNIQUE: 'DB_CONSTRAINT_UNIQUE',\n DB_CONSTRAINT_FK: 'DB_CONSTRAINT_FK',\n DB_CONNECTION_ERROR: 'DB_CONNECTION_ERROR',\n DATABASE_NOT_READY: 'DATABASE_NOT_READY',\n\n // System\n SYSTEM_INTERNAL_ERROR: 'SYSTEM_INTERNAL_ERROR',\n} as const\n\nexport type ErrorCode = typeof ErrorCodes[keyof typeof ErrorCodes]\n","import type { Knex } from 'knex'\n\n/**\n * Creates minimal core tables in SQLite :memory: for plugin integration tests.\n * Only includes columns that other tables reference via FK.\n * Call before runGeneratedMigration() in plugin tests.\n */\nexport async function createCoreTables(db: Knex): Promise<void> {\n if (!await db.schema.hasTable('users')) {\n await db.schema.createTable('users', (t) => {\n t.string('id', 26).primary()\n t.string('name', 100).notNullable()\n t.string('email', 255).notNullable()\n t.string('role', 20).notNullable().defaultTo('user')\n t.timestamps(true, true)\n })\n }\n\n if (!await db.schema.hasTable('roles')) {\n await db.schema.createTable('roles', (t) => {\n t.string('id', 26).primary()\n t.string('name', 50).notNullable()\n })\n }\n}\n","import type { ErrorCode } from './error-codes.js'\nimport { ErrorCodes } from './error-codes.js'\n\n/**\n * Parameters for creating an AppError with i18n support\n */\nexport interface AppErrorParams {\n /** Error code for i18n translation (e.g., 'AUTH_INVALID_CREDENTIALS') */\n code: ErrorCode\n /** Fallback message in English (used if frontend doesn't have translation) */\n message?: string\n /** Interpolation values for the translated message (e.g., { resource: 'User' }) */\n interpolation?: Record<string, string | number>\n}\n\n/**\n * Base application error with i18n support.\n *\n * Can be created with:\n * - String message (legacy, backward compatible)\n * - AppErrorParams object (new, with code and interpolation)\n *\n * @example\n * // Legacy usage\n * throw new AppError('Something went wrong', 400)\n *\n * // New usage with i18n\n * throw new AppError({\n * code: ErrorCodes.USER_NOT_FOUND,\n * message: 'User not found',\n * interpolation: { resource: 'User' }\n * }, 404)\n */\nexport class AppError extends Error {\n public readonly statusCode: number\n public readonly code: ErrorCode\n public readonly interpolation?: Record<string, string | number>\n public readonly details?: unknown\n\n constructor(\n params: AppErrorParams | string,\n statusCode: number = 400,\n details?: unknown\n ) {\n if (typeof params === 'string') {\n // Legacy: string message (backward compatible)\n super(params)\n this.code = ErrorCodes.SYSTEM_INTERNAL_ERROR\n } else {\n // New: structured params with code\n super(params.message || params.code)\n this.code = params.code\n this.interpolation = params.interpolation\n }\n\n this.statusCode = statusCode\n this.details = details\n this.name = 'AppError'\n Error.captureStackTrace(this, this.constructor)\n }\n}\n\n/**\n * Resource not found error (404)\n */\nexport class NotFoundError extends AppError {\n constructor(resource: string = 'Resource') {\n super({\n code: ErrorCodes.RESOURCE_NOT_FOUND,\n message: `${resource} not found`,\n interpolation: { resource }\n }, 404)\n this.name = 'NotFoundError'\n }\n}\n\n/**\n * Authentication required error (401)\n */\nexport class UnauthorizedError extends AppError {\n constructor(codeOrMessage: ErrorCode | string = ErrorCodes.AUTH_TOKEN_REQUIRED, message?: string) {\n // Check if first param is an ErrorCode\n const isCode = Object.values(ErrorCodes).includes(codeOrMessage as ErrorCode)\n\n if (isCode) {\n super({\n code: codeOrMessage as ErrorCode,\n message: message || 'Unauthorized'\n }, 401)\n } else {\n // Legacy: string message\n super({\n code: ErrorCodes.AUTH_TOKEN_REQUIRED,\n message: codeOrMessage as string\n }, 401)\n }\n this.name = 'UnauthorizedError'\n }\n}\n\n/**\n * Access denied error (403)\n */\nexport class ForbiddenError extends AppError {\n constructor(codeOrMessage: ErrorCode | string = ErrorCodes.PERMISSION_DENIED, message?: string) {\n const isCode = Object.values(ErrorCodes).includes(codeOrMessage as ErrorCode)\n\n if (isCode) {\n super({\n code: codeOrMessage as ErrorCode,\n message: message || 'Access denied'\n }, 403)\n } else {\n super({\n code: ErrorCodes.PERMISSION_DENIED,\n message: codeOrMessage as string\n }, 403)\n }\n this.name = 'ForbiddenError'\n }\n}\n\n/**\n * Resource conflict error (409)\n */\nexport class ConflictError extends AppError {\n constructor(codeOrMessage: ErrorCode | string = ErrorCodes.RESOURCE_CONFLICT, message?: string) {\n const isCode = Object.values(ErrorCodes).includes(codeOrMessage as ErrorCode)\n\n if (isCode) {\n super({\n code: codeOrMessage as ErrorCode,\n message: message || 'Conflict'\n }, 409)\n } else {\n super({\n code: ErrorCodes.RESOURCE_CONFLICT,\n message: codeOrMessage as string\n }, 409)\n }\n this.name = 'ConflictError'\n }\n}\n\n/**\n * Standard validation error detail\n */\nexport interface ValidationDetail {\n path: string\n message: string\n /** Error code for i18n translation */\n code?: string\n /** Interpolation values */\n interpolation?: Record<string, string | number>\n}\n\n/**\n * Validation error with field-level details (400)\n */\nexport class ValidationError extends AppError {\n public override readonly details: ValidationDetail[]\n\n constructor(messageOrCode: string | ErrorCode = ErrorCodes.VALIDATION_ERROR, details: ValidationDetail[] = []) {\n const isCode = Object.values(ErrorCodes).includes(messageOrCode as ErrorCode)\n\n if (isCode) {\n super({\n code: messageOrCode as ErrorCode,\n message: 'Validation error'\n }, 400)\n } else {\n super({\n code: ErrorCodes.VALIDATION_ERROR,\n message: messageOrCode as string\n }, 400)\n }\n\n this.name = 'ValidationError'\n this.details = details\n }\n}\n\n// Re-export ErrorCodes for convenience\nexport { ErrorCodes } from './error-codes.js'\nexport type { ErrorCode } from './error-codes.js'\n","import knex, { type Knex } from 'knex'\n\nexport type { Knex }\n\n/**\n * Creates a Knex instance with SQLite :memory: for integration tests.\n * Plugins should use this instead of importing knex/better-sqlite3 directly.\n */\nexport function createTestDb(): Knex {\n return knex({\n client: 'better-sqlite3',\n connection: ':memory:',\n useNullAsDefault: true\n })\n}\n"],"mappings":";AAIA,SAAS,UAAU;;;AC2KZ,SAAS,qBAAkC,OAAY,SAAuC;AACnG,SAAO,MAAM,OAAO,UAAQ;AAC1B,UAAM,SAAS;AACf,WAAO,mBAAmB,QAAQ,OAAO;AAAA,EAC3C,CAAC;AACH;AAMA,SAAS,mBAAmB,QAAiC,SAA2C;AACtG,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,OAAO,GAAG;AAClD,QAAI,UAAU,OAAW;AAGzB,QAAI,QAAQ,OAAO;AACjB,UAAI,MAAM,QAAQ,KAAK,KAAK,MAAM,SAAS,GAAG;AAC5C,cAAM,UAAW,MAAoC;AAAA,UAAK,WACxD,mBAAmB,QAAQ,KAAK;AAAA,QAClC;AACA,YAAI,CAAC,QAAS,QAAO;AAAA,MACvB;AACA;AAAA,IACF;AAEA,UAAM,YAAY,OAAO,GAAG;AAG5B,QAAI,UAAU,MAAM;AAClB,UAAI,cAAc,QAAQ,cAAc,OAAW,QAAO;AAC1D;AAAA,IACF;AAGA,QAAI,UAAU,GAAI;AAGlB,QAAI,MAAM,QAAQ,KAAK,GAAG;AAExB,UAAI,MAAM,WAAW,EAAG;AACxB,UAAI,CAAC,MAAM,SAAS,SAAS,EAAG,QAAO;AACvC;AAAA,IACF;AAGA,QAAI,OAAO,UAAU,YAAY,CAAC,MAAM,QAAQ,KAAK,GAAG;AACtD,UAAI,CAAC,qBAAqB,WAAW,KAAwB,EAAG,QAAO;AACvE;AAAA,IACF;AAGA,QAAI,cAAc,MAAO,QAAO;AAAA,EAClC;AAEA,SAAO;AACT;AAKO,SAAS,qBAAqB,WAAoB,WAAqC;AAC5F,aAAW,CAAC,IAAI,GAAG,KAAK,OAAO,QAAQ,SAAS,GAAG;AACjD,QAAI,QAAQ,OAAW;AAEvB,YAAQ,IAAI;AAAA,MACV,KAAK;AACH,YAAI,QAAQ,MAAM;AAChB,cAAI,cAAc,QAAQ,cAAc,OAAW,QAAO;AAAA,QAC5D,WAAW,cAAc,IAAK,QAAO;AACrC;AAAA,MAEF,KAAK;AACH,YAAI,QAAQ,MAAM;AAChB,cAAI,cAAc,QAAQ,cAAc,OAAW,QAAO;AAAA,QAC5D,WAAW,cAAc,IAAK,QAAO;AACrC;AAAA,MAEF,KAAK;AACH,YAAI,OAAO,cAAc,YAAY,OAAO,cAAc,SAAU,QAAO;AAC3E,YAAI,EAAE,YAAY,KAAM,QAAO;AAC/B;AAAA,MAEF,KAAK;AACH,YAAI,OAAO,cAAc,YAAY,OAAO,cAAc,SAAU,QAAO;AAC3E,YAAI,EAAE,aAAa,KAAM,QAAO;AAChC;AAAA,MAEF,KAAK;AACH,YAAI,OAAO,cAAc,YAAY,OAAO,cAAc,SAAU,QAAO;AAC3E,YAAI,EAAE,YAAY,KAAM,QAAO;AAC/B;AAAA,MAEF,KAAK;AACH,YAAI,OAAO,cAAc,YAAY,OAAO,cAAc,SAAU,QAAO;AAC3E,YAAI,EAAE,aAAa,KAAM,QAAO;AAChC;AAAA,MAEF,KAAK;AACH,YAAI,OAAO,cAAc,YAAY,OAAO,QAAQ,SAAU,QAAO;AACrE,YAAI,CAAC,UAAU,YAAY,EAAE,SAAS,IAAI,YAAY,CAAC,EAAG,QAAO;AACjE;AAAA,MAEF,KAAK;AACH,YAAI,OAAO,cAAc,YAAY,OAAO,QAAQ,SAAU,QAAO;AACrE,YAAI,CAAC,UAAU,YAAY,EAAE,WAAW,IAAI,YAAY,CAAC,EAAG,QAAO;AACnE;AAAA,MAEF,KAAK;AACH,YAAI,OAAO,cAAc,YAAY,OAAO,QAAQ,SAAU,QAAO;AACrE,YAAI,CAAC,UAAU,YAAY,EAAE,SAAS,IAAI,YAAY,CAAC,EAAG,QAAO;AACjE;AAAA,MAEF,KAAK;AACH,YAAI,CAAC,MAAM,QAAQ,GAAG,KAAK,IAAI,WAAW,EAAG;AAC7C,YAAI,CAAC,IAAI,SAAS,SAAS,EAAG,QAAO;AACrC;AAAA,MAEF,KAAK;AACH,YAAI,CAAC,MAAM,QAAQ,GAAG,KAAK,IAAI,WAAW,EAAG;AAC7C,YAAI,IAAI,SAAS,SAAS,EAAG,QAAO;AACpC;AAAA,MAEF,KAAK;AACH,YAAI,QAAQ,QAAQ,cAAc,QAAQ,cAAc,OAAW,QAAO;AAC1E,YAAI,QAAQ,UAAU,cAAc,QAAQ,cAAc,QAAY,QAAO;AAC7E;AAAA,MAEF,KAAK;AACH,YAAI,CAAC,MAAM,QAAQ,GAAG,KAAK,IAAI,WAAW,EAAG;AAC7C,YAAI,OAAO,cAAc,YAAY,OAAO,cAAc,SAAU,QAAO;AAC3E,YAAI,EAAE,aAAa,IAAI,CAAC,KAAK,aAAa,IAAI,CAAC,GAAI,QAAO;AAC1D;AAAA,IACJ;AAAA,EACF;AACA,SAAO;AACT;;;ACzSA,IAAM,eAAe;AACrB,IAAM,gBAAgB;AACtB,IAAM,oBAAoB;AAE1B,SAAS,aAAqB;AAC5B,SAAO,uCAAuC,QAAQ,SAAS,OAAK;AAClE,UAAM,IAAI,KAAK,OAAO,IAAI,KAAK;AAC/B,UAAM,IAAI,MAAM,MAAM,IAAK,IAAI,IAAM;AACrC,WAAO,EAAE,SAAS,EAAE;AAAA,EACtB,CAAC;AACH;AAcO,IAAM,kBAAN,MAAiD;AAAA,EAC9C,SAAiD,oBAAI,IAAI;AAAA,EACzD,SAAmC,oBAAI,IAAI;AAAA,EAEnD,IAAI,MAAe;AACjB,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,QAAc;AACZ,eAAW,YAAY,KAAK,OAAO,OAAO,GAAG;AAC3C,mBAAa,SAAS,OAAO;AAAA,IAC/B;AACA,SAAK,OAAO,MAAM;AAClB,SAAK,OAAO,MAAM;AAAA,EACpB;AAAA,EAEA,WAAW,OAAqB;AAC9B,SAAK,OAAO,OAAO,KAAK;AAAA,EAC1B;AAAA,EAEA,KAAwC,OAAe,SAAoB;AACzE,UAAM,YAAY,KAAK,iBAAiB,KAAK;AAC7C,eAAW,UAAU,SAAS;AAC5B,YAAM,KAAM,OAAO,IAAI,KAAgB,WAAW;AAClD,YAAM,OAAM,oBAAI,KAAK,GAAE,YAAY;AACnC,gBAAU,IAAI,IAAI;AAAA,QAChB,GAAG;AAAA,QACH;AAAA,QACA,YAAa,OAAO,YAAY,KAAgB;AAAA,QAChD,YAAa,OAAO,YAAY,KAAgB;AAAA,MAClD,CAAC;AAAA,IACH;AAAA,EACF;AAAA,EAEQ,iBAAiB,OAA0C;AACjE,QAAI,YAAY,KAAK,OAAO,IAAI,KAAK;AACrC,QAAI,CAAC,WAAW;AACd,kBAAY,oBAAI,IAAI;AACpB,WAAK,OAAO,IAAI,OAAO,SAAS;AAAA,IAClC;AACA,WAAO;AAAA,EACT;AAAA;AAAA,EAIA,MAAM,SAAsB,OAAe,OAAkD;AAC3F,UAAM,WAAW,OAAO,YAAY;AACpC,UAAM,OAAO,KAAK,IAAI,GAAG,OAAO,QAAQ,YAAY;AACpD,UAAM,QAAQ,KAAK,IAAI,UAAU,KAAK,IAAI,GAAG,OAAO,SAAS,aAAa,CAAC;AAC3E,UAAM,UAAU,OAAO,KAAK;AAE5B,UAAM,YAAY,KAAK,OAAO,IAAI,KAAK;AACvC,QAAI,CAAC,WAAW;AACd,aAAO,EAAE,OAAO,CAAC,GAAG,OAAO,GAAG,MAAM,OAAO,YAAY,GAAG,SAAS,MAAM;AAAA,IAC3E;AAEA,QAAI,QAAQ,MAAM,KAAK,UAAU,OAAO,CAAC;AAGzC,QAAI,OAAO,SAAS;AAClB,cAAQ,qBAAqB,OAAO,MAAM,OAAO;AAAA,IACnD;AAGA,QAAI,OAAO,MAAM;AACf,YAAM,YAAY,MAAM;AACxB,YAAM,QAAQ,MAAM,SAAS;AAC7B,YAAM,KAAK,CAAC,GAAG,MAAM;AACnB,cAAM,OAAQ,EAA8B,SAAS;AACrD,cAAM,OAAQ,EAA8B,SAAS;AACrD,YAAI,SAAS,KAAM,QAAO;AAC1B,YAAI,SAAS,QAAQ,SAAS,OAAW,QAAO;AAChD,YAAI,SAAS,QAAQ,SAAS,OAAW,QAAO;AAChD,cAAM,aAAa,OAAO,OAAO,KAAK;AACtC,eAAO,UAAU,QAAQ,aAAa,CAAC;AAAA,MACzC,CAAC;AAAA,IACH;AAEA,UAAM,QAAQ,MAAM;AACpB,YAAQ,MAAM,MAAM,QAAQ,SAAS,KAAK;AAC1C,UAAM,aAAa,KAAK,KAAK,QAAQ,KAAK;AAE1C,WAAO,EAAE,OAAO,OAAO,MAAM,OAAO,YAAY,SAAS,OAAO,WAAW;AAAA,EAC7E;AAAA,EAEA,MAAM,QAAqB,OAAe,SAAqD;AAC7F,UAAM,YAAY,KAAK,OAAO,IAAI,KAAK;AACvC,QAAI,CAAC,UAAW,QAAO;AACvB,eAAW,UAAU,UAAU,OAAO,GAAG;AACvC,YAAM,QAAQ,OAAO,QAAQ,OAAO,EAAE,MAAM,CAAC,CAAC,GAAG,CAAC,MAAM,OAAO,CAAC,MAAM,CAAC;AACvE,UAAI,MAAO,QAAO;AAAA,IACpB;AACA,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,SAAsB,OAAe,IAA+B;AACxE,UAAM,YAAY,KAAK,OAAO,IAAI,KAAK;AACvC,QAAI,CAAC,UAAW,QAAO;AACvB,WAAQ,UAAU,IAAI,EAAE,KAAW;AAAA,EACrC;AAAA,EAEA,MAAM,MAAM,OAAe,SAAoD;AAC7E,UAAM,YAAY,KAAK,OAAO,IAAI,KAAK;AACvC,QAAI,CAAC,UAAW,QAAO;AACvB,QAAI,CAAC,WAAW,OAAO,KAAK,OAAO,EAAE,WAAW,EAAG,QAAO,UAAU;AACpE,UAAM,QAAQ,qBAAqB,MAAM,KAAK,UAAU,OAAO,CAAC,GAAG,OAAO;AAC1E,WAAO,MAAM;AAAA,EACf;AAAA,EAEA,MAAM,OAAoB,OAAe,MAA2C;AAClF,UAAM,YAAY,KAAK,iBAAiB,KAAK;AAC7C,UAAM,KAAM,KAAK,IAAI,KAAgB,WAAW;AAChD,UAAM,OAAM,oBAAI,KAAK,GAAE,YAAY;AACnC,UAAM,SAAuB,EAAE,GAAG,MAAM,IAAI,YAAY,KAAK,YAAY,IAAI;AAC7E,cAAU,IAAI,IAAI,MAAM;AACxB,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,OAAoB,OAAe,IAAY,MAA2C;AAC9F,UAAM,YAAY,KAAK,OAAO,IAAI,KAAK;AACvC,QAAI,CAAC,UAAW,OAAM,IAAI,MAAM,UAAU,KAAK,aAAa;AAC5D,UAAM,WAAW,UAAU,IAAI,EAAE;AACjC,QAAI,CAAC,SAAU,OAAM,IAAI,MAAM,WAAW,EAAE,yBAAyB,KAAK,GAAG;AAC7E,UAAM,UAAwB;AAAA,MAC5B,GAAG;AAAA,MAAU,GAAG;AAAA,MAChB;AAAA,MACA,YAAY,SAAS;AAAA,MACrB,aAAY,oBAAI,KAAK,GAAE,YAAY;AAAA,IACrC;AACA,cAAU,IAAI,IAAI,OAAO;AACzB,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,OAAO,OAAe,IAA8B;AACxD,UAAM,YAAY,KAAK,OAAO,IAAI,KAAK;AACvC,QAAI,CAAC,UAAW,QAAO;AACvB,WAAO,UAAU,OAAO,EAAE;AAAA,EAC5B;AAAA,EAEA,MAAM,YAAe,IAAsD;AACzE,WAAO,GAAG,IAAI;AAAA,EAChB;AAAA;AAAA,EAIQ,UAAU,OAAe,IAAoB;AACnD,WAAO,GAAG,KAAK,IAAI,EAAE;AAAA,EACvB;AAAA,EAEA,MAAM,cAA2B,OAAe,MAA+B,YAAgC;AAC7G,UAAM,YAAY,KAAK,iBAAiB,KAAK;AAC7C,UAAM,KAAM,KAAK,IAAI,KAAgB,WAAW;AAChD,UAAM,OAAM,oBAAI,KAAK,GAAE,YAAY;AACnC,UAAM,aAAa,IAAI,KAAK,KAAK,IAAI,IAAI,aAAa,GAAI,EAAE,YAAY;AACxE,UAAM,SAAuB,EAAE,GAAG,MAAM,IAAI,YAAY,KAAK,YAAY,KAAK,WAAW;AACzF,cAAU,IAAI,IAAI,MAAM;AAExB,UAAM,SAAS,KAAK,UAAU,OAAO,EAAE;AACvC,UAAM,UAAU,WAAW,MAAM,KAAK,qBAAqB,OAAO,EAAE,GAAG,aAAa,GAAI;AACxF,SAAK,OAAO,IAAI,QAAQ,EAAE,WAAW,KAAK,IAAI,IAAI,aAAa,KAAM,QAAQ,CAAC;AAE9E,WAAO;AAAA,EACT;AAAA,EAEQ,qBAAqB,OAAe,IAAkB;AAC5D,UAAM,YAAY,KAAK,OAAO,IAAI,KAAK;AACvC,QAAI,UAAW,WAAU,OAAO,EAAE;AAClC,UAAM,SAAS,KAAK,UAAU,OAAO,EAAE;AACvC,UAAM,WAAW,KAAK,OAAO,IAAI,MAAM;AACvC,QAAI,UAAU;AACZ,mBAAa,SAAS,OAAO;AAC7B,WAAK,OAAO,OAAO,MAAM;AAAA,IAC3B;AAAA,EACF;AAAA,EAEA,MAAM,OAAO,OAAe,IAAY,YAAsC;AAC5E,UAAM,YAAY,KAAK,OAAO,IAAI,KAAK;AACvC,QAAI,CAAC,UAAW,QAAO;AACvB,UAAM,SAAS,UAAU,IAAI,EAAE;AAC/B,QAAI,CAAC,OAAQ,QAAO;AAEpB,WAAO,YAAY,IAAI,IAAI,KAAK,KAAK,IAAI,IAAI,aAAa,GAAI,EAAE,YAAY;AAC5E,WAAO,YAAY,KAAI,oBAAI,KAAK,GAAE,YAAY;AAE9C,UAAM,SAAS,KAAK,UAAU,OAAO,EAAE;AACvC,UAAM,WAAW,KAAK,OAAO,IAAI,MAAM;AACvC,QAAI,SAAU,cAAa,SAAS,OAAO;AAE3C,UAAM,UAAU,WAAW,MAAM,KAAK,qBAAqB,OAAO,EAAE,GAAG,aAAa,GAAI;AACxF,SAAK,OAAO,IAAI,QAAQ,EAAE,WAAW,KAAK,IAAI,IAAI,aAAa,KAAM,QAAQ,CAAC;AAC9E,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,OAAO,OAAe,IAA6B;AACvD,UAAM,YAAY,KAAK,OAAO,IAAI,KAAK;AACvC,QAAI,CAAC,aAAa,CAAC,UAAU,IAAI,EAAE,EAAG,QAAO;AAE7C,UAAM,SAAS,KAAK,UAAU,OAAO,EAAE;AACvC,UAAM,WAAW,KAAK,OAAO,IAAI,MAAM;AACvC,QAAI,CAAC,SAAU,QAAO;AAEtB,UAAM,cAAc,SAAS,YAAY,KAAK,IAAI;AAClD,WAAO,eAAe,IAAI,KAAK,KAAK,KAAK,cAAc,GAAI;AAAA,EAC7D;AAAA,EAEA,MAAM,kBAAkB,QAAiC;AACvD,WAAO;AAAA,EACT;AACF;AAEO,SAAS,wBAAyC;AACvD,SAAO,IAAI,gBAAgB;AAC7B;;;ACjOO,IAAM,WAAN,MAA4B;AAAA,EACzB;AAAA,EACS;AAAA,EACA;AAAA,EAET,OAAO;AAAA,EACP,SAAS;AAAA,EAEjB,YAAY,SAA2B;AACrC,SAAK,QAAQ,oBAAI,IAAI;AACrB,SAAK,aAAa,SAAS,cAAc;AACzC,SAAK,aAAa,SAAS,cAAc;AAAA,EAC3C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,IAAI,KAAuB;AACzB,UAAM,QAAQ,KAAK,MAAM,IAAI,GAAG;AAEhC,QAAI,CAAC,OAAO;AACV,WAAK;AACL,aAAO;AAAA,IACT;AAGA,QAAI,MAAM,UAAU,KAAK,MAAM,UAAU,KAAK,IAAI,GAAG;AACnD,WAAK,MAAM,OAAO,GAAG;AACrB,WAAK;AACL,aAAO;AAAA,IACT;AAGA,SAAK,MAAM,OAAO,GAAG;AACrB,SAAK,MAAM,IAAI,KAAK,KAAK;AAEzB,SAAK;AACL,WAAO,MAAM;AAAA,EACf;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,IAAI,KAAa,MAAS,KAAoB;AAE5C,SAAK,MAAM,OAAO,GAAG;AAGrB,QAAI,KAAK,MAAM,QAAQ,KAAK,YAAY;AACtC,YAAM,YAAY,KAAK,MAAM,KAAK,EAAE,KAAK,EAAE;AAC3C,UAAI,WAAW;AACb,aAAK,MAAM,OAAO,SAAS;AAAA,MAC7B;AAAA,IACF;AAEA,UAAM,YAAY,OAAO,KAAK;AAC9B,UAAM,UAAU,YAAY,IAAI,KAAK,IAAI,IAAI,YAAY,MAAO;AAEhE,SAAK,MAAM,IAAI,KAAK,EAAE,MAAM,QAAQ,CAAC;AAAA,EACvC;AAAA;AAAA;AAAA;AAAA,EAKA,OAAO,KAAsB;AAC3B,WAAO,KAAK,MAAM,OAAO,GAAG;AAAA,EAC9B;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,eAAe,QAAwB;AACrC,QAAI,UAAU;AACd,eAAW,OAAO,KAAK,MAAM,KAAK,GAAG;AACnC,UAAI,IAAI,WAAW,MAAM,GAAG;AAC1B,aAAK,MAAM,OAAO,GAAG;AACrB;AAAA,MACF;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,QAAc;AACZ,SAAK,MAAM,MAAM;AAAA,EACnB;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,KAAsB;AACxB,UAAM,QAAQ,KAAK,MAAM,IAAI,GAAG;AAChC,QAAI,CAAC,MAAO,QAAO;AACnB,QAAI,MAAM,UAAU,KAAK,MAAM,UAAU,KAAK,IAAI,GAAG;AACnD,WAAK,MAAM,OAAO,GAAG;AACrB,aAAO;AAAA,IACT;AACA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,OAAe;AACjB,WAAO,KAAK,MAAM;AAAA,EACpB;AAAA;AAAA;AAAA;AAAA,EAKA,WAAuB;AACrB,UAAM,QAAQ,KAAK,OAAO,KAAK;AAC/B,WAAO;AAAA,MACL,MAAM,KAAK;AAAA,MACX,QAAQ,KAAK;AAAA,MACb,SAAS,QAAQ,IAAI,KAAK,OAAO,QAAQ;AAAA,MACzC,MAAM,KAAK,MAAM;AAAA,MACjB,YAAY,KAAK;AAAA,IACnB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,aAAmB;AACjB,SAAK,OAAO;AACZ,SAAK,SAAS;AAAA,EAChB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,QAAgB;AACd,UAAM,MAAM,KAAK,IAAI;AACrB,QAAI,SAAS;AAEb,eAAW,CAAC,KAAK,KAAK,KAAK,KAAK,MAAM,QAAQ,GAAG;AAC/C,UAAI,MAAM,UAAU,KAAK,MAAM,UAAU,KAAK;AAC5C,aAAK,MAAM,OAAO,GAAG;AACrB;AAAA,MACF;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AACF;;;AC3KO,IAAM,mBAAN,MAA+D;AAAA,EAIpE,YACkB,MAChB,SACA,YACA;AAHgB;AAIhB,SAAK,QAAQ,IAAI,SAAY;AAAA,MAC3B,YAAY,SAAS;AAAA,MACrB,YAAY,SAAS;AAAA,IACvB,CAAC;AACD,SAAK,aAAa;AAAA,EACpB;AAAA,EAbQ;AAAA,EACA;AAAA,EAcR,MAAM,IAAI,KAAgC;AACxC,WAAO,KAAK,MAAM,IAAI,GAAG;AAAA,EAC3B;AAAA,EAEA,MAAM,IAAI,KAAa,OAAU,KAA6B;AAC5D,SAAK,MAAM,IAAI,KAAK,OAAO,GAAG;AAAA,EAChC;AAAA,EAEA,MAAM,OAAO,KAA+B;AAC1C,WAAO,KAAK,MAAM,OAAO,GAAG;AAAA,EAC9B;AAAA,EAEA,MAAM,eAAe,QAAiC;AACpD,WAAO,KAAK,MAAM,eAAe,MAAM;AAAA,EACzC;AAAA,EAEA,MAAM,IAAI,KAA+B;AACvC,WAAO,KAAK,MAAM,IAAI,GAAG;AAAA,EAC3B;AAAA,EAEA,MAAM,QAAuB;AAC3B,SAAK,MAAM,MAAM;AAAA,EACnB;AAAA,EAEA,WAAuB;AACrB,WAAO,KAAK,MAAM,SAAS;AAAA,EAC7B;AAAA,EAEA,aAAmB;AACjB,SAAK,MAAM,WAAW;AAAA,EACxB;AAAA,EAEA,qBAAqB,QAAwB;AAC3C,SAAK,aAAa,MAAM;AAAA,EAC1B;AAAA,EAEA,MAAM,QAAyB;AAC7B,WAAO,KAAK,MAAM,MAAM;AAAA,EAC1B;AAAA,EAEA,MAAM,UAA2B;AAC/B,WAAO,KAAK,MAAM;AAAA,EACpB;AACF;;;AC5DA,IAAMA,gBAAe;AACrB,IAAMC,iBAAgB;AACf,IAAMC,qBAAoB;AAY1B,SAAS,cAAc,OAAuC;AACnE,QAAM,WAAW,OAAO,YAAYA;AACpC,QAAM,OAAO,KAAK,IAAI,GAAG,OAAO,QAAQF,aAAY;AACpD,QAAM,QAAQ,KAAK,IAAI,UAAU,KAAK,IAAI,GAAG,OAAO,SAASC,cAAa,CAAC;AAC3E,QAAM,UAAU,OAAO,KAAK;AAC5B,SAAO,EAAE,MAAM,OAAO,OAAO;AAC/B;AAKO,SAAS,qBACd,OACA,OACA,YACoB;AACpB,QAAM,EAAE,MAAM,MAAM,IAAI;AACxB,QAAM,aAAa,KAAK,KAAK,QAAQ,KAAK;AAC1C,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,SAAS,OAAO;AAAA,EAClB;AACF;AAKO,SAAS,oBAAoB,YAAwC;AAC1E,SAAO,OAAO,QAAQ,WAAW,UAAU,CAAC,CAAC,EAC1C,OAAO,CAAC,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,eAAe,IAAI,EAC9C,IAAI,CAAC,CAAC,IAAI,MAAM,IAAI;AACzB;AAMO,SAAS,kBACd,IACA,YACA,QACmB;AACnB,QAAM,mBAAmB,oBAAoB,UAAU;AAGvD,MAAI,iBAAiB,WAAW,KAAK,gBAAgB,cAAc,WAAW,YAAY;AACxF,qBAAiB,KAAK,WAAW,UAAoB;AAAA,EACvD;AAGA,MAAI,iBAAiB,SAAS,GAAG;AAC/B,UAAM,gBAAgB,IAAI,MAAM;AAChC,OAAG,MAAM,WAAY;AACnB,iBAAW,SAAS,kBAAkB;AACpC,aAAK,QAAQ,OAAO,QAAQ,aAAa;AAAA,MAC3C;AAAA,IACF,CAAC;AAAA,EACH;AAEA,SAAO;AACT;;;AC5EO,IAAM,aAAa;AAAA;AAAA,EAExB,0BAA0B;AAAA,EAC1B,oBAAoB;AAAA,EACpB,oBAAoB;AAAA,EACpB,qBAAqB;AAAA,EACrB,mBAAmB;AAAA,EACnB,kBAAkB;AAAA,EAClB,6BAA6B;AAAA,EAC7B,4BAA4B;AAAA,EAC5B,4BAA4B;AAAA,EAC5B,wBAAwB;AAAA,EACxB,0BAA0B;AAAA,EAC1B,gCAAgC;AAAA,EAChC,4BAA4B;AAAA,EAC5B,2BAA2B;AAAA;AAAA,EAG3B,gBAAgB;AAAA,EAChB,mBAAmB;AAAA,EACnB,wBAAwB;AAAA;AAAA,EAGxB,gBAAgB;AAAA,EAChB,kBAAkB;AAAA,EAClB,uBAAuB;AAAA,EACvB,gBAAgB;AAAA,EAChB,wBAAwB;AAAA;AAAA,EAGxB,mBAAmB;AAAA;AAAA,EAGnB,kBAAkB;AAAA,EAClB,2BAA2B;AAAA,EAC3B,0BAA0B;AAAA,EAC1B,2BAA2B;AAAA;AAAA,EAG3B,wBAAwB;AAAA,EACxB,wBAAwB;AAAA,EACxB,+BAA+B;AAAA,EAC/B,2BAA2B;AAAA;AAAA,EAG3B,oBAAoB;AAAA,EACpB,mBAAmB;AAAA,EACnB,+BAA+B;AAAA,EAC/B,+BAA+B;AAAA,EAC/B,+BAA+B;AAAA;AAAA,EAG/B,kBAAkB;AAAA;AAAA,EAGlB,WAAW;AAAA,EACX,mBAAmB;AAAA;AAAA,EAGnB,sBAAsB;AAAA,EACtB,kBAAkB;AAAA,EAClB,qBAAqB;AAAA,EACrB,oBAAoB;AAAA;AAAA,EAGpB,uBAAuB;AACzB;;;AN/CA,IAAM,WAAN,cAAuB,MAAM;AAAA,EAC3B,YAAY,SAAwB,aAAqB,KAAK;AAC5D,UAAM,OAAO;AADqB;AAElC,SAAK,OAAO;AAAA,EACd;AACF;AAEA,IAAM,gBAAN,cAA4B,MAAM;AAAA,EAChC,YAAY,WAAW,YAAY;AACjC,UAAM,GAAG,QAAQ,YAAY;AAC7B,SAAK,OAAO;AAAA,EACd;AACF;AAEA,IAAM,oBAAN,cAAgC,MAAM;AAAA,EACpC,YAAY,UAAU,gBAAgB;AACpC,UAAM,OAAO;AACb,SAAK,OAAO;AAAA,EACd;AACF;AAEA,IAAM,iBAAN,cAA6B,MAAM;AAAA,EACjC,YAAY,UAAU,aAAa;AACjC,UAAM,OAAO;AACb,SAAK,OAAO;AAAA,EACd;AACF;AAEA,IAAM,gBAAN,cAA4B,MAAM;AAAA,EAChC,YAAY,UAAU,YAAY;AAChC,UAAM,OAAO;AACb,SAAK,OAAO;AAAA,EACd;AACF;AAEA,IAAM,kBAAN,cAA8B,MAAM;AAAA,EAC3B;AAAA,EAEP,YAAY,UAAU,qBAAqB,UAAoH,CAAC,GAAG;AACjK,UAAM,OAAO;AACb,SAAK,OAAO;AACZ,SAAK,UAAU;AAAA,EACjB;AACF;AA8CO,SAAS,uBAAuB,OAAkB,CAAC,GAAG;AAC3D,QAAM,SAAgC;AAAA,IACpC,OAAO,CAAC,GAAG,IAAI;AAAA,IACf,eAAe,CAAC;AAAA,IAChB,iBAAiB,CAAC;AAAA,IAClB,oBAAoB,CAAC;AAAA,IACrB,kBAAkB,CAAC;AAAA,IACnB,mBAAmB,CAAC;AAAA,IACpB,sBAAsB,CAAC;AAAA,IACvB,UAAU;AAAA,IACV,QAAQ;AAAA,IACR,SAAS;AAAA,IACT,aAAa;AAAA,IACb,aAAa;AAAA,IACb,UAAU;AAAA,IAEV,MAAM,QAAgB,iBAA0B,OAAiB;AAC/D,UAAI,UAAU,QAAW;AAEvB,eAAO,gBAAgB,CAAC,GAAI,OAAO,eAAgF,EAAE,QAAQ,UAAU,iBAA2B,MAAM,CAAC;AAAA,MAC3K,OAAO;AAEL,eAAO,gBAAgB,CAAC,GAAI,OAAO,eAAgF,EAAE,QAAQ,OAAO,gBAAgB,CAAC;AAAA,MACvJ;AACA,aAAO;AAAA,IACT;AAAA,IAEA,SAAS,QAAgB,OAAgB;AACvC,aAAO,mBAAmB,CAAC,GAAI,OAAO,kBAAgE,EAAE,QAAQ,MAAM,CAAC;AACvH,aAAO;AAAA,IACT;AAAA,IAEA,QAAQ,QAAgB,QAAmB;AACzC,aAAO,kBAAkB,CAAC,GAAI,OAAO,iBAAkE,EAAE,QAAQ,OAAO,CAAC;AACzH,aAAO;AAAA,IACT;AAAA,IAEA,WAAW,QAAgB,QAAmB;AAC5C,aAAO,qBAAqB,CAAC,GAAI,OAAO,oBAAqE,EAAE,QAAQ,OAAO,CAAC;AAC/H,aAAO;AAAA,IACT;AAAA,IAEA,UAAU,QAAgB;AACxB,aAAO,oBAAoB,CAAC,GAAI,OAAO,mBAAgC,MAAM;AAC7E,aAAO;AAAA,IACT;AAAA,IAEA,aAAa,QAAgB;AAC3B,aAAO,uBAAuB,CAAC,GAAI,OAAO,sBAAmC,MAAM;AACnF,aAAO;AAAA,IACT;AAAA,IAEA,eAAe;AACb,aAAO;AAAA,IACT;AAAA,IAEA,QAAQ,QAAgB,YAAY,OAAO;AACzC,aAAO,WAAW,EAAE,QAAQ,UAAU;AACtC,aAAO;AAAA,IACT;AAAA,IAEA,MAAM,GAAW;AACf,aAAO,SAAS;AAChB,aAAO;AAAA,IACT;AAAA,IAEA,OAAO,GAAW;AAChB,aAAO,UAAU;AACjB,aAAO;AAAA,IACT;AAAA,IAEA,SAAS;AACP,aAAO;AAAA,IACT;AAAA,IAEA,OAAO;AACL,aAAO;AAAA,IACT;AAAA,IAEA,WAAW;AACT,aAAO;AAAA,IACT;AAAA,IAEA,UAAU;AACR,aAAO;AAAA,IACT;AAAA,IAEA,WAAW;AACT,aAAO;AAAA,IACT;AAAA,IAEA,UAAU;AACR,aAAO;AAAA,IACT;AAAA,IAEA,YAAY;AACV,aAAO;AAAA,IACT;AAAA,IAEA,QAAQ;AACN,aAAO,uBAAuB,OAAO,KAAkB;AAAA,IACzD;AAAA,IAEA,QAAQ;AACN,aAAO;AAAA,QACL,OAAO,GAAG,GAAG,EAAE,kBAAkB,EAAE,OAAQ,OAAO,MAAoB,OAAO,CAAC;AAAA,MAChF;AAAA,IACF;AAAA,IAEA,MAAM,QAAQ;AACZ,UAAI,SAAS,aAAa,OAAO,OAAoC,MAAM;AAG3E,UAAI,OAAO,UAAU;AACnB,cAAM,EAAE,QAAQ,UAAU,IAAI,OAAO;AACrC,iBAAS,CAAC,GAAG,MAAM,EAAE,KAAK,CAAC,GAAG,MAAM;AAClC,gBAAM,OAAO,OAAO,EAAE,MAAM,KAAK,EAAE;AACnC,gBAAM,OAAO,OAAO,EAAE,MAAM,KAAK,EAAE;AACnC,iBAAO,cAAc,QACjB,KAAK,cAAc,IAAI,IACvB,KAAK,cAAc,IAAI;AAAA,QAC7B,CAAC;AAAA,MACH;AAEA,aAAO,OAAO,CAAC,KAAK;AAAA,IACtB;AAAA,IAEA,MAAM,OAAOE,OAAe;AAC1B,aAAO,cAAcA;AACrB,aAAO,CAAC,CAAC;AAAA,IACX;AAAA,IAEA,MAAM,OAAOA,OAAe;AAC1B,aAAO,cAAcA;AACrB,aAAO;AAAA,IACT;AAAA,IAEA,MAAM,SAAS;AACb,aAAO,WAAW;AAClB,aAAO;AAAA,IACT;AAAA,IAEA,KAAK,SAAmC;AACtC,YAAM,WAAW,aAAa,OAAO,OAAoC,MAAM;AAC/E,UAAI,SAAS;AAEb,UAAI,OAAO,UAAU;AACnB,cAAM,EAAE,QAAQ,UAAU,IAAI,OAAO;AACrC,iBAAS,CAAC,GAAG,MAAM,EAAE,KAAK,CAAC,GAAG,MAAM;AAClC,gBAAM,OAAO,OAAO,EAAE,MAAM,KAAK,EAAE;AACnC,gBAAM,OAAO,OAAO,EAAE,MAAM,KAAK,EAAE;AACnC,iBAAO,cAAc,QACjB,KAAK,cAAc,IAAI,IACvB,KAAK,cAAc,IAAI;AAAA,QAC7B,CAAC;AAAA,MACH;AAEA,UAAI,OAAO,YAAY,MAAM;AAC3B,iBAAS,OAAO,MAAM,OAAO,OAAiB;AAAA,MAChD;AAEA,UAAI,OAAO,WAAW,MAAM;AAC1B,iBAAS,OAAO,MAAM,GAAG,OAAO,MAAgB;AAAA,MAClD;AAEA,cAAQ,MAAM;AAAA,IAChB;AAAA,EACF;AAEA,SAAO;AACT;AAEA,SAAS,aAAa,MAAiC,IAAsD;AAC3G,MAAI,SAAS,CAAC,GAAG,IAAI;AAGrB,aAAW,UAAU,GAAG,eAA+E;AACrG,QAAI,OAAO,UAAU;AAEnB,eAAS,OAAO,OAAO,UAAQ;AAC7B,cAAM,UAAU,KAAK,OAAO,MAAM;AAClC,gBAAQ,OAAO,UAAU;AAAA,UACvB,KAAK;AAAK,mBAAQ,UAAsB,OAAO;AAAA,UAC/C,KAAK;AAAM,mBAAQ,WAAuB,OAAO;AAAA,UACjD,KAAK;AAAK,mBAAQ,UAAsB,OAAO;AAAA,UAC/C,KAAK;AAAM,mBAAQ,WAAuB,OAAO;AAAA,UACjD,KAAK,QAAQ;AACX,kBAAM,UAAU,OAAO,OAAO,KAAK;AACnC,kBAAM,MAAM,OAAO,WAAW,EAAE;AAChC,gBAAI,QAAQ,WAAW,GAAG,KAAK,QAAQ,SAAS,GAAG;AACjD,qBAAO,IAAI,YAAY,EAAE,SAAS,QAAQ,MAAM,GAAG,EAAE,EAAE,YAAY,CAAC;AACtE,gBAAI,QAAQ,WAAW,GAAG;AACxB,qBAAO,IAAI,YAAY,EAAE,SAAS,QAAQ,MAAM,CAAC,EAAE,YAAY,CAAC;AAClE,gBAAI,QAAQ,SAAS,GAAG;AACtB,qBAAO,IAAI,YAAY,EAAE,WAAW,QAAQ,MAAM,GAAG,EAAE,EAAE,YAAY,CAAC;AACxE,mBAAO,QAAQ;AAAA,UACjB;AAAA,UACA;AAAS,mBAAO,YAAY,OAAO;AAAA,QACrC;AAAA,MACF,CAAC;AAAA,IACH,OAAO;AAEL,eAAS,OAAO,OAAO,UAAQ,KAAK,OAAO,MAAM,MAAM,OAAO,KAAK;AAAA,IACrE;AAAA,EACF;AAGA,aAAW,UAAU,GAAG,kBAA+D;AACrF,aAAS,OAAO,OAAO,UAAQ,KAAK,OAAO,MAAM,MAAM,OAAO,KAAK;AAAA,EACrE;AAGA,aAAW,UAAU,GAAG,iBAAiE;AACvF,aAAS,OAAO,OAAO,UAAQ,OAAO,OAAO,SAAS,KAAK,OAAO,MAAM,CAAC,CAAC;AAAA,EAC5E;AAGA,aAAW,UAAU,GAAG,oBAAoE;AAC1F,aAAS,OAAO,OAAO,UAAQ,CAAC,OAAO,OAAO,SAAS,KAAK,OAAO,MAAM,CAAC,CAAC;AAAA,EAC7E;AAGA,aAAW,UAAU,GAAG,mBAA+B;AACrD,aAAS,OAAO,OAAO,UAAQ,KAAK,MAAM,MAAM,QAAQ,KAAK,MAAM,MAAM,MAAS;AAAA,EACpF;AAGA,aAAW,UAAU,GAAG,sBAAkC;AACxD,aAAS,OAAO,OAAO,UAAQ,KAAK,MAAM,MAAM,QAAQ,KAAK,MAAM,MAAM,MAAS;AAAA,EACpF;AAEA,SAAO;AACT;AAKO,SAAS,aAAa,YAAuC,CAAC,GAAG;AACtE,QAAM,SAAS,GAAG,GAAG,CAAC,UAAkB;AACtC,WAAO,uBAAuB,UAAU,KAAK,KAAK,CAAC,CAAC;AAAA,EACtD,CAAC;AAGA,EAAC,OAA8C,QAAQ,IAAI;AAAA,IAC1D,UAAU,GAAG,GAAG,EAAE,kBAAkB,KAAK;AAAA,IACzC,aAAa,GAAG,GAAG,EAAE,kBAAkB,MAAS;AAAA,EAClD;AAGC,EAAC,OAA8C,KAAK,IAAI,GAAG,GAAG,EAAE,gBAAgB;AAAA,IAC/E,MAAM,CAAC,YAAkC,QAAQ,CAAC,CAAC;AAAA,EACrD,CAAC;AAGA,EAAC,OAA8C,aAAa,IAAI,GAAG,GAAG,EAAE,mBAAmB,OAAO,aAA8C;AAE/I,UAAM,UAAU,GAAG,GAAG,CAAC,UAAkB;AACvC,aAAO,uBAAuB,UAAU,KAAK,KAAK,CAAC,CAAC;AAAA,IACtD,CAAC;AACD,UAAM,SAAS,OAAO;AAAA,EACxB,CAAC;AAED,SAAO;AACT;AAMO,SAAS,oBAAoB,YAAuC,CAAC,GAAwB;AAClG,QAAM,WAAW,aAAa,SAAS;AAEvC,SAAO;AAAA,IACL,MAAM;AAAA,IACN,SAAS;AAAA,MACP,UAAU,GAAG,GAAG,EAAE,kBAAkB,EAAE,OAAO,CAAC,GAAG,OAAO,GAAG,MAAM,GAAG,OAAO,IAAI,YAAY,GAAG,SAAS,MAAM,CAAC;AAAA,MAC9G,SAAS,GAAG,GAAG,EAAE,kBAAkB,IAAI;AAAA,MACvC,UAAU,GAAG,GAAG,EAAE,kBAAkB,IAAI;AAAA,MACxC,OAAO,GAAG,GAAG,EAAE,kBAAkB,CAAC;AAAA,MAClC,QAAQ,GAAG,GAAG,EAAE,kBAAkB,CAAC,CAAC;AAAA,MACpC,QAAQ,GAAG,GAAG,EAAE,kBAAkB,CAAC,CAAC;AAAA,MACpC,QAAQ,GAAG,GAAG,EAAE,kBAAkB,IAAI;AAAA,MACtC,aAAa,GAAG,GAAG,EAAE,mBAAmB,OAAO,OAA4C,GAAG,CAAC,CAAC,CAAC;AAAA,IACnG;AAAA,IACA,QAAQ;AAAA,MACN,UAAU,GAAG,GAAG,EAAE,kBAAkB,KAAK;AAAA,MACzC,WAAW,GAAG,GAAG,EAAE,kBAAkB,KAAK;AAAA,MAC1C,YAAY,GAAG,GAAG,EAAE,kBAAkB,CAAC,CAAC;AAAA,MACxC,aAAa,GAAG,GAAG,EAAE,kBAAkB,MAAS;AAAA,MAChD,YAAY,GAAG,GAAG,EAAE,kBAAkB,MAAS;AAAA,MAC/C,WAAW,GAAG,GAAG,EAAE,kBAAkB,MAAS;AAAA,MAC9C,eAAe,GAAG,GAAG,EAAE,kBAAkB,MAAS;AAAA,MAClD,gBAAgB,GAAG,GAAG,EAAE,kBAAkB,MAAS;AAAA,MACnD,oBAAoB,GAAG,GAAG,EAAE,kBAAkB,KAAK;AAAA,MACnD,KAAK,CAAC;AAAA,IACR;AAAA,IACA,GAAG,CAAC,SAAiB;AAAA,IACrB,eAAe,GAAG,GAAG;AAAA,IACrB,yBAAyB,GAAG,GAAG;AAAA,IAC/B,6BAA6B,GAAG,GAAG;AAAA,IACnC,uBAAuB,GAAG,GAAG;AAAA,IAC7B,oBAAoB,GAAG,GAAG;AAAA,IAC1B,cAAc,OAAM,oBAAI,KAAK,GAAE,YAAY;AAAA,IAC3C,iBAAiB,CAAC,KAAc,UAAiB,QAAQ,oBAAI,KAAK,GAAG,YAAY;AAAA,IACjF;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAyBO,SAAS,kBAAkB,YAAgC,CAAC,GAAkB;AACnF,MAAI,YAAY;AAGhB,QAAM,EAAE,YAAY,GAAG,KAAK,IAAI;AAChC,QAAM,IAAI,aACN,CAAC,SAAiB,GAAG,UAAU,IAAI,IAAI,KACvC,CAAC,SAAiB;AAGtB,QAAM,WAAoC,CAAC;AAI3C,QAAM,cAAc,sBAAsB;AAC1C,QAAM,WAAgE;AAAA,IACpE,MAAM,EAAE,MAAM,YAAY;AAAA,EAC5B;AAIA,MAAI,qBAAqB,EAAE,GAAG,KAAK;AACnC,MAAI,KAAK,MAAM,OAAO,KAAK,OAAO,YAAY;AAE5C,UAAM,WAAW,KAAK;AACtB,yBAAqB;AAAA,MACnB,GAAG;AAAA,MACH,IAAI;AAAA,QACF,MAAM;AAAA,QACN,SAAS;AAAA,UACP,UAAU,GAAG,GAAG,EAAE,kBAAkB,EAAE,OAAO,CAAC,GAAG,OAAO,GAAG,MAAM,GAAG,OAAO,IAAI,YAAY,GAAG,SAAS,MAAM,CAAC;AAAA,UAC9G,SAAS,GAAG,GAAG,EAAE,kBAAkB,IAAI;AAAA,UACvC,UAAU,GAAG,GAAG,EAAE,kBAAkB,IAAI;AAAA,UACxC,OAAO,GAAG,GAAG,EAAE,kBAAkB,CAAC;AAAA,UAClC,QAAQ,GAAG,GAAG,EAAE,kBAAkB,CAAC,CAAC;AAAA,UACpC,QAAQ,GAAG,GAAG,EAAE,kBAAkB,CAAC,CAAC;AAAA,UACpC,QAAQ,GAAG,GAAG,EAAE,kBAAkB,IAAI;AAAA,UACtC,aAAa,GAAG,GAAG,EAAE,mBAAmB,OAAO,OAA4C,GAAG,CAAC,CAAC,CAAC;AAAA,QACnG;AAAA,QACA,QAAQ;AAAA,UACN,UAAU,GAAG,GAAG,EAAE,kBAAkB,KAAK;AAAA,UACzC,WAAW,GAAG,GAAG,EAAE,kBAAkB,KAAK;AAAA,UAC1C,YAAY,GAAG,GAAG,EAAE,kBAAkB,CAAC,CAAC;AAAA,UACxC,aAAa,GAAG,GAAG,EAAE,kBAAkB,MAAS;AAAA,UAChD,YAAY,GAAG,GAAG,EAAE,kBAAkB,MAAS;AAAA,UAC/C,WAAW,GAAG,GAAG,EAAE,kBAAkB,MAAS;AAAA,UAC9C,eAAe,GAAG,GAAG,EAAE,kBAAkB,MAAS;AAAA,UAClD,gBAAgB,GAAG,GAAG,EAAE,kBAAkB,MAAS;AAAA,UACnD,oBAAoB,GAAG,GAAG,EAAE,kBAAkB,KAAK;AAAA,UACnD,KAAK,CAAC;AAAA,QACR;AAAA,QACA;AAAA,QACA,eAAe,GAAG,GAAG;AAAA,QACrB,yBAAyB,GAAG,GAAG;AAAA,QAC/B,6BAA6B,GAAG,GAAG;AAAA,QACnC,uBAAuB,GAAG,GAAG;AAAA,QAC7B,oBAAoB,GAAG,GAAG;AAAA,QAC1B,cAAc,OAAM,oBAAI,KAAK,GAAE,YAAY;AAAA,QAC3C,iBAAiB,CAAC,KAAc,UAAiB,QAAQ,oBAAI,KAAK,GAAG,YAAY;AAAA,QACjF;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA,SAAS,MAAM;AAAA;AAAA,QAEf,KAAM,SAAyC;AAAA,MACjD;AAAA,IACF;AAAA,EACF;AAGA,QAAM,WAAW,aAAa;AAG9B,QAAM,aAAa;AAAA,IACjB,MAAM,GAAG,GAAG;AAAA,IACZ,MAAM,GAAG,GAAG;AAAA,IACZ,OAAO,GAAG,GAAG;AAAA,IACb,OAAO,GAAG,GAAG;AAAA,IACb,OAAO,GAAG,GAAG;AAAA,IACb,OAAO,GAAG,GAAG;AAAA,IACb,OAAO,GAAG,GAAG,EAAE,eAAe;AAAA,EAChC;AAGA,QAAM,oBAAoB;AAAA,IACxB,UAAU,GAAG,GAAG,EAAE,kBAAkB,KAAK;AAAA,IACzC,WAAW,GAAG,GAAG,EAAE,kBAAkB,KAAK;AAAA,IAC1C,YAAY,GAAG,GAAG,EAAE,kBAAkB,CAAC,CAAC;AAAA,IACxC,aAAa,GAAG,GAAG,EAAE,kBAAkB,MAAS;AAAA,IAChD,YAAY,GAAG,GAAG,EAAE,kBAAkB,MAAS;AAAA,IAC/C,WAAW,GAAG,GAAG,EAAE,kBAAkB,MAAS;AAAA,IAC9C,eAAe,GAAG,GAAG,EAAE,kBAAkB,MAAS;AAAA,IAClD,gBAAgB,GAAG,GAAG,EAAE,kBAAkB,MAAS;AAAA,IACnD,oBAAoB,GAAG,GAAG,EAAE,kBAAkB,KAAK;AAAA,IACnD,KAAK,CAAC;AAAA,EACR;AAGA,QAAM,gBAAgB;AAAA,IACpB,UAAU,GAAG,GAAG,EAAE,kBAAkB,EAAE,OAAO,CAAC,GAAG,OAAO,GAAG,MAAM,GAAG,OAAO,IAAI,YAAY,GAAG,SAAS,MAAM,CAAC;AAAA,IAC9G,SAAS,GAAG,GAAG,EAAE,kBAAkB,IAAI;AAAA,IACvC,UAAU,GAAG,GAAG,EAAE,kBAAkB,IAAI;AAAA,IACxC,OAAO,GAAG,GAAG,EAAE,kBAAkB,CAAC;AAAA,IAClC,QAAQ,GAAG,GAAG,EAAE,kBAAkB,CAAC,CAAC;AAAA,IACpC,QAAQ,GAAG,GAAG,EAAE,kBAAkB,CAAC,CAAC;AAAA,IACpC,QAAQ,GAAG,GAAG,EAAE,kBAAkB,IAAI;AAAA,IACtC,aAAa,GAAG,GAAG,EAAE,mBAAmB,OAAO,OAA4C,GAAG,CAAC,CAAC,CAAC;AAAA,EACnG;AAEA,SAAO;AAAA;AAAA;AAAA;AAAA,IAIL,MAAM;AAAA,MACJ,QAAQ;AAAA,MACR,QAAQ;AAAA,QACN;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA,OAAO;AAAA,MACT;AAAA,MACA,QAAQ;AAAA,QACN,cAAc,GAAG,GAAG,EAAE,kBAAkB,iBAAiB;AAAA,QACzD,gBAAgB,GAAG,GAAG,EAAE,kBAAkB,IAAI;AAAA,QAC9C,YAAY;AAAA,MACd;AAAA,MACA,QAAQ;AAAA,QACN,OAAO,GAAG,GAAG,EAAE,gBAAgB,CAAC,CAAC;AAAA,QACjC,eAAe,GAAG,GAAG,EAAE,gBAAgB,KAAK;AAAA,QAC5C,iBAAiB,GAAG,GAAG,EAAE,gBAAgB,KAAK;AAAA,QAC9C,oBAAoB,GAAG,GAAG,EAAE,gBAAgB,CAAC;AAAA,QAC7C,mBAAmB,GAAG,GAAG,EAAE,gBAAgB,CAAC,CAAC;AAAA,MAC/C;AAAA,MACA,KAAK;AAAA,QACH,WAAW,GAAG,GAAG;AAAA,QACjB,OAAO,GAAG,GAAG;AAAA,MACf;AAAA,MACA,WAAW,CAAC;AAAA,MACZ,QAAQ;AAAA,QACN,MAAM,GAAG,GAAG;AAAA,QACZ,WAAW,GAAG,GAAG;AAAA,QACjB,WAAW,GAAG,GAAG,EAAE,kBAAkB,MAAS;AAAA,QAC9C,IAAI,GAAG,GAAG;AAAA,QACV,KAAK,GAAG,GAAG;AAAA,MACb;AAAA,MACA,YAAY,CAAC;AAAA,MACb,cAAc,GAAG,GAAG;AAAA,MACpB,YAAY,MAAM,WAAW,EAAE,SAAS;AAAA,MACxC,kBAAkB,CAAC,SAAkB;AACnC,YAAI,SAAS,UAAU,SAAS,YAAY,SAAS,UAAW,QAAO;AACvE,eAAO,WAAW,EAAE,SAAS;AAAA,MAC/B;AAAA,MACA,YAAY,MAAM;AAAA,MAClB,gBAAgB,MAAM;AAAA,MACtB,QAAQ,MAAM;AACZ,cAAM,SAAS,oBAAI,IAAmC;AACtD,eAAO;AAAA,UACL,QAAQ,GAAG,GAAG,EAAE,mBAAmB,CAAC,MAAc,SAAe;AAC/D,kBAAM,QAAQ,IAAI,iBAAiB,MAAM,IAAI;AAC7C,mBAAO,IAAI,MAAM,KAAK;AACtB,mBAAO;AAAA,UACT,CAAC;AAAA,UACD,aAAa,GAAG,GAAG,EAAE,mBAAmB,CAAC,MAAc,SAAe;AACpE,gBAAI,OAAO,IAAI,IAAI,EAAG,QAAO,OAAO,IAAI,IAAI;AAC5C,kBAAM,QAAQ,IAAI,iBAAiB,MAAM,IAAI;AAC7C,mBAAO,IAAI,MAAM,KAAK;AACtB,mBAAO;AAAA,UACT,CAAC;AAAA,UACD,KAAK,GAAG,GAAG,EAAE,mBAAmB,CAAC,SAAiB,OAAO,IAAI,IAAI,CAAC;AAAA,UAClE,UAAU,GAAG,GAAG;AAAA,UAChB,OAAO,GAAG,GAAG,EAAE,gBAAgB,CAAC,CAAC;AAAA,UACjC,SAAS,GAAG,GAAG;AAAA,QACjB;AAAA,MACF,GAAG;AAAA,MACH,eAAe,CAAI,YAAoB,aAAmB;AACxD,YAAI;AACF,iBAAO,KAAK,MAAM,UAAU;AAAA,QAC9B,QAAQ;AACN,iBAAO;AAAA,QACT;AAAA,MACF;AAAA,IACF;AAAA;AAAA;AAAA;AAAA,IAKA,IAAI;AAAA,MACF,MAAM;AAAA,MACN,SAAS;AAAA,MACT,QAAQ;AAAA,MACR;AAAA,MACA,eAAe,GAAG,GAAG;AAAA,MACrB,yBAAyB,GAAG,GAAG;AAAA,MAC/B,6BAA6B,GAAG,GAAG;AAAA,MACnC,uBAAuB,GAAG,GAAG;AAAA,MAC7B,oBAAoB,GAAG,GAAG;AAAA,MAC1B,cAAc,OAAM,oBAAI,KAAK,GAAE,YAAY;AAAA,MAC3C,iBAAiB,CAAC,KAAc,UAAiB,QAAQ,oBAAI,KAAK,GAAG,YAAY;AAAA,MACjF;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,SAAS,MAAM;AAAA;AAAA,MAEf,KAAM,SAAyC;AAAA,IACjD;AAAA;AAAA;AAAA;AAAA,IAKA,SAAS;AAAA,MACP,qBAAqB,GAAG,GAAG;AAAA,MAC3B,wBAAwB,GAAG,GAAG;AAAA,MAC9B,oBAAoB,GAAG,GAAG;AAAA,IAC5B;AAAA;AAAA;AAAA;AAAA,IAKA,QAAQ,CAAC;AAAA;AAAA;AAAA;AAAA,IAKT,QAAQ;AAAA,MACN,YAAY,GAAG,GAAG,EAAE,gBAAgB,CAAC,CAAC;AAAA,MACtC,YAAY,GAAG,GAAG,EAAE,gBAAgB,CAAC,CAAC;AAAA,MACtC,mBAAmB,GAAG,GAAG,EAAE,gBAAgB,CAAC,CAAC;AAAA,MAC7C,uBAAuB,GAAG,GAAG,EAAE,gBAAgB,CAAC,CAAC;AAAA,IACnD;AAAA;AAAA;AAAA;AAAA,IAKA,UAAU;AAAA,MACR,SAAS,MAAc,SAAwB;AAC7C,iBAAS,IAAI,IAAI;AAAA,MACnB;AAAA,MACA,IAAO,aAAwB;AAC7B,cAAM,UAAU,SAAS,WAAW;AACpC,YAAI,CAAC,SAAS;AACZ,gBAAM,IAAI,MAAM,YAAY,WAAW,oBAAoB;AAAA,QAC7D;AACA,eAAO;AAAA,MACT;AAAA,MACA,YAAe,aAAoC;AACjD,eAAO,SAAS,WAAW;AAAA,MAC7B;AAAA,MACA,IAAI,aAA8B;AAChC,eAAO,CAAC,CAAC,SAAS,WAAW;AAAA,MAC/B;AAAA,IACF;AAAA;AAAA;AAAA;AAAA,IAKA,UAAU;AAAA,MACR,SAAS,MAAc,aAAsB,eAA+B;AAC1E,iBAAS,IAAI,IAAI,EAAE,MAAM,aAAa,QAAQ,cAAc;AAAA,MAC9D;AAAA,MACA,IAAI,MAAc;AAChB,cAAM,OAAO,SAAS,IAAI;AAC1B,YAAI,CAAC,MAAM;AACT,gBAAM,IAAI,MAAM,YAAY,IAAI,aAAa;AAAA,QAC/C;AACA,eAAO,KAAK;AAAA,MACd;AAAA,MACA,UAAU,MAAc;AACtB,cAAM,OAAO,SAAS,IAAI;AAC1B,eAAO,MAAM;AAAA,MACf;AAAA,MACA,IAAI,MAAuB;AACzB,eAAO,QAAQ;AAAA,MACjB;AAAA,IACF;AAAA;AAAA;AAAA;AAAA,IAKA,cAAc,GAAG,GAAG;AAAA;AAAA,IAGpB,QAAQ;AAAA,MACN,QAAQ,GAAG,GAAG;AAAA,MACd,OAAO,GAAG,GAAG,EAAE,kBAAkB,CAAC,CAAC;AAAA,MACnC,SAAS,GAAG,GAAG,EAAE,kBAAkB,MAAS;AAAA,MAC5C,IAAI,GAAG,GAAG;AAAA,MACV,KAAK,GAAG,GAAG;AAAA,MACX,MAAM,GAAG,GAAG;AAAA,MACZ,OAAO,GAAG,GAAG;AAAA,IACf;AAAA;AAAA;AAAA;AAAA;AAAA,IAOA,QAAQ;AAAA;AAAA,IAGR,QAAQ;AAAA,MACN;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,OAAO;AAAA,IACT;AAAA;AAAA,IAGA,gBAAgB,MAAc,SAAwB;AACpD,eAAS,IAAI,IAAI;AAAA,IACnB;AAAA,IACA,WAAc,aAAwB;AACpC,YAAM,UAAU,SAAS,WAAW;AACpC,UAAI,CAAC,SAAS;AACZ,cAAM,IAAI,MAAM,YAAY,WAAW,oBAAoB;AAAA,MAC7D;AACA,aAAO;AAAA,IACT;AAAA,IACA,mBAAsB,aAAoC;AACxD,aAAO,SAAS,WAAW;AAAA,IAC7B;AAAA,IACA,WAAW,aAA8B;AACvC,aAAO,CAAC,CAAC,SAAS,WAAW;AAAA,IAC/B;AAAA,IACA,gBAAgB,MAAc,aAAsB,eAA+B;AACjF,eAAS,IAAI,IAAI,EAAE,MAAM,aAAa,QAAQ,cAAc;AAAA,IAC9D;AAAA,IACA,WAAW,MAAc;AACvB,YAAM,OAAO,SAAS,IAAI;AAC1B,UAAI,CAAC,MAAM;AACT,cAAM,IAAI,MAAM,YAAY,IAAI,aAAa;AAAA,MAC/C;AACA,aAAO,KAAK;AAAA,IACd;AAAA,IACA,WAAW,MAAuB;AAChC,aAAO,QAAQ;AAAA,IACjB;AAAA,IAEA,GAAG;AAAA,EACL;AACF;AAIO,SAAS,2BACd,YAAiD,CAAC,GACtB;AAC5B,SAAO;AAAA,IACL,MAAM;AAAA,IACN,OAAO;AAAA,IACP,OAAO;AAAA,IACP,YAAY;AAAA,IACZ,YAAY;AAAA,IACZ,QAAQ;AAAA,MACN,IAAI;AAAA,QACF,OAAO;AAAA,QACP,OAAO;AAAA,QACP,QAAQ;AAAA,QACR,IAAI,EAAE,MAAM,UAAU,MAAM,IAAI,UAAU,MAAM;AAAA,MAClD;AAAA,MACA,MAAM;AAAA,QACJ,OAAO;AAAA,QACP,OAAO;AAAA,QACP,IAAI,EAAE,MAAM,UAAU,MAAM,KAAK,UAAU,MAAM;AAAA,MACnD;AAAA,IACF;AAAA,IACA,GAAG;AAAA,EACL;AACF;AAEO,SAAS,uBACd,YAA6C,CAAC,GACtB;AACxB,SAAO;AAAA,IACL,MAAM;AAAA,IACN,KAAK;AAAA,IACL,OAAO;AAAA,IACP,UAAU,EAAE,OAAO,SAAS,UAAU,KAAK;AAAA,IAC3C,QAAQ;AAAA,MACN,OAAO;AAAA,QACL,OAAO;AAAA,QACP,OAAO;AAAA,QACP,IAAI,EAAE,MAAM,UAAU,MAAM,IAAI,UAAU,MAAM;AAAA,MAClD;AAAA,MACA,UAAU;AAAA,QACR,OAAO;AAAA,QACP,OAAO;AAAA,QACP,IAAI,EAAE,MAAM,UAAU,MAAM,IAAI,UAAU,MAAM;AAAA,MAClD;AAAA,IACF;AAAA,IACA,GAAG;AAAA,EACL;AACF;AAEO,SAAS,0BACd,YAAiD,CAAC,GACtB;AAC5B,SAAO;AAAA,IACL,MAAM;AAAA,IACN,OAAO;AAAA,IACP,OAAO;AAAA,IACP,YAAY;AAAA,IACZ,MAAM;AAAA,MACJ,EAAE,IAAI,MAAM,MAAM,MAAM,MAAM,QAAQ;AAAA,MACtC,EAAE,IAAI,MAAM,MAAM,MAAM,MAAM,gBAAgB;AAAA,MAC9C,EAAE,IAAI,MAAM,MAAM,MAAM,MAAM,SAAS;AAAA,IACzC;AAAA,IACA,QAAQ;AAAA,MACN,IAAI;AAAA,QACF,OAAO;AAAA,QACP,OAAO;AAAA,QACP,QAAQ;AAAA,QACR,IAAI,EAAE,MAAM,UAAU,MAAM,IAAI,UAAU,MAAM;AAAA,MAClD;AAAA,MACA,MAAM;AAAA,QACJ,OAAO;AAAA,QACP,OAAO;AAAA,QACP,IAAI,EAAE,MAAM,UAAU,MAAM,IAAI,UAAU,MAAM;AAAA,MAClD;AAAA,MACA,MAAM;AAAA,QACJ,OAAO;AAAA,QACP,OAAO;AAAA,QACP,IAAI,EAAE,MAAM,UAAU,MAAM,KAAK,UAAU,MAAM;AAAA,MACnD;AAAA,IACF;AAAA,IACA,GAAG;AAAA,EACL;AACF;AAEO,SAAS,sBACd,YAA4C,CAAC,GACtB;AACvB,SAAO;AAAA,IACL,MAAM;AAAA,IACN,OAAO;AAAA,IACP,OAAO;AAAA,IACP,YAAY;AAAA,IACZ,WAAW;AAAA,IACX,aAAa,EAAE,OAAO,cAAc,OAAO,OAAgB;AAAA,IAC3D,WAAW,EAAE,MAAM,IAAI,SAAS,IAAM;AAAA,IACtC,QAAQ;AAAA,MACN,IAAI;AAAA,QACF,OAAO;AAAA,QACP,OAAO;AAAA,QACP,QAAQ;AAAA,QACR,IAAI,EAAE,MAAM,UAAU,MAAM,IAAI,UAAU,MAAM;AAAA,MAClD;AAAA,MACA,QAAQ;AAAA,QACN,OAAO;AAAA,QACP,OAAO;AAAA,QACP,IAAI,EAAE,MAAM,UAAU,MAAM,IAAI,UAAU,MAAM;AAAA,MAClD;AAAA,MACA,SAAS;AAAA,QACP,OAAO;AAAA,QACP,OAAO;AAAA,QACP,IAAI,EAAE,MAAM,UAAU,MAAM,IAAI,UAAU,KAAK;AAAA,MACjD;AAAA,MACA,YAAY;AAAA,QACV,OAAO;AAAA,QACP,OAAO;AAAA,QACP,IAAI,EAAE,MAAM,YAAY,UAAU,MAAM;AAAA,MAC1C;AAAA,IACF;AAAA,IACA,GAAG;AAAA,EACL;AACF;AAGO,SAAS,uBACd,YAA6C,CAAC,GACtB;AACxB,SAAO;AAAA,IACL,MAAM;AAAA,IACN,KAAK;AAAA,IACL,OAAO;AAAA,IACP,YAAY;AAAA,IACZ,UAAU,EAAE,SAAS,MAAM,UAAU,IAAI;AAAA,IACzC,QAAQ;AAAA,MACN,aAAa;AAAA,QACX,OAAO;AAAA,QACP,OAAO;AAAA,QACP,IAAI,EAAE,MAAM,UAAU,MAAM,IAAI,UAAU,MAAM;AAAA,MAClD;AAAA,MACA,SAAS;AAAA,QACP,OAAO;AAAA,QACP,OAAO;AAAA,QACP,IAAI,EAAE,MAAM,WAAW,UAAU,MAAM;AAAA,MACzC;AAAA,MACA,UAAU;AAAA,QACR,OAAO;AAAA,QACP,OAAO;AAAA,QACP,IAAI,EAAE,MAAM,WAAW,UAAU,MAAM;AAAA,MACzC;AAAA,IACF;AAAA,IACA,GAAG;AAAA,EACL;AACF;AAGO,SAAS,qBACd,YAAiD,CAAC,GACtB;AAC5B,SAAO;AAAA,IACL,MAAM;AAAA,IACN,OAAO;AAAA,IACP,OAAO;AAAA,IACP,YAAY;AAAA,IACZ,WAAW,EAAE,SAAS,MAAM,cAAc,aAAa;AAAA;AAAA,IACvD,QAAQ;AAAA,MACN,IAAI;AAAA,QACF,OAAO;AAAA,QACP,OAAO;AAAA,QACP,QAAQ;AAAA,QACR,IAAI,EAAE,MAAM,UAAU,MAAM,IAAI,UAAU,MAAM;AAAA,MAClD;AAAA,MACA,OAAO;AAAA,QACL,OAAO;AAAA,QACP,OAAO;AAAA,QACP,IAAI,EAAE,MAAM,UAAU,MAAM,KAAK,UAAU,MAAM;AAAA,MACnD;AAAA,MACA,YAAY;AAAA,QACV,OAAO;AAAA,QACP,OAAO;AAAA,QACP,IAAI,EAAE,MAAM,YAAY,UAAU,MAAM;AAAA,MAC1C;AAAA,IACF;AAAA,IACA,GAAG;AAAA,EACL;AACF;AAEO,SAAS,qBACd,YAA2C,CAAC,GACtB;AACtB,SAAO;AAAA,IACL,MAAM;AAAA,IACN,OAAO;AAAA,IACP,OAAO;AAAA,IACP,YAAY;AAAA,IACZ,OAAO;AAAA,IACP,QAAQ;AAAA,MACN,SAAS;AAAA,QACP,OAAO;AAAA,QACP,OAAO;AAAA,QACP,IAAI,EAAE,MAAM,UAAU,MAAM,IAAI,UAAU,MAAM;AAAA,MAClD;AAAA,MACA,OAAO;AAAA,QACL,OAAO;AAAA,QACP,OAAO;AAAA,QACP,IAAI,EAAE,MAAM,WAAW,UAAU,MAAM;AAAA,MACzC;AAAA,IACF;AAAA,IACA,GAAG;AAAA,EACL;AACF;AAEO,SAAS,yBACd,YAA+C,CAAC,GACtB;AAC1B,SAAO;AAAA,IACL,MAAM;AAAA,IACN,SAAS;AAAA,IACT,OAAO;AAAA;AAAA,IACP,OAAO;AAAA,IACP,YAAY;AAAA,IACZ,OAAO,EAAE,KAAK,IAAI;AAAA,IAClB,QAAQ;AAAA,MACN,IAAI;AAAA,QACF,OAAO;AAAA,QACP,OAAO;AAAA,QACP,QAAQ;AAAA,QACR,IAAI,EAAE,MAAM,UAAU,MAAM,IAAI,UAAU,MAAM;AAAA,MAClD;AAAA,MACA,OAAO;AAAA,QACL,OAAO;AAAA,QACP,OAAO;AAAA,QACP,IAAI,EAAE,MAAM,UAAU,MAAM,KAAK,UAAU,MAAM;AAAA,MACnD;AAAA,IACF;AAAA,IACA,GAAG;AAAA,EACL;AACF;AAGO,SAAS,wBACd,YAA+C,CAAC,GACtB;AAC1B,SAAO,yBAAyB;AAAA,IAC9B,SAAS,CAAC,YAAY,UAAU;AAAA,IAChC,UAAU,CAAC,YAAY;AACrB,YAAM,WAAW;AAAA,QACf,GAAI,QAAQ,UAAU,KAAK,CAAC;AAAA,QAC5B,GAAI,QAAQ,UAAU,KAAK,CAAC;AAAA,MAC9B;AACA,aAAO;AAAA,IACT;AAAA,IACA,SAAS;AAAA,IACT,GAAG;AAAA,EACL,CAAC;AACH;AAEO,SAAS,yBACd,YAA+C,CAAC,GACtB;AAC1B,SAAO;AAAA,IACL,MAAM;AAAA,IACN,OAAO;AAAA,IACP,SAAS,GAAG,GAAG,EAAE,kBAAkB;AAAA,MACjC,EAAE,IAAI,KAAK,QAAQ,SAAS,OAAO,IAAI;AAAA,MACvC,EAAE,IAAI,KAAK,QAAQ,SAAS,OAAO,IAAI;AAAA,IACzC,CAAC;AAAA,IACD,OAAO,EAAE,KAAK,GAAG;AAAA,IACjB,QAAQ;AAAA,MACN,IAAI;AAAA,QACF,OAAO;AAAA,QACP,OAAO;AAAA,QACP,QAAQ;AAAA,QACR,IAAI,EAAE,MAAM,UAAU,MAAM,IAAI,UAAU,MAAM;AAAA,MAClD;AAAA,MACA,QAAQ;AAAA,QACN,OAAO;AAAA,QACP,OAAO;AAAA,QACP,IAAI,EAAE,MAAM,UAAU,MAAM,IAAI,UAAU,MAAM;AAAA,MAClD;AAAA,MACA,OAAO;AAAA,QACL,OAAO;AAAA,QACP,OAAO;AAAA,QACP,IAAI,EAAE,MAAM,WAAW,UAAU,MAAM;AAAA,MACzC;AAAA,IACF;AAAA,IACA,GAAG;AAAA,EACL;AACF;AAQO,SAAS,0BAA0B,YAAsC,CAAC,GAAoB;AACnG,SAAO;AAAA,IACL,UAAU,GAAG,GAAG,EAAE,kBAAkB;AAAA,MAClC,OAAO;AAAA,QACL,EAAE,IAAI,SAAS,OAAO,kBAAkB;AAAA,QACxC,EAAE,IAAI,SAAS,OAAO,kBAAkB;AAAA,MAC1C;AAAA,MACA,OAAO;AAAA,MACP,MAAM;AAAA,MACN,OAAO;AAAA,MACP,YAAY;AAAA,MACZ,SAAS;AAAA,IACX,CAAC;AAAA,IACD,SAAS,GAAG,GAAG,EAAE,kBAAkB,IAAI;AAAA,IACvC,UAAU,GAAG,GAAG,EAAE,kBAAkB,EAAE,IAAI,SAAS,OAAO,kBAAkB,CAAC;AAAA,IAC7E,OAAO,GAAG,GAAG,EAAE,kBAAkB,CAAC;AAAA,IAClC,QAAQ,GAAG,GAAG,EAAE,kBAAkB,EAAE,IAAI,WAAW,OAAO,UAAU,CAAC;AAAA,IACrE,QAAQ,GAAG,GAAG,EAAE,kBAAkB,EAAE,IAAI,SAAS,OAAO,UAAU,CAAC;AAAA,IACnE,QAAQ,GAAG,GAAG,EAAE,kBAAkB,IAAI;AAAA,IACtC,aAAa,GAAG,GAAG,EAAE,mBAAmB,OAAO,OAAO,GAAG,CAAC,CAAoB,CAAC;AAAA,IAC/E,KAAK,GAAG,GAAG,EAAE,kBAAkB,CAAC,CAAC;AAAA,IACjC,GAAG;AAAA,EACL;AACF;AAIO,SAAS,qBACd,YAA2C,CAAC,GACtB;AACtB,SAAO;AAAA,IACL,MAAM;AAAA,IACN,OAAO;AAAA,IACP,OAAO;AAAA,IACP,YAAY;AAAA,IACZ,YAAY;AAAA,IACZ,MAAM;AAAA,MACJ,EAAE,IAAI,QAAQ,MAAM,iBAAiB,WAAW,KAAK;AAAA,IACvD;AAAA,IACA,QAAQ;AAAA,MACN,IAAI;AAAA,QACF,OAAO;AAAA,QACP,OAAO;AAAA,QACP,QAAQ;AAAA,QACR,IAAI,EAAE,MAAM,UAAU,MAAM,IAAI,UAAU,MAAM;AAAA,MAClD;AAAA,MACA,MAAM;AAAA,QACJ,OAAO;AAAA,QACP,OAAO;AAAA,QACP,IAAI,EAAE,MAAM,UAAU,MAAM,KAAK,UAAU,MAAM;AAAA,MACnD;AAAA;AAAA,IAEF;AAAA,IACA,GAAG;AAAA,EACL;AACF;AAEO,SAAS,oBACd,YAA0C,CAAC,GACtB;AACrB,SAAO;AAAA,IACL,MAAM;AAAA,IACN,OAAO;AAAA,IACP,OAAO;AAAA,IACP,YAAY;AAAA,IACZ,YAAY;AAAA,IACZ,MAAM;AAAA,MACJ,EAAE,IAAI,QAAQ,MAAM,WAAW;AAAA,IACjC;AAAA,IACA,QAAQ;AAAA,MACN,IAAI;AAAA,QACF,OAAO;AAAA,QACP,OAAO;AAAA,QACP,QAAQ;AAAA,QACR,IAAI,EAAE,MAAM,UAAU,MAAM,IAAI,UAAU,MAAM;AAAA,MAClD;AAAA,MACA,MAAM;AAAA,QACJ,OAAO;AAAA,QACP,OAAO;AAAA,QACP,IAAI,EAAE,MAAM,UAAU,MAAM,KAAK,UAAU,MAAM;AAAA,MACnD;AAAA,IACF;AAAA,IACA,GAAG;AAAA,EACL;AACF;AAIO,SAAS,uBACd,YAAuC,CAAC,GACtB;AAClB,SAAO;AAAA,IACL,KAAK;AAAA,IACL,OAAO;AAAA,IACP,OAAO;AAAA,IACP,QAAQ;AAAA,IACR,SAAS,aAAa,EAAE,SAAS,KAAK;AAAA,IACtC,GAAG;AAAA,EACL;AACF;;;AOpqCA,eAAsB,iBAAiB,IAAyB;AAC9D,MAAI,CAAC,MAAM,GAAG,OAAO,SAAS,OAAO,GAAG;AACtC,UAAM,GAAG,OAAO,YAAY,SAAS,CAAC,MAAM;AAC1C,QAAE,OAAO,MAAM,EAAE,EAAE,QAAQ;AAC3B,QAAE,OAAO,QAAQ,GAAG,EAAE,YAAY;AAClC,QAAE,OAAO,SAAS,GAAG,EAAE,YAAY;AACnC,QAAE,OAAO,QAAQ,EAAE,EAAE,YAAY,EAAE,UAAU,MAAM;AACnD,QAAE,WAAW,MAAM,IAAI;AAAA,IACzB,CAAC;AAAA,EACH;AAEA,MAAI,CAAC,MAAM,GAAG,OAAO,SAAS,OAAO,GAAG;AACtC,UAAM,GAAG,OAAO,YAAY,SAAS,CAAC,MAAM;AAC1C,QAAE,OAAO,MAAM,EAAE,EAAE,QAAQ;AAC3B,QAAE,OAAO,QAAQ,EAAE,EAAE,YAAY;AAAA,IACnC,CAAC;AAAA,EACH;AACF;;;ACSO,IAAMC,YAAN,cAAuB,MAAM;AAAA,EAClB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAEhB,YACE,QACA,aAAqB,KACrB,SACA;AACA,QAAI,OAAO,WAAW,UAAU;AAE9B,YAAM,MAAM;AACZ,WAAK,OAAO,WAAW;AAAA,IACzB,OAAO;AAEL,YAAM,OAAO,WAAW,OAAO,IAAI;AACnC,WAAK,OAAO,OAAO;AACnB,WAAK,gBAAgB,OAAO;AAAA,IAC9B;AAEA,SAAK,aAAa;AAClB,SAAK,UAAU;AACf,SAAK,OAAO;AACZ,UAAM,kBAAkB,MAAM,KAAK,WAAW;AAAA,EAChD;AACF;AAKO,IAAMC,iBAAN,cAA4BD,UAAS;AAAA,EAC1C,YAAY,WAAmB,YAAY;AACzC,UAAM;AAAA,MACJ,MAAM,WAAW;AAAA,MACjB,SAAS,GAAG,QAAQ;AAAA,MACpB,eAAe,EAAE,SAAS;AAAA,IAC5B,GAAG,GAAG;AACN,SAAK,OAAO;AAAA,EACd;AACF;AAKO,IAAME,qBAAN,cAAgCF,UAAS;AAAA,EAC9C,YAAY,gBAAoC,WAAW,qBAAqB,SAAkB;AAEhG,UAAM,SAAS,OAAO,OAAO,UAAU,EAAE,SAAS,aAA0B;AAE5E,QAAI,QAAQ;AACV,YAAM;AAAA,QACJ,MAAM;AAAA,QACN,SAAS,WAAW;AAAA,MACtB,GAAG,GAAG;AAAA,IACR,OAAO;AAEL,YAAM;AAAA,QACJ,MAAM,WAAW;AAAA,QACjB,SAAS;AAAA,MACX,GAAG,GAAG;AAAA,IACR;AACA,SAAK,OAAO;AAAA,EACd;AACF;AAKO,IAAMG,kBAAN,cAA6BH,UAAS;AAAA,EAC3C,YAAY,gBAAoC,WAAW,mBAAmB,SAAkB;AAC9F,UAAM,SAAS,OAAO,OAAO,UAAU,EAAE,SAAS,aAA0B;AAE5E,QAAI,QAAQ;AACV,YAAM;AAAA,QACJ,MAAM;AAAA,QACN,SAAS,WAAW;AAAA,MACtB,GAAG,GAAG;AAAA,IACR,OAAO;AACL,YAAM;AAAA,QACJ,MAAM,WAAW;AAAA,QACjB,SAAS;AAAA,MACX,GAAG,GAAG;AAAA,IACR;AACA,SAAK,OAAO;AAAA,EACd;AACF;AAKO,IAAMI,iBAAN,cAA4BJ,UAAS;AAAA,EAC1C,YAAY,gBAAoC,WAAW,mBAAmB,SAAkB;AAC9F,UAAM,SAAS,OAAO,OAAO,UAAU,EAAE,SAAS,aAA0B;AAE5E,QAAI,QAAQ;AACV,YAAM;AAAA,QACJ,MAAM;AAAA,QACN,SAAS,WAAW;AAAA,MACtB,GAAG,GAAG;AAAA,IACR,OAAO;AACL,YAAM;AAAA,QACJ,MAAM,WAAW;AAAA,QACjB,SAAS;AAAA,MACX,GAAG,GAAG;AAAA,IACR;AACA,SAAK,OAAO;AAAA,EACd;AACF;AAiBO,IAAMK,mBAAN,cAA8BL,UAAS;AAAA,EACnB;AAAA,EAEzB,YAAY,gBAAoC,WAAW,kBAAkB,UAA8B,CAAC,GAAG;AAC7G,UAAM,SAAS,OAAO,OAAO,UAAU,EAAE,SAAS,aAA0B;AAE5E,QAAI,QAAQ;AACV,YAAM;AAAA,QACJ,MAAM;AAAA,QACN,SAAS;AAAA,MACX,GAAG,GAAG;AAAA,IACR,OAAO;AACL,YAAM;AAAA,QACJ,MAAM,WAAW;AAAA,QACjB,SAAS;AAAA,MACX,GAAG,GAAG;AAAA,IACR;AAEA,SAAK,OAAO;AACZ,SAAK,UAAU;AAAA,EACjB;AACF;;;ACpLA,OAAO,UAAyB;AAQzB,SAAS,eAAqB;AACnC,SAAO,KAAK;AAAA,IACV,QAAQ;AAAA,IACR,YAAY;AAAA,IACZ,kBAAkB;AAAA,EACpB,CAAC;AACH;","names":["DEFAULT_PAGE","DEFAULT_LIMIT","DEFAULT_MAX_LIMIT","data","AppError","NotFoundError","UnauthorizedError","ForbiddenError","ConflictError","ValidationError"]}
|
|
1
|
+
{"version":3,"sources":["../../src/testing/test-helpers.ts","../../src/db/filter-helpers.ts","../../src/db/memory-adapter.ts","../../src/core/cache/lru-cache.ts","../../src/core/cache/managed-cache.ts","../../src/db/query-helpers.ts","../../src/core/errors/error-codes.ts","../../src/testing/core-tables.ts","../../src/core/errors/app-error.ts","../../src/testing/test-db.ts"],"sourcesContent":["/**\n * Test helpers for runtime services\n */\n\nimport { vi } from 'vitest'\nimport type { Knex } from 'knex'\nimport type {\n ModuleContext,\n CollectionEntityDefinition,\n SingleEntityDefinition,\n EventEntityDefinition,\n ActionDefinition,\n // ConfigEntityDefinition absorbed into SingleEntityDefinition\n // TempEntityDefinition absorbed into CollectionEntityDefinition\n ViewEntityDefinition,\n ExternalEntityDefinition,\n ComputedEntityDefinition,\n TreeEntityDefinition,\n DagEntityDefinition,\n DatabaseAdapter\n} from '@gzl10/nexus-sdk'\nimport { createInMemoryAdapter } from '../db/memory-adapter.js'\nimport { ManagedCacheImpl } from '../core/cache/managed-cache.js'\nimport { applySearchFilter, getSearchableFields, getPagination, buildPaginatedResult } from '../db/query-helpers.js'\nimport { ErrorCodes } from '../core/errors/error-codes.js'\n\n// Mock error classes\nclass AppError extends Error {\n constructor(message: string, public statusCode: number = 500) {\n super(message)\n this.name = 'AppError'\n }\n}\n\nclass NotFoundError extends Error {\n constructor(resource = 'Resource') {\n super(`${resource} not found`)\n this.name = 'NotFoundError'\n }\n}\n\nclass UnauthorizedError extends Error {\n constructor(message = 'Unauthorized') {\n super(message)\n this.name = 'UnauthorizedError'\n }\n}\n\nclass ForbiddenError extends Error {\n constructor(message = 'Forbidden') {\n super(message)\n this.name = 'ForbiddenError'\n }\n}\n\nclass ConflictError extends Error {\n constructor(message = 'Conflict') {\n super(message)\n this.name = 'ConflictError'\n }\n}\n\nclass ValidationError extends Error {\n public details: Array<{ path: string; message: string; code?: string; interpolation?: Record<string, string | number> }>\n\n constructor(message = 'Validation failed', details: Array<{ path: string; message: string; code?: string; interpolation?: Record<string, string | number> }> = []) {\n super(message)\n this.name = 'ValidationError'\n this.details = details\n }\n}\n\ninterface MockQueryBuilderState {\n _data: unknown[]\n _whereClauses: Array<{ column: string; value: unknown; operator?: string }>\n _whereInClauses: Array<{ column: string; values: unknown[] }>\n _whereNotInClauses: Array<{ column: string; values: unknown[] }>\n _whereNotClauses: Array<{ column: string; value: unknown }>\n _whereNullClauses: string[]\n _whereNotNullClauses: string[]\n _orderBy: { column: string; direction: string } | null\n _limit: number | null\n _offset: number | null\n _insertData: unknown\n _updateData: unknown\n _deleted: boolean\n where: (column: string, operatorOrValue: unknown, value?: unknown) => MockQueryBuilderState\n whereNot: (column: string, value: unknown) => MockQueryBuilderState\n whereIn: (column: string, values: unknown[]) => MockQueryBuilderState\n whereNotIn: (column: string, values: unknown[]) => MockQueryBuilderState\n whereNull: (column: string) => MockQueryBuilderState\n whereNotNull: (column: string) => MockQueryBuilderState\n whereBetween: () => MockQueryBuilderState\n orderBy: (column: string, direction?: string) => MockQueryBuilderState\n limit: (n: number) => MockQueryBuilderState\n offset: (n: number) => MockQueryBuilderState\n select: () => MockQueryBuilderState\n join: () => MockQueryBuilderState\n leftJoin: () => MockQueryBuilderState\n groupBy: () => MockQueryBuilderState\n andWhere: () => MockQueryBuilderState\n orWhere: () => MockQueryBuilderState\n returning: () => MockQueryBuilderState\n clone: () => Knex.QueryBuilder\n count: () => { first: ReturnType<typeof vi.fn> }\n first: () => Promise<unknown>\n insert: (data: unknown) => Promise<number[]>\n update: (data: unknown) => Promise<number>\n delete: () => Promise<number>\n then: (resolve: (value: unknown) => void) => void\n [key: string]: unknown\n}\n\n/**\n * Create mock Knex query builder\n */\nexport function createMockQueryBuilder(data: unknown[] = []) {\n const mockQb: MockQueryBuilderState = {\n _data: [...data],\n _whereClauses: [] as Array<{ column: string; value: unknown; operator?: string }>,\n _whereInClauses: [] as Array<{ column: string; values: unknown[] }>,\n _whereNotInClauses: [] as Array<{ column: string; values: unknown[] }>,\n _whereNotClauses: [] as Array<{ column: string; value: unknown }>,\n _whereNullClauses: [] as string[],\n _whereNotNullClauses: [] as string[],\n _orderBy: null as { column: string; direction: string } | null,\n _limit: null as number | null,\n _offset: null as number | null,\n _insertData: null as unknown,\n _updateData: null as unknown,\n _deleted: false,\n\n where(column: string, operatorOrValue: unknown, value?: unknown) {\n if (value !== undefined) {\n // 3-arg form: where(column, operator, value)\n mockQb._whereClauses = [...(mockQb._whereClauses as Array<{ column: string; value: unknown; operator?: string }>), { column, operator: operatorOrValue as string, value }]\n } else {\n // 2-arg form: where(column, value)\n mockQb._whereClauses = [...(mockQb._whereClauses as Array<{ column: string; value: unknown; operator?: string }>), { column, value: operatorOrValue }]\n }\n return mockQb\n },\n\n whereNot(column: string, value: unknown) {\n mockQb._whereNotClauses = [...(mockQb._whereNotClauses as Array<{ column: string; value: unknown }>), { column, value }]\n return mockQb\n },\n\n whereIn(column: string, values: unknown[]) {\n mockQb._whereInClauses = [...(mockQb._whereInClauses as Array<{ column: string; values: unknown[] }>), { column, values }]\n return mockQb\n },\n\n whereNotIn(column: string, values: unknown[]) {\n mockQb._whereNotInClauses = [...(mockQb._whereNotInClauses as Array<{ column: string; values: unknown[] }>), { column, values }]\n return mockQb\n },\n\n whereNull(column: string) {\n mockQb._whereNullClauses = [...(mockQb._whereNullClauses as string[]), column]\n return mockQb\n },\n\n whereNotNull(column: string) {\n mockQb._whereNotNullClauses = [...(mockQb._whereNotNullClauses as string[]), column]\n return mockQb\n },\n\n whereBetween() {\n return mockQb\n },\n\n orderBy(column: string, direction = 'asc') {\n mockQb._orderBy = { column, direction }\n return mockQb\n },\n\n limit(n: number) {\n mockQb._limit = n\n return mockQb\n },\n\n offset(n: number) {\n mockQb._offset = n\n return mockQb\n },\n\n select() {\n return mockQb\n },\n\n join() {\n return mockQb\n },\n\n leftJoin() {\n return mockQb\n },\n\n groupBy() {\n return mockQb\n },\n\n andWhere() {\n return mockQb\n },\n\n orWhere() {\n return mockQb\n },\n\n returning() {\n return mockQb\n },\n\n clone() {\n return createMockQueryBuilder(mockQb._data as unknown[])\n },\n\n count() {\n return {\n first: vi.fn().mockResolvedValue({ count: (mockQb._data as unknown[]).length })\n }\n },\n\n async first() {\n let result = applyFilters(mockQb._data as Record<string, unknown>[], mockQb)\n\n // Apply orderBy if set\n if (mockQb._orderBy) {\n const { column, direction } = mockQb._orderBy as { column: string; direction: string }\n result = [...result].sort((a, b) => {\n const aVal = String(a[column] ?? '')\n const bVal = String(b[column] ?? '')\n return direction === 'asc'\n ? aVal.localeCompare(bVal)\n : bVal.localeCompare(aVal)\n })\n }\n\n return result[0] ?? undefined\n },\n\n async insert(data: unknown) {\n mockQb._insertData = data\n return [1]\n },\n\n async update(data: unknown) {\n mockQb._updateData = data\n return 1\n },\n\n async delete() {\n mockQb._deleted = true\n return 1\n },\n\n then(resolve: (value: unknown) => void) {\n const filtered = applyFilters(mockQb._data as Record<string, unknown>[], mockQb)\n let result = filtered\n\n if (mockQb._orderBy) {\n const { column, direction } = mockQb._orderBy as { column: string; direction: string }\n result = [...result].sort((a, b) => {\n const aVal = String(a[column] ?? '')\n const bVal = String(b[column] ?? '')\n return direction === 'asc'\n ? aVal.localeCompare(bVal)\n : bVal.localeCompare(aVal)\n })\n }\n\n if (mockQb._offset !== null) {\n result = result.slice(mockQb._offset as number)\n }\n\n if (mockQb._limit !== null) {\n result = result.slice(0, mockQb._limit as number)\n }\n\n resolve(result)\n }\n }\n\n return mockQb as unknown as Knex.QueryBuilder\n}\n\nfunction applyFilters(data: Record<string, unknown>[], qb: MockQueryBuilderState): Record<string, unknown>[] {\n let result = [...data]\n\n // Apply where clauses (supports 2-arg equality and 3-arg operator forms)\n for (const clause of qb._whereClauses as Array<{ column: string; value: unknown; operator?: string }>) {\n if (clause.operator) {\n // 3-arg form: where(column, operator, value)\n result = result.filter(item => {\n const itemVal = item[clause.column]\n switch (clause.operator) {\n case '>': return (itemVal as number) > (clause.value as number)\n case '>=': return (itemVal as number) >= (clause.value as number)\n case '<': return (itemVal as number) < (clause.value as number)\n case '<=': return (itemVal as number) <= (clause.value as number)\n case 'like': {\n const pattern = String(clause.value)\n const str = String(itemVal ?? '')\n if (pattern.startsWith('%') && pattern.endsWith('%'))\n return str.toLowerCase().includes(pattern.slice(1, -1).toLowerCase())\n if (pattern.startsWith('%'))\n return str.toLowerCase().endsWith(pattern.slice(1).toLowerCase())\n if (pattern.endsWith('%'))\n return str.toLowerCase().startsWith(pattern.slice(0, -1).toLowerCase())\n return str === pattern\n }\n default: return itemVal === clause.value\n }\n })\n } else {\n // 2-arg form: where(column, value) — equality\n result = result.filter(item => item[clause.column] === clause.value)\n }\n }\n\n // Apply whereNot clauses\n for (const clause of qb._whereNotClauses as Array<{ column: string; value: unknown }>) {\n result = result.filter(item => item[clause.column] !== clause.value)\n }\n\n // Apply whereIn clauses\n for (const clause of qb._whereInClauses as Array<{ column: string; values: unknown[] }>) {\n result = result.filter(item => clause.values.includes(item[clause.column]))\n }\n\n // Apply whereNotIn clauses\n for (const clause of qb._whereNotInClauses as Array<{ column: string; values: unknown[] }>) {\n result = result.filter(item => !clause.values.includes(item[clause.column]))\n }\n\n // Apply whereNull clauses\n for (const column of qb._whereNullClauses as string[]) {\n result = result.filter(item => item[column] === null || item[column] === undefined)\n }\n\n // Apply whereNotNull clauses\n for (const column of qb._whereNotNullClauses as string[]) {\n result = result.filter(item => item[column] !== null && item[column] !== undefined)\n }\n\n return result\n}\n\n/**\n * Create mock Knex instance\n */\nexport function createMockDb(tableData: Record<string, unknown[]> = {}) {\n const mockDb = vi.fn((table: string) => {\n return createMockQueryBuilder(tableData[table] ?? [])\n }) as unknown as Knex\n\n // Add schema property for migrations\n ;(mockDb as unknown as Record<string, unknown>)['schema'] = {\n hasTable: vi.fn().mockResolvedValue(false),\n createTable: vi.fn().mockResolvedValue(undefined)\n }\n\n // Add raw method\n ;(mockDb as unknown as Record<string, unknown>)['raw'] = vi.fn().mockReturnValue({\n then: (resolve: (v: unknown) => void) => resolve([])\n })\n\n // Add transaction method\n ;(mockDb as unknown as Record<string, unknown>)['transaction'] = vi.fn().mockImplementation(async (callback: (trx: unknown) => Promise<void>) => {\n // Create a trx mock that works like the db mock\n const trxMock = vi.fn((table: string) => {\n return createMockQueryBuilder(tableData[table] ?? [])\n })\n await callback(trxMock)\n })\n\n return mockDb\n}\n\n/**\n * Create mock DbContext with the new structure.\n * Wraps a Knex mock in the full DbContext interface.\n */\nexport function createMockDbContext(tableData: Record<string, unknown[]> = {}): ModuleContext['db'] {\n const mockKnex = createMockDb(tableData)\n\n return {\n knex: mockKnex,\n adapter: {\n findMany: vi.fn().mockResolvedValue({ items: [], total: 0, page: 1, limit: 20, totalPages: 0, hasNext: false }),\n findOne: vi.fn().mockResolvedValue(null),\n findById: vi.fn().mockResolvedValue(null),\n count: vi.fn().mockResolvedValue(0),\n insert: vi.fn().mockResolvedValue({}),\n update: vi.fn().mockResolvedValue({}),\n delete: vi.fn().mockResolvedValue(true),\n transaction: vi.fn().mockImplementation(async (fn: (adapter: unknown) => Promise<void>) => fn({}))\n },\n schema: {\n hasTable: vi.fn().mockResolvedValue(false),\n hasColumn: vi.fn().mockResolvedValue(false),\n getColumns: vi.fn().mockResolvedValue([]),\n createTable: vi.fn().mockResolvedValue(undefined),\n alterTable: vi.fn().mockResolvedValue(undefined),\n dropTable: vi.fn().mockResolvedValue(undefined),\n addTimestamps: vi.fn().mockResolvedValue(undefined),\n addAuditFields: vi.fn().mockResolvedValue(undefined),\n addColumnIfMissing: vi.fn().mockResolvedValue(false),\n raw: {}\n },\n t: (name: string) => name,\n addTimestamps: vi.fn(),\n addAuditFieldsIfMissing: vi.fn(),\n addSoftDeleteFieldIfMissing: vi.fn(),\n addConfigDefaultField: vi.fn(),\n addColumnIfMissing: vi.fn(),\n nowTimestamp: () => new Date().toISOString(),\n formatTimestamp: (_db: unknown, date?: Date) => (date ?? new Date()).toISOString(),\n applySearchFilter,\n getPagination,\n buildPaginatedResult,\n getSearchableFields\n } as unknown as ModuleContext['db']\n}\n\n/**\n * Options for createMockContext, extending ModuleContext overrides with\n * plugin-specific helpers.\n */\ninterface MockContextOptions extends Partial<ModuleContext> {\n pluginCode?: string\n}\n\n/**\n * Create mock ModuleContext\n * Provides sensible defaults for all context properties.\n * Use overrides to customize specific properties per test.\n *\n * Structure matches the new ModuleContext interface:\n * - ctx.core: logger, errors, generateId, crypto, socket, etc.\n * - ctx.db: knex, adapter, schema, helper functions\n * - ctx.engine: module/plugin introspection\n * - ctx.services: inter-module service registry\n * - ctx.adapters: external data source adapters\n *\n * @param overrides - Partial ModuleContext overrides plus optional pluginCode\n * for table name prefixing via ctx.db.t()\n */\nexport function createMockContext(overrides: MockContextOptions = {}): ModuleContext {\n let idCounter = 0\n\n // Extract pluginCode before spreading into ModuleContext\n const { pluginCode, ...rest } = overrides as MockContextOptions\n const t = pluginCode\n ? (name: string) => `${pluginCode}_${name}`\n : (name: string) => name\n\n // Service registry (private, exposed via API)\n const services: Record<string, unknown> = {}\n\n // Adapter registry (private, exposed via API)\n // Pre-register 'temp' adapter with InMemoryAdapter for TempService tests\n const tempAdapter = createInMemoryAdapter()\n const adapters: Record<string, { data: unknown; schema?: unknown }> = {\n temp: { data: tempAdapter }\n }\n\n // Handle legacy override pattern: if overrides.db is a function (Knex mock),\n // wrap it in the new DbContext structure for backwards compatibility\n let processedOverrides = { ...rest }\n if (rest.db && typeof rest.db === 'function') {\n // It's a raw Knex mock, wrap it in DbContext structure\n const knexMock = rest.db as unknown as Knex\n processedOverrides = {\n ...rest,\n db: {\n knex: knexMock,\n adapter: {\n findMany: vi.fn().mockResolvedValue({ items: [], total: 0, page: 1, limit: 20, totalPages: 0, hasNext: false }),\n findOne: vi.fn().mockResolvedValue(null),\n findById: vi.fn().mockResolvedValue(null),\n count: vi.fn().mockResolvedValue(0),\n insert: vi.fn().mockResolvedValue({}),\n update: vi.fn().mockResolvedValue({}),\n delete: vi.fn().mockResolvedValue(true),\n transaction: vi.fn().mockImplementation(async (fn: (adapter: unknown) => Promise<void>) => fn({}))\n },\n schema: {\n hasTable: vi.fn().mockResolvedValue(false),\n hasColumn: vi.fn().mockResolvedValue(false),\n getColumns: vi.fn().mockResolvedValue([]),\n createTable: vi.fn().mockResolvedValue(undefined),\n alterTable: vi.fn().mockResolvedValue(undefined),\n dropTable: vi.fn().mockResolvedValue(undefined),\n addTimestamps: vi.fn().mockResolvedValue(undefined),\n addAuditFields: vi.fn().mockResolvedValue(undefined),\n addColumnIfMissing: vi.fn().mockResolvedValue(false),\n raw: {}\n },\n t,\n addTimestamps: vi.fn(),\n addAuditFieldsIfMissing: vi.fn(),\n addSoftDeleteFieldIfMissing: vi.fn(),\n addConfigDefaultField: vi.fn(),\n addColumnIfMissing: vi.fn(),\n nowTimestamp: () => new Date().toISOString(),\n formatTimestamp: (_db: unknown, date?: Date) => (date ?? new Date()).toISOString(),\n applySearchFilter,\n getPagination,\n buildPaginatedResult,\n getSearchableFields,\n getKnex: () => knexMock,\n // Legacy: ctx.db.raw → now ctx.db.knex.raw\n raw: (knexMock as unknown as { raw: unknown }).raw\n } as unknown as ModuleContext['db']\n }\n }\n\n // Mock Knex instance\n const mockKnex = createMockDb()\n\n // Mock logger\n const mockLogger = {\n info: vi.fn(),\n warn: vi.fn(),\n error: vi.fn(),\n debug: vi.fn(),\n trace: vi.fn(),\n fatal: vi.fn(),\n child: vi.fn().mockReturnThis()\n }\n\n // Mock schema adapter\n const mockSchemaAdapter = {\n hasTable: vi.fn().mockResolvedValue(false),\n hasColumn: vi.fn().mockResolvedValue(false),\n getColumns: vi.fn().mockResolvedValue([]),\n createTable: vi.fn().mockResolvedValue(undefined),\n alterTable: vi.fn().mockResolvedValue(undefined),\n dropTable: vi.fn().mockResolvedValue(undefined),\n addTimestamps: vi.fn().mockResolvedValue(undefined),\n addAuditFields: vi.fn().mockResolvedValue(undefined),\n addColumnIfMissing: vi.fn().mockResolvedValue(false),\n raw: {}\n }\n\n // Mock database adapter\n const mockDbAdapter = {\n findMany: vi.fn().mockResolvedValue({ items: [], total: 0, page: 1, limit: 20, totalPages: 0, hasNext: false }),\n findOne: vi.fn().mockResolvedValue(null),\n findById: vi.fn().mockResolvedValue(null),\n count: vi.fn().mockResolvedValue(0),\n insert: vi.fn().mockResolvedValue({}),\n update: vi.fn().mockResolvedValue({}),\n delete: vi.fn().mockResolvedValue(true),\n transaction: vi.fn().mockImplementation(async (fn: (adapter: unknown) => Promise<void>) => fn({}))\n }\n\n return {\n // =========================================================================\n // Core Context: logger, errors, crypto, socket, events, middleware\n // =========================================================================\n core: {\n logger: mockLogger as unknown as ModuleContext['core']['logger'],\n errors: {\n AppError,\n NotFoundError,\n UnauthorizedError,\n ForbiddenError,\n ConflictError,\n ValidationError,\n codes: ErrorCodes\n },\n crypto: {\n hashPassword: vi.fn().mockResolvedValue('$2b$12$mockhash'),\n verifyPassword: vi.fn().mockResolvedValue(true),\n DUMMY_HASH: '$2b$12$dummyhashfordummypasswordcheck'\n },\n socket: {\n getIO: vi.fn().mockReturnValue({}),\n isInitialized: vi.fn().mockReturnValue(false),\n isUserConnected: vi.fn().mockReturnValue(false),\n getUserSocketCount: vi.fn().mockReturnValue(0),\n getConnectedUsers: vi.fn().mockReturnValue([])\n },\n sse: {\n sendEvent: vi.fn(),\n close: vi.fn()\n },\n abilities: {} as ModuleContext['core']['abilities'],\n events: {\n emit: vi.fn(),\n emitEvent: vi.fn(),\n emitAsync: vi.fn().mockResolvedValue(undefined),\n on: vi.fn(),\n off: vi.fn()\n },\n middleware: {} as ModuleContext['core']['middleware'],\n createRouter: vi.fn(),\n generateId: () => `test-id-${++idCounter}`,\n generateIdByType: (type?: string) => {\n if (type === 'auto' || type === 'custom' || type === 'pattern') return undefined\n return `test-id-${++idCounter}`\n },\n getLibPath: () => '/tmp',\n getProjectPath: () => '/tmp',\n cache: (() => {\n const caches = new Map<string, ManagedCacheImpl<any>>()\n return {\n create: vi.fn().mockImplementation((name: string, opts?: any) => {\n const cache = new ManagedCacheImpl(name, opts)\n caches.set(name, cache)\n return cache\n }),\n getOrCreate: vi.fn().mockImplementation((name: string, opts?: any) => {\n if (caches.has(name)) return caches.get(name)!\n const cache = new ManagedCacheImpl(name, opts)\n caches.set(name, cache)\n return cache\n }),\n get: vi.fn().mockImplementation((name: string) => caches.get(name)),\n clearAll: vi.fn(),\n stats: vi.fn().mockReturnValue({}),\n destroy: vi.fn()\n }\n })(),\n safeJsonParse: <T>(jsonString: string, fallback: T): T => {\n try {\n return JSON.parse(jsonString) as T\n } catch {\n return fallback\n }\n }\n } as unknown as ModuleContext['core'],\n\n // =========================================================================\n // Database Context: knex, adapter, schema, helper functions\n // =========================================================================\n db: {\n knex: mockKnex,\n adapter: mockDbAdapter as unknown as ModuleContext['db']['adapter'],\n schema: mockSchemaAdapter as unknown as ModuleContext['db']['schema'],\n t,\n addTimestamps: vi.fn(),\n addAuditFieldsIfMissing: vi.fn(),\n addSoftDeleteFieldIfMissing: vi.fn(),\n addConfigDefaultField: vi.fn(),\n addColumnIfMissing: vi.fn(),\n nowTimestamp: () => new Date().toISOString(),\n formatTimestamp: (_db: unknown, date?: Date) => (date ?? new Date()).toISOString(),\n applySearchFilter,\n getPagination,\n buildPaginatedResult,\n getSearchableFields,\n getKnex: () => mockKnex,\n // Legacy: ctx.db.raw → now ctx.db.knex.raw\n raw: (mockKnex as unknown as { raw: unknown }).raw\n } as unknown as ModuleContext['db'],\n\n // =========================================================================\n // Runtime Context: entity service/controller/router factories\n // =========================================================================\n runtime: {\n createEntityService: vi.fn(),\n createEntityController: vi.fn(),\n createEntityRouter: vi.fn()\n } as unknown as ModuleContext['runtime'],\n\n // =========================================================================\n // Config Context: env vars and resolved NexusConfig\n // =========================================================================\n config: {} as ModuleContext['config'],\n\n // =========================================================================\n // Engine Context: module/plugin introspection\n // =========================================================================\n engine: {\n getModules: vi.fn().mockReturnValue([]),\n getPlugins: vi.fn().mockReturnValue([]),\n getModuleSubjects: vi.fn().mockReturnValue([]),\n getRegisteredSubjects: vi.fn().mockReturnValue([])\n } as unknown as ModuleContext['engine'],\n\n // =========================================================================\n // Services Context: inter-module service registry\n // =========================================================================\n services: {\n register(name: string, service: unknown): void {\n services[name] = service\n },\n get<T>(serviceName: string): T {\n const service = services[serviceName]\n if (!service) {\n throw new Error(`Service \"${serviceName}\" not initialized.`)\n }\n return service as T\n },\n getOptional<T>(serviceName: string): T | undefined {\n return services[serviceName] as T | undefined\n },\n has(serviceName: string): boolean {\n return !!services[serviceName]\n }\n } as unknown as ModuleContext['services'],\n\n // =========================================================================\n // Adapters Context: external data source adapters\n // =========================================================================\n adapters: {\n register(name: string, dataAdapter: unknown, schemaAdapter?: unknown): void {\n adapters[name] = { data: dataAdapter, schema: schemaAdapter }\n },\n get(name: string) {\n const pair = adapters[name]\n if (!pair) {\n throw new Error(`Adapter \"${name}\" not found`)\n }\n return pair.data\n },\n getSchema(name: string) {\n const pair = adapters[name]\n return pair?.schema\n },\n has(name: string): boolean {\n return name in adapters\n }\n } as unknown as ModuleContext['adapters'],\n\n // =========================================================================\n // Root-level shortcut\n // =========================================================================\n createRouter: vi.fn(),\n\n // Semantic events API (NEX-161)\n events: {\n notify: vi.fn(),\n query: vi.fn().mockResolvedValue([]),\n command: vi.fn().mockResolvedValue(undefined),\n on: vi.fn(),\n off: vi.fn(),\n once: vi.fn(),\n onAny: vi.fn(),\n },\n\n // =========================================================================\n // Legacy API compatibility - deprecated, use new API instead\n // =========================================================================\n\n // Legacy: ctx.logger → now ctx.core.logger\n logger: mockLogger as unknown as ModuleContext['core']['logger'],\n\n // Legacy: ctx.errors → now ctx.core.errors\n errors: {\n AppError,\n NotFoundError,\n UnauthorizedError,\n ForbiddenError,\n ConflictError,\n ValidationError,\n codes: ErrorCodes\n },\n\n // Legacy: ctx.registerService → now ctx.services.register\n registerService(name: string, service: unknown): void {\n services[name] = service\n },\n getService<T>(serviceName: string): T {\n const service = services[serviceName]\n if (!service) {\n throw new Error(`Service \"${serviceName}\" not initialized.`)\n }\n return service as T\n },\n getOptionalService<T>(serviceName: string): T | undefined {\n return services[serviceName] as T | undefined\n },\n hasService(serviceName: string): boolean {\n return !!services[serviceName]\n },\n registerAdapter(name: string, dataAdapter: unknown, schemaAdapter?: unknown): void {\n adapters[name] = { data: dataAdapter, schema: schemaAdapter }\n },\n getAdapter(name: string) {\n const pair = adapters[name]\n if (!pair) {\n throw new Error(`Adapter \"${name}\" not found`)\n }\n return pair.data\n },\n hasAdapter(name: string): boolean {\n return name in adapters\n },\n\n ...processedOverrides\n } as ModuleContext\n}\n\n// === Entity Definition Factories ===\n\nexport function createCollectionDefinition(\n overrides: Partial<CollectionEntityDefinition> = {}\n): CollectionEntityDefinition {\n return {\n type: 'collection',\n table: 'test_items',\n label: 'Test Items',\n labelField: 'name',\n timestamps: true,\n fields: {\n id: {\n label: 'ID',\n input: 'text',\n hidden: true,\n db: { type: 'string', size: 26, nullable: false }\n },\n name: {\n label: 'Name',\n input: 'text',\n db: { type: 'string', size: 100, nullable: false }\n }\n },\n ...overrides\n }\n}\n\nexport function createSingleDefinition(\n overrides: Partial<SingleEntityDefinition> = {}\n): SingleEntityDefinition {\n return {\n type: 'single',\n key: 'test_settings',\n label: 'Test Settings',\n defaults: { theme: 'light', language: 'en' },\n fields: {\n theme: {\n label: 'Theme',\n input: 'select',\n db: { type: 'string', size: 20, nullable: false }\n },\n language: {\n label: 'Language',\n input: 'select',\n db: { type: 'string', size: 10, nullable: false }\n }\n },\n ...overrides\n }\n}\n\nexport function createReferenceDefinition(\n overrides: Partial<CollectionEntityDefinition> = {}\n): CollectionEntityDefinition {\n return {\n type: 'collection',\n table: 'ref_countries',\n label: 'Countries',\n labelField: 'name',\n seed: [\n { id: 'ES', code: 'ES', name: 'Spain' },\n { id: 'US', code: 'US', name: 'United States' },\n { id: 'MX', code: 'MX', name: 'Mexico' }\n ],\n fields: {\n id: {\n label: 'ID',\n input: 'text',\n hidden: true,\n db: { type: 'string', size: 10, nullable: false }\n },\n code: {\n label: 'Code',\n input: 'text',\n db: { type: 'string', size: 10, nullable: false }\n },\n name: {\n label: 'Name',\n input: 'text',\n db: { type: 'string', size: 100, nullable: false }\n }\n },\n ...overrides\n }\n}\n\nexport function createEventDefinition(\n overrides: Partial<EventEntityDefinition> = {}\n): EventEntityDefinition {\n return {\n type: 'event',\n table: 'evt_audit_logs',\n label: 'Audit Logs',\n labelField: 'action',\n immutable: true,\n defaultSort: { field: 'created_at', order: 'desc' as const },\n retention: { days: 90, maxRows: 10000 },\n fields: {\n id: {\n label: 'ID',\n input: 'text',\n hidden: true,\n db: { type: 'string', size: 26, nullable: false }\n },\n action: {\n label: 'Action',\n input: 'text',\n db: { type: 'string', size: 50, nullable: false }\n },\n user_id: {\n label: 'User',\n input: 'text',\n db: { type: 'string', size: 26, nullable: true }\n },\n created_at: {\n label: 'Created At',\n input: 'datetime',\n db: { type: 'datetime', nullable: false }\n }\n },\n ...overrides\n }\n}\n\n/** @deprecated Config absorbed into Single. Use createSingleDefinition with scopeField instead. */\nexport function createConfigDefinition(\n overrides: Partial<SingleEntityDefinition> = {}\n): SingleEntityDefinition {\n return {\n type: 'config',\n key: 'cfg_module_settings',\n label: 'Module Settings',\n scopeField: 'module_name',\n defaults: { enabled: true, maxItems: 100 },\n fields: {\n module_name: {\n label: 'Module',\n input: 'text',\n db: { type: 'string', size: 50, nullable: false }\n },\n enabled: {\n label: 'Enabled',\n input: 'checkbox',\n db: { type: 'boolean', nullable: false }\n },\n maxItems: {\n label: 'Max Items',\n input: 'number',\n db: { type: 'integer', nullable: false }\n }\n },\n ...overrides\n }\n}\n\n/** @deprecated Temp absorbed into Collection. Use createCollectionDefinition with retention instead. */\nexport function createTempDefinition(\n overrides: Partial<CollectionEntityDefinition> = {}\n): CollectionEntityDefinition {\n return {\n type: 'temp',\n table: 'tmp_sessions',\n label: 'Sessions',\n labelField: 'token',\n retention: { seconds: 3600, expiresField: 'expires_at' }, // 1 hour\n fields: {\n id: {\n label: 'ID',\n input: 'text',\n hidden: true,\n db: { type: 'string', size: 26, nullable: false }\n },\n token: {\n label: 'Token',\n input: 'text',\n db: { type: 'string', size: 256, nullable: false }\n },\n expires_at: {\n label: 'Expires At',\n input: 'datetime',\n db: { type: 'datetime', nullable: false }\n }\n },\n ...overrides\n }\n}\n\nexport function createViewDefinition(\n overrides: Partial<ViewEntityDefinition> = {}\n): ViewEntityDefinition {\n return {\n type: 'view',\n table: 'vw_user_stats',\n label: 'User Stats',\n labelField: 'user_id',\n query: 'SELECT user_id, COUNT(*) as count FROM posts GROUP BY user_id',\n fields: {\n user_id: {\n label: 'User',\n input: 'text',\n db: { type: 'string', size: 26, nullable: false }\n },\n count: {\n label: 'Count',\n input: 'number',\n db: { type: 'integer', nullable: false }\n }\n },\n ...overrides\n }\n}\n\nexport function createExternalDefinition(\n overrides: Partial<ExternalEntityDefinition> = {}\n): ExternalEntityDefinition {\n return {\n type: 'external',\n adapter: 'test-api',\n table: 'external_items', // Resource ID in external system\n label: 'External Items',\n labelField: 'title',\n cache: { ttl: 300 },\n fields: {\n id: {\n label: 'ID',\n input: 'text',\n hidden: true,\n db: { type: 'string', size: 26, nullable: false }\n },\n title: {\n label: 'Title',\n input: 'text',\n db: { type: 'string', size: 200, nullable: false }\n }\n },\n ...overrides\n }\n}\n\n/** @deprecated Use createComputedDefinition with sources instead */\nexport function createVirtualDefinition(\n overrides: Partial<ComputedEntityDefinition> = {}\n): ComputedEntityDefinition {\n return createComputedDefinition({\n sources: ['source_a', 'source_b'],\n resolver: (sources) => {\n const combined = [\n ...(sources['source_a'] ?? []),\n ...(sources['source_b'] ?? [])\n ]\n return combined\n },\n compute: undefined,\n ...overrides\n })\n}\n\nexport function createComputedDefinition(\n overrides: Partial<ComputedEntityDefinition> = {}\n): ComputedEntityDefinition {\n return {\n type: 'computed',\n label: 'Computed Stats',\n compute: vi.fn().mockResolvedValue([\n { id: '1', metric: 'users', value: 100 },\n { id: '2', metric: 'posts', value: 500 }\n ]),\n cache: { ttl: 60 },\n fields: {\n id: {\n label: 'ID',\n input: 'text',\n hidden: true,\n db: { type: 'string', size: 26, nullable: false }\n },\n metric: {\n label: 'Metric',\n input: 'text',\n db: { type: 'string', size: 50, nullable: false }\n },\n value: {\n label: 'Value',\n input: 'number',\n db: { type: 'integer', nullable: false }\n }\n },\n ...overrides\n }\n}\n\n// === Mock DatabaseAdapter Factory ===\n\n/**\n * Creates a mock DatabaseAdapter for testing external services.\n * All methods are vi.fn() mocks with sensible defaults.\n */\nexport function createMockDatabaseAdapter(overrides: Partial<DatabaseAdapter> = {}): DatabaseAdapter {\n return {\n findMany: vi.fn().mockResolvedValue({\n items: [\n { id: 'ext-1', title: 'External Item 1' },\n { id: 'ext-2', title: 'External Item 2' }\n ],\n total: 2,\n page: 1,\n limit: 20,\n totalPages: 1,\n hasNext: false\n }),\n findOne: vi.fn().mockResolvedValue(null),\n findById: vi.fn().mockResolvedValue({ id: 'ext-1', title: 'External Item 1' }),\n count: vi.fn().mockResolvedValue(2),\n insert: vi.fn().mockResolvedValue({ id: 'ext-new', title: 'Created' }),\n update: vi.fn().mockResolvedValue({ id: 'ext-1', title: 'Updated' }),\n delete: vi.fn().mockResolvedValue(true),\n transaction: vi.fn().mockImplementation(async (fn) => fn({} as DatabaseAdapter)),\n raw: vi.fn().mockResolvedValue([]),\n ...overrides\n }\n}\n\n// === Tree and DAG Definition Factories ===\n\nexport function createTreeDefinition(\n overrides: Partial<TreeEntityDefinition> = {}\n): TreeEntityDefinition {\n return {\n type: 'tree',\n table: 'tree_categories',\n label: 'Categories',\n labelField: 'name',\n timestamps: true,\n seed: [\n { id: 'root', name: 'Root Category', parent_id: null }\n ],\n fields: {\n id: {\n label: 'ID',\n input: 'text',\n hidden: true,\n db: { type: 'string', size: 26, nullable: false }\n },\n name: {\n label: 'Name',\n input: 'text',\n db: { type: 'string', size: 100, nullable: false }\n }\n // parent_id is auto-injected by TreeService\n },\n ...overrides\n }\n}\n\nexport function createDagDefinition(\n overrides: Partial<DagEntityDefinition> = {}\n): DagEntityDefinition {\n return {\n type: 'dag',\n table: 'dag_tags',\n label: 'Tags',\n labelField: 'name',\n timestamps: true,\n seed: [\n { id: 'root', name: 'Root Tag' }\n ],\n fields: {\n id: {\n label: 'ID',\n input: 'text',\n hidden: true,\n db: { type: 'string', size: 26, nullable: false }\n },\n name: {\n label: 'Name',\n input: 'text',\n db: { type: 'string', size: 100, nullable: false }\n }\n },\n ...overrides\n }\n}\n\n// === Action Definition Factory ===\n\nexport function createActionDefinition(\n overrides: Partial<ActionDefinition> = {}\n): ActionDefinition {\n return {\n key: 'test_action',\n label: 'Test Action',\n scope: 'row',\n method: 'POST',\n handler: async () => ({ success: true }),\n ...overrides\n }\n}\n","/**\n * Query filter helpers.\n *\n * Shared logic for applying filters to Knex queries.\n * Used by both KnexAdapter and BaseService for DRY.\n */\n\nimport type { Knex } from 'knex'\nimport type { FilterOperators } from '@gzl10/nexus-sdk'\n\n/**\n * Escape LIKE wildcard characters (%, _, \\) in user input.\n * Prevents wildcard injection in $contains, $startswith, $endswith operators.\n */\nexport function escapeLikeWildcards(value: string): string {\n return value.replace(/[%_\\\\]/g, '\\\\$&')\n}\n\n/**\n * Apply filters to a Knex query builder.\n *\n * Supports:\n * - Simple equality: `{ name: 'John' }`\n * - Operators: `{ age: { $gte: 18 } }`\n * - Array shorthand for $in: `{ status: ['active', 'pending'] }`\n * - Null check: `{ deletedAt: null }`\n *\n * @example\n * let qb = db('users')\n * qb = applyFilters(qb, { status: 'active', age: { $gte: 18 } })\n */\nexport function applyFilters(qb: Knex.QueryBuilder, filters: Record<string, unknown>): Knex.QueryBuilder {\n for (const [key, value] of Object.entries(filters)) {\n if (value === undefined) continue\n\n // $or: OR logic between filter groups\n if (key === '$or') {\n if (Array.isArray(value) && value.length > 0) {\n qb.where(function () {\n for (const group of value as Record<string, unknown>[]) {\n this.orWhere(function () {\n applyFilters(this, group)\n })\n }\n })\n }\n continue\n }\n\n // Null value - direct comparison\n if (value === null) {\n qb.whereNull(key)\n continue\n }\n\n // Empty string - skip\n if (value === '') continue\n\n // Array shorthand for $in\n if (Array.isArray(value) && value.length > 0) {\n qb.whereIn(key, value as (string | number)[])\n continue\n }\n\n // Object with operators\n if (typeof value === 'object' && !Array.isArray(value)) {\n applyFilterOperators(qb, key, value as FilterOperators)\n continue\n }\n\n // Simple equality\n qb.where(key, value)\n }\n return qb\n}\n\n/**\n * Apply filter operators for a single field.\n *\n * Supported operators:\n * - $eq: Equal\n * - $ne: Not equal\n * - $gt: Greater than\n * - $gte: Greater than or equal\n * - $lt: Less than\n * - $lte: Less than or equal\n * - $contains: LIKE %val%\n * - $startswith: LIKE val%\n * - $endswith: LIKE %val\n * - $in: IN (array)\n * - $nin: NOT IN (array)\n * - $isnull: IS NULL / IS NOT NULL\n */\nexport function applyFilterOperators(qb: Knex.QueryBuilder, field: string, operators: FilterOperators): void {\n for (const [op, val] of Object.entries(operators)) {\n if (val === undefined) continue\n\n switch (op) {\n case '$eq':\n if (val === null) qb.whereNull(field)\n else qb.where(field, val)\n break\n\n case '$ne':\n if (val === null) qb.whereNotNull(field)\n else qb.whereNot(field, val)\n break\n\n case '$gt':\n qb.where(field, '>', val)\n break\n\n case '$gte':\n qb.where(field, '>=', val)\n break\n\n case '$lt':\n qb.where(field, '<', val)\n break\n\n case '$lte':\n qb.where(field, '<=', val)\n break\n\n case '$contains':\n qb.where(field, 'like', `%${escapeLikeWildcards(String(val))}%`)\n break\n\n case '$startswith':\n qb.where(field, 'like', `${escapeLikeWildcards(String(val))}%`)\n break\n\n case '$endswith':\n qb.where(field, 'like', `%${escapeLikeWildcards(String(val))}`)\n break\n\n case '$in':\n if (Array.isArray(val) && val.length > 0) {\n qb.whereIn(field, val as (string | number)[])\n }\n break\n\n case '$nin':\n if (Array.isArray(val) && val.length > 0) {\n qb.whereNotIn(field, val as (string | number)[])\n }\n break\n\n case '$isnull':\n if (val === true) qb.whereNull(field)\n else if (val === false) qb.whereNotNull(field)\n break\n\n case '$between':\n if (Array.isArray(val) && val.length === 2) {\n qb.whereBetween(field, val as [string | number | Date, string | number | Date])\n }\n break\n }\n }\n}\n\n// ============================================================================\n// In-Memory Filter Helpers\n// ============================================================================\n\n/**\n * Apply filters in memory to an array of items.\n *\n * Supports same operators as Knex version:\n * $eq, $ne, $gt, $gte, $lt, $lte, $contains, $startswith, $endswith, $in, $nin, $isnull\n *\n * @example\n * const filtered = applyInMemoryFilters(users, { status: 'active', age: { $gte: 18 } })\n */\nexport function applyInMemoryFilters<T = unknown>(items: T[], filters: Record<string, unknown>): T[] {\n return items.filter(item => {\n const record = item as Record<string, unknown>\n return matchRecordFilters(record, filters)\n })\n}\n\n/**\n * Check if a single record matches all filters (AND logic).\n * Extracted for reuse by $or groups.\n */\nfunction matchRecordFilters(record: Record<string, unknown>, filters: Record<string, unknown>): boolean {\n for (const [key, value] of Object.entries(filters)) {\n if (value === undefined) continue\n\n // $or: at least one group must match\n if (key === '$or') {\n if (Array.isArray(value) && value.length > 0) {\n const orMatch = (value as Record<string, unknown>[]).some(group =>\n matchRecordFilters(record, group)\n )\n if (!orMatch) return false\n }\n continue\n }\n\n const itemValue = record[key]\n\n // Null value - check if field is null\n if (value === null) {\n if (itemValue !== null && itemValue !== undefined) return false\n continue\n }\n\n // Empty string - skip\n if (value === '') continue\n\n // Array shorthand for $in\n if (Array.isArray(value)) {\n // Empty array = no filter (return all)\n if (value.length === 0) continue\n if (!value.includes(itemValue)) return false\n continue\n }\n\n // Object with operators\n if (typeof value === 'object' && !Array.isArray(value)) {\n if (!matchFilterOperators(itemValue, value as FilterOperators)) return false\n continue\n }\n\n // Simple equality\n if (itemValue !== value) return false\n }\n\n return true\n}\n\n/**\n * Match filter operators against a single value (in-memory).\n */\nexport function matchFilterOperators(itemValue: unknown, operators: FilterOperators): boolean {\n for (const [op, val] of Object.entries(operators)) {\n if (val === undefined) continue\n\n switch (op) {\n case '$eq':\n if (val === null) {\n if (itemValue !== null && itemValue !== undefined) return false\n } else if (itemValue !== val) return false\n break\n\n case '$ne':\n if (val === null) {\n if (itemValue === null || itemValue === undefined) return false\n } else if (itemValue === val) return false\n break\n\n case '$gt':\n if (typeof itemValue !== 'number' && typeof itemValue !== 'string') return false\n if (!(itemValue > val)) return false\n break\n\n case '$gte':\n if (typeof itemValue !== 'number' && typeof itemValue !== 'string') return false\n if (!(itemValue >= val)) return false\n break\n\n case '$lt':\n if (typeof itemValue !== 'number' && typeof itemValue !== 'string') return false\n if (!(itemValue < val)) return false\n break\n\n case '$lte':\n if (typeof itemValue !== 'number' && typeof itemValue !== 'string') return false\n if (!(itemValue <= val)) return false\n break\n\n case '$contains':\n if (typeof itemValue !== 'string' || typeof val !== 'string') return false\n if (!itemValue.toLowerCase().includes(val.toLowerCase())) return false\n break\n\n case '$startswith':\n if (typeof itemValue !== 'string' || typeof val !== 'string') return false\n if (!itemValue.toLowerCase().startsWith(val.toLowerCase())) return false\n break\n\n case '$endswith':\n if (typeof itemValue !== 'string' || typeof val !== 'string') return false\n if (!itemValue.toLowerCase().endsWith(val.toLowerCase())) return false\n break\n\n case '$in':\n if (!Array.isArray(val) || val.length === 0) break\n if (!val.includes(itemValue)) return false\n break\n\n case '$nin':\n if (!Array.isArray(val) || val.length === 0) break\n if (val.includes(itemValue)) return false\n break\n\n case '$isnull':\n if (val === true && itemValue !== null && itemValue !== undefined) return false\n if (val === false && (itemValue === null || itemValue === undefined)) return false\n break\n\n case '$between':\n if (!Array.isArray(val) || val.length !== 2) break\n if (typeof itemValue !== 'number' && typeof itemValue !== 'string') return false\n if (!(itemValue >= val[0] && itemValue <= val[1])) return false\n break\n }\n }\n return true\n}\n","/**\n * In-Memory adapter with TTL support.\n *\n * Used exclusively by TempService for temporary entities with automatic expiration.\n * Persistent entities (collection, reference, etc.) use Knex SQLite :memory: instead.\n */\n\nimport type {\n DatabaseAdapter,\n PaginatedResult,\n EntityQuery,\n ServerEntityQuery\n} from '@gzl10/nexus-sdk'\nimport { applyInMemoryFilters } from './filter-helpers.js'\n\nconst DEFAULT_PAGE = 1\nconst DEFAULT_LIMIT = 20\nconst DEFAULT_MAX_LIMIT = 10000\n\nfunction generateId(): string {\n return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, c => {\n const r = Math.random() * 16 | 0\n const v = c === 'x' ? r : (r & 0x3 | 0x8)\n return v.toString(16)\n })\n}\n\ninterface StoredRecord {\n id: string\n created_at: string\n updated_at: string\n [key: string]: unknown\n}\n\ninterface TtlMetadata {\n expiresAt: number\n timerId: ReturnType<typeof setTimeout>\n}\n\nexport class InMemoryAdapter implements DatabaseAdapter {\n private tables: Map<string, Map<string, StoredRecord>> = new Map()\n private ttlMap: Map<string, TtlMetadata> = new Map()\n\n get raw(): unknown {\n return this.tables\n }\n\n clear(): void {\n for (const metadata of this.ttlMap.values()) {\n clearTimeout(metadata.timerId)\n }\n this.ttlMap.clear()\n this.tables.clear()\n }\n\n clearTable(table: string): void {\n this.tables.delete(table)\n }\n\n seed<T extends Record<string, unknown>>(table: string, records: T[]): void {\n const tableData = this.getOrCreateTable(table)\n for (const record of records) {\n const id = (record['id'] as string) || generateId()\n const now = new Date().toISOString()\n tableData.set(id, {\n ...record,\n id,\n created_at: (record['created_at'] as string) || now,\n updated_at: (record['updated_at'] as string) || now\n })\n }\n }\n\n private getOrCreateTable(table: string): Map<string, StoredRecord> {\n let tableData = this.tables.get(table)\n if (!tableData) {\n tableData = new Map()\n this.tables.set(table, tableData)\n }\n return tableData\n }\n\n // ---- DatabaseAdapter interface ----\n\n async findMany<T = unknown>(table: string, query?: ServerEntityQuery): Promise<PaginatedResult<T>> {\n const maxLimit = query?.maxLimit ?? DEFAULT_MAX_LIMIT\n const page = Math.max(1, query?.page ?? DEFAULT_PAGE)\n const limit = Math.min(maxLimit, Math.max(1, query?.limit ?? DEFAULT_LIMIT))\n const offset = (page - 1) * limit\n\n const tableData = this.tables.get(table)\n if (!tableData) {\n return { items: [], total: 0, page, limit, totalPages: 0, hasNext: false }\n }\n\n let items = Array.from(tableData.values()) as T[]\n\n // Apply filters\n if (query?.filters) {\n items = applyInMemoryFilters(items, query.filters)\n }\n\n // Basic sorting\n if (query?.sort) {\n const sortField = query.sort\n const order = query.order ?? 'asc'\n items.sort((a, b) => {\n const aVal = (a as Record<string, unknown>)[sortField]\n const bVal = (b as Record<string, unknown>)[sortField]\n if (aVal === bVal) return 0\n if (aVal === null || aVal === undefined) return 1\n if (bVal === null || bVal === undefined) return -1\n const comparison = aVal < bVal ? -1 : 1\n return order === 'asc' ? comparison : -comparison\n })\n }\n\n const total = items.length\n items = items.slice(offset, offset + limit)\n const totalPages = Math.ceil(total / limit)\n\n return { items, total, page, limit, totalPages, hasNext: page < totalPages }\n }\n\n async findOne<T = unknown>(table: string, filters: Record<string, unknown>): Promise<T | null> {\n const tableData = this.tables.get(table)\n if (!tableData) return null\n for (const record of tableData.values()) {\n const match = Object.entries(filters).every(([k, v]) => record[k] === v)\n if (match) return record as T\n }\n return null\n }\n\n async findById<T = unknown>(table: string, id: string): Promise<T | null> {\n const tableData = this.tables.get(table)\n if (!tableData) return null\n return (tableData.get(id) as T) ?? null\n }\n\n async count(table: string, filters?: Record<string, unknown>): Promise<number> {\n const tableData = this.tables.get(table)\n if (!tableData) return 0\n if (!filters || Object.keys(filters).length === 0) return tableData.size\n const items = applyInMemoryFilters(Array.from(tableData.values()), filters)\n return items.length\n }\n\n async insert<T = unknown>(table: string, data: Record<string, unknown>): Promise<T> {\n const tableData = this.getOrCreateTable(table)\n const id = (data['id'] as string) || generateId()\n const now = new Date().toISOString()\n const record: StoredRecord = { ...data, id, created_at: now, updated_at: now }\n tableData.set(id, record)\n return record as T\n }\n\n async update<T = unknown>(table: string, id: string, data: Record<string, unknown>): Promise<T> {\n const tableData = this.tables.get(table)\n if (!tableData) throw new Error(`Table \"${table}\" not found`)\n const existing = tableData.get(id)\n if (!existing) throw new Error(`Record \"${id}\" not found in table \"${table}\"`)\n const updated: StoredRecord = {\n ...existing, ...data,\n id,\n created_at: existing.created_at,\n updated_at: new Date().toISOString()\n }\n tableData.set(id, updated)\n return updated as T\n }\n\n async delete(table: string, id: string): Promise<boolean> {\n const tableData = this.tables.get(table)\n if (!tableData) return false\n return tableData.delete(id)\n }\n\n async transaction<T>(fn: (trx: DatabaseAdapter) => Promise<T>): Promise<T> {\n return fn(this)\n }\n\n // ---- TTL Methods ----\n\n private getTtlKey(table: string, id: string): string {\n return `${table}:${id}`\n }\n\n async insertWithTtl<T = unknown>(table: string, data: Record<string, unknown>, ttlSeconds: number): Promise<T> {\n const tableData = this.getOrCreateTable(table)\n const id = (data['id'] as string) || generateId()\n const now = new Date().toISOString()\n const expires_at = new Date(Date.now() + ttlSeconds * 1000).toISOString()\n const record: StoredRecord = { ...data, id, created_at: now, updated_at: now, expires_at }\n tableData.set(id, record)\n\n const ttlKey = this.getTtlKey(table, id)\n const timerId = setTimeout(() => this.deleteWithTtlCleanup(table, id), ttlSeconds * 1000)\n this.ttlMap.set(ttlKey, { expiresAt: Date.now() + ttlSeconds * 1000, timerId })\n\n return record as T\n }\n\n private deleteWithTtlCleanup(table: string, id: string): void {\n const tableData = this.tables.get(table)\n if (tableData) tableData.delete(id)\n const ttlKey = this.getTtlKey(table, id)\n const metadata = this.ttlMap.get(ttlKey)\n if (metadata) {\n clearTimeout(metadata.timerId)\n this.ttlMap.delete(ttlKey)\n }\n }\n\n async setTtl(table: string, id: string, ttlSeconds: number): Promise<boolean> {\n const tableData = this.tables.get(table)\n if (!tableData) return false\n const record = tableData.get(id)\n if (!record) return false\n\n record['expires_at'] = new Date(Date.now() + ttlSeconds * 1000).toISOString()\n record['updated_at'] = new Date().toISOString()\n\n const ttlKey = this.getTtlKey(table, id)\n const existing = this.ttlMap.get(ttlKey)\n if (existing) clearTimeout(existing.timerId)\n\n const timerId = setTimeout(() => this.deleteWithTtlCleanup(table, id), ttlSeconds * 1000)\n this.ttlMap.set(ttlKey, { expiresAt: Date.now() + ttlSeconds * 1000, timerId })\n return true\n }\n\n async getTtl(table: string, id: string): Promise<number> {\n const tableData = this.tables.get(table)\n if (!tableData || !tableData.has(id)) return -2\n\n const ttlKey = this.getTtlKey(table, id)\n const metadata = this.ttlMap.get(ttlKey)\n if (!metadata) return -1\n\n const remainingMs = metadata.expiresAt - Date.now()\n return remainingMs <= 0 ? -2 : Math.ceil(remainingMs / 1000)\n }\n\n async cleanupExpiredIds(_table: string): Promise<number> {\n return 0\n }\n}\n\nexport function createInMemoryAdapter(): InMemoryAdapter {\n return new InMemoryAdapter()\n}\n","/**\n * LRU Cache - Least Recently Used cache with TTL support\n *\n * Features:\n * - LRU eviction when max entries reached\n * - TTL expiration per entry\n * - Hit/miss statistics\n * - Prefix-based deletion for invalidation\n */\n\nimport type { CacheStats } from '@gzl10/nexus-sdk'\nexport type { CacheStats }\n\ninterface CacheEntry<T> {\n data: T\n expires: number\n}\n\nexport interface LRUCacheOptions {\n /** Maximum number of entries (default: 100) */\n maxEntries?: number\n /** Default TTL in seconds (default: 60) */\n defaultTTL?: number\n}\n\nexport class LRUCache<T = unknown> {\n private cache: Map<string, CacheEntry<T>>\n private readonly maxEntries: number\n private readonly defaultTTL: number\n\n private hits = 0\n private misses = 0\n\n constructor(options?: LRUCacheOptions) {\n this.cache = new Map()\n this.maxEntries = options?.maxEntries ?? 100\n this.defaultTTL = options?.defaultTTL ?? 60\n }\n\n /**\n * Get value from cache\n * Returns null if not found or expired\n * Moves entry to end (most recently used)\n */\n get(key: string): T | null {\n const entry = this.cache.get(key)\n\n if (!entry) {\n this.misses++\n return null\n }\n\n // Check expiration\n if (entry.expires > 0 && entry.expires < Date.now()) {\n this.cache.delete(key)\n this.misses++\n return null\n }\n\n // Move to end (most recently used)\n this.cache.delete(key)\n this.cache.set(key, entry)\n\n this.hits++\n return entry.data\n }\n\n /**\n * Set value in cache\n * Evicts oldest entry if max entries reached\n * @param ttl TTL in seconds (0 = no expiration, undefined = use default)\n */\n set(key: string, data: T, ttl?: number): void {\n // Delete existing to update position\n this.cache.delete(key)\n\n // Evict oldest if at capacity\n if (this.cache.size >= this.maxEntries) {\n const oldestKey = this.cache.keys().next().value\n if (oldestKey) {\n this.cache.delete(oldestKey)\n }\n }\n\n const actualTTL = ttl ?? this.defaultTTL\n const expires = actualTTL > 0 ? Date.now() + actualTTL * 1000 : 0\n\n this.cache.set(key, { data, expires })\n }\n\n /**\n * Delete specific key\n */\n delete(key: string): boolean {\n return this.cache.delete(key)\n }\n\n /**\n * Delete all keys matching prefix\n * @returns Number of deleted entries\n */\n deleteByPrefix(prefix: string): number {\n let deleted = 0\n for (const key of this.cache.keys()) {\n if (key.startsWith(prefix)) {\n this.cache.delete(key)\n deleted++\n }\n }\n return deleted\n }\n\n /**\n * Clear all entries\n */\n clear(): void {\n this.cache.clear()\n }\n\n /**\n * Check if key exists and is not expired\n */\n has(key: string): boolean {\n const entry = this.cache.get(key)\n if (!entry) return false\n if (entry.expires > 0 && entry.expires < Date.now()) {\n this.cache.delete(key)\n return false\n }\n return true\n }\n\n /**\n * Get current size\n */\n get size(): number {\n return this.cache.size\n }\n\n /**\n * Get cache statistics\n */\n getStats(): CacheStats {\n const total = this.hits + this.misses\n return {\n hits: this.hits,\n misses: this.misses,\n hitRate: total > 0 ? this.hits / total : 0,\n size: this.cache.size,\n maxEntries: this.maxEntries\n }\n }\n\n /**\n * Reset statistics\n */\n resetStats(): void {\n this.hits = 0\n this.misses = 0\n }\n\n /**\n * Prune expired entries\n * Call periodically to clean up memory\n */\n prune(): number {\n const now = Date.now()\n let pruned = 0\n\n for (const [key, entry] of this.cache.entries()) {\n if (entry.expires > 0 && entry.expires < now) {\n this.cache.delete(key)\n pruned++\n }\n }\n\n return pruned\n }\n}\n","import type { ManagedCache, CacheOptions, CacheStats } from '@gzl10/nexus-sdk'\nimport { LRUCache } from './lru-cache.js'\n\n/**\n * Thin wrapper over LRUCache implementing the ManagedCache SDK contract.\n * Adds name tracking and delegates to addRules callback for invalidation.\n */\nexport class ManagedCacheImpl<T = unknown> implements ManagedCache<T> {\n private cache: LRUCache<T>\n private onAddRules?: (events: string[]) => void\n\n constructor(\n public readonly name: string,\n options?: CacheOptions,\n onAddRules?: (events: string[]) => void\n ) {\n this.cache = new LRUCache<T>({\n maxEntries: options?.maxEntries,\n defaultTTL: options?.defaultTTL\n })\n this.onAddRules = onAddRules\n }\n\n async get(key: string): Promise<T | null> {\n return this.cache.get(key)\n }\n\n async set(key: string, value: T, ttl?: number): Promise<void> {\n this.cache.set(key, value, ttl)\n }\n\n async delete(key: string): Promise<boolean> {\n return this.cache.delete(key)\n }\n\n async deleteByPrefix(prefix: string): Promise<number> {\n return this.cache.deleteByPrefix(prefix)\n }\n\n async has(key: string): Promise<boolean> {\n return this.cache.has(key)\n }\n\n async clear(): Promise<void> {\n this.cache.clear()\n }\n\n getStats(): CacheStats {\n return this.cache.getStats()\n }\n\n resetStats(): void {\n this.cache.resetStats()\n }\n\n addInvalidationRules(events: string[]): void {\n this.onAddRules?.(events)\n }\n\n async prune(): Promise<number> {\n return this.cache.prune()\n }\n\n async getSize(): Promise<number> {\n return this.cache.size\n }\n}\n","/**\n * Query builder helpers for common operations\n */\nimport type { Knex } from 'knex'\nimport type { EntityDefinition, EntityQuery, ServerEntityQuery, PaginatedResult } from '@gzl10/nexus-sdk'\n\nconst DEFAULT_PAGE = 1\nconst DEFAULT_LIMIT = 20\nexport const DEFAULT_MAX_LIMIT = 100\n\nexport interface PaginationParams {\n page: number\n limit: number\n offset: number\n}\n\n/**\n * Extract pagination parameters from query.\n * Validates and normalizes page/limit values.\n */\nexport function getPagination(query?: ServerEntityQuery): PaginationParams {\n const maxLimit = query?.maxLimit ?? DEFAULT_MAX_LIMIT\n const page = Math.max(1, query?.page ?? DEFAULT_PAGE)\n const limit = Math.min(maxLimit, Math.max(1, query?.limit ?? DEFAULT_LIMIT))\n const offset = (page - 1) * limit\n return { page, limit, offset }\n}\n\n/**\n * Build a PaginatedResult from items and total count.\n */\nexport function buildPaginatedResult<T>(\n items: T[],\n total: number,\n pagination: PaginationParams\n): PaginatedResult<T> {\n const { page, limit } = pagination\n const totalPages = Math.ceil(total / limit)\n return {\n items,\n total,\n page,\n limit,\n totalPages,\n hasNext: page < totalPages\n }\n}\n\n/**\n * Get searchable field names from entity definition\n */\nexport function getSearchableFields(definition: EntityDefinition): string[] {\n return Object.entries(definition.fields ?? {})\n .filter(([_, f]) => f.meta?.searchable === true)\n .map(([name]) => name)\n}\n\n/**\n * Apply search filter to query builder based on entity definition.\n * Searches in fields with meta.searchable: true, or falls back to labelField.\n */\nexport function applySearchFilter(\n qb: Knex.QueryBuilder,\n definition: EntityDefinition,\n search: string\n): Knex.QueryBuilder {\n const searchableFields = getSearchableFields(definition)\n\n // Fallback to labelField if no searchable fields\n if (searchableFields.length === 0 && 'labelField' in definition && definition.labelField) {\n searchableFields.push(definition.labelField as string)\n }\n\n // Apply OR search across all searchable fields\n if (searchableFields.length > 0) {\n const searchPattern = `%${search}%`\n qb.where(function () {\n for (const field of searchableFields) {\n this.orWhere(field, 'like', searchPattern)\n }\n })\n }\n\n return qb\n}\n","/**\n * Error codes for i18n-friendly error handling.\n * Frontend translates these codes to localized messages.\n *\n * Format: CATEGORY_ACTION_REASON\n *\n * Categories: AUTH, USER, ROLE, VALIDATION, STORAGE, PERMISSION, RESOURCE, SYSTEM\n */\nexport const ErrorCodes = {\n // Auth\n AUTH_INVALID_CREDENTIALS: 'AUTH_INVALID_CREDENTIALS',\n AUTH_TOKEN_EXPIRED: 'AUTH_TOKEN_EXPIRED',\n AUTH_TOKEN_INVALID: 'AUTH_TOKEN_INVALID',\n AUTH_TOKEN_REQUIRED: 'AUTH_TOKEN_REQUIRED',\n AUTH_OTP_REQUIRED: 'AUTH_OTP_REQUIRED',\n AUTH_OTP_INVALID: 'AUTH_OTP_INVALID',\n AUTH_REFRESH_TOKEN_REQUIRED: 'AUTH_REFRESH_TOKEN_REQUIRED',\n AUTH_REFRESH_TOKEN_INVALID: 'AUTH_REFRESH_TOKEN_INVALID',\n AUTH_REFRESH_TOKEN_EXPIRED: 'AUTH_REFRESH_TOKEN_EXPIRED',\n AUTH_SESSION_NOT_FOUND: 'AUTH_SESSION_NOT_FOUND',\n AUTH_SESSION_SELF_REVOKE: 'AUTH_SESSION_SELF_REVOKE',\n AUTH_VERIFICATION_CODE_INVALID: 'AUTH_VERIFICATION_CODE_INVALID',\n AUTH_REGISTRATION_DISABLED: 'AUTH_REGISTRATION_DISABLED',\n AUTH_AUTO_CREATE_DISABLED: 'AUTH_AUTO_CREATE_DISABLED',\n\n // User\n USER_NOT_FOUND: 'USER_NOT_FOUND',\n USER_EMAIL_EXISTS: 'USER_EMAIL_EXISTS',\n USER_NOT_AUTHENTICATED: 'USER_NOT_AUTHENTICATED',\n\n // Role\n ROLE_NOT_FOUND: 'ROLE_NOT_FOUND',\n ROLE_NAME_EXISTS: 'ROLE_NAME_EXISTS',\n ROLE_SYSTEM_PROTECTED: 'ROLE_SYSTEM_PROTECTED',\n ROLE_HAS_USERS: 'ROLE_HAS_USERS',\n ROLE_DEFAULT_NOT_FOUND: 'ROLE_DEFAULT_NOT_FOUND',\n\n // Permission\n PERMISSION_DENIED: 'PERMISSION_DENIED',\n\n // Validation\n VALIDATION_ERROR: 'VALIDATION_ERROR',\n VALIDATION_FIELD_REQUIRED: 'VALIDATION_FIELD_REQUIRED',\n VALIDATION_FIELD_INVALID: 'VALIDATION_FIELD_INVALID',\n VALIDATION_JSON_MALFORMED: 'VALIDATION_JSON_MALFORMED',\n\n // Storage\n STORAGE_FILE_NOT_FOUND: 'STORAGE_FILE_NOT_FOUND',\n STORAGE_FILE_TOO_LARGE: 'STORAGE_FILE_TOO_LARGE',\n STORAGE_FILE_TYPE_NOT_ALLOWED: 'STORAGE_FILE_TYPE_NOT_ALLOWED',\n STORAGE_PAYLOAD_TOO_LARGE: 'STORAGE_PAYLOAD_TOO_LARGE',\n\n // Resource (generic)\n RESOURCE_NOT_FOUND: 'RESOURCE_NOT_FOUND',\n RESOURCE_CONFLICT: 'RESOURCE_CONFLICT',\n RESOURCE_CREATE_NOT_SUPPORTED: 'RESOURCE_CREATE_NOT_SUPPORTED',\n RESOURCE_UPDATE_NOT_SUPPORTED: 'RESOURCE_UPDATE_NOT_SUPPORTED',\n RESOURCE_DELETE_NOT_SUPPORTED: 'RESOURCE_DELETE_NOT_SUPPORTED',\n\n // Module\n MODULE_NOT_FOUND: 'MODULE_NOT_FOUND',\n\n // HTTP standard\n NOT_FOUND: 'NOT_FOUND',\n AUTH_UNAUTHORIZED: 'AUTH_UNAUTHORIZED',\n\n // Database\n DB_CONSTRAINT_UNIQUE: 'DB_CONSTRAINT_UNIQUE',\n DB_CONSTRAINT_FK: 'DB_CONSTRAINT_FK',\n DB_CONNECTION_ERROR: 'DB_CONNECTION_ERROR',\n DATABASE_NOT_READY: 'DATABASE_NOT_READY',\n\n // System\n SYSTEM_INTERNAL_ERROR: 'SYSTEM_INTERNAL_ERROR',\n} as const\n\nexport type ErrorCode = typeof ErrorCodes[keyof typeof ErrorCodes]\n","import type { Knex } from 'knex'\n\n/**\n * Creates minimal core tables in SQLite :memory: for plugin integration tests.\n * Only includes columns that other tables reference via FK.\n * Call before runGeneratedMigration() in plugin tests.\n */\nexport async function createCoreTables(db: Knex): Promise<void> {\n if (!await db.schema.hasTable('users')) {\n await db.schema.createTable('users', (t) => {\n t.string('id', 26).primary()\n t.string('name', 100).notNullable()\n t.string('email', 255).notNullable()\n t.string('role', 20).notNullable().defaultTo('user')\n t.timestamps(true, true)\n })\n }\n\n if (!await db.schema.hasTable('roles')) {\n await db.schema.createTable('roles', (t) => {\n t.string('id', 26).primary()\n t.string('name', 50).notNullable()\n })\n }\n}\n","import type { ErrorCode } from './error-codes.js'\nimport { ErrorCodes } from './error-codes.js'\n\n/**\n * Parameters for creating an AppError with i18n support\n */\nexport interface AppErrorParams {\n /** Error code for i18n translation (e.g., 'AUTH_INVALID_CREDENTIALS') */\n code: ErrorCode\n /** Fallback message in English (used if frontend doesn't have translation) */\n message?: string\n /** Interpolation values for the translated message (e.g., { resource: 'User' }) */\n interpolation?: Record<string, string | number>\n}\n\n/**\n * Base application error with i18n support.\n *\n * Can be created with:\n * - String message (legacy, backward compatible)\n * - AppErrorParams object (new, with code and interpolation)\n *\n * @example\n * // Legacy usage\n * throw new AppError('Something went wrong', 400)\n *\n * // New usage with i18n\n * throw new AppError({\n * code: ErrorCodes.USER_NOT_FOUND,\n * message: 'User not found',\n * interpolation: { resource: 'User' }\n * }, 404)\n */\nexport class AppError extends Error {\n public readonly statusCode: number\n public readonly code: ErrorCode\n public readonly interpolation?: Record<string, string | number>\n public readonly details?: unknown\n\n constructor(\n params: AppErrorParams | string,\n statusCode: number = 400,\n details?: unknown\n ) {\n if (typeof params === 'string') {\n // Legacy: string message (backward compatible)\n super(params)\n this.code = ErrorCodes.SYSTEM_INTERNAL_ERROR\n } else {\n // New: structured params with code\n super(params.message || params.code)\n this.code = params.code\n this.interpolation = params.interpolation\n }\n\n this.statusCode = statusCode\n this.details = details\n this.name = 'AppError'\n Error.captureStackTrace(this, this.constructor)\n }\n}\n\n/**\n * Resource not found error (404)\n */\nexport class NotFoundError extends AppError {\n constructor(resource: string = 'Resource') {\n super({\n code: ErrorCodes.RESOURCE_NOT_FOUND,\n message: `${resource} not found`,\n interpolation: { resource }\n }, 404)\n this.name = 'NotFoundError'\n }\n}\n\n/**\n * Authentication required error (401)\n */\nexport class UnauthorizedError extends AppError {\n constructor(codeOrMessage: ErrorCode | string = ErrorCodes.AUTH_TOKEN_REQUIRED, message?: string) {\n // Check if first param is an ErrorCode\n const isCode = Object.values(ErrorCodes).includes(codeOrMessage as ErrorCode)\n\n if (isCode) {\n super({\n code: codeOrMessage as ErrorCode,\n message: message || 'Unauthorized'\n }, 401)\n } else {\n // Legacy: string message\n super({\n code: ErrorCodes.AUTH_TOKEN_REQUIRED,\n message: codeOrMessage as string\n }, 401)\n }\n this.name = 'UnauthorizedError'\n }\n}\n\n/**\n * Access denied error (403)\n */\nexport class ForbiddenError extends AppError {\n constructor(codeOrMessage: ErrorCode | string = ErrorCodes.PERMISSION_DENIED, message?: string) {\n const isCode = Object.values(ErrorCodes).includes(codeOrMessage as ErrorCode)\n\n if (isCode) {\n super({\n code: codeOrMessage as ErrorCode,\n message: message || 'Access denied'\n }, 403)\n } else {\n super({\n code: ErrorCodes.PERMISSION_DENIED,\n message: codeOrMessage as string\n }, 403)\n }\n this.name = 'ForbiddenError'\n }\n}\n\n/**\n * Resource conflict error (409)\n */\nexport class ConflictError extends AppError {\n constructor(codeOrMessage: ErrorCode | string = ErrorCodes.RESOURCE_CONFLICT, message?: string) {\n const isCode = Object.values(ErrorCodes).includes(codeOrMessage as ErrorCode)\n\n if (isCode) {\n super({\n code: codeOrMessage as ErrorCode,\n message: message || 'Conflict'\n }, 409)\n } else {\n super({\n code: ErrorCodes.RESOURCE_CONFLICT,\n message: codeOrMessage as string\n }, 409)\n }\n this.name = 'ConflictError'\n }\n}\n\n/**\n * Standard validation error detail\n */\nexport interface ValidationDetail {\n path: string\n message: string\n /** Error code for i18n translation */\n code?: string\n /** Interpolation values */\n interpolation?: Record<string, string | number>\n}\n\n/**\n * Validation error with field-level details (400)\n */\nexport class ValidationError extends AppError {\n public override readonly details: ValidationDetail[]\n\n constructor(messageOrCode: string | ErrorCode = ErrorCodes.VALIDATION_ERROR, details: ValidationDetail[] = []) {\n const isCode = Object.values(ErrorCodes).includes(messageOrCode as ErrorCode)\n\n if (isCode) {\n super({\n code: messageOrCode as ErrorCode,\n message: 'Validation error'\n }, 400)\n } else {\n super({\n code: ErrorCodes.VALIDATION_ERROR,\n message: messageOrCode as string\n }, 400)\n }\n\n this.name = 'ValidationError'\n this.details = details\n }\n}\n\n// Re-export ErrorCodes for convenience\nexport { ErrorCodes } from './error-codes.js'\nexport type { ErrorCode } from './error-codes.js'\n","import knex, { type Knex } from 'knex'\n\nexport type { Knex }\n\n/**\n * Creates a Knex instance with SQLite :memory: for integration tests.\n * Plugins should use this instead of importing knex/better-sqlite3 directly.\n */\nexport function createTestDb(): Knex {\n return knex({\n client: 'better-sqlite3',\n connection: ':memory:',\n useNullAsDefault: true\n })\n}\n"],"mappings":"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","names":["DEFAULT_PAGE","DEFAULT_LIMIT","DEFAULT_MAX_LIMIT","data","AppError","NotFoundError","UnauthorizedError","ForbiddenError","ConflictError","ValidationError"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gzl10/nexus-backend",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.20.0",
|
|
4
4
|
"description": "Backend as a Service (BaaS) with Express 5, Knex and CASL",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -105,7 +105,7 @@
|
|
|
105
105
|
"socket.io": "^4.8.3",
|
|
106
106
|
"ulidx": "^2.4.1",
|
|
107
107
|
"zod": "^3.24.0",
|
|
108
|
-
"@gzl10/nexus-sdk": "0.
|
|
108
|
+
"@gzl10/nexus-sdk": "0.20.0"
|
|
109
109
|
},
|
|
110
110
|
"devDependencies": {
|
|
111
111
|
"@types/bcryptjs": "^2.4.0",
|