create-checks 1.0.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2022 cadienvan
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,307 @@
1
+ # create-checks
2
+
3
+ A zero-config scaffolding CLI that wires **ESLint + Prettier** into any Node.js project in one command.
4
+
5
+ ```sh
6
+ npm create @jeportie/checks
7
+ ```
8
+
9
+ ---
10
+
11
+ ## What it does
12
+
13
+ Running `npm create @jeportie/checks` inside an existing project will:
14
+
15
+ 1. **Install** ESLint, Prettier, and their plugins as dev dependencies
16
+ 2. **Copy** `eslint.config.js` and `prettier.config.js` into your project root
17
+ 3. **Inject** three scripts into your `package.json`:
18
+ - `lint` → `eslint .`
19
+ - `format` → `prettier . --write`
20
+ - `typecheck` → `tsc --noEmit`
21
+
22
+ Everything runs in your project — nothing is installed globally.
23
+
24
+ ---
25
+
26
+ ## Quick start
27
+
28
+ ```sh
29
+ # Inside your existing project
30
+ npm create @jeportie/checks
31
+
32
+ # Then use the injected scripts
33
+ npm run lint
34
+ npm run format
35
+ npm run typecheck
36
+ ```
37
+
38
+ ---
39
+
40
+ ## How it works internally
41
+
42
+ ```
43
+ npm create @jeportie/checks
44
+
45
+ └─▶ npm downloads the create-checks package
46
+ └─▶ node runs ./src/index.js (registered via "bin" in package.json)
47
+
48
+ ├─ 1. npm install -D eslint prettier ... (in YOUR project's CWD)
49
+ ├─ 2. copy src/templates/eslint.config.js → YOUR project/eslint.config.js
50
+ ├─ 3. copy src/templates/prettier.config.js → YOUR project/prettier.config.js
51
+ └─ 4. read YOUR project/package.json → inject scripts → write it back
52
+ ```
53
+
54
+ ### Template path resolution
55
+
56
+ Inside `src/index.js`:
57
+
58
+ ```js
59
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
60
+ const cwd = process.cwd();
61
+ ```
62
+
63
+ - `__dirname` always points to `create-checks/src/` — the CLI's own files, wherever npm installed them
64
+ - `cwd` is **your** project's directory — where files get copied and `package.json` gets updated
65
+
66
+ This separation is what lets a `create-*` tool safely write into an unrelated target directory.
67
+
68
+ ### How `bin` mapping works in npm
69
+
70
+ ```json
71
+ "bin": {
72
+ "create-checks": "./src/index.js"
73
+ }
74
+ ```
75
+
76
+ When npm installs a package that has a `bin` field, it creates a symlink in `node_modules/.bin/`. When you run `npm create foo`, npm translates that into `npm exec create-foo` and executes the registered binary. The `#!/usr/bin/env node` shebang on line 1 of `src/index.js` tells the OS to run it with Node.
77
+
78
+ ---
79
+
80
+ ## What gets installed in your project
81
+
82
+ | Package | Purpose |
83
+ | ----------------------------------- | ------------------------------------------------- |
84
+ | `eslint` | JavaScript/TypeScript linter |
85
+ | `prettier` | Opinionated code formatter |
86
+ | `eslint-config-prettier` | Disables ESLint rules that conflict with Prettier |
87
+ | `typescript-eslint` | TypeScript parser and rules for ESLint |
88
+ | `@stylistic/eslint-plugin` | Code style rules (quotes, spacing, etc.) |
89
+ | `eslint-plugin-import` | Import order and resolution rules |
90
+ | `eslint-import-resolver-typescript` | Resolves TypeScript paths in import plugin |
91
+
92
+ ---
93
+
94
+ ## What the templates configure
95
+
96
+ ### `eslint.config.js`
97
+
98
+ Uses ESLint's flat config format (ESLint 9+). Includes:
99
+
100
+ - `@eslint/js` recommended rules
101
+ - Full TypeScript type-checked rules via `typescript-eslint`
102
+ - Stylistic rules (single quotes, spaced comments)
103
+ - Import ordering and cycle detection
104
+ - Prettier compatibility (must be last)
105
+ - Test file overrides (relaxed rules in `*.test.*`)
106
+
107
+ ### `prettier.config.js`
108
+
109
+ Standard Prettier settings:
110
+
111
+ - Single quotes, trailing commas, 80-char print width
112
+ - No semicolons in prose, arrow parens always
113
+
114
+ ---
115
+
116
+ ## Next steps — optional tooling
117
+
118
+ After running `create-checks`, here are recommended tools to layer on top:
119
+
120
+ ### Husky — git hooks
121
+
122
+ Runs linting/tests automatically before every commit.
123
+
124
+ ```sh
125
+ npm install -D husky
126
+ npx husky init
127
+ ```
128
+
129
+ Add to `.husky/pre-commit`:
130
+
131
+ ```sh
132
+ npx lint-staged
133
+ ```
134
+
135
+ ### lint-staged — only lint changed files
136
+
137
+ Prevents the pre-commit hook from linting your entire codebase.
138
+
139
+ ```sh
140
+ npm install -D lint-staged
141
+ ```
142
+
143
+ Add to `package.json`:
144
+
145
+ ```json
146
+ "lint-staged": {
147
+ "*.{js,ts}": ["eslint --fix", "prettier --write"],
148
+ "*.{json,yml,md}": ["prettier --write --ignore-unknown"]
149
+ }
150
+ ```
151
+
152
+ ### Commitlint — enforce Conventional Commits
153
+
154
+ Ensures commit messages follow the `feat:`, `fix:`, `chore:` convention required by semantic-release.
155
+
156
+ ```sh
157
+ npm install -D @commitlint/cli @commitlint/config-conventional
158
+ echo "export default { extends: ['@commitlint/config-conventional'] };" > commitlint.config.js
159
+ ```
160
+
161
+ Add to `.husky/commit-msg`:
162
+
163
+ ```sh
164
+ npx --no -- commitlint --edit $1
165
+ ```
166
+
167
+ ### Secretlint — prevent secret leaks
168
+
169
+ Scans your files for accidentally committed API keys, tokens, and passwords.
170
+
171
+ ```sh
172
+ npm install -D secretlint @secretlint/secretlint-rule-preset-recommend
173
+ ```
174
+
175
+ Add a `.secretlintrc.json`:
176
+
177
+ ```json
178
+ {
179
+ "rules": [{ "id": "@secretlint/secretlint-rule-preset-recommend" }]
180
+ }
181
+ ```
182
+
183
+ Add to `package.json` scripts:
184
+
185
+ ```json
186
+ "secretlint": "secretlint ./src --maskSecrets"
187
+ ```
188
+
189
+ ### CSpell — spell checking
190
+
191
+ Catches typos in source code, comments, and docs.
192
+
193
+ ```sh
194
+ npm install -D cspell
195
+ ```
196
+
197
+ Add to `package.json` scripts:
198
+
199
+ ```json
200
+ "spellcheck": "cspell --no-progress \"./**/*.{js,ts,md,json}\""
201
+ ```
202
+
203
+ ### Semantic Release — automated versioning and publishing
204
+
205
+ Reads your Conventional Commits and automatically bumps the version, generates a changelog, and publishes to npm.
206
+
207
+ See [How to release](#how-to-release) below.
208
+
209
+ ---
210
+
211
+ ## How to release
212
+
213
+ This repo is pre-configured with [semantic-release](https://semantic-release.gitbook.io/semantic-release/).
214
+
215
+ ### One-time setup
216
+
217
+ 1. Create an **npm access token** at [npmjs.com → Access Tokens](https://www.npmjs.com/settings/~/tokens) (type: **Automation**)
218
+ 2. Add it as a secret named `NPM_TOKEN` in your GitHub repo under **Settings → Secrets → Actions**
219
+ 3. `GITHUB_TOKEN` is provided automatically — no action needed
220
+
221
+ ### Release flow
222
+
223
+ ```
224
+ git commit -m "feat: add support for --skip-install flag"
225
+ git push origin main
226
+
227
+ └─▶ GitHub Actions: semantic-release.yml
228
+ ├─ Analyzes commits since last tag
229
+ │ feat → minor bump (0.1.0 → 0.2.0)
230
+ │ fix → patch bump (0.1.0 → 0.1.1)
231
+ │ feat! → major bump (0.1.0 → 1.0.0)
232
+ ├─ Generates release notes
233
+ ├─ Publishes to npm registry
234
+ └─ Creates a GitHub Release + git tag (v0.2.0)
235
+ ```
236
+
237
+ **Never bump the version in `package.json` manually** — semantic-release owns that. The placeholder `"0.0.0-semantically-released"` is intentional and gets replaced at publish time.
238
+
239
+ ### Commit message format
240
+
241
+ ```
242
+ <type>(<scope>): <description>
243
+
244
+ feat: add --dry-run flag
245
+ fix: resolve template path on Windows
246
+ docs: update README with next steps
247
+ chore: upgrade eslint to v9
248
+ ```
249
+
250
+ ---
251
+
252
+ ## Development
253
+
254
+ ### Requirements
255
+
256
+ - Node.js 20+ (see `.nvmrc`)
257
+ - npm
258
+
259
+ ### Setup
260
+
261
+ ```sh
262
+ git clone https://github.com/jeportie/create-checks.git
263
+ cd create-checks
264
+ npm install
265
+ ```
266
+
267
+ ### Run tests
268
+
269
+ ```sh
270
+ npm test # all tests
271
+ npm run test:integration # integration tests only
272
+ npm run test:coverage # with coverage report
273
+ ```
274
+
275
+ ### Test a local build
276
+
277
+ ```sh
278
+ mkdir /tmp/my-test-project
279
+ cd /tmp/my-test-project
280
+ npm init -y
281
+ node /path/to/create-checks/src/index.js
282
+ ```
283
+
284
+ ### Project structure
285
+
286
+ ```
287
+ create-checks/
288
+ ├── src/
289
+ │ ├── index.js # CLI entrypoint (#!/usr/bin/env node)
290
+ │ └── templates/
291
+ │ ├── eslint.config.js # copied into the user's project
292
+ │ └── prettier.config.js
293
+ ├── __tests__/
294
+ │ └── integration/
295
+ │ └── index.int.test.js # spawns the CLI in a temp dir
296
+ ├── .github/workflows/
297
+ │ ├── pull-request-checks.yml
298
+ │ └── semantic-release.yml
299
+ ├── release.config.mjs # semantic-release configuration
300
+ └── package.json
301
+ ```
302
+
303
+ ---
304
+
305
+ ## License
306
+
307
+ MIT
package/package.json ADDED
@@ -0,0 +1,63 @@
1
+ {
2
+ "name": "create-checks",
3
+ "version": "1.0.1",
4
+ "description": "Scaffolding CLI that installs ESLint + Prettier and injects config into any project",
5
+ "author": "jeportie",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "git://github.com/jeportie/create-checks.git"
9
+ },
10
+ "keywords": [
11
+ "eslint",
12
+ "prettier",
13
+ "scaffolding",
14
+ "create",
15
+ "cli"
16
+ ],
17
+ "license": "MIT",
18
+ "private": false,
19
+ "type": "module",
20
+ "bin": {
21
+ "create-checks": "src/index.js"
22
+ },
23
+ "files": [
24
+ "src"
25
+ ],
26
+ "publishConfig": {
27
+ "access": "public"
28
+ },
29
+ "scripts": {
30
+ "format": "prettier . --write",
31
+ "lint": "eslint .",
32
+ "secretlint": "secretlint ./src --maskSecrets",
33
+ "spellcheck": "cspell --no-progress \"./**/*.{js,mjs,cjs,md,json,yml}\"",
34
+ "test": "vitest --run",
35
+ "test:coverage": "vitest --coverage --run",
36
+ "test:integration": "vitest int --run",
37
+ "prepare": "husky || true"
38
+ },
39
+ "dependencies": {
40
+ "execa": "^8.0.1",
41
+ "fs-extra": "^11.2.0",
42
+ "picocolors": "^1.0.0"
43
+ },
44
+ "devDependencies": {
45
+ "@commitlint/cli": "^19.3.0",
46
+ "@commitlint/config-conventional": "^19.2.2",
47
+ "@eslint/js": "^9.0.0",
48
+ "@secretlint/secretlint-rule-pattern": "^8.2.4",
49
+ "@secretlint/secretlint-rule-preset-recommend": "^8.2.4",
50
+ "@vitest/coverage-v8": "^2.0.4",
51
+ "commitlint-plugin-cspell": "^0.1.1",
52
+ "conventional-changelog-conventionalcommits": "~8.0.0",
53
+ "cspell": "^8.12.1",
54
+ "eslint": "^9.0.0",
55
+ "eslint-config-prettier": "^9.1.0",
56
+ "husky": "^9.1.1",
57
+ "lint-staged": "^15.2.7",
58
+ "prettier": "^3.3.3",
59
+ "secretlint": "^8.2.4",
60
+ "semantic-release": "~24.0.0",
61
+ "vitest": "^2.0.4"
62
+ }
63
+ }
package/src/index.js ADDED
@@ -0,0 +1,54 @@
1
+ #!/usr/bin/env node
2
+
3
+ import fs from 'fs-extra';
4
+ import { execa } from 'execa';
5
+ import pc from 'picocolors';
6
+ import path from 'node:path';
7
+ import { fileURLToPath } from 'node:url';
8
+
9
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
10
+ const cwd = process.cwd();
11
+
12
+ console.log(pc.cyan('🔧 Setting up ESLint + Prettier...'));
13
+
14
+ /* ---------------- INSTALL DEPENDENCIES ---------------- */
15
+
16
+ if (!process.env.NO_INSTALL) {
17
+ await execa(
18
+ 'npm',
19
+ [
20
+ 'install',
21
+ '-D',
22
+ 'eslint',
23
+ 'prettier',
24
+ 'eslint-config-prettier',
25
+ 'typescript-eslint',
26
+ '@stylistic/eslint-plugin',
27
+ 'eslint-plugin-import',
28
+ 'eslint-import-resolver-typescript',
29
+ ],
30
+ { stdio: 'inherit' },
31
+ );
32
+ }
33
+
34
+ /* ---------------- COPY TEMPLATE FILES ---------------- */
35
+
36
+ await fs.copyFile(path.join(__dirname, 'templates/eslint.config.js'), path.join(cwd, 'eslint.config.js'));
37
+
38
+ await fs.copyFile(path.join(__dirname, 'templates/prettier.config.js'), path.join(cwd, 'prettier.config.js'));
39
+
40
+ /* ---------------- UPDATE package.json ---------------- */
41
+
42
+ const pkgPath = path.join(cwd, 'package.json');
43
+ const pkg = await fs.readJson(pkgPath);
44
+
45
+ pkg.scripts = {
46
+ ...pkg.scripts,
47
+ lint: 'eslint .',
48
+ format: 'prettier . --write',
49
+ typecheck: 'tsc --noEmit',
50
+ };
51
+
52
+ await fs.writeJson(pkgPath, pkg, { spaces: 2 });
53
+
54
+ console.log(pc.green('✅ ESLint + Prettier configured successfully!'));
@@ -0,0 +1,95 @@
1
+ import eslint from '@eslint/js';
2
+ import tseslint from 'typescript-eslint';
3
+ import stylistic from '@stylistic/eslint-plugin';
4
+ import importPlugin from 'eslint-plugin-import';
5
+ import prettier from 'eslint-config-prettier';
6
+
7
+ export default tseslint.config(
8
+ {
9
+ ignores: [
10
+ '**/dist/**',
11
+ '**/node_modules/**',
12
+ '**/coverage/**',
13
+ '**/.vite/**',
14
+ ],
15
+ },
16
+
17
+ eslint.configs.recommended,
18
+
19
+ ...tseslint.configs.recommendedTypeChecked,
20
+ ...tseslint.configs.stylisticTypeChecked,
21
+
22
+ {
23
+ plugins: {
24
+ '@stylistic': stylistic,
25
+ import: importPlugin,
26
+ },
27
+
28
+ languageOptions: {
29
+ parserOptions: {
30
+ projectService: true,
31
+ tsconfigRootDir: import.meta.dirname,
32
+ },
33
+ },
34
+
35
+ settings: {
36
+ 'import/resolver': {
37
+ typescript: true,
38
+ node: true,
39
+ },
40
+ },
41
+
42
+ rules: {
43
+ /* ---------------- IMPORTS ---------------- */
44
+ 'import/first': 'error',
45
+ 'import/no-cycle': 'error',
46
+ 'import/no-self-import': 'error',
47
+ 'import/no-unresolved': 'error',
48
+ 'import/no-useless-path-segments': 'error',
49
+ 'import/order': [
50
+ 'error',
51
+ {
52
+ alphabetize: { order: 'asc', caseInsensitive: true },
53
+ groups: [
54
+ 'builtin',
55
+ 'external',
56
+ 'internal',
57
+ 'parent',
58
+ ['sibling', 'index'],
59
+ 'type',
60
+ ],
61
+ 'newlines-between': 'always',
62
+ },
63
+ ],
64
+
65
+ /* ---------------- STYLISTIC ---------------- */
66
+ '@stylistic/quotes': ['error', 'single', { avoidEscape: true }],
67
+ 'spaced-comment': ['error', 'always'],
68
+
69
+ /* ---------------- TYPESCRIPT ---------------- */
70
+ '@typescript-eslint/no-unused-vars': [
71
+ 'error',
72
+ { argsIgnorePattern: '^_' },
73
+ ],
74
+ },
75
+ },
76
+
77
+ /* ---------------- TEST OVERRIDES ---------------- */
78
+ {
79
+ files: ['**/*.test.{ts,tsx}', '**/*.spec.{ts,tsx}'],
80
+ rules: {
81
+ '@typescript-eslint/no-explicit-any': 'off',
82
+ '@typescript-eslint/no-unsafe-assignment': 'off',
83
+ '@typescript-eslint/no-unsafe-call': 'off',
84
+ },
85
+ },
86
+
87
+ /* ---------------- CONFIG FILES ---------------- */
88
+ {
89
+ files: ['*.config.{js,mjs,cjs}'],
90
+ ...tseslint.configs.disableTypeChecked,
91
+ },
92
+
93
+ /* ---------------- PRETTIER MUST BE LAST ---------------- */
94
+ prettier,
95
+ );
@@ -0,0 +1,12 @@
1
+ export default {
2
+ printWidth: 80,
3
+ tabWidth: 2,
4
+ useTabs: false,
5
+ semi: true,
6
+ singleQuote: true,
7
+ trailingComma: 'all',
8
+ bracketSameLine: false,
9
+ bracketSpacing: true,
10
+ arrowParens: 'always',
11
+ proseWrap: 'never',
12
+ };