@jeportie/create-tskickstart 1.6.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/src/index.js ADDED
@@ -0,0 +1,498 @@
1
+ #!/usr/bin/env node
2
+
3
+ // TODO: refactor into separate modules for easier maintenance
4
+
5
+ import fs from 'fs-extra';
6
+ import { execa } from 'execa';
7
+ import inquirer from 'inquirer';
8
+ import pc from 'picocolors';
9
+ import path from 'node:path';
10
+ import { fileURLToPath } from 'node:url';
11
+
12
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
13
+ const cwd = process.cwd();
14
+ const pkgPath = path.join(cwd, 'package.json');
15
+
16
+ // Thin wrapper: catches ExitPromptError (thrown synchronously via signal-exit
17
+ // when the user presses Ctrl+C) so the process exits cleanly without a stack trace.
18
+ async function prompt(questions) {
19
+ try {
20
+ return await inquirer.prompt(questions);
21
+ } catch (err) {
22
+ if (err?.name === 'ExitPromptError') {
23
+ console.log(pc.yellow('\nCancelled.\n'));
24
+ process.exit(0);
25
+ }
26
+ throw err;
27
+ }
28
+ }
29
+
30
+ console.log(pc.cyan('\nšŸ”§ tskickstart — setting up the project...\n'));
31
+
32
+ /* ---------------- ADDITIONAL LINT PROMPTS ---------------- */
33
+ let lintOption = [];
34
+
35
+ if (process.stdin.isTTY) {
36
+ const result = await prompt([
37
+ {
38
+ type: 'checkbox',
39
+ name: 'lintOption',
40
+ message: 'Select more lint options',
41
+ choices: ['cspell', 'secretlint', 'commitlint'],
42
+ },
43
+ ]);
44
+ lintOption = result.lintOption;
45
+ }
46
+
47
+ /* ---------------- VITEST PROMPT ---------------- */
48
+
49
+ // VITEST_PRESET can be set to 'native', 'coverage', or 'none' to bypass the prompt
50
+ // (used by tests and CI environments where stdin is not a TTY)
51
+ let vitestPreset = process.env.VITEST_PRESET;
52
+
53
+ if (!vitestPreset && process.stdin.isTTY) {
54
+ const { setupVitest } = await prompt([
55
+ {
56
+ type: 'confirm',
57
+ name: 'setupVitest',
58
+ message: 'Do you want to set up Vitest for testing?',
59
+ default: true,
60
+ },
61
+ ]);
62
+
63
+ if (setupVitest) {
64
+ const { preset } = await prompt([
65
+ {
66
+ type: 'list',
67
+ name: 'preset',
68
+ message: 'Which Vitest configuration would you like?',
69
+ choices: [
70
+ {
71
+ name: 'Native — vitest',
72
+ value: 'native',
73
+ },
74
+ {
75
+ name: 'Coverage — vitest + @vitest/coverage-v8',
76
+ value: 'coverage',
77
+ },
78
+ ],
79
+ },
80
+ ]);
81
+ vitestPreset = preset;
82
+ }
83
+ }
84
+
85
+ /* ---------------- PRE COMMIT HOOK PROMPT ---------------- */
86
+ let setupPrecommit = true;
87
+
88
+ if (process.stdin.isTTY) {
89
+ const result = await prompt([
90
+ {
91
+ type: 'confirm',
92
+ name: 'setupPrecommit',
93
+ message: 'Do you want to set up pre-commit hook (husky + lint-staged)?',
94
+ default: true,
95
+ },
96
+ ]);
97
+ setupPrecommit = result.setupPrecommit;
98
+ }
99
+
100
+ /* ---------------- AUTHOR NAME ---------------- */
101
+
102
+ // AUTHOR_NAME env var bypasses git config + prompt (used by tests and CI)
103
+ let authorName = '';
104
+
105
+ if (process.env.AUTHOR_NAME !== undefined) {
106
+ authorName = process.env.AUTHOR_NAME;
107
+ } else {
108
+ try {
109
+ const { stdout } = await execa('git', ['config', 'github.user']);
110
+ authorName = stdout.trim();
111
+ } catch {
112
+ // github.user not set
113
+ }
114
+
115
+ if (!authorName) {
116
+ try {
117
+ const { stdout } = await execa('git', ['config', 'user.name']);
118
+ authorName = stdout.trim();
119
+ } catch {
120
+ // git not available or user.name not set
121
+ }
122
+ }
123
+
124
+ if (!authorName && process.stdin.isTTY) {
125
+ const result = await prompt([
126
+ {
127
+ type: 'input',
128
+ name: 'authorName',
129
+ message: 'Your name (added to package.json and spell checker):',
130
+ },
131
+ ]);
132
+ authorName = result.authorName.trim();
133
+ }
134
+ }
135
+
136
+ /* ---------------- ENSURE package.json EXISTS ---------------- */
137
+
138
+ if (!(await fs.pathExists(pkgPath))) {
139
+ console.log(pc.red('\n⨯'), pc.yellow(' No package.json found — running npm init -y...'));
140
+ await execa('npm', ['init', '-y'], { stdout: 'ignore', stderr: 'inherit' });
141
+ const pkg = await fs.readJson(pkgPath);
142
+ pkg.type = 'module';
143
+ await fs.writeJson(pkgPath, pkg, { spaces: 2 });
144
+ console.log(pc.green('āœ”') + ' package.json created with "type": "module"');
145
+ } else {
146
+ const pkg = await fs.readJson(pkgPath);
147
+ if (pkg.type !== 'module') {
148
+ pkg.type = 'module';
149
+ await fs.writeJson(pkgPath, pkg, { spaces: 2 });
150
+ console.log(pc.green('āœ”') + ' package.json — added "type": "module"');
151
+ }
152
+ }
153
+
154
+ /* ---------------- SPINNER HELPER ---------------- */
155
+
156
+ function startSpinner(text) {
157
+ const frames = ['ā ‹', 'ā ™', 'ā ¹', 'ā ø', 'ā ¼', 'ā “', 'ā ¦', 'ā §', 'ā ‡', 'ā '];
158
+ let i = 0;
159
+ process.stdout.write(`${frames[0]} ${text}`);
160
+ const id = setInterval(() => {
161
+ process.stdout.write(`\r${pc.cyan(frames[i++ % frames.length])} ${text}`);
162
+ }, 80);
163
+ return (doneText) => {
164
+ clearInterval(id);
165
+ process.stdout.write(`\r\x1B[K${pc.green('āœ”')} ${doneText}\n`);
166
+ };
167
+ }
168
+
169
+ /* ---------------- INSTALL DEPENDENCIES ---------------- */
170
+
171
+ if (!process.env.NO_INSTALL) {
172
+ const deps = [
173
+ 'eslint@^9',
174
+ '@eslint/js@^9',
175
+ 'prettier',
176
+ 'eslint-config-prettier@^9.1.0',
177
+ 'typescript-eslint',
178
+ '@stylistic/eslint-plugin',
179
+ 'eslint-plugin-import',
180
+ 'eslint-import-resolver-typescript',
181
+ 'typescript',
182
+ '@types/node',
183
+ ];
184
+
185
+ if (lintOption.includes('secretlint')) {
186
+ deps.push('secretlint', '@secretlint/secretlint-rule-preset-recommend');
187
+ }
188
+
189
+ if (lintOption.includes('cspell')) {
190
+ deps.push('cspell', '@cspell/eslint-plugin');
191
+ }
192
+
193
+ if (lintOption.includes('commitlint')) {
194
+ deps.push('@commitlint/cli', '@commitlint/config-conventional');
195
+ if (lintOption.includes('cspell')) {
196
+ deps.push('commitlint-plugin-cspell');
197
+ }
198
+ }
199
+
200
+ if (setupPrecommit) {
201
+ deps.push('husky', 'lint-staged');
202
+ }
203
+
204
+ if (vitestPreset === 'native' || vitestPreset === 'coverage') {
205
+ deps.push('vitest');
206
+ }
207
+ if (vitestPreset === 'coverage') {
208
+ deps.push('@vitest/coverage-v8');
209
+ }
210
+
211
+ const stopSpinner = startSpinner('Installing dev dependencies...');
212
+ await execa('npm', ['install', '-D', ...deps], { stdio: 'ignore' });
213
+ stopSpinner('dev dependencies installed');
214
+ }
215
+
216
+ /* ---------------- COPY TEMPLATE FILES ---------------- */
217
+ console.log(pc.green('→') + ` copying config files...`);
218
+
219
+ // --- regular config files (typescript → formatting → linting → testing → commit hooks) ---
220
+
221
+ if (!(await fs.pathExists(path.join(cwd, 'tsconfig.base.json')))) {
222
+ await fs.copyFile(path.join(__dirname, 'templates/tsconfig.base.json'), path.join(cwd, 'tsconfig.base.json'));
223
+ console.log(pc.green('āœ”') + ' tsconfig.base.json');
224
+ } else {
225
+ console.log(pc.dim('–') + ' tsconfig.base.json (already exists, skipped)');
226
+ }
227
+
228
+ if (!(await fs.pathExists(path.join(cwd, 'tsconfig.json')))) {
229
+ await fs.copyFile(path.join(__dirname, 'templates/tsconfig.json'), path.join(cwd, 'tsconfig.json'));
230
+ console.log(pc.green('āœ”') + ' tsconfig.json');
231
+ } else {
232
+ console.log(pc.dim('–') + ' tsconfig.json (already exists, skipped)');
233
+ }
234
+
235
+ await fs.copyFile(path.join(__dirname, 'templates/prettier.config.js'), path.join(cwd, 'prettier.config.js'));
236
+ console.log(pc.green('āœ”') + ' prettier.config.js');
237
+
238
+ const eslintConfig = lintOption.includes('cspell') ? 'templates/eslintCspell.config.js' : 'templates/eslint.config.js';
239
+ await fs.copyFile(path.join(__dirname, eslintConfig), path.join(cwd, 'eslint.config.js'));
240
+ console.log(pc.green('āœ”') + ' eslint.config.js');
241
+
242
+ if (lintOption.includes('cspell')) {
243
+ if (!(await fs.pathExists(path.join(cwd, 'cspell.json')))) {
244
+ await fs.copyFile(path.join(__dirname, 'templates/cspell.json'), path.join(cwd, 'cspell.json'));
245
+ console.log(pc.green('āœ”') + ' cspell.json');
246
+ } else {
247
+ console.log(pc.dim('–') + ' cspell.json (already exists, skipped)');
248
+ }
249
+
250
+ if (authorName) {
251
+ const cspellPath = path.join(cwd, 'cspell.json');
252
+ const cspellJson = await fs.readJson(cspellPath);
253
+ if (!cspellJson.words) cspellJson.words = [];
254
+ for (const word of authorName.split(/\s+/).filter(Boolean)) {
255
+ if (!cspellJson.words.includes(word)) cspellJson.words.push(word);
256
+ }
257
+ await fs.writeJson(cspellPath, cspellJson, { spaces: 2 });
258
+ }
259
+ }
260
+
261
+ if (vitestPreset === 'native' || vitestPreset === 'coverage') {
262
+ await fs.copyFile(
263
+ path.join(__dirname, `templates/vitest.config.${vitestPreset}.ts`),
264
+ path.join(cwd, 'vitest.config.ts'),
265
+ );
266
+ console.log(pc.green('āœ”') + ' vitest.config.ts');
267
+ }
268
+
269
+ if (lintOption.includes('commitlint')) {
270
+ if (!(await fs.pathExists(path.join(cwd, 'commitlint.config.js')))) {
271
+ await fs.copyFile(path.join(__dirname, 'templates/commitlint.config.js'), path.join(cwd, 'commitlint.config.js'));
272
+ console.log(pc.green('āœ”') + ' commitlint.config.js');
273
+ } else {
274
+ console.log(pc.dim('–') + ' commitlint.config.js (already exists, skipped)');
275
+ }
276
+ }
277
+
278
+ // --- dotfiles (editor/git → formatting → linting → commit hooks) ---
279
+
280
+ if (!(await fs.pathExists(path.join(cwd, '.editorconfig')))) {
281
+ await fs.copyFile(path.join(__dirname, 'templates/.editorconfig'), path.join(cwd, '.editorconfig'));
282
+ console.log(pc.green('āœ”') + ' .editorconfig');
283
+ } else {
284
+ console.log(pc.dim('–') + ' .editorconfig (already exists, skipped)');
285
+ }
286
+
287
+ if (!(await fs.pathExists(path.join(cwd, '.gitignore')))) {
288
+ await fs.copyFile(path.join(__dirname, 'templates/_gitignore'), path.join(cwd, '.gitignore'));
289
+ console.log(pc.green('āœ”') + ' .gitignore');
290
+ } else {
291
+ console.log(pc.dim('–') + ' .gitignore (already exists, skipped)');
292
+ }
293
+
294
+ if (!(await fs.pathExists(path.join(cwd, '.prettierignore')))) {
295
+ await fs.copyFile(path.join(__dirname, 'templates/.prettierignore'), path.join(cwd, '.prettierignore'));
296
+ console.log(pc.green('āœ”') + ' .prettierignore');
297
+ } else {
298
+ console.log(pc.dim('–') + ' .prettierignore (already exists, skipped)');
299
+ }
300
+
301
+ if (!(await fs.pathExists(path.join(cwd, '.eslintignore')))) {
302
+ await fs.copyFile(path.join(__dirname, 'templates/.eslintignore'), path.join(cwd, '.eslintignore'));
303
+ console.log(pc.green('āœ”') + ' .eslintignore');
304
+ } else {
305
+ console.log(pc.dim('–') + ' .eslintignore (already exists, skipped)');
306
+ }
307
+
308
+ if (lintOption.includes('secretlint')) {
309
+ if (!(await fs.pathExists(path.join(cwd, '.secretlintrc.json')))) {
310
+ await fs.copyFile(path.join(__dirname, 'templates/.secretlintrc.json'), path.join(cwd, '.secretlintrc.json'));
311
+ console.log(pc.green('āœ”') + ' .secretlintrc.json');
312
+ } else {
313
+ console.log(pc.dim('–') + ' .secretlintrc.json (already exists, skipped)');
314
+ }
315
+ }
316
+
317
+ if (setupPrecommit) {
318
+ const huskyDir = path.join(cwd, '.husky');
319
+ await fs.ensureDir(huskyDir);
320
+
321
+ const preCommitDest = path.join(huskyDir, 'pre-commit');
322
+ if (!(await fs.pathExists(preCommitDest))) {
323
+ const lines = ['npx lint-staged', 'npm run typecheck'];
324
+ if (vitestPreset === 'native' || vitestPreset === 'coverage') lines.push('npm run test');
325
+ await fs.writeFile(preCommitDest, lines.join('\n') + '\n');
326
+ console.log(pc.green('āœ”') + ' .husky/pre-commit');
327
+ } else {
328
+ console.log(pc.dim('–') + ' .husky/pre-commit (already exists, skipped)');
329
+ }
330
+
331
+ if (lintOption.includes('commitlint')) {
332
+ const commitMsgDest = path.join(huskyDir, 'commit-msg');
333
+ if (!(await fs.pathExists(commitMsgDest))) {
334
+ await fs.writeFile(commitMsgDest, 'npx commitlint --edit\n');
335
+ console.log(pc.green('āœ”') + ' .husky/commit-msg');
336
+ } else {
337
+ console.log(pc.dim('–') + ' .husky/commit-msg (already exists, skipped)');
338
+ }
339
+ }
340
+ }
341
+
342
+ // --- project directories ---
343
+ console.log(pc.green('→') + ' creating project directories:');
344
+
345
+ const srcDir = path.join(cwd, 'src');
346
+ await fs.ensureDir(srcDir);
347
+ const mainTs = path.join(srcDir, 'main.ts');
348
+ if (!(await fs.pathExists(mainTs))) {
349
+ await fs.writeFile(
350
+ mainTs,
351
+ `export function helloWorld(): void {
352
+ console.log('Hello, World!');
353
+ }
354
+
355
+ helloWorld();
356
+ `,
357
+ );
358
+ console.log(pc.green('āœ”') + ' src/main.ts');
359
+ } else {
360
+ console.log(pc.dim('–') + ' src/main.ts (already exists, skipped)');
361
+ }
362
+
363
+ if (vitestPreset === 'native' || vitestPreset === 'coverage') {
364
+ const testDir = path.join(cwd, 'test');
365
+ await fs.ensureDir(testDir);
366
+ const mainTestTs = path.join(testDir, 'main.test.ts');
367
+ if (!(await fs.pathExists(mainTestTs))) {
368
+ await fs.writeFile(
369
+ mainTestTs,
370
+ `import { afterEach, describe, expect, it, vi } from 'vitest';
371
+
372
+ import { helloWorld } from '@/main';
373
+
374
+ describe('helloWorld', () => {
375
+ afterEach(() => {
376
+ vi.restoreAllMocks();
377
+ });
378
+
379
+ it('logs "Hello, World!" to the console', () => {
380
+ const spy = vi.spyOn(console, 'log');
381
+ helloWorld();
382
+ expect(spy).toHaveBeenCalledWith('Hello, World!');
383
+ });
384
+ });
385
+ `,
386
+ );
387
+ console.log(pc.green('āœ”') + ' test/main.test.ts');
388
+ } else {
389
+ console.log(pc.dim('–') + ' test/main.test.ts (already exists, skipped)');
390
+ }
391
+ }
392
+
393
+ /* ---------------- UPDATE package.json SCRIPTS ---------------- */
394
+
395
+ const pkg = await fs.readJson(pkgPath);
396
+
397
+ const checkParts = ['npm run format', 'npm run lint', 'npm run typecheck'];
398
+ if (lintOption.includes('cspell')) checkParts.push('npm run spellcheck');
399
+ if (lintOption.includes('secretlint')) checkParts.push('npm run secretlint');
400
+ if (vitestPreset === 'native' || vitestPreset === 'coverage') checkParts.push('npm run test');
401
+
402
+ pkg.scripts = {
403
+ ...pkg.scripts,
404
+ check: checkParts.join(' && '),
405
+ format: 'prettier . --write',
406
+ lint: 'eslint .',
407
+ typecheck: 'tsc --noEmit',
408
+ };
409
+
410
+ if (lintOption.includes('cspell')) pkg.scripts.spellcheck = 'cspell lint .';
411
+ if (lintOption.includes('secretlint')) pkg.scripts.secretlint = 'secretlint **/*';
412
+ if (setupPrecommit) pkg.scripts.prepare = 'husky';
413
+
414
+ if (vitestPreset === 'native' || vitestPreset === 'coverage') {
415
+ pkg.scripts.test = 'vitest --run';
416
+ pkg.scripts['test:unit'] = 'vitest unit --run';
417
+ pkg.scripts['test:integration'] = 'vitest int --run';
418
+ }
419
+ if (vitestPreset === 'coverage') {
420
+ pkg.scripts['test:coverage'] = 'vitest --coverage --run';
421
+ }
422
+
423
+ if (setupPrecommit) {
424
+ const lintStagedCmds = ['npm run format', 'npm run lint'];
425
+ if (lintOption.includes('cspell')) lintStagedCmds.push('npm run spellcheck');
426
+ if (lintOption.includes('secretlint')) lintStagedCmds.push('npm run secretlint');
427
+ pkg['lint-staged'] = { '**/*': lintStagedCmds };
428
+ }
429
+
430
+ // Set sensible defaults before writing
431
+ if (authorName && !pkg.author) pkg.author = authorName;
432
+ if (!pkg.license) pkg.license = 'MIT';
433
+ if (!pkg.keywords) pkg.keywords = [];
434
+ if (!pkg.main || pkg.main === 'index.js') pkg.main = 'src/main.ts';
435
+
436
+ // Rebuild scripts in preferred order
437
+ const scriptOrder = [
438
+ 'test',
439
+ 'check',
440
+ 'format',
441
+ 'lint',
442
+ 'typecheck',
443
+ 'spellcheck',
444
+ 'secretlint',
445
+ 'prepare',
446
+ 'test:unit',
447
+ 'test:integration',
448
+ 'test:coverage',
449
+ 'build',
450
+ 'dev',
451
+ 'start',
452
+ ];
453
+ const orderedScripts = {};
454
+ for (const key of scriptOrder) {
455
+ if (key in pkg.scripts) orderedScripts[key] = pkg.scripts[key];
456
+ }
457
+ for (const key of Object.keys(pkg.scripts)) {
458
+ if (!(key in orderedScripts)) orderedScripts[key] = pkg.scripts[key];
459
+ }
460
+ pkg.scripts = orderedScripts;
461
+
462
+ // Rebuild top-level keys in preferred order
463
+ const topLevelOrder = [
464
+ 'name',
465
+ 'description',
466
+ 'version',
467
+ 'author',
468
+ 'license',
469
+ 'keywords',
470
+ 'type',
471
+ 'main',
472
+ 'scripts',
473
+ 'devDependencies',
474
+ 'dependencies',
475
+ ];
476
+ const organized = {};
477
+ for (const key of topLevelOrder) {
478
+ if (key in pkg) organized[key] = pkg[key];
479
+ }
480
+ for (const key of Object.keys(pkg)) {
481
+ if (!topLevelOrder.includes(key) && key !== 'lint-staged') organized[key] = pkg[key];
482
+ }
483
+ if (pkg['lint-staged']) organized['lint-staged'] = pkg['lint-staged'];
484
+
485
+ await fs.writeJson(pkgPath, organized, { spaces: 2 });
486
+
487
+ const addedScripts = ['check', 'lint', 'format', 'typecheck'];
488
+ if (lintOption.includes('cspell')) addedScripts.push('spellcheck');
489
+ if (lintOption.includes('secretlint')) addedScripts.push('secretlint');
490
+ if (vitestPreset === 'native' || vitestPreset === 'coverage')
491
+ addedScripts.push('test', 'test:unit', 'test:integration');
492
+ if (vitestPreset === 'coverage') addedScripts.push('test:coverage');
493
+ console.log(pc.green('→') + ' scripts added in package.json:');
494
+ for (const script of addedScripts) {
495
+ console.log(pc.green('āœ”') + ` ${script}`);
496
+ }
497
+
498
+ console.log(pc.green('\nāœ… Done!\n'));
@@ -0,0 +1,14 @@
1
+ root = true
2
+
3
+ [*]
4
+ end_of_line = lf
5
+ insert_final_newline = true
6
+ indent_style = space
7
+ indent_size = 2
8
+ trim_trailing_whitespace = true
9
+
10
+ [*.md]
11
+ trim_trailing_whitespace = false
12
+
13
+ [Makefile]
14
+ indent_style = tab
@@ -0,0 +1,4 @@
1
+ dist
2
+ node_modules
3
+ package-lock.json
4
+ coverage
@@ -0,0 +1 @@
1
+ npx commitlint --edit
@@ -0,0 +1,3 @@
1
+ npx lint-staged
2
+ npm run typecheck
3
+ npm run test
@@ -0,0 +1,4 @@
1
+ dist
2
+ node_modules
3
+ package-lock.json
4
+ coverage
@@ -0,0 +1,8 @@
1
+ {
2
+ "ignorePatterns": ["**/.env"],
3
+ "rules": [
4
+ {
5
+ "id": "@secretlint/secretlint-rule-preset-recommend"
6
+ }
7
+ ]
8
+ }
@@ -0,0 +1,8 @@
1
+ node_modules
2
+ dist
3
+ coverage
4
+ .env
5
+ .env.local
6
+ .env*.local
7
+ *.log
8
+ npm-debug.log*
@@ -0,0 +1,69 @@
1
+ const Configuration = {
2
+ /*
3
+ * Resolve and load @commitlint/config-conventional from node_modules.
4
+ * Referenced packages must be installed
5
+ */
6
+ extends: ['@commitlint/config-conventional'],
7
+ plugins: ['commitlint-plugin-cspell'],
8
+
9
+ /*
10
+ * Any rules defined here will override rules from @commitlint/config-conventional
11
+ */
12
+ rules: {
13
+ 'cspell/type': [2, 'always'],
14
+ 'cspell/scope': [2, 'always'],
15
+ 'cspell/subject': [2, 'always'],
16
+ 'cspell/header': [2, 'always'],
17
+ 'cspell/body': [2, 'always'],
18
+ 'cspell/footer': [2, 'always'],
19
+ 'header-max-length': [2, 'always', 100],
20
+ 'body-max-line-length': [2, 'always', 250],
21
+ // This ensures that the scope is always present and follows the correct format.
22
+ 'scope-case': [2, 'always', ['lower-case', 'upper-case']],
23
+ // This ensures that the subject is not empty and starts with a lowercase letter.
24
+ 'subject-empty': [2, 'never'],
25
+ 'subject-case': [
26
+ 2,
27
+ 'never',
28
+ ['sentence-case', 'start-case', 'pascal-case', 'upper-case'],
29
+ ],
30
+ // This rule ensures that the type is one of the conventional commit types and is in lower-case.
31
+ 'type-case': [2, 'always', 'lower-case'],
32
+ 'type-empty': [2, 'never'],
33
+ 'type-enum': [
34
+ 2,
35
+ 'always',
36
+ [
37
+ 'feat', // New feature
38
+ 'fix', // Bug fix
39
+ 'docs', // Documentation only changes
40
+ 'style', // Changes that do not affect the meaning of the code (white-space, formatting, missing semi-colons, etc)
41
+ 'refactor', // A code change that neither fixes a bug nor adds a feature
42
+ 'perf', // A code change that improves performance
43
+ 'test', // Adding missing tests or correcting existing tests
44
+ 'build', // Changes that affect the build system or external dependencies (example scopes: gulp, broccoli, npm)
45
+ 'ci', // Changes to our CI configuration files and scripts (example scopes: Travis, Circle, BrowserStack, SauceLabs)
46
+ 'chore', // Other changes that don't modify src or test files
47
+ 'revert', // Reverts a previous commit
48
+ ],
49
+ ],
50
+ },
51
+ /*
52
+ * Custom URL to show upon failure
53
+ */
54
+ helpUrl:
55
+ 'https://github.com/conventional-changelog/commitlint/#what-is-commitlint',
56
+ /*
57
+ * Custom prompt configs
58
+ */
59
+ prompt: {
60
+ messages: {},
61
+ questions: {
62
+ type: {
63
+ description: 'please input type:',
64
+ },
65
+ },
66
+ },
67
+ };
68
+
69
+ export default Configuration;
@@ -0,0 +1,15 @@
1
+ {
2
+ "version": "0.2",
3
+ "language": "en",
4
+ "dictionaries": ["typescript", "node", "bash"],
5
+ "words": ["commitlint"],
6
+ "ignorePaths": [
7
+ "cspell.json",
8
+ "node_modules/**",
9
+ "coverage",
10
+ "package.json",
11
+ "package-lock.json",
12
+ "*ignore"
13
+ ],
14
+ "flagWords": ["hte"]
15
+ }