@invect/core 0.1.0 → 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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 @robase
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -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":"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"}
@@ -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) {