@invect/core 0.0.1 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/database/core-schema.cjs.map +1 -1
- package/dist/database/core-schema.js.map +1 -1
- package/dist/database/prisma-schema-generator.cjs +2 -2
- package/dist/database/prisma-schema-generator.cjs.map +1 -1
- package/dist/database/prisma-schema-generator.js +2 -2
- package/dist/database/prisma-schema-generator.js.map +1 -1
- package/dist/database/schema-generator.cjs +6 -6
- package/dist/database/schema-generator.cjs.map +1 -1
- package/dist/database/schema-generator.js +6 -6
- package/dist/database/schema-generator.js.map +1 -1
- package/dist/database/schema-merger.cjs.map +1 -1
- package/dist/database/schema-merger.js.map +1 -1
- package/dist/database/schema-verification.cjs +1 -1
- package/dist/database/schema-verification.cjs.map +1 -1
- package/dist/database/schema-verification.js +1 -1
- package/dist/database/schema-verification.js.map +1 -1
- package/dist/services/database/database.service.cjs +3 -3
- package/dist/services/database/database.service.cjs.map +1 -1
- package/dist/services/database/database.service.js +3 -3
- package/dist/services/database/database.service.js.map +1 -1
- package/dist/types/plugin.types.d.cts +1 -1
- package/dist/types/plugin.types.d.ts +1 -1
- package/dist/types/schemas-fresh/invect-config.cjs.map +1 -1
- package/dist/types/schemas-fresh/invect-config.js.map +1 -1
- package/package.json +2 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"core-schema.cjs","names":[],"sources":["../../src/database/core-schema.ts"],"sourcesContent":["/**\n * Core Abstract Schema\n *\n * The single source of truth for Invect's database tables.\n * Defined using the abstract `InvectPluginSchema` format.\n *\n * The CLI schema generator (`npx invect generate`) uses this + plugin schemas\n * to produce the three dialect-specific Drizzle schema files:\n * - schema-sqlite.ts\n * - schema-postgres.ts\n * - schema-mysql.ts\n *\n * When modifying the database schema, edit THIS file, then run `npx invect generate`.\n */\n\nimport type { InvectPluginSchema } from 'src/types/plugin.types';\n\n// =============================================================================\n// Enum Definitions\n// =============================================================================\n\n/**\n * Enum value sets used across the schema.\n * The generator creates pgEnum / mysqlEnum from these.\n */\nexport const CORE_ENUMS = {\n flowRunStatus: [\n 'PENDING',\n 'RUNNING',\n 'SUCCESS',\n 'FAILED',\n 'CANCELLED',\n 'PAUSED',\n 'PAUSED_FOR_BATCH',\n ],\n nodeExecutionStatus: [\n 'PENDING',\n 'RUNNING',\n 'SUCCESS',\n 'FAILED',\n 'SKIPPED',\n 'BATCH_SUBMITTED',\n 'BATCH_PROCESSING',\n ],\n batchStatus: ['SUBMITTED', 'PROCESSING', 'COMPLETED', 'FAILED', 'CANCELLED'],\n batchProvider: ['OPENAI', 'ANTHROPIC'],\n} as const;\n\n// =============================================================================\n// Core Schema Definition\n// =============================================================================\n\nexport const CORE_SCHEMA: InvectPluginSchema = {\n // ----- Flow definition table -----\n flows: {\n tableName: 'flows',\n order: 10,\n fields: {\n id: { type: 'string', primaryKey: true },\n name: { type: 'string', required: true },\n description: { type: 'string', required: false },\n tags: { type: 'json', required: false, typeAnnotation: 'string[]' },\n isActive: { type: 'boolean', required: true, defaultValue: true },\n liveVersionNumber: { type: 'number', required: false },\n createdAt: { type: 'date', required: true, defaultValue: 'now()' },\n updatedAt: { type: 'date', required: true, defaultValue: 'now()' },\n },\n },\n\n // ----- Flow version table -----\n flowVersions: {\n tableName: 'flow_versions',\n order: 20,\n compositePrimaryKey: ['version', 'flowId'],\n fields: {\n flowId: {\n type: 'string',\n required: true,\n references: { table: 'flows', field: 'id', onDelete: 'cascade' },\n },\n version: { type: 'number', required: true },\n invectDefinition: {\n type: 'json',\n required: true,\n typeAnnotation: 'InvectDefinitionRuntime',\n },\n createdAt: { type: 'date', required: true, defaultValue: 'now()' },\n createdBy: { type: 'string', required: false },\n },\n },\n\n // ----- Flow execution (runs) table -----\n flowRuns: {\n tableName: 'flow_executions',\n order: 30,\n fields: {\n id: { type: 'uuid', primaryKey: true, defaultValue: 'uuid()' },\n flowId: {\n type: 'string',\n required: true,\n references: { table: 'flows', field: 'id', onDelete: 'cascade' },\n },\n flowVersion: { type: 'number', required: true },\n status: {\n type: [...CORE_ENUMS.flowRunStatus],\n required: true,\n defaultValue: 'PENDING',\n typeAnnotation: 'FlowRunStatus',\n },\n inputs: { type: 'json', required: true, typeAnnotation: 'JSONValue' },\n outputs: { type: 'json', required: false, typeAnnotation: 'JSONValue' },\n error: { type: 'text', required: false },\n startedAt: { type: 'date', required: true, defaultValue: 'now()' },\n completedAt: { type: 'date', required: false },\n duration: { type: 'number', required: false },\n createdBy: { type: 'string', required: false },\n // Trigger provenance\n triggerType: { type: 'string', required: false },\n triggerId: { type: 'string', required: false },\n triggerNodeId: { type: 'string', required: false },\n triggerData: { type: 'json', required: false, typeAnnotation: 'JSONValue' },\n lastHeartbeatAt: { type: 'date', required: false },\n },\n },\n\n // ----- Execution traces (node executions) table -----\n nodeExecutions: {\n tableName: 'execution_traces',\n order: 40,\n fields: {\n id: { type: 'uuid', primaryKey: true, defaultValue: 'uuid()' },\n flowRunId: {\n type: 'uuid',\n required: true,\n references: { table: 'flow_executions', field: 'id', onDelete: 'cascade' },\n },\n nodeId: { type: 'string', required: true },\n nodeType: { type: 'string', required: true },\n status: {\n type: [...CORE_ENUMS.nodeExecutionStatus],\n required: true,\n defaultValue: 'PENDING',\n typeAnnotation: 'NodeExecutionStatus',\n },\n inputs: { type: 'json', required: true, typeAnnotation: 'JSONValue' },\n outputs: { type: 'json', required: false, typeAnnotation: 'JSONValue' },\n error: { type: 'text', required: false },\n startedAt: { type: 'date', required: true, defaultValue: 'now()' },\n completedAt: { type: 'date', required: false },\n duration: { type: 'number', required: false },\n retryCount: { type: 'number', required: true, defaultValue: 0 },\n },\n },\n\n // ----- Batch jobs table -----\n batchJobs: {\n tableName: 'batch_jobs',\n order: 50,\n fields: {\n id: { type: 'uuid', primaryKey: true, defaultValue: 'uuid()' },\n flowRunId: {\n type: 'uuid',\n required: true,\n references: { table: 'flow_executions', field: 'id', onDelete: 'cascade' },\n },\n nodeId: { type: 'string', required: true },\n provider: {\n type: [...CORE_ENUMS.batchProvider],\n required: true,\n typeAnnotation: 'BatchProvider',\n },\n batchId: { type: 'string', required: false },\n status: {\n type: [...CORE_ENUMS.batchStatus],\n required: true,\n defaultValue: 'SUBMITTED',\n typeAnnotation: 'BatchStatus',\n },\n requestData: { type: 'json', required: true },\n responseData: { type: 'json', required: false },\n error: { type: 'text', required: false },\n submittedAt: { type: 'date', required: true, defaultValue: 'now()' },\n completedAt: { type: 'date', required: false },\n createdAt: { type: 'date', required: true, defaultValue: 'now()' },\n updatedAt: { type: 'date', required: true, defaultValue: 'now()' },\n },\n },\n\n // ----- Agent tool executions table -----\n agentToolExecutions: {\n tableName: 'agent_tool_executions',\n order: 60,\n fields: {\n id: { type: 'uuid', primaryKey: true, defaultValue: 'uuid()' },\n nodeExecutionId: {\n type: 'uuid',\n required: true,\n references: { table: 'execution_traces', field: 'id', onDelete: 'cascade' },\n },\n flowRunId: {\n type: 'uuid',\n required: true,\n references: { table: 'flow_executions', field: 'id', onDelete: 'cascade' },\n },\n toolId: { type: 'string', required: true },\n toolName: { type: 'string', required: true },\n iteration: { type: 'number', required: true },\n input: { type: 'json', required: true, typeAnnotation: 'JSONValue' },\n output: { type: 'json', required: false, typeAnnotation: 'JSONValue' },\n error: { type: 'text', required: false },\n success: { type: 'boolean', required: true },\n startedAt: { type: 'date', required: true, defaultValue: 'now()' },\n completedAt: { type: 'date', required: false },\n duration: { type: 'number', required: false },\n },\n },\n\n // ----- Credentials table -----\n credentials: {\n tableName: 'credentials',\n order: 10,\n fields: {\n id: { type: 'uuid', primaryKey: true, defaultValue: 'uuid()' },\n name: { type: 'string', required: true },\n type: { type: 'string', required: true, typeAnnotation: 'CredentialType' },\n authType: { type: 'string', required: true, typeAnnotation: 'CredentialAuthType' },\n config: { type: 'json', required: true, typeAnnotation: 'CredentialConfig' },\n description: { type: 'text', required: false },\n isActive: { type: 'boolean', required: true, defaultValue: true },\n workspaceId: { type: 'string', required: false },\n isShared: { type: 'boolean', required: true, defaultValue: false },\n metadata: { type: 'json', required: false, typeAnnotation: 'Record<string, unknown>' },\n lastUsedAt: { type: 'date', required: false },\n expiresAt: { type: 'date', required: false },\n webhookPath: { type: 'string', required: false, unique: true },\n webhookSecret: { type: 'string', required: false },\n createdAt: { type: 'date', required: true, defaultValue: 'now()' },\n updatedAt: { type: 'date', required: true, defaultValue: 'now()' },\n },\n },\n\n // ----- Flow triggers table -----\n flowTriggers: {\n tableName: 'flow_triggers',\n order: 20,\n fields: {\n id: { type: 'uuid', primaryKey: true, defaultValue: 'uuid()' },\n flowId: {\n type: 'string',\n required: true,\n references: { table: 'flows', field: 'id', onDelete: 'cascade' },\n },\n nodeId: { type: 'string', required: true },\n type: { type: 'string', required: true, typeAnnotation: 'TriggerType' },\n isEnabled: { type: 'boolean', required: true, defaultValue: true },\n webhookPath: { type: 'string', required: false, unique: true },\n webhookSecret: { type: 'string', required: false },\n cronExpression: { type: 'string', required: false },\n cronTimezone: { type: 'string', required: false },\n lastTriggeredAt: { type: 'date', required: false },\n createdAt: { type: 'date', required: true, defaultValue: 'now()' },\n updatedAt: { type: 'date', required: true, defaultValue: 'now()' },\n },\n },\n\n // ----- Chat messages table -----\n chatMessages: {\n tableName: 'chat_messages',\n order: 30,\n fields: {\n id: { type: 'uuid', primaryKey: true, defaultValue: 'uuid()' },\n flowId: {\n type: 'string',\n required: true,\n references: { table: 'flows', field: 'id', onDelete: 'cascade' },\n },\n role: {\n type: 'string',\n required: true,\n typeAnnotation: \"'user' | 'assistant' | 'system' | 'tool'\",\n },\n content: { type: 'text', required: true, defaultValue: '' },\n toolMeta: { type: 'json', required: false, typeAnnotation: 'Record<string, unknown>' },\n createdAt: { type: 'date', required: true, defaultValue: 'now()' },\n },\n },\n\n // ----- Flow access control (RBAC) table -----\n flowAccess: {\n tableName: 'flow_access',\n order: 20,\n fields: {\n id: { type: 'uuid', primaryKey: true, defaultValue: 'uuid()' },\n flowId: {\n type: 'string',\n required: true,\n references: { table: 'flows', field: 'id', onDelete: 'cascade' },\n },\n userId: { type: 'string', required: false },\n teamId: { type: 'string', required: false },\n permission: {\n type: 'string',\n required: true,\n defaultValue: 'viewer',\n typeAnnotation: 'FlowAccessPermission',\n },\n grantedBy: { type: 'string', required: false },\n grantedAt: { type: 'date', required: true, defaultValue: 'now()' },\n expiresAt: { type: 'date', required: false },\n },\n },\n};\n\n/**\n * List of core table names (used by the merger to detect\n * when a plugin extends a core table vs. creates a new one).\n */\nexport const CORE_TABLE_NAMES = Object.keys(CORE_SCHEMA);\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"core-schema.cjs","names":[],"sources":["../../src/database/core-schema.ts"],"sourcesContent":["/**\n * Core Abstract Schema\n *\n * The single source of truth for Invect's database tables.\n * Defined using the abstract `InvectPluginSchema` format.\n *\n * The CLI schema generator (`npx invect-cli generate`) uses this + plugin schemas\n * to produce the three dialect-specific Drizzle schema files:\n * - schema-sqlite.ts\n * - schema-postgres.ts\n * - schema-mysql.ts\n *\n * When modifying the database schema, edit THIS file, then run `npx invect-cli generate`.\n */\n\nimport type { InvectPluginSchema } from 'src/types/plugin.types';\n\n// =============================================================================\n// Enum Definitions\n// =============================================================================\n\n/**\n * Enum value sets used across the schema.\n * The generator creates pgEnum / mysqlEnum from these.\n */\nexport const CORE_ENUMS = {\n flowRunStatus: [\n 'PENDING',\n 'RUNNING',\n 'SUCCESS',\n 'FAILED',\n 'CANCELLED',\n 'PAUSED',\n 'PAUSED_FOR_BATCH',\n ],\n nodeExecutionStatus: [\n 'PENDING',\n 'RUNNING',\n 'SUCCESS',\n 'FAILED',\n 'SKIPPED',\n 'BATCH_SUBMITTED',\n 'BATCH_PROCESSING',\n ],\n batchStatus: ['SUBMITTED', 'PROCESSING', 'COMPLETED', 'FAILED', 'CANCELLED'],\n batchProvider: ['OPENAI', 'ANTHROPIC'],\n} as const;\n\n// =============================================================================\n// Core Schema Definition\n// =============================================================================\n\nexport const CORE_SCHEMA: InvectPluginSchema = {\n // ----- Flow definition table -----\n flows: {\n tableName: 'flows',\n order: 10,\n fields: {\n id: { type: 'string', primaryKey: true },\n name: { type: 'string', required: true },\n description: { type: 'string', required: false },\n tags: { type: 'json', required: false, typeAnnotation: 'string[]' },\n isActive: { type: 'boolean', required: true, defaultValue: true },\n liveVersionNumber: { type: 'number', required: false },\n createdAt: { type: 'date', required: true, defaultValue: 'now()' },\n updatedAt: { type: 'date', required: true, defaultValue: 'now()' },\n },\n },\n\n // ----- Flow version table -----\n flowVersions: {\n tableName: 'flow_versions',\n order: 20,\n compositePrimaryKey: ['version', 'flowId'],\n fields: {\n flowId: {\n type: 'string',\n required: true,\n references: { table: 'flows', field: 'id', onDelete: 'cascade' },\n },\n version: { type: 'number', required: true },\n invectDefinition: {\n type: 'json',\n required: true,\n typeAnnotation: 'InvectDefinitionRuntime',\n },\n createdAt: { type: 'date', required: true, defaultValue: 'now()' },\n createdBy: { type: 'string', required: false },\n },\n },\n\n // ----- Flow execution (runs) table -----\n flowRuns: {\n tableName: 'flow_executions',\n order: 30,\n fields: {\n id: { type: 'uuid', primaryKey: true, defaultValue: 'uuid()' },\n flowId: {\n type: 'string',\n required: true,\n references: { table: 'flows', field: 'id', onDelete: 'cascade' },\n },\n flowVersion: { type: 'number', required: true },\n status: {\n type: [...CORE_ENUMS.flowRunStatus],\n required: true,\n defaultValue: 'PENDING',\n typeAnnotation: 'FlowRunStatus',\n },\n inputs: { type: 'json', required: true, typeAnnotation: 'JSONValue' },\n outputs: { type: 'json', required: false, typeAnnotation: 'JSONValue' },\n error: { type: 'text', required: false },\n startedAt: { type: 'date', required: true, defaultValue: 'now()' },\n completedAt: { type: 'date', required: false },\n duration: { type: 'number', required: false },\n createdBy: { type: 'string', required: false },\n // Trigger provenance\n triggerType: { type: 'string', required: false },\n triggerId: { type: 'string', required: false },\n triggerNodeId: { type: 'string', required: false },\n triggerData: { type: 'json', required: false, typeAnnotation: 'JSONValue' },\n lastHeartbeatAt: { type: 'date', required: false },\n },\n },\n\n // ----- Execution traces (node executions) table -----\n nodeExecutions: {\n tableName: 'execution_traces',\n order: 40,\n fields: {\n id: { type: 'uuid', primaryKey: true, defaultValue: 'uuid()' },\n flowRunId: {\n type: 'uuid',\n required: true,\n references: { table: 'flow_executions', field: 'id', onDelete: 'cascade' },\n },\n nodeId: { type: 'string', required: true },\n nodeType: { type: 'string', required: true },\n status: {\n type: [...CORE_ENUMS.nodeExecutionStatus],\n required: true,\n defaultValue: 'PENDING',\n typeAnnotation: 'NodeExecutionStatus',\n },\n inputs: { type: 'json', required: true, typeAnnotation: 'JSONValue' },\n outputs: { type: 'json', required: false, typeAnnotation: 'JSONValue' },\n error: { type: 'text', required: false },\n startedAt: { type: 'date', required: true, defaultValue: 'now()' },\n completedAt: { type: 'date', required: false },\n duration: { type: 'number', required: false },\n retryCount: { type: 'number', required: true, defaultValue: 0 },\n },\n },\n\n // ----- Batch jobs table -----\n batchJobs: {\n tableName: 'batch_jobs',\n order: 50,\n fields: {\n id: { type: 'uuid', primaryKey: true, defaultValue: 'uuid()' },\n flowRunId: {\n type: 'uuid',\n required: true,\n references: { table: 'flow_executions', field: 'id', onDelete: 'cascade' },\n },\n nodeId: { type: 'string', required: true },\n provider: {\n type: [...CORE_ENUMS.batchProvider],\n required: true,\n typeAnnotation: 'BatchProvider',\n },\n batchId: { type: 'string', required: false },\n status: {\n type: [...CORE_ENUMS.batchStatus],\n required: true,\n defaultValue: 'SUBMITTED',\n typeAnnotation: 'BatchStatus',\n },\n requestData: { type: 'json', required: true },\n responseData: { type: 'json', required: false },\n error: { type: 'text', required: false },\n submittedAt: { type: 'date', required: true, defaultValue: 'now()' },\n completedAt: { type: 'date', required: false },\n createdAt: { type: 'date', required: true, defaultValue: 'now()' },\n updatedAt: { type: 'date', required: true, defaultValue: 'now()' },\n },\n },\n\n // ----- Agent tool executions table -----\n agentToolExecutions: {\n tableName: 'agent_tool_executions',\n order: 60,\n fields: {\n id: { type: 'uuid', primaryKey: true, defaultValue: 'uuid()' },\n nodeExecutionId: {\n type: 'uuid',\n required: true,\n references: { table: 'execution_traces', field: 'id', onDelete: 'cascade' },\n },\n flowRunId: {\n type: 'uuid',\n required: true,\n references: { table: 'flow_executions', field: 'id', onDelete: 'cascade' },\n },\n toolId: { type: 'string', required: true },\n toolName: { type: 'string', required: true },\n iteration: { type: 'number', required: true },\n input: { type: 'json', required: true, typeAnnotation: 'JSONValue' },\n output: { type: 'json', required: false, typeAnnotation: 'JSONValue' },\n error: { type: 'text', required: false },\n success: { type: 'boolean', required: true },\n startedAt: { type: 'date', required: true, defaultValue: 'now()' },\n completedAt: { type: 'date', required: false },\n duration: { type: 'number', required: false },\n },\n },\n\n // ----- Credentials table -----\n credentials: {\n tableName: 'credentials',\n order: 10,\n fields: {\n id: { type: 'uuid', primaryKey: true, defaultValue: 'uuid()' },\n name: { type: 'string', required: true },\n type: { type: 'string', required: true, typeAnnotation: 'CredentialType' },\n authType: { type: 'string', required: true, typeAnnotation: 'CredentialAuthType' },\n config: { type: 'json', required: true, typeAnnotation: 'CredentialConfig' },\n description: { type: 'text', required: false },\n isActive: { type: 'boolean', required: true, defaultValue: true },\n workspaceId: { type: 'string', required: false },\n isShared: { type: 'boolean', required: true, defaultValue: false },\n metadata: { type: 'json', required: false, typeAnnotation: 'Record<string, unknown>' },\n lastUsedAt: { type: 'date', required: false },\n expiresAt: { type: 'date', required: false },\n webhookPath: { type: 'string', required: false, unique: true },\n webhookSecret: { type: 'string', required: false },\n createdAt: { type: 'date', required: true, defaultValue: 'now()' },\n updatedAt: { type: 'date', required: true, defaultValue: 'now()' },\n },\n },\n\n // ----- Flow triggers table -----\n flowTriggers: {\n tableName: 'flow_triggers',\n order: 20,\n fields: {\n id: { type: 'uuid', primaryKey: true, defaultValue: 'uuid()' },\n flowId: {\n type: 'string',\n required: true,\n references: { table: 'flows', field: 'id', onDelete: 'cascade' },\n },\n nodeId: { type: 'string', required: true },\n type: { type: 'string', required: true, typeAnnotation: 'TriggerType' },\n isEnabled: { type: 'boolean', required: true, defaultValue: true },\n webhookPath: { type: 'string', required: false, unique: true },\n webhookSecret: { type: 'string', required: false },\n cronExpression: { type: 'string', required: false },\n cronTimezone: { type: 'string', required: false },\n lastTriggeredAt: { type: 'date', required: false },\n createdAt: { type: 'date', required: true, defaultValue: 'now()' },\n updatedAt: { type: 'date', required: true, defaultValue: 'now()' },\n },\n },\n\n // ----- Chat messages table -----\n chatMessages: {\n tableName: 'chat_messages',\n order: 30,\n fields: {\n id: { type: 'uuid', primaryKey: true, defaultValue: 'uuid()' },\n flowId: {\n type: 'string',\n required: true,\n references: { table: 'flows', field: 'id', onDelete: 'cascade' },\n },\n role: {\n type: 'string',\n required: true,\n typeAnnotation: \"'user' | 'assistant' | 'system' | 'tool'\",\n },\n content: { type: 'text', required: true, defaultValue: '' },\n toolMeta: { type: 'json', required: false, typeAnnotation: 'Record<string, unknown>' },\n createdAt: { type: 'date', required: true, defaultValue: 'now()' },\n },\n },\n\n // ----- Flow access control (RBAC) table -----\n flowAccess: {\n tableName: 'flow_access',\n order: 20,\n fields: {\n id: { type: 'uuid', primaryKey: true, defaultValue: 'uuid()' },\n flowId: {\n type: 'string',\n required: true,\n references: { table: 'flows', field: 'id', onDelete: 'cascade' },\n },\n userId: { type: 'string', required: false },\n teamId: { type: 'string', required: false },\n permission: {\n type: 'string',\n required: true,\n defaultValue: 'viewer',\n typeAnnotation: 'FlowAccessPermission',\n },\n grantedBy: { type: 'string', required: false },\n grantedAt: { type: 'date', required: true, defaultValue: 'now()' },\n expiresAt: { type: 'date', required: false },\n },\n },\n};\n\n/**\n * List of core table names (used by the merger to detect\n * when a plugin extends a core table vs. creates a new one).\n */\nexport const CORE_TABLE_NAMES = Object.keys(CORE_SCHEMA);\n"],"mappings":";;;;;AAyBA,MAAa,aAAa;CACxB,eAAe;EACb;EACA;EACA;EACA;EACA;EACA;EACA;EACD;CACD,qBAAqB;EACnB;EACA;EACA;EACA;EACA;EACA;EACA;EACD;CACD,aAAa;EAAC;EAAa;EAAc;EAAa;EAAU;EAAY;CAC5E,eAAe,CAAC,UAAU,YAAY;CACvC;AAMD,MAAa,cAAkC;CAE7C,OAAO;EACL,WAAW;EACX,OAAO;EACP,QAAQ;GACN,IAAI;IAAE,MAAM;IAAU,YAAY;IAAM;GACxC,MAAM;IAAE,MAAM;IAAU,UAAU;IAAM;GACxC,aAAa;IAAE,MAAM;IAAU,UAAU;IAAO;GAChD,MAAM;IAAE,MAAM;IAAQ,UAAU;IAAO,gBAAgB;IAAY;GACnE,UAAU;IAAE,MAAM;IAAW,UAAU;IAAM,cAAc;IAAM;GACjE,mBAAmB;IAAE,MAAM;IAAU,UAAU;IAAO;GACtD,WAAW;IAAE,MAAM;IAAQ,UAAU;IAAM,cAAc;IAAS;GAClE,WAAW;IAAE,MAAM;IAAQ,UAAU;IAAM,cAAc;IAAS;GACnE;EACF;CAGD,cAAc;EACZ,WAAW;EACX,OAAO;EACP,qBAAqB,CAAC,WAAW,SAAS;EAC1C,QAAQ;GACN,QAAQ;IACN,MAAM;IACN,UAAU;IACV,YAAY;KAAE,OAAO;KAAS,OAAO;KAAM,UAAU;KAAW;IACjE;GACD,SAAS;IAAE,MAAM;IAAU,UAAU;IAAM;GAC3C,kBAAkB;IAChB,MAAM;IACN,UAAU;IACV,gBAAgB;IACjB;GACD,WAAW;IAAE,MAAM;IAAQ,UAAU;IAAM,cAAc;IAAS;GAClE,WAAW;IAAE,MAAM;IAAU,UAAU;IAAO;GAC/C;EACF;CAGD,UAAU;EACR,WAAW;EACX,OAAO;EACP,QAAQ;GACN,IAAI;IAAE,MAAM;IAAQ,YAAY;IAAM,cAAc;IAAU;GAC9D,QAAQ;IACN,MAAM;IACN,UAAU;IACV,YAAY;KAAE,OAAO;KAAS,OAAO;KAAM,UAAU;KAAW;IACjE;GACD,aAAa;IAAE,MAAM;IAAU,UAAU;IAAM;GAC/C,QAAQ;IACN,MAAM,CAAC,GAAG,WAAW,cAAc;IACnC,UAAU;IACV,cAAc;IACd,gBAAgB;IACjB;GACD,QAAQ;IAAE,MAAM;IAAQ,UAAU;IAAM,gBAAgB;IAAa;GACrE,SAAS;IAAE,MAAM;IAAQ,UAAU;IAAO,gBAAgB;IAAa;GACvE,OAAO;IAAE,MAAM;IAAQ,UAAU;IAAO;GACxC,WAAW;IAAE,MAAM;IAAQ,UAAU;IAAM,cAAc;IAAS;GAClE,aAAa;IAAE,MAAM;IAAQ,UAAU;IAAO;GAC9C,UAAU;IAAE,MAAM;IAAU,UAAU;IAAO;GAC7C,WAAW;IAAE,MAAM;IAAU,UAAU;IAAO;GAE9C,aAAa;IAAE,MAAM;IAAU,UAAU;IAAO;GAChD,WAAW;IAAE,MAAM;IAAU,UAAU;IAAO;GAC9C,eAAe;IAAE,MAAM;IAAU,UAAU;IAAO;GAClD,aAAa;IAAE,MAAM;IAAQ,UAAU;IAAO,gBAAgB;IAAa;GAC3E,iBAAiB;IAAE,MAAM;IAAQ,UAAU;IAAO;GACnD;EACF;CAGD,gBAAgB;EACd,WAAW;EACX,OAAO;EACP,QAAQ;GACN,IAAI;IAAE,MAAM;IAAQ,YAAY;IAAM,cAAc;IAAU;GAC9D,WAAW;IACT,MAAM;IACN,UAAU;IACV,YAAY;KAAE,OAAO;KAAmB,OAAO;KAAM,UAAU;KAAW;IAC3E;GACD,QAAQ;IAAE,MAAM;IAAU,UAAU;IAAM;GAC1C,UAAU;IAAE,MAAM;IAAU,UAAU;IAAM;GAC5C,QAAQ;IACN,MAAM,CAAC,GAAG,WAAW,oBAAoB;IACzC,UAAU;IACV,cAAc;IACd,gBAAgB;IACjB;GACD,QAAQ;IAAE,MAAM;IAAQ,UAAU;IAAM,gBAAgB;IAAa;GACrE,SAAS;IAAE,MAAM;IAAQ,UAAU;IAAO,gBAAgB;IAAa;GACvE,OAAO;IAAE,MAAM;IAAQ,UAAU;IAAO;GACxC,WAAW;IAAE,MAAM;IAAQ,UAAU;IAAM,cAAc;IAAS;GAClE,aAAa;IAAE,MAAM;IAAQ,UAAU;IAAO;GAC9C,UAAU;IAAE,MAAM;IAAU,UAAU;IAAO;GAC7C,YAAY;IAAE,MAAM;IAAU,UAAU;IAAM,cAAc;IAAG;GAChE;EACF;CAGD,WAAW;EACT,WAAW;EACX,OAAO;EACP,QAAQ;GACN,IAAI;IAAE,MAAM;IAAQ,YAAY;IAAM,cAAc;IAAU;GAC9D,WAAW;IACT,MAAM;IACN,UAAU;IACV,YAAY;KAAE,OAAO;KAAmB,OAAO;KAAM,UAAU;KAAW;IAC3E;GACD,QAAQ;IAAE,MAAM;IAAU,UAAU;IAAM;GAC1C,UAAU;IACR,MAAM,CAAC,GAAG,WAAW,cAAc;IACnC,UAAU;IACV,gBAAgB;IACjB;GACD,SAAS;IAAE,MAAM;IAAU,UAAU;IAAO;GAC5C,QAAQ;IACN,MAAM,CAAC,GAAG,WAAW,YAAY;IACjC,UAAU;IACV,cAAc;IACd,gBAAgB;IACjB;GACD,aAAa;IAAE,MAAM;IAAQ,UAAU;IAAM;GAC7C,cAAc;IAAE,MAAM;IAAQ,UAAU;IAAO;GAC/C,OAAO;IAAE,MAAM;IAAQ,UAAU;IAAO;GACxC,aAAa;IAAE,MAAM;IAAQ,UAAU;IAAM,cAAc;IAAS;GACpE,aAAa;IAAE,MAAM;IAAQ,UAAU;IAAO;GAC9C,WAAW;IAAE,MAAM;IAAQ,UAAU;IAAM,cAAc;IAAS;GAClE,WAAW;IAAE,MAAM;IAAQ,UAAU;IAAM,cAAc;IAAS;GACnE;EACF;CAGD,qBAAqB;EACnB,WAAW;EACX,OAAO;EACP,QAAQ;GACN,IAAI;IAAE,MAAM;IAAQ,YAAY;IAAM,cAAc;IAAU;GAC9D,iBAAiB;IACf,MAAM;IACN,UAAU;IACV,YAAY;KAAE,OAAO;KAAoB,OAAO;KAAM,UAAU;KAAW;IAC5E;GACD,WAAW;IACT,MAAM;IACN,UAAU;IACV,YAAY;KAAE,OAAO;KAAmB,OAAO;KAAM,UAAU;KAAW;IAC3E;GACD,QAAQ;IAAE,MAAM;IAAU,UAAU;IAAM;GAC1C,UAAU;IAAE,MAAM;IAAU,UAAU;IAAM;GAC5C,WAAW;IAAE,MAAM;IAAU,UAAU;IAAM;GAC7C,OAAO;IAAE,MAAM;IAAQ,UAAU;IAAM,gBAAgB;IAAa;GACpE,QAAQ;IAAE,MAAM;IAAQ,UAAU;IAAO,gBAAgB;IAAa;GACtE,OAAO;IAAE,MAAM;IAAQ,UAAU;IAAO;GACxC,SAAS;IAAE,MAAM;IAAW,UAAU;IAAM;GAC5C,WAAW;IAAE,MAAM;IAAQ,UAAU;IAAM,cAAc;IAAS;GAClE,aAAa;IAAE,MAAM;IAAQ,UAAU;IAAO;GAC9C,UAAU;IAAE,MAAM;IAAU,UAAU;IAAO;GAC9C;EACF;CAGD,aAAa;EACX,WAAW;EACX,OAAO;EACP,QAAQ;GACN,IAAI;IAAE,MAAM;IAAQ,YAAY;IAAM,cAAc;IAAU;GAC9D,MAAM;IAAE,MAAM;IAAU,UAAU;IAAM;GACxC,MAAM;IAAE,MAAM;IAAU,UAAU;IAAM,gBAAgB;IAAkB;GAC1E,UAAU;IAAE,MAAM;IAAU,UAAU;IAAM,gBAAgB;IAAsB;GAClF,QAAQ;IAAE,MAAM;IAAQ,UAAU;IAAM,gBAAgB;IAAoB;GAC5E,aAAa;IAAE,MAAM;IAAQ,UAAU;IAAO;GAC9C,UAAU;IAAE,MAAM;IAAW,UAAU;IAAM,cAAc;IAAM;GACjE,aAAa;IAAE,MAAM;IAAU,UAAU;IAAO;GAChD,UAAU;IAAE,MAAM;IAAW,UAAU;IAAM,cAAc;IAAO;GAClE,UAAU;IAAE,MAAM;IAAQ,UAAU;IAAO,gBAAgB;IAA2B;GACtF,YAAY;IAAE,MAAM;IAAQ,UAAU;IAAO;GAC7C,WAAW;IAAE,MAAM;IAAQ,UAAU;IAAO;GAC5C,aAAa;IAAE,MAAM;IAAU,UAAU;IAAO,QAAQ;IAAM;GAC9D,eAAe;IAAE,MAAM;IAAU,UAAU;IAAO;GAClD,WAAW;IAAE,MAAM;IAAQ,UAAU;IAAM,cAAc;IAAS;GAClE,WAAW;IAAE,MAAM;IAAQ,UAAU;IAAM,cAAc;IAAS;GACnE;EACF;CAGD,cAAc;EACZ,WAAW;EACX,OAAO;EACP,QAAQ;GACN,IAAI;IAAE,MAAM;IAAQ,YAAY;IAAM,cAAc;IAAU;GAC9D,QAAQ;IACN,MAAM;IACN,UAAU;IACV,YAAY;KAAE,OAAO;KAAS,OAAO;KAAM,UAAU;KAAW;IACjE;GACD,QAAQ;IAAE,MAAM;IAAU,UAAU;IAAM;GAC1C,MAAM;IAAE,MAAM;IAAU,UAAU;IAAM,gBAAgB;IAAe;GACvE,WAAW;IAAE,MAAM;IAAW,UAAU;IAAM,cAAc;IAAM;GAClE,aAAa;IAAE,MAAM;IAAU,UAAU;IAAO,QAAQ;IAAM;GAC9D,eAAe;IAAE,MAAM;IAAU,UAAU;IAAO;GAClD,gBAAgB;IAAE,MAAM;IAAU,UAAU;IAAO;GACnD,cAAc;IAAE,MAAM;IAAU,UAAU;IAAO;GACjD,iBAAiB;IAAE,MAAM;IAAQ,UAAU;IAAO;GAClD,WAAW;IAAE,MAAM;IAAQ,UAAU;IAAM,cAAc;IAAS;GAClE,WAAW;IAAE,MAAM;IAAQ,UAAU;IAAM,cAAc;IAAS;GACnE;EACF;CAGD,cAAc;EACZ,WAAW;EACX,OAAO;EACP,QAAQ;GACN,IAAI;IAAE,MAAM;IAAQ,YAAY;IAAM,cAAc;IAAU;GAC9D,QAAQ;IACN,MAAM;IACN,UAAU;IACV,YAAY;KAAE,OAAO;KAAS,OAAO;KAAM,UAAU;KAAW;IACjE;GACD,MAAM;IACJ,MAAM;IACN,UAAU;IACV,gBAAgB;IACjB;GACD,SAAS;IAAE,MAAM;IAAQ,UAAU;IAAM,cAAc;IAAI;GAC3D,UAAU;IAAE,MAAM;IAAQ,UAAU;IAAO,gBAAgB;IAA2B;GACtF,WAAW;IAAE,MAAM;IAAQ,UAAU;IAAM,cAAc;IAAS;GACnE;EACF;CAGD,YAAY;EACV,WAAW;EACX,OAAO;EACP,QAAQ;GACN,IAAI;IAAE,MAAM;IAAQ,YAAY;IAAM,cAAc;IAAU;GAC9D,QAAQ;IACN,MAAM;IACN,UAAU;IACV,YAAY;KAAE,OAAO;KAAS,OAAO;KAAM,UAAU;KAAW;IACjE;GACD,QAAQ;IAAE,MAAM;IAAU,UAAU;IAAO;GAC3C,QAAQ;IAAE,MAAM;IAAU,UAAU;IAAO;GAC3C,YAAY;IACV,MAAM;IACN,UAAU;IACV,cAAc;IACd,gBAAgB;IACjB;GACD,WAAW;IAAE,MAAM;IAAU,UAAU;IAAO;GAC9C,WAAW;IAAE,MAAM;IAAQ,UAAU;IAAM,cAAc;IAAS;GAClE,WAAW;IAAE,MAAM;IAAQ,UAAU;IAAO;GAC7C;EACF;CACF;;;;;AAMD,MAAa,mBAAmB,OAAO,KAAK,YAAY"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"core-schema.js","names":[],"sources":["../../src/database/core-schema.ts"],"sourcesContent":["/**\n * Core Abstract Schema\n *\n * The single source of truth for Invect's database tables.\n * Defined using the abstract `InvectPluginSchema` format.\n *\n * The CLI schema generator (`npx invect generate`) uses this + plugin schemas\n * to produce the three dialect-specific Drizzle schema files:\n * - schema-sqlite.ts\n * - schema-postgres.ts\n * - schema-mysql.ts\n *\n * When modifying the database schema, edit THIS file, then run `npx invect generate`.\n */\n\nimport type { InvectPluginSchema } from 'src/types/plugin.types';\n\n// =============================================================================\n// Enum Definitions\n// =============================================================================\n\n/**\n * Enum value sets used across the schema.\n * The generator creates pgEnum / mysqlEnum from these.\n */\nexport const CORE_ENUMS = {\n flowRunStatus: [\n 'PENDING',\n 'RUNNING',\n 'SUCCESS',\n 'FAILED',\n 'CANCELLED',\n 'PAUSED',\n 'PAUSED_FOR_BATCH',\n ],\n nodeExecutionStatus: [\n 'PENDING',\n 'RUNNING',\n 'SUCCESS',\n 'FAILED',\n 'SKIPPED',\n 'BATCH_SUBMITTED',\n 'BATCH_PROCESSING',\n ],\n batchStatus: ['SUBMITTED', 'PROCESSING', 'COMPLETED', 'FAILED', 'CANCELLED'],\n batchProvider: ['OPENAI', 'ANTHROPIC'],\n} as const;\n\n// =============================================================================\n// Core Schema Definition\n// =============================================================================\n\nexport const CORE_SCHEMA: InvectPluginSchema = {\n // ----- Flow definition table -----\n flows: {\n tableName: 'flows',\n order: 10,\n fields: {\n id: { type: 'string', primaryKey: true },\n name: { type: 'string', required: true },\n description: { type: 'string', required: false },\n tags: { type: 'json', required: false, typeAnnotation: 'string[]' },\n isActive: { type: 'boolean', required: true, defaultValue: true },\n liveVersionNumber: { type: 'number', required: false },\n createdAt: { type: 'date', required: true, defaultValue: 'now()' },\n updatedAt: { type: 'date', required: true, defaultValue: 'now()' },\n },\n },\n\n // ----- Flow version table -----\n flowVersions: {\n tableName: 'flow_versions',\n order: 20,\n compositePrimaryKey: ['version', 'flowId'],\n fields: {\n flowId: {\n type: 'string',\n required: true,\n references: { table: 'flows', field: 'id', onDelete: 'cascade' },\n },\n version: { type: 'number', required: true },\n invectDefinition: {\n type: 'json',\n required: true,\n typeAnnotation: 'InvectDefinitionRuntime',\n },\n createdAt: { type: 'date', required: true, defaultValue: 'now()' },\n createdBy: { type: 'string', required: false },\n },\n },\n\n // ----- Flow execution (runs) table -----\n flowRuns: {\n tableName: 'flow_executions',\n order: 30,\n fields: {\n id: { type: 'uuid', primaryKey: true, defaultValue: 'uuid()' },\n flowId: {\n type: 'string',\n required: true,\n references: { table: 'flows', field: 'id', onDelete: 'cascade' },\n },\n flowVersion: { type: 'number', required: true },\n status: {\n type: [...CORE_ENUMS.flowRunStatus],\n required: true,\n defaultValue: 'PENDING',\n typeAnnotation: 'FlowRunStatus',\n },\n inputs: { type: 'json', required: true, typeAnnotation: 'JSONValue' },\n outputs: { type: 'json', required: false, typeAnnotation: 'JSONValue' },\n error: { type: 'text', required: false },\n startedAt: { type: 'date', required: true, defaultValue: 'now()' },\n completedAt: { type: 'date', required: false },\n duration: { type: 'number', required: false },\n createdBy: { type: 'string', required: false },\n // Trigger provenance\n triggerType: { type: 'string', required: false },\n triggerId: { type: 'string', required: false },\n triggerNodeId: { type: 'string', required: false },\n triggerData: { type: 'json', required: false, typeAnnotation: 'JSONValue' },\n lastHeartbeatAt: { type: 'date', required: false },\n },\n },\n\n // ----- Execution traces (node executions) table -----\n nodeExecutions: {\n tableName: 'execution_traces',\n order: 40,\n fields: {\n id: { type: 'uuid', primaryKey: true, defaultValue: 'uuid()' },\n flowRunId: {\n type: 'uuid',\n required: true,\n references: { table: 'flow_executions', field: 'id', onDelete: 'cascade' },\n },\n nodeId: { type: 'string', required: true },\n nodeType: { type: 'string', required: true },\n status: {\n type: [...CORE_ENUMS.nodeExecutionStatus],\n required: true,\n defaultValue: 'PENDING',\n typeAnnotation: 'NodeExecutionStatus',\n },\n inputs: { type: 'json', required: true, typeAnnotation: 'JSONValue' },\n outputs: { type: 'json', required: false, typeAnnotation: 'JSONValue' },\n error: { type: 'text', required: false },\n startedAt: { type: 'date', required: true, defaultValue: 'now()' },\n completedAt: { type: 'date', required: false },\n duration: { type: 'number', required: false },\n retryCount: { type: 'number', required: true, defaultValue: 0 },\n },\n },\n\n // ----- Batch jobs table -----\n batchJobs: {\n tableName: 'batch_jobs',\n order: 50,\n fields: {\n id: { type: 'uuid', primaryKey: true, defaultValue: 'uuid()' },\n flowRunId: {\n type: 'uuid',\n required: true,\n references: { table: 'flow_executions', field: 'id', onDelete: 'cascade' },\n },\n nodeId: { type: 'string', required: true },\n provider: {\n type: [...CORE_ENUMS.batchProvider],\n required: true,\n typeAnnotation: 'BatchProvider',\n },\n batchId: { type: 'string', required: false },\n status: {\n type: [...CORE_ENUMS.batchStatus],\n required: true,\n defaultValue: 'SUBMITTED',\n typeAnnotation: 'BatchStatus',\n },\n requestData: { type: 'json', required: true },\n responseData: { type: 'json', required: false },\n error: { type: 'text', required: false },\n submittedAt: { type: 'date', required: true, defaultValue: 'now()' },\n completedAt: { type: 'date', required: false },\n createdAt: { type: 'date', required: true, defaultValue: 'now()' },\n updatedAt: { type: 'date', required: true, defaultValue: 'now()' },\n },\n },\n\n // ----- Agent tool executions table -----\n agentToolExecutions: {\n tableName: 'agent_tool_executions',\n order: 60,\n fields: {\n id: { type: 'uuid', primaryKey: true, defaultValue: 'uuid()' },\n nodeExecutionId: {\n type: 'uuid',\n required: true,\n references: { table: 'execution_traces', field: 'id', onDelete: 'cascade' },\n },\n flowRunId: {\n type: 'uuid',\n required: true,\n references: { table: 'flow_executions', field: 'id', onDelete: 'cascade' },\n },\n toolId: { type: 'string', required: true },\n toolName: { type: 'string', required: true },\n iteration: { type: 'number', required: true },\n input: { type: 'json', required: true, typeAnnotation: 'JSONValue' },\n output: { type: 'json', required: false, typeAnnotation: 'JSONValue' },\n error: { type: 'text', required: false },\n success: { type: 'boolean', required: true },\n startedAt: { type: 'date', required: true, defaultValue: 'now()' },\n completedAt: { type: 'date', required: false },\n duration: { type: 'number', required: false },\n },\n },\n\n // ----- Credentials table -----\n credentials: {\n tableName: 'credentials',\n order: 10,\n fields: {\n id: { type: 'uuid', primaryKey: true, defaultValue: 'uuid()' },\n name: { type: 'string', required: true },\n type: { type: 'string', required: true, typeAnnotation: 'CredentialType' },\n authType: { type: 'string', required: true, typeAnnotation: 'CredentialAuthType' },\n config: { type: 'json', required: true, typeAnnotation: 'CredentialConfig' },\n description: { type: 'text', required: false },\n isActive: { type: 'boolean', required: true, defaultValue: true },\n workspaceId: { type: 'string', required: false },\n isShared: { type: 'boolean', required: true, defaultValue: false },\n metadata: { type: 'json', required: false, typeAnnotation: 'Record<string, unknown>' },\n lastUsedAt: { type: 'date', required: false },\n expiresAt: { type: 'date', required: false },\n webhookPath: { type: 'string', required: false, unique: true },\n webhookSecret: { type: 'string', required: false },\n createdAt: { type: 'date', required: true, defaultValue: 'now()' },\n updatedAt: { type: 'date', required: true, defaultValue: 'now()' },\n },\n },\n\n // ----- Flow triggers table -----\n flowTriggers: {\n tableName: 'flow_triggers',\n order: 20,\n fields: {\n id: { type: 'uuid', primaryKey: true, defaultValue: 'uuid()' },\n flowId: {\n type: 'string',\n required: true,\n references: { table: 'flows', field: 'id', onDelete: 'cascade' },\n },\n nodeId: { type: 'string', required: true },\n type: { type: 'string', required: true, typeAnnotation: 'TriggerType' },\n isEnabled: { type: 'boolean', required: true, defaultValue: true },\n webhookPath: { type: 'string', required: false, unique: true },\n webhookSecret: { type: 'string', required: false },\n cronExpression: { type: 'string', required: false },\n cronTimezone: { type: 'string', required: false },\n lastTriggeredAt: { type: 'date', required: false },\n createdAt: { type: 'date', required: true, defaultValue: 'now()' },\n updatedAt: { type: 'date', required: true, defaultValue: 'now()' },\n },\n },\n\n // ----- Chat messages table -----\n chatMessages: {\n tableName: 'chat_messages',\n order: 30,\n fields: {\n id: { type: 'uuid', primaryKey: true, defaultValue: 'uuid()' },\n flowId: {\n type: 'string',\n required: true,\n references: { table: 'flows', field: 'id', onDelete: 'cascade' },\n },\n role: {\n type: 'string',\n required: true,\n typeAnnotation: \"'user' | 'assistant' | 'system' | 'tool'\",\n },\n content: { type: 'text', required: true, defaultValue: '' },\n toolMeta: { type: 'json', required: false, typeAnnotation: 'Record<string, unknown>' },\n createdAt: { type: 'date', required: true, defaultValue: 'now()' },\n },\n },\n\n // ----- Flow access control (RBAC) table -----\n flowAccess: {\n tableName: 'flow_access',\n order: 20,\n fields: {\n id: { type: 'uuid', primaryKey: true, defaultValue: 'uuid()' },\n flowId: {\n type: 'string',\n required: true,\n references: { table: 'flows', field: 'id', onDelete: 'cascade' },\n },\n userId: { type: 'string', required: false },\n teamId: { type: 'string', required: false },\n permission: {\n type: 'string',\n required: true,\n defaultValue: 'viewer',\n typeAnnotation: 'FlowAccessPermission',\n },\n grantedBy: { type: 'string', required: false },\n grantedAt: { type: 'date', required: true, defaultValue: 'now()' },\n expiresAt: { type: 'date', required: false },\n },\n },\n};\n\n/**\n * List of core table names (used by the merger to detect\n * when a plugin extends a core table vs. creates a new one).\n */\nexport const CORE_TABLE_NAMES = Object.keys(CORE_SCHEMA);\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"core-schema.js","names":[],"sources":["../../src/database/core-schema.ts"],"sourcesContent":["/**\n * Core Abstract Schema\n *\n * The single source of truth for Invect's database tables.\n * Defined using the abstract `InvectPluginSchema` format.\n *\n * The CLI schema generator (`npx invect-cli generate`) uses this + plugin schemas\n * to produce the three dialect-specific Drizzle schema files:\n * - schema-sqlite.ts\n * - schema-postgres.ts\n * - schema-mysql.ts\n *\n * When modifying the database schema, edit THIS file, then run `npx invect-cli generate`.\n */\n\nimport type { InvectPluginSchema } from 'src/types/plugin.types';\n\n// =============================================================================\n// Enum Definitions\n// =============================================================================\n\n/**\n * Enum value sets used across the schema.\n * The generator creates pgEnum / mysqlEnum from these.\n */\nexport const CORE_ENUMS = {\n flowRunStatus: [\n 'PENDING',\n 'RUNNING',\n 'SUCCESS',\n 'FAILED',\n 'CANCELLED',\n 'PAUSED',\n 'PAUSED_FOR_BATCH',\n ],\n nodeExecutionStatus: [\n 'PENDING',\n 'RUNNING',\n 'SUCCESS',\n 'FAILED',\n 'SKIPPED',\n 'BATCH_SUBMITTED',\n 'BATCH_PROCESSING',\n ],\n batchStatus: ['SUBMITTED', 'PROCESSING', 'COMPLETED', 'FAILED', 'CANCELLED'],\n batchProvider: ['OPENAI', 'ANTHROPIC'],\n} as const;\n\n// =============================================================================\n// Core Schema Definition\n// =============================================================================\n\nexport const CORE_SCHEMA: InvectPluginSchema = {\n // ----- Flow definition table -----\n flows: {\n tableName: 'flows',\n order: 10,\n fields: {\n id: { type: 'string', primaryKey: true },\n name: { type: 'string', required: true },\n description: { type: 'string', required: false },\n tags: { type: 'json', required: false, typeAnnotation: 'string[]' },\n isActive: { type: 'boolean', required: true, defaultValue: true },\n liveVersionNumber: { type: 'number', required: false },\n createdAt: { type: 'date', required: true, defaultValue: 'now()' },\n updatedAt: { type: 'date', required: true, defaultValue: 'now()' },\n },\n },\n\n // ----- Flow version table -----\n flowVersions: {\n tableName: 'flow_versions',\n order: 20,\n compositePrimaryKey: ['version', 'flowId'],\n fields: {\n flowId: {\n type: 'string',\n required: true,\n references: { table: 'flows', field: 'id', onDelete: 'cascade' },\n },\n version: { type: 'number', required: true },\n invectDefinition: {\n type: 'json',\n required: true,\n typeAnnotation: 'InvectDefinitionRuntime',\n },\n createdAt: { type: 'date', required: true, defaultValue: 'now()' },\n createdBy: { type: 'string', required: false },\n },\n },\n\n // ----- Flow execution (runs) table -----\n flowRuns: {\n tableName: 'flow_executions',\n order: 30,\n fields: {\n id: { type: 'uuid', primaryKey: true, defaultValue: 'uuid()' },\n flowId: {\n type: 'string',\n required: true,\n references: { table: 'flows', field: 'id', onDelete: 'cascade' },\n },\n flowVersion: { type: 'number', required: true },\n status: {\n type: [...CORE_ENUMS.flowRunStatus],\n required: true,\n defaultValue: 'PENDING',\n typeAnnotation: 'FlowRunStatus',\n },\n inputs: { type: 'json', required: true, typeAnnotation: 'JSONValue' },\n outputs: { type: 'json', required: false, typeAnnotation: 'JSONValue' },\n error: { type: 'text', required: false },\n startedAt: { type: 'date', required: true, defaultValue: 'now()' },\n completedAt: { type: 'date', required: false },\n duration: { type: 'number', required: false },\n createdBy: { type: 'string', required: false },\n // Trigger provenance\n triggerType: { type: 'string', required: false },\n triggerId: { type: 'string', required: false },\n triggerNodeId: { type: 'string', required: false },\n triggerData: { type: 'json', required: false, typeAnnotation: 'JSONValue' },\n lastHeartbeatAt: { type: 'date', required: false },\n },\n },\n\n // ----- Execution traces (node executions) table -----\n nodeExecutions: {\n tableName: 'execution_traces',\n order: 40,\n fields: {\n id: { type: 'uuid', primaryKey: true, defaultValue: 'uuid()' },\n flowRunId: {\n type: 'uuid',\n required: true,\n references: { table: 'flow_executions', field: 'id', onDelete: 'cascade' },\n },\n nodeId: { type: 'string', required: true },\n nodeType: { type: 'string', required: true },\n status: {\n type: [...CORE_ENUMS.nodeExecutionStatus],\n required: true,\n defaultValue: 'PENDING',\n typeAnnotation: 'NodeExecutionStatus',\n },\n inputs: { type: 'json', required: true, typeAnnotation: 'JSONValue' },\n outputs: { type: 'json', required: false, typeAnnotation: 'JSONValue' },\n error: { type: 'text', required: false },\n startedAt: { type: 'date', required: true, defaultValue: 'now()' },\n completedAt: { type: 'date', required: false },\n duration: { type: 'number', required: false },\n retryCount: { type: 'number', required: true, defaultValue: 0 },\n },\n },\n\n // ----- Batch jobs table -----\n batchJobs: {\n tableName: 'batch_jobs',\n order: 50,\n fields: {\n id: { type: 'uuid', primaryKey: true, defaultValue: 'uuid()' },\n flowRunId: {\n type: 'uuid',\n required: true,\n references: { table: 'flow_executions', field: 'id', onDelete: 'cascade' },\n },\n nodeId: { type: 'string', required: true },\n provider: {\n type: [...CORE_ENUMS.batchProvider],\n required: true,\n typeAnnotation: 'BatchProvider',\n },\n batchId: { type: 'string', required: false },\n status: {\n type: [...CORE_ENUMS.batchStatus],\n required: true,\n defaultValue: 'SUBMITTED',\n typeAnnotation: 'BatchStatus',\n },\n requestData: { type: 'json', required: true },\n responseData: { type: 'json', required: false },\n error: { type: 'text', required: false },\n submittedAt: { type: 'date', required: true, defaultValue: 'now()' },\n completedAt: { type: 'date', required: false },\n createdAt: { type: 'date', required: true, defaultValue: 'now()' },\n updatedAt: { type: 'date', required: true, defaultValue: 'now()' },\n },\n },\n\n // ----- Agent tool executions table -----\n agentToolExecutions: {\n tableName: 'agent_tool_executions',\n order: 60,\n fields: {\n id: { type: 'uuid', primaryKey: true, defaultValue: 'uuid()' },\n nodeExecutionId: {\n type: 'uuid',\n required: true,\n references: { table: 'execution_traces', field: 'id', onDelete: 'cascade' },\n },\n flowRunId: {\n type: 'uuid',\n required: true,\n references: { table: 'flow_executions', field: 'id', onDelete: 'cascade' },\n },\n toolId: { type: 'string', required: true },\n toolName: { type: 'string', required: true },\n iteration: { type: 'number', required: true },\n input: { type: 'json', required: true, typeAnnotation: 'JSONValue' },\n output: { type: 'json', required: false, typeAnnotation: 'JSONValue' },\n error: { type: 'text', required: false },\n success: { type: 'boolean', required: true },\n startedAt: { type: 'date', required: true, defaultValue: 'now()' },\n completedAt: { type: 'date', required: false },\n duration: { type: 'number', required: false },\n },\n },\n\n // ----- Credentials table -----\n credentials: {\n tableName: 'credentials',\n order: 10,\n fields: {\n id: { type: 'uuid', primaryKey: true, defaultValue: 'uuid()' },\n name: { type: 'string', required: true },\n type: { type: 'string', required: true, typeAnnotation: 'CredentialType' },\n authType: { type: 'string', required: true, typeAnnotation: 'CredentialAuthType' },\n config: { type: 'json', required: true, typeAnnotation: 'CredentialConfig' },\n description: { type: 'text', required: false },\n isActive: { type: 'boolean', required: true, defaultValue: true },\n workspaceId: { type: 'string', required: false },\n isShared: { type: 'boolean', required: true, defaultValue: false },\n metadata: { type: 'json', required: false, typeAnnotation: 'Record<string, unknown>' },\n lastUsedAt: { type: 'date', required: false },\n expiresAt: { type: 'date', required: false },\n webhookPath: { type: 'string', required: false, unique: true },\n webhookSecret: { type: 'string', required: false },\n createdAt: { type: 'date', required: true, defaultValue: 'now()' },\n updatedAt: { type: 'date', required: true, defaultValue: 'now()' },\n },\n },\n\n // ----- Flow triggers table -----\n flowTriggers: {\n tableName: 'flow_triggers',\n order: 20,\n fields: {\n id: { type: 'uuid', primaryKey: true, defaultValue: 'uuid()' },\n flowId: {\n type: 'string',\n required: true,\n references: { table: 'flows', field: 'id', onDelete: 'cascade' },\n },\n nodeId: { type: 'string', required: true },\n type: { type: 'string', required: true, typeAnnotation: 'TriggerType' },\n isEnabled: { type: 'boolean', required: true, defaultValue: true },\n webhookPath: { type: 'string', required: false, unique: true },\n webhookSecret: { type: 'string', required: false },\n cronExpression: { type: 'string', required: false },\n cronTimezone: { type: 'string', required: false },\n lastTriggeredAt: { type: 'date', required: false },\n createdAt: { type: 'date', required: true, defaultValue: 'now()' },\n updatedAt: { type: 'date', required: true, defaultValue: 'now()' },\n },\n },\n\n // ----- Chat messages table -----\n chatMessages: {\n tableName: 'chat_messages',\n order: 30,\n fields: {\n id: { type: 'uuid', primaryKey: true, defaultValue: 'uuid()' },\n flowId: {\n type: 'string',\n required: true,\n references: { table: 'flows', field: 'id', onDelete: 'cascade' },\n },\n role: {\n type: 'string',\n required: true,\n typeAnnotation: \"'user' | 'assistant' | 'system' | 'tool'\",\n },\n content: { type: 'text', required: true, defaultValue: '' },\n toolMeta: { type: 'json', required: false, typeAnnotation: 'Record<string, unknown>' },\n createdAt: { type: 'date', required: true, defaultValue: 'now()' },\n },\n },\n\n // ----- Flow access control (RBAC) table -----\n flowAccess: {\n tableName: 'flow_access',\n order: 20,\n fields: {\n id: { type: 'uuid', primaryKey: true, defaultValue: 'uuid()' },\n flowId: {\n type: 'string',\n required: true,\n references: { table: 'flows', field: 'id', onDelete: 'cascade' },\n },\n userId: { type: 'string', required: false },\n teamId: { type: 'string', required: false },\n permission: {\n type: 'string',\n required: true,\n defaultValue: 'viewer',\n typeAnnotation: 'FlowAccessPermission',\n },\n grantedBy: { type: 'string', required: false },\n grantedAt: { type: 'date', required: true, defaultValue: 'now()' },\n expiresAt: { type: 'date', required: false },\n },\n },\n};\n\n/**\n * List of core table names (used by the merger to detect\n * when a plugin extends a core table vs. creates a new one).\n */\nexport const CORE_TABLE_NAMES = Object.keys(CORE_SCHEMA);\n"],"mappings":"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"}
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
function generateFullPrismaSchema(schema, provider) {
|
|
8
8
|
const lines = [];
|
|
9
9
|
lines.push(`// Prisma schema for Invect — AUTO-GENERATED by @invect/cli`);
|
|
10
|
-
lines.push(`// Do not edit the Invect models manually. Run \`npx invect generate\` to regenerate.`);
|
|
10
|
+
lines.push(`// Do not edit the Invect models manually. Run \`npx invect-cli generate\` to regenerate.`);
|
|
11
11
|
lines.push(``);
|
|
12
12
|
lines.push(`generator client {`);
|
|
13
13
|
lines.push(` provider = "prisma-client-js"`);
|
|
@@ -54,7 +54,7 @@ function generatePrismaModels(schema, provider) {
|
|
|
54
54
|
lines.push(``);
|
|
55
55
|
lines.push(`// =============================================================================`);
|
|
56
56
|
lines.push(`// Invect Models — AUTO-GENERATED by @invect/cli`);
|
|
57
|
-
lines.push(`// Do not edit these models manually. Run \`npx invect generate\` to regenerate.`);
|
|
57
|
+
lines.push(`// Do not edit these models manually. Run \`npx invect-cli generate\` to regenerate.`);
|
|
58
58
|
lines.push(`// =============================================================================`);
|
|
59
59
|
lines.push(``);
|
|
60
60
|
if (provider !== "sqlite") {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prisma-schema-generator.cjs","names":[],"sources":["../../src/database/prisma-schema-generator.ts"],"sourcesContent":["/**\n * Prisma Schema Generator\n *\n * Converts the merged abstract schema (core + plugins) into Prisma schema\n * model blocks. Unlike the Drizzle generators which produce complete\n * TypeScript files, this generates Prisma DSL.\n *\n * Two modes:\n * 1. `generatePrismaModels(schema, provider)` — returns only the model blocks\n * (for appending to an existing schema.prisma)\n * 2. `generateFullPrismaSchema(schema, provider)` — returns a complete\n * schema.prisma including generator + datasource blocks\n *\n * Uses the abstract schema types directly, converting to Prisma's type system:\n *\n * | Abstract | Prisma (PG/MySQL) | Prisma (SQLite) |\n * |-------------|-------------------|------------------|\n * | \"string\" | String | String |\n * | \"text\" | String | String |\n * | \"number\" | Int | Int |\n * | \"boolean\" | Boolean | Boolean |\n * | \"date\" | DateTime | DateTime |\n * | \"json\" | Json | String |\n * | \"uuid\" | String | String |\n * | \"bigint\" | BigInt | BigInt |\n * | string[] | enum | String (fallback)|\n */\n\nimport type { PluginFieldAttribute, PluginFieldType } from 'src/types/plugin.types';\nimport type { MergedSchema, MergedTable } from './schema-merger';\n\nexport type PrismaProvider = 'postgresql' | 'mysql' | 'sqlite';\n\n// =============================================================================\n// Full Schema Generator\n// =============================================================================\n\n/**\n * Generate a complete Prisma schema file from the merged abstract schema.\n *\n * Includes generator, datasource, enums, and all models.\n */\nexport function generateFullPrismaSchema(schema: MergedSchema, provider: PrismaProvider): string {\n const lines: string[] = [];\n\n // Header\n lines.push(`// Prisma schema for Invect — AUTO-GENERATED by @invect/cli`);\n lines.push(\n `// Do not edit the Invect models manually. Run \\`npx invect generate\\` to regenerate.`,\n );\n lines.push(``);\n\n // Generator block\n lines.push(`generator client {`);\n lines.push(` provider = \"prisma-client-js\"`);\n lines.push(`}`);\n lines.push(``);\n\n // Datasource block\n lines.push(`datasource db {`);\n lines.push(` provider = \"${provider}\"`);\n if (provider === 'sqlite') {\n lines.push(` url = \"file:./dev.db\"`);\n } else {\n lines.push(` url = env(\"DATABASE_URL\")`);\n }\n lines.push(`}`);\n lines.push(``);\n\n // Enums (PostgreSQL and MySQL support enums; SQLite doesn't)\n if (provider !== 'sqlite') {\n const enums = collectPrismaEnums(schema);\n if (enums.length > 0) {\n lines.push(\n `// =============================================================================`,\n );\n lines.push(`// Enums`);\n lines.push(\n `// =============================================================================`,\n );\n lines.push(``);\n for (const e of enums) {\n lines.push(`enum ${e.name} {`);\n for (const v of e.values) {\n lines.push(` ${v}`);\n }\n lines.push(`}`);\n lines.push(``);\n }\n }\n }\n\n // Models\n lines.push(`// =============================================================================`);\n lines.push(`// Models`);\n lines.push(`// =============================================================================`);\n lines.push(``);\n\n for (const table of schema.tables) {\n lines.push(generatePrismaModel(table, schema, provider));\n lines.push(``);\n }\n\n return lines.join('\\n');\n}\n\n// =============================================================================\n// Model-Only Generator (for appending to existing schemas)\n// =============================================================================\n\n/**\n * Generate only the Prisma model blocks (no generator/datasource).\n *\n * Useful when adding Invect models to an existing Prisma schema.\n */\nexport function generatePrismaModels(schema: MergedSchema, provider: PrismaProvider): string {\n const lines: string[] = [];\n\n lines.push(``);\n lines.push(`// =============================================================================`);\n lines.push(`// Invect Models — AUTO-GENERATED by @invect/cli`);\n lines.push(`// Do not edit these models manually. Run \\`npx invect generate\\` to regenerate.`);\n lines.push(`// =============================================================================`);\n lines.push(``);\n\n // Enums\n if (provider !== 'sqlite') {\n const enums = collectPrismaEnums(schema);\n for (const e of enums) {\n lines.push(`enum ${e.name} {`);\n for (const v of e.values) {\n lines.push(` ${v}`);\n }\n lines.push(`}`);\n lines.push(``);\n }\n }\n\n // Models\n for (const table of schema.tables) {\n lines.push(generatePrismaModel(table, schema, provider));\n lines.push(``);\n }\n\n return lines.join('\\n');\n}\n\n// =============================================================================\n// Single Model Generator\n// =============================================================================\n\nfunction generatePrismaModel(\n table: MergedTable,\n schema: MergedSchema,\n provider: PrismaProvider,\n): string {\n const lines: string[] = [];\n const { name, definition } = table;\n const dbTableName = definition.tableName || toSnakeCase(name);\n const modelName = capitalize(name);\n\n lines.push(`model ${modelName} {`);\n\n // Fields\n for (const [fieldName, field] of Object.entries(definition.fields)) {\n const dbColName = toSnakeCase(fieldName);\n const prismaType = getPrismaType(field, provider, name, fieldName);\n const attrs = getPrismaAttributes(fieldName, dbColName, field, provider);\n\n lines.push(` ${fieldName} ${prismaType}${attrs}`);\n }\n\n // Relation fields (Prisma requires explicit relation fields)\n const relationLines = generateRelationFields(table, schema, provider);\n for (const line of relationLines) {\n lines.push(` ${line}`);\n }\n\n // Composite primary key\n if (definition.compositePrimaryKey?.length) {\n lines.push(``);\n lines.push(` @@id([${definition.compositePrimaryKey.join(', ')}])`);\n }\n\n // @@index for indexed fields\n for (const [fieldName, field] of Object.entries(definition.fields)) {\n if (field.index && !field.unique && !field.primaryKey) {\n lines.push(` @@index([${fieldName}])`);\n }\n }\n\n // @@map for table name mapping\n if (dbTableName !== name) {\n lines.push(` @@map(\"${dbTableName}\")`);\n }\n\n lines.push(`}`);\n\n return lines.join('\\n');\n}\n\n// =============================================================================\n// Type Mapping\n// =============================================================================\n\nfunction getPrismaType(\n field: PluginFieldAttribute,\n provider: PrismaProvider,\n tableName: string,\n fieldName: string,\n): string {\n const optional = field.required === false ? '?' : '';\n\n if (isEnumType(field.type)) {\n if (provider === 'sqlite') {\n // SQLite doesn't support enums in Prisma, use String\n return `String${optional}`;\n }\n const enumName = prismaEnumName(tableName, fieldName);\n return `${enumName}${optional}`;\n }\n\n switch (field.type) {\n case 'string':\n case 'text':\n case 'uuid':\n return `String${optional}`;\n case 'number':\n return `Int${optional}`;\n case 'bigint':\n return `BigInt${optional}`;\n case 'boolean':\n return `Boolean${optional}`;\n case 'date':\n return `DateTime${optional}`;\n case 'json':\n // SQLite doesn't have native JSON in Prisma — use String\n if (provider === 'sqlite') {\n return `String${optional}`;\n }\n return `Json${optional}`;\n default:\n return `String${optional}`;\n }\n}\n\n// =============================================================================\n// Attribute Generation\n// =============================================================================\n\nfunction getPrismaAttributes(\n fieldName: string,\n dbColName: string,\n field: PluginFieldAttribute,\n provider: PrismaProvider,\n): string {\n const attrs: string[] = [];\n\n // @id (single-column PK)\n if (field.primaryKey) {\n attrs.push('@id');\n }\n\n // @unique\n if (field.unique) {\n attrs.push('@unique');\n }\n\n // @default\n if (field.defaultValue !== undefined) {\n const defaultAttr = getPrismaDefault(field.defaultValue, field.type, provider);\n if (defaultAttr) {\n attrs.push(defaultAttr);\n }\n }\n\n // @updatedAt (for date fields with \"now()\" default and name \"updatedAt\")\n // In Prisma, @updatedAt automatically updates the timestamp\n // We only add it if the field is named updatedAt\n if (fieldName === 'updatedAt' && field.type === 'date') {\n attrs.push('@updatedAt');\n }\n\n // @map (column name differs from field name)\n if (dbColName !== fieldName) {\n attrs.push(`@map(\"${dbColName}\")`);\n }\n\n // @db.Text for MySQL long strings\n if (provider === 'mysql' && field.type === 'text') {\n attrs.push('@db.Text');\n }\n\n // @db.Timestamptz for PostgreSQL dates\n if (provider === 'postgresql' && field.type === 'date') {\n attrs.push('@db.Timestamptz(3)');\n }\n\n if (attrs.length === 0) {\n return '';\n }\n return ' ' + attrs.join(' ');\n}\n\nfunction getPrismaDefault(\n value: string | number | boolean | 'uuid()' | 'now()',\n _type: PluginFieldType,\n _provider: PrismaProvider,\n): string | null {\n if (value === 'uuid()') {\n return '@default(uuid())';\n }\n if (value === 'now()') {\n return '@default(now())';\n }\n if (typeof value === 'boolean') {\n return `@default(${value})`;\n }\n if (typeof value === 'number') {\n return `@default(${value})`;\n }\n if (typeof value === 'string') {\n return `@default(\"${value}\")`;\n }\n return null;\n}\n\n// =============================================================================\n// Relation Fields\n// =============================================================================\n\n/**\n * Generate Prisma relation fields for a model.\n *\n * In Prisma, if model A has a FK `bId → B.id`, we need:\n * - On A: `b B @relation(fields: [bId], references: [id])`\n * - On B: `as A[]` (reverse side)\n *\n * We generate the \"one\" side (FK holder) here; the \"many\" side\n * (reverse) is added to the referenced model.\n */\nfunction generateRelationFields(\n table: MergedTable,\n schema: MergedSchema,\n _provider: PrismaProvider,\n): string[] {\n const lines: string[] = [];\n const { definition } = table;\n\n // One-side: this table has FKs\n for (const [fieldName, field] of Object.entries(definition.fields)) {\n if (!field.references) {\n continue;\n }\n\n const refTableLogical = findLogicalName(schema, field.references.table);\n const refModelName = capitalize(refTableLogical);\n const relName = fieldName.replace(/Id$/, '').replace(/_id$/, '');\n const onDelete = mapOnDelete(field.references.onDelete);\n\n lines.push(\n `${relName} ${refModelName} @relation(fields: [${fieldName}], references: [${field.references.field}], onDelete: ${onDelete})`,\n );\n }\n\n // Many-side: other tables have FKs pointing to this table\n for (const otherTable of schema.tables) {\n if (otherTable.name === table.name) {\n continue;\n }\n\n for (const [_fieldName, field] of Object.entries(otherTable.definition.fields)) {\n if (!field.references) {\n continue;\n }\n\n // Check if this FK references our table\n const refsOurTable =\n field.references.table === table.name ||\n field.references.table === (table.definition.tableName || toSnakeCase(table.name));\n\n if (refsOurTable) {\n const otherModelName = capitalize(otherTable.name);\n // If the FK is unique, this is a one-to-one relation (singular, optional)\n // Otherwise it's one-to-many (array)\n const isUnique = field.unique === true;\n const relName = otherTable.name;\n lines.push(`${relName} ${otherModelName}${isUnique ? '?' : '[]'}`);\n }\n }\n }\n\n return lines;\n}\n\nfunction mapOnDelete(onDelete?: string): string {\n switch (onDelete) {\n case 'cascade':\n return 'Cascade';\n case 'set null':\n return 'SetNull';\n case 'restrict':\n return 'Restrict';\n case 'no action':\n return 'NoAction';\n default:\n return 'NoAction';\n }\n}\n\n// =============================================================================\n// Enum Helpers\n// =============================================================================\n\ninterface PrismaEnumDef {\n name: string;\n values: string[];\n}\n\nfunction collectPrismaEnums(schema: MergedSchema): PrismaEnumDef[] {\n const enums: PrismaEnumDef[] = [];\n\n for (const table of schema.tables) {\n for (const [fieldName, field] of Object.entries(table.definition.fields)) {\n if (isEnumType(field.type)) {\n enums.push({\n name: prismaEnumName(table.name, fieldName),\n values: field.type,\n });\n }\n }\n }\n\n return enums;\n}\n\nfunction prismaEnumName(tableName: string, fieldName: string): string {\n return `${capitalize(tableName)}${capitalize(fieldName)}`;\n}\n\n// =============================================================================\n// Shared Utilities\n// =============================================================================\n\nfunction isEnumType(type: PluginFieldType): type is string[] {\n return Array.isArray(type);\n}\n\nfunction toSnakeCase(str: string): string {\n return str.replace(/[A-Z]/g, (letter) => `_${letter.toLowerCase()}`);\n}\n\nfunction capitalize(str: string): string {\n return str.charAt(0).toUpperCase() + str.slice(1);\n}\n\n/**\n * Find the logical (camelCase) table name from a DB table name.\n */\nfunction findLogicalName(schema: MergedSchema, tableRef: string): string {\n // First try exact match on logical name\n const exact = schema.tables.find((t) => t.name === tableRef);\n if (exact) {\n return exact.name;\n }\n\n // Try by tableName property\n const byDbName = schema.tables.find(\n (t) => t.definition.tableName === tableRef || toSnakeCase(t.name) === tableRef,\n );\n if (byDbName) {\n return byDbName.name;\n }\n\n // Fallback: convert to camelCase\n if (tableRef.includes('_')) {\n return tableRef.replace(/_([a-z])/g, (_, c) => c.toUpperCase());\n }\n return tableRef;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"prisma-schema-generator.cjs","names":[],"sources":["../../src/database/prisma-schema-generator.ts"],"sourcesContent":["/**\n * Prisma Schema Generator\n *\n * Converts the merged abstract schema (core + plugins) into Prisma schema\n * model blocks. Unlike the Drizzle generators which produce complete\n * TypeScript files, this generates Prisma DSL.\n *\n * Two modes:\n * 1. `generatePrismaModels(schema, provider)` — returns only the model blocks\n * (for appending to an existing schema.prisma)\n * 2. `generateFullPrismaSchema(schema, provider)` — returns a complete\n * schema.prisma including generator + datasource blocks\n *\n * Uses the abstract schema types directly, converting to Prisma's type system:\n *\n * | Abstract | Prisma (PG/MySQL) | Prisma (SQLite) |\n * |-------------|-------------------|------------------|\n * | \"string\" | String | String |\n * | \"text\" | String | String |\n * | \"number\" | Int | Int |\n * | \"boolean\" | Boolean | Boolean |\n * | \"date\" | DateTime | DateTime |\n * | \"json\" | Json | String |\n * | \"uuid\" | String | String |\n * | \"bigint\" | BigInt | BigInt |\n * | string[] | enum | String (fallback)|\n */\n\nimport type { PluginFieldAttribute, PluginFieldType } from 'src/types/plugin.types';\nimport type { MergedSchema, MergedTable } from './schema-merger';\n\nexport type PrismaProvider = 'postgresql' | 'mysql' | 'sqlite';\n\n// =============================================================================\n// Full Schema Generator\n// =============================================================================\n\n/**\n * Generate a complete Prisma schema file from the merged abstract schema.\n *\n * Includes generator, datasource, enums, and all models.\n */\nexport function generateFullPrismaSchema(schema: MergedSchema, provider: PrismaProvider): string {\n const lines: string[] = [];\n\n // Header\n lines.push(`// Prisma schema for Invect — AUTO-GENERATED by @invect/cli`);\n lines.push(\n `// Do not edit the Invect models manually. Run \\`npx invect-cli generate\\` to regenerate.`,\n );\n lines.push(``);\n\n // Generator block\n lines.push(`generator client {`);\n lines.push(` provider = \"prisma-client-js\"`);\n lines.push(`}`);\n lines.push(``);\n\n // Datasource block\n lines.push(`datasource db {`);\n lines.push(` provider = \"${provider}\"`);\n if (provider === 'sqlite') {\n lines.push(` url = \"file:./dev.db\"`);\n } else {\n lines.push(` url = env(\"DATABASE_URL\")`);\n }\n lines.push(`}`);\n lines.push(``);\n\n // Enums (PostgreSQL and MySQL support enums; SQLite doesn't)\n if (provider !== 'sqlite') {\n const enums = collectPrismaEnums(schema);\n if (enums.length > 0) {\n lines.push(\n `// =============================================================================`,\n );\n lines.push(`// Enums`);\n lines.push(\n `// =============================================================================`,\n );\n lines.push(``);\n for (const e of enums) {\n lines.push(`enum ${e.name} {`);\n for (const v of e.values) {\n lines.push(` ${v}`);\n }\n lines.push(`}`);\n lines.push(``);\n }\n }\n }\n\n // Models\n lines.push(`// =============================================================================`);\n lines.push(`// Models`);\n lines.push(`// =============================================================================`);\n lines.push(``);\n\n for (const table of schema.tables) {\n lines.push(generatePrismaModel(table, schema, provider));\n lines.push(``);\n }\n\n return lines.join('\\n');\n}\n\n// =============================================================================\n// Model-Only Generator (for appending to existing schemas)\n// =============================================================================\n\n/**\n * Generate only the Prisma model blocks (no generator/datasource).\n *\n * Useful when adding Invect models to an existing Prisma schema.\n */\nexport function generatePrismaModels(schema: MergedSchema, provider: PrismaProvider): string {\n const lines: string[] = [];\n\n lines.push(``);\n lines.push(`// =============================================================================`);\n lines.push(`// Invect Models — AUTO-GENERATED by @invect/cli`);\n lines.push(`// Do not edit these models manually. Run \\`npx invect-cli generate\\` to regenerate.`);\n lines.push(`// =============================================================================`);\n lines.push(``);\n\n // Enums\n if (provider !== 'sqlite') {\n const enums = collectPrismaEnums(schema);\n for (const e of enums) {\n lines.push(`enum ${e.name} {`);\n for (const v of e.values) {\n lines.push(` ${v}`);\n }\n lines.push(`}`);\n lines.push(``);\n }\n }\n\n // Models\n for (const table of schema.tables) {\n lines.push(generatePrismaModel(table, schema, provider));\n lines.push(``);\n }\n\n return lines.join('\\n');\n}\n\n// =============================================================================\n// Single Model Generator\n// =============================================================================\n\nfunction generatePrismaModel(\n table: MergedTable,\n schema: MergedSchema,\n provider: PrismaProvider,\n): string {\n const lines: string[] = [];\n const { name, definition } = table;\n const dbTableName = definition.tableName || toSnakeCase(name);\n const modelName = capitalize(name);\n\n lines.push(`model ${modelName} {`);\n\n // Fields\n for (const [fieldName, field] of Object.entries(definition.fields)) {\n const dbColName = toSnakeCase(fieldName);\n const prismaType = getPrismaType(field, provider, name, fieldName);\n const attrs = getPrismaAttributes(fieldName, dbColName, field, provider);\n\n lines.push(` ${fieldName} ${prismaType}${attrs}`);\n }\n\n // Relation fields (Prisma requires explicit relation fields)\n const relationLines = generateRelationFields(table, schema, provider);\n for (const line of relationLines) {\n lines.push(` ${line}`);\n }\n\n // Composite primary key\n if (definition.compositePrimaryKey?.length) {\n lines.push(``);\n lines.push(` @@id([${definition.compositePrimaryKey.join(', ')}])`);\n }\n\n // @@index for indexed fields\n for (const [fieldName, field] of Object.entries(definition.fields)) {\n if (field.index && !field.unique && !field.primaryKey) {\n lines.push(` @@index([${fieldName}])`);\n }\n }\n\n // @@map for table name mapping\n if (dbTableName !== name) {\n lines.push(` @@map(\"${dbTableName}\")`);\n }\n\n lines.push(`}`);\n\n return lines.join('\\n');\n}\n\n// =============================================================================\n// Type Mapping\n// =============================================================================\n\nfunction getPrismaType(\n field: PluginFieldAttribute,\n provider: PrismaProvider,\n tableName: string,\n fieldName: string,\n): string {\n const optional = field.required === false ? '?' : '';\n\n if (isEnumType(field.type)) {\n if (provider === 'sqlite') {\n // SQLite doesn't support enums in Prisma, use String\n return `String${optional}`;\n }\n const enumName = prismaEnumName(tableName, fieldName);\n return `${enumName}${optional}`;\n }\n\n switch (field.type) {\n case 'string':\n case 'text':\n case 'uuid':\n return `String${optional}`;\n case 'number':\n return `Int${optional}`;\n case 'bigint':\n return `BigInt${optional}`;\n case 'boolean':\n return `Boolean${optional}`;\n case 'date':\n return `DateTime${optional}`;\n case 'json':\n // SQLite doesn't have native JSON in Prisma — use String\n if (provider === 'sqlite') {\n return `String${optional}`;\n }\n return `Json${optional}`;\n default:\n return `String${optional}`;\n }\n}\n\n// =============================================================================\n// Attribute Generation\n// =============================================================================\n\nfunction getPrismaAttributes(\n fieldName: string,\n dbColName: string,\n field: PluginFieldAttribute,\n provider: PrismaProvider,\n): string {\n const attrs: string[] = [];\n\n // @id (single-column PK)\n if (field.primaryKey) {\n attrs.push('@id');\n }\n\n // @unique\n if (field.unique) {\n attrs.push('@unique');\n }\n\n // @default\n if (field.defaultValue !== undefined) {\n const defaultAttr = getPrismaDefault(field.defaultValue, field.type, provider);\n if (defaultAttr) {\n attrs.push(defaultAttr);\n }\n }\n\n // @updatedAt (for date fields with \"now()\" default and name \"updatedAt\")\n // In Prisma, @updatedAt automatically updates the timestamp\n // We only add it if the field is named updatedAt\n if (fieldName === 'updatedAt' && field.type === 'date') {\n attrs.push('@updatedAt');\n }\n\n // @map (column name differs from field name)\n if (dbColName !== fieldName) {\n attrs.push(`@map(\"${dbColName}\")`);\n }\n\n // @db.Text for MySQL long strings\n if (provider === 'mysql' && field.type === 'text') {\n attrs.push('@db.Text');\n }\n\n // @db.Timestamptz for PostgreSQL dates\n if (provider === 'postgresql' && field.type === 'date') {\n attrs.push('@db.Timestamptz(3)');\n }\n\n if (attrs.length === 0) {\n return '';\n }\n return ' ' + attrs.join(' ');\n}\n\nfunction getPrismaDefault(\n value: string | number | boolean | 'uuid()' | 'now()',\n _type: PluginFieldType,\n _provider: PrismaProvider,\n): string | null {\n if (value === 'uuid()') {\n return '@default(uuid())';\n }\n if (value === 'now()') {\n return '@default(now())';\n }\n if (typeof value === 'boolean') {\n return `@default(${value})`;\n }\n if (typeof value === 'number') {\n return `@default(${value})`;\n }\n if (typeof value === 'string') {\n return `@default(\"${value}\")`;\n }\n return null;\n}\n\n// =============================================================================\n// Relation Fields\n// =============================================================================\n\n/**\n * Generate Prisma relation fields for a model.\n *\n * In Prisma, if model A has a FK `bId → B.id`, we need:\n * - On A: `b B @relation(fields: [bId], references: [id])`\n * - On B: `as A[]` (reverse side)\n *\n * We generate the \"one\" side (FK holder) here; the \"many\" side\n * (reverse) is added to the referenced model.\n */\nfunction generateRelationFields(\n table: MergedTable,\n schema: MergedSchema,\n _provider: PrismaProvider,\n): string[] {\n const lines: string[] = [];\n const { definition } = table;\n\n // One-side: this table has FKs\n for (const [fieldName, field] of Object.entries(definition.fields)) {\n if (!field.references) {\n continue;\n }\n\n const refTableLogical = findLogicalName(schema, field.references.table);\n const refModelName = capitalize(refTableLogical);\n const relName = fieldName.replace(/Id$/, '').replace(/_id$/, '');\n const onDelete = mapOnDelete(field.references.onDelete);\n\n lines.push(\n `${relName} ${refModelName} @relation(fields: [${fieldName}], references: [${field.references.field}], onDelete: ${onDelete})`,\n );\n }\n\n // Many-side: other tables have FKs pointing to this table\n for (const otherTable of schema.tables) {\n if (otherTable.name === table.name) {\n continue;\n }\n\n for (const [_fieldName, field] of Object.entries(otherTable.definition.fields)) {\n if (!field.references) {\n continue;\n }\n\n // Check if this FK references our table\n const refsOurTable =\n field.references.table === table.name ||\n field.references.table === (table.definition.tableName || toSnakeCase(table.name));\n\n if (refsOurTable) {\n const otherModelName = capitalize(otherTable.name);\n // If the FK is unique, this is a one-to-one relation (singular, optional)\n // Otherwise it's one-to-many (array)\n const isUnique = field.unique === true;\n const relName = otherTable.name;\n lines.push(`${relName} ${otherModelName}${isUnique ? '?' : '[]'}`);\n }\n }\n }\n\n return lines;\n}\n\nfunction mapOnDelete(onDelete?: string): string {\n switch (onDelete) {\n case 'cascade':\n return 'Cascade';\n case 'set null':\n return 'SetNull';\n case 'restrict':\n return 'Restrict';\n case 'no action':\n return 'NoAction';\n default:\n return 'NoAction';\n }\n}\n\n// =============================================================================\n// Enum Helpers\n// =============================================================================\n\ninterface PrismaEnumDef {\n name: string;\n values: string[];\n}\n\nfunction collectPrismaEnums(schema: MergedSchema): PrismaEnumDef[] {\n const enums: PrismaEnumDef[] = [];\n\n for (const table of schema.tables) {\n for (const [fieldName, field] of Object.entries(table.definition.fields)) {\n if (isEnumType(field.type)) {\n enums.push({\n name: prismaEnumName(table.name, fieldName),\n values: field.type,\n });\n }\n }\n }\n\n return enums;\n}\n\nfunction prismaEnumName(tableName: string, fieldName: string): string {\n return `${capitalize(tableName)}${capitalize(fieldName)}`;\n}\n\n// =============================================================================\n// Shared Utilities\n// =============================================================================\n\nfunction isEnumType(type: PluginFieldType): type is string[] {\n return Array.isArray(type);\n}\n\nfunction toSnakeCase(str: string): string {\n return str.replace(/[A-Z]/g, (letter) => `_${letter.toLowerCase()}`);\n}\n\nfunction capitalize(str: string): string {\n return str.charAt(0).toUpperCase() + str.slice(1);\n}\n\n/**\n * Find the logical (camelCase) table name from a DB table name.\n */\nfunction findLogicalName(schema: MergedSchema, tableRef: string): string {\n // First try exact match on logical name\n const exact = schema.tables.find((t) => t.name === tableRef);\n if (exact) {\n return exact.name;\n }\n\n // Try by tableName property\n const byDbName = schema.tables.find(\n (t) => t.definition.tableName === tableRef || toSnakeCase(t.name) === tableRef,\n );\n if (byDbName) {\n return byDbName.name;\n }\n\n // Fallback: convert to camelCase\n if (tableRef.includes('_')) {\n return tableRef.replace(/_([a-z])/g, (_, c) => c.toUpperCase());\n }\n return tableRef;\n}\n"],"mappings":"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"}
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
function generateFullPrismaSchema(schema, provider) {
|
|
8
8
|
const lines = [];
|
|
9
9
|
lines.push(`// Prisma schema for Invect — AUTO-GENERATED by @invect/cli`);
|
|
10
|
-
lines.push(`// Do not edit the Invect models manually. Run \`npx invect generate\` to regenerate.`);
|
|
10
|
+
lines.push(`// Do not edit the Invect models manually. Run \`npx invect-cli generate\` to regenerate.`);
|
|
11
11
|
lines.push(``);
|
|
12
12
|
lines.push(`generator client {`);
|
|
13
13
|
lines.push(` provider = "prisma-client-js"`);
|
|
@@ -54,7 +54,7 @@ function generatePrismaModels(schema, provider) {
|
|
|
54
54
|
lines.push(``);
|
|
55
55
|
lines.push(`// =============================================================================`);
|
|
56
56
|
lines.push(`// Invect Models — AUTO-GENERATED by @invect/cli`);
|
|
57
|
-
lines.push(`// Do not edit these models manually. Run \`npx invect generate\` to regenerate.`);
|
|
57
|
+
lines.push(`// Do not edit these models manually. Run \`npx invect-cli generate\` to regenerate.`);
|
|
58
58
|
lines.push(`// =============================================================================`);
|
|
59
59
|
lines.push(``);
|
|
60
60
|
if (provider !== "sqlite") {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prisma-schema-generator.js","names":[],"sources":["../../src/database/prisma-schema-generator.ts"],"sourcesContent":["/**\n * Prisma Schema Generator\n *\n * Converts the merged abstract schema (core + plugins) into Prisma schema\n * model blocks. Unlike the Drizzle generators which produce complete\n * TypeScript files, this generates Prisma DSL.\n *\n * Two modes:\n * 1. `generatePrismaModels(schema, provider)` — returns only the model blocks\n * (for appending to an existing schema.prisma)\n * 2. `generateFullPrismaSchema(schema, provider)` — returns a complete\n * schema.prisma including generator + datasource blocks\n *\n * Uses the abstract schema types directly, converting to Prisma's type system:\n *\n * | Abstract | Prisma (PG/MySQL) | Prisma (SQLite) |\n * |-------------|-------------------|------------------|\n * | \"string\" | String | String |\n * | \"text\" | String | String |\n * | \"number\" | Int | Int |\n * | \"boolean\" | Boolean | Boolean |\n * | \"date\" | DateTime | DateTime |\n * | \"json\" | Json | String |\n * | \"uuid\" | String | String |\n * | \"bigint\" | BigInt | BigInt |\n * | string[] | enum | String (fallback)|\n */\n\nimport type { PluginFieldAttribute, PluginFieldType } from 'src/types/plugin.types';\nimport type { MergedSchema, MergedTable } from './schema-merger';\n\nexport type PrismaProvider = 'postgresql' | 'mysql' | 'sqlite';\n\n// =============================================================================\n// Full Schema Generator\n// =============================================================================\n\n/**\n * Generate a complete Prisma schema file from the merged abstract schema.\n *\n * Includes generator, datasource, enums, and all models.\n */\nexport function generateFullPrismaSchema(schema: MergedSchema, provider: PrismaProvider): string {\n const lines: string[] = [];\n\n // Header\n lines.push(`// Prisma schema for Invect — AUTO-GENERATED by @invect/cli`);\n lines.push(\n `// Do not edit the Invect models manually. Run \\`npx invect generate\\` to regenerate.`,\n );\n lines.push(``);\n\n // Generator block\n lines.push(`generator client {`);\n lines.push(` provider = \"prisma-client-js\"`);\n lines.push(`}`);\n lines.push(``);\n\n // Datasource block\n lines.push(`datasource db {`);\n lines.push(` provider = \"${provider}\"`);\n if (provider === 'sqlite') {\n lines.push(` url = \"file:./dev.db\"`);\n } else {\n lines.push(` url = env(\"DATABASE_URL\")`);\n }\n lines.push(`}`);\n lines.push(``);\n\n // Enums (PostgreSQL and MySQL support enums; SQLite doesn't)\n if (provider !== 'sqlite') {\n const enums = collectPrismaEnums(schema);\n if (enums.length > 0) {\n lines.push(\n `// =============================================================================`,\n );\n lines.push(`// Enums`);\n lines.push(\n `// =============================================================================`,\n );\n lines.push(``);\n for (const e of enums) {\n lines.push(`enum ${e.name} {`);\n for (const v of e.values) {\n lines.push(` ${v}`);\n }\n lines.push(`}`);\n lines.push(``);\n }\n }\n }\n\n // Models\n lines.push(`// =============================================================================`);\n lines.push(`// Models`);\n lines.push(`// =============================================================================`);\n lines.push(``);\n\n for (const table of schema.tables) {\n lines.push(generatePrismaModel(table, schema, provider));\n lines.push(``);\n }\n\n return lines.join('\\n');\n}\n\n// =============================================================================\n// Model-Only Generator (for appending to existing schemas)\n// =============================================================================\n\n/**\n * Generate only the Prisma model blocks (no generator/datasource).\n *\n * Useful when adding Invect models to an existing Prisma schema.\n */\nexport function generatePrismaModels(schema: MergedSchema, provider: PrismaProvider): string {\n const lines: string[] = [];\n\n lines.push(``);\n lines.push(`// =============================================================================`);\n lines.push(`// Invect Models — AUTO-GENERATED by @invect/cli`);\n lines.push(`// Do not edit these models manually. Run \\`npx invect generate\\` to regenerate.`);\n lines.push(`// =============================================================================`);\n lines.push(``);\n\n // Enums\n if (provider !== 'sqlite') {\n const enums = collectPrismaEnums(schema);\n for (const e of enums) {\n lines.push(`enum ${e.name} {`);\n for (const v of e.values) {\n lines.push(` ${v}`);\n }\n lines.push(`}`);\n lines.push(``);\n }\n }\n\n // Models\n for (const table of schema.tables) {\n lines.push(generatePrismaModel(table, schema, provider));\n lines.push(``);\n }\n\n return lines.join('\\n');\n}\n\n// =============================================================================\n// Single Model Generator\n// =============================================================================\n\nfunction generatePrismaModel(\n table: MergedTable,\n schema: MergedSchema,\n provider: PrismaProvider,\n): string {\n const lines: string[] = [];\n const { name, definition } = table;\n const dbTableName = definition.tableName || toSnakeCase(name);\n const modelName = capitalize(name);\n\n lines.push(`model ${modelName} {`);\n\n // Fields\n for (const [fieldName, field] of Object.entries(definition.fields)) {\n const dbColName = toSnakeCase(fieldName);\n const prismaType = getPrismaType(field, provider, name, fieldName);\n const attrs = getPrismaAttributes(fieldName, dbColName, field, provider);\n\n lines.push(` ${fieldName} ${prismaType}${attrs}`);\n }\n\n // Relation fields (Prisma requires explicit relation fields)\n const relationLines = generateRelationFields(table, schema, provider);\n for (const line of relationLines) {\n lines.push(` ${line}`);\n }\n\n // Composite primary key\n if (definition.compositePrimaryKey?.length) {\n lines.push(``);\n lines.push(` @@id([${definition.compositePrimaryKey.join(', ')}])`);\n }\n\n // @@index for indexed fields\n for (const [fieldName, field] of Object.entries(definition.fields)) {\n if (field.index && !field.unique && !field.primaryKey) {\n lines.push(` @@index([${fieldName}])`);\n }\n }\n\n // @@map for table name mapping\n if (dbTableName !== name) {\n lines.push(` @@map(\"${dbTableName}\")`);\n }\n\n lines.push(`}`);\n\n return lines.join('\\n');\n}\n\n// =============================================================================\n// Type Mapping\n// =============================================================================\n\nfunction getPrismaType(\n field: PluginFieldAttribute,\n provider: PrismaProvider,\n tableName: string,\n fieldName: string,\n): string {\n const optional = field.required === false ? '?' : '';\n\n if (isEnumType(field.type)) {\n if (provider === 'sqlite') {\n // SQLite doesn't support enums in Prisma, use String\n return `String${optional}`;\n }\n const enumName = prismaEnumName(tableName, fieldName);\n return `${enumName}${optional}`;\n }\n\n switch (field.type) {\n case 'string':\n case 'text':\n case 'uuid':\n return `String${optional}`;\n case 'number':\n return `Int${optional}`;\n case 'bigint':\n return `BigInt${optional}`;\n case 'boolean':\n return `Boolean${optional}`;\n case 'date':\n return `DateTime${optional}`;\n case 'json':\n // SQLite doesn't have native JSON in Prisma — use String\n if (provider === 'sqlite') {\n return `String${optional}`;\n }\n return `Json${optional}`;\n default:\n return `String${optional}`;\n }\n}\n\n// =============================================================================\n// Attribute Generation\n// =============================================================================\n\nfunction getPrismaAttributes(\n fieldName: string,\n dbColName: string,\n field: PluginFieldAttribute,\n provider: PrismaProvider,\n): string {\n const attrs: string[] = [];\n\n // @id (single-column PK)\n if (field.primaryKey) {\n attrs.push('@id');\n }\n\n // @unique\n if (field.unique) {\n attrs.push('@unique');\n }\n\n // @default\n if (field.defaultValue !== undefined) {\n const defaultAttr = getPrismaDefault(field.defaultValue, field.type, provider);\n if (defaultAttr) {\n attrs.push(defaultAttr);\n }\n }\n\n // @updatedAt (for date fields with \"now()\" default and name \"updatedAt\")\n // In Prisma, @updatedAt automatically updates the timestamp\n // We only add it if the field is named updatedAt\n if (fieldName === 'updatedAt' && field.type === 'date') {\n attrs.push('@updatedAt');\n }\n\n // @map (column name differs from field name)\n if (dbColName !== fieldName) {\n attrs.push(`@map(\"${dbColName}\")`);\n }\n\n // @db.Text for MySQL long strings\n if (provider === 'mysql' && field.type === 'text') {\n attrs.push('@db.Text');\n }\n\n // @db.Timestamptz for PostgreSQL dates\n if (provider === 'postgresql' && field.type === 'date') {\n attrs.push('@db.Timestamptz(3)');\n }\n\n if (attrs.length === 0) {\n return '';\n }\n return ' ' + attrs.join(' ');\n}\n\nfunction getPrismaDefault(\n value: string | number | boolean | 'uuid()' | 'now()',\n _type: PluginFieldType,\n _provider: PrismaProvider,\n): string | null {\n if (value === 'uuid()') {\n return '@default(uuid())';\n }\n if (value === 'now()') {\n return '@default(now())';\n }\n if (typeof value === 'boolean') {\n return `@default(${value})`;\n }\n if (typeof value === 'number') {\n return `@default(${value})`;\n }\n if (typeof value === 'string') {\n return `@default(\"${value}\")`;\n }\n return null;\n}\n\n// =============================================================================\n// Relation Fields\n// =============================================================================\n\n/**\n * Generate Prisma relation fields for a model.\n *\n * In Prisma, if model A has a FK `bId → B.id`, we need:\n * - On A: `b B @relation(fields: [bId], references: [id])`\n * - On B: `as A[]` (reverse side)\n *\n * We generate the \"one\" side (FK holder) here; the \"many\" side\n * (reverse) is added to the referenced model.\n */\nfunction generateRelationFields(\n table: MergedTable,\n schema: MergedSchema,\n _provider: PrismaProvider,\n): string[] {\n const lines: string[] = [];\n const { definition } = table;\n\n // One-side: this table has FKs\n for (const [fieldName, field] of Object.entries(definition.fields)) {\n if (!field.references) {\n continue;\n }\n\n const refTableLogical = findLogicalName(schema, field.references.table);\n const refModelName = capitalize(refTableLogical);\n const relName = fieldName.replace(/Id$/, '').replace(/_id$/, '');\n const onDelete = mapOnDelete(field.references.onDelete);\n\n lines.push(\n `${relName} ${refModelName} @relation(fields: [${fieldName}], references: [${field.references.field}], onDelete: ${onDelete})`,\n );\n }\n\n // Many-side: other tables have FKs pointing to this table\n for (const otherTable of schema.tables) {\n if (otherTable.name === table.name) {\n continue;\n }\n\n for (const [_fieldName, field] of Object.entries(otherTable.definition.fields)) {\n if (!field.references) {\n continue;\n }\n\n // Check if this FK references our table\n const refsOurTable =\n field.references.table === table.name ||\n field.references.table === (table.definition.tableName || toSnakeCase(table.name));\n\n if (refsOurTable) {\n const otherModelName = capitalize(otherTable.name);\n // If the FK is unique, this is a one-to-one relation (singular, optional)\n // Otherwise it's one-to-many (array)\n const isUnique = field.unique === true;\n const relName = otherTable.name;\n lines.push(`${relName} ${otherModelName}${isUnique ? '?' : '[]'}`);\n }\n }\n }\n\n return lines;\n}\n\nfunction mapOnDelete(onDelete?: string): string {\n switch (onDelete) {\n case 'cascade':\n return 'Cascade';\n case 'set null':\n return 'SetNull';\n case 'restrict':\n return 'Restrict';\n case 'no action':\n return 'NoAction';\n default:\n return 'NoAction';\n }\n}\n\n// =============================================================================\n// Enum Helpers\n// =============================================================================\n\ninterface PrismaEnumDef {\n name: string;\n values: string[];\n}\n\nfunction collectPrismaEnums(schema: MergedSchema): PrismaEnumDef[] {\n const enums: PrismaEnumDef[] = [];\n\n for (const table of schema.tables) {\n for (const [fieldName, field] of Object.entries(table.definition.fields)) {\n if (isEnumType(field.type)) {\n enums.push({\n name: prismaEnumName(table.name, fieldName),\n values: field.type,\n });\n }\n }\n }\n\n return enums;\n}\n\nfunction prismaEnumName(tableName: string, fieldName: string): string {\n return `${capitalize(tableName)}${capitalize(fieldName)}`;\n}\n\n// =============================================================================\n// Shared Utilities\n// =============================================================================\n\nfunction isEnumType(type: PluginFieldType): type is string[] {\n return Array.isArray(type);\n}\n\nfunction toSnakeCase(str: string): string {\n return str.replace(/[A-Z]/g, (letter) => `_${letter.toLowerCase()}`);\n}\n\nfunction capitalize(str: string): string {\n return str.charAt(0).toUpperCase() + str.slice(1);\n}\n\n/**\n * Find the logical (camelCase) table name from a DB table name.\n */\nfunction findLogicalName(schema: MergedSchema, tableRef: string): string {\n // First try exact match on logical name\n const exact = schema.tables.find((t) => t.name === tableRef);\n if (exact) {\n return exact.name;\n }\n\n // Try by tableName property\n const byDbName = schema.tables.find(\n (t) => t.definition.tableName === tableRef || toSnakeCase(t.name) === tableRef,\n );\n if (byDbName) {\n return byDbName.name;\n }\n\n // Fallback: convert to camelCase\n if (tableRef.includes('_')) {\n return tableRef.replace(/_([a-z])/g, (_, c) => c.toUpperCase());\n }\n return tableRef;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"prisma-schema-generator.js","names":[],"sources":["../../src/database/prisma-schema-generator.ts"],"sourcesContent":["/**\n * Prisma Schema Generator\n *\n * Converts the merged abstract schema (core + plugins) into Prisma schema\n * model blocks. Unlike the Drizzle generators which produce complete\n * TypeScript files, this generates Prisma DSL.\n *\n * Two modes:\n * 1. `generatePrismaModels(schema, provider)` — returns only the model blocks\n * (for appending to an existing schema.prisma)\n * 2. `generateFullPrismaSchema(schema, provider)` — returns a complete\n * schema.prisma including generator + datasource blocks\n *\n * Uses the abstract schema types directly, converting to Prisma's type system:\n *\n * | Abstract | Prisma (PG/MySQL) | Prisma (SQLite) |\n * |-------------|-------------------|------------------|\n * | \"string\" | String | String |\n * | \"text\" | String | String |\n * | \"number\" | Int | Int |\n * | \"boolean\" | Boolean | Boolean |\n * | \"date\" | DateTime | DateTime |\n * | \"json\" | Json | String |\n * | \"uuid\" | String | String |\n * | \"bigint\" | BigInt | BigInt |\n * | string[] | enum | String (fallback)|\n */\n\nimport type { PluginFieldAttribute, PluginFieldType } from 'src/types/plugin.types';\nimport type { MergedSchema, MergedTable } from './schema-merger';\n\nexport type PrismaProvider = 'postgresql' | 'mysql' | 'sqlite';\n\n// =============================================================================\n// Full Schema Generator\n// =============================================================================\n\n/**\n * Generate a complete Prisma schema file from the merged abstract schema.\n *\n * Includes generator, datasource, enums, and all models.\n */\nexport function generateFullPrismaSchema(schema: MergedSchema, provider: PrismaProvider): string {\n const lines: string[] = [];\n\n // Header\n lines.push(`// Prisma schema for Invect — AUTO-GENERATED by @invect/cli`);\n lines.push(\n `// Do not edit the Invect models manually. Run \\`npx invect-cli generate\\` to regenerate.`,\n );\n lines.push(``);\n\n // Generator block\n lines.push(`generator client {`);\n lines.push(` provider = \"prisma-client-js\"`);\n lines.push(`}`);\n lines.push(``);\n\n // Datasource block\n lines.push(`datasource db {`);\n lines.push(` provider = \"${provider}\"`);\n if (provider === 'sqlite') {\n lines.push(` url = \"file:./dev.db\"`);\n } else {\n lines.push(` url = env(\"DATABASE_URL\")`);\n }\n lines.push(`}`);\n lines.push(``);\n\n // Enums (PostgreSQL and MySQL support enums; SQLite doesn't)\n if (provider !== 'sqlite') {\n const enums = collectPrismaEnums(schema);\n if (enums.length > 0) {\n lines.push(\n `// =============================================================================`,\n );\n lines.push(`// Enums`);\n lines.push(\n `// =============================================================================`,\n );\n lines.push(``);\n for (const e of enums) {\n lines.push(`enum ${e.name} {`);\n for (const v of e.values) {\n lines.push(` ${v}`);\n }\n lines.push(`}`);\n lines.push(``);\n }\n }\n }\n\n // Models\n lines.push(`// =============================================================================`);\n lines.push(`// Models`);\n lines.push(`// =============================================================================`);\n lines.push(``);\n\n for (const table of schema.tables) {\n lines.push(generatePrismaModel(table, schema, provider));\n lines.push(``);\n }\n\n return lines.join('\\n');\n}\n\n// =============================================================================\n// Model-Only Generator (for appending to existing schemas)\n// =============================================================================\n\n/**\n * Generate only the Prisma model blocks (no generator/datasource).\n *\n * Useful when adding Invect models to an existing Prisma schema.\n */\nexport function generatePrismaModels(schema: MergedSchema, provider: PrismaProvider): string {\n const lines: string[] = [];\n\n lines.push(``);\n lines.push(`// =============================================================================`);\n lines.push(`// Invect Models — AUTO-GENERATED by @invect/cli`);\n lines.push(`// Do not edit these models manually. Run \\`npx invect-cli generate\\` to regenerate.`);\n lines.push(`// =============================================================================`);\n lines.push(``);\n\n // Enums\n if (provider !== 'sqlite') {\n const enums = collectPrismaEnums(schema);\n for (const e of enums) {\n lines.push(`enum ${e.name} {`);\n for (const v of e.values) {\n lines.push(` ${v}`);\n }\n lines.push(`}`);\n lines.push(``);\n }\n }\n\n // Models\n for (const table of schema.tables) {\n lines.push(generatePrismaModel(table, schema, provider));\n lines.push(``);\n }\n\n return lines.join('\\n');\n}\n\n// =============================================================================\n// Single Model Generator\n// =============================================================================\n\nfunction generatePrismaModel(\n table: MergedTable,\n schema: MergedSchema,\n provider: PrismaProvider,\n): string {\n const lines: string[] = [];\n const { name, definition } = table;\n const dbTableName = definition.tableName || toSnakeCase(name);\n const modelName = capitalize(name);\n\n lines.push(`model ${modelName} {`);\n\n // Fields\n for (const [fieldName, field] of Object.entries(definition.fields)) {\n const dbColName = toSnakeCase(fieldName);\n const prismaType = getPrismaType(field, provider, name, fieldName);\n const attrs = getPrismaAttributes(fieldName, dbColName, field, provider);\n\n lines.push(` ${fieldName} ${prismaType}${attrs}`);\n }\n\n // Relation fields (Prisma requires explicit relation fields)\n const relationLines = generateRelationFields(table, schema, provider);\n for (const line of relationLines) {\n lines.push(` ${line}`);\n }\n\n // Composite primary key\n if (definition.compositePrimaryKey?.length) {\n lines.push(``);\n lines.push(` @@id([${definition.compositePrimaryKey.join(', ')}])`);\n }\n\n // @@index for indexed fields\n for (const [fieldName, field] of Object.entries(definition.fields)) {\n if (field.index && !field.unique && !field.primaryKey) {\n lines.push(` @@index([${fieldName}])`);\n }\n }\n\n // @@map for table name mapping\n if (dbTableName !== name) {\n lines.push(` @@map(\"${dbTableName}\")`);\n }\n\n lines.push(`}`);\n\n return lines.join('\\n');\n}\n\n// =============================================================================\n// Type Mapping\n// =============================================================================\n\nfunction getPrismaType(\n field: PluginFieldAttribute,\n provider: PrismaProvider,\n tableName: string,\n fieldName: string,\n): string {\n const optional = field.required === false ? '?' : '';\n\n if (isEnumType(field.type)) {\n if (provider === 'sqlite') {\n // SQLite doesn't support enums in Prisma, use String\n return `String${optional}`;\n }\n const enumName = prismaEnumName(tableName, fieldName);\n return `${enumName}${optional}`;\n }\n\n switch (field.type) {\n case 'string':\n case 'text':\n case 'uuid':\n return `String${optional}`;\n case 'number':\n return `Int${optional}`;\n case 'bigint':\n return `BigInt${optional}`;\n case 'boolean':\n return `Boolean${optional}`;\n case 'date':\n return `DateTime${optional}`;\n case 'json':\n // SQLite doesn't have native JSON in Prisma — use String\n if (provider === 'sqlite') {\n return `String${optional}`;\n }\n return `Json${optional}`;\n default:\n return `String${optional}`;\n }\n}\n\n// =============================================================================\n// Attribute Generation\n// =============================================================================\n\nfunction getPrismaAttributes(\n fieldName: string,\n dbColName: string,\n field: PluginFieldAttribute,\n provider: PrismaProvider,\n): string {\n const attrs: string[] = [];\n\n // @id (single-column PK)\n if (field.primaryKey) {\n attrs.push('@id');\n }\n\n // @unique\n if (field.unique) {\n attrs.push('@unique');\n }\n\n // @default\n if (field.defaultValue !== undefined) {\n const defaultAttr = getPrismaDefault(field.defaultValue, field.type, provider);\n if (defaultAttr) {\n attrs.push(defaultAttr);\n }\n }\n\n // @updatedAt (for date fields with \"now()\" default and name \"updatedAt\")\n // In Prisma, @updatedAt automatically updates the timestamp\n // We only add it if the field is named updatedAt\n if (fieldName === 'updatedAt' && field.type === 'date') {\n attrs.push('@updatedAt');\n }\n\n // @map (column name differs from field name)\n if (dbColName !== fieldName) {\n attrs.push(`@map(\"${dbColName}\")`);\n }\n\n // @db.Text for MySQL long strings\n if (provider === 'mysql' && field.type === 'text') {\n attrs.push('@db.Text');\n }\n\n // @db.Timestamptz for PostgreSQL dates\n if (provider === 'postgresql' && field.type === 'date') {\n attrs.push('@db.Timestamptz(3)');\n }\n\n if (attrs.length === 0) {\n return '';\n }\n return ' ' + attrs.join(' ');\n}\n\nfunction getPrismaDefault(\n value: string | number | boolean | 'uuid()' | 'now()',\n _type: PluginFieldType,\n _provider: PrismaProvider,\n): string | null {\n if (value === 'uuid()') {\n return '@default(uuid())';\n }\n if (value === 'now()') {\n return '@default(now())';\n }\n if (typeof value === 'boolean') {\n return `@default(${value})`;\n }\n if (typeof value === 'number') {\n return `@default(${value})`;\n }\n if (typeof value === 'string') {\n return `@default(\"${value}\")`;\n }\n return null;\n}\n\n// =============================================================================\n// Relation Fields\n// =============================================================================\n\n/**\n * Generate Prisma relation fields for a model.\n *\n * In Prisma, if model A has a FK `bId → B.id`, we need:\n * - On A: `b B @relation(fields: [bId], references: [id])`\n * - On B: `as A[]` (reverse side)\n *\n * We generate the \"one\" side (FK holder) here; the \"many\" side\n * (reverse) is added to the referenced model.\n */\nfunction generateRelationFields(\n table: MergedTable,\n schema: MergedSchema,\n _provider: PrismaProvider,\n): string[] {\n const lines: string[] = [];\n const { definition } = table;\n\n // One-side: this table has FKs\n for (const [fieldName, field] of Object.entries(definition.fields)) {\n if (!field.references) {\n continue;\n }\n\n const refTableLogical = findLogicalName(schema, field.references.table);\n const refModelName = capitalize(refTableLogical);\n const relName = fieldName.replace(/Id$/, '').replace(/_id$/, '');\n const onDelete = mapOnDelete(field.references.onDelete);\n\n lines.push(\n `${relName} ${refModelName} @relation(fields: [${fieldName}], references: [${field.references.field}], onDelete: ${onDelete})`,\n );\n }\n\n // Many-side: other tables have FKs pointing to this table\n for (const otherTable of schema.tables) {\n if (otherTable.name === table.name) {\n continue;\n }\n\n for (const [_fieldName, field] of Object.entries(otherTable.definition.fields)) {\n if (!field.references) {\n continue;\n }\n\n // Check if this FK references our table\n const refsOurTable =\n field.references.table === table.name ||\n field.references.table === (table.definition.tableName || toSnakeCase(table.name));\n\n if (refsOurTable) {\n const otherModelName = capitalize(otherTable.name);\n // If the FK is unique, this is a one-to-one relation (singular, optional)\n // Otherwise it's one-to-many (array)\n const isUnique = field.unique === true;\n const relName = otherTable.name;\n lines.push(`${relName} ${otherModelName}${isUnique ? '?' : '[]'}`);\n }\n }\n }\n\n return lines;\n}\n\nfunction mapOnDelete(onDelete?: string): string {\n switch (onDelete) {\n case 'cascade':\n return 'Cascade';\n case 'set null':\n return 'SetNull';\n case 'restrict':\n return 'Restrict';\n case 'no action':\n return 'NoAction';\n default:\n return 'NoAction';\n }\n}\n\n// =============================================================================\n// Enum Helpers\n// =============================================================================\n\ninterface PrismaEnumDef {\n name: string;\n values: string[];\n}\n\nfunction collectPrismaEnums(schema: MergedSchema): PrismaEnumDef[] {\n const enums: PrismaEnumDef[] = [];\n\n for (const table of schema.tables) {\n for (const [fieldName, field] of Object.entries(table.definition.fields)) {\n if (isEnumType(field.type)) {\n enums.push({\n name: prismaEnumName(table.name, fieldName),\n values: field.type,\n });\n }\n }\n }\n\n return enums;\n}\n\nfunction prismaEnumName(tableName: string, fieldName: string): string {\n return `${capitalize(tableName)}${capitalize(fieldName)}`;\n}\n\n// =============================================================================\n// Shared Utilities\n// =============================================================================\n\nfunction isEnumType(type: PluginFieldType): type is string[] {\n return Array.isArray(type);\n}\n\nfunction toSnakeCase(str: string): string {\n return str.replace(/[A-Z]/g, (letter) => `_${letter.toLowerCase()}`);\n}\n\nfunction capitalize(str: string): string {\n return str.charAt(0).toUpperCase() + str.slice(1);\n}\n\n/**\n * Find the logical (camelCase) table name from a DB table name.\n */\nfunction findLogicalName(schema: MergedSchema, tableRef: string): string {\n // First try exact match on logical name\n const exact = schema.tables.find((t) => t.name === tableRef);\n if (exact) {\n return exact.name;\n }\n\n // Try by tableName property\n const byDbName = schema.tables.find(\n (t) => t.definition.tableName === tableRef || toSnakeCase(t.name) === tableRef,\n );\n if (byDbName) {\n return byDbName.name;\n }\n\n // Fallback: convert to camelCase\n if (tableRef.includes('_')) {\n return tableRef.replace(/_([a-z])/g, (_, c) => c.toUpperCase());\n }\n return tableRef;\n}\n"],"mappings":"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"}
|
|
@@ -38,7 +38,7 @@ function generateSqliteSchema(schema) {
|
|
|
38
38
|
const lines = [];
|
|
39
39
|
const runtimeImports = collectSqliteRuntimeDefaultImports(schema);
|
|
40
40
|
lines.push(`// SQLite schema for Invect — AUTO-GENERATED by @invect/cli`);
|
|
41
|
-
lines.push(`// Do not edit manually. Run \`npx invect generate\` to regenerate.`);
|
|
41
|
+
lines.push(`// Do not edit manually. Run \`npx invect-cli generate\` to regenerate.`);
|
|
42
42
|
lines.push(``);
|
|
43
43
|
lines.push(`import { sqliteTable, text, integer, primaryKey, type AnySQLiteColumn } from 'drizzle-orm/sqlite-core';`);
|
|
44
44
|
lines.push(`import { relations, sql } from 'drizzle-orm';`);
|
|
@@ -149,7 +149,7 @@ function sqliteDefault(value, _type, typeAnnotation) {
|
|
|
149
149
|
function generatePostgresSchema(schema) {
|
|
150
150
|
const lines = [];
|
|
151
151
|
lines.push(`// PostgreSQL schema for Invect — AUTO-GENERATED by @invect/cli`);
|
|
152
|
-
lines.push(`// Do not edit manually. Run \`npx invect generate\` to regenerate.`);
|
|
152
|
+
lines.push(`// Do not edit manually. Run \`npx invect-cli generate\` to regenerate.`);
|
|
153
153
|
lines.push(``);
|
|
154
154
|
lines.push(`import {`);
|
|
155
155
|
lines.push(` pgTable,`);
|
|
@@ -274,7 +274,7 @@ function postgresDefault(value, _type) {
|
|
|
274
274
|
function generateMysqlSchema(schema) {
|
|
275
275
|
const lines = [];
|
|
276
276
|
lines.push(`// MySQL schema for Invect — AUTO-GENERATED by @invect/cli`);
|
|
277
|
-
lines.push(`// Do not edit manually. Run \`npx invect generate\` to regenerate.`);
|
|
277
|
+
lines.push(`// Do not edit manually. Run \`npx invect-cli generate\` to regenerate.`);
|
|
278
278
|
lines.push(``);
|
|
279
279
|
lines.push(`import {`);
|
|
280
280
|
lines.push(` mysqlTable,`);
|
|
@@ -400,7 +400,7 @@ function generateSqliteSchemaAppend(schema) {
|
|
|
400
400
|
lines.push(``);
|
|
401
401
|
lines.push(`// =============================================================================`);
|
|
402
402
|
lines.push(`// Invect tables — AUTO-GENERATED by @invect/cli`);
|
|
403
|
-
lines.push(`// Do not edit below this line. Run \`npx invect generate\` to regenerate.`);
|
|
403
|
+
lines.push(`// Do not edit below this line. Run \`npx invect-cli generate\` to regenerate.`);
|
|
404
404
|
lines.push(`// =============================================================================`);
|
|
405
405
|
lines.push(``);
|
|
406
406
|
for (const table of schema.tables) {
|
|
@@ -429,7 +429,7 @@ function generatePostgresSchemaAppend(schema) {
|
|
|
429
429
|
lines.push(``);
|
|
430
430
|
lines.push(`// =============================================================================`);
|
|
431
431
|
lines.push(`// Invect tables — AUTO-GENERATED by @invect/cli`);
|
|
432
|
-
lines.push(`// Do not edit below this line. Run \`npx invect generate\` to regenerate.`);
|
|
432
|
+
lines.push(`// Do not edit below this line. Run \`npx invect-cli generate\` to regenerate.`);
|
|
433
433
|
lines.push(`// =============================================================================`);
|
|
434
434
|
lines.push(``);
|
|
435
435
|
const enums = collectEnums(schema);
|
|
@@ -463,7 +463,7 @@ function generateMysqlSchemaAppend(schema) {
|
|
|
463
463
|
lines.push(``);
|
|
464
464
|
lines.push(`// =============================================================================`);
|
|
465
465
|
lines.push(`// Invect tables — AUTO-GENERATED by @invect/cli`);
|
|
466
|
-
lines.push(`// Do not edit below this line. Run \`npx invect generate\` to regenerate.`);
|
|
466
|
+
lines.push(`// Do not edit below this line. Run \`npx invect-cli generate\` to regenerate.`);
|
|
467
467
|
lines.push(`// =============================================================================`);
|
|
468
468
|
lines.push(``);
|
|
469
469
|
for (const table of schema.tables) {
|