@happyvertical/smrt-core 0.42.6 → 0.43.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.
Files changed (134) hide show
  1. package/AGENTS.md +39 -43
  2. package/agents/collection-reads.md +40 -0
  3. package/agents/data-query.md +21 -0
  4. package/agents/latest-related.md +35 -0
  5. package/agents/memory.md +16 -0
  6. package/agents/schema-paths.md +29 -15
  7. package/dist/browser.js +2 -2
  8. package/dist/cascade.d.ts +7 -6
  9. package/dist/cascade.d.ts.map +1 -1
  10. package/dist/cascade.js +19 -21
  11. package/dist/cascade.js.map +1 -1
  12. package/dist/class.d.ts +17 -0
  13. package/dist/class.d.ts.map +1 -1
  14. package/dist/class.js +30 -0
  15. package/dist/class.js.map +1 -1
  16. package/dist/collection.d.ts +164 -3
  17. package/dist/collection.d.ts.map +1 -1
  18. package/dist/collection.js +345 -10
  19. package/dist/collection.js.map +1 -1
  20. package/dist/decorators/index.d.ts +33 -15
  21. package/dist/decorators/index.d.ts.map +1 -1
  22. package/dist/decorators/index.js +16 -11
  23. package/dist/decorators/index.js.map +1 -1
  24. package/dist/generators/rest.d.ts.map +1 -1
  25. package/dist/generators/rest.js +10 -2
  26. package/dist/generators/rest.js.map +1 -1
  27. package/dist/generators/tool-schema.d.ts +14 -0
  28. package/dist/generators/tool-schema.d.ts.map +1 -1
  29. package/dist/generators/tool-schema.js +13 -1
  30. package/dist/generators/tool-schema.js.map +1 -1
  31. package/dist/index.d.ts +1 -0
  32. package/dist/index.d.ts.map +1 -1
  33. package/dist/index.js +3 -2
  34. package/dist/interceptors.d.ts +2 -1
  35. package/dist/interceptors.d.ts.map +1 -1
  36. package/dist/interceptors.js.map +1 -1
  37. package/dist/manifest/static-manifest.d.ts.map +1 -1
  38. package/dist/manifest/static-manifest.js +53 -1
  39. package/dist/manifest/static-manifest.js.map +1 -1
  40. package/dist/manifest/store.js +1 -1
  41. package/dist/manifest/store.js.map +1 -1
  42. package/dist/manifest.json +62 -1
  43. package/dist/migrations/differ.d.ts +2 -0
  44. package/dist/migrations/differ.d.ts.map +1 -1
  45. package/dist/migrations/differ.js +75 -0
  46. package/dist/migrations/differ.js.map +1 -1
  47. package/dist/migrations/generator.d.ts.map +1 -1
  48. package/dist/migrations/generator.js +19 -2
  49. package/dist/migrations/generator.js.map +1 -1
  50. package/dist/migrations/orchestrate.d.ts.map +1 -1
  51. package/dist/migrations/orchestrate.js +4 -1
  52. package/dist/migrations/orchestrate.js.map +1 -1
  53. package/dist/object.d.ts +4 -4
  54. package/dist/object.js +4 -4
  55. package/dist/object.js.map +1 -1
  56. package/dist/prebuild/index.d.ts.map +1 -1
  57. package/dist/prebuild/index.js +9 -0
  58. package/dist/prebuild/index.js.map +1 -1
  59. package/dist/registry/schema-builder.d.ts +6 -0
  60. package/dist/registry/schema-builder.d.ts.map +1 -1
  61. package/dist/registry/schema-builder.js +78 -8
  62. package/dist/registry/schema-builder.js.map +1 -1
  63. package/dist/registry.d.ts +5 -7
  64. package/dist/registry.d.ts.map +1 -1
  65. package/dist/registry.js +6 -8
  66. package/dist/registry.js.map +1 -1
  67. package/dist/runtime/types.d.ts +2 -2
  68. package/dist/runtime/types.d.ts.map +1 -1
  69. package/dist/scanner/manifest-generator.d.ts.map +1 -1
  70. package/dist/scanner/manifest-generator.js +62 -18
  71. package/dist/scanner/manifest-generator.js.map +1 -1
  72. package/dist/scanner/types.d.ts +5 -1
  73. package/dist/scanner/types.d.ts.map +1 -1
  74. package/dist/scanner/types.js.map +1 -1
  75. package/dist/schema/ddl/base-strategy.d.ts.map +1 -1
  76. package/dist/schema/ddl/base-strategy.js +2 -0
  77. package/dist/schema/ddl/base-strategy.js.map +1 -1
  78. package/dist/schema/ddl/duckdb-strategy.d.ts +1 -0
  79. package/dist/schema/ddl/duckdb-strategy.d.ts.map +1 -1
  80. package/dist/schema/ddl/duckdb-strategy.js +17 -1
  81. package/dist/schema/ddl/duckdb-strategy.js.map +1 -1
  82. package/dist/schema/ddl/postgres-strategy.js +1 -1
  83. package/dist/schema/foreign-key-ddl.d.ts +9 -0
  84. package/dist/schema/foreign-key-ddl.d.ts.map +1 -0
  85. package/dist/schema/foreign-key-ddl.js +53 -0
  86. package/dist/schema/foreign-key-ddl.js.map +1 -0
  87. package/dist/schema/foreign-key-planner.d.ts +18 -0
  88. package/dist/schema/foreign-key-planner.d.ts.map +1 -0
  89. package/dist/schema/foreign-key-planner.js +109 -0
  90. package/dist/schema/foreign-key-planner.js.map +1 -0
  91. package/dist/schema/foreign-key-policy.d.ts +21 -0
  92. package/dist/schema/foreign-key-policy.d.ts.map +1 -0
  93. package/dist/schema/foreign-key-policy.js +41 -0
  94. package/dist/schema/foreign-key-policy.js.map +1 -0
  95. package/dist/schema/generator.d.ts +3 -0
  96. package/dist/schema/generator.d.ts.map +1 -1
  97. package/dist/schema/generator.js +54 -10
  98. package/dist/schema/generator.js.map +1 -1
  99. package/dist/schema/index.d.ts +3 -0
  100. package/dist/schema/index.d.ts.map +1 -1
  101. package/dist/schema/index.js +4 -1
  102. package/dist/schema/manifest-schema.d.ts.map +1 -1
  103. package/dist/schema/manifest-schema.js +20 -3
  104. package/dist/schema/manifest-schema.js.map +1 -1
  105. package/dist/schema/schema-aggregator.d.ts +7 -1
  106. package/dist/schema/schema-aggregator.d.ts.map +1 -1
  107. package/dist/schema/schema-aggregator.js +54 -9
  108. package/dist/schema/schema-aggregator.js.map +1 -1
  109. package/dist/schema/schema-manager.d.ts +1 -6
  110. package/dist/schema/schema-manager.d.ts.map +1 -1
  111. package/dist/schema/schema-manager.js +26 -30
  112. package/dist/schema/schema-manager.js.map +1 -1
  113. package/dist/schema/types.d.ts +8 -5
  114. package/dist/schema/types.d.ts.map +1 -1
  115. package/dist/schema/utils.d.ts.map +1 -1
  116. package/dist/schema/utils.js +14 -1
  117. package/dist/schema/utils.js.map +1 -1
  118. package/dist/schema.js +4 -1
  119. package/dist/smrt-knowledge.json +63 -8
  120. package/dist/testing/database.d.ts +11 -1
  121. package/dist/testing/database.d.ts.map +1 -1
  122. package/dist/testing/database.js +80 -9
  123. package/dist/testing/database.js.map +1 -1
  124. package/dist/vite-plugin/index.d.ts.map +1 -1
  125. package/dist/vite-plugin/index.js +12 -3
  126. package/dist/vite-plugin/index.js.map +1 -1
  127. package/dist/vite-plugin/sveltekit-generator.d.ts.map +1 -1
  128. package/dist/vite-plugin/sveltekit-generator.js +24 -3
  129. package/dist/vite-plugin/sveltekit-generator.js.map +1 -1
  130. package/dist/vite-plugin/web-collections.d.ts +3 -1
  131. package/dist/vite-plugin/web-collections.d.ts.map +1 -1
  132. package/dist/vite-plugin/web-collections.js +24 -4
  133. package/dist/vite-plugin/web-collections.js.map +1 -1
  134. package/package.json +4 -4
