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