@opensaas/stack-cli 0.1.7 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (104) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/CHANGELOG.md +348 -0
  3. package/CLAUDE.md +60 -12
  4. package/dist/commands/generate.d.ts.map +1 -1
  5. package/dist/commands/generate.js +13 -13
  6. package/dist/commands/generate.js.map +1 -1
  7. package/dist/commands/mcp.d.ts +6 -0
  8. package/dist/commands/mcp.d.ts.map +1 -0
  9. package/dist/commands/mcp.js +116 -0
  10. package/dist/commands/mcp.js.map +1 -0
  11. package/dist/generator/context.d.ts.map +1 -1
  12. package/dist/generator/context.js +40 -7
  13. package/dist/generator/context.js.map +1 -1
  14. package/dist/generator/index.d.ts +4 -1
  15. package/dist/generator/index.d.ts.map +1 -1
  16. package/dist/generator/index.js +4 -1
  17. package/dist/generator/index.js.map +1 -1
  18. package/dist/generator/lists.d.ts +31 -0
  19. package/dist/generator/lists.d.ts.map +1 -0
  20. package/dist/generator/lists.js +123 -0
  21. package/dist/generator/lists.js.map +1 -0
  22. package/dist/generator/plugin-types.d.ts +10 -0
  23. package/dist/generator/plugin-types.d.ts.map +1 -0
  24. package/dist/generator/plugin-types.js +122 -0
  25. package/dist/generator/plugin-types.js.map +1 -0
  26. package/dist/generator/prisma-config.d.ts +17 -0
  27. package/dist/generator/prisma-config.d.ts.map +1 -0
  28. package/dist/generator/prisma-config.js +40 -0
  29. package/dist/generator/prisma-config.js.map +1 -0
  30. package/dist/generator/prisma-extensions.d.ts +11 -0
  31. package/dist/generator/prisma-extensions.d.ts.map +1 -0
  32. package/dist/generator/prisma-extensions.js +134 -0
  33. package/dist/generator/prisma-extensions.js.map +1 -0
  34. package/dist/generator/prisma.d.ts.map +1 -1
  35. package/dist/generator/prisma.js +5 -2
  36. package/dist/generator/prisma.js.map +1 -1
  37. package/dist/generator/types.d.ts.map +1 -1
  38. package/dist/generator/types.js +201 -17
  39. package/dist/generator/types.js.map +1 -1
  40. package/dist/index.js +3 -0
  41. package/dist/index.js.map +1 -1
  42. package/dist/mcp/lib/documentation-provider.d.ts +43 -0
  43. package/dist/mcp/lib/documentation-provider.d.ts.map +1 -0
  44. package/dist/mcp/lib/documentation-provider.js +163 -0
  45. package/dist/mcp/lib/documentation-provider.js.map +1 -0
  46. package/dist/mcp/lib/features/catalog.d.ts +26 -0
  47. package/dist/mcp/lib/features/catalog.d.ts.map +1 -0
  48. package/dist/mcp/lib/features/catalog.js +291 -0
  49. package/dist/mcp/lib/features/catalog.js.map +1 -0
  50. package/dist/mcp/lib/generators/feature-generator.d.ts +35 -0
  51. package/dist/mcp/lib/generators/feature-generator.d.ts.map +1 -0
  52. package/dist/mcp/lib/generators/feature-generator.js +546 -0
  53. package/dist/mcp/lib/generators/feature-generator.js.map +1 -0
  54. package/dist/mcp/lib/types.d.ts +80 -0
  55. package/dist/mcp/lib/types.d.ts.map +1 -0
  56. package/dist/mcp/lib/types.js +5 -0
  57. package/dist/mcp/lib/types.js.map +1 -0
  58. package/dist/mcp/lib/wizards/wizard-engine.d.ts +71 -0
  59. package/dist/mcp/lib/wizards/wizard-engine.d.ts.map +1 -0
  60. package/dist/mcp/lib/wizards/wizard-engine.js +356 -0
  61. package/dist/mcp/lib/wizards/wizard-engine.js.map +1 -0
  62. package/dist/mcp/server/index.d.ts +8 -0
  63. package/dist/mcp/server/index.d.ts.map +1 -0
  64. package/dist/mcp/server/index.js +202 -0
  65. package/dist/mcp/server/index.js.map +1 -0
  66. package/dist/mcp/server/stack-mcp-server.d.ts +92 -0
  67. package/dist/mcp/server/stack-mcp-server.d.ts.map +1 -0
  68. package/dist/mcp/server/stack-mcp-server.js +265 -0
  69. package/dist/mcp/server/stack-mcp-server.js.map +1 -0
  70. package/package.json +10 -8
  71. package/src/commands/__snapshots__/generate.test.ts.snap +145 -38
  72. package/src/commands/dev.test.ts +0 -1
  73. package/src/commands/generate.test.ts +18 -8
  74. package/src/commands/generate.ts +20 -19
  75. package/src/commands/mcp.ts +135 -0
  76. package/src/generator/__snapshots__/context.test.ts.snap +63 -18
  77. package/src/generator/__snapshots__/prisma.test.ts.snap +8 -16
  78. package/src/generator/__snapshots__/types.test.ts.snap +1267 -95
  79. package/src/generator/context.test.ts +15 -8
  80. package/src/generator/context.ts +40 -7
  81. package/src/generator/index.ts +4 -1
  82. package/src/generator/lists.test.ts +335 -0
  83. package/src/generator/lists.ts +140 -0
  84. package/src/generator/plugin-types.ts +147 -0
  85. package/src/generator/prisma-config.ts +46 -0
  86. package/src/generator/prisma-extensions.ts +159 -0
  87. package/src/generator/prisma.test.ts +0 -10
  88. package/src/generator/prisma.ts +6 -2
  89. package/src/generator/types.test.ts +0 -12
  90. package/src/generator/types.ts +257 -17
  91. package/src/index.ts +4 -0
  92. package/src/mcp/lib/documentation-provider.ts +203 -0
  93. package/src/mcp/lib/features/catalog.ts +301 -0
  94. package/src/mcp/lib/generators/feature-generator.ts +598 -0
  95. package/src/mcp/lib/types.ts +89 -0
  96. package/src/mcp/lib/wizards/wizard-engine.ts +427 -0
  97. package/src/mcp/server/index.ts +240 -0
  98. package/src/mcp/server/stack-mcp-server.ts +301 -0
  99. package/tsconfig.tsbuildinfo +1 -1
  100. package/dist/generator/type-patcher.d.ts +0 -13
  101. package/dist/generator/type-patcher.d.ts.map +0 -1
  102. package/dist/generator/type-patcher.js +0 -68
  103. package/dist/generator/type-patcher.js.map +0 -1
  104. package/src/generator/type-patcher.ts +0 -93
