@runmist/frameworks 1.1.0
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/LICENSE +21 -0
- package/README.md +53 -0
- package/dist/analyze-repo.d.ts +10 -0
- package/dist/analyze-repo.d.ts.map +1 -0
- package/dist/analyze-repo.js +80 -0
- package/dist/detect-framework.d.ts +7 -0
- package/dist/detect-framework.d.ts.map +1 -0
- package/dist/detect-framework.js +37 -0
- package/dist/detect-monorepo.d.ts +3 -0
- package/dist/detect-monorepo.d.ts.map +1 -0
- package/dist/detect-monorepo.js +23 -0
- package/dist/detect-orm.d.ts +8 -0
- package/dist/detect-orm.d.ts.map +1 -0
- package/dist/detect-orm.js +19 -0
- package/dist/detect-runtime.d.ts +11 -0
- package/dist/detect-runtime.d.ts.map +1 -0
- package/dist/detect-runtime.js +30 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +8 -0
- package/dist/orm-presets.d.ts +9 -0
- package/dist/orm-presets.d.ts.map +1 -0
- package/dist/orm-presets.js +66 -0
- package/dist/presets.d.ts +10 -0
- package/dist/presets.d.ts.map +1 -0
- package/dist/presets.js +154 -0
- package/dist/runtime-versions.d.ts +7 -0
- package/dist/runtime-versions.d.ts.map +1 -0
- package/dist/runtime-versions.js +6 -0
- package/dist/types.d.ts +41 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +0 -0
- package/package.json +53 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Daniel Chavez
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# @bitclaw/frameworks
|
|
2
|
+
|
|
3
|
+
Framework, ORM, runtime, and monorepo detection for deployment pipelines. Built on Bun.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **Framework detection** Identifies Next.js, Remix, Astro, SvelteKit, Nuxt, and more from `package.json` deps
|
|
8
|
+
- **ORM detection** Detects Prisma, Drizzle, Sequelize, TypeORM, Mongoose, and others
|
|
9
|
+
- **Runtime detection** Identifies Bun vs Node.js with version resolution
|
|
10
|
+
- **Monorepo detection** Detects Turborepo, Nx, PNPM workspaces, Bun workspaces, Lerna
|
|
11
|
+
- **Repo analysis** Full `analyzeRepo` combining all detections in one pass
|
|
12
|
+
- **Presets** Deployment presets per framework (build command, output dir, install command)
|
|
13
|
+
|
|
14
|
+
## Installation
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
bun add @bitclaw/frameworks
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Quick Start
|
|
21
|
+
|
|
22
|
+
```typescript
|
|
23
|
+
import { analyzeRepo } from '@bitclaw/frameworks'
|
|
24
|
+
|
|
25
|
+
const result = await analyzeRepo('/path/to/repo')
|
|
26
|
+
console.log(result)
|
|
27
|
+
// {
|
|
28
|
+
// framework: { name: 'nextjs', confidence: 'high' },
|
|
29
|
+
// orm: { name: 'prisma' },
|
|
30
|
+
// runtime: { name: 'bun', version: '1.3.0' },
|
|
31
|
+
// monorepo: null,
|
|
32
|
+
// packageManager: 'bun'
|
|
33
|
+
// }
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## API
|
|
37
|
+
|
|
38
|
+
```typescript
|
|
39
|
+
analyzeRepo(dir) // → Promise<RepoDetectionResult>
|
|
40
|
+
detectFramework(packageJson) // → DetectedApp | null
|
|
41
|
+
detectOrm(packageJson) // → OrmPreset | null
|
|
42
|
+
detectRuntime(dir) // → Promise<{ name, version }>
|
|
43
|
+
detectMonorepo(dir) // → Promise<MonorepoInfo | null>
|
|
44
|
+
detectPackageManager(dir) // → Promise<'bun' | 'npm' | 'pnpm' | 'yarn'>
|
|
45
|
+
getPreset(frameworkName) // → FrameworkPreset | null
|
|
46
|
+
getOrmPreset(ormName) // → OrmPreset | null
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## Testing
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
bun test
|
|
53
|
+
```
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { RepoDetectionResult } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* Analyze a repository's file tree and package.json contents to detect
|
|
4
|
+
* monorepo structure, frameworks, and runtimes.
|
|
5
|
+
*
|
|
6
|
+
* @param filePaths - All file paths in the repo (from git tree API)
|
|
7
|
+
* @param packageJsonContents - Map of file path to parsed package.json content string
|
|
8
|
+
*/
|
|
9
|
+
export declare function analyzeRepo(filePaths: string[], packageJsonContents: Map<string, string>): RepoDetectionResult;
|
|
10
|
+
//# sourceMappingURL=analyze-repo.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"analyze-repo.d.ts","sourceRoot":"","sources":["../src/analyze-repo.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAe,mBAAmB,EAAE,MAAM,SAAS,CAAC;AAEhE;;;;;;GAMG;AACH,wBAAgB,WAAW,CACzB,SAAS,EAAE,MAAM,EAAE,EACnB,mBAAmB,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,GACvC,mBAAmB,CAsErB"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { detectFramework } from './detect-framework';
|
|
2
|
+
import { detectMonorepo } from './detect-monorepo';
|
|
3
|
+
import { detectOrm } from './detect-orm';
|
|
4
|
+
import { detectPackageManager, detectRuntime } from './detect-runtime';
|
|
5
|
+
/**
|
|
6
|
+
* Analyze a repository's file tree and package.json contents to detect
|
|
7
|
+
* monorepo structure, frameworks, and runtimes.
|
|
8
|
+
*
|
|
9
|
+
* @param filePaths - All file paths in the repo (from git tree API)
|
|
10
|
+
* @param packageJsonContents - Map of file path to parsed package.json content string
|
|
11
|
+
*/
|
|
12
|
+
export function analyzeRepo(filePaths, packageJsonContents) {
|
|
13
|
+
const packageManager = detectPackageManager(filePaths);
|
|
14
|
+
const monorepo = detectMonorepo(filePaths);
|
|
15
|
+
// Detect root-level framework
|
|
16
|
+
let rootFramework = null;
|
|
17
|
+
let rootRuntime = null;
|
|
18
|
+
let rootParsed = null;
|
|
19
|
+
const rootPkgJson = packageJsonContents.get('package.json');
|
|
20
|
+
if (rootPkgJson) {
|
|
21
|
+
try {
|
|
22
|
+
rootParsed = JSON.parse(rootPkgJson);
|
|
23
|
+
rootFramework = detectFramework(rootParsed);
|
|
24
|
+
rootRuntime = detectRuntime(rootFramework, filePaths);
|
|
25
|
+
}
|
|
26
|
+
catch {
|
|
27
|
+
// Invalid JSON, skip
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
if (!monorepo.isMonorepo) {
|
|
31
|
+
// Single-app repo
|
|
32
|
+
const apps = [];
|
|
33
|
+
if (rootFramework) {
|
|
34
|
+
apps.push({
|
|
35
|
+
name: '.',
|
|
36
|
+
path: '.',
|
|
37
|
+
framework: rootFramework,
|
|
38
|
+
runtime: rootRuntime,
|
|
39
|
+
orm: detectOrm(rootParsed ?? {})
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
return {
|
|
43
|
+
isMonorepo: false,
|
|
44
|
+
apps,
|
|
45
|
+
rootFramework,
|
|
46
|
+
rootRuntime,
|
|
47
|
+
packageManager
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
// Monorepo: analyze each app directory
|
|
51
|
+
const apps = [];
|
|
52
|
+
for (const appDir of monorepo.appDirs) {
|
|
53
|
+
const pkgPath = `apps/${appDir}/package.json`;
|
|
54
|
+
const pkgContent = packageJsonContents.get(pkgPath);
|
|
55
|
+
if (!pkgContent)
|
|
56
|
+
continue;
|
|
57
|
+
try {
|
|
58
|
+
const parsed = JSON.parse(pkgContent);
|
|
59
|
+
const framework = detectFramework(parsed);
|
|
60
|
+
const runtime = detectRuntime(framework, filePaths);
|
|
61
|
+
apps.push({
|
|
62
|
+
name: appDir,
|
|
63
|
+
path: `apps/${appDir}`,
|
|
64
|
+
framework,
|
|
65
|
+
runtime,
|
|
66
|
+
orm: detectOrm(parsed)
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
catch {
|
|
70
|
+
// Invalid JSON, skip this app
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
return {
|
|
74
|
+
isMonorepo: true,
|
|
75
|
+
apps,
|
|
76
|
+
rootFramework,
|
|
77
|
+
rootRuntime,
|
|
78
|
+
packageManager
|
|
79
|
+
};
|
|
80
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"detect-framework.d.ts","sourceRoot":"","sources":["../src/detect-framework.ts"],"names":[],"mappings":"AAAA,KAAK,WAAW,GAAG;IACjB,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACtC,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC1C,CAAC;AAgCF,wBAAgB,eAAe,CAAC,WAAW,EAAE,WAAW,GAAG,MAAM,GAAG,IAAI,CAkBvE"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ordered by specificity: meta-frameworks first, then base tools last.
|
|
3
|
+
* Higher-specificity frameworks supersede lower ones (e.g. TanStack Start supersedes Nitro and Vite).
|
|
4
|
+
*/
|
|
5
|
+
const DETECTION_RULES = [
|
|
6
|
+
{ id: 'tanstack-start', matchPackages: ['@tanstack/react-start'] },
|
|
7
|
+
{ id: 'nextjs', matchPackages: ['next'] },
|
|
8
|
+
{ id: 'nuxt', matchPackages: ['nuxt', 'nuxt3'] },
|
|
9
|
+
{ id: 'sveltekit', matchPackages: ['@sveltejs/kit'] },
|
|
10
|
+
{ id: 'astro', matchPackages: ['astro'] },
|
|
11
|
+
{
|
|
12
|
+
id: 'react-router',
|
|
13
|
+
matchPackages: ['@react-router/dev', '@remix-run/dev']
|
|
14
|
+
},
|
|
15
|
+
{ id: 'nitro', matchPackages: ['nitropack', 'nitro'] },
|
|
16
|
+
{ id: 'hono', matchPackages: ['hono'] },
|
|
17
|
+
{ id: 'elysia', matchPackages: ['elysia'] },
|
|
18
|
+
{ id: 'express', matchPackages: ['express'] },
|
|
19
|
+
{ id: 'fastify', matchPackages: ['fastify'] },
|
|
20
|
+
{ id: 'vite', matchPackages: ['vite'], devOnly: true }
|
|
21
|
+
];
|
|
22
|
+
export function detectFramework(packageJson) {
|
|
23
|
+
const deps = packageJson.dependencies ?? {};
|
|
24
|
+
const devDeps = packageJson.devDependencies ?? {};
|
|
25
|
+
for (const rule of DETECTION_RULES) {
|
|
26
|
+
const hasDep = rule.matchPackages.some(pkg => {
|
|
27
|
+
if (rule.devOnly) {
|
|
28
|
+
return pkg in devDeps;
|
|
29
|
+
}
|
|
30
|
+
return pkg in deps || pkg in devDeps;
|
|
31
|
+
});
|
|
32
|
+
if (hasDep) {
|
|
33
|
+
return rule.id;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return null;
|
|
37
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"detect-monorepo.d.ts","sourceRoot":"","sources":["../src/detect-monorepo.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAW5C,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,YAAY,CAkBhE"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
const MONOREPO_INDICATORS = [
|
|
2
|
+
'pnpm-workspace.yaml',
|
|
3
|
+
'turbo.json',
|
|
4
|
+
'lerna.json',
|
|
5
|
+
'nx.json'
|
|
6
|
+
];
|
|
7
|
+
const APP_DIR_PATTERN = /^apps\/([^/]+)\/package\.json$/;
|
|
8
|
+
export function detectMonorepo(filePaths) {
|
|
9
|
+
const hasIndicator = filePaths.some(p => MONOREPO_INDICATORS.includes(p));
|
|
10
|
+
// Also check for workspaces in root package.json (handled by caller via packageJsonContents)
|
|
11
|
+
// Here we just detect via file-based indicators
|
|
12
|
+
const appDirs = [];
|
|
13
|
+
for (const fp of filePaths) {
|
|
14
|
+
const match = APP_DIR_PATTERN.exec(fp);
|
|
15
|
+
if (match?.[1]) {
|
|
16
|
+
appDirs.push(match[1]);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
return {
|
|
20
|
+
isMonorepo: hasIndicator && appDirs.length > 0,
|
|
21
|
+
appDirs
|
|
22
|
+
};
|
|
23
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { OrmPresetId } from './types';
|
|
2
|
+
type PackageJson = {
|
|
3
|
+
dependencies?: Record<string, string>;
|
|
4
|
+
devDependencies?: Record<string, string>;
|
|
5
|
+
};
|
|
6
|
+
export declare function detectOrm(packageJson: PackageJson): OrmPresetId;
|
|
7
|
+
export {};
|
|
8
|
+
//# sourceMappingURL=detect-orm.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"detect-orm.d.ts","sourceRoot":"","sources":["../src/detect-orm.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAE3C,KAAK,WAAW,GAAG;IACjB,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACtC,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC1C,CAAC;AAEF,wBAAgB,SAAS,CAAC,WAAW,EAAE,WAAW,GAAG,WAAW,CAc/D"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export function detectOrm(packageJson) {
|
|
2
|
+
const deps = {
|
|
3
|
+
...packageJson.dependencies,
|
|
4
|
+
...packageJson.devDependencies
|
|
5
|
+
};
|
|
6
|
+
if (deps.prisma || deps['@prisma/client'])
|
|
7
|
+
return 'prisma';
|
|
8
|
+
if (deps['drizzle-orm'])
|
|
9
|
+
return 'drizzle';
|
|
10
|
+
if (deps.typeorm)
|
|
11
|
+
return 'typeorm';
|
|
12
|
+
if (deps.knex)
|
|
13
|
+
return 'knex';
|
|
14
|
+
if (deps['@mikro-orm/core'] || deps['mikro-orm'])
|
|
15
|
+
return 'mikro-orm';
|
|
16
|
+
if (deps.sequelize)
|
|
17
|
+
return 'sequelize';
|
|
18
|
+
return 'none';
|
|
19
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Detect the runtime for a given framework.
|
|
3
|
+
* Uses the framework preset's default runtime.
|
|
4
|
+
*/
|
|
5
|
+
export declare function detectRuntime(detectedFramework: string | null, _filePaths: string[]): 'bun' | 'node' | null;
|
|
6
|
+
/**
|
|
7
|
+
* Detect the package manager from lockfiles in the file tree.
|
|
8
|
+
* Checks root-level lockfiles only.
|
|
9
|
+
*/
|
|
10
|
+
export declare function detectPackageManager(filePaths: string[]): 'bun' | 'npm' | 'yarn' | 'pnpm' | null;
|
|
11
|
+
//# sourceMappingURL=detect-runtime.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"detect-runtime.d.ts","sourceRoot":"","sources":["../src/detect-runtime.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,wBAAgB,aAAa,CAC3B,iBAAiB,EAAE,MAAM,GAAG,IAAI,EAChC,UAAU,EAAE,MAAM,EAAE,GACnB,KAAK,GAAG,MAAM,GAAG,IAAI,CAIvB;AAUD;;;GAGG;AACH,wBAAgB,oBAAoB,CAClC,SAAS,EAAE,MAAM,EAAE,GAClB,KAAK,GAAG,KAAK,GAAG,MAAM,GAAG,MAAM,GAAG,IAAI,CAMxC"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { getPreset } from './presets';
|
|
2
|
+
/**
|
|
3
|
+
* Detect the runtime for a given framework.
|
|
4
|
+
* Uses the framework preset's default runtime.
|
|
5
|
+
*/
|
|
6
|
+
export function detectRuntime(detectedFramework, _filePaths) {
|
|
7
|
+
if (!detectedFramework)
|
|
8
|
+
return null;
|
|
9
|
+
const preset = getPreset(detectedFramework);
|
|
10
|
+
return preset?.runtime ?? null;
|
|
11
|
+
}
|
|
12
|
+
const LOCKFILE_MAP = {
|
|
13
|
+
'bun.lockb': 'bun',
|
|
14
|
+
'bun.lock': 'bun',
|
|
15
|
+
'package-lock.json': 'npm',
|
|
16
|
+
'yarn.lock': 'yarn',
|
|
17
|
+
'pnpm-lock.yaml': 'pnpm'
|
|
18
|
+
};
|
|
19
|
+
/**
|
|
20
|
+
* Detect the package manager from lockfiles in the file tree.
|
|
21
|
+
* Checks root-level lockfiles only.
|
|
22
|
+
*/
|
|
23
|
+
export function detectPackageManager(filePaths) {
|
|
24
|
+
for (const fp of filePaths) {
|
|
25
|
+
const pm = LOCKFILE_MAP[fp];
|
|
26
|
+
if (pm)
|
|
27
|
+
return pm;
|
|
28
|
+
}
|
|
29
|
+
return null;
|
|
30
|
+
}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export { analyzeRepo } from './analyze-repo';
|
|
2
|
+
export { detectFramework } from './detect-framework';
|
|
3
|
+
export { detectMonorepo } from './detect-monorepo';
|
|
4
|
+
export { detectOrm } from './detect-orm';
|
|
5
|
+
export { detectPackageManager, detectRuntime } from './detect-runtime';
|
|
6
|
+
export { getOrmPreset, ORM_PRESET_OPTIONS, ORM_PRESETS } from './orm-presets';
|
|
7
|
+
export { FRAMEWORK_PRESET_OPTIONS, FRAMEWORK_PRESETS, getPreset } from './presets';
|
|
8
|
+
export type { BunVersion, NodeVersion } from './runtime-versions';
|
|
9
|
+
export { BUN_VERSIONS, DEFAULT_BUN_VERSION, DEFAULT_NODE_VERSION, NODE_VERSIONS } from './runtime-versions';
|
|
10
|
+
export type { DeployHookId, DetectedApp, FrameworkPreset, MonorepoInfo, OrmPreset, OrmPresetId, RepoDetectionResult } from './types';
|
|
11
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC7C,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACzC,OAAO,EAAE,oBAAoB,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACvE,OAAO,EACL,YAAY,EACZ,kBAAkB,EAClB,WAAW,EACZ,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,wBAAwB,EACxB,iBAAiB,EACjB,SAAS,EACV,MAAM,WAAW,CAAC;AACnB,YAAY,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAClE,OAAO,EACL,YAAY,EACZ,mBAAmB,EACnB,oBAAoB,EACpB,aAAa,EACd,MAAM,oBAAoB,CAAC;AAC5B,YAAY,EACV,YAAY,EACZ,WAAW,EACX,eAAe,EACf,YAAY,EACZ,SAAS,EACT,WAAW,EACX,mBAAmB,EACpB,MAAM,SAAS,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export { analyzeRepo } from './analyze-repo';
|
|
2
|
+
export { detectFramework } from './detect-framework';
|
|
3
|
+
export { detectMonorepo } from './detect-monorepo';
|
|
4
|
+
export { detectOrm } from './detect-orm';
|
|
5
|
+
export { detectPackageManager, detectRuntime } from './detect-runtime';
|
|
6
|
+
export { getOrmPreset, ORM_PRESET_OPTIONS, ORM_PRESETS } from './orm-presets';
|
|
7
|
+
export { FRAMEWORK_PRESET_OPTIONS, FRAMEWORK_PRESETS, getPreset } from './presets';
|
|
8
|
+
export { BUN_VERSIONS, DEFAULT_BUN_VERSION, DEFAULT_NODE_VERSION, NODE_VERSIONS } from './runtime-versions';
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { OrmPreset } from './types';
|
|
2
|
+
export declare const ORM_PRESETS: OrmPreset[];
|
|
3
|
+
export declare function getOrmPreset(id: string): OrmPreset | undefined;
|
|
4
|
+
export declare const ORM_PRESET_OPTIONS: {
|
|
5
|
+
value: import("./types").OrmPresetId;
|
|
6
|
+
label: string;
|
|
7
|
+
description: string;
|
|
8
|
+
}[];
|
|
9
|
+
//# sourceMappingURL=orm-presets.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"orm-presets.d.ts","sourceRoot":"","sources":["../src/orm-presets.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAEzC,eAAO,MAAM,WAAW,EAAE,SAAS,EAyDlC,CAAC;AAEF,wBAAgB,YAAY,CAAC,EAAE,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS,CAE9D;AAED,eAAO,MAAM,kBAAkB;;;;GAI5B,CAAC"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
export const ORM_PRESETS = [
|
|
2
|
+
{
|
|
3
|
+
id: 'none',
|
|
4
|
+
name: 'None',
|
|
5
|
+
description: 'No ORM — manage migrations manually'
|
|
6
|
+
},
|
|
7
|
+
{
|
|
8
|
+
id: 'prisma',
|
|
9
|
+
name: 'Prisma',
|
|
10
|
+
description: 'Type-safe ORM with auto-generated client',
|
|
11
|
+
hooks: {
|
|
12
|
+
'after-install': [
|
|
13
|
+
'PRISMA_SCHEMA_DISABLE_ADVISORY_LOCK=1 npx prisma generate',
|
|
14
|
+
'PRISMA_SCHEMA_DISABLE_ADVISORY_LOCK=1 npx prisma migrate deploy'
|
|
15
|
+
]
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
id: 'drizzle',
|
|
20
|
+
name: 'Drizzle',
|
|
21
|
+
description: 'Lightweight TypeScript ORM',
|
|
22
|
+
hooks: {
|
|
23
|
+
'after-install': ['npx drizzle-kit migrate']
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
id: 'knex',
|
|
28
|
+
name: 'Knex.js',
|
|
29
|
+
description: 'SQL query builder with migrations',
|
|
30
|
+
hooks: {
|
|
31
|
+
'after-install': ['npx knex migrate:latest']
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
id: 'typeorm',
|
|
36
|
+
name: 'TypeORM',
|
|
37
|
+
description: 'ORM for TypeScript and JavaScript',
|
|
38
|
+
hooks: {
|
|
39
|
+
'after-install': ['npx typeorm migration:run -d ./data-source.ts']
|
|
40
|
+
}
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
id: 'mikro-orm',
|
|
44
|
+
name: 'MikroORM',
|
|
45
|
+
description: 'TypeScript ORM with unit of work',
|
|
46
|
+
hooks: {
|
|
47
|
+
'after-install': ['npx mikro-orm migration:up']
|
|
48
|
+
}
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
id: 'sequelize',
|
|
52
|
+
name: 'Sequelize',
|
|
53
|
+
description: 'Promise-based Node.js ORM',
|
|
54
|
+
hooks: {
|
|
55
|
+
'after-install': ['npx sequelize-cli db:migrate']
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
];
|
|
59
|
+
export function getOrmPreset(id) {
|
|
60
|
+
return ORM_PRESETS.find(p => p.id === id);
|
|
61
|
+
}
|
|
62
|
+
export const ORM_PRESET_OPTIONS = ORM_PRESETS.map(p => ({
|
|
63
|
+
value: p.id,
|
|
64
|
+
label: p.name,
|
|
65
|
+
description: p.description
|
|
66
|
+
}));
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { FrameworkPreset } from './types';
|
|
2
|
+
export declare const FRAMEWORK_PRESETS: FrameworkPreset[];
|
|
3
|
+
export declare function getPreset(id: string): FrameworkPreset | undefined;
|
|
4
|
+
/** Pre-computed combobox items -- avoids re-creating on every render. */
|
|
5
|
+
export declare const FRAMEWORK_PRESET_OPTIONS: {
|
|
6
|
+
value: string;
|
|
7
|
+
label: string;
|
|
8
|
+
description: string;
|
|
9
|
+
}[];
|
|
10
|
+
//# sourceMappingURL=presets.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"presets.d.ts","sourceRoot":"","sources":["../src/presets.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAE/C,eAAO,MAAM,iBAAiB,EAAE,eAAe,EAgJ9C,CAAC;AAEF,wBAAgB,SAAS,CAAC,EAAE,EAAE,MAAM,GAAG,eAAe,GAAG,SAAS,CAEjE;AAED,yEAAyE;AACzE,eAAO,MAAM,wBAAwB;;;;GAIlC,CAAC"}
|
package/dist/presets.js
ADDED
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
export const FRAMEWORK_PRESETS = [
|
|
2
|
+
{
|
|
3
|
+
id: 'tanstack-start',
|
|
4
|
+
name: 'TanStack Start',
|
|
5
|
+
description: 'TanStack Start with Nitro',
|
|
6
|
+
runtime: 'bun',
|
|
7
|
+
installCommand: 'bun install --frozen-lockfile',
|
|
8
|
+
buildCommand: 'bun run build',
|
|
9
|
+
startCommand: 'bun .output/server/index.mjs',
|
|
10
|
+
outputDirectory: '.output/public',
|
|
11
|
+
staticUrlPath: '/assets/*'
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
id: 'nitro',
|
|
15
|
+
name: 'Nitro',
|
|
16
|
+
description: 'UnJS Nitro server framework',
|
|
17
|
+
runtime: 'bun',
|
|
18
|
+
installCommand: 'bun install --frozen-lockfile',
|
|
19
|
+
buildCommand: 'bun run build',
|
|
20
|
+
startCommand: 'bun .output/server/index.mjs',
|
|
21
|
+
outputDirectory: '.output/public',
|
|
22
|
+
staticUrlPath: '/assets/*'
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
id: 'react-router',
|
|
26
|
+
name: 'React Router',
|
|
27
|
+
description: 'React Router v7 / Remix',
|
|
28
|
+
runtime: 'node',
|
|
29
|
+
installCommand: 'npm install',
|
|
30
|
+
buildCommand: 'npm run build',
|
|
31
|
+
startCommand: 'node index.js',
|
|
32
|
+
outputDirectory: 'build/client',
|
|
33
|
+
staticUrlPath: '/build/*'
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
id: 'nextjs',
|
|
37
|
+
name: 'Next.js',
|
|
38
|
+
description: 'React framework by Vercel',
|
|
39
|
+
runtime: 'node',
|
|
40
|
+
installCommand: 'npm install',
|
|
41
|
+
buildCommand: 'npm run build',
|
|
42
|
+
startCommand: 'node server.js',
|
|
43
|
+
outputDirectory: '.next',
|
|
44
|
+
staticUrlPath: '/_next/*'
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
id: 'nuxt',
|
|
48
|
+
name: 'Nuxt',
|
|
49
|
+
description: 'Vue.js full-stack framework',
|
|
50
|
+
runtime: 'node',
|
|
51
|
+
installCommand: 'npm install',
|
|
52
|
+
buildCommand: 'npm run build',
|
|
53
|
+
startCommand: 'node .output/server/index.mjs',
|
|
54
|
+
outputDirectory: '.output/public',
|
|
55
|
+
staticUrlPath: '/_nuxt/*'
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
id: 'sveltekit',
|
|
59
|
+
name: 'SvelteKit',
|
|
60
|
+
description: 'Svelte app framework',
|
|
61
|
+
runtime: 'node',
|
|
62
|
+
installCommand: 'npm install',
|
|
63
|
+
buildCommand: 'npm run build',
|
|
64
|
+
startCommand: 'node build/index.js',
|
|
65
|
+
outputDirectory: 'build/client',
|
|
66
|
+
staticUrlPath: '/_app/immutable/*'
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
id: 'astro',
|
|
70
|
+
name: 'Astro',
|
|
71
|
+
description: 'Content-focused web framework',
|
|
72
|
+
runtime: 'node',
|
|
73
|
+
installCommand: 'npm install',
|
|
74
|
+
buildCommand: 'npm run build',
|
|
75
|
+
startCommand: 'node ./dist/server/entry.mjs',
|
|
76
|
+
outputDirectory: 'dist/client',
|
|
77
|
+
staticUrlPath: '/_astro/*'
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
id: 'vite',
|
|
81
|
+
name: 'Vite',
|
|
82
|
+
description: 'Frontend build tool',
|
|
83
|
+
runtime: 'bun',
|
|
84
|
+
installCommand: 'bun install --frozen-lockfile',
|
|
85
|
+
buildCommand: 'bun run build',
|
|
86
|
+
startCommand: 'bun run preview',
|
|
87
|
+
outputDirectory: 'dist',
|
|
88
|
+
staticUrlPath: '/assets/*'
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
id: 'hono',
|
|
92
|
+
name: 'Hono',
|
|
93
|
+
description: 'Lightweight web framework',
|
|
94
|
+
runtime: 'bun',
|
|
95
|
+
installCommand: 'bun install --frozen-lockfile',
|
|
96
|
+
buildCommand: 'bun run build',
|
|
97
|
+
startCommand: 'bun run start',
|
|
98
|
+
outputDirectory: 'dist',
|
|
99
|
+
staticUrlPath: null
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
id: 'elysia',
|
|
103
|
+
name: 'Elysia',
|
|
104
|
+
description: 'Bun-first web framework',
|
|
105
|
+
runtime: 'bun',
|
|
106
|
+
installCommand: 'bun install --frozen-lockfile',
|
|
107
|
+
buildCommand: 'bun run build',
|
|
108
|
+
startCommand: 'bun run start',
|
|
109
|
+
outputDirectory: 'dist',
|
|
110
|
+
staticUrlPath: null
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
id: 'express',
|
|
114
|
+
name: 'Express',
|
|
115
|
+
description: 'Node.js web framework',
|
|
116
|
+
runtime: 'node',
|
|
117
|
+
installCommand: 'npm install',
|
|
118
|
+
buildCommand: 'npm run build',
|
|
119
|
+
startCommand: 'node dist/index.js',
|
|
120
|
+
outputDirectory: 'dist',
|
|
121
|
+
staticUrlPath: null
|
|
122
|
+
},
|
|
123
|
+
{
|
|
124
|
+
id: 'fastify',
|
|
125
|
+
name: 'Fastify',
|
|
126
|
+
description: 'Fast Node.js web framework',
|
|
127
|
+
runtime: 'node',
|
|
128
|
+
installCommand: 'npm install',
|
|
129
|
+
buildCommand: 'npm run build',
|
|
130
|
+
startCommand: 'node dist/index.js',
|
|
131
|
+
outputDirectory: 'dist',
|
|
132
|
+
staticUrlPath: null
|
|
133
|
+
},
|
|
134
|
+
{
|
|
135
|
+
id: 'other',
|
|
136
|
+
name: 'Other',
|
|
137
|
+
description: 'Custom application',
|
|
138
|
+
runtime: 'bun',
|
|
139
|
+
installCommand: 'bun install',
|
|
140
|
+
buildCommand: 'bun run build',
|
|
141
|
+
startCommand: 'bun run start',
|
|
142
|
+
outputDirectory: 'dist',
|
|
143
|
+
staticUrlPath: null
|
|
144
|
+
}
|
|
145
|
+
];
|
|
146
|
+
export function getPreset(id) {
|
|
147
|
+
return FRAMEWORK_PRESETS.find(p => p.id === id);
|
|
148
|
+
}
|
|
149
|
+
/** Pre-computed combobox items -- avoids re-creating on every render. */
|
|
150
|
+
export const FRAMEWORK_PRESET_OPTIONS = FRAMEWORK_PRESETS.map(p => ({
|
|
151
|
+
value: p.id,
|
|
152
|
+
label: p.name,
|
|
153
|
+
description: p.description
|
|
154
|
+
}));
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export declare const NODE_VERSIONS: readonly ["22.x", "20.x", "18.x"];
|
|
2
|
+
export declare const DEFAULT_NODE_VERSION = "22.x";
|
|
3
|
+
export declare const BUN_VERSIONS: readonly ["latest", "1.3", "1.2", "1.1"];
|
|
4
|
+
export declare const DEFAULT_BUN_VERSION = "latest";
|
|
5
|
+
export type NodeVersion = (typeof NODE_VERSIONS)[number];
|
|
6
|
+
export type BunVersion = (typeof BUN_VERSIONS)[number];
|
|
7
|
+
//# sourceMappingURL=runtime-versions.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime-versions.d.ts","sourceRoot":"","sources":["../src/runtime-versions.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,aAAa,mCAAoC,CAAC;AAC/D,eAAO,MAAM,oBAAoB,SAAS,CAAC;AAI3C,eAAO,MAAM,YAAY,0CAA2C,CAAC;AACrE,eAAO,MAAM,mBAAmB,WAAW,CAAC;AAE5C,MAAM,MAAM,WAAW,GAAG,CAAC,OAAO,aAAa,CAAC,CAAC,MAAM,CAAC,CAAC;AACzD,MAAM,MAAM,UAAU,GAAG,CAAC,OAAO,YAAY,CAAC,CAAC,MAAM,CAAC,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export const NODE_VERSIONS = ['22.x', '20.x', '18.x'];
|
|
2
|
+
export const DEFAULT_NODE_VERSION = '22.x';
|
|
3
|
+
// Bun versions — "latest" installs whatever is current at deploy time
|
|
4
|
+
// Pinned versions (1.3, 1.2, 1.1) resolve to latest patch via the official installer
|
|
5
|
+
export const BUN_VERSIONS = ['latest', '1.3', '1.2', '1.1'];
|
|
6
|
+
export const DEFAULT_BUN_VERSION = 'latest';
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
export type DeployHookId = 'after-install' | 'before-activate' | 'after-activate' | 'on-fail';
|
|
2
|
+
export type OrmPresetId = 'prisma' | 'drizzle' | 'knex' | 'typeorm' | 'mikro-orm' | 'sequelize' | 'none';
|
|
3
|
+
export type OrmPreset = {
|
|
4
|
+
id: OrmPresetId;
|
|
5
|
+
name: string;
|
|
6
|
+
description: string;
|
|
7
|
+
hooks?: Partial<Record<DeployHookId, string[]>>;
|
|
8
|
+
};
|
|
9
|
+
export type FrameworkPreset = {
|
|
10
|
+
id: string;
|
|
11
|
+
name: string;
|
|
12
|
+
description: string;
|
|
13
|
+
runtime: 'bun' | 'node';
|
|
14
|
+
installCommand: string;
|
|
15
|
+
buildCommand: string;
|
|
16
|
+
startCommand: string;
|
|
17
|
+
outputDirectory: string;
|
|
18
|
+
/** Caddy URL path for static asset interception (e.g. "/build/*", "/assets/*"). Null for API-only frameworks. */
|
|
19
|
+
staticUrlPath: string | null;
|
|
20
|
+
/** Deploy hook commands keyed by hook point in the pipeline */
|
|
21
|
+
hooks?: Partial<Record<DeployHookId, string[]>>;
|
|
22
|
+
};
|
|
23
|
+
export type DetectedApp = {
|
|
24
|
+
name: string;
|
|
25
|
+
path: string;
|
|
26
|
+
framework: string | null;
|
|
27
|
+
runtime: 'bun' | 'node' | null;
|
|
28
|
+
orm: OrmPresetId;
|
|
29
|
+
};
|
|
30
|
+
export type MonorepoInfo = {
|
|
31
|
+
isMonorepo: boolean;
|
|
32
|
+
appDirs: string[];
|
|
33
|
+
};
|
|
34
|
+
export type RepoDetectionResult = {
|
|
35
|
+
isMonorepo: boolean;
|
|
36
|
+
apps: DetectedApp[];
|
|
37
|
+
rootFramework: string | null;
|
|
38
|
+
rootRuntime: 'bun' | 'node' | null;
|
|
39
|
+
packageManager: 'bun' | 'npm' | 'yarn' | 'pnpm' | null;
|
|
40
|
+
};
|
|
41
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,YAAY,GACpB,eAAe,GACf,iBAAiB,GACjB,gBAAgB,GAChB,SAAS,CAAC;AAEd,MAAM,MAAM,WAAW,GACnB,QAAQ,GACR,SAAS,GACT,MAAM,GACN,SAAS,GACT,WAAW,GACX,WAAW,GACX,MAAM,CAAC;AAEX,MAAM,MAAM,SAAS,GAAG;IACtB,EAAE,EAAE,WAAW,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,YAAY,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC;CACjD,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,KAAK,GAAG,MAAM,CAAC;IACxB,cAAc,EAAE,MAAM,CAAC;IACvB,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,eAAe,EAAE,MAAM,CAAC;IACxB,iHAAiH;IACjH,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,+DAA+D;IAC/D,KAAK,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,YAAY,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC;CACjD,CAAC;AAEF,MAAM,MAAM,WAAW,GAAG;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,OAAO,EAAE,KAAK,GAAG,MAAM,GAAG,IAAI,CAAC;IAC/B,GAAG,EAAE,WAAW,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG;IACzB,UAAU,EAAE,OAAO,CAAC;IACpB,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG;IAChC,UAAU,EAAE,OAAO,CAAC;IACpB,IAAI,EAAE,WAAW,EAAE,CAAC;IACpB,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,WAAW,EAAE,KAAK,GAAG,MAAM,GAAG,IAAI,CAAC;IACnC,cAAc,EAAE,KAAK,GAAG,KAAK,GAAG,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;CACxD,CAAC"}
|
package/dist/types.js
ADDED
|
File without changes
|
package/package.json
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@runmist/frameworks",
|
|
3
|
+
"version": "1.1.0",
|
|
4
|
+
"description": "Framework, ORM, runtime, and monorepo detection for deployment pipelines",
|
|
5
|
+
"files": [
|
|
6
|
+
"dist",
|
|
7
|
+
"LICENSE",
|
|
8
|
+
"README.md"
|
|
9
|
+
],
|
|
10
|
+
"type": "module",
|
|
11
|
+
"main": "./dist/index.js",
|
|
12
|
+
"types": "./dist/index.d.ts",
|
|
13
|
+
"exports": {
|
|
14
|
+
".": {
|
|
15
|
+
"types": "./dist/index.d.ts",
|
|
16
|
+
"default": "./dist/index.js"
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
"scripts": {
|
|
20
|
+
"build": "tsc -p tsconfig.build.json",
|
|
21
|
+
"test": "bun test",
|
|
22
|
+
"test:watch": "bun test --watch",
|
|
23
|
+
"typecheck": "tsc --noEmit",
|
|
24
|
+
"lint": "biome check",
|
|
25
|
+
"lint:fix": "biome check --write",
|
|
26
|
+
"format": "biome format --write",
|
|
27
|
+
"knip": "knip",
|
|
28
|
+
"prepublishOnly": "npm run build && npm test",
|
|
29
|
+
"publish:dev": "npm run build && npm publish --tag dev --access public",
|
|
30
|
+
"publish:patch": "npm whoami && npm version patch && git push --follow-tags && npm publish --access public",
|
|
31
|
+
"publish:minor": "npm whoami && npm version minor && git push --follow-tags && npm publish --access public",
|
|
32
|
+
"publish:major": "npm whoami && npm version major && git push --follow-tags && npm publish --access public"
|
|
33
|
+
},
|
|
34
|
+
"keywords": [
|
|
35
|
+
"framework-detection",
|
|
36
|
+
"orm",
|
|
37
|
+
"monorepo",
|
|
38
|
+
"runtime",
|
|
39
|
+
"deploy",
|
|
40
|
+
"analysis"
|
|
41
|
+
],
|
|
42
|
+
"author": "bitclaw",
|
|
43
|
+
"license": "MIT",
|
|
44
|
+
"devDependencies": {
|
|
45
|
+
"@biomejs/biome": "^2.4.15",
|
|
46
|
+
"knip": "^6.12.1",
|
|
47
|
+
"@types/bun": "^1.3.9",
|
|
48
|
+
"typescript": "^5.8.3"
|
|
49
|
+
},
|
|
50
|
+
"engines": {
|
|
51
|
+
"bun": ">=1.3.0"
|
|
52
|
+
}
|
|
53
|
+
}
|