boilerforge 1.0.0 → 1.2.0-dev.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.
Files changed (40) hide show
  1. package/dist/cli.js +13586 -995
  2. package/dist/templates/create-simple-app/package.json.hbs +30 -0
  3. package/dist/templates/create-simple-app/src/index.js.hbs +5 -0
  4. package/dist/templates/create-simple-app/src/index.ts.hbs +5 -0
  5. package/dist/templates/create-simple-app/tsconfig.json.hbs +14 -0
  6. package/package.json +23 -5
  7. package/{src/templates/create-node-app/resource/gitignore.ts → templates/create-simple-app/.gitignore.hbs} +1 -14
  8. package/templates/create-simple-app/eslint.config.mjs.hbs +23 -0
  9. package/templates/create-simple-app/package.json.hbs +30 -0
  10. package/templates/create-simple-app/src/index.js.hbs +5 -0
  11. package/templates/create-simple-app/src/index.ts.hbs +5 -0
  12. package/templates/create-simple-app/tsconfig.json.hbs +14 -0
  13. package/.github/workflows/npm-publish.yml +0 -34
  14. package/bin/cli.ts +0 -21
  15. package/src/config/cli-config.ts +0 -20
  16. package/src/lib/file.ts +0 -159
  17. package/src/lib/project.ts +0 -210
  18. package/src/lib/prompter.ts +0 -201
  19. package/src/lib/task.ts +0 -41
  20. package/src/templates/create-node-app/index.ts +0 -306
  21. package/src/templates/create-node-app/resource/editor-config.ts +0 -24
  22. package/src/templates/create-node-app/resource/eslint.ts +0 -62
  23. package/src/templates/create-node-app/resource/package-json.ts +0 -57
  24. package/src/templates/create-node-app/resource/prettier.ts +0 -45
  25. package/src/templates/create-node-app/resource/project-deps.ts +0 -30
  26. package/src/templates/create-node-app/resource/project-files.ts +0 -17
  27. package/src/templates/create-node-app/resource/tsconfig.ts +0 -20
  28. package/src/templates/index.ts +0 -1
  29. package/src/templates/utils/badges.ts +0 -13
  30. package/src/templates/utils/git.ts +0 -64
  31. package/src/templates/utils/package-manager.ts +0 -78
  32. package/src/templates/utils/readme.ts +0 -115
  33. package/src/utils/exec-cmd.ts +0 -80
  34. package/src/utils/index.ts +0 -60
  35. package/src/utils/logger.ts +0 -24
  36. package/tsconfig.json +0 -17
  37. /package/{eslint.config.mjs → dist/templates/create-simple-app/eslint.config.mjs.hbs} +0 -0
  38. /package/{.editorconfig → templates/create-simple-app/.editorconfig.hbs} +0 -0
  39. /package/{.prettierignore → templates/create-simple-app/.prettierignore.hbs} +0 -0
  40. /package/{.prettierrc.json → templates/create-simple-app/.prettierrc.json.hbs} +0 -0
