@njeybe/nativ 2.4.1 → 2.5.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/CHANGELOG.md +26 -0
- package/README.md +26 -0
- package/dist/commands/db/db-formatter.d.ts +5 -0
- package/dist/commands/db/db-formatter.js +116 -0
- package/dist/commands/db/db-introspect.d.ts +11 -0
- package/dist/commands/db/db-introspect.js +84 -0
- package/dist/commands/db.js +4 -206
- package/dist/commands/profile.d.ts +3 -0
- package/dist/commands/profile.js +39 -0
- package/dist/commands/task/task-add.d.ts +11 -0
- package/dist/commands/task/task-add.js +169 -0
- package/dist/commands/task/task-common.d.ts +57 -0
- package/dist/commands/task/task-common.js +45 -0
- package/dist/commands/task/task-escalate.d.ts +7 -0
- package/dist/commands/task/task-escalate.js +119 -0
- package/dist/commands/task/task-lifecycle.d.ts +5 -0
- package/dist/commands/task/task-lifecycle.js +252 -0
- package/dist/commands/task/task-query.d.ts +10 -0
- package/dist/commands/task/task-query.js +269 -0
- package/dist/commands/task.d.ts +9 -87
- package/dist/commands/task.js +8 -850
- package/dist/commands/triage/triage-store.d.ts +56 -0
- package/dist/commands/triage/triage-store.js +108 -0
- package/dist/commands/triage/triage-ui.d.ts +14 -0
- package/dist/commands/triage/triage-ui.js +104 -0
- package/dist/commands/triage.d.ts +3 -52
- package/dist/commands/triage.js +8 -216
- package/dist/core/enforcement.d.ts +1 -0
- package/dist/core/enforcement.js +19 -0
- package/dist/core/human-gate.d.ts +2 -1
- package/dist/core/human-gate.js +9 -2
- package/dist/core/profiles.d.ts +14 -0
- package/dist/core/profiles.js +82 -0
- package/dist/core/setup/config-merger.d.ts +59 -0
- package/dist/core/setup/config-merger.js +107 -0
- package/dist/core/setup/session-context.d.ts +4 -0
- package/dist/core/setup/session-context.js +65 -0
- package/dist/core/setup/setup-planner.d.ts +14 -0
- package/dist/core/setup/setup-planner.js +180 -0
- package/dist/core/setup/template-planner.d.ts +8 -0
- package/dist/core/setup/template-planner.js +32 -0
- package/dist/core/setup/types.d.ts +65 -0
- package/dist/core/setup/types.js +55 -0
- package/dist/core/setup-assets.d.ts +8 -119
- package/dist/core/setup-assets.js +7 -437
- package/dist/core/tier1-liaison.d.ts +2 -0
- package/dist/core/tier1-liaison.js +64 -3
- package/dist/core/verifier/executor.d.ts +5 -0
- package/dist/core/verifier/executor.js +62 -0
- package/dist/core/verifier/phases.d.ts +5 -0
- package/dist/core/verifier/phases.js +71 -0
- package/dist/core/verifier/task-verifier.d.ts +37 -0
- package/dist/core/verifier/task-verifier.js +233 -0
- package/dist/core/verifier/types.d.ts +51 -0
- package/dist/core/verifier/types.js +1 -0
- package/dist/core/verifier.d.ts +5 -93
- package/dist/core/verifier.js +5 -359
- package/dist/db/introspector.js +59 -59
- package/dist/governor/evaluator.d.ts +4 -64
- package/dist/governor/evaluator.js +21 -686
- package/dist/governor/patch-applier.d.ts +8 -0
- package/dist/governor/patch-applier.js +121 -0
- package/dist/governor/self-healing.d.ts +24 -0
- package/dist/governor/self-healing.js +351 -0
- package/dist/governor/test-integrity.d.ts +41 -0
- package/dist/governor/test-integrity.js +237 -0
- package/dist/index.js +8 -0
- package/dist/mcp/capture.d.ts +4 -0
- package/dist/mcp/capture.js +33 -0
- package/dist/mcp/resources.d.ts +39 -0
- package/dist/mcp/resources.js +44 -0
- package/dist/mcp/server.d.ts +11 -0
- package/dist/mcp/server.js +14 -89
- package/dist/mcp/tools.d.ts +1 -0
- package/dist/mcp/tools.js +1 -0
- package/dist/runner/agent-supervisor.d.ts +8 -302
- package/dist/runner/agent-supervisor.js +41 -1030
- package/dist/runner/cli-config.d.ts +84 -0
- package/dist/runner/cli-config.js +215 -0
- package/dist/runner/native-driver.d.ts +18 -0
- package/dist/runner/native-driver.js +208 -0
- package/dist/runner/native-engine.d.ts +27 -0
- package/dist/runner/native-engine.js +184 -0
- package/dist/runner/native-tools.d.ts +31 -0
- package/dist/runner/native-tools.js +241 -0
- package/dist/runner/process-utils.d.ts +12 -0
- package/dist/runner/process-utils.js +96 -0
- package/dist/runner/run-lifecycle.d.ts +6 -0
- package/dist/runner/run-lifecycle.js +42 -0
- package/dist/runner/types.d.ts +215 -0
- package/dist/runner/types.js +41 -0
- package/dist/scanner/detector.js +42 -663
- package/dist/scanner/detectors/ecosystem-detector.d.ts +16 -0
- package/dist/scanner/detectors/ecosystem-detector.js +354 -0
- package/dist/scanner/detectors/orm-detector.d.ts +5 -0
- package/dist/scanner/detectors/orm-detector.js +59 -0
- package/dist/scanner/detectors/workspace-detector.d.ts +19 -0
- package/dist/scanner/detectors/workspace-detector.js +266 -0
- package/dist/server/cli-runner.d.ts +15 -0
- package/dist/server/cli-runner.js +43 -0
- package/dist/server/event-hub.d.ts +42 -0
- package/dist/server/event-hub.js +169 -0
- package/dist/server/http-utils.d.ts +15 -0
- package/dist/server/http-utils.js +56 -0
- package/dist/server/plan-utils.d.ts +9 -0
- package/dist/server/plan-utils.js +31 -0
- package/dist/server/routes/db-routes.d.ts +57 -0
- package/dist/server/routes/db-routes.js +484 -0
- package/dist/server/routes/task-routes.d.ts +266 -0
- package/dist/server/routes/task-routes.js +285 -0
- package/dist/server/routes/telemetry-routes.d.ts +128 -0
- package/dist/server/routes/telemetry-routes.js +179 -0
- package/dist/server/routes/triage-routes.d.ts +81 -0
- package/dist/server/routes/triage-routes.js +244 -0
- package/dist/server/routes/worktree-routes.d.ts +31 -0
- package/dist/server/routes/worktree-routes.js +144 -0
- package/dist/server/studio-server.d.ts +4 -11
- package/dist/server/studio-server.js +34 -1578
- package/dist/server/studio-ui/shell/pipeline-state.js +2 -0
- package/dist/server/studio-ui/shell/triage.js +10 -0
- package/package.json +2 -2
- package/plugin/.claude-plugin/plugin.json +1 -1
- package/plugin/agents/architect.md +4 -2
- package/plugin/agents/verifier.md +1 -1
- package/plugin/agents/worker.md +7 -4
- package/plugin/skills/nativ/SKILL.md +1 -0
- package/templates/.claudeignore +62 -45
- package/templates/AGENTS.md +1 -0
- package/templates/CLAUDE.md +13 -0
- package/templates/claude-agents/architect.md +4 -2
- package/templates/claude-agents/verifier.md +1 -1
- package/templates/claude-agents/worker.md +7 -4
- package/templates/dot-ai/api_contracts.json +66 -66
- package/templates/dot-ai/context.md +38 -38
- package/templates/dot-ai/db_schema.json +39 -39
- package/templates/dot-ai/subagents/architect.md +54 -0
- package/dist/commands/session.d.ts +0 -22
- package/dist/commands/session.js +0 -106
- package/dist/core/session-memory.d.ts +0 -42
- package/dist/core/session-memory.js +0 -121
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export interface EcosystemProfile {
|
|
2
|
+
projectName?: string;
|
|
3
|
+
projectGoal?: string;
|
|
4
|
+
projectType?: string;
|
|
5
|
+
runtime: string;
|
|
6
|
+
framework: string;
|
|
7
|
+
databaseOrm: string;
|
|
8
|
+
styling: string;
|
|
9
|
+
testing: string;
|
|
10
|
+
packageManager: string;
|
|
11
|
+
verificationCommand: string;
|
|
12
|
+
ecosystemManifests: string[];
|
|
13
|
+
monorepoWorkspaces: string[];
|
|
14
|
+
monorepoIndicators: string[];
|
|
15
|
+
}
|
|
16
|
+
export declare function detectEcosystems(resolvedTarget: string, baseName: string, fileExists: (relPath: string) => boolean, readFileSafe: (filePath: string) => string): EcosystemProfile;
|
|
@@ -0,0 +1,354 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
export function detectEcosystems(resolvedTarget, baseName, fileExists, readFileSafe) {
|
|
3
|
+
let projectName;
|
|
4
|
+
let projectGoal;
|
|
5
|
+
let projectType;
|
|
6
|
+
let runtime = 'Unknown / Greenfield';
|
|
7
|
+
let framework = 'None detected';
|
|
8
|
+
let databaseOrm = 'None detected';
|
|
9
|
+
let styling = 'None detected';
|
|
10
|
+
let testing = 'None detected';
|
|
11
|
+
let packageManager = 'None detected';
|
|
12
|
+
let verificationCommand = 'npm test';
|
|
13
|
+
const ecosystemManifests = [];
|
|
14
|
+
const monorepoWorkspaces = [];
|
|
15
|
+
const monorepoIndicators = [];
|
|
16
|
+
// --- Ecosystem A: Node.js / JavaScript / TypeScript ---
|
|
17
|
+
const pkgPath = path.join(resolvedTarget, 'package.json');
|
|
18
|
+
if (fileExists('package.json')) {
|
|
19
|
+
ecosystemManifests.push('package.json');
|
|
20
|
+
try {
|
|
21
|
+
const pkg = JSON.parse(readFileSafe(pkgPath));
|
|
22
|
+
if (pkg.name)
|
|
23
|
+
projectName = pkg.name;
|
|
24
|
+
if (pkg.description)
|
|
25
|
+
projectGoal = pkg.description;
|
|
26
|
+
if (pkg.workspaces) {
|
|
27
|
+
if (Array.isArray(pkg.workspaces)) {
|
|
28
|
+
monorepoWorkspaces.push(...pkg.workspaces);
|
|
29
|
+
}
|
|
30
|
+
else if (Array.isArray(pkg.workspaces.packages)) {
|
|
31
|
+
monorepoWorkspaces.push(...pkg.workspaces.packages);
|
|
32
|
+
}
|
|
33
|
+
if (!monorepoIndicators.includes('npm/yarn workspaces')) {
|
|
34
|
+
monorepoIndicators.push('npm/yarn workspaces');
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
const deps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
38
|
+
if (deps.typescript || fileExists('tsconfig.json')) {
|
|
39
|
+
runtime = 'Node.js (TypeScript)';
|
|
40
|
+
if (fileExists('tsconfig.json'))
|
|
41
|
+
ecosystemManifests.push('tsconfig.json');
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
runtime = 'Node.js (JavaScript)';
|
|
45
|
+
}
|
|
46
|
+
if (deps['react-native'] || deps.expo) {
|
|
47
|
+
framework = deps.expo ? 'Expo Mobile App' : 'React Native';
|
|
48
|
+
}
|
|
49
|
+
else if (deps.next)
|
|
50
|
+
framework = `Next.js (${deps.next})`;
|
|
51
|
+
else if (deps.nuxt)
|
|
52
|
+
framework = `Nuxt (${deps.nuxt})`;
|
|
53
|
+
else if (deps.remix || deps['@remix-run/react'])
|
|
54
|
+
framework = 'Remix';
|
|
55
|
+
else if (deps.astro)
|
|
56
|
+
framework = 'Astro';
|
|
57
|
+
else if (deps['@sveltejs/kit'] || deps.svelte)
|
|
58
|
+
framework = 'Svelte / SvelteKit';
|
|
59
|
+
else if (deps.vite)
|
|
60
|
+
framework = 'Vite / React/Vue';
|
|
61
|
+
else if (deps['@nestjs/core'])
|
|
62
|
+
framework = 'NestJS';
|
|
63
|
+
else if (deps.hono)
|
|
64
|
+
framework = 'Hono';
|
|
65
|
+
else if (deps.fastify)
|
|
66
|
+
framework = 'Fastify';
|
|
67
|
+
else if (deps.express)
|
|
68
|
+
framework = 'Express.js';
|
|
69
|
+
else if (deps['@angular/core'])
|
|
70
|
+
framework = 'Angular';
|
|
71
|
+
else if (deps.react)
|
|
72
|
+
framework = 'React SPA';
|
|
73
|
+
else if (deps.vue)
|
|
74
|
+
framework = 'Vue.js SPA';
|
|
75
|
+
if (deps.prisma || deps['@prisma/client'])
|
|
76
|
+
databaseOrm = 'Prisma ORM';
|
|
77
|
+
else if (deps['drizzle-orm'])
|
|
78
|
+
databaseOrm = 'Drizzle ORM';
|
|
79
|
+
else if (deps.typeorm)
|
|
80
|
+
databaseOrm = 'TypeORM';
|
|
81
|
+
else if (deps.mongoose)
|
|
82
|
+
databaseOrm = 'Mongoose / MongoDB';
|
|
83
|
+
else if (deps.sequelize)
|
|
84
|
+
databaseOrm = 'Sequelize';
|
|
85
|
+
else if (deps.knex)
|
|
86
|
+
databaseOrm = 'Knex';
|
|
87
|
+
else if (deps['@supabase/supabase-js'])
|
|
88
|
+
databaseOrm = 'Supabase Client';
|
|
89
|
+
else if (deps.pg)
|
|
90
|
+
databaseOrm = 'pg (node-postgres)';
|
|
91
|
+
else if (deps.mysql2)
|
|
92
|
+
databaseOrm = 'mysql2';
|
|
93
|
+
else if (deps['better-sqlite3'] || deps.sqlite3)
|
|
94
|
+
databaseOrm = 'SQLite';
|
|
95
|
+
if (deps.tailwindcss)
|
|
96
|
+
styling = 'Tailwind CSS';
|
|
97
|
+
else if (deps['styled-components'])
|
|
98
|
+
styling = 'Styled Components';
|
|
99
|
+
else if (deps['@emotion/react'])
|
|
100
|
+
styling = 'Emotion';
|
|
101
|
+
else if (deps.sass)
|
|
102
|
+
styling = 'SASS / SCSS';
|
|
103
|
+
if (deps.vitest) {
|
|
104
|
+
testing = 'Vitest';
|
|
105
|
+
verificationCommand = 'npm run test';
|
|
106
|
+
}
|
|
107
|
+
else if (deps.jest) {
|
|
108
|
+
testing = 'Jest';
|
|
109
|
+
verificationCommand = 'npm test';
|
|
110
|
+
}
|
|
111
|
+
else if (deps.playwright || deps['@playwright/test']) {
|
|
112
|
+
testing = 'Playwright';
|
|
113
|
+
verificationCommand = 'npx playwright test';
|
|
114
|
+
}
|
|
115
|
+
if (fileExists('pnpm-lock.yaml')) {
|
|
116
|
+
packageManager = 'pnpm';
|
|
117
|
+
ecosystemManifests.push('pnpm-lock.yaml');
|
|
118
|
+
}
|
|
119
|
+
else if (fileExists('yarn.lock')) {
|
|
120
|
+
packageManager = 'yarn';
|
|
121
|
+
ecosystemManifests.push('yarn.lock');
|
|
122
|
+
}
|
|
123
|
+
else if (fileExists('bun.lockb') || fileExists('bun.lock')) {
|
|
124
|
+
packageManager = 'bun';
|
|
125
|
+
ecosystemManifests.push(fileExists('bun.lockb') ? 'bun.lockb' : 'bun.lock');
|
|
126
|
+
}
|
|
127
|
+
else if (fileExists('package-lock.json')) {
|
|
128
|
+
packageManager = 'npm';
|
|
129
|
+
ecosystemManifests.push('package-lock.json');
|
|
130
|
+
}
|
|
131
|
+
else {
|
|
132
|
+
packageManager = 'npm';
|
|
133
|
+
}
|
|
134
|
+
if (pkg.scripts?.test && pkg.scripts.test !== 'echo "Error: no test specified" && exit 1') {
|
|
135
|
+
verificationCommand = `${packageManager === 'npm' ? 'npm test' : `${packageManager} test`}`;
|
|
136
|
+
}
|
|
137
|
+
else if (pkg.scripts?.build) {
|
|
138
|
+
verificationCommand = `${packageManager === 'npm' ? 'npm run build' : `${packageManager} build`}`;
|
|
139
|
+
}
|
|
140
|
+
projectType = framework !== 'None detected' ? `Web Application (${framework})` : 'Node.js Application';
|
|
141
|
+
}
|
|
142
|
+
catch {
|
|
143
|
+
// ignore parse failure
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
// --- Ecosystem B: PHP (composer.json) ---
|
|
147
|
+
if (fileExists('composer.json')) {
|
|
148
|
+
ecosystemManifests.push('composer.json');
|
|
149
|
+
if (runtime === 'Unknown / Greenfield') {
|
|
150
|
+
runtime = 'PHP';
|
|
151
|
+
packageManager = 'composer';
|
|
152
|
+
projectType = 'PHP Application';
|
|
153
|
+
verificationCommand = 'composer test';
|
|
154
|
+
}
|
|
155
|
+
const composerRaw = readFileSafe(path.join(resolvedTarget, 'composer.json'));
|
|
156
|
+
try {
|
|
157
|
+
const composerPkg = JSON.parse(composerRaw);
|
|
158
|
+
if (composerPkg.name && !projectName) {
|
|
159
|
+
projectName = composerPkg.name;
|
|
160
|
+
}
|
|
161
|
+
if (composerPkg.description && !projectGoal) {
|
|
162
|
+
projectGoal = composerPkg.description;
|
|
163
|
+
}
|
|
164
|
+
const allPhpDeps = { ...composerPkg.require, ...composerPkg['require-dev'] };
|
|
165
|
+
if (allPhpDeps['laravel/framework']) {
|
|
166
|
+
framework = 'Laravel';
|
|
167
|
+
projectType = 'Laravel Web Application';
|
|
168
|
+
databaseOrm = 'Eloquent ORM';
|
|
169
|
+
verificationCommand = 'php artisan test';
|
|
170
|
+
}
|
|
171
|
+
else if (allPhpDeps['symfony/framework-bundle'] || allPhpDeps['symfony/symfony']) {
|
|
172
|
+
framework = 'Symfony';
|
|
173
|
+
projectType = 'Symfony Application';
|
|
174
|
+
databaseOrm = 'Doctrine ORM';
|
|
175
|
+
verificationCommand = 'bin/phpunit';
|
|
176
|
+
}
|
|
177
|
+
else if (allPhpDeps['slim/slim']) {
|
|
178
|
+
framework = 'Slim Framework';
|
|
179
|
+
}
|
|
180
|
+
else if (allPhpDeps['roots/bedrock'] || composerRaw.includes('wordpress')) {
|
|
181
|
+
framework = 'WordPress';
|
|
182
|
+
}
|
|
183
|
+
if (allPhpDeps['pestphp/pest']) {
|
|
184
|
+
testing = 'Pest';
|
|
185
|
+
}
|
|
186
|
+
else if (allPhpDeps['phpunit/phpunit']) {
|
|
187
|
+
testing = 'PHPUnit';
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
catch {
|
|
191
|
+
if (composerRaw.includes('laravel/framework')) {
|
|
192
|
+
framework = 'Laravel';
|
|
193
|
+
databaseOrm = 'Eloquent ORM';
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
// --- Ecosystem C: Python (pyproject.toml, requirements.txt, poetry.lock, Pipfile) ---
|
|
198
|
+
const hasPyproject = fileExists('pyproject.toml');
|
|
199
|
+
const hasRequirements = fileExists('requirements.txt');
|
|
200
|
+
const hasPipfile = fileExists('Pipfile');
|
|
201
|
+
if (hasPyproject || hasRequirements || hasPipfile) {
|
|
202
|
+
if (hasPyproject)
|
|
203
|
+
ecosystemManifests.push('pyproject.toml');
|
|
204
|
+
if (hasRequirements)
|
|
205
|
+
ecosystemManifests.push('requirements.txt');
|
|
206
|
+
if (hasPipfile)
|
|
207
|
+
ecosystemManifests.push('Pipfile');
|
|
208
|
+
if (fileExists('poetry.lock'))
|
|
209
|
+
ecosystemManifests.push('poetry.lock');
|
|
210
|
+
if (fileExists('uv.lock'))
|
|
211
|
+
ecosystemManifests.push('uv.lock');
|
|
212
|
+
if (runtime === 'Unknown / Greenfield') {
|
|
213
|
+
runtime = 'Python 3.x';
|
|
214
|
+
projectType = 'Python Service / Application';
|
|
215
|
+
packageManager = fileExists('poetry.lock')
|
|
216
|
+
? 'Poetry'
|
|
217
|
+
: fileExists('uv.lock')
|
|
218
|
+
? 'uv'
|
|
219
|
+
: fileExists('Pipfile')
|
|
220
|
+
? 'Pipenv'
|
|
221
|
+
: 'pip';
|
|
222
|
+
verificationCommand = 'pytest';
|
|
223
|
+
}
|
|
224
|
+
let pyContent = '';
|
|
225
|
+
if (hasRequirements)
|
|
226
|
+
pyContent += readFileSafe(path.join(resolvedTarget, 'requirements.txt'));
|
|
227
|
+
if (hasPyproject)
|
|
228
|
+
pyContent += readFileSafe(path.join(resolvedTarget, 'pyproject.toml'));
|
|
229
|
+
if (pyContent.includes('fastapi'))
|
|
230
|
+
framework = 'FastAPI';
|
|
231
|
+
else if (pyContent.includes('django')) {
|
|
232
|
+
framework = 'Django';
|
|
233
|
+
databaseOrm = 'Django ORM';
|
|
234
|
+
verificationCommand = 'python manage.py test';
|
|
235
|
+
}
|
|
236
|
+
else if (pyContent.includes('flask'))
|
|
237
|
+
framework = 'Flask';
|
|
238
|
+
else if (pyContent.includes('litestar'))
|
|
239
|
+
framework = 'Litestar';
|
|
240
|
+
if (pyContent.includes('sqlalchemy'))
|
|
241
|
+
databaseOrm = 'SQLAlchemy';
|
|
242
|
+
else if (pyContent.includes('tortoise-orm'))
|
|
243
|
+
databaseOrm = 'Tortoise ORM';
|
|
244
|
+
else if (pyContent.includes('sqlmodel'))
|
|
245
|
+
databaseOrm = 'SQLModel';
|
|
246
|
+
if (pyContent.includes('pytest'))
|
|
247
|
+
testing = 'pytest';
|
|
248
|
+
}
|
|
249
|
+
// --- Ecosystem D: Go (go.mod) ---
|
|
250
|
+
if (fileExists('go.mod')) {
|
|
251
|
+
ecosystemManifests.push('go.mod');
|
|
252
|
+
if (runtime === 'Unknown / Greenfield') {
|
|
253
|
+
runtime = 'Go';
|
|
254
|
+
projectType = 'Go Service';
|
|
255
|
+
packageManager = 'go modules';
|
|
256
|
+
verificationCommand = 'go test ./...';
|
|
257
|
+
}
|
|
258
|
+
const modContent = readFileSafe(path.join(resolvedTarget, 'go.mod'));
|
|
259
|
+
const moduleMatch = modContent.match(/module\s+([^\s\n]+)/);
|
|
260
|
+
if (moduleMatch && !projectName) {
|
|
261
|
+
projectName = path.basename(moduleMatch[1]);
|
|
262
|
+
}
|
|
263
|
+
if (modContent.includes('gin-gonic/gin'))
|
|
264
|
+
framework = 'Gin';
|
|
265
|
+
else if (modContent.includes('gofiber/fiber'))
|
|
266
|
+
framework = 'Fiber';
|
|
267
|
+
else if (modContent.includes('labstack/echo'))
|
|
268
|
+
framework = 'Echo';
|
|
269
|
+
else if (modContent.includes('go-chi/chi'))
|
|
270
|
+
framework = 'Chi';
|
|
271
|
+
if (modContent.includes('gorm.io/gorm'))
|
|
272
|
+
databaseOrm = 'GORM';
|
|
273
|
+
else if (modContent.includes('entgo.io/ent'))
|
|
274
|
+
databaseOrm = 'Ent';
|
|
275
|
+
else if (modContent.includes('jmoiron/sqlx'))
|
|
276
|
+
databaseOrm = 'sqlx';
|
|
277
|
+
}
|
|
278
|
+
// --- Ecosystem E: Rust (Cargo.toml) ---
|
|
279
|
+
if (fileExists('Cargo.toml')) {
|
|
280
|
+
ecosystemManifests.push('Cargo.toml');
|
|
281
|
+
if (runtime === 'Unknown / Greenfield') {
|
|
282
|
+
runtime = 'Rust';
|
|
283
|
+
projectType = 'Rust Application';
|
|
284
|
+
packageManager = 'cargo';
|
|
285
|
+
verificationCommand = 'cargo test';
|
|
286
|
+
}
|
|
287
|
+
const cargoContent = readFileSafe(path.join(resolvedTarget, 'Cargo.toml'));
|
|
288
|
+
if (cargoContent.includes('actix-web'))
|
|
289
|
+
framework = 'Actix Web';
|
|
290
|
+
else if (cargoContent.includes('axum'))
|
|
291
|
+
framework = 'Axum';
|
|
292
|
+
else if (cargoContent.includes('rocket'))
|
|
293
|
+
framework = 'Rocket';
|
|
294
|
+
else if (cargoContent.includes('tauri'))
|
|
295
|
+
framework = 'Tauri';
|
|
296
|
+
if (cargoContent.includes('diesel'))
|
|
297
|
+
databaseOrm = 'Diesel';
|
|
298
|
+
else if (cargoContent.includes('sqlx'))
|
|
299
|
+
databaseOrm = 'SQLx';
|
|
300
|
+
else if (cargoContent.includes('sea-orm'))
|
|
301
|
+
databaseOrm = 'SeaORM';
|
|
302
|
+
}
|
|
303
|
+
// --- Ecosystem F: Java / JVM (pom.xml, build.gradle) ---
|
|
304
|
+
if (fileExists('pom.xml') || fileExists('build.gradle') || fileExists('build.gradle.kts')) {
|
|
305
|
+
if (fileExists('pom.xml'))
|
|
306
|
+
ecosystemManifests.push('pom.xml');
|
|
307
|
+
if (fileExists('build.gradle'))
|
|
308
|
+
ecosystemManifests.push('build.gradle');
|
|
309
|
+
if (fileExists('build.gradle.kts'))
|
|
310
|
+
ecosystemManifests.push('build.gradle.kts');
|
|
311
|
+
if (runtime === 'Unknown / Greenfield') {
|
|
312
|
+
runtime = 'Java / JVM';
|
|
313
|
+
projectType = 'Java Service / Application';
|
|
314
|
+
packageManager = fileExists('pom.xml') ? 'Maven' : 'Gradle';
|
|
315
|
+
verificationCommand = fileExists('pom.xml') ? 'mvn test' : './gradlew test';
|
|
316
|
+
}
|
|
317
|
+
const jvmContent = readFileSafe(path.join(resolvedTarget, fileExists('pom.xml') ? 'pom.xml' : 'build.gradle'));
|
|
318
|
+
if (jvmContent.includes('spring-boot'))
|
|
319
|
+
framework = 'Spring Boot';
|
|
320
|
+
else if (jvmContent.includes('quarkus'))
|
|
321
|
+
framework = 'Quarkus';
|
|
322
|
+
else if (jvmContent.includes('micronaut'))
|
|
323
|
+
framework = 'Micronaut';
|
|
324
|
+
if (jvmContent.includes('hibernate') || jvmContent.includes('spring-boot-starter-data-jpa')) {
|
|
325
|
+
databaseOrm = 'Hibernate / JPA';
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
// --- Ecosystem G: Mobile / Flutter (pubspec.yaml) ---
|
|
329
|
+
if (fileExists('pubspec.yaml')) {
|
|
330
|
+
ecosystemManifests.push('pubspec.yaml');
|
|
331
|
+
if (runtime === 'Unknown / Greenfield') {
|
|
332
|
+
runtime = 'Dart / Flutter';
|
|
333
|
+
framework = 'Flutter Mobile App';
|
|
334
|
+
projectType = 'Mobile Application (Flutter)';
|
|
335
|
+
packageManager = 'flutter pub';
|
|
336
|
+
verificationCommand = 'flutter test';
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
return {
|
|
340
|
+
projectName,
|
|
341
|
+
projectGoal,
|
|
342
|
+
projectType,
|
|
343
|
+
runtime,
|
|
344
|
+
framework,
|
|
345
|
+
databaseOrm,
|
|
346
|
+
styling,
|
|
347
|
+
testing,
|
|
348
|
+
packageManager,
|
|
349
|
+
verificationCommand,
|
|
350
|
+
ecosystemManifests,
|
|
351
|
+
monorepoWorkspaces,
|
|
352
|
+
monorepoIndicators,
|
|
353
|
+
};
|
|
354
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
export function detectOrm(resolvedTarget, fileExists, initialOrm) {
|
|
4
|
+
let detectedOrmConfig = '';
|
|
5
|
+
let databaseOrm = initialOrm;
|
|
6
|
+
if (fileExists('prisma/schema.prisma')) {
|
|
7
|
+
detectedOrmConfig = 'prisma/schema.prisma';
|
|
8
|
+
databaseOrm = 'Prisma ORM';
|
|
9
|
+
}
|
|
10
|
+
else if (fileExists('schema.prisma')) {
|
|
11
|
+
detectedOrmConfig = 'schema.prisma';
|
|
12
|
+
databaseOrm = 'Prisma ORM';
|
|
13
|
+
}
|
|
14
|
+
if (fileExists('drizzle.config.ts')) {
|
|
15
|
+
detectedOrmConfig = 'drizzle.config.ts';
|
|
16
|
+
databaseOrm = 'Drizzle ORM';
|
|
17
|
+
}
|
|
18
|
+
else if (fileExists('drizzle.config.js')) {
|
|
19
|
+
detectedOrmConfig = 'drizzle.config.js';
|
|
20
|
+
databaseOrm = 'Drizzle ORM';
|
|
21
|
+
}
|
|
22
|
+
else if (fileExists('drizzle.config.json')) {
|
|
23
|
+
detectedOrmConfig = 'drizzle.config.json';
|
|
24
|
+
databaseOrm = 'Drizzle ORM';
|
|
25
|
+
}
|
|
26
|
+
if (fileExists('knexfile.js')) {
|
|
27
|
+
detectedOrmConfig = 'knexfile.js';
|
|
28
|
+
databaseOrm = 'Knex';
|
|
29
|
+
}
|
|
30
|
+
else if (fileExists('knexfile.ts')) {
|
|
31
|
+
detectedOrmConfig = 'knexfile.ts';
|
|
32
|
+
databaseOrm = 'Knex';
|
|
33
|
+
}
|
|
34
|
+
if (fileExists('alembic.ini')) {
|
|
35
|
+
detectedOrmConfig = 'alembic.ini';
|
|
36
|
+
databaseOrm = databaseOrm === 'None detected' ? 'SQLAlchemy (Alembic)' : `${databaseOrm} (Alembic)`;
|
|
37
|
+
}
|
|
38
|
+
if (fileExists('database/migrations')) {
|
|
39
|
+
try {
|
|
40
|
+
const isDir = fs.statSync(path.join(resolvedTarget, 'database/migrations')).isDirectory();
|
|
41
|
+
if (isDir) {
|
|
42
|
+
detectedOrmConfig = 'database/migrations';
|
|
43
|
+
if (databaseOrm === 'None detected')
|
|
44
|
+
databaseOrm = 'SQL Migrations';
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
catch {
|
|
48
|
+
// ignore
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
if (fileExists('ormconfig.json')) {
|
|
52
|
+
detectedOrmConfig = 'ormconfig.json';
|
|
53
|
+
databaseOrm = 'TypeORM';
|
|
54
|
+
}
|
|
55
|
+
return {
|
|
56
|
+
detectedOrmConfig,
|
|
57
|
+
databaseOrm,
|
|
58
|
+
};
|
|
59
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export interface SubServiceInfo {
|
|
2
|
+
name: string;
|
|
3
|
+
dirPath: string;
|
|
4
|
+
manifests: string[];
|
|
5
|
+
tech: string;
|
|
6
|
+
runtime?: string;
|
|
7
|
+
framework?: string;
|
|
8
|
+
orm?: string;
|
|
9
|
+
ormConfig?: string;
|
|
10
|
+
}
|
|
11
|
+
export interface WorkspaceDetectionResult {
|
|
12
|
+
monorepoIndicators: string[];
|
|
13
|
+
monorepoWorkspaces: string[];
|
|
14
|
+
keyDirectories: string[];
|
|
15
|
+
detectedSubpackagesCount: number;
|
|
16
|
+
independentServices: SubServiceInfo[];
|
|
17
|
+
ecosystemManifests: string[];
|
|
18
|
+
}
|
|
19
|
+
export declare function detectWorkspacesAndServices(resolvedTarget: string, fileExists: (relPath: string) => boolean, readFileSafe: (filePath: string) => string): WorkspaceDetectionResult;
|