db-model-router 1.0.19 → 1.0.20
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/dbmr.schema.mysql.json +360 -0
- package/package.json +3 -1
- package/scripts/demo-create.js +11 -5
- package/src/cli/commands/generate.js +18 -9
- package/src/cli/commands/init.js +8 -4
|
@@ -0,0 +1,360 @@
|
|
|
1
|
+
{
|
|
2
|
+
"adapter": "mysql",
|
|
3
|
+
"framework": "express",
|
|
4
|
+
"options": {
|
|
5
|
+
"session": "memory",
|
|
6
|
+
"rateLimiting": true,
|
|
7
|
+
"helmet": true,
|
|
8
|
+
"logger": true,
|
|
9
|
+
"loki": false,
|
|
10
|
+
"saasStructure": false,
|
|
11
|
+
"apiBasePath": "/api",
|
|
12
|
+
"output": "backend",
|
|
13
|
+
"port": 6000
|
|
14
|
+
},
|
|
15
|
+
"tables": {
|
|
16
|
+
"languages": {
|
|
17
|
+
"columns": {
|
|
18
|
+
"language_id": "auto_increment",
|
|
19
|
+
"name": "required|string|maxLength:100",
|
|
20
|
+
"slug": "required|string|regex:^[a-z0-9-]+$|maxLength:100",
|
|
21
|
+
"file_extension": "required|string|maxLength:20",
|
|
22
|
+
"runtime_family": "string|maxLength:50",
|
|
23
|
+
"package_registry": "string|maxLength:50",
|
|
24
|
+
"is_active": "boolean",
|
|
25
|
+
"created_at": "datetime"
|
|
26
|
+
},
|
|
27
|
+
"pk": "language_id",
|
|
28
|
+
"unique": ["slug"],
|
|
29
|
+
"timestamps": {
|
|
30
|
+
"created_at": "created_at"
|
|
31
|
+
},
|
|
32
|
+
"parent": null
|
|
33
|
+
},
|
|
34
|
+
|
|
35
|
+
"frameworks": {
|
|
36
|
+
"columns": {
|
|
37
|
+
"framework_id": "auto_increment",
|
|
38
|
+
"language_id": "required|integer:unsigned",
|
|
39
|
+
"name": "required|string|maxLength:150",
|
|
40
|
+
"slug": "required|string|regex:^[a-z0-9-]+$|maxLength:150",
|
|
41
|
+
"package_name": "string|maxLength:150",
|
|
42
|
+
"homepage_url": "string|maxLength:500",
|
|
43
|
+
"latest_version": "string|maxLength:50",
|
|
44
|
+
"weekly_downloads": "integer:unsigned",
|
|
45
|
+
"popularity_index": "numeric:decimal(5,2)",
|
|
46
|
+
"popularity_updated_at": "datetime",
|
|
47
|
+
"created_at": "datetime"
|
|
48
|
+
},
|
|
49
|
+
"pk": "framework_id",
|
|
50
|
+
"unique": ["slug"],
|
|
51
|
+
"search_columns": ["name", "package_name"],
|
|
52
|
+
"timestamps": {
|
|
53
|
+
"created_at": "created_at"
|
|
54
|
+
},
|
|
55
|
+
"parent": null
|
|
56
|
+
},
|
|
57
|
+
|
|
58
|
+
"libraries": {
|
|
59
|
+
"columns": {
|
|
60
|
+
"library_id": "auto_increment",
|
|
61
|
+
"language_id": "required|integer:unsigned",
|
|
62
|
+
"framework_id": "integer:unsigned",
|
|
63
|
+
"name": "required|string|maxLength:150",
|
|
64
|
+
"slug": "required|string|regex:^[a-z0-9-]+$|maxLength:150",
|
|
65
|
+
"package_name": "string|maxLength:150",
|
|
66
|
+
"homepage_url": "string|maxLength:500",
|
|
67
|
+
"latest_version": "string|maxLength:50",
|
|
68
|
+
"weekly_downloads": "integer:unsigned",
|
|
69
|
+
"popularity_index": "numeric:decimal(5,2)",
|
|
70
|
+
"popularity_updated_at": "datetime",
|
|
71
|
+
"created_at": "datetime"
|
|
72
|
+
},
|
|
73
|
+
"pk": "library_id",
|
|
74
|
+
"unique": ["slug"],
|
|
75
|
+
"search_columns": ["name", "package_name"],
|
|
76
|
+
"timestamps": {
|
|
77
|
+
"created_at": "created_at"
|
|
78
|
+
},
|
|
79
|
+
"parent": null
|
|
80
|
+
},
|
|
81
|
+
|
|
82
|
+
"tasks": {
|
|
83
|
+
"columns": {
|
|
84
|
+
"task_id": "auto_increment",
|
|
85
|
+
"name": "required|string|maxLength:150",
|
|
86
|
+
"slug": "required|string|regex:^[a-z0-9-]+$|maxLength:150",
|
|
87
|
+
"category": "required|string|in:auth,storage,networking,data-processing,messaging,payments,caching,middleware,ai-integration,database,validation,integration,utility",
|
|
88
|
+
"description": "string:text",
|
|
89
|
+
"created_at": "datetime"
|
|
90
|
+
},
|
|
91
|
+
"pk": "task_id",
|
|
92
|
+
"unique": ["slug"],
|
|
93
|
+
"search_columns": ["name", "description"],
|
|
94
|
+
"timestamps": {
|
|
95
|
+
"created_at": "created_at"
|
|
96
|
+
},
|
|
97
|
+
"parent": null
|
|
98
|
+
},
|
|
99
|
+
|
|
100
|
+
"tags": {
|
|
101
|
+
"columns": {
|
|
102
|
+
"tag_id": "auto_increment",
|
|
103
|
+
"name": "required|string|maxLength:100",
|
|
104
|
+
"slug": "required|string|regex:^[a-z0-9-]+$|maxLength:100"
|
|
105
|
+
},
|
|
106
|
+
"pk": "tag_id",
|
|
107
|
+
"unique": [["name"], ["slug"]],
|
|
108
|
+
"parent": null
|
|
109
|
+
},
|
|
110
|
+
|
|
111
|
+
"popularity_snapshots": {
|
|
112
|
+
"columns": {
|
|
113
|
+
"snapshot_id": "auto_increment",
|
|
114
|
+
"entity_type": "required|string|in:framework,library",
|
|
115
|
+
"entity_id": "required|integer:unsigned",
|
|
116
|
+
"weekly_downloads": "required|integer:unsigned",
|
|
117
|
+
"source": "string|maxLength:50",
|
|
118
|
+
"snapshot_date": "required|datetime"
|
|
119
|
+
},
|
|
120
|
+
"pk": "snapshot_id",
|
|
121
|
+
"parent": null
|
|
122
|
+
},
|
|
123
|
+
|
|
124
|
+
"sandbox_images": {
|
|
125
|
+
"columns": {
|
|
126
|
+
"image_id": "auto_increment",
|
|
127
|
+
"language_id": "required|integer:unsigned",
|
|
128
|
+
"image_name": "required|string|maxLength:255",
|
|
129
|
+
"os_base": "string|maxLength:100",
|
|
130
|
+
"installed_toolchain": "string:text",
|
|
131
|
+
"is_active": "boolean",
|
|
132
|
+
"created_at": "datetime"
|
|
133
|
+
},
|
|
134
|
+
"pk": "image_id",
|
|
135
|
+
"unique": ["image_name"],
|
|
136
|
+
"timestamps": {
|
|
137
|
+
"created_at": "created_at"
|
|
138
|
+
},
|
|
139
|
+
"parent": null
|
|
140
|
+
},
|
|
141
|
+
|
|
142
|
+
"snippets": {
|
|
143
|
+
"columns": {
|
|
144
|
+
"snippet_id": "required|string:uuid",
|
|
145
|
+
"title": "required|string|maxLength:255",
|
|
146
|
+
"description": "string:text",
|
|
147
|
+
"usecase": "string:text",
|
|
148
|
+
"task_id": "required|integer:unsigned",
|
|
149
|
+
"language_id": "required|integer:unsigned",
|
|
150
|
+
"framework_id": "integer:unsigned",
|
|
151
|
+
"status": "required|string|in:draft,in_verification,verified,failed,deprecated",
|
|
152
|
+
"current_stage": "required|string|in:execution,lint,static_analysis,security_scan,performance,published",
|
|
153
|
+
"verified": "boolean",
|
|
154
|
+
"quality_score": "numeric:decimal(5,2)",
|
|
155
|
+
"source": "required|string|in:ai-generated,human-curated,imported",
|
|
156
|
+
"generation_provider": "string|maxLength:64",
|
|
157
|
+
"generation_model": "string|maxLength:128",
|
|
158
|
+
"enrichment_model": "string|maxLength:128",
|
|
159
|
+
"usage_count": "integer:unsigned",
|
|
160
|
+
"last_tested_at": "datetime",
|
|
161
|
+
"created_at": "datetime",
|
|
162
|
+
"modified_at": "datetime"
|
|
163
|
+
},
|
|
164
|
+
"pk": "snippet_id",
|
|
165
|
+
"search_columns": ["title", "description", "usecase"],
|
|
166
|
+
"timestamps": {
|
|
167
|
+
"created_at": "created_at",
|
|
168
|
+
"modified_at": "modified_at"
|
|
169
|
+
},
|
|
170
|
+
"parent": null
|
|
171
|
+
},
|
|
172
|
+
|
|
173
|
+
"snippet_files": {
|
|
174
|
+
"columns": {
|
|
175
|
+
"file_id": "auto_increment",
|
|
176
|
+
"snippet_id": "required|string:uuid",
|
|
177
|
+
"file_role": "required|string|in:code,test,dependency,readme",
|
|
178
|
+
"file_name": "required|string|maxLength:255",
|
|
179
|
+
"content": "required|string:longtext",
|
|
180
|
+
"sort_order": "integer:unsigned",
|
|
181
|
+
"created_at": "datetime",
|
|
182
|
+
"modified_at": "datetime"
|
|
183
|
+
},
|
|
184
|
+
"pk": "file_id",
|
|
185
|
+
"timestamps": {
|
|
186
|
+
"created_at": "created_at",
|
|
187
|
+
"modified_at": "modified_at"
|
|
188
|
+
},
|
|
189
|
+
"parent": "snippets"
|
|
190
|
+
},
|
|
191
|
+
|
|
192
|
+
"snippet_dependencies": {
|
|
193
|
+
"columns": {
|
|
194
|
+
"dependency_id": "auto_increment",
|
|
195
|
+
"snippet_id": "required|string:uuid",
|
|
196
|
+
"library_id": "required|integer:unsigned",
|
|
197
|
+
"version_constraint": "string|maxLength:50",
|
|
198
|
+
"is_primary": "boolean",
|
|
199
|
+
"created_at": "datetime"
|
|
200
|
+
},
|
|
201
|
+
"pk": "dependency_id",
|
|
202
|
+
"unique": [["snippet_id", "library_id"]],
|
|
203
|
+
"timestamps": {
|
|
204
|
+
"created_at": "created_at"
|
|
205
|
+
},
|
|
206
|
+
"parent": "snippets"
|
|
207
|
+
},
|
|
208
|
+
|
|
209
|
+
"snippet_tags": {
|
|
210
|
+
"columns": {
|
|
211
|
+
"snippet_id": "required|string:uuid",
|
|
212
|
+
"tag_id": "required|integer:unsigned"
|
|
213
|
+
},
|
|
214
|
+
"pk": "snippet_id",
|
|
215
|
+
"unique": [["snippet_id", "tag_id"]],
|
|
216
|
+
"parent": "snippets"
|
|
217
|
+
},
|
|
218
|
+
|
|
219
|
+
"testing_logs": {
|
|
220
|
+
"columns": {
|
|
221
|
+
"testing_id": "auto_increment",
|
|
222
|
+
"snippet_id": "required|string:uuid",
|
|
223
|
+
"queue_id": "integer:bigint",
|
|
224
|
+
"language_id": "required|integer:unsigned",
|
|
225
|
+
"framework_id": "integer:unsigned",
|
|
226
|
+
"code_snapshot": "required|string:longtext",
|
|
227
|
+
"test_snapshot": "required|string:longtext",
|
|
228
|
+
"dependency_snapshot": "required|string:longtext",
|
|
229
|
+
"result": "required|string|in:pass,fail,error,timeout",
|
|
230
|
+
"exit_code": "integer",
|
|
231
|
+
"stdout": "string:longtext",
|
|
232
|
+
"stderr": "string:longtext",
|
|
233
|
+
"response_time_ms": "integer",
|
|
234
|
+
"sandbox_image": "string|maxLength:128",
|
|
235
|
+
"tested_at": "datetime"
|
|
236
|
+
},
|
|
237
|
+
"pk": "testing_id",
|
|
238
|
+
"timestamps": {
|
|
239
|
+
"tested_at": "tested_at"
|
|
240
|
+
},
|
|
241
|
+
"parent": "snippets"
|
|
242
|
+
},
|
|
243
|
+
|
|
244
|
+
"verification_stage_results": {
|
|
245
|
+
"columns": {
|
|
246
|
+
"result_id": "auto_increment",
|
|
247
|
+
"snippet_id": "required|string:uuid",
|
|
248
|
+
"queue_id": "integer:bigint",
|
|
249
|
+
"stage": "required|string|in:lint,static_analysis,security_scan,performance",
|
|
250
|
+
"status": "required|string|in:pass,fail,warning",
|
|
251
|
+
"score": "numeric:decimal(5,2)",
|
|
252
|
+
"tool_used": "string|maxLength:64",
|
|
253
|
+
"findings": "object",
|
|
254
|
+
"executed_at": "datetime"
|
|
255
|
+
},
|
|
256
|
+
"pk": "result_id",
|
|
257
|
+
"timestamps": {
|
|
258
|
+
"executed_at": "executed_at"
|
|
259
|
+
},
|
|
260
|
+
"parent": "snippets"
|
|
261
|
+
},
|
|
262
|
+
|
|
263
|
+
"enrichment_jobs": {
|
|
264
|
+
"columns": {
|
|
265
|
+
"job_id": "auto_increment",
|
|
266
|
+
"snippet_id": "required|string:uuid",
|
|
267
|
+
"provider": "required|string|maxLength:64",
|
|
268
|
+
"model": "required|string|maxLength:128",
|
|
269
|
+
"prompt_version": "string|maxLength:50",
|
|
270
|
+
"status": "required|string|in:pending,success,failed",
|
|
271
|
+
"raw_response": "string:longtext",
|
|
272
|
+
"tokens_used": "integer",
|
|
273
|
+
"latency_ms": "integer",
|
|
274
|
+
"created_at": "datetime"
|
|
275
|
+
},
|
|
276
|
+
"pk": "job_id",
|
|
277
|
+
"timestamps": {
|
|
278
|
+
"created_at": "created_at"
|
|
279
|
+
},
|
|
280
|
+
"parent": "snippets"
|
|
281
|
+
},
|
|
282
|
+
|
|
283
|
+
"generation_attempts": {
|
|
284
|
+
"columns": {
|
|
285
|
+
"attempt_id": "auto_increment",
|
|
286
|
+
"snippet_id": "required|string:uuid",
|
|
287
|
+
"attempt_number": "required|integer|min:1",
|
|
288
|
+
"previous_attempt_id": "integer:unsigned",
|
|
289
|
+
"prompt": "required|string:longtext",
|
|
290
|
+
"generated_code": "required|string:longtext",
|
|
291
|
+
"generated_test": "required|string:longtext",
|
|
292
|
+
"generated_dependency_manifest": "required|string:longtext",
|
|
293
|
+
"failure_stage": "string|in:execution,lint,static_analysis,security_scan",
|
|
294
|
+
"error_output": "string:longtext",
|
|
295
|
+
"outcome": "required|string|in:failed,succeeded",
|
|
296
|
+
"generation_provider": "string|maxLength:64",
|
|
297
|
+
"generation_model": "string|maxLength:128",
|
|
298
|
+
"created_at": "datetime"
|
|
299
|
+
},
|
|
300
|
+
"pk": "attempt_id",
|
|
301
|
+
"timestamps": {
|
|
302
|
+
"created_at": "created_at"
|
|
303
|
+
},
|
|
304
|
+
"parent": "snippets"
|
|
305
|
+
},
|
|
306
|
+
|
|
307
|
+
"execution_queue": {
|
|
308
|
+
"columns": {
|
|
309
|
+
"queue_id": "auto_increment",
|
|
310
|
+
"snippet_id": "required|string:uuid",
|
|
311
|
+
"stage": "required|string|in:execution,lint,static_analysis,security_scan,performance",
|
|
312
|
+
"status": "required|string|in:pending,locked,completed,failed",
|
|
313
|
+
"locked_by": "string|maxLength:100",
|
|
314
|
+
"locked_at": "datetime",
|
|
315
|
+
"lease_expires_at": "datetime",
|
|
316
|
+
"attempt_count": "integer:unsigned",
|
|
317
|
+
"max_attempts": "integer:unsigned",
|
|
318
|
+
"created_at": "datetime",
|
|
319
|
+
"updated_at": "datetime"
|
|
320
|
+
},
|
|
321
|
+
"pk": "queue_id",
|
|
322
|
+
"timestamps": {
|
|
323
|
+
"created_at": "created_at",
|
|
324
|
+
"updated_at": "updated_at"
|
|
325
|
+
},
|
|
326
|
+
"parent": "snippets"
|
|
327
|
+
},
|
|
328
|
+
|
|
329
|
+
"search_query_log": {
|
|
330
|
+
"columns": {
|
|
331
|
+
"log_id": "auto_increment",
|
|
332
|
+
"queries_json": "required|object",
|
|
333
|
+
"results_snippet_ids": "required|object",
|
|
334
|
+
"agent_session_id": "string|maxLength:100",
|
|
335
|
+
"created_at": "datetime"
|
|
336
|
+
},
|
|
337
|
+
"pk": "log_id",
|
|
338
|
+
"timestamps": {
|
|
339
|
+
"created_at": "created_at"
|
|
340
|
+
},
|
|
341
|
+
"parent": null
|
|
342
|
+
},
|
|
343
|
+
|
|
344
|
+
"snippet_feedback": {
|
|
345
|
+
"columns": {
|
|
346
|
+
"feedback_id": "auto_increment",
|
|
347
|
+
"snippet_id": "required|string:uuid",
|
|
348
|
+
"outcome": "required|string|in:used-success,used-failure,rejected-irrelevant",
|
|
349
|
+
"notes": "string:text",
|
|
350
|
+
"agent_session_id": "string|maxLength:100",
|
|
351
|
+
"created_at": "datetime"
|
|
352
|
+
},
|
|
353
|
+
"pk": "feedback_id",
|
|
354
|
+
"timestamps": {
|
|
355
|
+
"created_at": "created_at"
|
|
356
|
+
},
|
|
357
|
+
"parent": "snippets"
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "db-model-router",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.20",
|
|
4
4
|
"description": "Generative API Creation using mysql2 and express libraries in node js",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"bin": {
|
|
@@ -24,6 +24,8 @@
|
|
|
24
24
|
"test:command": "mocha test/commands/*.test.js --timeout 30000 --exit",
|
|
25
25
|
"demo:clear": "node -e \"var fs=require('fs'),p=require('path'),d=p.join(__dirname,'demo');fs.existsSync(d)&&fs.rmSync(d,{recursive:true,force:true});fs.mkdirSync(d,{recursive:true})\"",
|
|
26
26
|
"demo:create": "node scripts/demo-create.js",
|
|
27
|
+
"demo:create-mysql": "node scripts/demo-create.js mysql",
|
|
28
|
+
"demo:create-mariadb": "node scripts/demo-create.js mariadb",
|
|
27
29
|
"demo:create-postgres": "node scripts/demo-create.js postgres"
|
|
28
30
|
},
|
|
29
31
|
"repository": {
|
package/scripts/demo-create.js
CHANGED
|
@@ -29,20 +29,26 @@ const run = (cmd, cwd) => {
|
|
|
29
29
|
};
|
|
30
30
|
|
|
31
31
|
// 2. Copy schema into the demo folder
|
|
32
|
-
const
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
32
|
+
const SCHEMA_BY_ADAPTER = {
|
|
33
|
+
postgres: "dbmr.postgres.test.schema.json",
|
|
34
|
+
mysql: "dbmr.schema.mysql.json",
|
|
35
|
+
mariadb: "dbmr.schema.mysql.json",
|
|
36
|
+
sqlite3: "dbmr.schema.json",
|
|
37
|
+
};
|
|
38
|
+
const schemaPath = path.join(ROOT, SCHEMA_BY_ADAPTER[ADAPTER]);
|
|
36
39
|
|
|
37
40
|
const schema = JSON.parse(fs.readFileSync(schemaPath, "utf8"));
|
|
38
41
|
|
|
39
|
-
// Patch adapter
|
|
42
|
+
// Patch adapter for sqlite3/mariadb demos. mysql/postgres use dedicated
|
|
43
|
+
// schemas with adapter already set; mariadb reuses the mysql schema.
|
|
40
44
|
if (ADAPTER === "sqlite3") {
|
|
41
45
|
schema.adapter = "sqlite3";
|
|
42
46
|
if (schema.options) {
|
|
43
47
|
delete schema.options.session;
|
|
44
48
|
delete schema.options.loki;
|
|
45
49
|
}
|
|
50
|
+
} else if (ADAPTER === "mariadb") {
|
|
51
|
+
schema.adapter = "mariadb";
|
|
46
52
|
}
|
|
47
53
|
|
|
48
54
|
const schemaDest = path.join(DEMO, "dbmr.schema.json");
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
const fs = require("fs");
|
|
4
4
|
const path = require("path");
|
|
5
5
|
const { schemaToModelMeta } = require("../../schema/schema-to-meta");
|
|
6
|
-
const { generateModelFile } = require("../generate-model");
|
|
6
|
+
const { generateModelFile, generateIndexFile } = require("../generate-model");
|
|
7
7
|
const {
|
|
8
8
|
generateRouteFile,
|
|
9
9
|
generateParentRouteFile,
|
|
@@ -104,6 +104,14 @@ async function buildSchemaArtifacts({ schema, baseDir, ctx, flags }) {
|
|
|
104
104
|
content: generateModelFile(m),
|
|
105
105
|
});
|
|
106
106
|
}
|
|
107
|
+
|
|
108
|
+
// Barrel re-exporting all schema models. When SaaS is enabled, the SaaS
|
|
109
|
+
// generator emits a combined barrel (SaaS + schema tables) and replaces
|
|
110
|
+
// this one below; without SaaS, this barrel is the final models/index.js.
|
|
111
|
+
planned.push({
|
|
112
|
+
relPath: "models/index.js",
|
|
113
|
+
content: generateIndexFile(meta),
|
|
114
|
+
});
|
|
107
115
|
}
|
|
108
116
|
|
|
109
117
|
// --- Route files ---
|
|
@@ -258,14 +266,15 @@ async function buildSchemaArtifacts({ schema, baseDir, ctx, flags }) {
|
|
|
258
266
|
baseDir,
|
|
259
267
|
});
|
|
260
268
|
|
|
261
|
-
// The SaaS generator produces a combined routes/index.js
|
|
262
|
-
// both SaaS
|
|
263
|
-
// planned
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
+
// The SaaS generator produces a combined routes/index.js and models/index.js
|
|
270
|
+
// that include both SaaS and dbmr schema-generated entries. Remove the
|
|
271
|
+
// plain barrels previously planned by the schema generator so the combined
|
|
272
|
+
// SaaS versions win.
|
|
273
|
+
for (const barrel of ["routes/index.js", "models/index.js"]) {
|
|
274
|
+
const existingIdx = planned.findIndex((p) => p.relPath === barrel);
|
|
275
|
+
if (existingIdx !== -1) {
|
|
276
|
+
planned.splice(existingIdx, 1);
|
|
277
|
+
}
|
|
269
278
|
}
|
|
270
279
|
|
|
271
280
|
for (const entry of saasFiles) {
|
package/src/cli/commands/init.js
CHANGED
|
@@ -132,9 +132,6 @@ async function init(args, flags, ctx) {
|
|
|
132
132
|
updatePackageJson(answers, outputDir);
|
|
133
133
|
|
|
134
134
|
const installed = !flags.noInstall;
|
|
135
|
-
if (installed) {
|
|
136
|
-
runInstall();
|
|
137
|
-
}
|
|
138
135
|
|
|
139
136
|
// Build init's JSON result first so it lands at ctx._results[0] (buildSchemaArtifacts
|
|
140
137
|
// pushes its own result afterward).
|
|
@@ -153,10 +150,17 @@ async function init(args, flags, ctx) {
|
|
|
153
150
|
});
|
|
154
151
|
}
|
|
155
152
|
|
|
156
|
-
// Schema-driven artifacts: models, routes, migrations, openapi, tests, SaaS
|
|
153
|
+
// Schema-driven artifacts: models, routes, migrations, openapi, tests, SaaS.
|
|
154
|
+
// Generated BEFORE npm install so all files exist on disk first; bail skips
|
|
155
|
+
// install if the build reported an error.
|
|
157
156
|
await buildSchemaArtifacts({ schema, baseDir, ctx, flags });
|
|
158
157
|
if (process.exitCode) return; // bail if build reported an error
|
|
159
158
|
|
|
159
|
+
// Install dependencies only after every project file has been written.
|
|
160
|
+
if (installed) {
|
|
161
|
+
runInstall();
|
|
162
|
+
}
|
|
163
|
+
|
|
160
164
|
// Human-readable summary (non-json only)
|
|
161
165
|
if (!flags.json) {
|
|
162
166
|
printSummary(generated);
|