@objectql/cli 1.8.3 → 1.9.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 (94) hide show
  1. package/README.md +157 -1
  2. package/dist/commands/ai.js +4 -3
  3. package/dist/commands/ai.js.map +1 -1
  4. package/dist/commands/build.d.ts +12 -0
  5. package/dist/commands/build.js +119 -0
  6. package/dist/commands/build.js.map +1 -0
  7. package/dist/commands/database-push.d.ts +5 -0
  8. package/dist/commands/database-push.js +15 -0
  9. package/dist/commands/database-push.js.map +1 -0
  10. package/dist/commands/dev.d.ts +11 -0
  11. package/dist/commands/dev.js +111 -0
  12. package/dist/commands/dev.js.map +1 -0
  13. package/dist/commands/doctor.d.ts +4 -0
  14. package/dist/commands/doctor.js +37 -0
  15. package/dist/commands/doctor.js.map +1 -0
  16. package/dist/commands/format.d.ts +9 -0
  17. package/dist/commands/format.js +137 -0
  18. package/dist/commands/format.js.map +1 -0
  19. package/dist/commands/init.js +31 -30
  20. package/dist/commands/init.js.map +1 -1
  21. package/dist/commands/lint.d.ts +9 -0
  22. package/dist/commands/lint.js +120 -0
  23. package/dist/commands/lint.js.map +1 -0
  24. package/dist/commands/new.js +0 -52
  25. package/dist/commands/new.js.map +1 -1
  26. package/dist/commands/serve.d.ts +2 -0
  27. package/dist/commands/serve.js +122 -46
  28. package/dist/commands/serve.js.map +1 -1
  29. package/dist/commands/start.d.ts +12 -0
  30. package/dist/commands/start.js +134 -0
  31. package/dist/commands/start.js.map +1 -0
  32. package/dist/commands/test.d.ts +10 -0
  33. package/dist/commands/test.js +120 -0
  34. package/dist/commands/test.js.map +1 -0
  35. package/dist/index.js +189 -149
  36. package/dist/index.js.map +1 -1
  37. package/package.json +13 -8
  38. package/templates/hello-world/.vscode/extensions.json +7 -0
  39. package/templates/hello-world/CHANGELOG.md +41 -0
  40. package/templates/hello-world/README.md +29 -0
  41. package/templates/hello-world/package.json +24 -0
  42. package/templates/hello-world/src/index.ts +58 -0
  43. package/templates/hello-world/tsconfig.json +10 -0
  44. package/templates/starter/.vscode/extensions.json +7 -0
  45. package/{CHANGELOG.md → templates/starter/CHANGELOG.md} +47 -41
  46. package/templates/starter/README.md +17 -0
  47. package/templates/starter/__tests__/projects-hooks-actions.test.ts +490 -0
  48. package/templates/starter/jest.config.js +16 -0
  49. package/templates/starter/package.json +52 -0
  50. package/templates/starter/src/README.pages.md +110 -0
  51. package/templates/starter/src/demo.app.yml +4 -0
  52. package/templates/starter/src/i18n/zh-CN/projects.json +22 -0
  53. package/templates/starter/src/modules/kitchen-sink/kitchen_sink.data.yml +18 -0
  54. package/templates/starter/src/modules/kitchen-sink/kitchen_sink.object.yml +156 -0
  55. package/templates/starter/src/modules/projects/project_approval.workflow.yml +51 -0
  56. package/templates/starter/src/modules/projects/projects.action.ts +472 -0
  57. package/templates/starter/src/modules/projects/projects.data.yml +13 -0
  58. package/templates/starter/src/modules/projects/projects.hook.ts +339 -0
  59. package/templates/starter/src/modules/projects/projects.object.yml +148 -0
  60. package/templates/starter/src/modules/projects/projects.permission.yml +141 -0
  61. package/templates/starter/src/modules/projects/projects.validation.yml +37 -0
  62. package/templates/starter/src/modules/tasks/tasks.data.yml +23 -0
  63. package/templates/starter/src/modules/tasks/tasks.object.yml +34 -0
  64. package/templates/starter/src/modules/tasks/tasks.permission.yml +167 -0
  65. package/templates/starter/src/seed.ts +55 -0
  66. package/templates/starter/src/types/index.ts +3 -0
  67. package/templates/starter/src/types/kitchen_sink.ts +101 -0
  68. package/templates/starter/src/types/projects.ts +49 -0
  69. package/templates/starter/src/types/tasks.ts +33 -0
  70. package/templates/starter/tsconfig.json +11 -0
  71. package/templates/starter/tsconfig.tsbuildinfo +1 -0
  72. package/AI_EXAMPLES.md +0 -154
  73. package/AI_IMPLEMENTATION_SUMMARY.md +0 -509
  74. package/AI_TUTORIAL.md +0 -144
  75. package/IMPLEMENTATION_SUMMARY.md +0 -437
  76. package/USAGE_EXAMPLES.md +0 -951
  77. package/__tests__/commands.test.ts +0 -316
  78. package/dist/commands/studio.d.ts +0 -5
  79. package/dist/commands/studio.js +0 -364
  80. package/dist/commands/studio.js.map +0 -1
  81. package/jest.config.js +0 -19
  82. package/src/commands/ai.ts +0 -508
  83. package/src/commands/generate.ts +0 -135
  84. package/src/commands/i18n.ts +0 -303
  85. package/src/commands/init.ts +0 -191
  86. package/src/commands/migrate.ts +0 -314
  87. package/src/commands/new.ts +0 -273
  88. package/src/commands/repl.ts +0 -120
  89. package/src/commands/serve.ts +0 -96
  90. package/src/commands/studio.ts +0 -354
  91. package/src/commands/sync.ts +0 -328
  92. package/src/index.ts +0 -274
  93. package/tsconfig.json +0 -15
  94. package/tsconfig.tsbuildinfo +0 -1
