@neurodevs/meta-node 0.19.11 → 0.19.13

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.
@@ -1,7 +1,6 @@
1
1
  import { exec as execSync } from 'child_process'
2
2
  import { mkdir, readFile, writeFile } from 'fs/promises'
3
3
  import path from 'path'
4
- import { chdir } from 'process'
5
4
  import { promisify } from 'util'
6
5
  import { pathExists } from 'fs-extra'
7
6
  import { parse } from 'jsonc-parser'
@@ -10,7 +9,6 @@ import GitAutocommit from './GitAutocommit.js'
10
9
 
11
10
  export default class NpmAutopackage implements Autopackage {
12
11
  public static Class?: AutopackageConstructor
13
- public static chdir = chdir
14
12
  public static exec = promisify(execSync)
15
13
  public static fetch = fetch
16
14
  public static mkdir = mkdir
@@ -18,8 +16,6 @@ export default class NpmAutopackage implements Autopackage {
18
16
  public static readFile = readFile
19
17
  public static writeFile = writeFile
20
18
 
21
- private installDir: string
22
- private packageName: string
23
19
  private description: string
24
20
  private gitNamespace: string
25
21
  private npmNamespace?: string
@@ -28,7 +24,9 @@ export default class NpmAutopackage implements Autopackage {
28
24
  private author?: string
29
25
 
30
26
  private originalPackageJson!: Record<string, unknown>
31
- private originalGitignoreFile!: string
27
+ private originalGitignore!: string
28
+
29
+ private originalTsconfig!: TsConfig
32
30
  private metaNodeVersion!: string
33
31
 
34
32
  private originalTasksJson!: {
@@ -39,6 +37,35 @@ export default class NpmAutopackage implements Autopackage {
39
37
 
40
38
  private shouldOpenVscode = false
41
39
 
40
+ private readonly installDir: string
41
+ private readonly packageName: string
42
+ private readonly packageDir: string
43
+ private readonly packageJsonPath: string
44
+ private readonly gitignorePath: string
45
+ private readonly tsconfigPath: string
46
+ private readonly tasksJsonPath: string
47
+ private readonly testDirPath: string
48
+ private readonly abstractTestPath: string
49
+
50
+ private readonly abstractPackageTestFile = `import AbstractModuleTest from '@neurodevs/node-tdd'
51
+
52
+ export default abstract class AbstractPackageTest extends AbstractModuleTest {
53
+ protected static async beforeEach() {
54
+ await super.beforeEach()
55
+ }
56
+ }
57
+ `
58
+
59
+ private readonly eslintConfigFile = `import esConfigNdx from './src/eslint.config.js'
60
+
61
+ export default esConfigNdx
62
+ `
63
+
64
+ private readonly prettierConfigFile = `import prettierConfigNdx from '@neurodevs/prettier-config-ndx'
65
+
66
+ export default prettierConfigNdx
67
+ `
68
+
42
69
  protected constructor(options: AutopackageOptions) {
43
70
  const {
44
71
  installDir,
@@ -59,6 +86,18 @@ export default class NpmAutopackage implements Autopackage {
59
86
  this.keywords = keywords
60
87
  this.license = license
61
88
  this.author = author
89
+
90
+ this.packageDir = path.join(this.installDir, this.packageName)
91
+ this.packageJsonPath = path.join(this.packageDir, 'package.json')
92
+ this.gitignorePath = path.join(this.packageDir, '.gitignore')
93
+ this.tsconfigPath = path.join(this.packageDir, 'tsconfig.json')
94
+ this.tasksJsonPath = path.join(this.packageDir, '.vscode/tasks.json')
95
+ this.testDirPath = path.join(this.packageDir, 'src', '__tests__')
96
+
97
+ this.abstractTestPath = path.join(
98
+ this.testDirPath,
99
+ 'AbstractPackageTest.ts'
100
+ )
62
101
  }
63
102
 
64
103
  public static Create(options: AutopackageOptions) {
@@ -69,20 +108,19 @@ export default class NpmAutopackage implements Autopackage {
69
108
  this.throwIfGithubTokenNotInEnv()
70
109
 
71
110
  await this.createRepoInGithubOrg()
72
-
73
- this.chdirToInstallDir()
74
111
  await this.cloneGitRepo()
75
-
76
- this.chdirToPackageDir()
77
112
  await this.resetMainToOrigin()
78
113
  await this.setCurrentMetaNodeVersion()
79
114
  await this.spruceCreateModule()
80
115
  await this.updatePackageJson()
81
116
  await this.updateGitignore()
117
+ await this.updateTsconfig()
82
118
  await this.setupVscode()
83
119
  await this.updateVscodeTasks()
84
120
  await this.installDefaultDevDependencies()
85
121
  await this.installAbstractPackageTest()
122
+ await this.installEslintConfigFile()
123
+ await this.installPrettierConfigFile()
86
124
  await this.openVscode()
87
125
  }
88
126
 
@@ -141,16 +179,15 @@ export default class NpmAutopackage implements Autopackage {
141
179
  )
142
180
  }
143
181
 
144
- private chdirToInstallDir() {
145
- this.chdir(this.installDir)
146
- }
147
-
148
182
  private async cloneGitRepo() {
149
183
  const packageDirExists = await this.checkIfPackageDirExists()
150
184
 
151
185
  if (!packageDirExists) {
152
186
  console.log('Cloning git repository...')
153
- await this.exec(`git clone ${this.gitUrl}`)
187
+
188
+ await this.exec(`git clone ${this.gitUrl}`, {
189
+ cwd: this.installDir,
190
+ })
154
191
  this.shouldOpenVscode = true
155
192
  }
156
193
  }
@@ -159,21 +196,16 @@ export default class NpmAutopackage implements Autopackage {
159
196
  return this.pathExists(this.packageDir)
160
197
  }
161
198
 
162
- private get packageDir() {
163
- return this.packageName
164
- }
165
-
166
199
  private get gitUrl() {
167
200
  return `https://github.com/${this.gitNamespace}/${this.packageName}.git`
168
201
  }
169
202
 
170
203
  private async resetMainToOrigin() {
171
- await this.exec('git fetch origin')
172
- await this.exec('git reset --hard origin/main')
173
- }
204
+ await this.exec('git fetch origin', { cwd: this.packageDir })
174
205
 
175
- private chdirToPackageDir() {
176
- this.chdir(this.packageDir)
206
+ await this.exec('git reset --hard origin/main', {
207
+ cwd: this.packageDir,
208
+ })
177
209
  }
178
210
 
179
211
  private async setCurrentMetaNodeVersion() {
@@ -198,6 +230,7 @@ export default class NpmAutopackage implements Autopackage {
198
230
 
199
231
  if (!packageJsonExists) {
200
232
  console.log('Running spruce create.module...')
233
+
201
234
  await this.execSpruceCreateModule()
202
235
  await this.commitCreatePackage()
203
236
  }
@@ -207,11 +240,10 @@ export default class NpmAutopackage implements Autopackage {
207
240
  return this.pathExists(this.packageJsonPath)
208
241
  }
209
242
 
210
- private readonly packageJsonPath = 'package.json'
211
-
212
243
  private async execSpruceCreateModule() {
213
244
  await this.exec(
214
- `spruce create.module --name "${this.packageName}" --destination "." --description "${this.description}"`
245
+ `spruce create.module --name "${this.packageName}" --destination "." --description "${this.description}"`,
246
+ { cwd: this.packageDir }
215
247
  )
216
248
  }
217
249
 
@@ -222,16 +254,17 @@ export default class NpmAutopackage implements Autopackage {
222
254
  }
223
255
 
224
256
  private async updatePackageJson() {
225
- this.originalPackageJson = await this.loadPackageJsonFile()
257
+ this.originalPackageJson = await this.loadPackageJson()
226
258
 
227
259
  if (!this.isPackageUpToDate) {
228
260
  console.log('Updating package.json...')
261
+
229
262
  await this.updatePackageJsonFile()
230
263
  await this.commitUpdatePackageJson()
231
264
  }
232
265
  }
233
266
 
234
- private async loadPackageJsonFile() {
267
+ private async loadPackageJson() {
235
268
  const raw = await this.readFile(this.packageJsonPath, {
236
269
  encoding: 'utf-8',
237
270
  })
@@ -278,6 +311,7 @@ export default class NpmAutopackage implements Autopackage {
278
311
  ...this.originalPackageJson,
279
312
  name: this.scopedPackageName,
280
313
  description: this.description,
314
+ type: 'module',
281
315
  keywords: this.keywords ?? [],
282
316
  license: this.license,
283
317
  author: this.author,
@@ -327,7 +361,7 @@ export default class NpmAutopackage implements Autopackage {
327
361
  }
328
362
 
329
363
  private async updateGitignore() {
330
- this.originalGitignoreFile = await this.loadGitignoreFile()
364
+ this.originalGitignore = await this.loadGitignore()
331
365
 
332
366
  if (!this.isGitignoreUpdated) {
333
367
  console.log('Updating .gitignore...')
@@ -337,16 +371,14 @@ export default class NpmAutopackage implements Autopackage {
337
371
  }
338
372
  }
339
373
 
340
- private async loadGitignoreFile() {
374
+ private async loadGitignore() {
341
375
  return await this.readFile(this.gitignorePath, {
342
376
  encoding: 'utf-8',
343
377
  })
344
378
  }
345
379
 
346
- private readonly gitignorePath = '.gitignore'
347
-
348
380
  private get isGitignoreUpdated() {
349
- const lines = this.originalGitignoreFile
381
+ const lines = this.originalGitignore
350
382
  .split(/\r?\n/)
351
383
  .map((line) => line.trim())
352
384
 
@@ -366,22 +398,112 @@ export default class NpmAutopackage implements Autopackage {
366
398
  )
367
399
  }
368
400
 
401
+ private async updateTsconfig() {
402
+ this.originalTsconfig = await this.loadTsconfig()
403
+
404
+ if (!this.isTsconfigUpdated) {
405
+ console.log('Updating tsconfig...')
406
+ await this.updateTsconfigFile()
407
+ await this.commitUpdateTsconfig()
408
+ }
409
+ }
410
+
411
+ private async loadTsconfig() {
412
+ const raw = await this.readFile(this.tsconfigPath, {
413
+ encoding: 'utf-8',
414
+ })
415
+ return JSON.parse(raw)
416
+ }
417
+
418
+ private get isTsconfigUpdated() {
419
+ return (
420
+ JSON.stringify(this.originalTsconfig) ==
421
+ JSON.stringify(this.updatedTsconfig)
422
+ )
423
+ }
424
+
425
+ private async updateTsconfigFile() {
426
+ await this.writeFile(
427
+ this.tsconfigPath,
428
+ JSON.stringify(this.updatedTsconfig, null, 4) + '\n',
429
+ {
430
+ encoding: 'utf-8',
431
+ flag: 'a',
432
+ }
433
+ )
434
+ }
435
+
436
+ private get updatedTsconfig() {
437
+ return {
438
+ ...this.originalTsconfig,
439
+ compilerOptions: {
440
+ module: 'nodenext',
441
+ moduleResolution: 'nodenext',
442
+ target: 'ES2022',
443
+ lib: Array.from(
444
+ new Set([
445
+ ...(this.originalTsconfig?.compilerOptions?.lib ?? []),
446
+ 'ES2022',
447
+ ])
448
+ ),
449
+ types: Array.from(
450
+ new Set([
451
+ ...(this.originalTsconfig?.compilerOptions?.types ??
452
+ []),
453
+ 'node',
454
+ ])
455
+ ),
456
+ baseUrl: 'src',
457
+ outDir: 'build',
458
+ sourceMap: false,
459
+ strict: true,
460
+ noImplicitAny: true,
461
+ noImplicitReturns: true,
462
+ noUnusedLocals: true,
463
+ forceConsistentCasingInFileNames: true,
464
+ declaration: true,
465
+ skipLibCheck: true,
466
+ esModuleInterop: true,
467
+ moduleDetection: 'force',
468
+ allowJs: true,
469
+ resolveJsonModule: true,
470
+ experimentalDecorators: true,
471
+ },
472
+ include: Array.from(
473
+ new Set([
474
+ ...(this.originalTsconfig?.include ?? []),
475
+ './src/*.ts',
476
+ './src/**/*.ts',
477
+ ])
478
+ ),
479
+ }
480
+ }
481
+
482
+ private async commitUpdateTsconfig() {
483
+ await this.GitAutocommit(
484
+ `patch: update tsconfig (@neurodevs/meta-node: ${this.metaNodeVersion})`
485
+ )
486
+ }
487
+
369
488
  private async setupVscode() {
370
- const vscodeSettingsExist = await this.checkIfVscodeSettingsExist()
489
+ const vscodeTasksExist = await this.checkIfVscodeTasksExist()
371
490
 
372
- if (!vscodeSettingsExist) {
491
+ if (!vscodeTasksExist) {
373
492
  console.log('Setting up VSCode...')
493
+
374
494
  await this.spruceSetupVscode()
375
495
  await this.commitSetupVscode()
376
496
  }
377
497
  }
378
498
 
379
- private async checkIfVscodeSettingsExist() {
380
- return this.pathExists(`.vscode/settings.json`)
499
+ private async checkIfVscodeTasksExist() {
500
+ return this.pathExists(this.tasksJsonPath)
381
501
  }
382
502
 
383
503
  private async spruceSetupVscode() {
384
- await this.exec('spruce setup.vscode --all true')
504
+ await this.exec('spruce setup.vscode --all true', {
505
+ cwd: this.packageDir,
506
+ })
385
507
  }
386
508
 
387
509
  private async commitSetupVscode() {
@@ -430,8 +552,6 @@ export default class NpmAutopackage implements Autopackage {
430
552
  return parse(raw)
431
553
  }
432
554
 
433
- private readonly tasksJsonPath = '.vscode/tasks.json'
434
-
435
555
  private get updatedTasksJsonFile() {
436
556
  return JSON.stringify(
437
557
  {
@@ -483,14 +603,25 @@ export default class NpmAutopackage implements Autopackage {
483
603
  '@neurodevs/node-tdd'
484
604
  )
485
605
 
606
+ const eslintConfigNdxVersion = await this.getLatestVersion(
607
+ '@neurodevs/eslint-config-ndx'
608
+ )
609
+
610
+ const prettierConfigNdxVersion = await this.getLatestVersion(
611
+ '@neurodevs/prettier-config-ndx'
612
+ )
613
+
486
614
  if (
487
615
  this.currentGenerateIdVersion != generateIdVersion ||
488
- this.currentNodeTddVersion != nodeTddVersion
616
+ this.currentNodeTddVersion != nodeTddVersion ||
617
+ this.currentEslintConfigNdxVersion != eslintConfigNdxVersion ||
618
+ this.currentPrettierConfigNdxVersion != prettierConfigNdxVersion
489
619
  ) {
490
620
  console.log('Installing default devDependencies...')
491
621
 
492
622
  await this.exec(
493
- 'yarn add -D @neurodevs/generate-id@latest @neurodevs/node-tdd@latest'
623
+ 'yarn add -D @neurodevs/generate-id @neurodevs/node-tdd @neurodevs/eslint-config-ndx @neurodevs/prettier-config-ndx',
624
+ { cwd: this.packageDir }
494
625
  )
495
626
  await this.commitInstallDevDependencies()
496
627
  }
@@ -498,7 +629,8 @@ export default class NpmAutopackage implements Autopackage {
498
629
 
499
630
  private async getLatestVersion(scopedPackageName: string) {
500
631
  const { stdout } = await this.exec(
501
- `yarn info ${scopedPackageName} version --silent`
632
+ `yarn info ${scopedPackageName} version --silent`,
633
+ { cwd: this.packageDir }
502
634
  )
503
635
  return stdout.trim()
504
636
  }
@@ -519,6 +651,22 @@ export default class NpmAutopackage implements Autopackage {
519
651
  ).replace('^', '')
520
652
  }
521
653
 
654
+ private get currentEslintConfigNdxVersion() {
655
+ return (
656
+ (this.originalPackageJson.devDependencies as any)[
657
+ '@neurodevs/eslint-config-ndx'
658
+ ] || ''
659
+ ).replace('^', '')
660
+ }
661
+
662
+ private get currentPrettierConfigNdxVersion() {
663
+ return (
664
+ (this.originalPackageJson.devDependencies as any)[
665
+ '@neurodevs/prettier-config-ndx'
666
+ ] || ''
667
+ ).replace('^', '')
668
+ }
669
+
522
670
  private async commitInstallDevDependencies() {
523
671
  await this.GitAutocommit(
524
672
  `patch: install default devDependencies (@neurodevs/meta-node: ${this.metaNodeVersion})`
@@ -531,12 +679,14 @@ export default class NpmAutopackage implements Autopackage {
531
679
  if (!fileExists) {
532
680
  console.log(`Installing ${this.abstractTestPath}...`)
533
681
 
534
- await this.mkdir('src/__tests__', { recursive: true })
682
+ await this.mkdir(this.testDirPath, { recursive: true })
535
683
 
536
684
  await this.writeFile(
537
685
  this.abstractTestPath,
538
686
  this.abstractPackageTestFile,
539
- { encoding: 'utf-8' }
687
+ {
688
+ encoding: 'utf-8',
689
+ }
540
690
  )
541
691
 
542
692
  await this.commitInstallAbstractPackageTest()
@@ -550,31 +700,62 @@ export default class NpmAutopackage implements Autopackage {
550
700
  return doesTsExist || doesTsxExist
551
701
  }
552
702
 
553
- private readonly abstractTestPath = `src/__tests__/AbstractPackageTest.ts`
703
+ private async commitInstallAbstractPackageTest() {
704
+ await this.GitAutocommit(
705
+ `patch: install AbstractPackageTest (@neurodevs/meta-node: ${this.metaNodeVersion})`
706
+ )
707
+ }
554
708
 
555
- private readonly abstractPackageTestFile = `import AbstractModuleTest from '@neurodevs/node-tdd'
709
+ private async installEslintConfigFile() {
710
+ const eslintConfigPath = path.join(this.packageDir, 'eslint.config.js')
711
+ const fileExists = await this.pathExists(eslintConfigPath)
556
712
 
557
- export default abstract class AbstractPackageTest extends AbstractModuleTest {
558
- protected static async beforeEach() {
559
- await super.beforeEach()
713
+ if (!fileExists) {
714
+ console.log('Installing eslint.config.js...')
715
+
716
+ await this.writeFile(eslintConfigPath, this.eslintConfigFile, {
717
+ encoding: 'utf-8',
718
+ })
719
+
720
+ await this.commitInstallEslintConfigFile()
721
+ }
560
722
  }
561
- }
562
- `
563
723
 
564
- private async commitInstallAbstractPackageTest() {
724
+ private async commitInstallEslintConfigFile() {
565
725
  await this.GitAutocommit(
566
- `patch: install AbstractPackageTest (@neurodevs/meta-node: ${this.metaNodeVersion})`
726
+ `patch: install eslint.config.js (@neurodevs/meta-node: ${this.metaNodeVersion})`
567
727
  )
568
728
  }
569
729
 
570
- private async openVscode() {
571
- if (this.shouldOpenVscode) {
572
- await this.exec('code .')
730
+ private async installPrettierConfigFile() {
731
+ const prettierConfigPath = path.join(
732
+ this.packageDir,
733
+ 'prettier.config.js'
734
+ )
735
+
736
+ const fileExists = await this.pathExists(prettierConfigPath)
737
+
738
+ if (!fileExists) {
739
+ console.log('Installing prettier.config.js...')
740
+
741
+ await this.writeFile(prettierConfigPath, this.prettierConfigFile, {
742
+ encoding: 'utf-8',
743
+ })
744
+
745
+ await this.commitInstallPrettierConfigFile()
573
746
  }
574
747
  }
575
748
 
576
- private get chdir() {
577
- return NpmAutopackage.chdir
749
+ private async commitInstallPrettierConfigFile() {
750
+ await this.GitAutocommit(
751
+ `patch: install prettier.config.js (@neurodevs/meta-node: ${this.metaNodeVersion})`
752
+ )
753
+ }
754
+
755
+ private async openVscode() {
756
+ if (this.shouldOpenVscode) {
757
+ await this.exec('code .', { cwd: this.packageDir })
758
+ }
578
759
  }
579
760
 
580
761
  private get exec() {
@@ -602,7 +783,7 @@ export default abstract class AbstractPackageTest extends AbstractModuleTest {
602
783
  }
603
784
 
604
785
  private GitAutocommit(commitMessage: string) {
605
- return GitAutocommit.Create(commitMessage)
786
+ return GitAutocommit.Create(commitMessage, this.packageDir)
606
787
  }
607
788
  }
608
789
 
@@ -624,3 +805,13 @@ export interface AutopackageOptions {
624
805
  export type AutopackageConstructor = new (
625
806
  options: AutopackageOptions
626
807
  ) => Autopackage
808
+
809
+ export interface TsConfig {
810
+ compilerOptions?: {
811
+ lib?: string[]
812
+ types?: string[]
813
+ [key: string]: unknown
814
+ }
815
+ include?: string[]
816
+ [key: string]: unknown
817
+ }