@@ -0,0 +1,116 @@
1
+ /**
2
+ * MCP command group for AI-assisted development
3
+ */
4
+ import { Command } from 'commander';
5
+ import { spawn } from 'child_process';
6
+ import { fileURLToPath } from 'url';
7
+ import { dirname, join } from 'path';
8
+ const __filename = fileURLToPath(import.meta.url);
9
+ const __dirname = dirname(__filename);
10
+ function getServerPath() {
11
+ // In development: cli/dist/mcp/server/index.js
12
+ // In production: same structure
13
+ return join(__dirname, '..', 'mcp', 'server', 'index.js');
14
+ }
15
+ function installMCPServer() {
16
+ return new Promise((resolve, reject) => {
17
+ console.log('📦 Installing OpenSaaS Stack MCP server...\n');
18
+ const serverPath = getServerPath();
19
+ const claudeCommand = ['claude', 'mcp', 'add', 'opensaas-stack', '--', 'node', serverPath];
20
+ console.log(`Running: ${claudeCommand.join(' ')}\n`);
21
+ const child = spawn(claudeCommand[0], claudeCommand.slice(1), {
22
+ stdio: 'inherit',
23
+ });
24
+ child.on('close', (code) => {
25
+ if (code === 0) {
26
+ console.log('\n✅ OpenSaaS Stack MCP server installed successfully!');
27
+ console.log('\n📖 Available tools:');
28
+ console.log(' - opensaas_implement_feature');
29
+ console.log(' - opensaas_feature_docs');
30
+ console.log(' - opensaas_list_features');
31
+ console.log(' - opensaas_suggest_features');
32
+ console.log(' - opensaas_validate_feature');
33
+ console.log('\n🚀 Restart Claude Code to use the MCP tools.');
34
+ resolve();
35
+ }
36
+ else {
37
+ console.error(`\n❌ Installation failed with code ${code}. Please ensure Claude Code is installed.`);
38
+ reject(new Error(`Installation failed with code ${code}`));
39
+ }
40
+ });
41
+ child.on('error', (error) => {
42
+ console.error('\n❌ Error during installation:', error.message);
43
+ console.error('\nMake sure Claude Code is installed and the "claude" command is available.');
44
+ reject(error);
45
+ });
46
+ });
47
+ }
48
+ function uninstallMCPServer() {
49
+ return new Promise((resolve, reject) => {
50
+ console.log('🗑️ Uninstalling OpenSaaS Stack MCP server...\n');
51
+ const child = spawn('claude', ['mcp', 'remove', 'opensaas-stack'], {
52
+ stdio: 'inherit',
53
+ });
54
+ child.on('close', (code) => {
55
+ if (code === 0) {
56
+ console.log('\n✅ OpenSaaS Stack MCP server uninstalled successfully.');
57
+ resolve();
58
+ }
59
+ else {
60
+ console.error(`\n❌ Uninstall failed with code ${code}`);
61
+ reject(new Error(`Uninstall failed with code ${code}`));
62
+ }
63
+ });
64
+ child.on('error', (error) => {
65
+ console.error('\n❌ Error during uninstall:', error.message);
66
+ reject(error);
67
+ });
68
+ });
69
+ }
70
+ function startMCPServer() {
71
+ console.log('🚀 Starting OpenSaaS Stack MCP server...\n');
72
+ const serverPath = getServerPath();
73
+ const child = spawn('node', [serverPath], {
74
+ stdio: 'inherit',
75
+ });
76
+ child.on('error', (error) => {
77
+ console.error('❌ Error starting server:', error.message);
78
+ process.exit(1);
79
+ });
80
+ }
81
+ export function createMCPCommand() {
82
+ const mcp = new Command('mcp');
83
+ mcp.description('MCP server for AI-assisted development with Claude Code');
84
+ mcp
85
+ .command('install')
86
+ .description('Install MCP server in Claude Code')
87
+ .action(async () => {
88
+ try {
89
+ await installMCPServer();
90
+ process.exit(0);
91
+ }
92
+ catch {
93
+ process.exit(1);
94
+ }
95
+ });
96
+ mcp
97
+ .command('uninstall')
98
+ .description('Remove MCP server from Claude Code')
99
+ .action(async () => {
100
+ try {
101
+ await uninstallMCPServer();
102
+ process.exit(0);
103
+ }
104
+ catch {
105
+ process.exit(1);
106
+ }
107
+ });
108
+ mcp
109
+ .command('start')
110
+ .description('Start MCP server directly (for debugging)')
111
+ .action(() => {
112
+ startMCPServer();
113
+ });
114
+ return mcp;
115
+ }
116
+ //# sourceMappingURL=mcp.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp.js","sourceRoot":"","sources":["../../src/commands/mcp.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/generator/context.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAA;AAI1D;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,cAAc,GAAG,MAAM,CAwK9D;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI,CAU7E"}
1
+ {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/generator/context.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAA;AAI1D;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,cAAc,GAAG,MAAM,CAyM9D;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI,CAU7E"}
@@ -12,9 +12,27 @@ export function generateContext(config) {
12
12
  // Check if storage is configured
13
13
  const hasStorage = !!config.storage && Object.keys(config.storage).length > 0;
14
14
  // Generate the Prisma client instantiation code
15
+ // Prisma 7 requires adapters, so prismaClientConstructor must be provided
15
16
  const prismaInstantiation = hasCustomConstructor
16
17
  ? `resolvedConfig.db.prismaClientConstructor!(PrismaClient)`
17
- : `new PrismaClient()`;
18
+ : `(() => {
19
+ throw new Error(
20
+ 'Prisma 7 requires a database adapter. Please add prismaClientConstructor to your opensaas.config.ts db configuration.\\n\\n' +
21
+ 'Example for SQLite:\\n' +
22
+ 'import { PrismaBetterSQLite3 } from \\'@prisma/adapter-better-sqlite3\\'\\n' +
23
+ 'import Database from \\'better-sqlite3\\'\\n\\n' +
24
+ 'db: {\\n' +
25
+ ' provider: \\'sqlite\\',\\n' +
26
+ ' url: process.env.DATABASE_URL || \\'file:./dev.db\\',\\n' +
27
+ ' prismaClientConstructor: (PrismaClient) => {\\n' +
28
+ ' const db = new Database(process.env.DATABASE_URL || \\'./dev.db\\')\\n' +
29
+ ' const adapter = new PrismaBetterSQLite3(db)\\n' +
30
+ ' return new PrismaClient({ adapter })\\n' +
31
+ ' }\\n' +
32
+ '}\\n\\n' +
33
+ 'See https://www.prisma.io/docs/orm/overview/databases/database-drivers for more information.'
34
+ )
35
+ })()`;
18
36
  // Generate storage utilities if storage is configured
19
37
  const storageUtilities = hasStorage
20
38
  ? `
@@ -97,8 +115,9 @@ const storage = {
97
115
 
98
116
  import { getContext as getOpensaasContext } from '@opensaas/stack-core'
99
117
  import type { Session as OpensaasSession, OpenSaasConfig } from '@opensaas/stack-core'
100
- import { PrismaClient } from './prisma-client'
118
+ import { PrismaClient } from './prisma-client/client'
101
119
  import type { Context } from './types'
120
+ import { prismaExtensions } from './prisma-extensions'
102
121
  import configOrPromise from '../opensaas.config'
103
122
 
104
123
  // Resolve config if it's a Promise (when plugins are present)
@@ -106,15 +125,29 @@ const configPromise = Promise.resolve(configOrPromise)
106
125
  let resolvedConfig: OpenSaasConfig | null = null
107
126
 
108
127
  // Internal Prisma singleton - managed automatically
109
- const globalForPrisma = globalThis as unknown as { prisma: PrismaClient | undefined }
110
- let prisma: PrismaClient | null = null
128
+ const globalForPrisma = globalThis as unknown as { prisma: ReturnType<typeof createExtendedPrisma> | null }
129
+ let prisma: ReturnType<typeof createExtendedPrisma> | null = null
130
+
131
+ /**
132
+ * Create Prisma client with result extensions
133
+ */
134
+ function createExtendedPrisma(basePrisma: PrismaClient) {
135
+ // Check if there are any extensions to apply
136
+ if (Object.keys(prismaExtensions).length === 0) {
137
+ return basePrisma
138
+ }
139
+ // Apply result extensions
140
+ return basePrisma.$extends(prismaExtensions)
141
+ }
111
142
 
112
143
  async function getPrisma() {
113
144
  if (!prisma) {
114
145
  if (!resolvedConfig) {
115
146
  resolvedConfig = await configPromise
116
147
  }
117
- prisma = globalForPrisma.prisma ?? ${prismaInstantiation}
148
+ const basePrisma = ${prismaInstantiation}
149
+ const extendedPrisma = createExtendedPrisma(basePrisma)
150
+ prisma = globalForPrisma.prisma ?? extendedPrisma
118
151
  if (process.env.NODE_ENV !== 'production') globalForPrisma.prisma = prisma
119
152
  }
120
153
  return prisma
@@ -151,7 +184,7 @@ ${storageUtilities}
151
184
  export async function getContext<TSession extends OpensaasSession = OpensaasSession>(session?: TSession): Promise<Context<TSession>> {
152
185
  const config = await getConfig()
153
186
  const prismaClient = await getPrisma()
154
- return getOpensaasContext(config, prismaClient, session ?? null, storage) as Context<TSession>
187
+ return getOpensaasContext(config, prismaClient, session ?? null, storage) as unknown as Context<TSession>
155
188
  }
156
189
 
157
190
  /**
@@ -161,7 +194,7 @@ export async function getContext<TSession extends OpensaasSession = OpensaasSess
161
194
  export const rawOpensaasContext = (async () => {
162
195
  const config = await getConfig()
163
196
  const prismaClient = await getPrisma()
164
- return getOpensaasContext(config, prismaClient, null, storage)
197
+ return getOpensaasContext(config, prismaClient, null, storage) as unknown as Context
165
198
  })()
166
199
 
167
200
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"context.js","sourceRoot":"","sources":["../../src/generator/context.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,IAAI,CAAA;AACxB,OAAO,KAAK,IAAI,MAAM,MAAM,CAAA;AAE5B;;;;;GAKG;AACH,MAAM,UAAU,eAAe,CAAC,MAAsB;IACpD,wDAAwD;IACxD,MAAM,oBAAoB,GAAG,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,uBAAuB,CAAA;IAEhE,iCAAiC;IACjC,MAAM,UAAU,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,MAAM,GAAG,CAAC,CAAA;IAE7E,gDAAgD;IAChD,MAAM,mBAAmB,GAAG,oBAAoB;QAC9C,CAAC,CAAC,0DAA0D;QAC5D,CAAC,CAAC,oBAAoB,CAAA;IAExB,sDAAsD;IACtD,MAAM,gBAAgB,GAAG,UAAU;QACjC,CAAC,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAgDL;QACG,CAAC,CAAC;;;;;;;;;;;;;;;;;;CAkBL,CAAA;IAEC,2CAA2C;IAC3C,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;yCA4BgC,mBAAmB;;;;;;;;;;;;EAY1D,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA2CjB,CAAA;AACD,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,YAAY,CAAC,MAAsB,EAAE,UAAkB;IACrE,MAAM,OAAO,GAAG,eAAe,CAAC,MAAM,CAAC,CAAA;IAEvC,0BAA0B;IAC1B,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAA;IACpC,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QACxB,EAAE,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;IACxC,CAAC;IAED,EAAE,CAAC,aAAa,CAAC,UAAU,EAAE,OAAO,EAAE,OAAO,CAAC,CAAA;AAChD,CAAC"}
1
+ {"version":3,"file":"context.js","sourceRoot":"","sources":["../../src/generator/context.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,IAAI,CAAA;AACxB,OAAO,KAAK,IAAI,MAAM,MAAM,CAAA;AAE5B;;;;;GAKG;AACH,MAAM,UAAU,eAAe,CAAC,MAAsB;IACpD,wDAAwD;IACxD,MAAM,oBAAoB,GAAG,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,uBAAuB,CAAA;IAEhE,iCAAiC;IACjC,MAAM,UAAU,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,MAAM,GAAG,CAAC,CAAA;IAE7E,gDAAgD;IAChD,0EAA0E;IAC1E,MAAM,mBAAmB,GAAG,oBAAoB;QAC9C,CAAC,CAAC,0DAA0D;QAC5D,CAAC,CAAC;;;;;;;;;;;;;;;;;SAiBG,CAAA;IAEP,sDAAsD;IACtD,MAAM,gBAAgB,GAAG,UAAU;QACjC,CAAC,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAgDL;QACG,CAAC,CAAC;;;;;;;;;;;;;;;;;;CAkBL,CAAA;IAEC,2CAA2C;IAC3C,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;yBAyCgB,mBAAmB;;;;;;;;;;;;;;EAc1C,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA2CjB,CAAA;AACD,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,YAAY,CAAC,MAAsB,EAAE,UAAkB;IACrE,MAAM,OAAO,GAAG,eAAe,CAAC,MAAM,CAAC,CAAA;IAEvC,0BAA0B;IAC1B,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAA;IACpC,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QACxB,EAAE,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;IACxC,CAAC;IAED,EAAE,CAAC,aAAa,CAAC,UAAU,EAAE,OAAO,EAAE,OAAO,CAAC,CAAA;AAChD,CAAC"}
@@ -1,5 +1,8 @@
1
1
  export { generatePrismaSchema, writePrismaSchema } from './prisma.js';
2
+ export { generatePrismaConfig, writePrismaConfig } from './prisma-config.js';
2
3
  export { generateTypes, writeTypes } from './types.js';
3
- export { patchPrismaTypes } from './type-patcher.js';
4
+ export { generateListsNamespace, writeLists } from './lists.js';
4
5
  export { generateContext, writeContext } from './context.js';
6
+ export { generatePluginTypes, writePluginTypes } from './plugin-types.js';
7
+ export { generatePrismaExtensions, writePrismaExtensions } from './prisma-extensions.js';
5
8
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/generator/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAA;AACrE,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AACtD,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAA;AACpD,OAAO,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,cAAc,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/generator/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAA;AACrE,OAAO,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAA;AAC5E,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AACtD,OAAO,EAAE,sBAAsB,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAC/D,OAAO,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,cAAc,CAAA;AAC5D,OAAO,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAA;AACzE,OAAO,EAAE,wBAAwB,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAA"}
@@ -1,5 +1,8 @@
1
1
  export { generatePrismaSchema, writePrismaSchema } from './prisma.js';
2
+ export { generatePrismaConfig, writePrismaConfig } from './prisma-config.js';
2
3
  export { generateTypes, writeTypes } from './types.js';
3
- export { patchPrismaTypes } from './type-patcher.js';
4
+ export { generateListsNamespace, writeLists } from './lists.js';
4
5
  export { generateContext, writeContext } from './context.js';
6
+ export { generatePluginTypes, writePluginTypes } from './plugin-types.js';
7
+ export { generatePrismaExtensions, writePrismaExtensions } from './prisma-extensions.js';
5
8
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/generator/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAA;AACrE,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AACtD,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAA;AACpD,OAAO,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,cAAc,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/generator/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAA;AACrE,OAAO,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAA;AAC5E,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AACtD,OAAO,EAAE,sBAAsB,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAC/D,OAAO,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,cAAc,CAAA;AAC5D,OAAO,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAA;AACzE,OAAO,EAAE,wBAAwB,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAA"}
@@ -0,0 +1,31 @@
1
+ import type { OpenSaasConfig } from '@opensaas/stack-core';
2
+ /**
3
+ * Generate Lists namespace with TypeInfo for each list
4
+ * This provides strongly-typed hooks with Prisma input types
5
+ *
6
+ * @example
7
+ * ```typescript
8
+ * // Generated output:
9
+ * export declare namespace Lists {
10
+ * export type Post = import('@opensaas/stack-core').ListConfig<Lists.Post.TypeInfo>
11
+ *
12
+ * namespace Post {
13
+ * export type Item = import('./types').Post
14
+ * export type TypeInfo = {
15
+ * key: 'Post'
16
+ * item: Item
17
+ * inputs: {
18
+ * create: import('./prisma-client/client').Prisma.PostCreateInput
19
+ * update: import('./prisma-client/client').Prisma.PostUpdateInput
20
+ * }
21
+ * }
22
+ * }
23
+ * }
24
+ * ```
25
+ */
26
+ export declare function generateListsNamespace(config: OpenSaasConfig): string;
27
+ /**
28
+ * Write Lists namespace to file
29
+ */
30
+ export declare function writeLists(config: OpenSaasConfig, outputPath: string): void;
31
+ //# sourceMappingURL=lists.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lists.d.ts","sourceRoot":"","sources":["../../src/generator/lists.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAA;AAuB1D;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,cAAc,GAAG,MAAM,CA6ErE;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,MAAM,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI,CAU3E"}
@@ -0,0 +1,123 @@
1
+ import * as fs from 'fs';
2
+ import * as path from 'path';
3
+ /**
4
+ * Map field type string to TypeScript field type name
5
+ */
6
+ function getFieldTypeName(fieldType) {
7
+ const typeMap = {
8
+ text: 'TextField',
9
+ integer: 'IntegerField',
10
+ checkbox: 'CheckboxField',
11
+ timestamp: 'TimestampField',
12
+ password: 'PasswordField',
13
+ select: 'SelectField',
14
+ relationship: 'RelationshipField',
15
+ json: 'JsonField',
16
+ virtual: 'VirtualField',
17
+ };
18
+ return typeMap[fieldType] || 'BaseFieldConfig';
19
+ }
20
+ /**
21
+ * Generate Lists namespace with TypeInfo for each list
22
+ * This provides strongly-typed hooks with Prisma input types
23
+ *
24
+ * @example
25
+ * ```typescript
26
+ * // Generated output:
27
+ * export declare namespace Lists {
28
+ * export type Post = import('@opensaas/stack-core').ListConfig<Lists.Post.TypeInfo>
29
+ *
30
+ * namespace Post {
31
+ * export type Item = import('./types').Post
32
+ * export type TypeInfo = {
33
+ * key: 'Post'
34
+ * item: Item
35
+ * inputs: {
36
+ * create: import('./prisma-client/client').Prisma.PostCreateInput
37
+ * update: import('./prisma-client/client').Prisma.PostUpdateInput
38
+ * }
39
+ * }
40
+ * }
41
+ * }
42
+ * ```
43
+ */
44
+ export function generateListsNamespace(config) {
45
+ const lines = [];
46
+ // Add header comment
47
+ lines.push('/**');
48
+ lines.push(' * Generated Lists namespace from OpenSaas configuration');
49
+ lines.push(' * DO NOT EDIT - This file is automatically generated');
50
+ lines.push(' *');
51
+ lines.push(' * This file provides TypeInfo for each list, enabling strong typing');
52
+ lines.push(' * for hooks with Prisma input types.');
53
+ lines.push(' *');
54
+ lines.push(' * @example');
55
+ lines.push(' * ```typescript');
56
+ lines.push(" * import type { Lists } from './.opensaas/lists'");
57
+ lines.push(' *');
58
+ lines.push(' * // Use TypeInfo as generic parameter');
59
+ lines.push(' * Post: list<Lists.Post.TypeInfo>({');
60
+ lines.push(' * hooks: {');
61
+ lines.push(' * resolveInput: async ({ operation, resolvedData }) => {');
62
+ lines.push(' * // resolvedData is Prisma.PostCreateInput or Prisma.PostUpdateInput');
63
+ lines.push(' * return resolvedData');
64
+ lines.push(' * }');
65
+ lines.push(' * }');
66
+ lines.push(' * })');
67
+ lines.push(' *');
68
+ lines.push(' * // Or use as typed constant');
69
+ lines.push(' * const Post: Lists.Post = list({ ... })');
70
+ lines.push(' * ```');
71
+ lines.push(' */');
72
+ lines.push('');
73
+ // Start Lists namespace
74
+ lines.push('export declare namespace Lists {');
75
+ // Generate type for each list
76
+ for (const [listName, listConfig] of Object.entries(config.lists)) {
77
+ lines.push(` export type ${listName} = import('@opensaas/stack-core').ListConfig<Lists.${listName}.TypeInfo>`);
78
+ lines.push('');
79
+ lines.push(` namespace ${listName} {`);
80
+ lines.push(` export type Item = import('./types').${listName}`);
81
+ lines.push('');
82
+ // Generate Fields type
83
+ lines.push(` /**`);
84
+ lines.push(` * Field configurations for ${listName}`);
85
+ lines.push(` * Maps field names to their field config types`);
86
+ lines.push(` */`);
87
+ lines.push(` export type Fields = {`);
88
+ for (const [fieldName, fieldConfig] of Object.entries(listConfig.fields)) {
89
+ const fieldTypeName = getFieldTypeName(fieldConfig.type);
90
+ lines.push(` ${fieldName}: import('@opensaas/stack-core').${fieldTypeName}<Lists.${listName}.TypeInfo>`);
91
+ }
92
+ lines.push(` }`);
93
+ lines.push('');
94
+ // Generate TypeInfo with fields property
95
+ lines.push(` export type TypeInfo = {`);
96
+ lines.push(` key: '${listName}'`);
97
+ lines.push(` fields: Fields`);
98
+ lines.push(` item: Item`);
99
+ lines.push(` inputs: {`);
100
+ lines.push(` create: import('./prisma-client/client').Prisma.${listName}CreateInput`);
101
+ lines.push(` update: import('./prisma-client/client').Prisma.${listName}UpdateInput`);
102
+ lines.push(` }`);
103
+ lines.push(` }`);
104
+ lines.push(` }`);
105
+ lines.push('');
106
+ }
107
+ // Close Lists namespace
108
+ lines.push('}');
109
+ return lines.join('\n');
110
+ }
111
+ /**
112
+ * Write Lists namespace to file
113
+ */
114
+ export function writeLists(config, outputPath) {
115
+ const lists = generateListsNamespace(config);
116
+ // Ensure directory exists
117
+ const dir = path.dirname(outputPath);
118
+ if (!fs.existsSync(dir)) {
119
+ fs.mkdirSync(dir, { recursive: true });
120
+ }
121
+ fs.writeFileSync(outputPath, lists, 'utf-8');
122
+ }
123
+ //# sourceMappingURL=lists.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lists.js","sourceRoot":"","sources":["../../src/generator/lists.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ import type { OpenSaasConfig } from '@opensaas/stack-core';
2
+ /**
3
+ * Generate complete plugin types file
4
+ */
5
+ export declare function generatePluginTypes(config: OpenSaasConfig): string;
6
+ /**
7
+ * Write plugin types to file
8
+ */
9
+ export declare function writePluginTypes(config: OpenSaasConfig, outputPath: string): void;
10
+ //# sourceMappingURL=plugin-types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin-types.d.ts","sourceRoot":"","sources":["../../src/generator/plugin-types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAA;AA0G1D;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,cAAc,GAAG,MAAM,CAsBlE;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI,CAUjF"}
@@ -0,0 +1,122 @@
1
+ import * as fs from 'fs';
2
+ import * as path from 'path';
3
+ /**
4
+ * Generate TypeScript declaration for plugin data types
5
+ * Creates type-safe access to config._pluginData
6
+ */
7
+ function generatePluginDataInterface(config) {
8
+ const lines = [];
9
+ lines.push('/**');
10
+ lines.push(' * Plugin data storage types');
11
+ lines.push(' * Provides type-safe access to config._pluginData');
12
+ lines.push(' */');
13
+ lines.push('export interface PluginData {');
14
+ // Check if we have plugin data types to generate
15
+ if (config._pluginData && Object.keys(config._pluginData).length > 0) {
16
+ for (const pluginName of Object.keys(config._pluginData)) {
17
+ // Skip internal keys
18
+ if (pluginName.startsWith('__'))
19
+ continue;
20
+ // For each plugin, we'll add a Record<string, unknown> entry
21
+ // TODO: In the future, plugins could export their data types for proper typing
22
+ lines.push(` ${pluginName}?: Record<string, unknown>`);
23
+ }
24
+ }
25
+ lines.push('}');
26
+ return lines.join('\n');
27
+ }
28
+ /**
29
+ * Generate TypeScript declaration for plugin runtime services
30
+ * Creates type-safe access to context.plugins
31
+ */
32
+ function generatePluginServicesInterface(config) {
33
+ const lines = [];
34
+ const imports = [];
35
+ // Check if we have plugins with runtime functions
36
+ const pluginsWithRuntime = (config._plugins || config.plugins || []).filter((p) => p.runtime);
37
+ // Collect imports from plugins that provide runtime service types
38
+ if (pluginsWithRuntime.length > 0) {
39
+ for (const plugin of pluginsWithRuntime) {
40
+ if (plugin.runtimeServiceTypes) {
41
+ imports.push(plugin.runtimeServiceTypes.import);
42
+ }
43
+ }
44
+ }
45
+ // Add imports at the top if any exist
46
+ if (imports.length > 0) {
47
+ lines.push(...imports);
48
+ lines.push('');
49
+ }
50
+ lines.push('/**');
51
+ lines.push(' * Plugin runtime services');
52
+ lines.push(' * Provides type-safe access to context.plugins');
53
+ lines.push(' * Extends Record to allow compatibility with base AccessContext type');
54
+ lines.push(' */');
55
+ lines.push('export interface PluginServices extends Record<string, Record<string, any> | undefined> {');
56
+ if (pluginsWithRuntime.length > 0) {
57
+ for (const plugin of pluginsWithRuntime) {
58
+ if (plugin.runtimeServiceTypes) {
59
+ // Use typed runtime service from plugin
60
+ lines.push(` ${plugin.name}?: ${plugin.runtimeServiceTypes.typeName}`);
61
+ }
62
+ else {
63
+ // Fallback to Record<string, any> for plugins without type metadata
64
+ lines.push(` ${plugin.name}?: Record<string, any>`);
65
+ }
66
+ }
67
+ }
68
+ lines.push('}');
69
+ return lines.join('\n');
70
+ }
71
+ /**
72
+ * Generate module augmentation for OpenSaaS core types
73
+ * Note: We cannot augment _pluginData or plugins properties directly due to type constraints
74
+ * Instead, users should cast to PluginServices when accessing context.plugins
75
+ */
76
+ function generateModuleAugmentation() {
77
+ const lines = [];
78
+ lines.push('');
79
+ lines.push('/**');
80
+ lines.push(' * Declare this module to make interfaces available globally');
81
+ lines.push(' * Import this file to get typed plugin access');
82
+ lines.push(' */');
83
+ lines.push('declare global {');
84
+ lines.push(' // Plugin types are available as PluginServices interface');
85
+ lines.push('}');
86
+ return lines.join('\n');
87
+ }
88
+ /**
89
+ * Generate complete plugin types file
90
+ */
91
+ export function generatePluginTypes(config) {
92
+ const lines = [];
93
+ // Add header comment
94
+ lines.push('/**');
95
+ lines.push(' * Generated plugin types from OpenSaas configuration');
96
+ lines.push(' * DO NOT EDIT - This file is automatically generated');
97
+ lines.push(' *');
98
+ lines.push(' * This file provides type-safe access to:');
99
+ lines.push(' * - config._pluginData - Plugin configuration data');
100
+ lines.push(' * - context.plugins - Plugin runtime services');
101
+ lines.push(' */');
102
+ lines.push('');
103
+ // Generate interfaces
104
+ lines.push(generatePluginDataInterface(config));
105
+ lines.push(generatePluginServicesInterface(config));
106
+ // Generate module augmentation
107
+ lines.push(generateModuleAugmentation());
108
+ return lines.join('\n');
109
+ }
110
+ /**
111
+ * Write plugin types to file
112
+ */
113
+ export function writePluginTypes(config, outputPath) {
114
+ const pluginTypes = generatePluginTypes(config);
115
+ // Ensure directory exists
116
+ const dir = path.dirname(outputPath);
117
+ if (!fs.existsSync(dir)) {
118
+ fs.mkdirSync(dir, { recursive: true });
119
+ }
120
+ fs.writeFileSync(outputPath, pluginTypes, 'utf-8');
121
+ }
122
+ //# sourceMappingURL=plugin-types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin-types.js","sourceRoot":"","sources":["../../src/generator/plugin-types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ import type { OpenSaasConfig } from '@opensaas/stack-core';
2
+ /**
3
+ * Generate Prisma config file for CLI commands
4
+ *
5
+ * Prisma 7 requires a prisma.config.ts file at the project root for CLI commands
6
+ * like `prisma db push` and `prisma migrate dev`. This is separate from the
7
+ * runtime configuration (which uses adapters in opensaas.config.ts).
8
+ *
9
+ * The CLI config provides the database URL for schema operations, while the
10
+ * runtime config provides adapters for actual query execution.
11
+ */
12
+ export declare function generatePrismaConfig(_config: OpenSaasConfig): string;
13
+ /**
14
+ * Write Prisma config to file
15
+ */
16
+ export declare function writePrismaConfig(config: OpenSaasConfig, outputPath: string): void;
17
+ //# sourceMappingURL=prisma-config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prisma-config.d.ts","sourceRoot":"","sources":["../../src/generator/prisma-config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAA;AAI1D;;;;;;;;;GASG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,cAAc,GAAG,MAAM,CAgBpE;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI,CAUlF"}
@@ -0,0 +1,40 @@
1
+ import * as fs from 'fs';
2
+ import * as path from 'path';
3
+ /**
4
+ * Generate Prisma config file for CLI commands
5
+ *
6
+ * Prisma 7 requires a prisma.config.ts file at the project root for CLI commands
7
+ * like `prisma db push` and `prisma migrate dev`. This is separate from the
8
+ * runtime configuration (which uses adapters in opensaas.config.ts).
9
+ *
10
+ * The CLI config provides the database URL for schema operations, while the
11
+ * runtime config provides adapters for actual query execution.
12
+ */
13
+ export function generatePrismaConfig(_config) {
14
+ const lines = [];
15
+ // Import dotenv for environment variable loading
16
+ lines.push("import 'dotenv/config'");
17
+ lines.push("import { defineConfig, env } from 'prisma/config'");
18
+ lines.push('');
19
+ lines.push('export default defineConfig({');
20
+ lines.push(" schema: 'prisma/schema.prisma',");
21
+ lines.push(' datasource: {');
22
+ lines.push(" url: env('DATABASE_URL'),");
23
+ lines.push(' },');
24
+ lines.push('})');
25
+ lines.push('');
26
+ return lines.join('\n');
27
+ }
28
+ /**
29
+ * Write Prisma config to file
30
+ */
31
+ export function writePrismaConfig(config, outputPath) {
32
+ const prismaConfig = generatePrismaConfig(config);
33
+ // Ensure directory exists
34
+ const dir = path.dirname(outputPath);
35
+ if (!fs.existsSync(dir)) {
36
+ fs.mkdirSync(dir, { recursive: true });
37
+ }
38
+ fs.writeFileSync(outputPath, prismaConfig, 'utf-8');
39
+ }
40
+ //# sourceMappingURL=prisma-config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prisma-config.js","sourceRoot":"","sources":["../../src/generator/prisma-config.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,IAAI,CAAA;AACxB,OAAO,KAAK,IAAI,MAAM,MAAM,CAAA;AAE5B;;;;;;;;;GASG;AACH,MAAM,UAAU,oBAAoB,CAAC,OAAuB;IAC1D,MAAM,KAAK,GAAa,EAAE,CAAA;IAE1B,iDAAiD;IACjD,KAAK,CAAC,IAAI,CAAC,wBAAwB,CAAC,CAAA;IACpC,KAAK,CAAC,IAAI,CAAC,mDAAmD,CAAC,CAAA;IAC/D,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;IACd,KAAK,CAAC,IAAI,CAAC,+BAA+B,CAAC,CAAA;IAC3C,KAAK,CAAC,IAAI,CAAC,mCAAmC,CAAC,CAAA;IAC/C,KAAK,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAA;IAC7B,KAAK,CAAC,IAAI,CAAC,+BAA+B,CAAC,CAAA;IAC3C,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;IAClB,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IAChB,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;IAEd,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;AACzB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,iBAAiB,CAAC,MAAsB,EAAE,UAAkB;IAC1E,MAAM,YAAY,GAAG,oBAAoB,CAAC,MAAM,CAAC,CAAA;IAEjD,0BAA0B;IAC1B,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAA;IACpC,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QACxB,EAAE,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;IACxC,CAAC;IAED,EAAE,CAAC,aAAa,CAAC,UAAU,EAAE,YAAY,EAAE,OAAO,CAAC,CAAA;AACrD,CAAC"}