@@ -0,0 +1,30 @@
1
+ {
2
+ "name": "{{name}}",
3
+ "version": "{{version}}",
4
+ "description": "{{description}}",
5
+ "author": "{{author}}",
6
+ "license": "ISC",
7
+ "main": "{{main}}",
8
+ {{#if scripts}}
9
+ "scripts": {
10
+ {{#each scripts}}
11
+ "{{@key}}": "{{this}}"{{#unless @last}},{{/unless}}
12
+ {{/each}}
13
+ },
14
+ {{/if}}
15
+ {{#if devDependencies}}
16
+ "devDependencies": {
17
+ {{#each devDependencies}}
18
+ "{{@key}}": "{{this}}"{{#unless @last}},{{/unless}}
19
+ {{/each}}
20
+ },
21
+ {{/if}}
22
+ {{#if dependencies}}
23
+ "dependencies": {
24
+ {{#each dependencies}}
25
+ "{{@key}}": "{{this}}"{{#unless @last}},{{/unless}}
26
+ {{/each}}
27
+ },
28
+ {{/if}}
29
+ "packageManager": "{{packageManager}}"
30
+ }
@@ -0,0 +1,5 @@
1
+ async function main() {
2
+ console.log('Hello from {{name}}');
3
+ }
4
+
5
+ main().catch((error) => console.error(error));
@@ -0,0 +1,5 @@
1
+ async function main() {
2
+ console.log('Hello from {{name}}');
3
+ }
4
+
5
+ main().catch((error) => console.error(error));
@@ -0,0 +1,14 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2024",
4
+ "module": "commonjs",
5
+ "outDir": "./dist",
6
+ "esModuleInterop": true,
7
+ "forceConsistentCasingInFileNames": true,
8
+ "strict": true,
9
+ "skipLibCheck": true
10
+ },
11
+ "include": [
12
+ "src"
13
+ ]
14
+ }
package/package.json CHANGED
@@ -1,34 +1,50 @@
1
1
  {
2
2
  "name": "boilerforge",
3
- "version": "1.0.0",
3
+ "version": "1.2.0-dev.1",
4
4
  "description": "✨ boilerforge is a blazing-fast CLI utility that scaffolds clean, ready-to-use project structures so you can skip the setup and start building instantly.",
5
- "main": "dist/",
5
+ "main": "dist/cli.js",
6
6
  "bin": {
7
7
  "boilerforge": "dist/cli.js"
8
8
  },
9
+ "files": [
10
+ "dist",
11
+ "templates",
12
+ "README.md"
13
+ ],
14
+ "engines": {
15
+ "node": ">= 20.11.1"
16
+ },
9
17
  "scripts": {
10
18
  "clean": "rimraf dist",
11
19
  "ci": "pnpm install --frozen-lockfile",
12
- "build": "esbuild bin/cli.ts --bundle --platform=node --outfile=dist/cli.js --format=cjs",
20
+ "build": "ts-node esbuild.config.ts",
13
21
  "prebuild": "pnpm run clean && pnpm run lint && pnpm run format",
14
- "start": "node dist/",
22
+ "start": "node dist/cli.js",
15
23
  "lint": "eslint --ext .js,.ts .",
16
24
  "format": "prettier --write \"**/*.+(js|ts)\"",
17
25
  "test": "echo \"Error: no test specified\" && exit 1",
18
- "dev": "ts-node bin/cli.ts"
26
+ "dev": "ts-node bin/cli.ts",
27
+ "prepare": "husky"
19
28
  },
20
29
  "keywords": [],
30
+ "publishConfig": {
31
+ "tag": "dev"
32
+ },
21
33
  "author": "tspyder7",
22
34
  "license": "MIT",
23
35
  "packageManager": "pnpm@10.9.0",
24
36
  "devDependencies": {
37
+ "@commitlint/cli": "^19.8.1",
38
+ "@commitlint/config-conventional": "^19.8.1",
25
39
  "@eslint/js": "^9.25.1",
26
40
  "@types/node": "^22.15.2",
27
41
  "@typescript-eslint/eslint-plugin": "^8.31.0",
28
42
  "@typescript-eslint/parser": "^8.31.0",
29
43
  "esbuild": "^0.25.3",
44
+ "esbuild-plugin-copy": "^2.1.1",
30
45
  "eslint": "^9.25.1",
31
46
  "globals": "^16.0.0",
47
+ "husky": "^9.1.7",
32
48
  "prettier": "^3.5.3",
33
49
  "rimraf": "^6.0.1",
34
50
  "ts-node": "^10.9.2",
@@ -41,6 +57,8 @@
41
57
  "commander": "^13.1.0",
42
58
  "enquirer": "^2.4.1",
43
59
  "execa": "^9.5.2",
60
+ "globby": "^14.1.0",
61
+ "handlebars": "^4.7.8",
44
62
  "inquirer": "^12.6.1",
45
63
  "listr2": "^8.3.2",
46
64
  "remark-stringify": "^11.0.0",
@@ -1,6 +1,3 @@
1
- import { Resource } from '../../../lib/project';
2
-
3
- const gitignore = `
4
1
  # Logs
5
2
  logs
6
3
  *.log
@@ -141,15 +138,5 @@ dist
141
138
  # build or bundles
142
139
  build/**/*
143
140
 
144
- # Ignore built ts files
141
+ # Ignore built js files
145
142
  dist/**/*
146
- `;
147
-
148
- export const getGitIgnoreContent = (): Resource => {
149
- const filename = '.gitignore';
150
-
151
- return {
152
- filename,
153
- content: gitignore,
154
- };
155
- };
@@ -0,0 +1,23 @@
1
+ import js from "@eslint/js";
2
+ import globals from "globals";
3
+ import tseslint from "typescript-eslint";
4
+ import eslintPluginTs from '@typescript-eslint/eslint-plugin';
5
+ import { defineConfig } from "eslint/config";
6
+
7
+ export default defineConfig([
8
+ { files: ["**/*.{js,mjs,cjs,ts}"], plugins: { js }, extends: ["js/recommended"] },
9
+ { files: ["**/*.{js,mjs,cjs,ts}"], languageOptions: { globals: globals.node } },
10
+ tseslint.configs.recommended,
11
+ {
12
+ plugins: {
13
+ '@typescript-eslint': eslintPluginTs,
14
+ },
15
+ rules: {
16
+ "@typescript-eslint/no-namespace": "off",
17
+ "@typescript-eslint/no-empty-interface": "off",
18
+ "@typescript-eslint/no-empty-object-type": "off",
19
+ "@typescript-eslint/no-unused-expressions": "off"
20
+ }
21
+ },
22
+ { ignores: ["node_modules/*", "dist/*"] },
23
+ ]);
@@ -0,0 +1,30 @@
1
+ {
2
+ "name": "{{name}}",
3
+ "version": "{{version}}",
4
+ "description": "{{description}}",
5
+ "author": "{{author}}",
6
+ "license": "ISC",
7
+ "main": "{{main}}",
8
+ {{#if scripts}}
9
+ "scripts": {
10
+ {{#each scripts}}
11
+ "{{@key}}": "{{this}}"{{#unless @last}},{{/unless}}
12
+ {{/each}}
13
+ },
14
+ {{/if}}
15
+ {{#if devDependencies}}
16
+ "devDependencies": {
17
+ {{#each devDependencies}}
18
+ "{{@key}}": "{{this}}"{{#unless @last}},{{/unless}}
19
+ {{/each}}
20
+ },
21
+ {{/if}}
22
+ {{#if dependencies}}
23
+ "dependencies": {
24
+ {{#each dependencies}}
25
+ "{{@key}}": "{{this}}"{{#unless @last}},{{/unless}}
26
+ {{/each}}
27
+ },
28
+ {{/if}}
29
+ "packageManager": "{{packageManager}}"
30
+ }
@@ -0,0 +1,5 @@
1
+ async function main() {
2
+ console.log('Hello from {{name}}');
3
+ }
4
+
5
+ main().catch((error) => console.error(error));
@@ -0,0 +1,5 @@
1
+ async function main() {
2
+ console.log('Hello from {{name}}');
3
+ }
4
+
5
+ main().catch((error) => console.error(error));
@@ -0,0 +1,14 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2024",
4
+ "module": "commonjs",
5
+ "outDir": "./dist",
6
+ "esModuleInterop": true,
7
+ "forceConsistentCasingInFileNames": true,
8
+ "strict": true,
9
+ "skipLibCheck": true
10
+ },
11
+ "include": [
12
+ "src"
13
+ ]
14
+ }
@@ -1,34 +0,0 @@
1
- name: Publish to NPM
2
-
3
- on:
4
- push:
5
- branches:
6
- - main # Trigger publish on push to main
7
-
8
- jobs:
9
- publish:
10
- runs-on: ubuntu-latest
11
-
12
- steps:
13
- - name: Checkout code
14
- uses: actions/checkout@v4
15
-
16
- - name: Setup Node.js
17
- uses: actions/setup-node@v4
18
- with:
19
- node-version: "22"
20
- registry-url: "https://registry.npmjs.org/"
21
-
22
- - name: Install pnpm
23
- run: npm install -g pnpm
24
-
25
- - name: Install dependencies
26
- run: pnpm install
27
-
28
- - name: Build
29
- run: pnpm run build
30
-
31
- - name: Publish to NPM
32
- run: npm publish --access public
33
- env:
34
- NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
package/bin/cli.ts DELETED
@@ -1,21 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- import { Command } from 'commander';
4
- import cliConfig from '../src/config/cli-config';
5
- import { CreateNodeApp } from '../src/templates';
6
-
7
- (async function () {
8
- const program = new Command();
9
- program
10
- .name(cliConfig.name)
11
- .description(cliConfig.description)
12
- .version(
13
- cliConfig.version,
14
- '-v, --version',
15
- 'output the version number',
16
- );
17
-
18
- new CreateNodeApp({ program });
19
-
20
- program.parse();
21
- })();
@@ -1,20 +0,0 @@
1
- type SemVersion =
2
- | `${number}.${number}.${number}`
3
- | `${number}.${number}.${number}-${string}`
4
- | `${number}.${number}.${number}+${string}`
5
- | `${number}.${number}.${number}-${string}+${string}`;
6
-
7
- type CLIConfiguration = {
8
- name: string;
9
- description: string;
10
- version: SemVersion;
11
- };
12
-
13
- const cliConfig: CLIConfiguration = {
14
- name: 'boilerforge',
15
- description:
16
- 'boilerforge is a blazing-fast CLI utility that scaffolds clean, ready-to-use project structures so you can skip the setup and start building instantly.',
17
- version: '0.0.1',
18
- };
19
-
20
- export default cliConfig;
package/src/lib/file.ts DELETED
@@ -1,159 +0,0 @@
1
- import {
2
- createReadStream,
3
- createWriteStream,
4
- existsSync,
5
- mkdirSync,
6
- readdirSync,
7
- rmdirSync,
8
- unlinkSync,
9
- writeFileSync,
10
- } from 'fs';
11
- import { join, sep } from 'path';
12
-
13
- import { logger } from '../utils/logger';
14
-
15
- export class File {
16
- private fileName: string;
17
- private filePath: string;
18
- private fileExtension?: string;
19
- private dirPath: string;
20
- private contextPath: string;
21
- private relativeDirPath: string;
22
- private relativeFilePath: string;
23
- private content?: string;
24
-
25
- constructor(
26
- filePath: string,
27
- fileOptions?: { dirPath?: string; content?: string },
28
- ) {
29
- const { content = '', dirPath } = fileOptions ?? {};
30
-
31
- const filePathSplit = filePath.split('/');
32
-
33
- const relativeDirPath = join(
34
- ...filePathSplit.slice(0, filePathSplit.length - 1),
35
- );
36
-
37
- const fileName = filePathSplit[filePathSplit.length - 1];
38
-
39
- this.contextPath = dirPath ?? __dirname;
40
- this.fileName = fileName;
41
- this.content = content;
42
- this.dirPath = join(
43
- this.contextPath,
44
- relativeDirPath.length ? relativeDirPath : __dirname,
45
- );
46
- this.filePath = join(this.dirPath, fileName);
47
- this.fileExtension = fileName.split('.').at(1);
48
- this.relativeDirPath = relativeDirPath;
49
- this.relativeFilePath = join(relativeDirPath, fileName);
50
- }
51
-
52
- get getFileName(): string {
53
- return this.fileName;
54
- }
55
-
56
- get getFilePath(): string {
57
- return this.filePath;
58
- }
59
-
60
- get getFileExtension(): string | undefined {
61
- return this.fileExtension;
62
- }
63
-
64
- get getDirPath(): string {
65
- return this.dirPath;
66
- }
67
-
68
- get getContextPath(): string {
69
- return this.contextPath;
70
- }
71
-
72
- get getRelativeDirPath(): string {
73
- return this.relativeDirPath;
74
- }
75
-
76
- get getRelativeFilePath(): string {
77
- return this.relativeFilePath;
78
- }
79
-
80
- create(content?: string) {
81
- try {
82
- mkdirSync(this.dirPath, { recursive: true });
83
- writeFileSync(
84
- this.filePath,
85
- content || this.content || '',
86
- 'utf-8',
87
- );
88
- } catch (error) {
89
- logger.err(
90
- `Error while creating the file: ${this.filePath}, ${(error as Error).message}`,
91
- );
92
-
93
- throw new Error(`Error while creating the file ${this.filePath}`);
94
- }
95
- }
96
-
97
- isExists() {
98
- return existsSync(this.filePath);
99
- }
100
-
101
- delete() {
102
- if (!this.isExists())
103
- throw new Error(`File does not exists: ${this.filePath}`);
104
-
105
- try {
106
- unlinkSync(this.filePath);
107
- this.deleteDir();
108
- } catch (error) {
109
- logger.err(
110
- `Error while deleting the file: ${this.filePath}, ${(error as Error).message}`,
111
- );
112
-
113
- throw new Error(`Error while deleting the file ${this.filePath}`);
114
- }
115
- }
116
-
117
- async createFrom(file: File) {
118
- if (!file.isExists())
119
- throw new Error(
120
- `File to copy from does not exist: ${file.getFilePath}`,
121
- );
122
-
123
- if (this.isExists())
124
- throw new Error(`File already exists: ${this.filePath}`);
125
-
126
- await new Promise((resolve, reject) => {
127
- const readStream = createReadStream(file.getFilePath, 'utf-8');
128
- const writeStream = createWriteStream(this.filePath);
129
-
130
- readStream.pipe(writeStream);
131
-
132
- readStream.on('error', reject);
133
- writeStream.on('error', reject);
134
- writeStream.on('finish', () => resolve);
135
- });
136
- }
137
-
138
- private deleteDir() {
139
- try {
140
- const dirs = this.relativeDirPath.split(sep);
141
-
142
- for (let i = dirs.length; i > 0; i--) {
143
- const dirPath = join(this.contextPath, ...dirs.slice(0, i));
144
-
145
- if (readdirSync(dirPath).length) break;
146
-
147
- rmdirSync(dirPath);
148
- }
149
- } catch (error) {
150
- logger.err(
151
- `Error while deleting the dirs: ${this.relativeDirPath}, ${(error as Error).message}`,
152
- );
153
-
154
- throw new Error(
155
- `Error while deleting the dirs: ${this.relativeDirPath}`,
156
- );
157
- }
158
- }
159
- }
@@ -1,210 +0,0 @@
1
- import { Command } from 'commander';
2
- import { Listr, ListrTaskWrapper } from 'listr2';
3
- import { dirname, join } from 'path';
4
- import { logger } from '../utils/logger';
5
- import { File } from './file';
6
- import { Task } from './task';
7
-
8
- export interface GitCheck {
9
- version?: string;
10
- configuration?: {
11
- username: string;
12
- email: string;
13
- };
14
- }
15
-
16
- export interface SystemCheck {
17
- git?: GitCheck;
18
- packageManager?: string;
19
- }
20
-
21
- export interface ProjectDependency {
22
- devDependencies: string[];
23
- dependencies: string[];
24
- }
25
-
26
- export interface Resource {
27
- filename: string;
28
- content: string;
29
- }
30
-
31
- export interface ProjectProps {
32
- name: string;
33
- packageManager: string;
34
- description?: string;
35
- version?: string;
36
- author?: string;
37
- }
38
-
39
- export interface BootstrapProps extends Partial<ProjectProps> {
40
- program: Command;
41
- showSubTasks?: boolean;
42
- showErrorMessage?: boolean;
43
- }
44
-
45
- export interface NodejsProjectProps extends BootstrapProps {}
46
-
47
- export abstract class Project {
48
- name: string = '';
49
- description: string = '';
50
- version: string = '';
51
- author: string = '';
52
- projectPath: string = '';
53
- parentDirPath: string = '';
54
- packageManager: string = '';
55
- packageManagerVersion: string = '';
56
-
57
- protected configureProject(projectProps: Partial<ProjectProps>) {
58
- const {
59
- name = this.name,
60
- description,
61
- version = '0.0.1',
62
- author,
63
- packageManager = '',
64
- } = projectProps;
65
-
66
- const cwd = process.cwd();
67
-
68
- this.name = !name.length ? cwd[cwd.length - 1] : name;
69
- this.description =
70
- description ?? `Node.js application for ${this.name}`;
71
- this.version = version;
72
- this.author = author ?? '';
73
- this.packageManager = packageManager;
74
- this.projectPath = join(cwd, name.length ? name : '');
75
- this.parentDirPath = name.length ? cwd : dirname(cwd);
76
- this.packageManagerVersion = '';
77
- }
78
-
79
- getPackageManager() {
80
- return `${this.packageManager}@${this.packageManagerVersion}`;
81
- }
82
- }
83
-
84
- export abstract class Bootstrap extends Project {
85
- protected tasks: Task[];
86
- protected executedTasks: Task[];
87
- protected showSubTasks?: boolean;
88
- protected showErrorMessage?: boolean;
89
- protected taskExecutor: Listr;
90
- protected systemCheck: SystemCheck;
91
- protected files: File[];
92
- protected program: Command;
93
- protected cmdExecutedFromDir: string;
94
-
95
- constructor(props: BootstrapProps) {
96
- super();
97
- this.tasks = [];
98
- this.executedTasks = [];
99
- this.showSubTasks = props.showSubTasks ?? true;
100
- this.showErrorMessage = props.showErrorMessage ?? false;
101
- this.taskExecutor = new Listr([]);
102
- this.systemCheck = {};
103
- this.files = [];
104
- this.program = props.program;
105
- this.cmdExecutedFromDir = process.cwd();
106
- this.configureProject(props);
107
- }
108
-
109
- private async buildListrTask(
110
- taskHandler: Task,
111
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
112
- ): Promise<{ title: string; task: any; enabled?: any }> {
113
- if (!taskHandler.subTasks.length) {
114
- return {
115
- title: taskHandler.title,
116
- enabled: taskHandler.enabled,
117
- task: async () => {
118
- await taskHandler.task();
119
- this.executedTasks.push(taskHandler);
120
- },
121
- };
122
- }
123
-
124
- return {
125
- title: taskHandler.title,
126
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
127
- task: async (_: any, task: ListrTaskWrapper<any, any, any>) => {
128
- await taskHandler.task();
129
- this.executedTasks.push(taskHandler);
130
-
131
- const subTasks = [];
132
- for (const subTask of taskHandler.subTasks) {
133
- subTasks.push(await this.buildListrTask(subTask));
134
- }
135
-
136
- return task.newListr([...subTasks], {
137
- exitOnError: taskHandler.exitOnError,
138
- concurrent: taskHandler.concurrent,
139
- });
140
- },
141
- };
142
- }
143
-
144
- async bootstrap(): Promise<void> {
145
- try {
146
- const listrTasks = await Promise.all(
147
- this.tasks.map(
148
- async (taskHandler) =>
149
- await this.buildListrTask(taskHandler),
150
- ),
151
- );
152
-
153
- this.taskExecutor.add(listrTasks);
154
- this.taskExecutor.options = {
155
- rendererOptions: {
156
- showErrorMessage: this.showErrorMessage,
157
- showSubtasks: this.showSubTasks,
158
- },
159
- };
160
- await this.taskExecutor.run();
161
- } catch (error) {
162
- logger.err(error);
163
-
164
- const rollbacks = this.tasks
165
- .map(({ rollback }) => rollback)
166
- .reverse();
167
-
168
- await Promise.all(
169
- rollbacks.map(
170
- async (rollback) => rollback && (await rollback()),
171
- ),
172
- );
173
- }
174
- }
175
-
176
- async setup(): Promise<Bootstrap> {
177
- throw new Error('Not Implemented');
178
- }
179
-
180
- async configureCliCommand(): Promise<Bootstrap> {
181
- throw new Error('Not Implemented');
182
- }
183
-
184
- async promptUser() {
185
- throw new Error('Not Implemented');
186
- }
187
-
188
- getSystemCheck() {
189
- return this.systemCheck;
190
- }
191
- }
192
-
193
- export abstract class NodejsProject extends Bootstrap {
194
- protected isTypescript: boolean;
195
- protected isEslintPrettier: boolean;
196
-
197
- constructor(nodejsProjectProps: NodejsProjectProps) {
198
- super(nodejsProjectProps);
199
- this.isTypescript = false;
200
- this.isEslintPrettier = false;
201
- }
202
-
203
- get enabledTypescript() {
204
- return this.isTypescript;
205
- }
206
-
207
- get enabledEslintPrettier() {
208
- return this.isEslintPrettier;
209
- }
210
- }