@@ -1,328 +0,0 @@
1
- import * as fs from 'fs';
2
- import * as path from 'path';
3
- import chalk from 'chalk';
4
- import * as yaml from 'js-yaml';
5
- import { IntrospectedSchema, IntrospectedTable, IntrospectedColumn, ObjectConfig, IObjectQL, FieldConfig, FieldType } from '@objectql/types';
6
-
7
- interface SyncOptions {
8
- config?: string;
9
- output?: string;
10
- tables?: string[];
11
- force?: boolean;
12
- app?: IObjectQL; // Allow passing app instance directly for testing
13
- }
14
-
15
- /**
16
- * Sync database schema to ObjectQL .object.yml files
17
- * Introspects existing SQL database and generates object definitions
18
- */
19
- export async function syncDatabase(options: SyncOptions) {
20
- const outputDir = path.resolve(process.cwd(), options.output || './src/objects');
21
-
22
- console.log(chalk.blue('🔄 Syncing database schema to ObjectQL...'));
23
- console.log(chalk.gray(`Output directory: ${outputDir}\n`));
24
-
25
- let app: IObjectQL | undefined = options.app;
26
- const shouldClose = !options.app; // Only close if we loaded it ourselves
27
-
28
- try {
29
- // Load ObjectQL instance from config if not provided
30
- if (!app) {
31
- app = await loadObjectQLInstance(options.config);
32
- }
33
-
34
- // Check if driver supports introspection
35
- const driver = app.datasource('default');
36
- if (!driver || !driver.introspectSchema) {
37
- const errorMsg = 'The configured driver does not support schema introspection. Only SQL drivers (PostgreSQL, MySQL, SQLite) support this feature.';
38
- console.error(chalk.red(`❌ ${errorMsg}`));
39
- throw new Error(errorMsg);
40
- }
41
-
42
- // Introspect database schema
43
- console.log(chalk.blue('📊 Introspecting database schema...'));
44
- const schema: IntrospectedSchema = await driver.introspectSchema();
45
-
46
- const tableNames = Object.keys(schema.tables);
47
- if (tableNames.length === 0) {
48
- console.log(chalk.yellow('⚠ No tables found in database'));
49
- return;
50
- }
51
-
52
- console.log(chalk.green(`✓ Found ${tableNames.length} table(s)\n`));
53
-
54
- // Filter tables if specified
55
- let tablesToSync = tableNames;
56
- if (options.tables && options.tables.length > 0) {
57
- tablesToSync = tableNames.filter(t => options.tables!.includes(t));
58
- if (tablesToSync.length === 0) {
59
- console.log(chalk.yellow('⚠ No matching tables found'));
60
- return;
61
- }
62
- }
63
-
64
- // Create output directory if it doesn't exist
65
- if (!fs.existsSync(outputDir)) {
66
- fs.mkdirSync(outputDir, { recursive: true });
67
- console.log(chalk.gray(`Created directory: ${outputDir}\n`));
68
- }
69
-
70
- // Generate .object.yml files
71
- let createdCount = 0;
72
- let skippedCount = 0;
73
-
74
- for (const tableName of tablesToSync) {
75
- const table = schema.tables[tableName];
76
- const filename = `${tableName}.object.yml`;
77
- const filePath = path.join(outputDir, filename);
78
-
79
- // Check if file already exists
80
- if (fs.existsSync(filePath) && !options.force) {
81
- console.log(chalk.yellow(`⊘ ${tableName} (file exists, use --force to overwrite)`));
82
- skippedCount++;
83
- continue;
84
- }
85
-
86
- // Generate object definition
87
- const objectDef = generateObjectDefinition(table, schema);
88
-
89
- // Write to file
90
- const yamlContent = yaml.dump(objectDef, {
91
- indent: 2,
92
- lineWidth: -1,
93
- noRefs: true,
94
- sortKeys: false
95
- });
96
-
97
- fs.writeFileSync(filePath, yamlContent, 'utf-8');
98
-
99
- console.log(chalk.green(`✓ ${tableName} → ${filename}`));
100
- createdCount++;
101
- }
102
-
103
- console.log(chalk.blue('\n📊 Summary:'));
104
- console.log(chalk.gray(`Total tables: ${tablesToSync.length}`));
105
- console.log(chalk.gray(`Created: ${createdCount}`));
106
- console.log(chalk.gray(`Skipped: ${skippedCount}`));
107
-
108
- if (createdCount > 0) {
109
- console.log(chalk.green(`\n✅ Successfully synced ${createdCount} table(s) to ${outputDir}`));
110
- }
111
-
112
- } catch (error: any) {
113
- console.error(chalk.red(`❌ Sync failed: ${error.message}`));
114
- if (error.stack) {
115
- console.error(chalk.gray(error.stack));
116
- }
117
- throw error;
118
- } finally {
119
- // Ensure connection is closed if we opened it
120
- if (shouldClose && app) {
121
- if (app.close) {
122
- await app.close();
123
- } else {
124
- // Fallback for older versions if close isn't available
125
- const driver = app.datasource('default');
126
- if (driver && (driver as any).disconnect) {
127
- await (driver as any).disconnect();
128
- }
129
- }
130
- }
131
- }
132
- }
133
-
134
- /**
135
- * Generate ObjectQL object definition from introspected table
136
- */
137
- function generateObjectDefinition(table: IntrospectedTable, schema: IntrospectedSchema): ObjectConfig {
138
- const obj: ObjectConfig = {
139
- name: table.name,
140
- label: formatLabel(table.name),
141
- fields: {}
142
- };
143
-
144
- // Process each column
145
- for (const column of table.columns) {
146
- // Skip system fields (id, created_at, updated_at) - they're automatic
147
- if (['id', 'created_at', 'updated_at'].includes(column.name)) {
148
- continue;
149
- }
150
-
151
- const field: Partial<FieldConfig> = {};
152
-
153
- // Check if this is a foreign key
154
- const fk = table.foreignKeys.find(fk => fk.columnName === column.name);
155
- if (fk) {
156
- // This is a lookup/relationship field
157
- field.type = 'lookup';
158
- field.reference_to = fk.referencedTable;
159
-
160
- // Add label
161
- field.label = formatLabel(column.name);
162
-
163
- // Add required constraint
164
- if (!column.nullable) {
165
- field.required = true;
166
- }
167
- } else {
168
- // Regular field - map SQL type to ObjectQL type
169
- const fieldType = mapSqlTypeToObjectQL(column.type, column);
170
- field.type = fieldType;
171
-
172
- // Add label
173
- field.label = formatLabel(column.name);
174
-
175
- // Add constraints
176
- if (!column.nullable) {
177
- field.required = true;
178
- }
179
-
180
- if (column.isUnique) {
181
- field.unique = true;
182
- }
183
-
184
- // Add max_length for text-based fields
185
- if (column.maxLength && (fieldType === 'text' || fieldType === 'textarea')) {
186
- field.max_length = column.maxLength;
187
- }
188
-
189
- if (column.defaultValue !== undefined && column.defaultValue !== null) {
190
- // Only include simple default values
191
- if (typeof column.defaultValue === 'string' ||
192
- typeof column.defaultValue === 'number' ||
193
- typeof column.defaultValue === 'boolean') {
194
- field.defaultValue = column.defaultValue;
195
- }
196
- }
197
- }
198
-
199
- obj.fields[column.name] = field as FieldConfig;
200
- }
201
-
202
- return obj;
203
- }
204
-
205
- /**
206
- * Map SQL native type to ObjectQL field type
207
- */
208
- function mapSqlTypeToObjectQL(sqlType: string, column: IntrospectedColumn): FieldType {
209
- const type = sqlType.toLowerCase();
210
-
211
- // Integer types - map to 'number'
212
- if (type.includes('int') || type.includes('serial') || type.includes('bigserial')) {
213
- return 'number';
214
- }
215
-
216
- // Float/Decimal types
217
- if (type.includes('float') || type.includes('double') ||
218
- type.includes('decimal') || type.includes('numeric') || type.includes('real')) {
219
- return 'number';
220
- }
221
-
222
- // Boolean
223
- if (type.includes('bool') || type === 'bit') {
224
- return 'boolean';
225
- }
226
-
227
- // Date/Time types
228
- if (type.includes('timestamp') || type.includes('datetime')) {
229
- return 'datetime';
230
- }
231
- if (type === 'date') {
232
- return 'date';
233
- }
234
- if (type === 'time') {
235
- return 'time';
236
- }
237
-
238
- // Text types
239
- if (type.includes('text') || type.includes('clob') || type.includes('long')) {
240
- return 'textarea';
241
- }
242
-
243
- // JSON types - map to 'object'
244
- if (type.includes('json') || type.includes('jsonb')) {
245
- return 'object';
246
- }
247
-
248
- // Binary/Blob types
249
- if (type.includes('blob') || type.includes('binary') || type.includes('bytea')) {
250
- return 'file';
251
- }
252
-
253
- // String types (varchar, char, etc.)
254
- // Default to 'text' for general string fields
255
- return 'text';
256
- }
257
-
258
- /**
259
- * Format table/column name to human-readable label
260
- * e.g., "user_profile" -> "User Profile"
261
- */
262
- function formatLabel(name: string): string {
263
- return name
264
- .split('_')
265
- .map(word => word.charAt(0).toUpperCase() + word.slice(1))
266
- .join(' ');
267
- }
268
-
269
- /**
270
- * Load ObjectQL instance from config file
271
- */
272
- async function loadObjectQLInstance(configPath?: string): Promise<IObjectQL> {
273
- const cwd = process.cwd();
274
-
275
- // Try to load from config file
276
- let configFile = configPath;
277
- if (!configFile) {
278
- const potentialFiles = ['objectql.config.ts', 'objectql.config.js'];
279
- for (const file of potentialFiles) {
280
- if (fs.existsSync(path.join(cwd, file))) {
281
- configFile = path.join(cwd, file);
282
- break;
283
- }
284
- }
285
- } else if (!path.isAbsolute(configFile)) {
286
- // If configPath is provided but relative, make it absolute
287
- configFile = path.join(cwd, configFile);
288
- }
289
-
290
- if (!configFile) {
291
- throw new Error('No configuration file found (objectql.config.ts/js). Please create one with database connection.');
292
- }
293
-
294
- // Register ts-node for TypeScript support
295
- if (configFile.endsWith('.ts')) {
296
- try {
297
- require('ts-node').register({
298
- transpileOnly: true,
299
- compilerOptions: {
300
- module: 'commonjs'
301
- }
302
- });
303
- } catch (err) {
304
- throw new Error('TypeScript config file detected but ts-node is not installed. Please run: npm install --save-dev ts-node');
305
- }
306
- }
307
-
308
- const configModule = require(configFile);
309
-
310
- // Clear cache to support multiple runs in same process (e.g. tests)
311
- try {
312
- const resolvedPath = require.resolve(configFile);
313
- delete require.cache[resolvedPath];
314
- } catch (e) {
315
- // Ignore resolution errors
316
- }
317
-
318
- // Support multiple export patterns: default, app, objectql, or db (in order of precedence)
319
- const app = configModule.default || configModule.app || configModule.objectql || configModule.db;
320
-
321
- if (!app) {
322
- throw new Error('Config file must export an ObjectQL instance as default export or named export (app/objectql/db)');
323
- }
324
-
325
- // Initialize app (but don't sync schema - we're reading it)
326
- await app.init();
327
- return app;
328
- }
package/src/index.ts DELETED
@@ -1,274 +0,0 @@
1
- import { Command } from 'commander';
2
- import { generateTypes } from './commands/generate';
3
- import { startRepl } from './commands/repl';
4
- import { serve } from './commands/serve';
5
- import { startStudio } from './commands/studio';
6
- import { initProject } from './commands/init';
7
- import { newMetadata } from './commands/new';
8
- import { i18nExtract, i18nInit, i18nValidate } from './commands/i18n';
9
- import { migrate, migrateCreate, migrateStatus } from './commands/migrate';
10
- import { aiGenerate, aiValidate, aiChat, aiConversational } from './commands/ai';
11
- import { syncDatabase } from './commands/sync';
12
-
13
- const program = new Command();
14
-
15
- program
16
- .name('objectql')
17
- .description('ObjectQL CLI tool')
18
- .version('1.5.0');
19
-
20
- // Init command - Create new project
21
- program
22
- .command('init')
23
- .description('Create a new ObjectQL project from template')
24
- .option('-t, --template <template>', 'Template to use (basic, express-api, enterprise)', 'basic')
25
- .option('-n, --name <name>', 'Project name')
26
- .option('-d, --dir <path>', 'Target directory')
27
- .option('--skip-install', 'Skip dependency installation')
28
- .option('--skip-git', 'Skip git initialization')
29
- .action(async (options) => {
30
- try {
31
- await initProject(options);
32
- } catch (error) {
33
- console.error(error);
34
- process.exit(1);
35
- }
36
- });
37
-
38
- // New command - Generate metadata files
39
- program
40
- .command('new <type> <name>')
41
- .description('Generate a new metadata file (object, view, form, etc.)')
42
- .option('-d, --dir <path>', 'Output directory', '.')
43
- .action(async (type, name, options) => {
44
- try {
45
- await newMetadata({ type, name, dir: options.dir });
46
- } catch (error) {
47
- console.error(error);
48
- process.exit(1);
49
- }
50
- });
51
-
52
- // Generate command - Generate TypeScript types
53
- program
54
- .command('generate')
55
- .alias('g')
56
- .description('Generate TypeScript interfaces from ObjectQL schema files')
57
- .option('-s, --source <path>', 'Source directory containing *.object.yml', '.')
58
- .option('-o, --output <path>', 'Output directory for generated types', './src/generated')
59
- .action(async (options) => {
60
- try {
61
- await generateTypes(options.source, options.output);
62
- } catch (error) {
63
- console.error(error);
64
- process.exit(1);
65
- }
66
- });
67
-
68
- // I18n commands
69
- const i18nCmd = program
70
- .command('i18n')
71
- .description('Internationalization commands');
72
-
73
- i18nCmd
74
- .command('extract')
75
- .description('Extract translatable strings from metadata files')
76
- .option('-s, --source <path>', 'Source directory', '.')
77
- .option('-o, --output <path>', 'Output directory', './src/i18n')
78
- .option('-l, --lang <lang>', 'Language code', 'en')
79
- .action(async (options) => {
80
- try {
81
- await i18nExtract(options);
82
- } catch (error) {
83
- console.error(error);
84
- process.exit(1);
85
- }
86
- });
87
-
88
- i18nCmd
89
- .command('init <lang>')
90
- .description('Initialize i18n for a new language')
91
- .option('-b, --base-dir <path>', 'Base i18n directory', './src/i18n')
92
- .action(async (lang, options) => {
93
- try {
94
- await i18nInit({ lang, baseDir: options.baseDir });
95
- } catch (error) {
96
- console.error(error);
97
- process.exit(1);
98
- }
99
- });
100
-
101
- i18nCmd
102
- .command('validate <lang>')
103
- .description('Validate translation completeness')
104
- .option('-b, --base-dir <path>', 'Base i18n directory', './src/i18n')
105
- .option('--base-lang <lang>', 'Base language to compare against', 'en')
106
- .action(async (lang, options) => {
107
- try {
108
- await i18nValidate({ lang, baseDir: options.baseDir, baseLang: options.baseLang });
109
- } catch (error) {
110
- console.error(error);
111
- process.exit(1);
112
- }
113
- });
114
-
115
- // Migration commands
116
- const migrateCmd = program
117
- .command('migrate')
118
- .description('Run pending database migrations')
119
- .option('-c, --config <path>', 'Path to objectql.config.ts/js')
120
- .option('-d, --dir <path>', 'Migrations directory', './migrations')
121
- .action(async (options) => {
122
- try {
123
- await migrate(options);
124
- } catch (error) {
125
- console.error(error);
126
- process.exit(1);
127
- }
128
- });
129
-
130
- migrateCmd
131
- .command('create <name>')
132
- .description('Create a new migration file')
133
- .option('-d, --dir <path>', 'Migrations directory', './migrations')
134
- .action(async (name, options) => {
135
- try {
136
- await migrateCreate({ name, dir: options.dir });
137
- } catch (error) {
138
- console.error(error);
139
- process.exit(1);
140
- }
141
- });
142
-
143
- migrateCmd
144
- .command('status')
145
- .description('Show migration status')
146
- .option('-c, --config <path>', 'Path to objectql.config.ts/js')
147
- .option('-d, --dir <path>', 'Migrations directory', './migrations')
148
- .action(async (options) => {
149
- try {
150
- await migrateStatus(options);
151
- } catch (error) {
152
- console.error(error);
153
- process.exit(1);
154
- }
155
- });
156
-
157
- // Sync command - Introspect database and generate .object.yml files
158
- program
159
- .command('sync')
160
- .description('Sync database schema to ObjectQL object definitions')
161
- .option('-c, --config <path>', 'Path to objectql.config.ts/js')
162
- .option('-o, --output <path>', 'Output directory for .object.yml files', './src/objects')
163
- .option('-t, --tables <tables...>', 'Specific tables to sync (default: all)')
164
- .option('-f, --force', 'Overwrite existing files')
165
- .action(async (options) => {
166
- try {
167
- await syncDatabase(options);
168
- } catch (error) {
169
- console.error(error);
170
- process.exit(1);
171
- }
172
- });
173
-
174
- // REPL command
175
- program
176
- .command('repl')
177
- .alias('r')
178
- .description('Start an interactive shell (REPL) to query the database')
179
- .option('-c, --config <path>', 'Path to objectql.config.ts/js')
180
- .action(async (options) => {
181
- await startRepl(options.config);
182
- });
183
-
184
- // Serve command
185
- program
186
- .command('serve')
187
- .alias('s')
188
- .description('Start a development server')
189
- .option('-p, --port <number>', 'Port to listen on', '3000')
190
- .option('-d, --dir <path>', 'Directory containing schema', '.')
191
- .action(async (options) => {
192
- await serve({ port: parseInt(options.port), dir: options.dir });
193
- });
194
-
195
- // Studio command
196
- program
197
- .command('studio')
198
- .alias('ui')
199
- .description('Start the ObjectQL Studio')
200
- .option('-p, --port <number>', 'Port to listen on', '5555')
201
- .option('-d, --dir <path>', 'Directory containing schema', '.')
202
- .option('--no-open', 'Do not open browser automatically')
203
- .action(async (options) => {
204
- await startStudio({
205
- port: parseInt(options.port),
206
- dir: options.dir,
207
- open: options.open
208
- });
209
- });
210
-
211
- // AI command - Interactive by default, with specific subcommands for other modes
212
- const aiCmd = program
213
- .command('ai')
214
- .description('AI-powered interactive application builder (starts conversational mode by default)');
215
-
216
- // Default action: Interactive conversational mode
217
- aiCmd
218
- .argument('[output-dir]', 'Output directory for generated files', './src')
219
- .action(async (outputDir) => {
220
- try {
221
- await aiConversational({ output: outputDir });
222
- } catch (error) {
223
- console.error(error);
224
- process.exit(1);
225
- }
226
- });
227
-
228
- // Subcommand: Generate (one-shot generation)
229
- aiCmd
230
- .command('generate')
231
- .description('Generate application from description (one-shot, non-interactive)')
232
- .requiredOption('-d, --description <text>', 'Application description')
233
- .option('-o, --output <path>', 'Output directory', './src')
234
- .option('-t, --type <type>', 'Generation type: basic, complete, or custom', 'custom')
235
- .action(async (options) => {
236
- try {
237
- await aiGenerate(options);
238
- } catch (error) {
239
- console.error(error);
240
- process.exit(1);
241
- }
242
- });
243
-
244
- // Subcommand: Validate
245
- aiCmd
246
- .command('validate')
247
- .description('Validate metadata files with AI analysis')
248
- .argument('<path>', 'Path to metadata files directory')
249
- .option('--fix', 'Automatically fix issues')
250
- .option('-v, --verbose', 'Detailed output')
251
- .action(async (pathArg, options) => {
252
- try {
253
- await aiValidate({ path: pathArg, ...options });
254
- } catch (error) {
255
- console.error(error);
256
- process.exit(1);
257
- }
258
- });
259
-
260
- // Subcommand: Chat
261
- aiCmd
262
- .command('chat')
263
- .description('AI assistant for questions and guidance')
264
- .option('-p, --prompt <text>', 'Initial prompt')
265
- .action(async (options) => {
266
- try {
267
- await aiChat({ initialPrompt: options.prompt });
268
- } catch (error) {
269
- console.error(error);
270
- process.exit(1);
271
- }
272
- });
273
-
274
- program.parse();
package/tsconfig.json DELETED
@@ -1,15 +0,0 @@
1
- {
2
- "extends": "../../../tsconfig.base.json",
3
- "compilerOptions": {
4
- "outDir": "dist",
5
- "rootDir": "src"
6
- },
7
- "include": ["src"],
8
- "references": [
9
- { "path": "../../foundation/types" },
10
- { "path": "../../foundation/core" },
11
- { "path": "../../runtime/server" },
12
- { "path": "../../foundation/platform-node" },
13
- { "path": "../../drivers/sql" }
14
- ]
15
- }