stackinit 0.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/.editorconfig +18 -0
- package/.env.example +11 -0
- package/.eslintrc.json +30 -0
- package/.github/workflows/ci.yml +36 -0
- package/.prettierignore +11 -0
- package/.prettierrc.json +10 -0
- package/CONTRIBUTING.md +272 -0
- package/Dockerfile +36 -0
- package/LICENSE +22 -0
- package/README.md +202 -0
- package/dist/banner.d.ts +2 -0
- package/dist/banner.d.ts.map +1 -0
- package/dist/banner.js +16 -0
- package/dist/banner.js.map +1 -0
- package/dist/ci.d.ts +3 -0
- package/dist/ci.d.ts.map +1 -0
- package/dist/ci.js +83 -0
- package/dist/ci.js.map +1 -0
- package/dist/dependencies.d.ts +3 -0
- package/dist/dependencies.d.ts.map +1 -0
- package/dist/dependencies.js +102 -0
- package/dist/dependencies.js.map +1 -0
- package/dist/detect.d.ts +3 -0
- package/dist/detect.d.ts.map +1 -0
- package/dist/detect.js +125 -0
- package/dist/detect.js.map +1 -0
- package/dist/docker.d.ts +3 -0
- package/dist/docker.d.ts.map +1 -0
- package/dist/docker.js +100 -0
- package/dist/docker.js.map +1 -0
- package/dist/generate.d.ts +3 -0
- package/dist/generate.d.ts.map +1 -0
- package/dist/generate.js +71 -0
- package/dist/generate.js.map +1 -0
- package/dist/husky.d.ts +3 -0
- package/dist/husky.d.ts.map +1 -0
- package/dist/husky.js +92 -0
- package/dist/husky.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +128 -0
- package/dist/index.js.map +1 -0
- package/dist/templates.d.ts +11 -0
- package/dist/templates.d.ts.map +1 -0
- package/dist/templates.js +209 -0
- package/dist/templates.js.map +1 -0
- package/dist/types.d.ts +16 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/docker-compose.yml +15 -0
- package/package.json +60 -0
- package/src/banner.ts +15 -0
- package/src/ci.ts +94 -0
- package/src/dependencies.ts +120 -0
- package/src/detect.ts +132 -0
- package/src/docker.ts +107 -0
- package/src/generate.ts +81 -0
- package/src/husky.ts +107 -0
- package/src/index.ts +145 -0
- package/src/templates.ts +244 -0
- package/src/types.ts +18 -0
- package/tsconfig.json +26 -0
package/dist/ci.js
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { mkdir, writeFile, access } from 'fs/promises';
|
|
2
|
+
import { join } from 'path';
|
|
3
|
+
export async function generateCI(projectInfo, options) {
|
|
4
|
+
const workflowsDir = join(projectInfo.rootPath, '.github', 'workflows');
|
|
5
|
+
try {
|
|
6
|
+
await mkdir(workflowsDir, { recursive: true });
|
|
7
|
+
}
|
|
8
|
+
catch {
|
|
9
|
+
// Directory might already exist
|
|
10
|
+
}
|
|
11
|
+
const ciYml = generateCIYml(projectInfo, options);
|
|
12
|
+
const ciPath = join(workflowsDir, 'ci.yml');
|
|
13
|
+
// Check if file already exists
|
|
14
|
+
try {
|
|
15
|
+
await access(ciPath);
|
|
16
|
+
console.log(' Skipping .github/workflows/ci.yml (already exists)');
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
catch {
|
|
20
|
+
// File doesn't exist, proceed
|
|
21
|
+
}
|
|
22
|
+
await writeFile(ciPath, ciYml, 'utf-8');
|
|
23
|
+
console.log(' Generated .github/workflows/ci.yml');
|
|
24
|
+
}
|
|
25
|
+
function generateCIYml(projectInfo, options) {
|
|
26
|
+
const nodeVersion = '20';
|
|
27
|
+
const installCommand = getInstallCommand(projectInfo.packageManager);
|
|
28
|
+
// Build YAML content
|
|
29
|
+
let yaml = `name: CI
|
|
30
|
+
|
|
31
|
+
on:
|
|
32
|
+
push:
|
|
33
|
+
branches: [main, master, develop]
|
|
34
|
+
pull_request:
|
|
35
|
+
branches: [main, master, develop]
|
|
36
|
+
|
|
37
|
+
jobs:
|
|
38
|
+
ci:
|
|
39
|
+
runs-on: ubuntu-latest
|
|
40
|
+
|
|
41
|
+
steps:
|
|
42
|
+
- name: Checkout code
|
|
43
|
+
uses: actions/checkout@v4
|
|
44
|
+
|
|
45
|
+
- name: Setup Node.js
|
|
46
|
+
uses: actions/setup-node@v4
|
|
47
|
+
with:
|
|
48
|
+
node-version: '${nodeVersion}'
|
|
49
|
+
cache: '${projectInfo.packageManager}'
|
|
50
|
+
|
|
51
|
+
- name: Install dependencies
|
|
52
|
+
run: ${installCommand}
|
|
53
|
+
|
|
54
|
+
- name: Lint
|
|
55
|
+
run: ${projectInfo.packageManager === 'pnpm' ? 'pnpm lint' : 'npm run lint'}
|
|
56
|
+
${options.strict ? '' : ' continue-on-error: true'}
|
|
57
|
+
|
|
58
|
+
`;
|
|
59
|
+
if (projectInfo.hasTypeScript) {
|
|
60
|
+
yaml += ` - name: Type check
|
|
61
|
+
run: ${projectInfo.packageManager === 'pnpm' ? 'pnpm type-check' : 'npm run type-check'}
|
|
62
|
+
${options.strict ? '' : ' continue-on-error: true'}
|
|
63
|
+
|
|
64
|
+
`;
|
|
65
|
+
}
|
|
66
|
+
yaml += ` - name: Run tests
|
|
67
|
+
run: ${projectInfo.packageManager === 'pnpm' ? 'pnpm test' : 'npm test'}
|
|
68
|
+
continue-on-error: true
|
|
69
|
+
`;
|
|
70
|
+
return yaml;
|
|
71
|
+
}
|
|
72
|
+
function getInstallCommand(packageManager) {
|
|
73
|
+
switch (packageManager) {
|
|
74
|
+
case 'pnpm':
|
|
75
|
+
return 'pnpm install --frozen-lockfile';
|
|
76
|
+
case 'yarn':
|
|
77
|
+
return 'yarn install --frozen-lockfile';
|
|
78
|
+
case 'npm':
|
|
79
|
+
default:
|
|
80
|
+
return 'npm ci';
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
//# sourceMappingURL=ci.js.map
|
package/dist/ci.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ci.js","sourceRoot":"","sources":["../src/ci.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACvD,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAG5B,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,WAAwB,EAAE,OAAgB;IACzE,MAAM,YAAY,GAAG,IAAI,CAAC,WAAW,CAAC,QAAQ,EAAE,SAAS,EAAE,WAAW,CAAC,CAAC;IAExE,IAAI,CAAC;QACH,MAAM,KAAK,CAAC,YAAY,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACjD,CAAC;IAAC,MAAM,CAAC;QACP,gCAAgC;IAClC,CAAC;IAED,MAAM,KAAK,GAAG,aAAa,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;IAClD,MAAM,MAAM,GAAG,IAAI,CAAC,YAAY,EAAE,QAAQ,CAAC,CAAC;IAE5C,+BAA+B;IAC/B,IAAI,CAAC;QACH,MAAM,MAAM,CAAC,MAAM,CAAC,CAAC;QACrB,OAAO,CAAC,GAAG,CAAC,sDAAsD,CAAC,CAAC;QACpE,OAAO;IACT,CAAC;IAAC,MAAM,CAAC;QACP,8BAA8B;IAChC,CAAC;IAED,MAAM,SAAS,CAAC,MAAM,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC;IACxC,OAAO,CAAC,GAAG,CAAC,sCAAsC,CAAC,CAAC;AACtD,CAAC;AAED,SAAS,aAAa,CAAC,WAAwB,EAAE,OAAgB;IAC/D,MAAM,WAAW,GAAG,IAAI,CAAC;IACzB,MAAM,cAAc,GAAG,iBAAiB,CAAC,WAAW,CAAC,cAAc,CAAC,CAAC;IAErE,qBAAqB;IACrB,IAAI,IAAI,GAAG;;;;;;;;;;;;;;;;;;;2BAmBc,WAAW;oBAClB,WAAW,CAAC,cAAc;;;eAG/B,cAAc;;;eAGd,WAAW,CAAC,cAAc,KAAK,MAAM,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,cAAc;EACjF,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,iCAAiC;;CAExD,CAAC;IAEA,IAAI,WAAW,CAAC,aAAa,EAAE,CAAC;QAC9B,IAAI,IAAI;eACG,WAAW,CAAC,cAAc,KAAK,MAAM,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC,oBAAoB;EAC7F,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,iCAAiC;;CAExD,CAAC;IACA,CAAC;IAED,IAAI,IAAI;eACK,WAAW,CAAC,cAAc,KAAK,MAAM,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,UAAU;;CAE9E,CAAC;IAEA,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,iBAAiB,CAAC,cAA6C;IACtE,QAAQ,cAAc,EAAE,CAAC;QACvB,KAAK,MAAM;YACT,OAAO,gCAAgC,CAAC;QAC1C,KAAK,MAAM;YACT,OAAO,gCAAgC,CAAC;QAC1C,KAAK,KAAK,CAAC;QACX;YACE,OAAO,QAAQ,CAAC;IACpB,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dependencies.d.ts","sourceRoot":"","sources":["../src/dependencies.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAIvD,wBAAsB,eAAe,CAAC,WAAW,EAAE,WAAW,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAuE/F"}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { readFile, writeFile } from 'fs/promises';
|
|
2
|
+
import { join } from 'path';
|
|
3
|
+
import { exec } from 'child_process';
|
|
4
|
+
import { promisify } from 'util';
|
|
5
|
+
const execAsync = promisify(exec);
|
|
6
|
+
export async function addDependencies(projectInfo, options) {
|
|
7
|
+
const packageJsonPath = join(projectInfo.rootPath, 'package.json');
|
|
8
|
+
try {
|
|
9
|
+
const packageJson = JSON.parse(await readFile(packageJsonPath, 'utf-8'));
|
|
10
|
+
// Initialize devDependencies if not present
|
|
11
|
+
if (!packageJson.devDependencies) {
|
|
12
|
+
packageJson.devDependencies = {};
|
|
13
|
+
}
|
|
14
|
+
// Core dependencies (always needed)
|
|
15
|
+
const coreDeps = {
|
|
16
|
+
eslint: '^8.57.0',
|
|
17
|
+
prettier: '^3.2.0',
|
|
18
|
+
husky: '^9.0.0',
|
|
19
|
+
'lint-staged': '^15.2.0',
|
|
20
|
+
};
|
|
21
|
+
// TypeScript dependencies
|
|
22
|
+
if (projectInfo.hasTypeScript) {
|
|
23
|
+
coreDeps['@typescript-eslint/parser'] = '^6.19.0';
|
|
24
|
+
coreDeps['@typescript-eslint/eslint-plugin'] = '^6.19.0';
|
|
25
|
+
}
|
|
26
|
+
// React dependencies
|
|
27
|
+
const isReact = projectInfo.type === 'react' ||
|
|
28
|
+
projectInfo.type === 'nextjs' ||
|
|
29
|
+
projectInfo.type === 'vite';
|
|
30
|
+
if (isReact) {
|
|
31
|
+
coreDeps['eslint-plugin-react'] = '^7.33.0';
|
|
32
|
+
coreDeps['eslint-plugin-react-hooks'] = '^4.6.0';
|
|
33
|
+
}
|
|
34
|
+
// Next.js specific
|
|
35
|
+
if (projectInfo.type === 'nextjs') {
|
|
36
|
+
coreDeps['eslint-config-next'] = 'latest';
|
|
37
|
+
}
|
|
38
|
+
// Commitlint (strict mode)
|
|
39
|
+
if (options.strict) {
|
|
40
|
+
coreDeps['@commitlint/cli'] = '^18.6.0';
|
|
41
|
+
coreDeps['@commitlint/config-conventional'] = '^18.6.0';
|
|
42
|
+
}
|
|
43
|
+
// Add dependencies only if they don't already exist
|
|
44
|
+
let hasNewDeps = false;
|
|
45
|
+
for (const [dep, version] of Object.entries(coreDeps)) {
|
|
46
|
+
if (!packageJson.devDependencies[dep] && !packageJson.dependencies?.[dep]) {
|
|
47
|
+
packageJson.devDependencies[dep] = version;
|
|
48
|
+
hasNewDeps = true;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
if (hasNewDeps) {
|
|
52
|
+
await writeFile(packageJsonPath, JSON.stringify(packageJson, null, 2) + '\n', 'utf-8');
|
|
53
|
+
console.log(' Updated package.json with dependencies');
|
|
54
|
+
// Install dependencies
|
|
55
|
+
await installDependencies(projectInfo);
|
|
56
|
+
}
|
|
57
|
+
else {
|
|
58
|
+
console.log(' All required dependencies already present');
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
catch (error) {
|
|
62
|
+
if (error instanceof Error && 'code' in error && error.code === 'ENOENT') {
|
|
63
|
+
console.warn(' Warning: package.json not found, skipping dependency installation');
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
throw error;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
async function installDependencies(projectInfo) {
|
|
71
|
+
const { packageManager } = projectInfo;
|
|
72
|
+
const rootPath = projectInfo.rootPath;
|
|
73
|
+
console.log(`\n Installing dependencies with ${packageManager}...`);
|
|
74
|
+
try {
|
|
75
|
+
let installCommand;
|
|
76
|
+
switch (packageManager) {
|
|
77
|
+
case 'pnpm':
|
|
78
|
+
installCommand = 'pnpm install';
|
|
79
|
+
break;
|
|
80
|
+
case 'yarn':
|
|
81
|
+
installCommand = 'yarn install';
|
|
82
|
+
break;
|
|
83
|
+
case 'npm':
|
|
84
|
+
default:
|
|
85
|
+
installCommand = 'npm install';
|
|
86
|
+
break;
|
|
87
|
+
}
|
|
88
|
+
await execAsync(installCommand, {
|
|
89
|
+
cwd: rootPath,
|
|
90
|
+
maxBuffer: 10 * 1024 * 1024, // 10MB buffer
|
|
91
|
+
});
|
|
92
|
+
console.log(' Dependencies installed successfully');
|
|
93
|
+
}
|
|
94
|
+
catch {
|
|
95
|
+
console.error(' Failed to install dependencies automatically');
|
|
96
|
+
console.error(' Please run manually:', packageManager === 'pnpm' ? 'pnpm install' :
|
|
97
|
+
packageManager === 'yarn' ? 'yarn install' :
|
|
98
|
+
'npm install');
|
|
99
|
+
// Don't throw - let the user install manually if needed
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
//# sourceMappingURL=dependencies.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dependencies.js","sourceRoot":"","sources":["../src/dependencies.ts"],"names":[],"mappings":"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"}
|
package/dist/detect.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"detect.d.ts","sourceRoot":"","sources":["../src/detect.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAA+B,MAAM,YAAY,CAAC;AAE3E,wBAAsB,aAAa,IAAI,OAAO,CAAC,WAAW,CAAC,CAiB1D"}
|
package/dist/detect.js
ADDED
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import { readFile, access } from 'fs/promises';
|
|
2
|
+
import { join } from 'path';
|
|
3
|
+
export async function detectProject() {
|
|
4
|
+
const rootPath = process.cwd();
|
|
5
|
+
const [type, packageManager, hasTypeScript, isMonorepo] = await Promise.all([
|
|
6
|
+
detectProjectType(rootPath),
|
|
7
|
+
detectPackageManager(rootPath),
|
|
8
|
+
detectTypeScript(rootPath),
|
|
9
|
+
detectMonorepo(rootPath),
|
|
10
|
+
]);
|
|
11
|
+
return {
|
|
12
|
+
type,
|
|
13
|
+
packageManager,
|
|
14
|
+
hasTypeScript,
|
|
15
|
+
isMonorepo,
|
|
16
|
+
rootPath,
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
async function detectProjectType(rootPath) {
|
|
20
|
+
try {
|
|
21
|
+
const packageJsonPath = join(rootPath, 'package.json');
|
|
22
|
+
const packageJson = JSON.parse(await readFile(packageJsonPath, 'utf-8'));
|
|
23
|
+
const deps = { ...packageJson.dependencies, ...packageJson.devDependencies };
|
|
24
|
+
// Check for Next.js
|
|
25
|
+
if (deps.next || deps['nextjs']) {
|
|
26
|
+
return 'nextjs';
|
|
27
|
+
}
|
|
28
|
+
// Check for Vite
|
|
29
|
+
if (deps.vite || deps['@vitejs/plugin-react']) {
|
|
30
|
+
return 'vite';
|
|
31
|
+
}
|
|
32
|
+
// Check for React
|
|
33
|
+
if (deps.react || deps['react-dom']) {
|
|
34
|
+
return 'react';
|
|
35
|
+
}
|
|
36
|
+
// Default to Node backend
|
|
37
|
+
return 'node';
|
|
38
|
+
}
|
|
39
|
+
catch {
|
|
40
|
+
return 'unknown';
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
async function detectPackageManager(rootPath) {
|
|
44
|
+
// Check for lock files
|
|
45
|
+
const lockFiles = [
|
|
46
|
+
{ file: 'pnpm-lock.yaml', manager: 'pnpm' },
|
|
47
|
+
{ file: 'yarn.lock', manager: 'yarn' },
|
|
48
|
+
{ file: 'package-lock.json', manager: 'npm' },
|
|
49
|
+
];
|
|
50
|
+
for (const { file, manager } of lockFiles) {
|
|
51
|
+
try {
|
|
52
|
+
await access(join(rootPath, file));
|
|
53
|
+
return manager;
|
|
54
|
+
}
|
|
55
|
+
catch {
|
|
56
|
+
// Continue checking
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
// Check for packageManager field in package.json
|
|
60
|
+
try {
|
|
61
|
+
const packageJsonPath = join(rootPath, 'package.json');
|
|
62
|
+
const packageJson = JSON.parse(await readFile(packageJsonPath, 'utf-8'));
|
|
63
|
+
if (packageJson.packageManager) {
|
|
64
|
+
if (packageJson.packageManager.startsWith('pnpm'))
|
|
65
|
+
return 'pnpm';
|
|
66
|
+
if (packageJson.packageManager.startsWith('yarn'))
|
|
67
|
+
return 'yarn';
|
|
68
|
+
if (packageJson.packageManager.startsWith('npm'))
|
|
69
|
+
return 'npm';
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
catch {
|
|
73
|
+
// Fall through
|
|
74
|
+
}
|
|
75
|
+
// Default to npm
|
|
76
|
+
return 'npm';
|
|
77
|
+
}
|
|
78
|
+
async function detectTypeScript(rootPath) {
|
|
79
|
+
try {
|
|
80
|
+
const tsConfigPath = join(rootPath, 'tsconfig.json');
|
|
81
|
+
await access(tsConfigPath);
|
|
82
|
+
return true;
|
|
83
|
+
}
|
|
84
|
+
catch {
|
|
85
|
+
// Check for TypeScript in dependencies
|
|
86
|
+
try {
|
|
87
|
+
const packageJsonPath = join(rootPath, 'package.json');
|
|
88
|
+
const packageJson = JSON.parse(await readFile(packageJsonPath, 'utf-8'));
|
|
89
|
+
const deps = { ...packageJson.dependencies, ...packageJson.devDependencies };
|
|
90
|
+
return 'typescript' in deps;
|
|
91
|
+
}
|
|
92
|
+
catch {
|
|
93
|
+
return false;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
async function detectMonorepo(rootPath) {
|
|
98
|
+
// Check for common monorepo indicators
|
|
99
|
+
const indicators = [
|
|
100
|
+
'pnpm-workspace.yaml',
|
|
101
|
+
'lerna.json',
|
|
102
|
+
'nx.json',
|
|
103
|
+
'turbo.json',
|
|
104
|
+
'rush.json',
|
|
105
|
+
];
|
|
106
|
+
for (const indicator of indicators) {
|
|
107
|
+
try {
|
|
108
|
+
await access(join(rootPath, indicator));
|
|
109
|
+
return true;
|
|
110
|
+
}
|
|
111
|
+
catch {
|
|
112
|
+
// Continue checking
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
// Check package.json for workspaces
|
|
116
|
+
try {
|
|
117
|
+
const packageJsonPath = join(rootPath, 'package.json');
|
|
118
|
+
const packageJson = JSON.parse(await readFile(packageJsonPath, 'utf-8'));
|
|
119
|
+
return !!(packageJson.workspaces || packageJson.workspace);
|
|
120
|
+
}
|
|
121
|
+
catch {
|
|
122
|
+
return false;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
//# sourceMappingURL=detect.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"detect.js","sourceRoot":"","sources":["../src/detect.ts"],"names":[],"mappings":"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"}
|
package/dist/docker.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"docker.d.ts","sourceRoot":"","sources":["../src/docker.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE9C,wBAAsB,cAAc,CAAC,WAAW,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAuB5E"}
|
package/dist/docker.js
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { writeFile, access } from 'fs/promises';
|
|
2
|
+
import { join } from 'path';
|
|
3
|
+
export async function generateDocker(projectInfo) {
|
|
4
|
+
const dockerfile = generateDockerfile(projectInfo);
|
|
5
|
+
const dockerCompose = generateDockerCompose();
|
|
6
|
+
const dockerfilePath = join(projectInfo.rootPath, 'Dockerfile');
|
|
7
|
+
const dockerComposePath = join(projectInfo.rootPath, 'docker-compose.yml');
|
|
8
|
+
// Check if files exist
|
|
9
|
+
try {
|
|
10
|
+
await access(dockerfilePath);
|
|
11
|
+
console.log(' Skipping Dockerfile (already exists)');
|
|
12
|
+
}
|
|
13
|
+
catch {
|
|
14
|
+
await writeFile(dockerfilePath, dockerfile, 'utf-8');
|
|
15
|
+
console.log(' Generated Dockerfile');
|
|
16
|
+
}
|
|
17
|
+
try {
|
|
18
|
+
await access(dockerComposePath);
|
|
19
|
+
console.log(' Skipping docker-compose.yml (already exists)');
|
|
20
|
+
}
|
|
21
|
+
catch {
|
|
22
|
+
await writeFile(dockerComposePath, dockerCompose, 'utf-8');
|
|
23
|
+
console.log(' Generated docker-compose.yml');
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
function generateDockerfile(projectInfo) {
|
|
27
|
+
const packageManager = projectInfo.packageManager;
|
|
28
|
+
const installCmd = packageManager === 'pnpm'
|
|
29
|
+
? 'RUN pnpm install --frozen-lockfile'
|
|
30
|
+
: packageManager === 'yarn'
|
|
31
|
+
? 'RUN yarn install --frozen-lockfile'
|
|
32
|
+
: 'RUN npm ci';
|
|
33
|
+
const lockFileName = packageManager === 'pnpm'
|
|
34
|
+
? 'pnpm-lock.yaml'
|
|
35
|
+
: packageManager === 'yarn'
|
|
36
|
+
? 'yarn.lock'
|
|
37
|
+
: 'package-lock.json';
|
|
38
|
+
return `# Build stage
|
|
39
|
+
FROM node:20-alpine AS builder
|
|
40
|
+
|
|
41
|
+
WORKDIR /app
|
|
42
|
+
|
|
43
|
+
# Copy package files
|
|
44
|
+
COPY package.json .
|
|
45
|
+
COPY ${lockFileName} .
|
|
46
|
+
|
|
47
|
+
${installCmd}
|
|
48
|
+
|
|
49
|
+
# Copy source files
|
|
50
|
+
COPY . .
|
|
51
|
+
|
|
52
|
+
# Build the application (adjust as needed)
|
|
53
|
+
${projectInfo.hasTypeScript ? 'RUN npm run build' : '# Add build command if needed'}
|
|
54
|
+
|
|
55
|
+
# Production stage
|
|
56
|
+
FROM node:20-alpine AS production
|
|
57
|
+
|
|
58
|
+
WORKDIR /app
|
|
59
|
+
|
|
60
|
+
# Copy package files
|
|
61
|
+
COPY package.json .
|
|
62
|
+
COPY ${lockFileName} .
|
|
63
|
+
|
|
64
|
+
# Install production dependencies only
|
|
65
|
+
${packageManager === 'pnpm'
|
|
66
|
+
? 'RUN pnpm install --frozen-lockfile --prod'
|
|
67
|
+
: packageManager === 'yarn'
|
|
68
|
+
? 'RUN yarn install --frozen-lockfile --production'
|
|
69
|
+
: 'RUN npm ci --only=production'}
|
|
70
|
+
|
|
71
|
+
# Copy built application from builder
|
|
72
|
+
COPY --from=builder /app/dist ./dist
|
|
73
|
+
COPY --from=builder /app/public ./public 2>/dev/null || true
|
|
74
|
+
|
|
75
|
+
# Expose port (adjust as needed)
|
|
76
|
+
EXPOSE 3000
|
|
77
|
+
|
|
78
|
+
# Start the application
|
|
79
|
+
CMD ["node", "dist/index.js"]
|
|
80
|
+
`;
|
|
81
|
+
}
|
|
82
|
+
function generateDockerCompose() {
|
|
83
|
+
return `version: '3.8'
|
|
84
|
+
|
|
85
|
+
services:
|
|
86
|
+
app:
|
|
87
|
+
build:
|
|
88
|
+
context: .
|
|
89
|
+
dockerfile: Dockerfile
|
|
90
|
+
target: production
|
|
91
|
+
ports:
|
|
92
|
+
- "3000:3000"
|
|
93
|
+
environment:
|
|
94
|
+
- NODE_ENV=production
|
|
95
|
+
restart: unless-stopped
|
|
96
|
+
# volumes:
|
|
97
|
+
# - ./data:/app/data
|
|
98
|
+
`;
|
|
99
|
+
}
|
|
100
|
+
//# sourceMappingURL=docker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"docker.js","sourceRoot":"","sources":["../src/docker.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAG5B,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,WAAwB;IAC3D,MAAM,UAAU,GAAG,kBAAkB,CAAC,WAAW,CAAC,CAAC;IACnD,MAAM,aAAa,GAAG,qBAAqB,EAAE,CAAC;IAE9C,MAAM,cAAc,GAAG,IAAI,CAAC,WAAW,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAC;IAChE,MAAM,iBAAiB,GAAG,IAAI,CAAC,WAAW,CAAC,QAAQ,EAAE,oBAAoB,CAAC,CAAC;IAE3E,uBAAuB;IACvB,IAAI,CAAC;QACH,MAAM,MAAM,CAAC,cAAc,CAAC,CAAC;QAC7B,OAAO,CAAC,GAAG,CAAC,wCAAwC,CAAC,CAAC;IACxD,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,SAAS,CAAC,cAAc,EAAE,UAAU,EAAE,OAAO,CAAC,CAAC;QACrD,OAAO,CAAC,GAAG,CAAC,wBAAwB,CAAC,CAAC;IACxC,CAAC;IAED,IAAI,CAAC;QACH,MAAM,MAAM,CAAC,iBAAiB,CAAC,CAAC;QAChC,OAAO,CAAC,GAAG,CAAC,gDAAgD,CAAC,CAAC;IAChE,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,SAAS,CAAC,iBAAiB,EAAE,aAAa,EAAE,OAAO,CAAC,CAAC;QAC3D,OAAO,CAAC,GAAG,CAAC,gCAAgC,CAAC,CAAC;IAChD,CAAC;AACH,CAAC;AAED,SAAS,kBAAkB,CAAC,WAAwB;IAClD,MAAM,cAAc,GAAG,WAAW,CAAC,cAAc,CAAC;IAClD,MAAM,UAAU,GAAG,cAAc,KAAK,MAAM;QAC1C,CAAC,CAAC,oCAAoC;QACtC,CAAC,CAAC,cAAc,KAAK,MAAM;YAC3B,CAAC,CAAC,oCAAoC;YACtC,CAAC,CAAC,YAAY,CAAC;IAEjB,MAAM,YAAY,GAAG,cAAc,KAAK,MAAM;QAC5C,CAAC,CAAC,gBAAgB;QAClB,CAAC,CAAC,cAAc,KAAK,MAAM;YAC3B,CAAC,CAAC,WAAW;YACb,CAAC,CAAC,mBAAmB,CAAC;IAExB,OAAO;;;;;;;OAOF,YAAY;;EAEjB,UAAU;;;;;;EAMV,WAAW,CAAC,aAAa,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC,CAAC,+BAA+B;;;;;;;;;OAS5E,YAAY;;;EAGjB,cAAc,KAAK,MAAM;QACzB,CAAC,CAAC,2CAA2C;QAC7C,CAAC,CAAC,cAAc,KAAK,MAAM;YAC3B,CAAC,CAAC,iDAAiD;YACnD,CAAC,CAAC,8BAA8B;;;;;;;;;;;CAWjC,CAAC;AACF,CAAC;AAED,SAAS,qBAAqB;IAC5B,OAAO;;;;;;;;;;;;;;;CAeR,CAAC;AACF,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generate.d.ts","sourceRoot":"","sources":["../src/generate.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAGvD,wBAAsB,aAAa,CAAC,WAAW,EAAE,WAAW,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CA6B7F"}
|
package/dist/generate.js
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { writeFile, readFile, access } from 'fs/promises';
|
|
2
|
+
import { join } from 'path';
|
|
3
|
+
import { getTemplates } from './templates.js';
|
|
4
|
+
export async function generateFiles(projectInfo, options) {
|
|
5
|
+
const templates = getTemplates(projectInfo, options);
|
|
6
|
+
const filesToGenerate = [
|
|
7
|
+
{ name: '.eslintrc.json', content: templates.eslint },
|
|
8
|
+
{ name: '.prettierrc.json', content: templates.prettier },
|
|
9
|
+
{ name: '.prettierignore', content: templates.prettierIgnore },
|
|
10
|
+
{ name: '.gitignore', content: templates.gitignore },
|
|
11
|
+
{ name: '.editorconfig', content: templates.editorconfig },
|
|
12
|
+
{ name: '.env.example', content: templates.envExample },
|
|
13
|
+
];
|
|
14
|
+
for (const file of filesToGenerate) {
|
|
15
|
+
const filePath = join(projectInfo.rootPath, file.name);
|
|
16
|
+
// Skip if file exists (don't overwrite)
|
|
17
|
+
try {
|
|
18
|
+
await access(filePath);
|
|
19
|
+
console.log(` Skipping ${file.name} (already exists)`);
|
|
20
|
+
continue;
|
|
21
|
+
}
|
|
22
|
+
catch {
|
|
23
|
+
// File doesn't exist, proceed
|
|
24
|
+
}
|
|
25
|
+
await writeFile(filePath, file.content, 'utf-8');
|
|
26
|
+
console.log(` Generated ${file.name}`);
|
|
27
|
+
}
|
|
28
|
+
// Update package.json scripts
|
|
29
|
+
await updatePackageJson(projectInfo);
|
|
30
|
+
}
|
|
31
|
+
async function updatePackageJson(projectInfo) {
|
|
32
|
+
const packageJsonPath = join(projectInfo.rootPath, 'package.json');
|
|
33
|
+
try {
|
|
34
|
+
const packageJson = JSON.parse(await readFile(packageJsonPath, 'utf-8'));
|
|
35
|
+
// Initialize scripts if not present
|
|
36
|
+
if (!packageJson.scripts) {
|
|
37
|
+
packageJson.scripts = {};
|
|
38
|
+
}
|
|
39
|
+
// Add scripts only if they don't exist
|
|
40
|
+
const scriptsToAdd = {
|
|
41
|
+
lint: projectInfo.hasTypeScript
|
|
42
|
+
? 'eslint . --ext .js,.jsx,.ts,.tsx'
|
|
43
|
+
: 'eslint . --ext .js,.jsx',
|
|
44
|
+
'lint:fix': projectInfo.hasTypeScript
|
|
45
|
+
? 'eslint . --ext .js,.jsx,.ts,.tsx --fix'
|
|
46
|
+
: 'eslint . --ext .js,.jsx --fix',
|
|
47
|
+
format: 'prettier --write "**/*.{js,jsx,ts,tsx,json,md}"',
|
|
48
|
+
'format:check': 'prettier --check "**/*.{js,jsx,ts,tsx,json,md}"',
|
|
49
|
+
};
|
|
50
|
+
if (projectInfo.hasTypeScript) {
|
|
51
|
+
scriptsToAdd['type-check'] = 'tsc --noEmit';
|
|
52
|
+
}
|
|
53
|
+
// Only add scripts that don't already exist
|
|
54
|
+
for (const [key, value] of Object.entries(scriptsToAdd)) {
|
|
55
|
+
if (!packageJson.scripts[key]) {
|
|
56
|
+
packageJson.scripts[key] = value;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
await writeFile(packageJsonPath, JSON.stringify(packageJson, null, 2) + '\n', 'utf-8');
|
|
60
|
+
console.log(' Updated package.json scripts');
|
|
61
|
+
}
|
|
62
|
+
catch (error) {
|
|
63
|
+
if (error instanceof Error && 'code' in error && error.code === 'ENOENT') {
|
|
64
|
+
console.warn(' Warning: package.json not found, skipping script updates');
|
|
65
|
+
}
|
|
66
|
+
else {
|
|
67
|
+
throw error;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=generate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generate.js","sourceRoot":"","sources":["../src/generate.ts"],"names":[],"mappings":"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"}
|
package/dist/husky.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"husky.d.ts","sourceRoot":"","sources":["../src/husky.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAEvD,wBAAsB,UAAU,CAAC,WAAW,EAAE,WAAW,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAqD1F"}
|
package/dist/husky.js
ADDED
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { writeFile, mkdir, access, readFile } from 'fs/promises';
|
|
2
|
+
import { join } from 'path';
|
|
3
|
+
export async function setupHusky(projectInfo, options) {
|
|
4
|
+
const huskyDir = join(projectInfo.rootPath, '.husky');
|
|
5
|
+
// Check if .git exists
|
|
6
|
+
try {
|
|
7
|
+
await access(join(projectInfo.rootPath, '.git'));
|
|
8
|
+
}
|
|
9
|
+
catch {
|
|
10
|
+
console.warn(' Warning: .git directory not found, skipping Husky setup');
|
|
11
|
+
return;
|
|
12
|
+
}
|
|
13
|
+
// Create .husky directory
|
|
14
|
+
try {
|
|
15
|
+
await mkdir(huskyDir, { recursive: true });
|
|
16
|
+
}
|
|
17
|
+
catch {
|
|
18
|
+
// Directory might already exist
|
|
19
|
+
}
|
|
20
|
+
// Create pre-commit hook
|
|
21
|
+
const preCommitHook = `#!/usr/bin/env sh
|
|
22
|
+
. "$(dirname -- "$0")/_/husky.sh"
|
|
23
|
+
|
|
24
|
+
${projectInfo.packageManager === 'pnpm' ? 'pnpm' : 'npx'} lint-staged
|
|
25
|
+
`;
|
|
26
|
+
const preCommitPath = join(huskyDir, 'pre-commit');
|
|
27
|
+
await writeFile(preCommitPath, preCommitHook, 'utf-8');
|
|
28
|
+
// Make it executable (Unix-like systems)
|
|
29
|
+
if (process.platform !== 'win32') {
|
|
30
|
+
const { chmod } = await import('fs/promises');
|
|
31
|
+
await chmod(preCommitPath, 0o755);
|
|
32
|
+
}
|
|
33
|
+
// Create commit-msg hook if commitlint is enabled
|
|
34
|
+
if (options.strict) {
|
|
35
|
+
const commitMsgHook = `#!/usr/bin/env sh
|
|
36
|
+
. "$(dirname -- "$0")/_/husky.sh"
|
|
37
|
+
|
|
38
|
+
${projectInfo.packageManager === 'pnpm' ? 'pnpm' : 'npx'} commitlint --edit "$1"
|
|
39
|
+
`;
|
|
40
|
+
const commitMsgPath = join(huskyDir, 'commit-msg');
|
|
41
|
+
await writeFile(commitMsgPath, commitMsgHook, 'utf-8');
|
|
42
|
+
if (process.platform !== 'win32') {
|
|
43
|
+
const { chmod } = await import('fs/promises');
|
|
44
|
+
await chmod(commitMsgPath, 0o755);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
// Update package.json with husky and lint-staged config
|
|
48
|
+
await updatePackageJsonForHusky(projectInfo, options);
|
|
49
|
+
}
|
|
50
|
+
async function updatePackageJsonForHusky(projectInfo, options) {
|
|
51
|
+
const packageJsonPath = join(projectInfo.rootPath, 'package.json');
|
|
52
|
+
try {
|
|
53
|
+
const packageJson = JSON.parse(await readFile(packageJsonPath, 'utf-8'));
|
|
54
|
+
// Add prepare script for husky
|
|
55
|
+
if (!packageJson.scripts) {
|
|
56
|
+
packageJson.scripts = {};
|
|
57
|
+
}
|
|
58
|
+
if (!packageJson.scripts.prepare) {
|
|
59
|
+
packageJson.scripts.prepare = 'husky install';
|
|
60
|
+
}
|
|
61
|
+
// Add lint-staged configuration
|
|
62
|
+
if (!packageJson['lint-staged']) {
|
|
63
|
+
const lintStagedConfig = {
|
|
64
|
+
'*.{js,jsx,ts,tsx}': [
|
|
65
|
+
'eslint --fix',
|
|
66
|
+
'prettier --write',
|
|
67
|
+
],
|
|
68
|
+
'*.{json,md,yml,yaml}': [
|
|
69
|
+
'prettier --write',
|
|
70
|
+
],
|
|
71
|
+
};
|
|
72
|
+
packageJson['lint-staged'] = lintStagedConfig;
|
|
73
|
+
}
|
|
74
|
+
// Add commitlint config if strict mode
|
|
75
|
+
if (options.strict && !packageJson.commitlint) {
|
|
76
|
+
packageJson.commitlint = {
|
|
77
|
+
extends: ['@commitlint/config-conventional'],
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
await writeFile(packageJsonPath, JSON.stringify(packageJson, null, 2) + '\n', 'utf-8');
|
|
81
|
+
console.log(' Configured Husky git hooks');
|
|
82
|
+
}
|
|
83
|
+
catch (error) {
|
|
84
|
+
if (error instanceof Error && 'code' in error && error.code === 'ENOENT') {
|
|
85
|
+
console.warn(' Warning: package.json not found, skipping Husky configuration');
|
|
86
|
+
}
|
|
87
|
+
else {
|
|
88
|
+
throw error;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
//# sourceMappingURL=husky.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"husky.js","sourceRoot":"","sources":["../src/husky.ts"],"names":[],"mappings":"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"}
|