swallowkit 1.0.0-beta.54 → 1.0.0-beta.56
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/commands/add-auth.d.ts.map +1 -1
- package/dist/cli/commands/add-auth.js +154 -157
- package/dist/cli/commands/add-auth.js.map +1 -1
- package/dist/cli/commands/init.d.ts +5 -0
- package/dist/cli/commands/init.d.ts.map +1 -1
- package/dist/cli/commands/init.js +178 -25
- package/dist/cli/commands/init.js.map +1 -1
- package/dist/cli/commands/scaffold.d.ts +7 -2
- package/dist/cli/commands/scaffold.d.ts.map +1 -1
- package/dist/cli/commands/scaffold.js +111 -123
- package/dist/cli/commands/scaffold.js.map +1 -1
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +127 -2
- package/dist/cli/index.js.map +1 -1
- package/dist/core/config.d.ts +1 -1
- package/dist/core/config.d.ts.map +1 -1
- package/dist/core/config.js +8 -4
- package/dist/core/config.js.map +1 -1
- package/dist/core/operations/auth-operations.d.ts +57 -0
- package/dist/core/operations/auth-operations.d.ts.map +1 -0
- package/dist/core/operations/auth-operations.js +269 -0
- package/dist/core/operations/auth-operations.js.map +1 -0
- package/dist/core/operations/create-model.d.ts.map +1 -1
- package/dist/core/operations/create-model.js +23 -13
- package/dist/core/operations/create-model.js.map +1 -1
- package/dist/core/operations/file-session.d.ts +53 -0
- package/dist/core/operations/file-session.d.ts.map +1 -0
- package/dist/core/operations/file-session.js +195 -0
- package/dist/core/operations/file-session.js.map +1 -0
- package/dist/core/operations/provision-operations.d.ts +52 -0
- package/dist/core/operations/provision-operations.d.ts.map +1 -0
- package/dist/core/operations/provision-operations.js +211 -0
- package/dist/core/operations/provision-operations.js.map +1 -0
- package/dist/core/operations/runtime.d.ts +5 -0
- package/dist/core/operations/runtime.d.ts.map +1 -1
- package/dist/core/operations/runtime.js +23 -0
- package/dist/core/operations/runtime.js.map +1 -1
- package/dist/core/operations/scaffold-apply.d.ts +21 -0
- package/dist/core/operations/scaffold-apply.d.ts.map +1 -0
- package/dist/core/operations/scaffold-apply.js +57 -0
- package/dist/core/operations/scaffold-apply.js.map +1 -0
- package/dist/core/operations/scaffold-machine.d.ts.map +1 -1
- package/dist/core/operations/scaffold-machine.js +1 -13
- package/dist/core/operations/scaffold-machine.js.map +1 -1
- package/dist/core/operations/scaffold-plan.d.ts +43 -0
- package/dist/core/operations/scaffold-plan.d.ts.map +1 -0
- package/dist/core/operations/scaffold-plan.js +195 -0
- package/dist/core/operations/scaffold-plan.js.map +1 -0
- package/dist/core/project/artifacts.d.ts +58 -0
- package/dist/core/project/artifacts.d.ts.map +1 -0
- package/dist/core/project/artifacts.js +179 -0
- package/dist/core/project/artifacts.js.map +1 -0
- package/dist/core/project/boundaries.d.ts +50 -0
- package/dist/core/project/boundaries.d.ts.map +1 -0
- package/dist/core/project/boundaries.js +117 -0
- package/dist/core/project/boundaries.js.map +1 -0
- package/dist/core/project/drift.d.ts +29 -0
- package/dist/core/project/drift.d.ts.map +1 -0
- package/dist/core/project/drift.js +188 -0
- package/dist/core/project/drift.js.map +1 -0
- package/dist/core/project/infra.d.ts +49 -0
- package/dist/core/project/infra.d.ts.map +1 -0
- package/dist/core/project/infra.js +167 -0
- package/dist/core/project/infra.js.map +1 -0
- package/dist/core/project/state.d.ts +15 -0
- package/dist/core/project/state.d.ts.map +1 -0
- package/dist/core/project/state.js +106 -0
- package/dist/core/project/state.js.map +1 -0
- package/dist/core/project/workflows.d.ts +43 -0
- package/dist/core/project/workflows.d.ts.map +1 -0
- package/dist/core/project/workflows.js +255 -0
- package/dist/core/project/workflows.js.map +1 -0
- package/dist/core/scaffold/auth-generator.d.ts +1 -1
- package/dist/core/scaffold/auth-generator.d.ts.map +1 -1
- package/dist/core/scaffold/auth-generator.js +108 -52
- package/dist/core/scaffold/auth-generator.js.map +1 -1
- package/dist/core/scaffold/functions-generator.js +9 -9
- package/dist/core/scaffold/nextjs-generator.js +6 -6
- package/dist/core/scaffold/ui-generator.js +19 -19
- package/dist/core/scaffold/ui-generator.js.map +1 -1
- package/dist/core/verify/index.d.ts +62 -0
- package/dist/core/verify/index.d.ts.map +1 -0
- package/dist/core/verify/index.js +343 -0
- package/dist/core/verify/index.js.map +1 -0
- package/dist/machine/contracts.d.ts +8 -0
- package/dist/machine/contracts.d.ts.map +1 -1
- package/dist/machine/errors.d.ts +4 -1
- package/dist/machine/errors.d.ts.map +1 -1
- package/dist/machine/errors.js +9 -1
- package/dist/machine/errors.js.map +1 -1
- package/dist/machine/index.d.ts.map +1 -1
- package/dist/machine/index.js +350 -16
- package/dist/machine/index.js.map +1 -1
- package/dist/mcp/index.d.ts.map +1 -1
- package/dist/mcp/index.js +202 -1
- package/dist/mcp/index.js.map +1 -1
- package/dist/types/index.d.ts +14 -0
- package/dist/types/index.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/__tests__/__snapshots__/functions-generator.test.ts.snap +17 -17
- package/src/__tests__/__snapshots__/nextjs-generator.test.ts.snap +6 -6
- package/src/__tests__/__snapshots__/ui-generator.test.ts.snap +11 -11
- package/src/__tests__/agent-loop-phase34.test.ts +449 -0
- package/src/__tests__/bff-swa-auth.test.ts +275 -0
- package/src/__tests__/file-session.test.ts +98 -0
- package/src/__tests__/init.test.ts +50 -0
- package/src/__tests__/mcp.test.ts +113 -5
- package/src/__tests__/multi-auth.test.ts +1 -1
- package/src/__tests__/plan-apply.test.ts +294 -0
- package/src/cli/commands/add-auth.ts +164 -164
- package/src/cli/commands/init.ts +186 -24
- package/src/cli/commands/scaffold.ts +128 -129
- package/src/cli/index.ts +148 -2
- package/src/core/config.ts +5 -4
- package/src/core/operations/auth-operations.ts +353 -0
- package/src/core/operations/create-model.ts +25 -13
- package/src/core/operations/file-session.ts +210 -0
- package/src/core/operations/provision-operations.ts +297 -0
- package/src/core/operations/runtime.ts +23 -0
- package/src/core/operations/scaffold-apply.ts +106 -0
- package/src/core/operations/scaffold-machine.ts +2 -16
- package/src/core/operations/scaffold-plan.ts +224 -0
- package/src/core/project/artifacts.ts +205 -0
- package/src/core/project/boundaries.ts +170 -0
- package/src/core/project/drift.ts +202 -0
- package/src/core/project/infra.ts +196 -0
- package/src/core/project/state.ts +77 -0
- package/src/core/project/workflows.ts +249 -0
- package/src/core/scaffold/auth-generator.ts +119 -60
- package/src/core/scaffold/functions-generator.ts +9 -9
- package/src/core/scaffold/nextjs-generator.ts +6 -6
- package/src/core/scaffold/ui-generator.ts +19 -19
- package/src/core/verify/index.ts +392 -0
- package/src/machine/contracts.ts +16 -0
- package/src/machine/errors.ts +12 -1
- package/src/machine/index.ts +444 -15
- package/src/mcp/index.ts +198 -2
- package/src/types/index.ts +17 -0
|
@@ -39,6 +39,7 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
39
39
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
40
40
|
exports.scaffoldCommand = scaffoldCommand;
|
|
41
41
|
exports.resolveAuthPolicy = resolveAuthPolicy;
|
|
42
|
+
exports.resolveModelPath = resolveModelPath;
|
|
42
43
|
exports.createUIAuthOptions = createUIAuthOptions;
|
|
43
44
|
exports.generateCosmosContainer = generateCosmosContainer;
|
|
44
45
|
exports.generateUIComponents = generateUIComponents;
|
|
@@ -55,6 +56,9 @@ const native_schema_generator_1 = require("../../core/scaffold/native-schema-gen
|
|
|
55
56
|
const package_manager_1 = require("../../utils/package-manager");
|
|
56
57
|
const manifest_1 = require("../../core/project/manifest");
|
|
57
58
|
const auth_generator_1 = require("../../core/scaffold/auth-generator");
|
|
59
|
+
const file_session_1 = require("../../core/operations/file-session");
|
|
60
|
+
const artifacts_1 = require("../../core/project/artifacts");
|
|
61
|
+
const SCAFFOLD_GENERATOR = "scaffold";
|
|
58
62
|
function getMachineAwareStdio() {
|
|
59
63
|
return process.env.SWALLOWKIT_MACHINE_OUTPUT === "1" ? "pipe" : "inherit";
|
|
60
64
|
}
|
|
@@ -77,6 +81,8 @@ async function scaffoldCommand(options) {
|
|
|
77
81
|
const configValidation = (0, config_1.validateConfig)((0, config_1.getFullConfig)());
|
|
78
82
|
if (!configValidation.valid)
|
|
79
83
|
throw new Error(`Invalid SwallowKit configuration:\n${configValidation.errors.map(error => `- ${error}`).join("\n")}`);
|
|
84
|
+
// Plan(dry-run) や Apply からセッションが供給される。単体実行時は commit セッションを生成。
|
|
85
|
+
const session = (0, file_session_1.getActiveFileSession)() ?? new file_session_1.FileOperationSession("commit");
|
|
80
86
|
console.log("🏗️ SwallowKit Scaffold: Generating CRUD operations...\n");
|
|
81
87
|
try {
|
|
82
88
|
// 1. Resolve model file path
|
|
@@ -117,30 +123,35 @@ async function scaffoldCommand(options) {
|
|
|
117
123
|
console.log("ℹ️ --api-only skips UI generation only; Functions, BFF routes, OpenAPI, and native schema assets are still updated.");
|
|
118
124
|
}
|
|
119
125
|
// 5. Generate BFF callFunction helper
|
|
120
|
-
await generateCallFunctionHelper();
|
|
126
|
+
await generateCallFunctionHelper(session);
|
|
121
127
|
// 6. Generate Azure Functions code
|
|
122
128
|
if (isConnectorModel) {
|
|
123
|
-
await generateConnectorFunctionsCode(modelInfo, functionsDir, sharedPackageName, backendLanguage);
|
|
129
|
+
await generateConnectorFunctionsCode(modelInfo, functionsDir, sharedPackageName, backendLanguage, session);
|
|
124
130
|
// 6b. Install connector driver dependencies
|
|
125
|
-
await installConnectorDriverDependencies(modelInfo, functionsDir, backendLanguage);
|
|
131
|
+
await installConnectorDriverDependencies(modelInfo, functionsDir, backendLanguage, session);
|
|
126
132
|
}
|
|
127
133
|
else {
|
|
128
|
-
await generateFunctionsCode(modelInfo, functionsDir, sharedPackageName, backendLanguage);
|
|
134
|
+
await generateFunctionsCode(modelInfo, functionsDir, sharedPackageName, backendLanguage, session);
|
|
129
135
|
if (backendLanguage !== "typescript") {
|
|
130
|
-
|
|
136
|
+
if (session.mode === "collect") {
|
|
137
|
+
session.addWarning(`external-codegen: ${functionsDir}/openapi and ${functionsDir}/generated are regenerated by external tooling on apply and are not included in this plan.`);
|
|
138
|
+
}
|
|
139
|
+
else {
|
|
140
|
+
await (0, native_schema_generator_1.generateLanguageSchemaArtifacts)(relatedModels, modelInfo, functionsDir, backendLanguage);
|
|
141
|
+
}
|
|
131
142
|
}
|
|
132
143
|
}
|
|
133
144
|
// 7. Generate Next.js BFF API Routes
|
|
134
145
|
const apiDir = options.apiDir || "app/api";
|
|
135
146
|
if (isConnectorModel) {
|
|
136
|
-
await generateConnectorBFFRoutesFiles(modelInfo, apiDir, sharedPackageName);
|
|
147
|
+
await generateConnectorBFFRoutesFiles(modelInfo, apiDir, sharedPackageName, session);
|
|
137
148
|
}
|
|
138
149
|
else {
|
|
139
|
-
await generateBFFRoutes(modelInfo, apiDir, sharedPackageName);
|
|
150
|
+
await generateBFFRoutes(modelInfo, apiDir, sharedPackageName, session);
|
|
140
151
|
}
|
|
141
152
|
// 8. Generate Cosmos DB container Bicep file (skip for connector models)
|
|
142
153
|
if (!isConnectorModel) {
|
|
143
|
-
await generateCosmosContainer(modelInfo);
|
|
154
|
+
await generateCosmosContainer(modelInfo, session);
|
|
144
155
|
}
|
|
145
156
|
// 9. Generate UI components (unless --api-only)
|
|
146
157
|
if (!options.apiOnly) {
|
|
@@ -149,13 +160,19 @@ async function scaffoldCommand(options) {
|
|
|
149
160
|
const uiAuthOptions = uiAuthPolicy && uiAuthConfig && uiAuthConfig.provider !== 'none'
|
|
150
161
|
? createUIAuthOptions(uiAuthPolicy, uiAuthConfig)
|
|
151
162
|
: undefined;
|
|
152
|
-
await generateUIComponents(modelInfo, sharedPackageName, uiAuthOptions);
|
|
163
|
+
await generateUIComponents(modelInfo, sharedPackageName, uiAuthOptions, session);
|
|
153
164
|
if (uiAuthOptions?.authenticatedFetchImport) {
|
|
154
|
-
applyExternalTokenFetchToGeneratedUi(modelInfo, uiAuthOptions.authenticatedFetchImport);
|
|
165
|
+
applyExternalTokenFetchToGeneratedUi(modelInfo, session, uiAuthOptions.authenticatedFetchImport);
|
|
155
166
|
}
|
|
156
|
-
await updateNavigationMenu(modelInfo);
|
|
167
|
+
await updateNavigationMenu(modelInfo, session);
|
|
168
|
+
}
|
|
169
|
+
if (session.mode === "commit") {
|
|
170
|
+
(0, artifacts_1.recordSessionOperations)(session.operations, {
|
|
171
|
+
schemaHash: (0, file_session_1.hashFileIfExists)(modelPath) ?? undefined,
|
|
172
|
+
sourceModel: modelInfo.name,
|
|
173
|
+
});
|
|
174
|
+
await (0, manifest_1.syncProjectManifest)();
|
|
157
175
|
}
|
|
158
|
-
await (0, manifest_1.syncProjectManifest)();
|
|
159
176
|
console.log("\n✅ Scaffold completed successfully!");
|
|
160
177
|
console.log("\n📝 Next steps:");
|
|
161
178
|
console.log(` 1. Review generated files in ${describeFunctionsOutputPath(functionsDir, backendLanguage)} and ${apiDir}/`);
|
|
@@ -175,32 +192,26 @@ async function scaffoldCommand(options) {
|
|
|
175
192
|
process.exit(1);
|
|
176
193
|
}
|
|
177
194
|
}
|
|
178
|
-
function applyExternalTokenFetchToGeneratedUi(modelInfo, importPath = '@/lib/auth/authenticated-fetch') {
|
|
179
|
-
const
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
let content = fs.readFileSync(target, 'utf-8');
|
|
192
|
-
if (!content.includes('fetch('))
|
|
193
|
-
continue;
|
|
194
|
-
content = content.replace(/\bfetch\(/g, 'authenticatedFetch(');
|
|
195
|
-
content = content.replace(/(if \(!res\.ok\) throw new Error\([^\n]+\);)/g, `if (res.status === 401) throw new Error('Authentication required');\n $1`);
|
|
196
|
-
if (!content.includes(importPath)) {
|
|
197
|
-
const directive = content.match(/^'use client';\s*\r?\n/)?.[0] ?? '';
|
|
198
|
-
content = `${directive}import { authenticatedFetch } from '${importPath}';\n${content.slice(directive.length)}`;
|
|
199
|
-
}
|
|
200
|
-
fs.writeFileSync(target, content, 'utf-8');
|
|
195
|
+
function applyExternalTokenFetchToGeneratedUi(modelInfo, session, importPath = '@/lib/auth/authenticated-fetch') {
|
|
196
|
+
const uiPrefix = `app/${(0, model_parser_1.toKebabCase)(modelInfo.name)}/`;
|
|
197
|
+
for (const operation of session.operations) {
|
|
198
|
+
if (!operation.path.startsWith(uiPrefix) || !operation.path.endsWith('.tsx') || operation.action === 'delete')
|
|
199
|
+
continue;
|
|
200
|
+
let content = session.readFile(operation.absolutePath);
|
|
201
|
+
if (!content.includes('fetch('))
|
|
202
|
+
continue;
|
|
203
|
+
content = content.replace(/\bfetch\(/g, 'authenticatedFetch(');
|
|
204
|
+
content = content.replace(/(if \(!res\.ok\) throw new Error\([^\n]+\);)/g, `if (res.status === 401) throw new Error('Authentication required');\n $1`);
|
|
205
|
+
if (!content.includes(importPath)) {
|
|
206
|
+
const directive = content.match(/^'use client';\s*\r?\n/)?.[0] ?? '';
|
|
207
|
+
content = `${directive}import { authenticatedFetch } from '${importPath}';\n${content.slice(directive.length)}`;
|
|
201
208
|
}
|
|
202
|
-
|
|
203
|
-
|
|
209
|
+
session.writeFile(operation.absolutePath, content, {
|
|
210
|
+
ownership: 'managed',
|
|
211
|
+
generator: SCAFFOLD_GENERATOR,
|
|
212
|
+
sourceModel: modelInfo.name,
|
|
213
|
+
});
|
|
214
|
+
}
|
|
204
215
|
}
|
|
205
216
|
/**
|
|
206
217
|
* モデルの authPolicy と auth config から実効的な認可ポリシーを解決
|
|
@@ -289,14 +300,11 @@ function readSharedPackageName() {
|
|
|
289
300
|
/**
|
|
290
301
|
* Generate BFF callFunction helper (lib/api/call-function.ts)
|
|
291
302
|
*/
|
|
292
|
-
async function generateCallFunctionHelper() {
|
|
303
|
+
async function generateCallFunctionHelper(session) {
|
|
293
304
|
console.log("\n📦 Generating BFF callFunction helper...");
|
|
294
305
|
const cwd = process.cwd();
|
|
295
306
|
const helperDir = path.join(cwd, "lib", "api");
|
|
296
307
|
const helperPath = path.join(helperDir, "call-function.ts");
|
|
297
|
-
if (!fs.existsSync(helperDir)) {
|
|
298
|
-
fs.mkdirSync(helperDir, { recursive: true });
|
|
299
|
-
}
|
|
300
308
|
// auth 設定がある場合は Authorization ヘッダー転送版を生成
|
|
301
309
|
const authConfig = (0, config_1.getAuthConfig)();
|
|
302
310
|
const normalizedAuth = (0, config_1.normalizeAuthConfig)(authConfig);
|
|
@@ -311,13 +319,13 @@ async function generateCallFunctionHelper() {
|
|
|
311
319
|
else {
|
|
312
320
|
helperCode = (0, nextjs_generator_1.generateBFFCallFunction)();
|
|
313
321
|
}
|
|
314
|
-
|
|
322
|
+
session.writeFile(helperPath, helperCode, { ownership: "managed", generator: SCAFFOLD_GENERATOR });
|
|
315
323
|
console.log(`✅ Created: ${helperPath}`);
|
|
316
324
|
}
|
|
317
325
|
/**
|
|
318
326
|
* Generate Azure Functions CRUD code
|
|
319
327
|
*/
|
|
320
|
-
async function generateFunctionsCode(modelInfo, functionsDir, sharedPackageName, backendLanguage) {
|
|
328
|
+
async function generateFunctionsCode(modelInfo, functionsDir, sharedPackageName, backendLanguage, session) {
|
|
321
329
|
console.log("\n🔨 Generating Azure Functions CRUD code...");
|
|
322
330
|
// Resolve auth policy: model-level authPolicy or global defaultPolicy
|
|
323
331
|
const authConfig = (0, config_1.getAuthConfig)();
|
|
@@ -326,20 +334,16 @@ async function generateFunctionsCode(modelInfo, functionsDir, sharedPackageName,
|
|
|
326
334
|
console.log(`🔐 Auth policy detected: ${JSON.stringify(authPolicy)}`);
|
|
327
335
|
}
|
|
328
336
|
const modelKebab = (0, model_parser_1.toKebabCase)(modelInfo.name);
|
|
337
|
+
const managedMeta = { ownership: "managed", generator: SCAFFOLD_GENERATOR, sourceModel: modelInfo.name };
|
|
329
338
|
if (backendLanguage === "typescript") {
|
|
330
339
|
const normalizedAuth = (0, config_1.getNormalizedAuthConfig)();
|
|
331
340
|
if (normalizedAuth && Object.keys(normalizedAuth.schemes).some(name => name !== "default")) {
|
|
332
341
|
const routerPath = path.join(process.cwd(), functionsDir, "src", "auth", "auth-router.ts");
|
|
333
|
-
|
|
334
|
-
fs.writeFileSync(routerPath, (0, auth_generator_1.generateNamedAuthRouterTS)(normalizedAuth), "utf-8");
|
|
342
|
+
session.writeFile(routerPath, (0, auth_generator_1.generateNamedAuthRouterTS)(normalizedAuth), { ownership: "managed", generator: SCAFFOLD_GENERATOR });
|
|
335
343
|
}
|
|
336
344
|
const functionFilePath = path.join(process.cwd(), functionsDir, "src", `${modelKebab}.ts`);
|
|
337
|
-
const functionDir = path.dirname(functionFilePath);
|
|
338
|
-
if (!fs.existsSync(functionDir)) {
|
|
339
|
-
fs.mkdirSync(functionDir, { recursive: true });
|
|
340
|
-
}
|
|
341
345
|
const code = (0, functions_generator_1.generateCompactAzureFunctionsCRUD)(modelInfo, sharedPackageName, authPolicy, authConfig?.provider);
|
|
342
|
-
|
|
346
|
+
session.writeFile(functionFilePath, code, managedMeta);
|
|
343
347
|
console.log(`✅ Created: ${functionFilePath}`);
|
|
344
348
|
return;
|
|
345
349
|
}
|
|
@@ -347,34 +351,30 @@ async function generateFunctionsCode(modelInfo, functionsDir, sharedPackageName,
|
|
|
347
351
|
const normalizedAuth = (0, config_1.getNormalizedAuthConfig)();
|
|
348
352
|
if (normalizedAuth && Object.keys(normalizedAuth.schemes).some(name => name !== "default")) {
|
|
349
353
|
const routerPath = path.join(process.cwd(), functionsDir, "Auth", "AuthRouter.cs");
|
|
350
|
-
|
|
351
|
-
fs.writeFileSync(routerPath, (0, auth_generator_1.generateNamedAuthRouterCSharp)(normalizedAuth), "utf-8");
|
|
354
|
+
session.writeFile(routerPath, (0, auth_generator_1.generateNamedAuthRouterCSharp)(normalizedAuth), { ownership: "managed", generator: SCAFFOLD_GENERATOR });
|
|
352
355
|
}
|
|
353
356
|
const crudDir = path.join(process.cwd(), functionsDir, "Crud");
|
|
354
357
|
const functionFilePath = path.join(crudDir, `${modelInfo.name}CrudFunctions.cs`);
|
|
355
|
-
fs.mkdirSync(crudDir, { recursive: true });
|
|
356
358
|
// Remove init-generated template (singular) to avoid route conflicts
|
|
357
359
|
const templatePath = path.join(crudDir, `${modelInfo.name}Function.cs`);
|
|
358
|
-
if (
|
|
359
|
-
|
|
360
|
+
if (session.fileExists(templatePath)) {
|
|
361
|
+
session.deleteFile(templatePath, managedMeta);
|
|
360
362
|
console.log(`🗑️ Removed template: ${templatePath}`);
|
|
361
363
|
}
|
|
362
|
-
|
|
364
|
+
session.writeFile(functionFilePath, (0, functions_generator_1.generateCSharpAzureFunctionsCRUD)(modelInfo, authPolicy), managedMeta);
|
|
363
365
|
console.log(`✅ Created: ${functionFilePath}`);
|
|
364
366
|
return;
|
|
365
367
|
}
|
|
366
368
|
const normalizedAuth = (0, config_1.getNormalizedAuthConfig)();
|
|
367
369
|
if (normalizedAuth && Object.keys(normalizedAuth.schemes).some(name => name !== "default")) {
|
|
368
370
|
const routerPath = path.join(process.cwd(), functionsDir, "auth", "auth_router.py");
|
|
369
|
-
|
|
370
|
-
fs.writeFileSync(routerPath, (0, auth_generator_1.generateNamedAuthRouterPython)(normalizedAuth), "utf-8");
|
|
371
|
+
session.writeFile(routerPath, (0, auth_generator_1.generateNamedAuthRouterPython)(normalizedAuth), { ownership: "managed", generator: SCAFFOLD_GENERATOR });
|
|
371
372
|
}
|
|
372
373
|
const blueprintsDir = path.join(process.cwd(), functionsDir, "blueprints");
|
|
373
374
|
const blueprintPath = path.join(blueprintsDir, `${modelKebab.replace(/-/g, "_")}.py`);
|
|
374
|
-
fs.mkdirSync(blueprintsDir, { recursive: true });
|
|
375
375
|
const { blueprint, registration } = (0, functions_generator_1.generatePythonAzureFunctionsCRUD)(modelInfo, authPolicy);
|
|
376
|
-
|
|
377
|
-
updatePythonFunctionRegistrations(path.join(process.cwd(), functionsDir, "function_app.py"), registration);
|
|
376
|
+
session.writeFile(blueprintPath, blueprint, managedMeta);
|
|
377
|
+
updatePythonFunctionRegistrations(path.join(process.cwd(), functionsDir, "function_app.py"), registration, session);
|
|
378
378
|
console.log(`✅ Created: ${blueprintPath}`);
|
|
379
379
|
}
|
|
380
380
|
function createUIAuthOptions(policy, authConfig) {
|
|
@@ -393,7 +393,7 @@ function createUIAuthOptions(policy, authConfig) {
|
|
|
393
393
|
/**
|
|
394
394
|
* コネクタモデル用 Azure Functions コード生成
|
|
395
395
|
*/
|
|
396
|
-
async function generateConnectorFunctionsCode(modelInfo, functionsDir, sharedPackageName, backendLanguage) {
|
|
396
|
+
async function generateConnectorFunctionsCode(modelInfo, functionsDir, sharedPackageName, backendLanguage, session) {
|
|
397
397
|
console.log("\n🔌 Generating Connector Azure Functions code...");
|
|
398
398
|
const connectorConfig = modelInfo.connectorConfig;
|
|
399
399
|
const connectorDef = (0, config_1.getConnectorDefinition)(connectorConfig.connector);
|
|
@@ -408,9 +408,9 @@ async function generateConnectorFunctionsCode(modelInfo, functionsDir, sharedPac
|
|
|
408
408
|
console.log(`🔐 Auth policy detected: ${JSON.stringify(authPolicy)}`);
|
|
409
409
|
}
|
|
410
410
|
const modelKebab = (0, model_parser_1.toKebabCase)(modelInfo.name);
|
|
411
|
+
const connectorManagedMeta = { ownership: "managed", generator: SCAFFOLD_GENERATOR, sourceModel: modelInfo.name };
|
|
411
412
|
if (backendLanguage === "typescript") {
|
|
412
413
|
const functionFilePath = path.join(process.cwd(), functionsDir, "src", `${modelKebab}.ts`);
|
|
413
|
-
fs.mkdirSync(path.dirname(functionFilePath), { recursive: true });
|
|
414
414
|
let code;
|
|
415
415
|
if (connectorDef.type === "rdb") {
|
|
416
416
|
code = (0, connector_functions_generator_1.generateRdbConnectorFunctionTS)(modelInfo, sharedPackageName, connectorDef, connectorConfig, authPolicy, authConfig?.provider);
|
|
@@ -418,13 +418,12 @@ async function generateConnectorFunctionsCode(modelInfo, functionsDir, sharedPac
|
|
|
418
418
|
else {
|
|
419
419
|
code = (0, connector_functions_generator_1.generateApiConnectorFunctionTS)(modelInfo, sharedPackageName, connectorDef, connectorConfig, authPolicy, authConfig?.provider);
|
|
420
420
|
}
|
|
421
|
-
|
|
421
|
+
session.writeFile(functionFilePath, code, connectorManagedMeta);
|
|
422
422
|
console.log(`✅ Created: ${functionFilePath}`);
|
|
423
423
|
return;
|
|
424
424
|
}
|
|
425
425
|
if (backendLanguage === "csharp") {
|
|
426
426
|
const functionFilePath = path.join(process.cwd(), functionsDir, "Connectors", `${modelInfo.name}ConnectorFunctions.cs`);
|
|
427
|
-
fs.mkdirSync(path.dirname(functionFilePath), { recursive: true });
|
|
428
427
|
let code;
|
|
429
428
|
if (connectorDef.type === "rdb") {
|
|
430
429
|
code = (0, connector_functions_generator_1.generateRdbConnectorFunctionCSharp)(modelInfo, connectorDef, connectorConfig);
|
|
@@ -432,14 +431,13 @@ async function generateConnectorFunctionsCode(modelInfo, functionsDir, sharedPac
|
|
|
432
431
|
else {
|
|
433
432
|
code = (0, connector_functions_generator_1.generateApiConnectorFunctionCSharp)(modelInfo, connectorDef, connectorConfig);
|
|
434
433
|
}
|
|
435
|
-
|
|
434
|
+
session.writeFile(functionFilePath, code, connectorManagedMeta);
|
|
436
435
|
console.log(`✅ Created: ${functionFilePath}`);
|
|
437
436
|
return;
|
|
438
437
|
}
|
|
439
438
|
// Python
|
|
440
439
|
const blueprintsDir = path.join(process.cwd(), functionsDir, "blueprints");
|
|
441
440
|
const blueprintPath = path.join(blueprintsDir, `${modelKebab.replace(/-/g, "_")}.py`);
|
|
442
|
-
fs.mkdirSync(blueprintsDir, { recursive: true });
|
|
443
441
|
let result;
|
|
444
442
|
if (connectorDef.type === "rdb") {
|
|
445
443
|
result = (0, connector_functions_generator_1.generateRdbConnectorFunctionPython)(modelInfo, connectorDef, connectorConfig);
|
|
@@ -447,15 +445,15 @@ async function generateConnectorFunctionsCode(modelInfo, functionsDir, sharedPac
|
|
|
447
445
|
else {
|
|
448
446
|
result = (0, connector_functions_generator_1.generateApiConnectorFunctionPython)(modelInfo, connectorDef, connectorConfig);
|
|
449
447
|
}
|
|
450
|
-
|
|
451
|
-
updatePythonFunctionRegistrations(path.join(process.cwd(), functionsDir, "function_app.py"), result.registration);
|
|
448
|
+
session.writeFile(blueprintPath, result.blueprint, connectorManagedMeta);
|
|
449
|
+
updatePythonFunctionRegistrations(path.join(process.cwd(), functionsDir, "function_app.py"), result.registration, session);
|
|
452
450
|
console.log(`✅ Created: ${blueprintPath}`);
|
|
453
451
|
}
|
|
454
452
|
/**
|
|
455
453
|
* コネクタモデルの scaffold 後に、生成コードが必要とする RDB/API ドライバを
|
|
456
454
|
* functions ディレクトリにインストールする。
|
|
457
455
|
*/
|
|
458
|
-
async function installConnectorDriverDependencies(modelInfo, functionsDir, backendLanguage) {
|
|
456
|
+
async function installConnectorDriverDependencies(modelInfo, functionsDir, backendLanguage, session) {
|
|
459
457
|
const connectorConfig = modelInfo.connectorConfig;
|
|
460
458
|
const connectorDef = (0, config_1.getConnectorDefinition)(connectorConfig.connector);
|
|
461
459
|
if (!connectorDef || connectorDef.type !== "rdb")
|
|
@@ -481,6 +479,10 @@ async function installConnectorDriverDependencies(modelInfo, functionsDir, backe
|
|
|
481
479
|
if (missingDeps.length === 0 && missingDevDeps.length === 0)
|
|
482
480
|
return;
|
|
483
481
|
}
|
|
482
|
+
if (session.mode === "collect") {
|
|
483
|
+
session.addWarning(`external-install: ${rdbDef.provider} driver dependencies (${[...entry.deps, ...entry.devDeps].join(", ")}) will be installed into ${functionsDir}/ on apply.`);
|
|
484
|
+
return;
|
|
485
|
+
}
|
|
484
486
|
console.log(`\n📦 Installing ${rdbDef.provider} driver dependencies...`);
|
|
485
487
|
const pm = (0, package_manager_1.detectFromProject)(functionsPath);
|
|
486
488
|
const cmds = (0, package_manager_1.getCommands)(pm);
|
|
@@ -502,6 +504,10 @@ async function installConnectorDriverDependencies(modelInfo, functionsDir, backe
|
|
|
502
504
|
const pkg = nugetMap[rdbDef.provider];
|
|
503
505
|
if (!pkg)
|
|
504
506
|
return;
|
|
507
|
+
if (session.mode === "collect") {
|
|
508
|
+
session.addWarning(`external-install: NuGet package ${pkg} will be added to ${functionsDir}/functions.csproj on apply.`);
|
|
509
|
+
return;
|
|
510
|
+
}
|
|
505
511
|
console.log(`\n📦 Installing ${rdbDef.provider} NuGet package...`);
|
|
506
512
|
runSpawnSyncCommand("dotnet", ["add", path.join(functionsPath, "functions.csproj"), "package", pkg], functionsPath);
|
|
507
513
|
console.log(`✅ ${pkg} installed`);
|
|
@@ -517,11 +523,11 @@ async function installConnectorDriverDependencies(modelInfo, functionsDir, backe
|
|
|
517
523
|
if (!pipPkg)
|
|
518
524
|
return;
|
|
519
525
|
const reqPath = path.join(functionsPath, "requirements.txt");
|
|
520
|
-
if (
|
|
521
|
-
const existing =
|
|
526
|
+
if (session.fileExists(reqPath)) {
|
|
527
|
+
const existing = session.readFile(reqPath);
|
|
522
528
|
if (!existing.includes(pipPkg)) {
|
|
523
529
|
console.log(`\n📦 Adding ${pipPkg} to requirements.txt...`);
|
|
524
|
-
|
|
530
|
+
session.writeFile(reqPath, `${existing}\n${pipPkg}\n`, { ownership: "extension-point", generator: SCAFFOLD_GENERATOR });
|
|
525
531
|
console.log(`✅ ${pipPkg} added`);
|
|
526
532
|
}
|
|
527
533
|
}
|
|
@@ -529,17 +535,16 @@ async function installConnectorDriverDependencies(modelInfo, functionsDir, backe
|
|
|
529
535
|
/**
|
|
530
536
|
* コネクタモデル用 BFF ルート生成(操作制限に対応)
|
|
531
537
|
*/
|
|
532
|
-
async function generateConnectorBFFRoutesFiles(modelInfo, apiDir, sharedPackageName) {
|
|
538
|
+
async function generateConnectorBFFRoutesFiles(modelInfo, apiDir, sharedPackageName, session) {
|
|
533
539
|
console.log("\n🔌 Generating Connector BFF API routes...");
|
|
534
540
|
const modelCamel = (0, model_parser_1.toCamelCase)(modelInfo.name);
|
|
535
541
|
const operations = modelInfo.connectorConfig.operations;
|
|
536
542
|
const listRoutePath = path.join(process.cwd(), apiDir, modelCamel, "route.ts");
|
|
537
543
|
const detailRoutePath = path.join(process.cwd(), apiDir, modelCamel, "[id]", "route.ts");
|
|
538
|
-
fs.mkdirSync(path.dirname(listRoutePath), { recursive: true });
|
|
539
|
-
fs.mkdirSync(path.dirname(detailRoutePath), { recursive: true });
|
|
540
544
|
const routes = (0, nextjs_generator_1.generateConnectorBFFRoutes)(modelInfo, sharedPackageName, operations);
|
|
541
|
-
|
|
542
|
-
|
|
545
|
+
const meta = { ownership: "managed", generator: SCAFFOLD_GENERATOR, sourceModel: modelInfo.name };
|
|
546
|
+
session.writeFile(listRoutePath, routes.listRoute, meta);
|
|
547
|
+
session.writeFile(detailRoutePath, routes.detailRoute, meta);
|
|
543
548
|
console.log(`✅ Created: ${listRoutePath}`);
|
|
544
549
|
console.log(`✅ Created: ${detailRoutePath}`);
|
|
545
550
|
}
|
|
@@ -572,11 +577,11 @@ function describeFunctionsOutputPath(functionsDir, backendLanguage) {
|
|
|
572
577
|
}
|
|
573
578
|
return `${functionsDir}/blueprints/`;
|
|
574
579
|
}
|
|
575
|
-
function updatePythonFunctionRegistrations(functionAppPath, registration) {
|
|
576
|
-
if (!
|
|
580
|
+
function updatePythonFunctionRegistrations(functionAppPath, registration, session) {
|
|
581
|
+
if (!session.fileExists(functionAppPath)) {
|
|
577
582
|
throw new Error(`Python Functions entrypoint not found: ${functionAppPath}`);
|
|
578
583
|
}
|
|
579
|
-
const content =
|
|
584
|
+
const content = session.readFile(functionAppPath);
|
|
580
585
|
// Check if import line already exists (handles init-generated layout)
|
|
581
586
|
const importLine = registration.split("\n").find((l) => l.startsWith("from ") || l.startsWith("import "));
|
|
582
587
|
if (importLine && content.includes(importLine)) {
|
|
@@ -590,39 +595,31 @@ function updatePythonFunctionRegistrations(functionAppPath, registration) {
|
|
|
590
595
|
throw new Error(`Could not find scaffold registration marker in ${functionAppPath}`);
|
|
591
596
|
}
|
|
592
597
|
const updated = content.replace(marker, `${registration}\n${marker}`);
|
|
593
|
-
|
|
598
|
+
session.writeFile(functionAppPath, updated, { ownership: "extension-point", generator: SCAFFOLD_GENERATOR });
|
|
594
599
|
}
|
|
595
600
|
/**
|
|
596
601
|
* Next.js BFF API Routes を生成
|
|
597
602
|
*/
|
|
598
|
-
async function generateBFFRoutes(modelInfo, apiDir, sharedPackageName) {
|
|
603
|
+
async function generateBFFRoutes(modelInfo, apiDir, sharedPackageName, session) {
|
|
599
604
|
console.log("\n🔨 Generating Next.js BFF API routes...");
|
|
600
605
|
const modelCamel = modelInfo.name.charAt(0).toLowerCase() + modelInfo.name.slice(1);
|
|
601
606
|
// List route: app/api/[model]/route.ts
|
|
602
607
|
const listRoutePath = path.join(process.cwd(), apiDir, modelCamel, "route.ts");
|
|
603
608
|
// Detail route: app/api/[model]/[id]/route.ts
|
|
604
609
|
const detailRoutePath = path.join(process.cwd(), apiDir, modelCamel, "[id]", "route.ts");
|
|
605
|
-
// ディレクトリを作成
|
|
606
|
-
const listRouteDir = path.dirname(listRoutePath);
|
|
607
|
-
const detailRouteDir = path.dirname(detailRoutePath);
|
|
608
|
-
if (!fs.existsSync(listRouteDir)) {
|
|
609
|
-
fs.mkdirSync(listRouteDir, { recursive: true });
|
|
610
|
-
}
|
|
611
|
-
if (!fs.existsSync(detailRouteDir)) {
|
|
612
|
-
fs.mkdirSync(detailRouteDir, { recursive: true });
|
|
613
|
-
}
|
|
614
610
|
// コードを生成
|
|
615
611
|
const routes = (0, nextjs_generator_1.generateCompactBFFRoutes)(modelInfo, sharedPackageName);
|
|
616
612
|
// ファイルに書き込み
|
|
617
|
-
|
|
618
|
-
|
|
613
|
+
const meta = { ownership: "managed", generator: SCAFFOLD_GENERATOR, sourceModel: modelInfo.name };
|
|
614
|
+
session.writeFile(listRoutePath, routes.listRoute, meta);
|
|
615
|
+
session.writeFile(detailRoutePath, routes.detailRoute, meta);
|
|
619
616
|
console.log(`✅ Created: ${listRoutePath}`);
|
|
620
617
|
console.log(`✅ Created: ${detailRoutePath}`);
|
|
621
618
|
}
|
|
622
619
|
/**
|
|
623
620
|
* Generate Cosmos DB container Bicep file
|
|
624
621
|
*/
|
|
625
|
-
async function generateCosmosContainer(modelInfo) {
|
|
622
|
+
async function generateCosmosContainer(modelInfo, session = new file_session_1.FileOperationSession("commit")) {
|
|
626
623
|
console.log("\n🗄️ Generating Cosmos DB container Bicep file...");
|
|
627
624
|
const modelKebab = (0, model_parser_1.toKebabCase)(modelInfo.name);
|
|
628
625
|
const modelPascal = (0, model_parser_1.toPascalCase)(modelInfo.name);
|
|
@@ -633,12 +630,8 @@ async function generateCosmosContainer(modelInfo) {
|
|
|
633
630
|
console.log("ℹ️ infra directory not found. Skipping Cosmos DB container generation.");
|
|
634
631
|
return;
|
|
635
632
|
}
|
|
636
|
-
// Check if containers directory exists, if not create it
|
|
637
|
-
const containersDir = path.join(infraDir, "containers");
|
|
638
|
-
if (!fs.existsSync(containersDir)) {
|
|
639
|
-
fs.mkdirSync(containersDir, { recursive: true });
|
|
640
|
-
}
|
|
641
633
|
// Generate container Bicep file
|
|
634
|
+
const containersDir = path.join(infraDir, "containers");
|
|
642
635
|
const containerFileName = `${modelKebab}-container.bicep`;
|
|
643
636
|
const containerFilePath = path.join(containersDir, containerFileName);
|
|
644
637
|
const bicepContent = `@description('Cosmos DB account name')
|
|
@@ -698,22 +691,22 @@ resource container 'Microsoft.DocumentDB/databaseAccounts/sqlDatabases/container
|
|
|
698
691
|
output containerName string = container.name
|
|
699
692
|
`;
|
|
700
693
|
// Write Bicep file (overwrite if exists)
|
|
701
|
-
|
|
694
|
+
session.writeFile(containerFilePath, bicepContent, { ownership: "managed", generator: SCAFFOLD_GENERATOR, sourceModel: modelInfo.name });
|
|
702
695
|
console.log(`✅ Created: ${containerFilePath}`);
|
|
703
696
|
// Update main.bicep to include this container module
|
|
704
|
-
await updateMainBicepWithContainer(modelKebab, modelPascal);
|
|
697
|
+
await updateMainBicepWithContainer(modelKebab, modelPascal, session);
|
|
705
698
|
}
|
|
706
699
|
/**
|
|
707
700
|
* Update main.bicep to include new container module
|
|
708
701
|
*/
|
|
709
|
-
async function updateMainBicepWithContainer(modelKebab, modelPascal) {
|
|
702
|
+
async function updateMainBicepWithContainer(modelKebab, modelPascal, session) {
|
|
710
703
|
const cwd = process.cwd();
|
|
711
704
|
const mainBicepPath = path.join(cwd, "infra", "main.bicep");
|
|
712
|
-
if (!
|
|
705
|
+
if (!session.fileExists(mainBicepPath)) {
|
|
713
706
|
console.log("ℹ️ main.bicep not found. Please manually add the container module.");
|
|
714
707
|
return;
|
|
715
708
|
}
|
|
716
|
-
let mainBicepContent =
|
|
709
|
+
let mainBicepContent = session.readFile(mainBicepPath);
|
|
717
710
|
// Check if container module already exists
|
|
718
711
|
const containerModuleName = `${modelPascal.charAt(0).toLowerCase()}${modelPascal.slice(1)}Container`;
|
|
719
712
|
if (mainBicepContent.includes(`module ${containerModuleName}`)) {
|
|
@@ -758,13 +751,13 @@ module ${containerModuleName} 'containers/${modelKebab}-container.bicep' = {
|
|
|
758
751
|
mainBicepContent.slice(0, insertPosition) +
|
|
759
752
|
containerModule +
|
|
760
753
|
mainBicepContent.slice(insertPosition);
|
|
761
|
-
|
|
754
|
+
session.writeFile(mainBicepPath, mainBicepContent, { ownership: "extension-point", generator: SCAFFOLD_GENERATOR });
|
|
762
755
|
console.log(`✅ Added container module to main.bicep`);
|
|
763
756
|
}
|
|
764
757
|
/**
|
|
765
758
|
* Generate UI components (list, detail, form, create, edit pages)
|
|
766
759
|
*/
|
|
767
|
-
async function generateUIComponents(modelInfo, sharedPackageName, authOptions) {
|
|
760
|
+
async function generateUIComponents(modelInfo, sharedPackageName, authOptions, session = new file_session_1.FileOperationSession("commit")) {
|
|
768
761
|
console.log("\n🎨 Generating UI components...");
|
|
769
762
|
const modelKebab = (0, model_parser_1.toKebabCase)(modelInfo.name);
|
|
770
763
|
const modelName = modelInfo.name;
|
|
@@ -775,12 +768,6 @@ async function generateUIComponents(modelInfo, sharedPackageName, authOptions) {
|
|
|
775
768
|
const newDir = path.join(modelDir, "new");
|
|
776
769
|
const idDir = path.join(modelDir, "[id]");
|
|
777
770
|
const editDir = path.join(idDir, "edit");
|
|
778
|
-
// Create directories
|
|
779
|
-
[componentsDir, newDir, editDir].forEach(dir => {
|
|
780
|
-
if (!fs.existsSync(dir)) {
|
|
781
|
-
fs.mkdirSync(dir, { recursive: true });
|
|
782
|
-
}
|
|
783
|
-
});
|
|
784
771
|
// Generate and write files
|
|
785
772
|
const listPage = (0, ui_generator_1.generateListPage)(modelInfo, sharedPackageName, authOptions);
|
|
786
773
|
const detailPage = (0, ui_generator_1.generateDetailPage)(modelInfo, sharedPackageName, authOptions);
|
|
@@ -788,13 +775,14 @@ async function generateUIComponents(modelInfo, sharedPackageName, authOptions) {
|
|
|
788
775
|
const newPage = (0, ui_generator_1.generateNewPage)(modelInfo, authOptions);
|
|
789
776
|
const editPage = (0, ui_generator_1.generateEditPage)(modelInfo, sharedPackageName, authOptions);
|
|
790
777
|
const authLayout = (0, ui_generator_1.generateAuthLayout)(modelInfo, authOptions);
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
778
|
+
const meta = { ownership: "managed", generator: SCAFFOLD_GENERATOR, sourceModel: modelInfo.name };
|
|
779
|
+
session.writeFile(path.join(modelDir, "page.tsx"), listPage, meta);
|
|
780
|
+
session.writeFile(path.join(idDir, "page.tsx"), detailPage, meta);
|
|
781
|
+
session.writeFile(path.join(componentsDir, `${modelName}Form.tsx`), formComponent, meta);
|
|
782
|
+
session.writeFile(path.join(newDir, "page.tsx"), newPage, meta);
|
|
783
|
+
session.writeFile(path.join(editDir, "page.tsx"), editPage, meta);
|
|
796
784
|
if (authLayout) {
|
|
797
|
-
|
|
785
|
+
session.writeFile(path.join(modelDir, "layout.tsx"), authLayout, meta);
|
|
798
786
|
}
|
|
799
787
|
console.log(`✅ Created: ${path.join(modelDir, "page.tsx")}`);
|
|
800
788
|
console.log(`✅ Created: ${path.join(idDir, "page.tsx")}`);
|
|
@@ -808,18 +796,18 @@ async function generateUIComponents(modelInfo, sharedPackageName, authOptions) {
|
|
|
808
796
|
/**
|
|
809
797
|
* Update navigation menu on the homepage
|
|
810
798
|
*/
|
|
811
|
-
async function updateNavigationMenu(modelInfo) {
|
|
799
|
+
async function updateNavigationMenu(modelInfo, session) {
|
|
812
800
|
console.log("\n📋 Updating navigation menu...");
|
|
813
801
|
const modelKebab = (0, model_parser_1.toKebabCase)(modelInfo.name);
|
|
814
802
|
const cwd = process.cwd();
|
|
815
803
|
// Update scaffold config
|
|
816
804
|
const configPath = path.join(cwd, "lib", "scaffold-config.ts");
|
|
817
|
-
if (!
|
|
805
|
+
if (!session.fileExists(configPath)) {
|
|
818
806
|
console.log("⚠️ scaffold-config.ts not found. Skipping navigation menu update.");
|
|
819
807
|
return;
|
|
820
808
|
}
|
|
821
809
|
// Read existing config
|
|
822
|
-
const configContent =
|
|
810
|
+
const configContent = session.readFile(configPath);
|
|
823
811
|
// Parse models array - extract each model entry
|
|
824
812
|
const models = [];
|
|
825
813
|
const modelsMatch = configContent.match(/models:\s*\[([\s\S]*?)\]\s*as\s*ScaffoldModel\[\]/);
|
|
@@ -860,7 +848,7 @@ ${models.map(m => ` { name: '${m.name}', path: '${m.path}', label: '${m.label
|
|
|
860
848
|
] as ScaffoldModel[]
|
|
861
849
|
};
|
|
862
850
|
`;
|
|
863
|
-
|
|
851
|
+
session.writeFile(configPath, newConfigContent, { ownership: "extension-point", generator: SCAFFOLD_GENERATOR });
|
|
864
852
|
console.log(`✅ Added ${modelInfo.name} to navigation menu`);
|
|
865
853
|
}
|
|
866
854
|
//# sourceMappingURL=scaffold.js.map
|