@specverse/engines 4.1.5 → 4.1.7
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/libs/instance-factories/applications/templates/generic/backend-env-generator.js +22 -0
- package/dist/libs/instance-factories/applications/templates/generic/backend-package-json-generator.js +66 -0
- package/dist/libs/instance-factories/applications/templates/generic/backend-tsconfig-generator.js +54 -0
- package/dist/libs/instance-factories/applications/templates/generic/main-generator.js +290 -0
- package/dist/libs/instance-factories/applications/templates/react/_view-components-source.js +530 -0
- package/dist/libs/instance-factories/applications/templates/react/api-client-generator.js +437 -0
- package/dist/libs/instance-factories/applications/templates/react/api-types-generator.js +146 -0
- package/dist/libs/instance-factories/applications/templates/react/app-tsx-generator.js +73 -0
- package/dist/libs/instance-factories/applications/templates/react/env-example-generator.js +18 -0
- package/dist/libs/instance-factories/applications/templates/react/field-helpers-generator.js +99 -0
- package/dist/libs/instance-factories/applications/templates/react/gitignore-generator.js +35 -0
- package/dist/libs/instance-factories/applications/templates/react/index-css-generator.js +9 -0
- package/dist/libs/instance-factories/applications/templates/react/index-html-generator.js +23 -0
- package/dist/libs/instance-factories/applications/templates/react/main-tsx-generator.js +29 -0
- package/dist/libs/instance-factories/applications/templates/react/package-json-generator.js +49 -0
- package/dist/libs/instance-factories/applications/templates/react/pattern-adapter-generator.js +156 -0
- package/dist/libs/instance-factories/applications/templates/react/react-pattern-adapter.js +935 -0
- package/dist/libs/instance-factories/applications/templates/react/relationship-field-generator.js +143 -0
- package/dist/libs/instance-factories/applications/templates/react/runtime-app-tsx-generator.js +101 -0
- package/dist/libs/instance-factories/applications/templates/react/runtime-package-json-generator.js +50 -0
- package/dist/libs/instance-factories/applications/templates/react/tailwind-adapter-generator.js +646 -0
- package/dist/libs/instance-factories/applications/templates/react/tailwind-adapter-wrapper-generator.js +65 -0
- package/dist/libs/instance-factories/applications/templates/react/tsconfig-generator.js +28 -0
- package/dist/libs/instance-factories/applications/templates/react/use-api-hooks-generator.js +132 -0
- package/dist/libs/instance-factories/applications/templates/react/view-dashboard-generator.js +143 -0
- package/dist/libs/instance-factories/applications/templates/react/view-detail-generator.js +143 -0
- package/dist/libs/instance-factories/applications/templates/react/view-form-generator.js +355 -0
- package/dist/libs/instance-factories/applications/templates/react/view-list-generator.js +91 -0
- package/dist/libs/instance-factories/applications/templates/react/view-router-generator.js +79 -0
- package/dist/libs/instance-factories/applications/templates/react/vite-config-generator.js +42 -0
- package/dist/libs/instance-factories/cli/templates/commander/cli-bin-wrapper-generator.js +11 -0
- package/dist/libs/instance-factories/cli/templates/commander/cli-entry-generator.js +111 -0
- package/dist/libs/instance-factories/cli/templates/commander/command-generator.js +928 -0
- package/dist/libs/instance-factories/communication/templates/eventemitter/bus-generator.js +83 -0
- package/dist/libs/instance-factories/communication/templates/eventemitter/publisher-generator.js +91 -0
- package/dist/libs/instance-factories/communication/templates/eventemitter/subscriber-generator.js +86 -0
- package/dist/libs/instance-factories/controllers/templates/fastify/meta-routes-generator.js +93 -0
- package/dist/libs/instance-factories/controllers/templates/fastify/routes-generator.js +280 -0
- package/dist/libs/instance-factories/controllers/templates/fastify/server-generator.js +125 -0
- package/dist/libs/instance-factories/infrastructure/templates/docker-k8s/infrastructure-generator.js +25 -0
- package/dist/libs/instance-factories/orms/templates/prisma/schema-generator.js +371 -0
- package/dist/libs/instance-factories/orms/templates/prisma/services-generator.js +266 -0
- package/dist/libs/instance-factories/scaffolding/templates/generic/env-example-generator.js +51 -0
- package/dist/libs/instance-factories/scaffolding/templates/generic/env-generator.js +61 -0
- package/dist/libs/instance-factories/scaffolding/templates/generic/gitignore-generator.js +59 -0
- package/dist/libs/instance-factories/scaffolding/templates/generic/package-json-generator.js +126 -0
- package/dist/libs/instance-factories/scaffolding/templates/generic/readme-generator.js +159 -0
- package/dist/libs/instance-factories/scaffolding/templates/generic/tsconfig-generator.js +56 -0
- package/dist/libs/instance-factories/scaffolding/templates/generic/tsconfig-react-generator.js +37 -0
- package/dist/libs/instance-factories/sdks/templates/python/sdk-generator.js +29 -0
- package/dist/libs/instance-factories/sdks/templates/typescript/sdk-generator.js +28 -0
- package/dist/libs/instance-factories/services/templates/memory/generate-interpreter.js +14 -0
- package/dist/libs/instance-factories/services/templates/memory/step-conventions-memory.js +415 -0
- package/dist/libs/instance-factories/services/templates/prisma/behavior-generator.js +177 -0
- package/dist/libs/instance-factories/services/templates/prisma/controller-generator.js +413 -0
- package/dist/libs/instance-factories/services/templates/prisma/service-generator.js +243 -0
- package/dist/libs/instance-factories/services/templates/prisma/step-conventions.js +264 -0
- package/dist/libs/instance-factories/services/templates/shared-patterns.js +24 -0
- package/dist/libs/instance-factories/shared/path-resolver.js +59 -0
- package/dist/libs/instance-factories/storage/templates/mongodb/config-generator.js +13 -0
- package/dist/libs/instance-factories/storage/templates/mongodb/docker-generator.js +16 -0
- package/dist/libs/instance-factories/storage/templates/postgresql/config-generator.js +45 -0
- package/dist/libs/instance-factories/storage/templates/postgresql/docker-generator.js +46 -0
- package/dist/libs/instance-factories/storage/templates/redis/config-generator.js +14 -0
- package/dist/libs/instance-factories/storage/templates/redis/docker-generator.js +16 -0
- package/dist/libs/instance-factories/test-generation.js +145 -0
- package/dist/libs/instance-factories/testing/templates/vitest/tests-generator.js +30 -0
- package/dist/libs/instance-factories/tools/templates/mcp/mcp-server-generator.js +149 -0
- package/dist/libs/instance-factories/tools/templates/mcp/static/src/controllers/MCPServerController.js +232 -0
- package/dist/libs/instance-factories/tools/templates/mcp/static/src/events/EventEmitter.js +49 -0
- package/dist/libs/instance-factories/tools/templates/mcp/static/src/index.js +18 -0
- package/dist/libs/instance-factories/tools/templates/mcp/static/src/interfaces/ResourceProvider.js +0 -0
- package/dist/libs/instance-factories/tools/templates/mcp/static/src/models/LibrarySuggestion.js +97 -0
- package/dist/libs/instance-factories/tools/templates/mcp/static/src/models/SpecVerseResource.js +64 -0
- package/dist/libs/instance-factories/tools/templates/mcp/static/src/server/mcp-server.js +182 -0
- package/dist/libs/instance-factories/tools/templates/mcp/static/src/services/CLIProxyService.js +1210 -0
- package/dist/libs/instance-factories/tools/templates/mcp/static/src/services/EmbeddedResourcesAdapter.js +172 -0
- package/dist/libs/instance-factories/tools/templates/mcp/static/src/services/EntityModuleService.js +240 -0
- package/dist/libs/instance-factories/tools/templates/mcp/static/src/services/HybridResourcesProvider.js +147 -0
- package/dist/libs/instance-factories/tools/templates/mcp/static/src/services/LibraryToolsService.js +281 -0
- package/dist/libs/instance-factories/tools/templates/mcp/static/src/services/OrchestratorBridge.js +409 -0
- package/dist/libs/instance-factories/tools/templates/mcp/static/src/services/OrchestratorToolsService.js +414 -0
- package/dist/libs/instance-factories/tools/templates/mcp/static/src/services/PromptToolsService.js +467 -0
- package/dist/libs/instance-factories/tools/templates/mcp/static/src/services/ResourcesProviderService.js +135 -0
- package/dist/libs/instance-factories/tools/templates/mcp/static/src/types/index.js +0 -0
- package/dist/libs/instance-factories/tools/templates/vscode/static/extension.js +965 -0
- package/dist/libs/instance-factories/tools/templates/vscode/vscode-extension-generator.js +238 -0
- package/dist/libs/instance-factories/validation/templates/zod/validation-generator.js +25 -0
- package/dist/libs/instance-factories/views/index.js +48 -0
- package/dist/libs/instance-factories/views/templates/react/adapters/antd-adapter.js +742 -0
- package/dist/libs/instance-factories/views/templates/react/adapters/mui-adapter.js +824 -0
- package/dist/libs/instance-factories/views/templates/react/adapters/shadcn-adapter.js +719 -0
- package/dist/libs/instance-factories/views/templates/react/app-generator.js +45 -0
- package/dist/libs/instance-factories/views/templates/react/components-generator.js +779 -0
- package/dist/libs/instance-factories/views/templates/react/forms-generator.js +285 -0
- package/dist/libs/instance-factories/views/templates/react/frontend-package-json-generator.js +46 -0
- package/dist/libs/instance-factories/views/templates/react/hooks-generator.js +111 -0
- package/dist/libs/instance-factories/views/templates/react/index-css-generator.js +9 -0
- package/dist/libs/instance-factories/views/templates/react/index-html-generator.js +23 -0
- package/dist/libs/instance-factories/views/templates/react/main-tsx-generator.js +21 -0
- package/dist/libs/instance-factories/views/templates/react/react-component-generator.js +299 -0
- package/dist/libs/instance-factories/views/templates/react/router-generator.js +136 -0
- package/dist/libs/instance-factories/views/templates/react/router-generic-generator.js +107 -0
- package/dist/libs/instance-factories/views/templates/react/shared-utils-generator.js +179 -0
- package/dist/libs/instance-factories/views/templates/react/spec-json-generator.js +7 -0
- package/dist/libs/instance-factories/views/templates/react/types-generator.js +56 -0
- package/dist/libs/instance-factories/views/templates/react/views-metadata-generator.js +27 -0
- package/dist/libs/instance-factories/views/templates/react/vite-config-generator.js +29 -0
- package/dist/libs/instance-factories/views/templates/runtime/runtime-view-renderer.js +261 -0
- package/dist/libs/instance-factories/views/templates/shared/adapter-types.js +34 -0
- package/dist/libs/instance-factories/views/templates/shared/atomic-components-registry.js +800 -0
- package/dist/libs/instance-factories/views/templates/shared/base-generator.js +305 -0
- package/dist/libs/instance-factories/views/templates/shared/component-metadata.js +517 -0
- package/dist/libs/instance-factories/views/templates/shared/composite-pattern-types.js +0 -0
- package/dist/libs/instance-factories/views/templates/shared/composite-patterns.js +445 -0
- package/dist/libs/instance-factories/views/templates/shared/index.js +80 -0
- package/dist/libs/instance-factories/views/templates/shared/pattern-validator.js +210 -0
- package/dist/libs/instance-factories/views/templates/shared/property-mapper.js +492 -0
- package/dist/libs/instance-factories/views/templates/shared/syntax-mapper.js +321 -0
- package/dist/realize/index.js +36 -12
- package/dist/realize/index.js.map +1 -1
- package/package.json +3 -2
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
function generateBackendEnv(context) {
|
|
2
|
+
const { spec, manifest } = context;
|
|
3
|
+
const projectName = (spec.metadata?.component || "app").toLowerCase().replace(/\s+/g, "-");
|
|
4
|
+
const dbName = `spv_${projectName}_dev`;
|
|
5
|
+
const dbUser = process.env.USER || "postgres";
|
|
6
|
+
const port = manifest?.configuration?.environments?.development?.server?.port || 3e3;
|
|
7
|
+
return `# Backend Environment Configuration
|
|
8
|
+
# Database
|
|
9
|
+
DATABASE_URL="postgresql://${dbUser}:@localhost:5432/${dbName}"
|
|
10
|
+
|
|
11
|
+
# API Configuration
|
|
12
|
+
PORT=${port}
|
|
13
|
+
HOST=0.0.0.0
|
|
14
|
+
NODE_ENV=development
|
|
15
|
+
|
|
16
|
+
# CORS
|
|
17
|
+
CORS_ORIGINS="http://localhost:5173"
|
|
18
|
+
`;
|
|
19
|
+
}
|
|
20
|
+
export {
|
|
21
|
+
generateBackendEnv as default
|
|
22
|
+
};
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
function generateBackendPackageJson(context) {
|
|
2
|
+
const { spec } = context;
|
|
3
|
+
const appName = (spec.metadata?.component || "app").toLowerCase().replace(/\s+/g, "-");
|
|
4
|
+
const pkg = {
|
|
5
|
+
name: `${appName}-backend`,
|
|
6
|
+
version: spec.metadata?.version || "1.0.0",
|
|
7
|
+
description: `Backend API for ${spec.metadata?.component || "application"}`,
|
|
8
|
+
type: "module",
|
|
9
|
+
bin: {
|
|
10
|
+
[appName]: "./bin/cli.mjs"
|
|
11
|
+
},
|
|
12
|
+
scripts: {
|
|
13
|
+
// Development
|
|
14
|
+
"dev": "tsx watch src/main.ts",
|
|
15
|
+
"dev:debug": "tsx watch --inspect src/main.ts",
|
|
16
|
+
// Build
|
|
17
|
+
"build": "tsc",
|
|
18
|
+
"build:watch": "tsc --watch",
|
|
19
|
+
// Production
|
|
20
|
+
"start": "node dist/main.js",
|
|
21
|
+
// Database
|
|
22
|
+
"db:setup": "prisma generate && prisma db push",
|
|
23
|
+
"db:generate": "prisma generate",
|
|
24
|
+
"db:push": "prisma db push",
|
|
25
|
+
"db:migrate": "prisma migrate dev",
|
|
26
|
+
"db:studio": "prisma studio",
|
|
27
|
+
"db:seed": "tsx prisma/seed.ts",
|
|
28
|
+
// Testing
|
|
29
|
+
"test": "vitest run --passWithNoTests",
|
|
30
|
+
"test:watch": "vitest watch",
|
|
31
|
+
"test:coverage": "vitest --coverage",
|
|
32
|
+
// Linting
|
|
33
|
+
"lint": "eslint src --ext .ts",
|
|
34
|
+
"lint:fix": "eslint src --ext .ts --fix",
|
|
35
|
+
// Type checking
|
|
36
|
+
"typecheck": "tsc --noEmit"
|
|
37
|
+
},
|
|
38
|
+
dependencies: {
|
|
39
|
+
"@prisma/client": "^5.7.0",
|
|
40
|
+
"fastify": "^4.25.0",
|
|
41
|
+
"@fastify/cors": "^8.4.0",
|
|
42
|
+
"@fastify/helmet": "^11.1.1",
|
|
43
|
+
"@fastify/rate-limit": "^9.1.0",
|
|
44
|
+
"zod": "^3.22.0",
|
|
45
|
+
"dotenv": "^16.3.0"
|
|
46
|
+
},
|
|
47
|
+
devDependencies: {
|
|
48
|
+
"typescript": "^5.3.0",
|
|
49
|
+
"@types/node": "^20.10.0",
|
|
50
|
+
"tsx": "^4.7.0",
|
|
51
|
+
"prisma": "^5.7.0",
|
|
52
|
+
"vitest": "^1.0.0",
|
|
53
|
+
"@vitest/coverage-v8": "^1.0.0",
|
|
54
|
+
"eslint": "^8.55.0",
|
|
55
|
+
"@typescript-eslint/eslint-plugin": "^6.15.0",
|
|
56
|
+
"@typescript-eslint/parser": "^6.15.0"
|
|
57
|
+
},
|
|
58
|
+
engines: {
|
|
59
|
+
node: ">=18.0.0"
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
return JSON.stringify(pkg, null, 2);
|
|
63
|
+
}
|
|
64
|
+
export {
|
|
65
|
+
generateBackendPackageJson as default
|
|
66
|
+
};
|
package/dist/libs/instance-factories/applications/templates/generic/backend-tsconfig-generator.js
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
function generateBackendTsConfig(context) {
|
|
2
|
+
const config = {
|
|
3
|
+
compilerOptions: {
|
|
4
|
+
// Target and Module
|
|
5
|
+
target: "ES2022",
|
|
6
|
+
module: "ESNext",
|
|
7
|
+
lib: ["ES2022"],
|
|
8
|
+
moduleResolution: "node",
|
|
9
|
+
// Output
|
|
10
|
+
outDir: "./dist",
|
|
11
|
+
rootDir: "./src",
|
|
12
|
+
// Strict Type Checking
|
|
13
|
+
strict: true,
|
|
14
|
+
noImplicitAny: true,
|
|
15
|
+
strictNullChecks: true,
|
|
16
|
+
strictFunctionTypes: true,
|
|
17
|
+
strictBindCallApply: true,
|
|
18
|
+
strictPropertyInitialization: true,
|
|
19
|
+
noImplicitThis: true,
|
|
20
|
+
alwaysStrict: true,
|
|
21
|
+
// Additional Checks
|
|
22
|
+
noUnusedLocals: true,
|
|
23
|
+
noUnusedParameters: true,
|
|
24
|
+
noImplicitReturns: true,
|
|
25
|
+
noFallthroughCasesInSwitch: true,
|
|
26
|
+
noUncheckedIndexedAccess: true,
|
|
27
|
+
// Module Resolution
|
|
28
|
+
esModuleInterop: true,
|
|
29
|
+
allowSyntheticDefaultImports: true,
|
|
30
|
+
resolveJsonModule: true,
|
|
31
|
+
isolatedModules: true,
|
|
32
|
+
// Source Maps
|
|
33
|
+
sourceMap: true,
|
|
34
|
+
declaration: true,
|
|
35
|
+
declarationMap: true,
|
|
36
|
+
// Skip lib check for faster builds
|
|
37
|
+
skipLibCheck: true,
|
|
38
|
+
// Emit
|
|
39
|
+
removeComments: false,
|
|
40
|
+
importHelpers: true,
|
|
41
|
+
// Experimental
|
|
42
|
+
experimentalDecorators: true,
|
|
43
|
+
emitDecoratorMetadata: true,
|
|
44
|
+
// Types
|
|
45
|
+
types: ["node"]
|
|
46
|
+
},
|
|
47
|
+
include: ["src/**/*"],
|
|
48
|
+
exclude: ["node_modules", "dist", "**/*.test.ts", "**/*.spec.ts"]
|
|
49
|
+
};
|
|
50
|
+
return JSON.stringify(config, null, 2);
|
|
51
|
+
}
|
|
52
|
+
export {
|
|
53
|
+
generateBackendTsConfig as default
|
|
54
|
+
};
|
|
@@ -0,0 +1,290 @@
|
|
|
1
|
+
function generateMain(context) {
|
|
2
|
+
const { spec, manifest } = context;
|
|
3
|
+
let framework = "fastify";
|
|
4
|
+
if (manifest.capabilityMappings) {
|
|
5
|
+
const apiMapping = manifest.capabilityMappings.find(
|
|
6
|
+
(m) => m.capability === "api.rest"
|
|
7
|
+
);
|
|
8
|
+
if (apiMapping?.instanceFactory) {
|
|
9
|
+
const factoryName = apiMapping.instanceFactory.toLowerCase();
|
|
10
|
+
if (factoryName.includes("fastify")) framework = "fastify";
|
|
11
|
+
else if (factoryName.includes("express")) framework = "express";
|
|
12
|
+
else if (factoryName.includes("nestjs")) framework = "nestjs";
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
switch (framework) {
|
|
16
|
+
case "fastify":
|
|
17
|
+
return generateFastifyMain(spec);
|
|
18
|
+
case "express":
|
|
19
|
+
return generateExpressMain(spec);
|
|
20
|
+
case "nestjs":
|
|
21
|
+
return generateNestJSMain(spec);
|
|
22
|
+
default:
|
|
23
|
+
throw new Error(`Unsupported framework: ${framework}`);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
function generateFastifyMain(spec) {
|
|
27
|
+
const controllers = spec.controllers || [];
|
|
28
|
+
const services = spec.services || [];
|
|
29
|
+
const routeImports = controllers.map(
|
|
30
|
+
(ctrl) => `import ${ctrl.name.replace("Controller", "")}Routes from './routes/${ctrl.name}.js';`
|
|
31
|
+
).join("\n");
|
|
32
|
+
const metaRoutesImport = ``;
|
|
33
|
+
const serviceImports = services.map(
|
|
34
|
+
(svc) => `import { ${svc.name} } from './services/${svc.name}.js';`
|
|
35
|
+
).join("\n");
|
|
36
|
+
const controllerImports = controllers.map(
|
|
37
|
+
(ctrl) => `import { ${ctrl.name} } from './controllers/${ctrl.name}.js';`
|
|
38
|
+
).join("\n");
|
|
39
|
+
const serviceInstantiations = services.map(
|
|
40
|
+
(svc) => ` const ${svc.name.charAt(0).toLowerCase() + svc.name.slice(1)} = new ${svc.name}(prisma);`
|
|
41
|
+
).join("\n");
|
|
42
|
+
const controllerInstantiations = controllers.map(
|
|
43
|
+
(ctrl) => ` const ${ctrl.name.charAt(0).toLowerCase() + ctrl.name.slice(1)} = new ${ctrl.name}();`
|
|
44
|
+
).join("\n");
|
|
45
|
+
const serviceMap = services.map(
|
|
46
|
+
(svc) => ` ${svc.name}: ${svc.name.charAt(0).toLowerCase() + svc.name.slice(1)}`
|
|
47
|
+
).join(",\n");
|
|
48
|
+
const controllerMap = controllers.map(
|
|
49
|
+
(ctrl) => ` ${ctrl.name}: ${ctrl.name.charAt(0).toLowerCase() + ctrl.name.slice(1)}`
|
|
50
|
+
).join(",\n");
|
|
51
|
+
const routeRegistrations = controllers.map((ctrl) => {
|
|
52
|
+
let prefix = ctrl.basePath;
|
|
53
|
+
if (!prefix) {
|
|
54
|
+
const modelName = ctrl.model || ctrl.name.replace("Controller", "");
|
|
55
|
+
const pluralModel = modelName.toLowerCase() + "s";
|
|
56
|
+
prefix = `/api/${pluralModel}`;
|
|
57
|
+
}
|
|
58
|
+
return ` await app.register(${ctrl.name.replace("Controller", "")}Routes, {
|
|
59
|
+
prefix: '${prefix}',
|
|
60
|
+
controllers: {
|
|
61
|
+
${ctrl.name}: ${ctrl.name.charAt(0).toLowerCase() + ctrl.name.slice(1)}
|
|
62
|
+
},
|
|
63
|
+
services: services
|
|
64
|
+
});`;
|
|
65
|
+
}).join("\n");
|
|
66
|
+
const specJson = JSON.stringify(spec, null, 2).replace(/\\/g, "\\\\").replace(/`/g, "\\`").replace(/\$/g, "\\$");
|
|
67
|
+
return `import Fastify from 'fastify';
|
|
68
|
+
import cors from '@fastify/cors';
|
|
69
|
+
import { PrismaClient } from '@prisma/client';
|
|
70
|
+
${routeImports}
|
|
71
|
+
${metaRoutesImport}
|
|
72
|
+
${serviceImports}
|
|
73
|
+
${controllerImports}
|
|
74
|
+
|
|
75
|
+
// Embedded specification for /api/spec endpoint
|
|
76
|
+
const spec = ${specJson};
|
|
77
|
+
|
|
78
|
+
const app = Fastify({
|
|
79
|
+
logger: {
|
|
80
|
+
level: process.env.LOG_LEVEL || 'info'
|
|
81
|
+
}
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
const prisma = new PrismaClient();
|
|
85
|
+
|
|
86
|
+
async function start() {
|
|
87
|
+
try {
|
|
88
|
+
// Initialize services and controllers
|
|
89
|
+
${serviceInstantiations}
|
|
90
|
+
${controllerInstantiations}
|
|
91
|
+
${controllers.length > 0 ? `
|
|
92
|
+
const services = {
|
|
93
|
+
${serviceMap}
|
|
94
|
+
};` : ""}
|
|
95
|
+
|
|
96
|
+
// Register plugins
|
|
97
|
+
await app.register(cors, {
|
|
98
|
+
origin: true,
|
|
99
|
+
credentials: true
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
// Spec endpoint \u2014 serves the specification for the runtime frontend
|
|
103
|
+
app.get('/api/spec', async () => spec);
|
|
104
|
+
|
|
105
|
+
// Runtime info endpoint \u2014 models and controllers for DevShell
|
|
106
|
+
app.get('/api/runtime/info', async () => ({
|
|
107
|
+
controllers: [${controllers.map((c) => `'${c.name}'`).join(", ")}],
|
|
108
|
+
models: [${controllers.map((c) => `'${c.model || c.name.replace("Controller", "")}'`).join(", ")}],
|
|
109
|
+
events: [],
|
|
110
|
+
services: []
|
|
111
|
+
}));
|
|
112
|
+
|
|
113
|
+
// Register routes
|
|
114
|
+
// MetaRoutes disabled for now - enable when meta-routes generator is integrated
|
|
115
|
+
// await app.register(MetaRoutes, {
|
|
116
|
+
// prefix: '/api'
|
|
117
|
+
// });
|
|
118
|
+
${routeRegistrations}
|
|
119
|
+
|
|
120
|
+
const preferredPort = process.env.PORT ? parseInt(process.env.PORT) : 3000;
|
|
121
|
+
const host = process.env.HOST || '0.0.0.0';
|
|
122
|
+
|
|
123
|
+
// Try to start server with automatic port fallback
|
|
124
|
+
let port = preferredPort;
|
|
125
|
+
let started = false;
|
|
126
|
+
const maxAttempts = 10;
|
|
127
|
+
|
|
128
|
+
for (let i = 0; i < maxAttempts && !started; i++) {
|
|
129
|
+
port = preferredPort + i;
|
|
130
|
+
try {
|
|
131
|
+
await app.listen({ port, host });
|
|
132
|
+
started = true;
|
|
133
|
+
|
|
134
|
+
if (i > 0) {
|
|
135
|
+
console.log(\`\u26A0\uFE0F Port \${preferredPort} was in use, using \${port} instead\`);
|
|
136
|
+
}
|
|
137
|
+
console.log(\`\u{1F680} Server running on http://\${host}:\${port}\`);
|
|
138
|
+
console.log(\`\u{1F4DA} Environment: \${process.env.NODE_ENV || 'development'}\`);
|
|
139
|
+
} catch (err: any) {
|
|
140
|
+
if (err.code === 'EADDRINUSE' && i < maxAttempts - 1) {
|
|
141
|
+
// Port in use, try next port
|
|
142
|
+
continue;
|
|
143
|
+
} else {
|
|
144
|
+
// Different error or ran out of attempts
|
|
145
|
+
throw err;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
if (!started) {
|
|
151
|
+
throw new Error(\`Could not find available port in range \${preferredPort}-\${preferredPort + maxAttempts - 1}\`);
|
|
152
|
+
}
|
|
153
|
+
} catch (err) {
|
|
154
|
+
app.log.error(err);
|
|
155
|
+
await prisma.$disconnect();
|
|
156
|
+
process.exit(1);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// Handle graceful shutdown
|
|
161
|
+
process.on('SIGINT', async () => {
|
|
162
|
+
console.log('\\n\u{1F44B} Shutting down gracefully...');
|
|
163
|
+
await app.close();
|
|
164
|
+
await prisma.$disconnect();
|
|
165
|
+
process.exit(0);
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
process.on('SIGTERM', async () => {
|
|
169
|
+
console.log('\\n\u{1F44B} Shutting down gracefully...');
|
|
170
|
+
await app.close();
|
|
171
|
+
await prisma.$disconnect();
|
|
172
|
+
process.exit(0);
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
start();
|
|
176
|
+
`;
|
|
177
|
+
}
|
|
178
|
+
function generateExpressMain(spec) {
|
|
179
|
+
const controllers = spec.controllers || [];
|
|
180
|
+
const routeImports = controllers.map(
|
|
181
|
+
(ctrl) => `import ${ctrl.name.replace("Controller", "")}Router from './routes/${ctrl.name}.js';`
|
|
182
|
+
).join("\n");
|
|
183
|
+
const routeRegistrations = controllers.map(
|
|
184
|
+
(ctrl) => `app.use('${ctrl.basePath || "/api"}', ${ctrl.name.replace("Controller", "")}Router);`
|
|
185
|
+
).join("\n");
|
|
186
|
+
return `import express from 'express';
|
|
187
|
+
import cors from 'cors';
|
|
188
|
+
${routeImports}
|
|
189
|
+
|
|
190
|
+
const app = express();
|
|
191
|
+
|
|
192
|
+
// Middleware
|
|
193
|
+
app.use(cors());
|
|
194
|
+
app.use(express.json());
|
|
195
|
+
|
|
196
|
+
// Routes
|
|
197
|
+
${routeRegistrations}
|
|
198
|
+
|
|
199
|
+
async function start() {
|
|
200
|
+
const preferredPort = process.env.PORT ? parseInt(process.env.PORT) : 3000;
|
|
201
|
+
const host = process.env.HOST || '0.0.0.0';
|
|
202
|
+
const maxAttempts = 10;
|
|
203
|
+
|
|
204
|
+
// Try to start server with automatic port fallback
|
|
205
|
+
for (let i = 0; i < maxAttempts; i++) {
|
|
206
|
+
const port = preferredPort + i;
|
|
207
|
+
try {
|
|
208
|
+
await new Promise((resolve, reject) => {
|
|
209
|
+
const server = app.listen(port, host, () => {
|
|
210
|
+
if (i > 0) {
|
|
211
|
+
console.log(\`\u26A0\uFE0F Port \${preferredPort} was in use, using \${port} instead\`);
|
|
212
|
+
}
|
|
213
|
+
console.log(\`\u{1F680} Server running on http://\${host}:\${port}\`);
|
|
214
|
+
console.log(\`\u{1F4DA} Environment: \${process.env.NODE_ENV || 'development'}\`);
|
|
215
|
+
resolve(server);
|
|
216
|
+
}).on('error', (err: any) => {
|
|
217
|
+
if (err.code === 'EADDRINUSE' && i < maxAttempts - 1) {
|
|
218
|
+
resolve(null); // Try next port
|
|
219
|
+
} else {
|
|
220
|
+
reject(err);
|
|
221
|
+
}
|
|
222
|
+
});
|
|
223
|
+
});
|
|
224
|
+
break; // Successfully started
|
|
225
|
+
} catch (err) {
|
|
226
|
+
if (i === maxAttempts - 1) {
|
|
227
|
+
console.error(\`Could not find available port in range \${preferredPort}-\${preferredPort + maxAttempts - 1}\`);
|
|
228
|
+
process.exit(1);
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
start();
|
|
235
|
+
|
|
236
|
+
export default app;
|
|
237
|
+
`;
|
|
238
|
+
}
|
|
239
|
+
function generateNestJSMain(spec) {
|
|
240
|
+
return `import { NestFactory } from '@nestjs/core';
|
|
241
|
+
import { AppModule } from './app.module.js';
|
|
242
|
+
|
|
243
|
+
async function bootstrap() {
|
|
244
|
+
const app = await NestFactory.create(AppModule, {
|
|
245
|
+
logger: ['log', 'error', 'warn', 'debug', 'verbose']
|
|
246
|
+
});
|
|
247
|
+
|
|
248
|
+
app.enableCors({
|
|
249
|
+
origin: true,
|
|
250
|
+
credentials: true
|
|
251
|
+
});
|
|
252
|
+
|
|
253
|
+
const preferredPort = process.env.PORT ? parseInt(process.env.PORT) : 3000;
|
|
254
|
+
const host = process.env.HOST || '0.0.0.0';
|
|
255
|
+
const maxAttempts = 10;
|
|
256
|
+
|
|
257
|
+
// Try to start server with automatic port fallback
|
|
258
|
+
let started = false;
|
|
259
|
+
for (let i = 0; i < maxAttempts && !started; i++) {
|
|
260
|
+
const port = preferredPort + i;
|
|
261
|
+
try {
|
|
262
|
+
await app.listen(port, host);
|
|
263
|
+
started = true;
|
|
264
|
+
|
|
265
|
+
if (i > 0) {
|
|
266
|
+
console.log(\`\u26A0\uFE0F Port \${preferredPort} was in use, using \${port} instead\`);
|
|
267
|
+
}
|
|
268
|
+
console.log(\`\u{1F680} Server running on http://\${host}:\${port}\`);
|
|
269
|
+
console.log(\`\u{1F4DA} Environment: \${process.env.NODE_ENV || 'development'}\`);
|
|
270
|
+
} catch (err: any) {
|
|
271
|
+
if (err.code === 'EADDRINUSE' && i < maxAttempts - 1) {
|
|
272
|
+
// Port in use, try next port
|
|
273
|
+
continue;
|
|
274
|
+
} else {
|
|
275
|
+
throw err;
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
if (!started) {
|
|
281
|
+
throw new Error(\`Could not find available port in range \${preferredPort}-\${preferredPort + maxAttempts - 1}\`);
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
bootstrap();
|
|
286
|
+
`;
|
|
287
|
+
}
|
|
288
|
+
export {
|
|
289
|
+
generateMain as default
|
|
290
|
+
};
|