@@ -1 +1 @@
1
- {"version":3,"file":"tool-schema.js","names":[],"sources":["../../src/generators/tool-schema.ts"],"sourcesContent":["import {\n buildCustomActionInputSchema,\n type CustomActionMetadata,\n} from './custom-action.js';\n\n/**\n * Transport-agnostic tool-descriptor builder (#1812, tracer).\n *\n * The single source of truth for turning a model's fields + exposed actions into\n * MCP-shaped tool descriptors (`{ name, description, inputSchema }`). This is the\n * shape both the Model Context Protocol AND Chrome's WebMCP\n * (`document.modelContext.registerTool`) consume — see\n * https://developer.chrome.com/docs/ai/webmcp.\n *\n * It is deliberately pure and free of `ObjectRegistry` / manifest coupling: it\n * takes a normalized {@link ToolFieldMeta}[] so BOTH callers can share it —\n * - `MCPGenerator` (`src/generators/mcp.ts`) for the Node stdio server, and\n * - the web-collections emitter (`src/vite-plugin/web-collections.ts`) for the\n * browser client-data runtime's WebMCP descriptors.\n *\n * Keeping one implementation removes the field-mapping drift risk the\n * \"three emission sites must agree\" contract in web-collections.ts already warns\n * about. The `fieldTypeToJsonSchema` / per-action skeletons below are ported\n * verbatim from mcp.ts's `fieldToMCPSchema` + `generateObjectTools`, so wiring\n * mcp.ts to call this helper is a mechanical, behavior-preserving refactor.\n */\n\n/**\n * A JSON Schema fragment. Values vary by field kind, so this is only ever\n * serialized into tool descriptors, never read back structurally.\n */\nexport type ToolJsonSchema = Record<string, unknown>;\n\n/** The only JSON Schema dialect emitted by generated MCP and WebMCP tools. */\nexport const JSON_SCHEMA_2020_12 =\n 'https://json-schema.org/draft/2020-12/schema';\n\n/**\n * Bounds for generated schemas. Field metadata is authored input, so it must\n * not turn a tools/list response into an unbounded composition or validation\n * workload. These limits are deliberately far above normal SMRT objects while\n * still keeping schemas comfortably inside MCP transport budgets.\n */\nexport const MCP_SCHEMA_LIMITS = {\n maxDepth: 16,\n maxNodes: 2_048,\n maxSerializedBytes: 65_536,\n} as const;\n\n/**\n * Apply the draft-2020-12 dialect and reject schemas that violate MCP's\n * bounded-composition contract. Generated schemas only ever reference local\n * `$defs`; external refs are neither emitted nor followed.\n */\nexport function finalizeMcpJsonSchema(schema: ToolJsonSchema): ToolJsonSchema {\n const finalized = {\n ...schema,\n $schema: JSON_SCHEMA_2020_12,\n };\n assertMcpJsonSchemaSafety(finalized);\n return finalized;\n}\n\n/**\n * Validate the resource envelope of an emitted schema without resolving refs.\n * This is intentionally structural rather than a general JSON-Schema\n * evaluator: the server already owns every schema it emits, and this guard\n * exists to keep authored metadata from introducing hostile shape growth.\n */\nexport function assertMcpJsonSchemaSafety(schema: ToolJsonSchema): void {\n let nodes = 0;\n const ancestors = new WeakSet<object>();\n\n const visit = (value: unknown, depth: number, key?: string): void => {\n nodes += 1;\n if (nodes > MCP_SCHEMA_LIMITS.maxNodes) {\n throw new Error(\n `MCP JSON Schema exceeds ${MCP_SCHEMA_LIMITS.maxNodes} nodes`,\n );\n }\n if (depth > MCP_SCHEMA_LIMITS.maxDepth) {\n throw new Error(\n `MCP JSON Schema exceeds ${MCP_SCHEMA_LIMITS.maxDepth} levels of depth`,\n );\n }\n if (key === '$ref') {\n if (\n typeof value !== 'string' ||\n !value.startsWith('#/$defs/') ||\n value.includes('://')\n ) {\n throw new Error(\n 'MCP JSON Schema may only use local #/$defs/ references',\n );\n }\n return;\n }\n if (value === null || typeof value !== 'object') return;\n if (ancestors.has(value)) {\n throw new Error('MCP JSON Schema must not contain cyclic values');\n }\n\n ancestors.add(value);\n if (Array.isArray(value)) {\n for (const entry of value) visit(entry, depth + 1);\n } else {\n for (const [childKey, child] of Object.entries(value)) {\n visit(child, depth + 1, childKey);\n }\n }\n ancestors.delete(value);\n };\n\n visit(schema, 0);\n\n let serialized: string;\n try {\n serialized = JSON.stringify(schema);\n } catch {\n throw new Error('MCP JSON Schema must be JSON-serializable');\n }\n if (\n new TextEncoder().encode(serialized).byteLength >\n MCP_SCHEMA_LIMITS.maxSerializedBytes\n ) {\n throw new Error(\n `MCP JSON Schema exceeds ${MCP_SCHEMA_LIMITS.maxSerializedBytes} serialized bytes`,\n );\n }\n}\n\n/**\n * Normalized field metadata — the intersection of what the runtime registry\n * (`FieldDefinition._meta`) and the build-time manifest (`WebFieldDefinition`)\n * can each supply. Callers flatten their own field source into this shape.\n */\nexport interface ToolFieldMeta {\n name: string;\n /** Field kind: text | integer | decimal | boolean | datetime | json | foreignKey | … */\n type: string;\n required?: boolean;\n description?: string;\n default?: unknown;\n maxLength?: number;\n minLength?: number;\n min?: number;\n max?: number;\n /** Field values may explicitly be null in the runtime/manifest contract. */\n nullable?: boolean;\n /** For `foreignKey`: the related class name, for the generated description. */\n related?: string;\n}\n\n/** Storage contract for the synthetic primary identifier. */\nexport type ToolIdType = 'uuid' | 'text';\n\n/** The CRUD verbs with dedicated input-schema skeletons; anything else is custom. */\nconst CRUD_ACTIONS = new Set(['list', 'get', 'create', 'update', 'delete']);\n\n/** A single generated tool descriptor — the WebMCP / MCP tool shape. */\nexport interface ToolDescriptor {\n /** The action this tool performs (`list` | `get` | … | a custom method name). */\n action: string;\n /** Tool id, `${toolPrefix}_${action}` (e.g. `product_list`). */\n name: string;\n description: string;\n inputSchema: ToolJsonSchema;\n /** True for non-mutating reads (`list`/`get`) → WebMCP `annotations.readOnlyHint`. */\n readOnly: boolean;\n}\n\n/**\n * Map one normalized field to its JSON-Schema fragment. Ported from\n * `MCPGenerator.fieldToMCPSchema` (mcp.ts) — keep the two in lockstep until\n * mcp.ts is switched to call this.\n */\nexport function fieldTypeToJsonSchema(field: ToolFieldMeta): ToolJsonSchema {\n const schema: ToolJsonSchema = {\n description: field.description || `${field.type} field`,\n };\n\n switch (field.type) {\n case 'text':\n schema.type = 'string';\n if (field.maxLength !== undefined) schema.maxLength = field.maxLength;\n if (field.minLength !== undefined) schema.minLength = field.minLength;\n break;\n case 'integer':\n schema.type = 'integer';\n if (field.min !== undefined) schema.minimum = field.min;\n if (field.max !== undefined) schema.maximum = field.max;\n break;\n case 'decimal':\n schema.type = 'number';\n if (field.min !== undefined) schema.minimum = field.min;\n if (field.max !== undefined) schema.maximum = field.max;\n break;\n case 'boolean':\n schema.type = 'boolean';\n break;\n case 'datetime':\n schema.type = 'string';\n schema.format = 'date-time';\n break;\n case 'json':\n schema.type = 'object';\n break;\n case 'foreignKey':\n case 'crossPackageRef':\n schema.type = 'string';\n // The generic relation hint is a fallback only — an authored\n // `@field({ description })` wins (#2046 threads descriptions into web\n // tool descriptors; clobbering them here would strip the help text).\n if (!field.description) {\n schema.description = `ID of related ${field.related || 'object'}`;\n }\n break;\n default:\n schema.type = 'string';\n }\n\n if (field.default !== undefined) {\n schema.default = field.default;\n }\n\n if (field.nullable && typeof schema.type === 'string') {\n schema.type = [schema.type, 'null'];\n }\n\n return schema;\n}\n\nfunction buildFieldProperties(fields: ToolFieldMeta[]): {\n properties: Record<string, ToolJsonSchema>;\n defs: Record<string, ToolJsonSchema>;\n} {\n const properties: Record<string, ToolJsonSchema> = {};\n const defs: Record<string, ToolJsonSchema> = {};\n\n fields.forEach((field, index) => {\n // Numeric keys avoid JSON Pointer escaping and keep output deterministic\n // even for an authored field name containing `/` or `~`.\n const defKey = `field_${index}`;\n defs[defKey] = fieldTypeToJsonSchema(field);\n properties[field.name] = { $ref: `#/$defs/${defKey}` };\n });\n\n return { properties, defs };\n}\n\n/**\n * Build the `inputSchema` for one action. CRUD verbs get the fixed skeletons\n * ported from mcp.ts's `generateObjectTools`; any other action is treated as a\n * custom method taking `{ id, options }`.\n */\nexport function buildToolInputSchema(\n action: string,\n fields: ToolFieldMeta[],\n customAction?: CustomActionMetadata,\n idType: ToolIdType = 'uuid',\n): ToolJsonSchema {\n const identifierSchema = (description: string): ToolJsonSchema => ({\n type: 'string',\n ...(idType === 'uuid' ? { format: 'uuid' } : {}),\n description,\n });\n\n switch (action) {\n case 'list':\n return finalizeMcpJsonSchema({\n type: 'object',\n properties: {\n limit: {\n type: 'integer',\n description: 'Maximum number of items to return',\n default: 50,\n minimum: 1,\n maximum: 1000,\n },\n offset: {\n type: 'integer',\n description: 'Number of items to skip',\n default: 0,\n minimum: 0,\n },\n orderBy: {\n type: 'string',\n description: 'Field to order by (e.g., \"created_at DESC\")',\n },\n where: {\n type: 'object',\n description: 'Filter conditions as key-value pairs',\n additionalProperties: true,\n },\n },\n });\n\n case 'get':\n // Either `id` OR `slug` identifies the object (collection.get resolves\n // both). The schema must require one of them just as the handler does,\n // while still allowing slug-only lookups.\n return finalizeMcpJsonSchema({\n type: 'object',\n anyOf: [{ required: ['id'] }, { required: ['slug'] }],\n properties: {\n id: identifierSchema('Unique identifier of the object'),\n slug: {\n type: 'string',\n description: 'URL-friendly identifier of the object',\n },\n },\n });\n\n case 'create': {\n const { properties, defs } = buildFieldProperties(fields);\n const required: string[] = [];\n for (const field of fields) {\n if (field.required) required.push(field.name);\n }\n return finalizeMcpJsonSchema({\n type: 'object',\n properties,\n ...(required.length > 0 ? { required } : {}),\n ...(Object.keys(defs).length > 0 ? { $defs: defs } : {}),\n });\n }\n\n case 'update': {\n const { properties: fieldProperties, defs } =\n buildFieldProperties(fields);\n const properties: Record<string, ToolJsonSchema> = {\n id: identifierSchema('ID of the object to update'),\n ...fieldProperties,\n };\n return finalizeMcpJsonSchema({\n type: 'object',\n properties,\n required: ['id'],\n ...(Object.keys(defs).length > 0 ? { $defs: defs } : {}),\n });\n }\n\n case 'delete':\n return finalizeMcpJsonSchema({\n type: 'object',\n properties: {\n id: identifierSchema('ID of the object to delete'),\n },\n required: ['id'],\n });\n\n default:\n return finalizeMcpJsonSchema(\n buildCustomActionInputSchema(\n customAction ?? {\n scope: 'item',\n idRequired: true,\n isStatic: false,\n },\n ),\n );\n }\n}\n\n/**\n * Human-readable description for a tool, matching mcp.ts's phrasing so the Node\n * MCP and WebMCP surfaces read identically.\n */\nfunction describeAction(action: string, className: string): string {\n switch (action) {\n case 'list':\n return `List ${className} objects with optional filtering`;\n case 'get':\n return `Get a specific ${className} by ID or slug`;\n case 'create':\n return `Create a new ${className}`;\n case 'update':\n return `Update an existing ${className}`;\n case 'delete':\n return `Delete a ${className} by ID`;\n default:\n return `Execute ${action} action on ${className}`;\n }\n}\n\n/**\n * Build the full descriptor set for a model. `toolPrefix` defaults to the\n * lowercased class name so tool ids match the existing Node MCP surface exactly\n * (`product_list`, `invoice_record_payment`), giving one stable tool vocabulary\n * across MCP and WebMCP.\n */\nexport function buildToolDescriptors(opts: {\n className: string;\n fields: ToolFieldMeta[];\n actions: string[];\n customActions?: Record<string, CustomActionMetadata>;\n toolPrefix?: string;\n idType?: ToolIdType;\n}): ToolDescriptor[] {\n const { className, fields, actions } = opts;\n const prefix = (opts.toolPrefix ?? className).toLowerCase();\n\n return actions.map((action) => ({\n action,\n // Custom method names can contain underscores; the runtime splits on the\n // FIRST underscore only (mcp.ts #1378), so a lowercased join is safe here.\n name: `${prefix}_${action}`.toLowerCase(),\n description: describeAction(action, className),\n inputSchema: buildToolInputSchema(\n action,\n fields,\n opts.customActions?.[action],\n opts.idType,\n ),\n readOnly: action === 'list' || action === 'get',\n }));\n}\n\n/** True when `action` is one of the fixed CRUD verbs (vs. a custom method). */\nexport function isCrudAction(action: string): boolean {\n return CRUD_ACTIONS.has(action);\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"tool-schema.js","names":[],"sources":["../../src/generators/tool-schema.ts"],"sourcesContent":["import {\n buildCustomActionInputSchema,\n type CustomActionMetadata,\n} from './custom-action.js';\n\n/**\n * Transport-agnostic tool-descriptor builder (#1812, tracer).\n *\n * The single source of truth for turning a model's fields + exposed actions into\n * MCP-shaped tool descriptors (`{ name, description, inputSchema }`). This is the\n * shape both the Model Context Protocol AND Chrome's WebMCP\n * (`document.modelContext.registerTool`) consume — see\n * https://developer.chrome.com/docs/ai/webmcp.\n *\n * It is deliberately pure and free of `ObjectRegistry` / manifest coupling: it\n * takes a normalized {@link ToolFieldMeta}[] so BOTH callers can share it —\n * - `MCPGenerator` (`src/generators/mcp.ts`) for the Node stdio server, and\n * - the web-collections emitter (`src/vite-plugin/web-collections.ts`) for the\n * browser client-data runtime's WebMCP descriptors.\n *\n * Keeping one implementation removes the field-mapping drift risk the\n * \"three emission sites must agree\" contract in web-collections.ts already warns\n * about. The `fieldTypeToJsonSchema` / per-action skeletons below are ported\n * verbatim from mcp.ts's `fieldToMCPSchema` + `generateObjectTools`, so wiring\n * mcp.ts to call this helper is a mechanical, behavior-preserving refactor.\n */\n\n/**\n * A JSON Schema fragment. Values vary by field kind, so this is only ever\n * serialized into tool descriptors, never read back structurally.\n */\nexport type ToolJsonSchema = Record<string, unknown>;\n\n/** The only JSON Schema dialect emitted by generated MCP and WebMCP tools. */\nexport const JSON_SCHEMA_2020_12 =\n 'https://json-schema.org/draft/2020-12/schema';\n\n/**\n * Bounds for generated schemas. Field metadata is authored input, so it must\n * not turn a tools/list response into an unbounded composition or validation\n * workload. These limits are deliberately far above normal SMRT objects while\n * still keeping schemas comfortably inside MCP transport budgets.\n */\nexport const MCP_SCHEMA_LIMITS = {\n maxDepth: 16,\n maxNodes: 2_048,\n maxSerializedBytes: 65_536,\n} as const;\n\n/**\n * Apply the draft-2020-12 dialect and reject schemas that violate MCP's\n * bounded-composition contract. Generated schemas only ever reference local\n * `$defs`; external refs are neither emitted nor followed.\n */\nexport function finalizeMcpJsonSchema(schema: ToolJsonSchema): ToolJsonSchema {\n const finalized = {\n ...schema,\n $schema: JSON_SCHEMA_2020_12,\n };\n assertMcpJsonSchemaSafety(finalized);\n return finalized;\n}\n\n/**\n * Validate the resource envelope of an emitted schema without resolving refs.\n * This is intentionally structural rather than a general JSON-Schema\n * evaluator: the server already owns every schema it emits, and this guard\n * exists to keep authored metadata from introducing hostile shape growth.\n */\nexport function assertMcpJsonSchemaSafety(schema: ToolJsonSchema): void {\n let nodes = 0;\n const ancestors = new WeakSet<object>();\n\n const visit = (value: unknown, depth: number, key?: string): void => {\n nodes += 1;\n if (nodes > MCP_SCHEMA_LIMITS.maxNodes) {\n throw new Error(\n `MCP JSON Schema exceeds ${MCP_SCHEMA_LIMITS.maxNodes} nodes`,\n );\n }\n if (depth > MCP_SCHEMA_LIMITS.maxDepth) {\n throw new Error(\n `MCP JSON Schema exceeds ${MCP_SCHEMA_LIMITS.maxDepth} levels of depth`,\n );\n }\n if (key === '$ref') {\n if (\n typeof value !== 'string' ||\n !value.startsWith('#/$defs/') ||\n value.includes('://')\n ) {\n throw new Error(\n 'MCP JSON Schema may only use local #/$defs/ references',\n );\n }\n return;\n }\n if (value === null || typeof value !== 'object') return;\n if (ancestors.has(value)) {\n throw new Error('MCP JSON Schema must not contain cyclic values');\n }\n\n ancestors.add(value);\n if (Array.isArray(value)) {\n for (const entry of value) visit(entry, depth + 1);\n } else {\n for (const [childKey, child] of Object.entries(value)) {\n visit(child, depth + 1, childKey);\n }\n }\n ancestors.delete(value);\n };\n\n visit(schema, 0);\n\n let serialized: string;\n try {\n serialized = JSON.stringify(schema);\n } catch {\n throw new Error('MCP JSON Schema must be JSON-serializable');\n }\n if (\n new TextEncoder().encode(serialized).byteLength >\n MCP_SCHEMA_LIMITS.maxSerializedBytes\n ) {\n throw new Error(\n `MCP JSON Schema exceeds ${MCP_SCHEMA_LIMITS.maxSerializedBytes} serialized bytes`,\n );\n }\n}\n\n/**\n * Normalized field metadata — the intersection of what the runtime registry\n * (`FieldDefinition._meta`) and the build-time manifest (`WebFieldDefinition`)\n * can each supply. Callers flatten their own field source into this shape.\n */\nexport interface ToolFieldMeta {\n name: string;\n /** Field kind: text | integer | decimal | boolean | datetime | json | foreignKey | … */\n type: string;\n required?: boolean;\n description?: string;\n default?: unknown;\n maxLength?: number;\n minLength?: number;\n min?: number;\n max?: number;\n /** Field values may explicitly be null in the runtime/manifest contract. */\n nullable?: boolean;\n /** For `foreignKey`: the related class name, for the generated description. */\n related?: string;\n}\n\n/** Storage contract for the synthetic primary identifier. */\nexport type ToolIdType = 'uuid' | 'text';\n\n/** The CRUD verbs with dedicated input-schema skeletons; anything else is custom. */\nconst CRUD_ACTIONS = new Set(['list', 'get', 'create', 'update', 'delete']);\n\nexport interface ToolRouteDescriptor {\n /** HTTP method emitted for the route. */\n method: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';\n /** Whether the route targets one item or the whole collection. */\n scope: 'item' | 'collection';\n /** Route segments below the collection endpoint. Dynamic segments use `[x]`. */\n path: string[];\n /** Transport names rewritten by the tool schema (e.g. `actionId` → `id`). */\n parameterAliases?: Record<string, string>;\n /** The generated method accepts one `options` bag as its sole argument. */\n optionsBag?: boolean;\n}\n\n/** A single generated tool descriptor — the WebMCP / MCP tool shape. */\nexport interface ToolDescriptor {\n /** The action this tool performs (`list` | `get` | … | a custom method name). */\n action: string;\n /** Tool id, `${toolPrefix}_${action}` (e.g. `product_list`). */\n name: string;\n description: string;\n inputSchema: ToolJsonSchema;\n /** True for non-mutating reads (`list`/`get`) → WebMCP `annotations.readOnlyHint`. */\n readOnly: boolean;\n /** Generated custom-route transport metadata, when the action has a route. */\n route?: ToolRouteDescriptor;\n}\n\n/**\n * Map one normalized field to its JSON-Schema fragment. Ported from\n * `MCPGenerator.fieldToMCPSchema` (mcp.ts) — keep the two in lockstep until\n * mcp.ts is switched to call this.\n */\nexport function fieldTypeToJsonSchema(field: ToolFieldMeta): ToolJsonSchema {\n const schema: ToolJsonSchema = {\n description: field.description || `${field.type} field`,\n };\n\n switch (field.type) {\n case 'text':\n schema.type = 'string';\n if (field.maxLength !== undefined) schema.maxLength = field.maxLength;\n if (field.minLength !== undefined) schema.minLength = field.minLength;\n break;\n case 'integer':\n schema.type = 'integer';\n if (field.min !== undefined) schema.minimum = field.min;\n if (field.max !== undefined) schema.maximum = field.max;\n break;\n case 'decimal':\n schema.type = 'number';\n if (field.min !== undefined) schema.minimum = field.min;\n if (field.max !== undefined) schema.maximum = field.max;\n break;\n case 'boolean':\n schema.type = 'boolean';\n break;\n case 'datetime':\n schema.type = 'string';\n schema.format = 'date-time';\n break;\n case 'json':\n schema.type = 'object';\n break;\n case 'foreignKey':\n case 'crossPackageRef':\n schema.type = 'string';\n // The generic relation hint is a fallback only — an authored\n // `@field({ description })` wins (#2046 threads descriptions into web\n // tool descriptors; clobbering them here would strip the help text).\n if (!field.description) {\n schema.description = `ID of related ${field.related || 'object'}`;\n }\n break;\n default:\n schema.type = 'string';\n }\n\n if (field.default !== undefined) {\n schema.default = field.default;\n }\n\n if (field.nullable && typeof schema.type === 'string') {\n schema.type = [schema.type, 'null'];\n }\n\n return schema;\n}\n\nfunction buildFieldProperties(fields: ToolFieldMeta[]): {\n properties: Record<string, ToolJsonSchema>;\n defs: Record<string, ToolJsonSchema>;\n} {\n const properties: Record<string, ToolJsonSchema> = {};\n const defs: Record<string, ToolJsonSchema> = {};\n\n fields.forEach((field, index) => {\n // Numeric keys avoid JSON Pointer escaping and keep output deterministic\n // even for an authored field name containing `/` or `~`.\n const defKey = `field_${index}`;\n defs[defKey] = fieldTypeToJsonSchema(field);\n properties[field.name] = { $ref: `#/$defs/${defKey}` };\n });\n\n return { properties, defs };\n}\n\n/**\n * Build the `inputSchema` for one action. CRUD verbs get the fixed skeletons\n * ported from mcp.ts's `generateObjectTools`; any other action is treated as a\n * custom method taking `{ id, options }`.\n */\nexport function buildToolInputSchema(\n action: string,\n fields: ToolFieldMeta[],\n customAction?: CustomActionMetadata,\n idType: ToolIdType = 'uuid',\n): ToolJsonSchema {\n const identifierSchema = (description: string): ToolJsonSchema => ({\n type: 'string',\n ...(idType === 'uuid' ? { format: 'uuid' } : {}),\n description,\n });\n\n switch (action) {\n case 'list':\n return finalizeMcpJsonSchema({\n type: 'object',\n properties: {\n limit: {\n type: 'integer',\n description: 'Maximum number of items to return',\n default: 50,\n minimum: 1,\n maximum: 1000,\n },\n offset: {\n type: 'integer',\n description: 'Number of items to skip',\n default: 0,\n minimum: 0,\n },\n orderBy: {\n type: 'string',\n description: 'Field to order by (e.g., \"created_at DESC\")',\n },\n where: {\n type: 'object',\n description: 'Filter conditions as key-value pairs',\n additionalProperties: true,\n },\n },\n });\n\n case 'get':\n // Either `id` OR `slug` identifies the object (collection.get resolves\n // both). The schema must require one of them just as the handler does,\n // while still allowing slug-only lookups.\n return finalizeMcpJsonSchema({\n type: 'object',\n anyOf: [{ required: ['id'] }, { required: ['slug'] }],\n properties: {\n id: identifierSchema('Unique identifier of the object'),\n slug: {\n type: 'string',\n description: 'URL-friendly identifier of the object',\n },\n },\n });\n\n case 'create': {\n const { properties, defs } = buildFieldProperties(fields);\n const required: string[] = [];\n for (const field of fields) {\n if (field.required) required.push(field.name);\n }\n return finalizeMcpJsonSchema({\n type: 'object',\n properties,\n ...(required.length > 0 ? { required } : {}),\n ...(Object.keys(defs).length > 0 ? { $defs: defs } : {}),\n });\n }\n\n case 'update': {\n const { properties: fieldProperties, defs } =\n buildFieldProperties(fields);\n const properties: Record<string, ToolJsonSchema> = {\n id: identifierSchema('ID of the object to update'),\n ...fieldProperties,\n };\n return finalizeMcpJsonSchema({\n type: 'object',\n properties,\n required: ['id'],\n ...(Object.keys(defs).length > 0 ? { $defs: defs } : {}),\n });\n }\n\n case 'delete':\n return finalizeMcpJsonSchema({\n type: 'object',\n properties: {\n id: identifierSchema('ID of the object to delete'),\n },\n required: ['id'],\n });\n\n default:\n return finalizeMcpJsonSchema(\n buildCustomActionInputSchema(\n customAction ?? {\n scope: 'item',\n idRequired: true,\n isStatic: false,\n },\n ),\n );\n }\n}\n\n/**\n * Human-readable description for a tool, matching mcp.ts's phrasing so the Node\n * MCP and WebMCP surfaces read identically.\n */\nfunction describeAction(action: string, className: string): string {\n switch (action) {\n case 'list':\n return `List ${className} objects with optional filtering`;\n case 'get':\n return `Get a specific ${className} by ID or slug`;\n case 'create':\n return `Create a new ${className}`;\n case 'update':\n return `Update an existing ${className}`;\n case 'delete':\n return `Delete a ${className} by ID`;\n default:\n return `Execute ${action} action on ${className}`;\n }\n}\n\n/**\n * Build the full descriptor set for a model. `toolPrefix` defaults to the\n * lowercased class name so tool ids match the existing Node MCP surface exactly\n * (`product_list`, `invoice_record_payment`), giving one stable tool vocabulary\n * across MCP and WebMCP.\n */\nexport function buildToolDescriptors(opts: {\n className: string;\n fields: ToolFieldMeta[];\n actions: string[];\n customActions?: Record<string, CustomActionMetadata>;\n toolPrefix?: string;\n idType?: ToolIdType;\n}): ToolDescriptor[] {\n const { className, fields, actions } = opts;\n const prefix = (opts.toolPrefix ?? className).toLowerCase();\n\n return actions.map((action) => ({\n action,\n // Custom method names can contain underscores; the runtime splits on the\n // FIRST underscore only (mcp.ts #1378), so a lowercased join is safe here.\n name: `${prefix}_${action}`.toLowerCase(),\n description: describeAction(action, className),\n inputSchema: buildToolInputSchema(\n action,\n fields,\n opts.customActions?.[action],\n opts.idType,\n ),\n readOnly: action === 'list' || action === 'get',\n }));\n}\n\n/** True when `action` is one of the fixed CRUD verbs (vs. a custom method). */\nexport function isCrudAction(action: string): boolean {\n return CRUD_ACTIONS.has(action);\n}\n"],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -55,6 +55,7 @@ export * from './registry';
55
55
  export { smrt as smrtRegistry } from './registry';
56
56
  export * from './runtime/index';
57
57
  export { detectEngine, generateDDLForEngine } from './schema/ddl';
58
+ export { planForeignKeyCreation } from './schema/foreign-key-planner';
58
59
  export { type ConflictTargetInput, checkLiveSchemaParity, type ExpectedTableOrigin, type LiveParityFinding, type LiveParityFindingKind, type LiveParitySeverity, LiveSchemaParityError, type LiveSchemaParityOptions, type LiveSchemaParityReport, } from './schema/live-parity';
59
60
  export { getSystemTableShapes, SYSTEM_TABLE_NAMES, type SystemTableShape, } from './schema/system-table-shapes';
60
61
  export type { SchemaDefinition } from './schema/types';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAGH,cAAc,kBAAkB,CAAC;AAEjC,OAAO,EACL,gBAAgB,EAChB,KAAK,WAAW,EAChB,KAAK,2BAA2B,EAChC,KAAK,gBAAgB,EACrB,KAAK,mBAAmB,EACxB,KAAK,aAAa,EAClB,mBAAmB,EACnB,iBAAiB,EACjB,KAAK,cAAc,EACnB,gBAAgB,GACjB,MAAM,WAAW,CAAC;AAGnB,OAAO,EACL,KAAK,iBAAiB,EACtB,YAAY,EACZ,cAAc,EACd,4BAA4B,EAC5B,iBAAiB,EACjB,KAAK,eAAe,EACpB,KAAK,cAAc,EACnB,KAAK,mBAAmB,EACxB,KAAK,eAAe,EACpB,qBAAqB,EACrB,qBAAqB,EACrB,KAAK,iBAAiB,EACtB,eAAe,EACf,eAAe,EACf,2BAA2B,EAC3B,iBAAiB,EACjB,eAAe,EACf,wBAAwB,EACxB,uBAAuB,EACvB,0BAA0B,GAC3B,MAAM,eAAe,CAAC;AAKvB,OAAO,EACL,qBAAqB,EACrB,KAAK,YAAY,EACjB,KAAK,oBAAoB,EACzB,kBAAkB,EAClB,yBAAyB,EACzB,wBAAwB,GACzB,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EACL,4BAA4B,EAC5B,iBAAiB,GAClB,MAAM,mBAAmB,CAAC;AAE3B,cAAc,SAAS,CAAC;AACxB,cAAc,cAAc,CAAC;AAE7B,OAAO,EACL,0BAA0B,EAC1B,0BAA0B,EAC1B,KAAK,qBAAqB,EAC1B,+BAA+B,EAC/B,kBAAkB,EAClB,yBAAyB,EACzB,oBAAoB,EACpB,iBAAiB,EACjB,8BAA8B,GAC/B,MAAM,oBAAoB,CAAC;AAC5B,cAAc,wBAAwB,CAAC;AACvC,YAAY,EACV,aAAa,EACb,kBAAkB,EAClB,aAAa,EACb,YAAY,GACb,MAAM,UAAU,CAAC;AAElB,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAGlC,OAAO,EACL,qBAAqB,EACrB,0BAA0B,EAC1B,wBAAwB,EACxB,6BAA6B,EAC7B,+BAA+B,EAC/B,4BAA4B,EAC5B,qBAAqB,EACrB,2BAA2B,EAC3B,sBAAsB,EACtB,wBAAwB,EACxB,qBAAqB,EACrB,yBAAyB,EACzB,4BAA4B,EAC5B,2BAA2B,EAC3B,uBAAuB,EACvB,yBAAyB,EACzB,wBAAwB,EACxB,wBAAwB,GACzB,MAAM,cAAc,CAAC;AAEtB,OAAO,EACL,KAAK,cAAc,EACnB,mBAAmB,EACnB,KAAK,sBAAsB,EAC3B,eAAe,GAChB,MAAM,YAAY,CAAC;AAEpB,OAAO,EACL,qBAAqB,EACrB,sBAAsB,EACtB,KAAK,2BAA2B,EAChC,KAAK,iBAAiB,EACtB,yBAAyB,EACzB,4BAA4B,EAC5B,uBAAuB,EACvB,wBAAwB,EACxB,sBAAsB,GACvB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,kCAAkC,EAClC,KAAK,2BAA2B,EAChC,KAAK,kCAAkC,EACvC,KAAK,6BAA6B,EAClC,gCAAgC,GACjC,MAAM,4BAA4B,CAAC;AAGpC,OAAO,EACL,KAAK,sBAAsB,EAC3B,eAAe,EACf,KAAK,YAAY,EACjB,KAAK,YAAY,EACjB,KAAK,EACL,UAAU,EACV,KAAK,IAAI,EACT,UAAU,EACV,IAAI,EACJ,KAAK,mBAAmB,EACxB,SAAS,EACT,KAAK,wBAAwB,EAC7B,KAAK,gBAAgB,GACtB,MAAM,oBAAoB,CAAC;AAE5B,cAAc,kBAAkB,CAAC;AAEjC,cAAc,oBAAoB,CAAC;AACnC,cAAc,UAAU,CAAC;AAEzB,OAAO,EACL,uBAAuB,EACvB,KAAK,wBAAwB,EAC7B,gCAAgC,GACjC,MAAM,qBAAqB,CAAC;AAE7B,cAAc,oBAAoB,CAAC;AACnC,OAAO,EAAE,KAAK,aAAa,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAEtE,cAAc,gBAAgB,CAAC;AAC/B,OAAO,EACL,KAAK,qBAAqB,EAC1B,KAAK,qBAAqB,EAC1B,YAAY,GACb,MAAM,YAAY,CAAC;AACpB,cAAc,aAAa,CAAC;AAG5B,YAAY,EACV,cAAc,EACd,kBAAkB,EAClB,wBAAwB,GACzB,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,uBAAuB,EACvB,iBAAiB,EACjB,oBAAoB,EACpB,mBAAmB,EACnB,sBAAsB,EACtB,oBAAoB,EACpB,iBAAiB,EACjB,wBAAwB,GACzB,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,wBAAwB,EACxB,0BAA0B,GAC3B,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EACL,uBAAuB,EACvB,KAAK,eAAe,EACpB,cAAc,EACd,KAAK,oBAAoB,EACzB,KAAK,qBAAqB,EAC1B,KAAK,oBAAoB,EACzB,KAAK,eAAe,EACpB,KAAK,qBAAqB,EAC1B,KAAK,sBAAsB,GAC5B,MAAM,kBAAkB,CAAC;AAE1B,cAAc,kBAAkB,CAAC;AACjC,YAAY,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAEvD,OAAO,EACL,kBAAkB,EAClB,cAAc,EACd,oBAAoB,EACpB,oBAAoB,EACpB,wBAAwB,EACxB,cAAc,GACf,MAAM,qBAAqB,CAAC;AAC7B,cAAc,UAAU,CAAC;AACzB,OAAO,EACL,0BAA0B,EAC1B,KAAK,iCAAiC,GACvC,MAAM,2BAA2B,CAAC;AAMnC,OAAO,EACL,4BAA4B,EAC5B,yBAAyB,EACzB,yBAAyB,EACzB,KAAK,qBAAqB,EAC1B,KAAK,wBAAwB,EAC7B,uBAAuB,GACxB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EACL,uBAAuB,EACvB,kBAAkB,EAClB,qBAAqB,EACrB,KAAK,gBAAgB,EACrB,cAAc,EACd,gBAAgB,EAChB,iBAAiB,EACjB,gBAAgB,EAChB,iBAAiB,GAClB,MAAM,gBAAgB,CAAC;AACxB,cAAc,YAAY,CAAC;AAC3B,OAAO,EAAE,IAAI,IAAI,YAAY,EAAE,MAAM,YAAY,CAAC;AAElD,cAAc,iBAAiB,CAAC;AAChC,OAAO,EAAE,YAAY,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AAGlE,OAAO,EACL,KAAK,mBAAmB,EACxB,qBAAqB,EACrB,KAAK,mBAAmB,EACxB,KAAK,iBAAiB,EACtB,KAAK,qBAAqB,EAC1B,KAAK,kBAAkB,EACvB,qBAAqB,EACrB,KAAK,uBAAuB,EAC5B,KAAK,sBAAsB,GAC5B,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EACL,oBAAoB,EACpB,kBAAkB,EAClB,KAAK,gBAAgB,GACtB,MAAM,8BAA8B,CAAC;AAEtC,YAAY,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAEvD,cAAc,iBAAiB,CAAC;AAGhC,cAAc,cAAc,CAAC;AAE7B,cAAc,gBAAgB,CAAC;AAC/B,YAAY,EACV,iBAAiB,EACjB,aAAa,EACb,kBAAkB,EAClB,YAAY,EACZ,WAAW,EACX,gBAAgB,EAChB,aAAa,EACb,iBAAiB,GAClB,MAAM,gBAAgB,CAAC;AAExB,OAAO,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AAEpD,OAAO,EACL,eAAe,EACf,KAAK,mBAAmB,GACzB,MAAM,oBAAoB,CAAC;AAE5B,cAAc,eAAe,CAAC;AAE9B,OAAO,EACL,KAAK,EACL,cAAc,EACd,OAAO,EACP,KAAK,WAAW,EAChB,KAAK,UAAU,EACf,KAAK,EACL,KAAK,MAAM,EACX,KAAK,cAAc,EACnB,SAAS,EACT,aAAa,EACb,SAAS,GACV,MAAM,cAAc,CAAC;AAEtB,OAAO,EACL,mBAAmB,EACnB,YAAY,EACZ,2BAA2B,EAC3B,aAAa,EACb,eAAe,EACf,MAAM,EACN,KAAK,mBAAmB,EACxB,kBAAkB,EAClB,mBAAmB,GACpB,MAAM,yBAAyB,CAAC;AAEjC,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -41,7 +41,7 @@ import { executeToolCall, executeToolCalls, formatToolResults, validateToolCall
41
41
  import { SmrtObject } from "./object.js";
42
42
  import { SMRT_COLLECTION_BASE_NAMES, isSmrtCollectionExtendsName } from "./registry/collection-resolution.js";
43
43
  import { ObjectRegistry, smrt } from "./registry.js";
44
- import { SmrtCollection } from "./collection.js";
44
+ import { DEFAULT_FACET_LIMIT, MAX_FACET_FIELDS, MAX_FACET_LIMIT, SmrtCollection } from "./collection.js";
45
45
  import { executeCollectionReadPlan } from "./collection-read-plan.js";
46
46
  import { DEFAULT_DATA_QUERY_PAGE_LIMIT, DEFAULT_DATA_QUERY_RESULT_BYTES, DataQueryValidationError, MAX_DATA_QUERY_CURSOR_LENGTH, MAX_DATA_QUERY_FACETS, MAX_DATA_QUERY_FILTERS, MAX_DATA_QUERY_FILTER_DEPTH, MAX_DATA_QUERY_IN_VALUES, MAX_DATA_QUERY_OFFSET, MAX_DATA_QUERY_PAGE_LIMIT, MAX_DATA_QUERY_REQUEST_BYTES, MAX_DATA_QUERY_RESULT_BYTES, MAX_DATA_QUERY_WARNINGS, canonicalizeDataQuery, createDataQueryFingerprint, normalizeDataQueryRequest, normalizeDataQueryResult, normalizeDataQuerySchema } from "./data-query.js";
47
47
  import { isDatabaseInterface, resolveDatabase } from "./database.js";
@@ -70,6 +70,7 @@ import { getClassConfigResolvers, getConfigResolver, isLazyConfigSentinel, listC
70
70
  import { DEFAULT_LEARNING_CONFIG, LearningMemory } from "./learning/memory.js";
71
71
  import { ManifestBuilder } from "./manifest/generator.js";
72
72
  import manifest, { getManifest, staticManifest } from "./manifest/index.js";
73
+ import { planForeignKeyCreation } from "./schema/foreign-key-planner.js";
73
74
  import { SchemaComparer, generateSchemaDiff, getSQLFromDiff, hasActionableChanges, isAdvisoryOnlyChange, isManualOrAdvisoryChange } from "./migrations/differ.js";
74
75
  import { SmrtPolymorphicAssociation } from "./polymorphic-association.js";
75
76
  import { createSmrtClient } from "./runtime/client.js";
@@ -83,4 +84,4 @@ import "./system/index.js";
83
84
  import { getTestDatabase } from "./testing/database.js";
84
85
  import "./tools/index.js";
85
86
  import { smrtPlugin } from "./vite-plugin/index.js";
86
- export { AIError, APIGenerator, AiUsageCollector, AiUsagePersistenceHandler, CACHE_INVALIDATION_CHANNEL, CHANGE_FEED_INTERCEPTOR_NAME, CHANGE_FEED_TABLE, CHANGE_SIGNAL_CHANNEL, CLIGenerator, ConfigurationError, ContentHasher, CosineSimilarity, DEFAULT_AI_COST_RATES, DEFAULT_CHANGES_LIMIT, DEFAULT_DATA_QUERY_PAGE_LIMIT, DEFAULT_DATA_QUERY_RESULT_BYTES, DEFAULT_EMBEDDING_CONFIG, DEFAULT_EVENTS_HEARTBEAT_MS, DEFAULT_EVENTS_MAX_SUBSCRIBERS, DEFAULT_EVENTS_RETRY_AFTER_SECONDS, DEFAULT_LEARNING_CONFIG, DEFAULT_LIST_LIMIT, DEFAULT_LIST_ORDER_BY, DEFAULT_POSTGRES_TIMEOUTS, DEFAULT_RETENTION_POLICY, DataQueryValidationError, DatabaseError, Dispatch, DispatchBus, DispatchCollection, DispatchSubscription, DispatchSubscriptionCollection, EmbeddingProvider, EmbeddingStorage, ErrorUtils, FilesystemError, GlobalInterceptors, LearningMemory, LiveSchemaParityError, MAX_CHANGES_LIMIT, MAX_DATA_QUERY_CURSOR_LENGTH, MAX_DATA_QUERY_FACETS, MAX_DATA_QUERY_FILTERS, MAX_DATA_QUERY_FILTER_DEPTH, MAX_DATA_QUERY_IN_VALUES, MAX_DATA_QUERY_OFFSET, MAX_DATA_QUERY_PAGE_LIMIT, MAX_DATA_QUERY_REQUEST_BYTES, MAX_DATA_QUERY_RESULT_BYTES, MAX_DATA_QUERY_WARNINGS, MAX_LIST_LIMIT, MAX_SYNC_APPLY_BATCH_SIZE, MCPGenerator, MCP_STABLE_CATALOG_TTL_MS, MODULE_DOC_HASH_PREFIX, ManifestBuilder, ManifestGenerator, ManifestManager, MetricsAdapter, NetworkError, ObjectRegistry, POSTGRES_TIMEOUT_ENV_VARS, PRIVATE_READ_CACHE_CONTROL, PubSubAdapter, QueryBoundsError, QueryOrderByError, RuntimeError, SMRT_COLLECTION_BASE_NAMES, SMRT_CUSTOM_ACTION_ERROR_METADATA_KEY, SYNC_APPLY_ROUTE_SEGMENTS, SYNC_APPLY_UUID_PATTERN, SYSTEM_TABLE_NAMES, SchemaComparer, SignalBus, SignalSanitizer, SmrtClass, SmrtCollection, SmrtError, SmrtHierarchical, SmrtJunction, SmrtMCPServer, SmrtObject, SmrtPolymorphicAssociation, TenantIsolationError, ValidationError, ValidationReport, ValidationUtils, appendChange, applyOneToManyChildAccessors, applyPendingDecoratorRegistrations, applyPostgresRuntimeTimeouts, applySyncWritablePolicy, assertPostgresSystemTimestampsCurrent, broadcastCacheInvalidation, buildCascadePlan, buildChangeEventStream, buildCustomActionInputSchema, buildCustomActionInvocationArgs, buildDefaultListOrderBy, buildDomainKnowledgeManifest, bumpChangeFeed, canonicalReadRepresentation, canonicalizeDataQuery, cascadeReferencesTo, changeEventSubscribersAtCapacity, checkLiveSchemaParity, childAccessorName, classifyDatabaseError, classifyDialectMessage, clearRetentionTasks, clone, computeBodyEtag, computeRuntimeWebManifestHash, computeTableVersionEtag, conditionalJsonResponse, config, convertTypeToJsonSchema, createDataQueryFingerprint, createDispatchBus, createFilesystemAdapter, createInterceptorContext, createMCPServer, createQualifiedName, createRestServer, createSmrtClient, createSmrtServer, crossPackageRef, customActionParameterInputName, detectEngine, discoverManifestEntry, ensureBootstrapSystemTableCompatibility, ensureCacheInvalidationListener, ensureChangeFeedTable, ensureDeferredSystemTableCompatibility, ensureDispatchSubscriptionsSystemTableCompatibility, ensureDispatchSystemTableCompatibility, ensureJobEventsSystemTableCompatibility, ensureJobsSystemTableCompatibility, ensureLegacySystemTableCompatibility, ensureSystemTables, estimateAiUsageCost, eventStreamCapacityExceededResponse, executeCollectionReadPlan, executeToolCall, executeToolCalls, field, findManifestEntryByQualifiedName, foreignKey, formatToolResults, generateDDLForEngine, generateOpenAPISpec, generateSchemaDiff, generateToolFromMethod, generateToolManifest, getAdapterInfo, getCLIHandler, getCacheGeneration, getChangesSince, getClassConfigResolvers, getClassName, getConfigResolver, getDatabaseEngine, getManifest, getPackageFromQualifiedName, getRetentionTasks, getSQLFromDiff, getSystemTableShapes, getTableVersion, getTenantScopedChangesSince, getTestDatabase, hasActionableChanges, ifNoneMatchHasConcreteMatch, ifNoneMatchSatisfied, importOptionalDependency, invalidateCollectionCache, isAbortedTransactionError, isAdvisoryOnlyChange, isDatabaseInterface, isDeterministicDatabaseError, isFromPackage, isLazyConfigSentinel, isManualOrAdvisoryChange, isNotNullViolationError, isQualifiedName, isSmrtCollectionExtendsName, isStaleWrite, isTenantScopedClassResolved, isTransientDatabaseError, isType, isUniqueViolationError, isValid, listConfigResolvers, loadExternalManifest, loadExternalManifestSync, loadLocalTestManifestSync, loadManifestFromPathSync, manifest, manyToMany, meta, migratePostgresSystemTimestamps, normalizeCustomActionFailure, normalizeDataQueryRequest, normalizeDataQueryResult, normalizeDataQuerySchema, normalizeEventsMaxSubscribers, normalizeOnDelete, normalizeTypedHttpError, oneToMany, parse, parseQualifiedName, parseSyncApplyBatch, payloadMatchesRow, planPostgresSystemTimestampMigrations, processSyncApplyBatch, pruneAiUsage, pruneChangeFeed, pruneExpiredContexts, qualifiedNamesEqual, readAgentModuleDocs, registerChangeFeedWriter, registerCompatibleFieldDecorator, registerConfigResolver, registerFilesystemAdapterFactory, registerOptionalDependency, registerRetentionTask, resetChangeFeedWarnings, resetChangeSignals, resetCollectionCache, resetConfigResolvers, resetVerifiedTables, resolveAgentModuleDocPaths, resolveCustomActionMetadata, resolveDatabase, resolveDbCacheKey, resolveDispatchTenantId, resolveDispatchTenantScope, resolveGetStringFilter, resolveLazyConfig, resolveListLimit, resolveListOffset, resolveMCPToolListCacheHint, resolvePostgresTimeouts, resolveReadCacheControl, resolveTenantEtagDiscriminator, runCascadeDelete, runRetentionSweep, runWithTenantGate, safeParse, safeStringify, setDispatchTenantResolver, setTenantEntryPointRunner, setTenantScopedClassResolver, setupCLI, setupSwaggerUI, shouldIncludeMethod, signalVisibleToTenant, smrt, smrtPlugin, smrt as smrtRegistry, sortMCPTools, startRestServer, staticManifest, stopCacheInvalidationListeners, stopChangeSignalListeners, stringify, subscribeToChangeSignals, tableExists, tryReserveChangeEventSubscriberSlot, unregisterChangeFeedWriter, unregisterConfigResolver, unregisterRetentionTask, validateSyncApplyItem, validateToolCall, versionConditionalResponse, warnIfSharedCacheNeutralized };
87
+ export { AIError, APIGenerator, AiUsageCollector, AiUsagePersistenceHandler, CACHE_INVALIDATION_CHANNEL, CHANGE_FEED_INTERCEPTOR_NAME, CHANGE_FEED_TABLE, CHANGE_SIGNAL_CHANNEL, CLIGenerator, ConfigurationError, ContentHasher, CosineSimilarity, DEFAULT_AI_COST_RATES, DEFAULT_CHANGES_LIMIT, DEFAULT_DATA_QUERY_PAGE_LIMIT, DEFAULT_DATA_QUERY_RESULT_BYTES, DEFAULT_EMBEDDING_CONFIG, DEFAULT_EVENTS_HEARTBEAT_MS, DEFAULT_EVENTS_MAX_SUBSCRIBERS, DEFAULT_EVENTS_RETRY_AFTER_SECONDS, DEFAULT_FACET_LIMIT, DEFAULT_LEARNING_CONFIG, DEFAULT_LIST_LIMIT, DEFAULT_LIST_ORDER_BY, DEFAULT_POSTGRES_TIMEOUTS, DEFAULT_RETENTION_POLICY, DataQueryValidationError, DatabaseError, Dispatch, DispatchBus, DispatchCollection, DispatchSubscription, DispatchSubscriptionCollection, EmbeddingProvider, EmbeddingStorage, ErrorUtils, FilesystemError, GlobalInterceptors, LearningMemory, LiveSchemaParityError, MAX_CHANGES_LIMIT, MAX_DATA_QUERY_CURSOR_LENGTH, MAX_DATA_QUERY_FACETS, MAX_DATA_QUERY_FILTERS, MAX_DATA_QUERY_FILTER_DEPTH, MAX_DATA_QUERY_IN_VALUES, MAX_DATA_QUERY_OFFSET, MAX_DATA_QUERY_PAGE_LIMIT, MAX_DATA_QUERY_REQUEST_BYTES, MAX_DATA_QUERY_RESULT_BYTES, MAX_DATA_QUERY_WARNINGS, MAX_FACET_FIELDS, MAX_FACET_LIMIT, MAX_LIST_LIMIT, MAX_SYNC_APPLY_BATCH_SIZE, MCPGenerator, MCP_STABLE_CATALOG_TTL_MS, MODULE_DOC_HASH_PREFIX, ManifestBuilder, ManifestGenerator, ManifestManager, MetricsAdapter, NetworkError, ObjectRegistry, POSTGRES_TIMEOUT_ENV_VARS, PRIVATE_READ_CACHE_CONTROL, PubSubAdapter, QueryBoundsError, QueryOrderByError, RuntimeError, SMRT_COLLECTION_BASE_NAMES, SMRT_CUSTOM_ACTION_ERROR_METADATA_KEY, SYNC_APPLY_ROUTE_SEGMENTS, SYNC_APPLY_UUID_PATTERN, SYSTEM_TABLE_NAMES, SchemaComparer, SignalBus, SignalSanitizer, SmrtClass, SmrtCollection, SmrtError, SmrtHierarchical, SmrtJunction, SmrtMCPServer, SmrtObject, SmrtPolymorphicAssociation, TenantIsolationError, ValidationError, ValidationReport, ValidationUtils, appendChange, applyOneToManyChildAccessors, applyPendingDecoratorRegistrations, applyPostgresRuntimeTimeouts, applySyncWritablePolicy, assertPostgresSystemTimestampsCurrent, broadcastCacheInvalidation, buildCascadePlan, buildChangeEventStream, buildCustomActionInputSchema, buildCustomActionInvocationArgs, buildDefaultListOrderBy, buildDomainKnowledgeManifest, bumpChangeFeed, canonicalReadRepresentation, canonicalizeDataQuery, cascadeReferencesTo, changeEventSubscribersAtCapacity, checkLiveSchemaParity, childAccessorName, classifyDatabaseError, classifyDialectMessage, clearRetentionTasks, clone, computeBodyEtag, computeRuntimeWebManifestHash, computeTableVersionEtag, conditionalJsonResponse, config, convertTypeToJsonSchema, createDataQueryFingerprint, createDispatchBus, createFilesystemAdapter, createInterceptorContext, createMCPServer, createQualifiedName, createRestServer, createSmrtClient, createSmrtServer, crossPackageRef, customActionParameterInputName, detectEngine, discoverManifestEntry, ensureBootstrapSystemTableCompatibility, ensureCacheInvalidationListener, ensureChangeFeedTable, ensureDeferredSystemTableCompatibility, ensureDispatchSubscriptionsSystemTableCompatibility, ensureDispatchSystemTableCompatibility, ensureJobEventsSystemTableCompatibility, ensureJobsSystemTableCompatibility, ensureLegacySystemTableCompatibility, ensureSystemTables, estimateAiUsageCost, eventStreamCapacityExceededResponse, executeCollectionReadPlan, executeToolCall, executeToolCalls, field, findManifestEntryByQualifiedName, foreignKey, formatToolResults, generateDDLForEngine, generateOpenAPISpec, generateSchemaDiff, generateToolFromMethod, generateToolManifest, getAdapterInfo, getCLIHandler, getCacheGeneration, getChangesSince, getClassConfigResolvers, getClassName, getConfigResolver, getDatabaseEngine, getManifest, getPackageFromQualifiedName, getRetentionTasks, getSQLFromDiff, getSystemTableShapes, getTableVersion, getTenantScopedChangesSince, getTestDatabase, hasActionableChanges, ifNoneMatchHasConcreteMatch, ifNoneMatchSatisfied, importOptionalDependency, invalidateCollectionCache, isAbortedTransactionError, isAdvisoryOnlyChange, isDatabaseInterface, isDeterministicDatabaseError, isFromPackage, isLazyConfigSentinel, isManualOrAdvisoryChange, isNotNullViolationError, isQualifiedName, isSmrtCollectionExtendsName, isStaleWrite, isTenantScopedClassResolved, isTransientDatabaseError, isType, isUniqueViolationError, isValid, listConfigResolvers, loadExternalManifest, loadExternalManifestSync, loadLocalTestManifestSync, loadManifestFromPathSync, manifest, manyToMany, meta, migratePostgresSystemTimestamps, normalizeCustomActionFailure, normalizeDataQueryRequest, normalizeDataQueryResult, normalizeDataQuerySchema, normalizeEventsMaxSubscribers, normalizeOnDelete, normalizeTypedHttpError, oneToMany, parse, parseQualifiedName, parseSyncApplyBatch, payloadMatchesRow, planForeignKeyCreation, planPostgresSystemTimestampMigrations, processSyncApplyBatch, pruneAiUsage, pruneChangeFeed, pruneExpiredContexts, qualifiedNamesEqual, readAgentModuleDocs, registerChangeFeedWriter, registerCompatibleFieldDecorator, registerConfigResolver, registerFilesystemAdapterFactory, registerOptionalDependency, registerRetentionTask, resetChangeFeedWarnings, resetChangeSignals, resetCollectionCache, resetConfigResolvers, resetVerifiedTables, resolveAgentModuleDocPaths, resolveCustomActionMetadata, resolveDatabase, resolveDbCacheKey, resolveDispatchTenantId, resolveDispatchTenantScope, resolveGetStringFilter, resolveLazyConfig, resolveListLimit, resolveListOffset, resolveMCPToolListCacheHint, resolvePostgresTimeouts, resolveReadCacheControl, resolveTenantEtagDiscriminator, runCascadeDelete, runRetentionSweep, runWithTenantGate, safeParse, safeStringify, setDispatchTenantResolver, setTenantEntryPointRunner, setTenantScopedClassResolver, setupCLI, setupSwaggerUI, shouldIncludeMethod, signalVisibleToTenant, smrt, smrtPlugin, smrt as smrtRegistry, sortMCPTools, startRestServer, staticManifest, stopCacheInvalidationListeners, stopChangeSignalListeners, stringify, subscribeToChangeSignals, tableExists, tryReserveChangeEventSubscriberSlot, unregisterChangeFeedWriter, unregisterConfigResolver, unregisterRetentionTask, validateSyncApplyItem, validateToolCall, versionConditionalResponse, warnIfSharedCacheNeutralized };
@@ -18,7 +18,8 @@ export interface InterceptorContext {
18
18
  * Options for list operations
19
19
  */
20
20
  export interface ListOptions {
21
- where?: Record<string, unknown>;
21
+ /** AND-only object or DNF (outer OR, inner AND) collection predicate. */
22
+ where?: Record<string, unknown> | Record<string, unknown>[][];
22
23
  orderBy?: string | string[];
23
24
  limit?: number;
24
25
  offset?: number;
@@ -1 +1 @@
1
- {"version":3,"file":"interceptors.d.ts","sourceRoot":"","sources":["../src/interceptors.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"interceptors.d.ts","sourceRoot":"","sources":["../src/interceptors.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAE9C;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,+CAA+C;IAC/C,SAAS,EAAE,MAAM,CAAC;IAClB,6CAA6C;IAC7C,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,iCAAiC;IACjC,SAAS,EAAE,IAAI,CAAC;IAChB,mCAAmC;IACnC,SAAS,EAAE,MAAM,GAAG,KAAK,GAAG,OAAO,GAAG,MAAM,GAAG,QAAQ,CAAC;IACxD,0BAA0B;IAC1B,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACpC;AAED;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,yEAAyE;IACzE,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,EAAE,CAAC;IAC9D,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IAC5B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC3B,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,wBAAwB;IACxB,GAAG,EAAE,MAAM,CAAC;IACZ,uBAAuB;IACvB,MAAM,EAAE,OAAO,EAAE,CAAC;IAClB,iFAAiF;IACjF,sBAAsB,CAAC,EAAE,OAAO,CAAC;CAClC;AAED;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,OAAO,EAAE,CAAC;CACnB;AAED;;;;;GAKG;AACH,MAAM,WAAW,qBAAqB;IACpC,4EAA4E;IAC5E,IAAI,CAAC,EAAE,MAAM,CAAC;IAEd,kEAAkE;IAClE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB;;;;;;OAMG;IACH,UAAU,CAAC,CACT,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,WAAW,EACpB,OAAO,EAAE,kBAAkB,GAC1B,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAE7D;;;;;;OAMG;IACH,SAAS,CAAC,CAAC,CAAC,SAAS,UAAU,EAC7B,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,CAAC,EAAE,EACZ,OAAO,EAAE,kBAAkB,GAC1B,CAAC,EAAE,GAAG,OAAO,CAAC,CAAC,EAAE,CAAC,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAE7C;;;;;;OAMG;IACH,SAAS,CAAC,CACR,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACxC,OAAO,EAAE,kBAAkB,GAEzB,MAAM,GACN,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GACvB,OAAO,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GACzC,IAAI,GACJ,OAAO,CAAC,IAAI,CAAC,CAAC;IAElB;;;;;;OAMG;IACH,QAAQ,CAAC,CAAC,CAAC,SAAS,UAAU,EAC5B,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,CAAC,GAAG,IAAI,EAClB,OAAO,EAAE,kBAAkB,GAC1B,CAAC,GAAG,IAAI,GAAG,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEvD;;;;;;OAMG;IACH,WAAW,CAAC,CACV,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,YAAY,EACrB,OAAO,EAAE,kBAAkB,GAEzB,oBAAoB,GACpB,OAAO,CAAC,oBAAoB,CAAC,GAC7B,IAAI,GACJ,OAAO,CAAC,IAAI,CAAC,CAAC;IAElB;;;;;;OAMG;IACH,UAAU,CAAC,CAAC,CAAC,SAAS,UAAU,EAC9B,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,CAAC,EAAE,EACZ,OAAO,EAAE,kBAAkB,GAC1B,CAAC,EAAE,GAAG,OAAO,CAAC,CAAC,EAAE,CAAC,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAE7C;;;;;OAKG;IACH,UAAU,CAAC,CACT,QAAQ,EAAE,UAAU,EACpB,OAAO,EAAE,kBAAkB,GAC1B,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAExB;;;;OAIG;IACH,SAAS,CAAC,CACR,QAAQ,EAAE,UAAU,EACpB,OAAO,EAAE,kBAAkB,GAC1B,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAExB;;;;;OAKG;IACH,YAAY,CAAC,CACX,QAAQ,EAAE,UAAU,EACpB,OAAO,EAAE,kBAAkB,GAC1B,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAExB;;;;OAIG;IACH,WAAW,CAAC,CACV,QAAQ,EAAE,UAAU,EACpB,OAAO,EAAE,kBAAkB,GAC1B,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACzB;AAED;;;;;;;GAOG;AACH,OAAO,CAAC,MAAM,CAAC;IAEb,IAAI,kBAAkB,EAAE,OAAO,EAAE,GAAG,SAAS,CAAC;CAC/C;AAED;;;;;;GAMG;AACH,qBAAa,kBAAkB;IAC7B;;OAEG;IACH,OAAO,CAAC,MAAM,KAAK,YAAY,GAK9B;IAED;;;;;;;;;;;;;;;OAeG;IACH,MAAM,CAAC,QAAQ,CAAC,WAAW,EAAE,qBAAqB,GAAG,IAAI;IAkBzD;;;;;OAKG;IACH,MAAM,CAAC,UAAU,CACf,iBAAiB,EAAE,qBAAqB,GAAG,MAAM,GAChD,OAAO;IAaV;;OAEG;IACH,MAAM,CAAC,KAAK,IAAI,IAAI;IAIpB;;OAEG;IACH,MAAM,CAAC,MAAM,IAAI,SAAS,qBAAqB,EAAE;IAIjD;;OAEG;IACH,MAAM,CAAC,eAAe,IAAI,OAAO;IAIjC;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,cAAc;IAQ7B;;;OAGG;WACU,iBAAiB,CAC5B,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,WAAW,EACpB,OAAO,EAAE,kBAAkB,GAC1B,OAAO,CAAC,WAAW,CAAC;IAmBvB;;;OAGG;WACU,gBAAgB,CAAC,CAAC,SAAS,UAAU,EAChD,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,CAAC,EAAE,EACZ,OAAO,EAAE,kBAAkB,GAC1B,OAAO,CAAC,CAAC,EAAE,CAAC;IAmBf;;;OAGG;WACU,gBAAgB,CAC3B,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACxC,OAAO,EAAE,kBAAkB,GAC1B,OAAO,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAmB5C;;;OAGG;WACU,eAAe,CAAC,CAAC,SAAS,UAAU,EAC/C,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,CAAC,GAAG,IAAI,EAClB,OAAO,EAAE,kBAAkB,GAC1B,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC;IAepB;;;OAGG;WACU,kBAAkB,CAC7B,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,YAAY,EACrB,OAAO,EAAE,kBAAkB,GAC1B,OAAO,CAAC,oBAAoB,CAAC;IAsBhC;;;OAGG;WACU,iBAAiB,CAAC,CAAC,SAAS,UAAU,EACjD,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,CAAC,EAAE,EACZ,OAAO,EAAE,kBAAkB,GAC1B,OAAO,CAAC,CAAC,EAAE,CAAC;IAmBf;;;OAGG;WACU,iBAAiB,CAC5B,QAAQ,EAAE,UAAU,EACpB,OAAO,EAAE,kBAAkB,GAC1B,OAAO,CAAC,IAAI,CAAC;IAQhB;;;OAGG;WACU,gBAAgB,CAC3B,QAAQ,EAAE,UAAU,EACpB,OAAO,EAAE,kBAAkB,GAC1B,OAAO,CAAC,IAAI,CAAC;IAQhB;;;OAGG;WACU,mBAAmB,CAC9B,QAAQ,EAAE,UAAU,EACpB,OAAO,EAAE,kBAAkB,GAC1B,OAAO,CAAC,IAAI,CAAC;IAQhB;;;OAGG;WACU,kBAAkB,CAC7B,QAAQ,EAAE,UAAU,EACpB,OAAO,EAAE,kBAAkB,GAC1B,OAAO,CAAC,IAAI,CAAC;CAOjB;AASD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,sBAAsB,CACpC,MAAM,EAAE,MAAM,GACb;IAAE,EAAE,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAIpD;AAED;;;GAGG;AACH,wBAAgB,wBAAwB,CACtC,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,kBAAkB,CAAC,WAAW,CAAC,EAC1C,cAAc,CAAC,EAAE,MAAM,EACvB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GACjC,kBAAkB,CAQpB"}
@@ -1 +1 @@
1
- {"version":3,"file":"interceptors.js","names":[],"sources":["../src/interceptors.ts"],"sourcesContent":["/**\n * Global Interceptors System for SMRT Collections and Objects\n *\n * Provides a plugin architecture for intercepting collection and object operations.\n * This enables external packages (like @happyvertical/smrt-tenancy) to register\n * interceptors without creating circular dependencies.\n *\n * Pattern: Static methods on GlobalInterceptors class with globalThis state\n * (matches ObjectRegistry pattern for cross-module state sharing)\n *\n * @example Basic interceptor registration\n * ```typescript\n * import { GlobalInterceptors } from '@happyvertical/smrt-core';\n *\n * // Register a beforeList interceptor\n * GlobalInterceptors.register({\n * beforeList(className, options) {\n * console.log(`Listing ${className}`);\n * return options; // Return modified options\n * }\n * });\n * ```\n *\n * @example Tenancy interceptor (from smrt-tenancy)\n * ```typescript\n * GlobalInterceptors.register({\n * beforeList(className, options, context) {\n * const tenantId = getCurrentTenantId();\n * if (tenantId && isTenantScoped(className)) {\n * return {\n * ...options,\n * where: { ...options.where, tenantId }\n * };\n * }\n * return options;\n * },\n * beforeSave(instance, context) {\n * // Validate tenant on save\n * }\n * });\n * ```\n *\n * @see https://github.com/happyvertical/smrt/issues/675\n */\n\nimport type { SmrtObject } from './object.js';\n\n/**\n * Context passed to interceptors with operation metadata\n */\nexport interface InterceptorContext {\n /** Name of the SMRT class being operated on */\n className: string;\n /** Name of the collection (if applicable) */\n collectionName?: string;\n /** Timestamp of the operation */\n timestamp: Date;\n /** Operation type for debugging */\n operation: 'list' | 'get' | 'query' | 'save' | 'delete';\n /** Additional metadata */\n metadata?: Record<string, unknown>;\n}\n\n/**\n * Options for list operations\n */\nexport interface ListOptions {\n where?: Record<string, unknown>;\n orderBy?: string | string[];\n limit?: number;\n offset?: number;\n select?: readonly string[];\n include?: string[];\n [key: string]: unknown;\n}\n\n/**\n * Options for query operations (raw SQL)\n */\nexport interface QueryOptions {\n /** The raw SQL query */\n sql: string;\n /** Query parameters */\n params: unknown[];\n /** If true, allow raw SQL on tenant-scoped classes (requires explicit opt-in) */\n allowRawOnTenantScoped?: boolean;\n}\n\n/**\n * Result from query interceptor - can modify SQL or throw to block\n */\nexport interface QueryInterceptResult {\n sql: string;\n params: unknown[];\n}\n\n/**\n * Interface for collection/object interceptors\n *\n * All methods are optional. Return void to pass through unchanged,\n * or return modified data to transform the operation.\n */\nexport interface CollectionInterceptor {\n /** Unique identifier for this interceptor (for debugging/unregistration) */\n name?: string;\n\n /** Priority for execution order (higher = earlier). Default: 0 */\n priority?: number;\n\n /**\n * Called before list() operations\n * @param className - Name of the class being listed\n * @param options - List options (where, orderBy, limit, select, etc.)\n * @param context - Operation context\n * @returns Modified options or void to pass through\n */\n beforeList?(\n className: string,\n options: ListOptions,\n context: InterceptorContext,\n ): ListOptions | Promise<ListOptions> | void | Promise<void>;\n\n /**\n * Called after list() operations with results\n * @param className - Name of the class\n * @param results - Array of hydrated instances\n * @param context - Operation context\n * @returns Modified results or void to pass through\n */\n afterList?<T extends SmrtObject>(\n className: string,\n results: T[],\n context: InterceptorContext,\n ): T[] | Promise<T[]> | void | Promise<void>;\n\n /**\n * Called before get() operations\n * @param className - Name of the class\n * @param filter - ID, slug, or filter object\n * @param context - Operation context\n * @returns Modified filter or void to pass through\n */\n beforeGet?(\n className: string,\n filter: string | Record<string, unknown>,\n context: InterceptorContext,\n ):\n | string\n | Record<string, unknown>\n | Promise<string | Record<string, unknown>>\n | void\n | Promise<void>;\n\n /**\n * Called after get() operations with result\n * @param className - Name of the class\n * @param instance - Hydrated instance or null if not found\n * @param context - Operation context\n * @returns Modified instance, null, or void to pass through\n */\n afterGet?<T extends SmrtObject>(\n className: string,\n instance: T | null,\n context: InterceptorContext,\n ): T | null | Promise<T | null> | void | Promise<void>;\n\n /**\n * Called before query() operations (raw SQL)\n * @param className - Name of the class\n * @param options - Query options with SQL and params\n * @param context - Operation context\n * @returns Modified query options, or throw to block the query\n */\n beforeQuery?(\n className: string,\n options: QueryOptions,\n context: InterceptorContext,\n ):\n | QueryInterceptResult\n | Promise<QueryInterceptResult>\n | void\n | Promise<void>;\n\n /**\n * Called after query() operations with results\n * @param className - Name of the class\n * @param results - Array of hydrated instances\n * @param context - Operation context\n * @returns Modified results or void to pass through\n */\n afterQuery?<T extends SmrtObject>(\n className: string,\n results: T[],\n context: InterceptorContext,\n ): T[] | Promise<T[]> | void | Promise<void>;\n\n /**\n * Called before save() operations\n * @param instance - The object being saved\n * @param context - Operation context\n * @returns void (modify instance in place) or throw to block\n */\n beforeSave?(\n instance: SmrtObject,\n context: InterceptorContext,\n ): void | Promise<void>;\n\n /**\n * Called after save() operations\n * @param instance - The saved object\n * @param context - Operation context\n */\n afterSave?(\n instance: SmrtObject,\n context: InterceptorContext,\n ): void | Promise<void>;\n\n /**\n * Called before delete() operations\n * @param instance - The object being deleted\n * @param context - Operation context\n * @returns void or throw to block\n */\n beforeDelete?(\n instance: SmrtObject,\n context: InterceptorContext,\n ): void | Promise<void>;\n\n /**\n * Called after delete() operations\n * @param instance - The deleted object\n * @param context - Operation context\n */\n afterDelete?(\n instance: SmrtObject,\n context: InterceptorContext,\n ): void | Promise<void>;\n}\n\n/**\n * Extend globalThis to include interceptors state.\n * Using globalThis ensures all module instances share the same interceptors,\n * which is critical in monorepos where the same package can be loaded\n * from different paths.\n *\n * @see ObjectRegistry for similar pattern\n */\ndeclare global {\n // eslint-disable-next-line no-var\n var __smrtInterceptors: unknown[] | undefined;\n}\n\n/**\n * Global Interceptors Registry\n *\n * Manages collection/object interceptors for the SMRT framework.\n * External packages can register interceptors to hook into operations\n * without modifying core code.\n */\nexport class GlobalInterceptors {\n /**\n * Get the global interceptors array (lazy-initialized)\n */\n private static get interceptors(): CollectionInterceptor[] {\n if (!globalThis.__smrtInterceptors) {\n globalThis.__smrtInterceptors = [];\n }\n return globalThis.__smrtInterceptors as CollectionInterceptor[];\n }\n\n /**\n * Register an interceptor\n *\n * @param interceptor - The interceptor to register\n * @example\n * ```typescript\n * GlobalInterceptors.register({\n * name: 'tenancy',\n * priority: 100,\n * beforeList(className, options) {\n * // Add tenant filtering\n * return { ...options, where: { ...options.where, tenantId: 'xxx' } };\n * }\n * });\n * ```\n */\n static register(interceptor: CollectionInterceptor): void {\n // Check for duplicate by name\n if (interceptor.name) {\n const existing = this.interceptors.findIndex(\n (i) => i.name === interceptor.name,\n );\n if (existing >= 0) {\n // Replace existing interceptor with same name\n this.interceptors[existing] = interceptor;\n this.sortByPriority();\n return;\n }\n }\n\n this.interceptors.push(interceptor);\n this.sortByPriority();\n }\n\n /**\n * Unregister an interceptor by reference or name\n *\n * @param interceptorOrName - The interceptor instance or name to remove\n * @returns true if removed, false if not found\n */\n static unregister(\n interceptorOrName: CollectionInterceptor | string,\n ): boolean {\n const idx =\n typeof interceptorOrName === 'string'\n ? this.interceptors.findIndex((i) => i.name === interceptorOrName)\n : this.interceptors.indexOf(interceptorOrName);\n\n if (idx >= 0) {\n this.interceptors.splice(idx, 1);\n return true;\n }\n return false;\n }\n\n /**\n * Clear all interceptors (useful for testing)\n */\n static clear(): void {\n globalThis.__smrtInterceptors = [];\n }\n\n /**\n * Get all registered interceptors (readonly)\n */\n static getAll(): readonly CollectionInterceptor[] {\n return [...this.interceptors];\n }\n\n /**\n * Check if any interceptors are registered\n */\n static hasInterceptors(): boolean {\n return this.interceptors.length > 0;\n }\n\n /**\n * Sort interceptors by priority (higher priority first)\n */\n private static sortByPriority(): void {\n this.interceptors.sort((a, b) => (b.priority ?? 0) - (a.priority ?? 0));\n }\n\n // ─────────────────────────────────────────────────────────────────────────\n // Execution methods - called by SmrtCollection and SmrtObject\n // ─────────────────────────────────────────────────────────────────────────\n\n /**\n * Execute beforeList interceptors\n * @internal Called by SmrtCollection.list()\n */\n static async executeBeforeList(\n className: string,\n options: ListOptions,\n context: InterceptorContext,\n ): Promise<ListOptions> {\n let result = options;\n\n for (const interceptor of this.interceptors) {\n if (interceptor.beforeList) {\n const modified = await interceptor.beforeList(\n className,\n result,\n context,\n );\n if (modified !== undefined && modified !== null) {\n result = modified;\n }\n }\n }\n\n return result;\n }\n\n /**\n * Execute afterList interceptors\n * @internal Called by SmrtCollection.list()\n */\n static async executeAfterList<T extends SmrtObject>(\n className: string,\n results: T[],\n context: InterceptorContext,\n ): Promise<T[]> {\n let result = results;\n\n for (const interceptor of this.interceptors) {\n if (interceptor.afterList) {\n const modified = await interceptor.afterList(\n className,\n result,\n context,\n );\n if (modified !== undefined && modified !== null) {\n result = modified as T[];\n }\n }\n }\n\n return result;\n }\n\n /**\n * Execute beforeGet interceptors\n * @internal Called by SmrtCollection.get()\n */\n static async executeBeforeGet(\n className: string,\n filter: string | Record<string, unknown>,\n context: InterceptorContext,\n ): Promise<string | Record<string, unknown>> {\n let result = filter;\n\n for (const interceptor of this.interceptors) {\n if (interceptor.beforeGet) {\n const modified = await interceptor.beforeGet(\n className,\n result,\n context,\n );\n if (modified !== undefined && modified !== null) {\n result = modified;\n }\n }\n }\n\n return result;\n }\n\n /**\n * Execute afterGet interceptors\n * @internal Called by SmrtCollection.get()\n */\n static async executeAfterGet<T extends SmrtObject>(\n className: string,\n instance: T | null,\n context: InterceptorContext,\n ): Promise<T | null> {\n let result = instance;\n\n for (const interceptor of this.interceptors) {\n if (interceptor.afterGet) {\n const modified = await interceptor.afterGet(className, result, context);\n if (modified !== undefined) {\n result = modified as T | null;\n }\n }\n }\n\n return result;\n }\n\n /**\n * Execute beforeQuery interceptors\n * @internal Called by SmrtCollection.query()\n */\n static async executeBeforeQuery(\n className: string,\n options: QueryOptions,\n context: InterceptorContext,\n ): Promise<QueryInterceptResult> {\n let result: QueryInterceptResult = {\n sql: options.sql,\n params: options.params,\n };\n\n for (const interceptor of this.interceptors) {\n if (interceptor.beforeQuery) {\n const modified = await interceptor.beforeQuery(\n className,\n { ...options, ...result },\n context,\n );\n if (modified !== undefined && modified !== null) {\n result = modified;\n }\n }\n }\n\n return result;\n }\n\n /**\n * Execute afterQuery interceptors\n * @internal Called by SmrtCollection.query()\n */\n static async executeAfterQuery<T extends SmrtObject>(\n className: string,\n results: T[],\n context: InterceptorContext,\n ): Promise<T[]> {\n let result = results;\n\n for (const interceptor of this.interceptors) {\n if (interceptor.afterQuery) {\n const modified = await interceptor.afterQuery(\n className,\n result,\n context,\n );\n if (modified !== undefined && modified !== null) {\n result = modified as T[];\n }\n }\n }\n\n return result;\n }\n\n /**\n * Execute beforeSave interceptors\n * @internal Called by SmrtObject.save()\n */\n static async executeBeforeSave(\n instance: SmrtObject,\n context: InterceptorContext,\n ): Promise<void> {\n for (const interceptor of this.interceptors) {\n if (interceptor.beforeSave) {\n await interceptor.beforeSave(instance, context);\n }\n }\n }\n\n /**\n * Execute afterSave interceptors\n * @internal Called by SmrtObject.save()\n */\n static async executeAfterSave(\n instance: SmrtObject,\n context: InterceptorContext,\n ): Promise<void> {\n for (const interceptor of this.interceptors) {\n if (interceptor.afterSave) {\n await interceptor.afterSave(instance, context);\n }\n }\n }\n\n /**\n * Execute beforeDelete interceptors\n * @internal Called by SmrtObject.delete()\n */\n static async executeBeforeDelete(\n instance: SmrtObject,\n context: InterceptorContext,\n ): Promise<void> {\n for (const interceptor of this.interceptors) {\n if (interceptor.beforeDelete) {\n await interceptor.beforeDelete(instance, context);\n }\n }\n }\n\n /**\n * Execute afterDelete interceptors\n * @internal Called by SmrtObject.delete()\n */\n static async executeAfterDelete(\n instance: SmrtObject,\n context: InterceptorContext,\n ): Promise<void> {\n for (const interceptor of this.interceptors) {\n if (interceptor.afterDelete) {\n await interceptor.afterDelete(instance, context);\n }\n }\n }\n}\n\n/**\n * Canonical UUID shape used by `SmrtCollection.get()` to decide whether a\n * string filter is an id or a slug.\n */\nconst GET_STRING_FILTER_UUID_PATTERN =\n /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;\n\n/**\n * Resolve a string filter to the WHERE shape `SmrtCollection.get()` gives it:\n * a UUID string becomes `{ id }`, anything else becomes the natural-key lookup\n * `{ slug, context: '' }`.\n *\n * This is the single source of truth for that string-filter contract. Any\n * `beforeGet` interceptor that rewrites a string filter into an object filter\n * MUST resolve it through this helper first — the tenancy interceptor used to\n * rewrite every string to `{ id: filter, tenantId }`, which broke get-by-slug\n * under an active tenant context (null on SQLite, a uuid cast error on\n * PostgreSQL native-uuid id columns). See #2365.\n *\n * @param filter - The string filter passed to `get()`\n * @returns The object filter `get()` would build for that string\n */\nexport function resolveGetStringFilter(\n filter: string,\n): { id: string } | { slug: string; context: string } {\n return GET_STRING_FILTER_UUID_PATTERN.test(filter)\n ? { id: filter }\n : { slug: filter, context: '' };\n}\n\n/**\n * Helper function to create an interceptor context\n * @internal\n */\nexport function createInterceptorContext(\n className: string,\n operation: InterceptorContext['operation'],\n collectionName?: string,\n metadata?: Record<string, unknown>,\n): InterceptorContext {\n return {\n className,\n collectionName,\n operation,\n timestamp: new Date(),\n metadata,\n };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"interceptors.js","names":[],"sources":["../src/interceptors.ts"],"sourcesContent":["/**\n * Global Interceptors System for SMRT Collections and Objects\n *\n * Provides a plugin architecture for intercepting collection and object operations.\n * This enables external packages (like @happyvertical/smrt-tenancy) to register\n * interceptors without creating circular dependencies.\n *\n * Pattern: Static methods on GlobalInterceptors class with globalThis state\n * (matches ObjectRegistry pattern for cross-module state sharing)\n *\n * @example Basic interceptor registration\n * ```typescript\n * import { GlobalInterceptors } from '@happyvertical/smrt-core';\n *\n * // Register a beforeList interceptor\n * GlobalInterceptors.register({\n * beforeList(className, options) {\n * console.log(`Listing ${className}`);\n * return options; // Return modified options\n * }\n * });\n * ```\n *\n * @example Tenancy interceptor (from smrt-tenancy)\n * ```typescript\n * GlobalInterceptors.register({\n * beforeList(className, options, context) {\n * const tenantId = getCurrentTenantId();\n * if (tenantId && isTenantScoped(className)) {\n * return {\n * ...options,\n * where: { ...options.where, tenantId }\n * };\n * }\n * return options;\n * },\n * beforeSave(instance, context) {\n * // Validate tenant on save\n * }\n * });\n * ```\n *\n * @see https://github.com/happyvertical/smrt/issues/675\n */\n\nimport type { SmrtObject } from './object.js';\n\n/**\n * Context passed to interceptors with operation metadata\n */\nexport interface InterceptorContext {\n /** Name of the SMRT class being operated on */\n className: string;\n /** Name of the collection (if applicable) */\n collectionName?: string;\n /** Timestamp of the operation */\n timestamp: Date;\n /** Operation type for debugging */\n operation: 'list' | 'get' | 'query' | 'save' | 'delete';\n /** Additional metadata */\n metadata?: Record<string, unknown>;\n}\n\n/**\n * Options for list operations\n */\nexport interface ListOptions {\n /** AND-only object or DNF (outer OR, inner AND) collection predicate. */\n where?: Record<string, unknown> | Record<string, unknown>[][];\n orderBy?: string | string[];\n limit?: number;\n offset?: number;\n select?: readonly string[];\n include?: string[];\n [key: string]: unknown;\n}\n\n/**\n * Options for query operations (raw SQL)\n */\nexport interface QueryOptions {\n /** The raw SQL query */\n sql: string;\n /** Query parameters */\n params: unknown[];\n /** If true, allow raw SQL on tenant-scoped classes (requires explicit opt-in) */\n allowRawOnTenantScoped?: boolean;\n}\n\n/**\n * Result from query interceptor - can modify SQL or throw to block\n */\nexport interface QueryInterceptResult {\n sql: string;\n params: unknown[];\n}\n\n/**\n * Interface for collection/object interceptors\n *\n * All methods are optional. Return void to pass through unchanged,\n * or return modified data to transform the operation.\n */\nexport interface CollectionInterceptor {\n /** Unique identifier for this interceptor (for debugging/unregistration) */\n name?: string;\n\n /** Priority for execution order (higher = earlier). Default: 0 */\n priority?: number;\n\n /**\n * Called before list() operations\n * @param className - Name of the class being listed\n * @param options - List options (where, orderBy, limit, select, etc.)\n * @param context - Operation context\n * @returns Modified options or void to pass through\n */\n beforeList?(\n className: string,\n options: ListOptions,\n context: InterceptorContext,\n ): ListOptions | Promise<ListOptions> | void | Promise<void>;\n\n /**\n * Called after list() operations with results\n * @param className - Name of the class\n * @param results - Array of hydrated instances\n * @param context - Operation context\n * @returns Modified results or void to pass through\n */\n afterList?<T extends SmrtObject>(\n className: string,\n results: T[],\n context: InterceptorContext,\n ): T[] | Promise<T[]> | void | Promise<void>;\n\n /**\n * Called before get() operations\n * @param className - Name of the class\n * @param filter - ID, slug, or filter object\n * @param context - Operation context\n * @returns Modified filter or void to pass through\n */\n beforeGet?(\n className: string,\n filter: string | Record<string, unknown>,\n context: InterceptorContext,\n ):\n | string\n | Record<string, unknown>\n | Promise<string | Record<string, unknown>>\n | void\n | Promise<void>;\n\n /**\n * Called after get() operations with result\n * @param className - Name of the class\n * @param instance - Hydrated instance or null if not found\n * @param context - Operation context\n * @returns Modified instance, null, or void to pass through\n */\n afterGet?<T extends SmrtObject>(\n className: string,\n instance: T | null,\n context: InterceptorContext,\n ): T | null | Promise<T | null> | void | Promise<void>;\n\n /**\n * Called before query() operations (raw SQL)\n * @param className - Name of the class\n * @param options - Query options with SQL and params\n * @param context - Operation context\n * @returns Modified query options, or throw to block the query\n */\n beforeQuery?(\n className: string,\n options: QueryOptions,\n context: InterceptorContext,\n ):\n | QueryInterceptResult\n | Promise<QueryInterceptResult>\n | void\n | Promise<void>;\n\n /**\n * Called after query() operations with results\n * @param className - Name of the class\n * @param results - Array of hydrated instances\n * @param context - Operation context\n * @returns Modified results or void to pass through\n */\n afterQuery?<T extends SmrtObject>(\n className: string,\n results: T[],\n context: InterceptorContext,\n ): T[] | Promise<T[]> | void | Promise<void>;\n\n /**\n * Called before save() operations\n * @param instance - The object being saved\n * @param context - Operation context\n * @returns void (modify instance in place) or throw to block\n */\n beforeSave?(\n instance: SmrtObject,\n context: InterceptorContext,\n ): void | Promise<void>;\n\n /**\n * Called after save() operations\n * @param instance - The saved object\n * @param context - Operation context\n */\n afterSave?(\n instance: SmrtObject,\n context: InterceptorContext,\n ): void | Promise<void>;\n\n /**\n * Called before delete() operations\n * @param instance - The object being deleted\n * @param context - Operation context\n * @returns void or throw to block\n */\n beforeDelete?(\n instance: SmrtObject,\n context: InterceptorContext,\n ): void | Promise<void>;\n\n /**\n * Called after delete() operations\n * @param instance - The deleted object\n * @param context - Operation context\n */\n afterDelete?(\n instance: SmrtObject,\n context: InterceptorContext,\n ): void | Promise<void>;\n}\n\n/**\n * Extend globalThis to include interceptors state.\n * Using globalThis ensures all module instances share the same interceptors,\n * which is critical in monorepos where the same package can be loaded\n * from different paths.\n *\n * @see ObjectRegistry for similar pattern\n */\ndeclare global {\n // eslint-disable-next-line no-var\n var __smrtInterceptors: unknown[] | undefined;\n}\n\n/**\n * Global Interceptors Registry\n *\n * Manages collection/object interceptors for the SMRT framework.\n * External packages can register interceptors to hook into operations\n * without modifying core code.\n */\nexport class GlobalInterceptors {\n /**\n * Get the global interceptors array (lazy-initialized)\n */\n private static get interceptors(): CollectionInterceptor[] {\n if (!globalThis.__smrtInterceptors) {\n globalThis.__smrtInterceptors = [];\n }\n return globalThis.__smrtInterceptors as CollectionInterceptor[];\n }\n\n /**\n * Register an interceptor\n *\n * @param interceptor - The interceptor to register\n * @example\n * ```typescript\n * GlobalInterceptors.register({\n * name: 'tenancy',\n * priority: 100,\n * beforeList(className, options) {\n * // Add tenant filtering\n * return { ...options, where: { ...options.where, tenantId: 'xxx' } };\n * }\n * });\n * ```\n */\n static register(interceptor: CollectionInterceptor): void {\n // Check for duplicate by name\n if (interceptor.name) {\n const existing = this.interceptors.findIndex(\n (i) => i.name === interceptor.name,\n );\n if (existing >= 0) {\n // Replace existing interceptor with same name\n this.interceptors[existing] = interceptor;\n this.sortByPriority();\n return;\n }\n }\n\n this.interceptors.push(interceptor);\n this.sortByPriority();\n }\n\n /**\n * Unregister an interceptor by reference or name\n *\n * @param interceptorOrName - The interceptor instance or name to remove\n * @returns true if removed, false if not found\n */\n static unregister(\n interceptorOrName: CollectionInterceptor | string,\n ): boolean {\n const idx =\n typeof interceptorOrName === 'string'\n ? this.interceptors.findIndex((i) => i.name === interceptorOrName)\n : this.interceptors.indexOf(interceptorOrName);\n\n if (idx >= 0) {\n this.interceptors.splice(idx, 1);\n return true;\n }\n return false;\n }\n\n /**\n * Clear all interceptors (useful for testing)\n */\n static clear(): void {\n globalThis.__smrtInterceptors = [];\n }\n\n /**\n * Get all registered interceptors (readonly)\n */\n static getAll(): readonly CollectionInterceptor[] {\n return [...this.interceptors];\n }\n\n /**\n * Check if any interceptors are registered\n */\n static hasInterceptors(): boolean {\n return this.interceptors.length > 0;\n }\n\n /**\n * Sort interceptors by priority (higher priority first)\n */\n private static sortByPriority(): void {\n this.interceptors.sort((a, b) => (b.priority ?? 0) - (a.priority ?? 0));\n }\n\n // ─────────────────────────────────────────────────────────────────────────\n // Execution methods - called by SmrtCollection and SmrtObject\n // ─────────────────────────────────────────────────────────────────────────\n\n /**\n * Execute beforeList interceptors\n * @internal Called by SmrtCollection.list()\n */\n static async executeBeforeList(\n className: string,\n options: ListOptions,\n context: InterceptorContext,\n ): Promise<ListOptions> {\n let result = options;\n\n for (const interceptor of this.interceptors) {\n if (interceptor.beforeList) {\n const modified = await interceptor.beforeList(\n className,\n result,\n context,\n );\n if (modified !== undefined && modified !== null) {\n result = modified;\n }\n }\n }\n\n return result;\n }\n\n /**\n * Execute afterList interceptors\n * @internal Called by SmrtCollection.list()\n */\n static async executeAfterList<T extends SmrtObject>(\n className: string,\n results: T[],\n context: InterceptorContext,\n ): Promise<T[]> {\n let result = results;\n\n for (const interceptor of this.interceptors) {\n if (interceptor.afterList) {\n const modified = await interceptor.afterList(\n className,\n result,\n context,\n );\n if (modified !== undefined && modified !== null) {\n result = modified as T[];\n }\n }\n }\n\n return result;\n }\n\n /**\n * Execute beforeGet interceptors\n * @internal Called by SmrtCollection.get()\n */\n static async executeBeforeGet(\n className: string,\n filter: string | Record<string, unknown>,\n context: InterceptorContext,\n ): Promise<string | Record<string, unknown>> {\n let result = filter;\n\n for (const interceptor of this.interceptors) {\n if (interceptor.beforeGet) {\n const modified = await interceptor.beforeGet(\n className,\n result,\n context,\n );\n if (modified !== undefined && modified !== null) {\n result = modified;\n }\n }\n }\n\n return result;\n }\n\n /**\n * Execute afterGet interceptors\n * @internal Called by SmrtCollection.get()\n */\n static async executeAfterGet<T extends SmrtObject>(\n className: string,\n instance: T | null,\n context: InterceptorContext,\n ): Promise<T | null> {\n let result = instance;\n\n for (const interceptor of this.interceptors) {\n if (interceptor.afterGet) {\n const modified = await interceptor.afterGet(className, result, context);\n if (modified !== undefined) {\n result = modified as T | null;\n }\n }\n }\n\n return result;\n }\n\n /**\n * Execute beforeQuery interceptors\n * @internal Called by SmrtCollection.query()\n */\n static async executeBeforeQuery(\n className: string,\n options: QueryOptions,\n context: InterceptorContext,\n ): Promise<QueryInterceptResult> {\n let result: QueryInterceptResult = {\n sql: options.sql,\n params: options.params,\n };\n\n for (const interceptor of this.interceptors) {\n if (interceptor.beforeQuery) {\n const modified = await interceptor.beforeQuery(\n className,\n { ...options, ...result },\n context,\n );\n if (modified !== undefined && modified !== null) {\n result = modified;\n }\n }\n }\n\n return result;\n }\n\n /**\n * Execute afterQuery interceptors\n * @internal Called by SmrtCollection.query()\n */\n static async executeAfterQuery<T extends SmrtObject>(\n className: string,\n results: T[],\n context: InterceptorContext,\n ): Promise<T[]> {\n let result = results;\n\n for (const interceptor of this.interceptors) {\n if (interceptor.afterQuery) {\n const modified = await interceptor.afterQuery(\n className,\n result,\n context,\n );\n if (modified !== undefined && modified !== null) {\n result = modified as T[];\n }\n }\n }\n\n return result;\n }\n\n /**\n * Execute beforeSave interceptors\n * @internal Called by SmrtObject.save()\n */\n static async executeBeforeSave(\n instance: SmrtObject,\n context: InterceptorContext,\n ): Promise<void> {\n for (const interceptor of this.interceptors) {\n if (interceptor.beforeSave) {\n await interceptor.beforeSave(instance, context);\n }\n }\n }\n\n /**\n * Execute afterSave interceptors\n * @internal Called by SmrtObject.save()\n */\n static async executeAfterSave(\n instance: SmrtObject,\n context: InterceptorContext,\n ): Promise<void> {\n for (const interceptor of this.interceptors) {\n if (interceptor.afterSave) {\n await interceptor.afterSave(instance, context);\n }\n }\n }\n\n /**\n * Execute beforeDelete interceptors\n * @internal Called by SmrtObject.delete()\n */\n static async executeBeforeDelete(\n instance: SmrtObject,\n context: InterceptorContext,\n ): Promise<void> {\n for (const interceptor of this.interceptors) {\n if (interceptor.beforeDelete) {\n await interceptor.beforeDelete(instance, context);\n }\n }\n }\n\n /**\n * Execute afterDelete interceptors\n * @internal Called by SmrtObject.delete()\n */\n static async executeAfterDelete(\n instance: SmrtObject,\n context: InterceptorContext,\n ): Promise<void> {\n for (const interceptor of this.interceptors) {\n if (interceptor.afterDelete) {\n await interceptor.afterDelete(instance, context);\n }\n }\n }\n}\n\n/**\n * Canonical UUID shape used by `SmrtCollection.get()` to decide whether a\n * string filter is an id or a slug.\n */\nconst GET_STRING_FILTER_UUID_PATTERN =\n /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;\n\n/**\n * Resolve a string filter to the WHERE shape `SmrtCollection.get()` gives it:\n * a UUID string becomes `{ id }`, anything else becomes the natural-key lookup\n * `{ slug, context: '' }`.\n *\n * This is the single source of truth for that string-filter contract. Any\n * `beforeGet` interceptor that rewrites a string filter into an object filter\n * MUST resolve it through this helper first — the tenancy interceptor used to\n * rewrite every string to `{ id: filter, tenantId }`, which broke get-by-slug\n * under an active tenant context (null on SQLite, a uuid cast error on\n * PostgreSQL native-uuid id columns). See #2365.\n *\n * @param filter - The string filter passed to `get()`\n * @returns The object filter `get()` would build for that string\n */\nexport function resolveGetStringFilter(\n filter: string,\n): { id: string } | { slug: string; context: string } {\n return GET_STRING_FILTER_UUID_PATTERN.test(filter)\n ? { id: filter }\n : { slug: filter, context: '' };\n}\n\n/**\n * Helper function to create an interceptor context\n * @internal\n */\nexport function createInterceptorContext(\n className: string,\n operation: InterceptorContext['operation'],\n collectionName?: string,\n metadata?: Record<string, unknown>,\n): InterceptorContext {\n return {\n className,\n collectionName,\n operation,\n timestamp: new Date(),\n metadata,\n };\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"static-manifest.d.ts","sourceRoot":"","sources":["../../src/manifest/static-manifest.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAE/D,eAAO,MAAM,cAAc,EAAE,mBAu1CnB,CAAC;AAEX,eAAe,cAAc,CAAC"}
1
+ {"version":3,"file":"static-manifest.d.ts","sourceRoot":"","sources":["../../src/manifest/static-manifest.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAE/D,eAAO,MAAM,cAAc,EAAE,mBAo5CnB,CAAC;AAEX,eAAe,cAAc,CAAC"}
@@ -3,7 +3,7 @@ var staticManifest = {
3
3
  "version": "1.0.0",
4
4
  "timestamp": 0,
5
5
  "packageName": "@happyvertical/smrt-core",
6
- "packageVersion": "0.42.6",
6
+ "packageVersion": "0.43.0",
7
7
  "objects": {
8
8
  "@happyvertical/smrt-core:SmrtClass": {
9
9
  "name": "smrtclass",
@@ -14,6 +14,22 @@ var staticManifest = {
14
14
  "packageName": "@happyvertical/smrt-core",
15
15
  "fields": {},
16
16
  "methods": {
17
+ "withDatabase": {
18
+ "name": "withDatabase",
19
+ "async": true,
20
+ "parameters": [{
21
+ "name": "db",
22
+ "type": "DatabaseInterface",
23
+ "optional": false
24
+ }, {
25
+ "name": "operation",
26
+ "type": "Function",
27
+ "optional": false
28
+ }],
29
+ "returnType": "Promise<T>",
30
+ "isStatic": false,
31
+ "isPublic": true
32
+ },
17
33
  "getAiUsageSnapshot": {
18
34
  "name": "getAiUsageSnapshot",
19
35
  "async": false,
@@ -116,6 +132,18 @@ var staticManifest = {
116
132
  "packageName": "@happyvertical/smrt-core",
117
133
  "fields": {},
118
134
  "methods": {
135
+ "listWithLatestRelated": {
136
+ "name": "listWithLatestRelated",
137
+ "async": true,
138
+ "parameters": [{
139
+ "name": "options",
140
+ "type": "SmrtLatestRelatedListOptions<ModelType>",
141
+ "optional": false
142
+ }],
143
+ "returnType": "Promise<SmrtLatestRelatedRow<ModelType>[]>",
144
+ "isStatic": false,
145
+ "isPublic": true
146
+ },
119
147
  "getItemClass": {
120
148
  "name": "getItemClass",
121
149
  "async": false,
@@ -324,6 +352,30 @@ var staticManifest = {
324
352
  "isStatic": false,
325
353
  "isPublic": true
326
354
  },
355
+ "facets": {
356
+ "name": "facets",
357
+ "async": true,
358
+ "parameters": [{
359
+ "name": "options",
360
+ "type": "SmrtFacetOptions<ModelType>",
361
+ "optional": false
362
+ }],
363
+ "returnType": "Promise<SmrtFacetResult[]>",
364
+ "isStatic": false,
365
+ "isPublic": true
366
+ },
367
+ "counts": {
368
+ "name": "counts",
369
+ "async": true,
370
+ "parameters": [{
371
+ "name": "options",
372
+ "type": "object",
373
+ "optional": true
374
+ }],
375
+ "returnType": "Promise<SmrtCollectionCounts>",
376
+ "isStatic": false,
377
+ "isPublic": true
378
+ },
327
379
  "getStiChildMetaType": {
328
380
  "name": "getStiChildMetaType",
329
381
  "async": false,