rapidkit 0.40.1 → 0.41.1
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/README.md +48 -7
- package/contracts/agent-customization-pack.v1.json +52 -2
- package/contracts/extension-cli-compatibility.v1.json +14 -2
- package/contracts/runtime-command-surface.v1.json +7 -1
- package/contracts/workspace-intelligence/agent-action-outcome.v1.json +38 -0
- package/contracts/workspace-intelligence/blocker-resolution.v1.json +65 -0
- package/contracts/workspace-intelligence/doctor-fix-result.v1.json +34 -0
- package/contracts/workspace-intelligence/studio-blocker-handoff.v1.json +91 -0
- package/contracts/workspace-intelligence/workspace-contract-verify.v1.json +51 -0
- package/contracts/workspace-intelligence/workspace-dependency-graph.v1.json +61 -1
- package/contracts/workspace-intelligence/workspace-explain.v1.json +31 -0
- package/contracts/workspace-intelligence/workspace-intelligence-history.v1.json +36 -0
- package/contracts/workspace-intelligence/workspace-operational-skill.v1.json +37 -0
- package/contracts/workspace-intelligence/workspace-skills-index.v1.json +27 -0
- package/dist/analyze-QYHMGLSG.js +1 -0
- package/dist/autopilot-release-AHMQEUFH.js +1 -0
- package/dist/chunk-33LR2QEM.js +2 -0
- package/dist/chunk-3PTJID76.js +2 -0
- package/dist/chunk-46AGNYI7.js +50 -0
- package/dist/chunk-64RTZBHU.js +2 -0
- package/dist/chunk-AQ4XZZC6.js +1 -0
- package/dist/{chunk-RXWM5DSC.js → chunk-BFEBZABL.js} +3 -3
- package/dist/{chunk-3YLMCP3V.js → chunk-CDCYRBAY.js} +1 -1
- package/dist/chunk-CDPR2YKL.js +13 -0
- package/dist/chunk-CKXJR3YT.js +7 -0
- package/dist/chunk-E5ZVQL3C.js +13 -0
- package/dist/chunk-ELU3G6DQ.js +9 -0
- package/dist/chunk-EN6YCX36.js +1 -0
- package/dist/chunk-FMBSON6H.js +33 -0
- package/dist/chunk-GBJBQ43T.js +1 -0
- package/dist/chunk-ICGWHIMK.js +1 -0
- package/dist/{chunk-4FJQWL7P.js → chunk-ITJ6RKUW.js} +3 -3
- package/dist/{workspace-graph-ICB7OVAZ.js → chunk-JEI6BTZI.js} +1 -1
- package/dist/{chunk-G76C74EV.js → chunk-JU3VNLTY.js} +1 -1
- package/dist/chunk-JW2FSKT3.js +2 -0
- package/dist/chunk-KIUSCFHF.js +1 -0
- package/dist/chunk-LKX3L7TE.js +2 -0
- package/dist/chunk-MIWDCR6I.js +2 -0
- package/dist/{chunk-6G2KSHP6.js → chunk-OLDPVVSV.js} +1 -1
- package/dist/{chunk-4Q2ZZKGB.js → chunk-PCXSTKZ5.js} +1 -1
- package/dist/{chunk-6KD5F6LX.js → chunk-Q2KZIBV4.js} +1 -1
- package/dist/{chunk-ERCD6NFF.js → chunk-RSYUNEH7.js} +13 -13
- package/dist/chunk-TJN7G2MA.js +1 -0
- package/dist/chunk-UQR6G7KH.js +32 -0
- package/dist/chunk-VMJA36WD.js +1 -0
- package/dist/chunk-WRMCPKGA.js +1 -0
- package/dist/{create-XVDDQA42.js → create-RNP5ACQL.js} +1 -1
- package/dist/demo-kit-N5U3NGAE.js +149 -0
- package/dist/{doctor-UOLOGJ2Z.js → doctor-XM6QDTDC.js} +1 -1
- package/dist/{dotnet-webapi-clean-RTBRPDPL.js → dotnet-webapi-clean-K33C77EI.js} +1 -1
- package/dist/{gofiber-standard-UGIRKPKL.js → gofiber-standard-BQ4HCXL2.js} +1 -1
- package/dist/{gogin-standard-HJ7SPFNT.js → gogin-standard-PUBCYW3A.js} +1 -1
- package/dist/index.d.ts +45 -7
- package/dist/index.js +145 -127
- package/dist/{pipeline-XK62WL4D.js → pipeline-DH6Z47O4.js} +1 -1
- package/dist/platform-capabilities-TSLK667K.js +1 -0
- package/dist/{pythonRapidkitExec-MNWRC4F2.js → pythonRapidkitExec-SGKW76XM.js} +1 -1
- package/dist/{springboot-standard-IWJSVDLZ.js → springboot-standard-XFVQI37R.js} +1 -1
- package/dist/{workspace-L4ITCKMM.js → workspace-E554C5SM.js} +1 -1
- package/dist/workspace-agent-sync-2HRPM5ZD.js +1 -0
- package/dist/{workspace-context-NMMQMHNU.js → workspace-context-VJTXW3K4.js} +1 -1
- package/dist/workspace-contract-OO4GMENV.js +1 -0
- package/dist/workspace-explain-3WSJLIJ6.js +1 -0
- package/dist/workspace-explain-contract-24RQ7KIW.js +1 -0
- package/dist/workspace-feedback-65NR3EZH.js +1 -0
- package/dist/{workspace-foundation-HNIRAIBF.js → workspace-foundation-LISDH53T.js} +1 -1
- package/dist/workspace-graph-2A5THUCI.js +1 -0
- package/dist/workspace-history-VPDADQKG.js +1 -0
- package/dist/{workspace-intelligence-64IWAYHS.js → workspace-intelligence-E3KXEZCM.js} +1 -1
- package/dist/workspace-mcp-serve-RFYDCA2L.js +3 -0
- package/dist/workspace-model-YL7W3573.js +1 -0
- package/dist/workspace-registry-summary-X5WRUU3T.js +1 -0
- package/dist/workspace-run-GCIQD73R.js +1 -0
- package/dist/workspace-verify-NRYH7RNB.js +1 -0
- package/dist/workspace-watch-H2AETGFI.js +1 -0
- package/docs/DEVELOPMENT.md +1 -1
- package/docs/OPEN_SOURCE_USER_SCENARIOS.md +1 -1
- package/docs/README.md +1 -1
- package/docs/commands-reference.md +10 -2
- package/docs/contracts/ARTIFACT_CATALOG.md +3 -1
- package/docs/contracts/NAMING_AND_COEXISTENCE.md +58 -0
- package/docs/workspace-run.md +25 -1
- package/package.json +7 -3
- package/scripts/enterprise-package-smoke.mjs +427 -0
- package/scripts/prepack-enterprise.mjs +40 -0
- package/templates/generator.js +175 -0
- package/templates/kits/fastapi-ddd/README.md.j2 +122 -0
- package/templates/kits/fastapi-ddd/common/env.example.j2 +10 -0
- package/templates/kits/fastapi-ddd/env.example.j2 +1 -0
- package/templates/kits/fastapi-ddd/pyproject.toml.j2 +64 -0
- package/templates/kits/fastapi-ddd/src/__init__.py.j2 +3 -0
- package/templates/kits/fastapi-ddd/src/app/__init__.py.j2 +11 -0
- package/templates/kits/fastapi-ddd/src/app/application/__init__.py.j2 +5 -0
- package/templates/kits/fastapi-ddd/src/app/application/interfaces.py.j2 +43 -0
- package/templates/kits/fastapi-ddd/src/app/application/use_cases/__init__.py.j2 +6 -0
- package/templates/kits/fastapi-ddd/src/app/application/use_cases/health.py.j2 +14 -0
- package/templates/kits/fastapi-ddd/src/app/application/use_cases/notes.py.j2 +24 -0
- package/templates/kits/fastapi-ddd/src/app/config/__init__.py.j2 +16 -0
- package/templates/kits/fastapi-ddd/src/app/domain/__init__.py.j2 +3 -0
- package/templates/kits/fastapi-ddd/src/app/domain/models/__init__.py.j2 +6 -0
- package/templates/kits/fastapi-ddd/src/app/domain/models/health.py.j2 +16 -0
- package/templates/kits/fastapi-ddd/src/app/domain/models/note.py.j2 +27 -0
- package/templates/kits/fastapi-ddd/src/app/infrastructure/__init__.py.j2 +5 -0
- package/templates/kits/fastapi-ddd/src/app/infrastructure/repositories/__init__.py.j2 +6 -0
- package/templates/kits/fastapi-ddd/src/app/infrastructure/repositories/health.py.j2 +17 -0
- package/templates/kits/fastapi-ddd/src/app/infrastructure/repositories/notes.py.j2 +28 -0
- package/templates/kits/fastapi-ddd/src/app/main.py.j2 +61 -0
- package/templates/kits/fastapi-ddd/src/app/presentation/__init__.py.j2 +3 -0
- package/templates/kits/fastapi-ddd/src/app/presentation/api/__init__.py.j2 +5 -0
- package/templates/kits/fastapi-ddd/src/app/presentation/api/dependencies/__init__.py.j2 +19 -0
- package/templates/kits/fastapi-ddd/src/app/presentation/api/router.py.j2 +10 -0
- package/templates/kits/fastapi-ddd/src/app/presentation/api/routes/__init__.py.j2 +5 -0
- package/templates/kits/fastapi-ddd/src/app/presentation/api/routes/health.py.j2 +27 -0
- package/templates/kits/fastapi-ddd/src/app/presentation/api/routes/notes.py.j2 +50 -0
- package/templates/kits/fastapi-ddd/src/app/shared/__init__.py.j2 +5 -0
- package/templates/kits/fastapi-ddd/src/app/shared/result.py.j2 +28 -0
- package/templates/kits/fastapi-ddd/src/cli.py.j2 +167 -0
- package/templates/kits/fastapi-ddd/src/main.py.j2 +35 -0
- package/templates/kits/fastapi-ddd/src/modules/__init__.py.j2 +3 -0
- package/templates/kits/fastapi-ddd/src/routing/__init__.py.j2 +13 -0
- package/templates/kits/fastapi-ddd/src/routing/health.py.j2 +7 -0
- package/templates/kits/fastapi-ddd/src/routing/notes.py.j2 +7 -0
- package/templates/kits/fastapi-ddd/tests/__init__.py.j2 +1 -0
- package/templates/kits/fastapi-ddd/tests/test_app_factory.py.j2 +22 -0
- package/templates/kits/fastapi-ddd/tests/test_health.py.j2 +17 -0
- package/templates/kits/fastapi-ddd/tests/test_notes.py.j2 +27 -0
- package/templates/kits/fastapi-standard/README.md.j2 +145 -0
- package/templates/kits/fastapi-standard/common/env.example.j2 +10 -0
- package/templates/kits/fastapi-standard/env.example.j2 +1 -0
- package/templates/kits/fastapi-standard/pyproject.toml.j2 +64 -0
- package/templates/kits/fastapi-standard/src/__init__.py.j2 +3 -0
- package/templates/kits/fastapi-standard/src/cli.py.j2 +168 -0
- package/templates/kits/fastapi-standard/src/main.py.j2 +66 -0
- package/templates/kits/fastapi-standard/src/modules/__init__.py.j2 +3 -0
- package/templates/kits/fastapi-standard/src/routing/__init__.py.j2 +16 -0
- package/templates/kits/fastapi-standard/src/routing/examples.py.j2 +71 -0
- package/templates/kits/fastapi-standard/src/routing/health.py.j2 +22 -0
- package/templates/kits/fastapi-standard/tests/__init__.py.j2 +1 -0
- package/templates/kits/fastapi-standard/tests/test_examples.py.j2 +29 -0
- package/templates/kits/fastapi-standard/tests/test_health.py.j2 +17 -0
- package/templates/kits/nestjs-standard/Dockerfile.j2 +41 -0
- package/templates/kits/nestjs-standard/README.md.j2 +139 -0
- package/templates/kits/nestjs-standard/docker-compose.yml.j2 +94 -0
- package/templates/kits/nestjs-standard/docs/README.md.j2 +15 -0
- package/templates/kits/nestjs-standard/env.example.j2 +18 -0
- package/templates/kits/nestjs-standard/eslint.config.cjs.j2 +9 -0
- package/templates/kits/nestjs-standard/jest.config.ts.j2 +22 -0
- package/templates/kits/nestjs-standard/nest-cli.json.j2 +10 -0
- package/templates/kits/nestjs-standard/package.json.j2 +101 -0
- package/templates/kits/nestjs-standard/src/app.controller.ts.j2 +14 -0
- package/templates/kits/nestjs-standard/src/app.module.ts.j2 +26 -0
- package/templates/kits/nestjs-standard/src/app.service.ts.j2 +16 -0
- package/templates/kits/nestjs-standard/src/auth/auth.controller.ts.j2 +20 -0
- package/templates/kits/nestjs-standard/src/auth/auth.module.ts.j2 +13 -0
- package/templates/kits/nestjs-standard/src/auth/auth.service.ts.j2 +6 -0
- package/templates/kits/nestjs-standard/src/auth/entities/token.entity.ts.j2 +3 -0
- package/templates/kits/nestjs-standard/src/auth/entities/user.entity.ts.j2 +3 -0
- package/templates/kits/nestjs-standard/src/auth/entities/webauthn.entity.ts.j2 +3 -0
- package/templates/kits/nestjs-standard/src/config/configuration.ts.j2 +85 -0
- package/templates/kits/nestjs-standard/src/config/index.ts.j2 +2 -0
- package/templates/kits/nestjs-standard/src/config/validation.ts.j2 +21 -0
- package/templates/kits/nestjs-standard/src/examples/dto/create-note.dto.ts.j2 +11 -0
- package/templates/kits/nestjs-standard/src/examples/examples.controller.ts.j2 +24 -0
- package/templates/kits/nestjs-standard/src/examples/examples.module.ts.j2 +10 -0
- package/templates/kits/nestjs-standard/src/examples/examples.service.ts.j2 +33 -0
- package/templates/kits/nestjs-standard/src/main.ts.j2 +53 -0
- package/templates/kits/nestjs-standard/src/modules/index.ts.j2 +25 -0
- package/templates/kits/nestjs-standard/test/app.controller.spec.ts.j2 +24 -0
- package/templates/kits/nestjs-standard/test/app.e2e-spec.ts.j2 +60 -0
- package/templates/kits/nestjs-standard/test/examples.controller.spec.ts.j2 +28 -0
- package/templates/kits/nestjs-standard/test/jest-e2e.json.j2 +15 -0
- package/templates/kits/nestjs-standard/tsconfig.build.json.j2 +12 -0
- package/templates/kits/nestjs-standard/tsconfig.json.j2 +26 -0
- package/dist/analyze-RHQM4AB2.js +0 -1
- package/dist/autopilot-release-OJTLXPMX.js +0 -1
- package/dist/chunk-5VBRMLRU.js +0 -7
- package/dist/chunk-7VI4U7Q5.js +0 -2
- package/dist/chunk-FV5A3N3I.js +0 -2
- package/dist/chunk-GDGATWR5.js +0 -2
- package/dist/chunk-GOM3RFB3.js +0 -2
- package/dist/chunk-GX7UU7LL.js +0 -33
- package/dist/chunk-KYH364KQ.js +0 -1
- package/dist/chunk-OWNGSAO3.js +0 -2
- package/dist/chunk-QPEBI6AB.js +0 -2
- package/dist/chunk-TYZPPUBH.js +0 -1
- package/dist/chunk-VQMZC5TC.js +0 -9
- package/dist/chunk-WHCON2VN.js +0 -50
- package/dist/chunk-X7PWDIQW.js +0 -1
- package/dist/chunk-Z5LKRG57.js +0 -1
- package/dist/chunk-ZWKLRZE5.js +0 -13
- package/dist/demo-kit-RWGOEDW4.js +0 -141
- package/dist/workspace-agent-sync-G7JU77IK.js +0 -25
- package/dist/workspace-contract-D5O4OZD5.js +0 -1
- package/dist/workspace-history-LHUTLE3S.js +0 -1
- package/dist/workspace-model-SDHH5RBC.js +0 -1
- package/dist/workspace-registry-summary-MIPHVB56.js +0 -1
- package/dist/workspace-run-SPP32MPV.js +0 -1
- package/dist/workspace-verify-6Q6MGRG6.js +0 -1
- package/dist/workspace-watch-JDXVGW4H.js +0 -1
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# Application
|
|
2
|
+
APP_NAME={{ project_name | upper }}
|
|
3
|
+
PORT=8000
|
|
4
|
+
HOST=0.0.0.0
|
|
5
|
+
NODE_ENV=development
|
|
6
|
+
|
|
7
|
+
# Security
|
|
8
|
+
JWT_SECRET="{{ '' | generate_secret(48) }}"
|
|
9
|
+
JWT_EXPIRATION=1h
|
|
10
|
+
|
|
11
|
+
# Database
|
|
12
|
+
DATABASE_URL=postgresql://user:password@localhost:5432/{{ project_name | replace('-', '_') }}
|
|
13
|
+
|
|
14
|
+
# Redis
|
|
15
|
+
REDIS_HOST=localhost
|
|
16
|
+
REDIS_PORT=6379
|
|
17
|
+
|
|
18
|
+
# <<<inject:module-env>>>
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { Config } from 'jest';
|
|
2
|
+
|
|
3
|
+
const config: Config = {
|
|
4
|
+
moduleFileExtensions: ['js', 'json', 'ts'],
|
|
5
|
+
rootDir: '.',
|
|
6
|
+
testEnvironment: 'node',
|
|
7
|
+
testRegex: '.*\\.spec.ts$',
|
|
8
|
+
testPathIgnorePatterns: ['/node_modules/', '/.rapidkit/vendor/', '/.rapidkit/snapshots/'],
|
|
9
|
+
transform: {
|
|
10
|
+
'^.+\\.ts$': 'ts-jest',
|
|
11
|
+
},
|
|
12
|
+
collectCoverageFrom: ['src/**/*.{ts,tsx}', '!src/**/*.module.ts'],
|
|
13
|
+
coverageDirectory: './coverage',
|
|
14
|
+
moduleNameMapper: {
|
|
15
|
+
'^@config/(.*)$': '<rootDir>/src/config/$1',
|
|
16
|
+
'^@modules/(.*)$': '<rootDir>/src/modules/$1',
|
|
17
|
+
'^@shared/(.*)$': '<rootDir>/src/shared/$1',
|
|
18
|
+
},
|
|
19
|
+
setupFiles: ['dotenv/config'],
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
export default config;
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "{{ project_name | replace('_', '-') | lower }}",
|
|
3
|
+
"version": "{{ app_version | default('1.0.0') }}",
|
|
4
|
+
"description": "{{ description | default('NestJS application generated with RapidKit') }}",
|
|
5
|
+
"license": "{{ license | default('Apache-2.0') }}",
|
|
6
|
+
"author": "{{ author }}",
|
|
7
|
+
"engines": {
|
|
8
|
+
"node": ">={{ node_version }}"
|
|
9
|
+
},
|
|
10
|
+
"private": true,
|
|
11
|
+
"scripts": {
|
|
12
|
+
"start": "node dist/main",
|
|
13
|
+
"dev": "nest start --watch",
|
|
14
|
+
"start:dev": "nest start --watch",
|
|
15
|
+
"start:debug": "nest start --debug --watch",
|
|
16
|
+
"start:prod": "node dist/main",
|
|
17
|
+
"build": "nest build",
|
|
18
|
+
"lint": "eslint \"{src,test}/**/*.ts\" --fix",
|
|
19
|
+
"format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"",
|
|
20
|
+
"test": "jest",
|
|
21
|
+
"test:watch": "jest --watch",
|
|
22
|
+
"test:cov": "jest --coverage",
|
|
23
|
+
"test:e2e": "jest --config ./test/jest-e2e.json"
|
|
24
|
+
},
|
|
25
|
+
"dependencies": {
|
|
26
|
+
"@nestjs/common": "^11.1.10",
|
|
27
|
+
"@nestjs/config": "^4.0.2",
|
|
28
|
+
"@nestjs/core": "^11.1.10",
|
|
29
|
+
"@nestjs/platform-express": "^11.1.10",
|
|
30
|
+
"@nestjs/swagger": "^11.2.3",
|
|
31
|
+
"class-transformer": "^0.5.1",
|
|
32
|
+
"class-validator": "^0.14.3",
|
|
33
|
+
"reflect-metadata": "^0.2.2",
|
|
34
|
+
"rxjs": "^7.8.2",
|
|
35
|
+
"helmet": "^8.1.0",
|
|
36
|
+
"compression": "^1.8.1",
|
|
37
|
+
"winston": "^3.19.0",
|
|
38
|
+
"zod": "^4.2.1",
|
|
39
|
+
"joi": "^18.0.2",
|
|
40
|
+
"@nestjs/terminus": "^11.0.0",
|
|
41
|
+
{% if database_type in ['postgresql', 'mysql'] %}
|
|
42
|
+
"@nestjs/typeorm": "^11.0.0",
|
|
43
|
+
"typeorm": "^0.3.28",
|
|
44
|
+
{% if database_type == 'postgresql' %}
|
|
45
|
+
"pg": "^8.16.3",
|
|
46
|
+
{% elif database_type == 'mysql' %}
|
|
47
|
+
"mysql2": "^3.15.3",
|
|
48
|
+
{% endif %}
|
|
49
|
+
{% elif database_type == 'mongodb' %}
|
|
50
|
+
"@nestjs/mongoose": "^11.0.3",
|
|
51
|
+
"mongoose": "^9.0.1",
|
|
52
|
+
{% endif %}
|
|
53
|
+
{% if include_caching %}
|
|
54
|
+
"@nestjs/cache-manager": "^3.0.1",
|
|
55
|
+
"cache-manager": "^7.2.6",
|
|
56
|
+
"cache-manager-redis-store": "^3.0.1",
|
|
57
|
+
"ioredis": "^5.8.2",
|
|
58
|
+
{% endif %}
|
|
59
|
+
{% if include_monitoring %}
|
|
60
|
+
"prom-client": "^15.1.3",
|
|
61
|
+
{% endif %}
|
|
62
|
+
{% if auth_type in ['jwt', 'oauth2'] %}
|
|
63
|
+
"@nestjs/jwt": "^11.0.2",
|
|
64
|
+
"@nestjs/passport": "^11.0.5",
|
|
65
|
+
"bcrypt": "^6.0.0",
|
|
66
|
+
"passport": "^0.7.0",
|
|
67
|
+
"passport-jwt": "^4.0.1",
|
|
68
|
+
{% endif %}
|
|
69
|
+
"dotenv": "^17.2.3"
|
|
70
|
+
},
|
|
71
|
+
"devDependencies": {
|
|
72
|
+
"@eslint/eslintrc": "^3.3.3",
|
|
73
|
+
"@nestjs/cli": "^11.0.14",
|
|
74
|
+
"@nestjs/schematics": "^11.0.9",
|
|
75
|
+
"@nestjs/testing": "^11.1.10",
|
|
76
|
+
"@types/compression": "^1.8.1",
|
|
77
|
+
"@types/express": "^5.0.6",
|
|
78
|
+
"@types/jest": "^30.0.0",
|
|
79
|
+
"@types/node": "^18.19.130",
|
|
80
|
+
"@types/supertest": "^6.0.3",
|
|
81
|
+
"@typescript-eslint/eslint-plugin": "^8.50.1",
|
|
82
|
+
"@typescript-eslint/parser": "^8.50.1",
|
|
83
|
+
"eslint": "^9.39.2",
|
|
84
|
+
"eslint-config-prettier": "^10.1.8",
|
|
85
|
+
"eslint-plugin-import": "^2.32.0",
|
|
86
|
+
"eslint-plugin-prettier": "^5.5.4",
|
|
87
|
+
"jest": "^30.2.0",
|
|
88
|
+
"prettier": "^3.7.4",
|
|
89
|
+
"source-map-support": "^0.5.21",
|
|
90
|
+
"supertest": "^7.1.4",
|
|
91
|
+
"ts-jest": "^29.4.6",
|
|
92
|
+
"ts-loader": "^9.5.4",
|
|
93
|
+
"ts-node": "^10.9.2",
|
|
94
|
+
"tsconfig-paths": "^4.2.0",
|
|
95
|
+
"typescript": "^5.9.3"
|
|
96
|
+
},
|
|
97
|
+
"overrides": {
|
|
98
|
+
"cross-spawn": "7.0.5",
|
|
99
|
+
"glob": "10.5.0"
|
|
100
|
+
}
|
|
101
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { Controller, Get } from '@nestjs/common';
|
|
2
|
+
import { AppService } from './app.service';
|
|
3
|
+
|
|
4
|
+
@Controller()
|
|
5
|
+
export class AppController {
|
|
6
|
+
constructor(private readonly appService: AppService) {}
|
|
7
|
+
|
|
8
|
+
@Get('health')
|
|
9
|
+
getHealth() {
|
|
10
|
+
return this.appService.getHealth();
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
// <<<inject:controller-routes>>>
|
|
14
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { Module } from '@nestjs/common';
|
|
2
|
+
import { ConfigModule } from '@nestjs/config';
|
|
3
|
+
|
|
4
|
+
import { settingsConfiguration } from './config/configuration';
|
|
5
|
+
import { validationSchema } from './config/validation';
|
|
6
|
+
import { AppController } from './app.controller';
|
|
7
|
+
import { AppService } from './app.service';
|
|
8
|
+
import { rapidkitModules } from './modules';
|
|
9
|
+
import { ExamplesModule } from './examples/examples.module';
|
|
10
|
+
// <<<inject:module-imports>>>
|
|
11
|
+
|
|
12
|
+
@Module({
|
|
13
|
+
imports: [
|
|
14
|
+
ConfigModule.forRoot({
|
|
15
|
+
isGlobal: true,
|
|
16
|
+
load: [settingsConfiguration],
|
|
17
|
+
validationSchema,
|
|
18
|
+
expandVariables: true,
|
|
19
|
+
}),
|
|
20
|
+
ExamplesModule,
|
|
21
|
+
...rapidkitModules,
|
|
22
|
+
],
|
|
23
|
+
controllers: [AppController],
|
|
24
|
+
providers: [AppService],
|
|
25
|
+
})
|
|
26
|
+
export class AppModule {}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { Injectable } from '@nestjs/common';
|
|
2
|
+
|
|
3
|
+
@Injectable()
|
|
4
|
+
export class AppService {
|
|
5
|
+
getHealth() {
|
|
6
|
+
return {
|
|
7
|
+
status: 'ok',
|
|
8
|
+
timestamp: new Date().toISOString(),
|
|
9
|
+
version: process.env.APP_VERSION ?? process.env.npm_package_version ?? '0.0.1',
|
|
10
|
+
uptime: process.uptime(),
|
|
11
|
+
module: process.env.APP_MODULE ?? process.env.APP_NAME ?? process.env.npm_package_name ?? 'app',
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
// <<<inject:service-methods>>>
|
|
16
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { Controller } from '@nestjs/common';
|
|
2
|
+
|
|
3
|
+
@Controller('auth')
|
|
4
|
+
export class AuthController {
|
|
5
|
+
// <<<inject:auth-login>>>
|
|
6
|
+
// <<<inject:auth-signup>>>
|
|
7
|
+
// <<<inject:auth-refresh>>>
|
|
8
|
+
// <<<inject:auth-logout>>>
|
|
9
|
+
// <<<inject:auth-logout-all>>>
|
|
10
|
+
// <<<inject:auth-me>>>
|
|
11
|
+
// <<<inject:auth-protected>>>
|
|
12
|
+
// <<<inject:auth-oauth-google>>>
|
|
13
|
+
// <<<inject:auth-mfa-totp>>>
|
|
14
|
+
// <<<inject:auth-email-verification>>>
|
|
15
|
+
// <<<inject:auth-captcha>>>
|
|
16
|
+
// <<<inject:auth-biometric>>>
|
|
17
|
+
// <<<inject:auth-passwordless>>>
|
|
18
|
+
// <<<inject:auth-federated>>>
|
|
19
|
+
// <<<inject:auth-zero-trust>>>
|
|
20
|
+
}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import { registerAs } from '@nestjs/config';
|
|
3
|
+
|
|
4
|
+
/* eslint-disable @typescript-eslint/no-require-imports */
|
|
5
|
+
|
|
6
|
+
// Dynamic vendor loader - resolves .rapidkit/vendor in project root or uses
|
|
7
|
+
// RAPIDKIT_VENDOR_ROOT if set. This avoids hard-coded relative imports into
|
|
8
|
+
// src/.rapidkit and makes generated projects robust and portable.
|
|
9
|
+
const VENDOR_ROOT_ENV = 'RAPIDKIT_VENDOR_ROOT';
|
|
10
|
+
const VENDOR_MODULE = '{{ rapidkit_vendor_module }}';
|
|
11
|
+
const VENDOR_VERSION = '{{ rapidkit_vendor_version }}';
|
|
12
|
+
const VENDOR_CONFIGURATION_RELATIVE = 'src/config/configuration';
|
|
13
|
+
|
|
14
|
+
function resolveVendorRoot(): string {
|
|
15
|
+
const override = process.env[VENDOR_ROOT_ENV];
|
|
16
|
+
if (override && override.trim().length > 0) {
|
|
17
|
+
return path.resolve(override);
|
|
18
|
+
}
|
|
19
|
+
return path.resolve(process.cwd(), '.rapidkit', 'vendor');
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function resolveVendorModule() {
|
|
23
|
+
const vendorPath = path.join(
|
|
24
|
+
resolveVendorRoot(),
|
|
25
|
+
VENDOR_MODULE,
|
|
26
|
+
VENDOR_VERSION,
|
|
27
|
+
VENDOR_CONFIGURATION_RELATIVE,
|
|
28
|
+
);
|
|
29
|
+
// Attempt to dynamically load a vendor-provided configuration. If the
|
|
30
|
+
// vendor snapshot is not present in .rapidkit/vendor (common when the
|
|
31
|
+
// 'settings' module wasn't installed), fail gracefully instead of
|
|
32
|
+
// allowing require() to throw and crash the application.
|
|
33
|
+
try {
|
|
34
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires, global-require
|
|
35
|
+
return require(vendorPath);
|
|
36
|
+
} catch (err: unknown) {
|
|
37
|
+
const e = err as { code?: string } | undefined;
|
|
38
|
+
// Only suppress MODULE_NOT_FOUND / ENOENT for the vendor path so other
|
|
39
|
+
// unexpected errors still surface to the user.
|
|
40
|
+
if (e && (e.code === 'MODULE_NOT_FOUND' || e.code === 'ENOENT')) {
|
|
41
|
+
// eslint-disable-next-line no-console
|
|
42
|
+
console.warn(`WARN: vendor settings not found at ${vendorPath} - continuing without vendor settings`);
|
|
43
|
+
return null;
|
|
44
|
+
}
|
|
45
|
+
throw err;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const _vendor = resolveVendorModule();
|
|
50
|
+
|
|
51
|
+
export default registerAs('app', () => ({
|
|
52
|
+
name: process.env.APP_NAME ?? "{{ project_name | replace('-', ' ') | title }}",
|
|
53
|
+
env: process.env.NODE_ENV ?? 'development',
|
|
54
|
+
host: process.env.HOST ?? '0.0.0.0',
|
|
55
|
+
port: parseInt(process.env.PORT ?? '8000', 10),
|
|
56
|
+
logLevel: (() => {
|
|
57
|
+
const raw = (process.env.LOG_LEVEL ?? 'log').toLowerCase();
|
|
58
|
+
if (raw === 'info') return 'log';
|
|
59
|
+
if (raw === 'warning') return 'warn';
|
|
60
|
+
return raw;
|
|
61
|
+
})(),
|
|
62
|
+
// <<<inject:configuration>>>
|
|
63
|
+
}));
|
|
64
|
+
|
|
65
|
+
// Provide a safe default settingsConfiguration if no vendor snapshot is present
|
|
66
|
+
// so generated projects still boot even when the optional settings module
|
|
67
|
+
// hasn't been installed.
|
|
68
|
+
const defaultSettings = () => ({
|
|
69
|
+
ENV: process.env.NODE_ENV ?? 'development',
|
|
70
|
+
DEBUG: process.env.DEBUG === '1' || process.env.DEBUG?.toLowerCase() === 'true',
|
|
71
|
+
PROJECT_NAME: process.env.APP_NAME ?? '{{ project_name | replace('-', ' ') | title }}',
|
|
72
|
+
SECRET_KEY: process.env.SECRET_KEY ?? '{{ '' | generate_secret(48) }}',
|
|
73
|
+
VERSION: process.env.APP_VERSION ?? '0.0.1',
|
|
74
|
+
ALLOWED_HOSTS: (process.env.ALLOWED_HOSTS ?? '*').split(',').map((s) => s.trim()).filter(Boolean),
|
|
75
|
+
CONFIG_FILES: [],
|
|
76
|
+
CONFIG_REFRESH_INTERVAL: Number.parseInt(process.env.CONFIG_REFRESH_INTERVAL ?? '60', 10),
|
|
77
|
+
VAULT_URL: null,
|
|
78
|
+
AWS_REGION: null,
|
|
79
|
+
HOT_RELOAD_ENABLED:
|
|
80
|
+
process.env.HOT_RELOAD_ENABLED === '1' || process.env.HOT_RELOAD_ENABLED?.toLowerCase() === 'true',
|
|
81
|
+
HOT_RELOAD_ENV_ALLOWLIST: (process.env.HOT_RELOAD_ENV_ALLOWLIST ?? '').split(',').map((s) => s.trim()).filter(Boolean),
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
export const settingsConfiguration =
|
|
85
|
+
_vendor?.settingsConfiguration ?? _vendor?.default?.settingsConfiguration ?? (() => defaultSettings());
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import * as Joi from 'joi';
|
|
2
|
+
|
|
3
|
+
export const validationSchema = Joi.object({
|
|
4
|
+
APP_NAME: Joi.string().default("{{ project_name | replace('-', ' ') | title }}"),
|
|
5
|
+
NODE_ENV: Joi.string().valid('development', 'production', 'test').default('development'),
|
|
6
|
+
HOST: Joi.string().hostname().default('0.0.0.0'),
|
|
7
|
+
PORT: Joi.number().port().default(8000),
|
|
8
|
+
LOG_LEVEL: Joi.string()
|
|
9
|
+
.lowercase()
|
|
10
|
+
.valid('error', 'warn', 'log', 'debug', 'verbose', 'info', 'warning')
|
|
11
|
+
.default('log'),
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
export const loggingValidationSchema = Joi.object({
|
|
15
|
+
LOG_LEVEL: Joi.string().valid('debug', 'info', 'warning', 'error').default('info'),
|
|
16
|
+
LOG_FORMAT: Joi.string().valid('json', 'text', 'colored').default('json'),
|
|
17
|
+
LOG_SINKS: Joi.string().default('stderr'),
|
|
18
|
+
LOG_ASYNC_QUEUE: Joi.boolean().truthy('true').falsy('false').default(true),
|
|
19
|
+
LOG_FILE_PATH: Joi.string().default('logs/app.log'),
|
|
20
|
+
LOG_SAMPLING_RATE: Joi.number().min(0).max(1).default(1),
|
|
21
|
+
});
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { Body, Controller, Get, Param, ParseIntPipe, Post } from '@nestjs/common';
|
|
2
|
+
|
|
3
|
+
import { CreateNoteDto } from './dto/create-note.dto';
|
|
4
|
+
import { ExamplesService } from './examples.service';
|
|
5
|
+
|
|
6
|
+
@Controller('examples/notes')
|
|
7
|
+
export class ExamplesController {
|
|
8
|
+
constructor(private readonly examplesService: ExamplesService) {}
|
|
9
|
+
|
|
10
|
+
@Post()
|
|
11
|
+
create(@Body() payload: CreateNoteDto) {
|
|
12
|
+
return this.examplesService.create(payload);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
@Get()
|
|
16
|
+
findAll() {
|
|
17
|
+
return this.examplesService.findAll();
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
@Get(':id')
|
|
21
|
+
findOne(@Param('id', ParseIntPipe) id: number) {
|
|
22
|
+
return this.examplesService.findOne(id);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Module } from '@nestjs/common';
|
|
2
|
+
|
|
3
|
+
import { ExamplesController } from './examples.controller';
|
|
4
|
+
import { ExamplesService } from './examples.service';
|
|
5
|
+
|
|
6
|
+
@Module({
|
|
7
|
+
controllers: [ExamplesController],
|
|
8
|
+
providers: [ExamplesService],
|
|
9
|
+
})
|
|
10
|
+
export class ExamplesModule {}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { Injectable, NotFoundException } from '@nestjs/common';
|
|
2
|
+
|
|
3
|
+
import { CreateNoteDto } from './dto/create-note.dto';
|
|
4
|
+
|
|
5
|
+
export interface ExampleNote {
|
|
6
|
+
id: number;
|
|
7
|
+
title: string;
|
|
8
|
+
body: string;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
@Injectable()
|
|
12
|
+
export class ExamplesService {
|
|
13
|
+
private notes: ExampleNote[] = [];
|
|
14
|
+
private sequence = 1;
|
|
15
|
+
|
|
16
|
+
create(payload: CreateNoteDto): ExampleNote {
|
|
17
|
+
const note: ExampleNote = { id: this.sequence++, ...payload };
|
|
18
|
+
this.notes.push(note);
|
|
19
|
+
return note;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
findAll(): ExampleNote[] {
|
|
23
|
+
return [...this.notes];
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
findOne(id: number): ExampleNote {
|
|
27
|
+
const note = this.notes.find((entry) => entry.id === id);
|
|
28
|
+
if (!note) {
|
|
29
|
+
throw new NotFoundException('Note not found');
|
|
30
|
+
}
|
|
31
|
+
return note;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { Logger } from '@nestjs/common';
|
|
2
|
+
import { SwaggerModule, DocumentBuilder } from '@nestjs/swagger';
|
|
3
|
+
import { NestFactory } from '@nestjs/core';
|
|
4
|
+
import helmet from 'helmet';
|
|
5
|
+
import compression from 'compression';
|
|
6
|
+
|
|
7
|
+
import { AppModule } from './app.module';
|
|
8
|
+
|
|
9
|
+
async function bootstrap() {
|
|
10
|
+
const app = await NestFactory.create(AppModule, {
|
|
11
|
+
bufferLogs: true,
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
const logger = new Logger('Bootstrap');
|
|
15
|
+
|
|
16
|
+
app.use(helmet());
|
|
17
|
+
app.use(compression());
|
|
18
|
+
|
|
19
|
+
app.enableCors({
|
|
20
|
+
origin: '*',
|
|
21
|
+
credentials: true,
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
// <<<inject:global-middleware>>>
|
|
25
|
+
|
|
26
|
+
const port = parseInt(process.env.PORT ?? '8000', 10);
|
|
27
|
+
const host = process.env.HOST ?? '0.0.0.0';
|
|
28
|
+
|
|
29
|
+
// Enable Swagger docs in development or when explicitly requested.
|
|
30
|
+
const enableDocs = process.env.RAPIDKIT_ENABLE_SWAGGER === '1' || process.env.NODE_ENV !== 'production';
|
|
31
|
+
if (enableDocs) {
|
|
32
|
+
const config = new DocumentBuilder()
|
|
33
|
+
.setTitle('{{ project_name | default("RapidKit App") }} API')
|
|
34
|
+
.setDescription('Auto-generated API docs')
|
|
35
|
+
.setVersion('{{ app_version | default("1.0.0") }}')
|
|
36
|
+
.addBearerAuth()
|
|
37
|
+
.build();
|
|
38
|
+
|
|
39
|
+
const document = SwaggerModule.createDocument(app, config);
|
|
40
|
+
SwaggerModule.setup('docs', app, document);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
await app.listen(port, host);
|
|
44
|
+
|
|
45
|
+
logger.log(`🚀 Application is running on http://${host}:${port}`);
|
|
46
|
+
// <<<inject:bootstrap-hooks>>>
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
bootstrap().catch((error) => {
|
|
50
|
+
// eslint-disable-next-line no-console
|
|
51
|
+
console.error('❌ Failed to bootstrap application', error);
|
|
52
|
+
process.exit(1);
|
|
53
|
+
});
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-var-requires, @typescript-eslint/no-require-imports, global-require */
|
|
2
|
+
|
|
3
|
+
import type { DynamicModule, Type } from '@nestjs/common';
|
|
4
|
+
|
|
5
|
+
// Central export for dynamically injected RapidKit modules
|
|
6
|
+
|
|
7
|
+
type ModuleRef = DynamicModule | Type<unknown>;
|
|
8
|
+
|
|
9
|
+
const registerOptionalModule = (loader: () => ModuleRef | null | undefined): ModuleRef | null => {
|
|
10
|
+
try {
|
|
11
|
+
const resolved = loader();
|
|
12
|
+
return resolved ?? null;
|
|
13
|
+
} catch {
|
|
14
|
+
return null;
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
const optionalModules: Array<ModuleRef | null> = [
|
|
19
|
+
registerOptionalModule(() => require('../config/logging.module').LoggingModule as ModuleRef),
|
|
20
|
+
registerOptionalModule(() => require('../config/settings.module').SettingsModule as ModuleRef),
|
|
21
|
+
registerOptionalModule(() => require('../deployment/deployment.module').DeploymentModule as ModuleRef),
|
|
22
|
+
// <<<inject:module-exports>>>
|
|
23
|
+
];
|
|
24
|
+
|
|
25
|
+
export const rapidkitModules: ModuleRef[] = optionalModules.filter(Boolean) as ModuleRef[];
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { Test, TestingModule } from '@nestjs/testing';
|
|
2
|
+
|
|
3
|
+
import { AppController } from '../src/app.controller';
|
|
4
|
+
import { AppService } from '../src/app.service';
|
|
5
|
+
|
|
6
|
+
describe('AppController', () => {
|
|
7
|
+
let appController: AppController;
|
|
8
|
+
|
|
9
|
+
beforeEach(async () => {
|
|
10
|
+
const app: TestingModule = await Test.createTestingModule({
|
|
11
|
+
controllers: [AppController],
|
|
12
|
+
providers: [AppService],
|
|
13
|
+
}).compile();
|
|
14
|
+
|
|
15
|
+
appController = app.get<AppController>(AppController);
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
it('should return health status', () => {
|
|
19
|
+
const result = appController.getHealth();
|
|
20
|
+
expect(result).toHaveProperty('status', 'ok');
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
// <<<inject:controller-tests>>>
|
|
24
|
+
});
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { Test, TestingModule } from '@nestjs/testing';
|
|
2
|
+
import { INestApplication } from '@nestjs/common';
|
|
3
|
+
import request from 'supertest';
|
|
4
|
+
|
|
5
|
+
import { AppModule } from '../src/app.module';
|
|
6
|
+
|
|
7
|
+
describe('AppController (e2e)', () => {
|
|
8
|
+
let app: INestApplication;
|
|
9
|
+
|
|
10
|
+
beforeAll(async () => {
|
|
11
|
+
const moduleFixture: TestingModule = await Test.createTestingModule({
|
|
12
|
+
imports: [AppModule],
|
|
13
|
+
}).compile();
|
|
14
|
+
|
|
15
|
+
app = moduleFixture.createNestApplication();
|
|
16
|
+
await app.init();
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
afterAll(async () => {
|
|
20
|
+
await app.close();
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
it('/health (GET)', () => {
|
|
24
|
+
return request(app.getHttpServer())
|
|
25
|
+
.get('/health')
|
|
26
|
+
.expect(200)
|
|
27
|
+
.expect((res) => {
|
|
28
|
+
expect(res.body).toEqual(
|
|
29
|
+
expect.objectContaining({
|
|
30
|
+
status: 'ok',
|
|
31
|
+
timestamp: expect.any(String),
|
|
32
|
+
version: expect.any(String),
|
|
33
|
+
uptime: expect.any(Number),
|
|
34
|
+
module: expect.any(String),
|
|
35
|
+
}),
|
|
36
|
+
);
|
|
37
|
+
});
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
it('/examples/notes (POST + GET)', async () => {
|
|
41
|
+
const server = app.getHttpServer();
|
|
42
|
+
const createResponse = await request(server)
|
|
43
|
+
.post('/examples/notes')
|
|
44
|
+
.send({ title: 'ddd', body: 'documented via e2e' })
|
|
45
|
+
.expect(201);
|
|
46
|
+
|
|
47
|
+
const noteId = createResponse.body.id;
|
|
48
|
+
|
|
49
|
+
await request(server)
|
|
50
|
+
.get('/examples/notes')
|
|
51
|
+
.expect(200)
|
|
52
|
+
.expect((res) => {
|
|
53
|
+
expect(res.body).toEqual(
|
|
54
|
+
expect.arrayContaining([expect.objectContaining({ id: noteId, title: 'ddd' })]),
|
|
55
|
+
);
|
|
56
|
+
});
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
// <<<inject:e2e-tests>>>
|
|
60
|
+
});
|