@neurodevs/meta-node 0.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.
Files changed (39) hide show
  1. package/.nvmrc +1 -0
  2. package/.vscode/launch.json +58 -0
  3. package/.vscode/settings.json +67 -0
  4. package/.vscode/tasks.json +112 -0
  5. package/LICENSE +21 -0
  6. package/README.md +2 -0
  7. package/build/.spruce/settings.json +11 -0
  8. package/build/__tests__/modules/GitAutocloner.test.d.ts +28 -0
  9. package/build/__tests__/modules/GitAutocloner.test.js +158 -0
  10. package/build/__tests__/modules/GitAutocloner.test.js.map +1 -0
  11. package/build/__tests__/modules/NpmAutopackage.test.d.ts +24 -0
  12. package/build/__tests__/modules/NpmAutopackage.test.js +136 -0
  13. package/build/__tests__/modules/NpmAutopackage.test.js.map +1 -0
  14. package/build/index.d.ts +6 -0
  15. package/build/index.js +32 -0
  16. package/build/index.js.map +1 -0
  17. package/build/modules/GitAutocloner.d.ts +38 -0
  18. package/build/modules/GitAutocloner.js +84 -0
  19. package/build/modules/GitAutocloner.js.map +1 -0
  20. package/build/modules/NpmAutopackage.d.ts +44 -0
  21. package/build/modules/NpmAutopackage.js +83 -0
  22. package/build/modules/NpmAutopackage.js.map +1 -0
  23. package/build/scripts/runAutopackage.d.ts +1 -0
  24. package/build/scripts/runAutopackage.js +26 -0
  25. package/build/scripts/runAutopackage.js.map +1 -0
  26. package/build/testDoubles/Autocloner/FakeAutocloner.d.ts +8 -0
  27. package/build/testDoubles/Autocloner/FakeAutocloner.js +18 -0
  28. package/build/testDoubles/Autocloner/FakeAutocloner.js.map +1 -0
  29. package/eslint.config.mjs +3 -0
  30. package/package.json +66 -0
  31. package/src/.spruce/settings.json +11 -0
  32. package/src/__tests__/modules/GitAutocloner.test.ts +149 -0
  33. package/src/__tests__/modules/NpmAutopackage.test.ts +124 -0
  34. package/src/index.ts +12 -0
  35. package/src/modules/GitAutocloner.ts +115 -0
  36. package/src/modules/NpmAutopackage.ts +124 -0
  37. package/src/scripts/runAutopackage.ts +25 -0
  38. package/src/testDoubles/Autocloner/FakeAutocloner.ts +19 -0
  39. package/tsconfig.json +39 -0
@@ -0,0 +1,124 @@
1
+ import AbstractSpruceTest, {
2
+ test,
3
+ assert,
4
+ generateId,
5
+ } from '@sprucelabs/test-utils'
6
+ import NpmAutopackage, {
7
+ Autopackage,
8
+ AutopackageOptions,
9
+ } from '../../modules/NpmAutopackage'
10
+
11
+ export default class NpmAutopackageTest extends AbstractSpruceTest {
12
+ private static instance: Autopackage
13
+
14
+ protected static async beforeEach() {
15
+ await super.beforeEach()
16
+
17
+ this.fakeExecToPreventActual()
18
+ this.fakeChdirToPreventActual()
19
+
20
+ this.instance = await this.NpmAutopackage()
21
+ }
22
+
23
+ @test()
24
+ protected static async createsNpmAutopackageInstance() {
25
+ assert.isTruthy(this.instance, 'Should create an instance!')
26
+ }
27
+
28
+ @test()
29
+ protected static async firstCallsChdirToInstallDir() {
30
+ assert.isEqual(
31
+ this.callsToChdir[0],
32
+ this.installDir,
33
+ 'Should have changed dir!'
34
+ )
35
+ }
36
+
37
+ @test()
38
+ protected static async thenCallsSpruceCreateModule() {
39
+ assert.isEqual(
40
+ this.callsToExecSync[0],
41
+ this.createModuleCmd,
42
+ 'Should have called "spruce create.module"!'
43
+ )
44
+ }
45
+
46
+ @test()
47
+ protected static async thenCallsChdirToNewlyCreatedDir() {
48
+ assert.isEqual(
49
+ this.callsToChdir[1],
50
+ `${this.installDir}/${this.packageName}`,
51
+ 'Should have changed dir!'
52
+ )
53
+ }
54
+
55
+ @test()
56
+ protected static async thenSetsUpNewGitRepo() {
57
+ assert.isEqualDeep(
58
+ this.callsToExecSync.slice(1, 5),
59
+ [
60
+ 'git init',
61
+ 'git add .',
62
+ 'git commit -m "patch: create module"',
63
+ `git remote add origin "https://github.com/${this.gitNamespace}/${this.packageName}.git"`,
64
+ ],
65
+ 'Should have called "git init"!'
66
+ )
67
+ }
68
+
69
+ @test()
70
+ protected static async thenCallsSpruceSetupVscode() {
71
+ assert.isEqual(
72
+ this.callsToExecSync[5],
73
+ 'spruce setup.vscode --all true',
74
+ 'Should have called "spruce setup.vscode"!'
75
+ )
76
+ }
77
+
78
+ @test()
79
+ protected static async thenGitCommitsVscodeChanges() {
80
+ assert.isEqualDeep(
81
+ this.callsToExecSync.slice(6, 8),
82
+ ['git add .', 'git commit -m "patch: setup vscode"'],
83
+ 'Should have committed vscode changes!'
84
+ )
85
+ }
86
+
87
+ private static fakeExecToPreventActual() {
88
+ // @ts-ignore
89
+ NpmAutopackage.execSync = (cmd: string) => {
90
+ this.callsToExecSync.push(cmd)
91
+ }
92
+ this.callsToExecSync = []
93
+ }
94
+
95
+ private static fakeChdirToPreventActual() {
96
+ NpmAutopackage.chdir = (dir: string) => {
97
+ this.callsToChdir.push(dir)
98
+ }
99
+ this.callsToChdir = []
100
+ }
101
+
102
+ private static callsToExecSync: string[] = []
103
+ private static callsToChdir: string[] = []
104
+
105
+ private static readonly packageName = generateId()
106
+ private static readonly packageDescription = generateId()
107
+ private static readonly gitNamespace = generateId()
108
+ private static readonly npmNamespace = generateId()
109
+ private static readonly installDir = generateId()
110
+
111
+ private static readonly createModuleCmd = `spruce create.module --name "${this.packageName}" --destination "${this.installDir}/${this.packageName}" --description "${this.packageDescription}"`
112
+
113
+ private static readonly defaultOptions = {
114
+ name: this.packageName,
115
+ description: this.packageDescription,
116
+ gitNamespace: this.gitNamespace,
117
+ npmNamespace: this.npmNamespace,
118
+ installDir: this.installDir,
119
+ }
120
+
121
+ private static NpmAutopackage(options?: Partial<AutopackageOptions>) {
122
+ return NpmAutopackage.Create({ ...this.defaultOptions, ...options })
123
+ }
124
+ }
package/src/index.ts ADDED
@@ -0,0 +1,12 @@
1
+ // Autopackage
2
+
3
+ export { default as NpmAutopackage } from './modules/NpmAutopackage'
4
+ export * from './modules/NpmAutopackage'
5
+
6
+ // Autocloner
7
+
8
+ export { default as GitAutocloner } from './modules/GitAutocloner'
9
+ export * from './modules/GitAutocloner'
10
+
11
+ export { default as FakeAutocloner } from './testDoubles/Autocloner/FakeAutocloner'
12
+ export * from './testDoubles/Autocloner/FakeAutocloner'
@@ -0,0 +1,115 @@
1
+ import { execSync } from 'child_process'
2
+ import { existsSync } from 'fs'
3
+ import { chdir } from 'process'
4
+
5
+ export default class GitAutocloner implements Autocloner {
6
+ public static Class?: AutoclonerConstructor
7
+ public static execSync = execSync
8
+ public static existsSync = existsSync
9
+
10
+ private urls!: string[]
11
+ private dirPath!: string
12
+ private currentUrl!: string
13
+ private currentError!: any
14
+ private log = console
15
+
16
+ protected constructor() {}
17
+
18
+ public static Create() {
19
+ return new (this.Class ?? this)()
20
+ }
21
+
22
+ public async run(options: AutoclonerOptions) {
23
+ const { urls, dirPath } = options
24
+
25
+ this.urls = urls
26
+ this.dirPath = dirPath
27
+
28
+ this.throwIfDirPathDoesNotExist()
29
+ this.changeDirectoryToDirPath()
30
+ this.cloneReposFromUrls()
31
+ }
32
+
33
+ private throwIfDirPathDoesNotExist() {
34
+ if (!this.dirPathExists) {
35
+ throw new Error(this.dirPathDoesNotExistMessage)
36
+ }
37
+ }
38
+
39
+ private get dirPathDoesNotExistMessage() {
40
+ return `dirPath does not exist: ${this.dirPath}!`
41
+ }
42
+
43
+ private changeDirectoryToDirPath() {
44
+ chdir(this.dirPath)
45
+ }
46
+
47
+ private cloneReposFromUrls() {
48
+ this.urls.forEach((url) => {
49
+ this.currentUrl = url
50
+ this.cloneCurrentUrl()
51
+ })
52
+ }
53
+
54
+ private cloneCurrentUrl() {
55
+ if (!this.currentRepoExists) {
56
+ this.tryToCloneRepo()
57
+ } else {
58
+ this.log.info(this.repoExistsMessage)
59
+ }
60
+ }
61
+
62
+ private tryToCloneRepo() {
63
+ try {
64
+ this.execSync(`git clone ${this.currentUrl}`)
65
+ } catch (err: any) {
66
+ this.currentError = err
67
+ this.throwGitCloneFailed()
68
+ }
69
+ }
70
+
71
+ private throwGitCloneFailed() {
72
+ throw new Error(this.gitCloneFailedMessage)
73
+ }
74
+
75
+ private get gitCloneFailedMessage() {
76
+ return `Git clone failed for repo: ${this.currentUrl}!\n\n${this.currentError}\n\n`
77
+ }
78
+
79
+ private get dirPathExists() {
80
+ return this.existsSync(this.dirPath)
81
+ }
82
+
83
+ private get currentRepoName() {
84
+ return this.currentUrl.match(this.regex)![1]
85
+ }
86
+
87
+ private get currentRepoExists() {
88
+ return this.existsSync(this.currentRepoName)
89
+ }
90
+
91
+ private get repoExistsMessage() {
92
+ return `Repo already exists, skipping: ${this.currentRepoName}!`
93
+ }
94
+
95
+ private get existsSync() {
96
+ return GitAutocloner.existsSync
97
+ }
98
+
99
+ private get execSync() {
100
+ return GitAutocloner.execSync
101
+ }
102
+
103
+ private readonly regex = /\/([a-zA-Z0-9_.-]+)\.git/
104
+ }
105
+
106
+ export interface Autocloner {
107
+ run(options: AutoclonerOptions): Promise<void>
108
+ }
109
+
110
+ export type AutoclonerConstructor = new () => Autocloner
111
+
112
+ export interface AutoclonerOptions {
113
+ urls: string[]
114
+ dirPath: string
115
+ }
@@ -0,0 +1,124 @@
1
+ import { execSync } from 'child_process'
2
+
3
+ export default class NpmAutopackage implements Autopackage {
4
+ public static Class?: AutopackageConstructor
5
+ public static chdir = process.chdir
6
+ public static execSync = execSync
7
+
8
+ private packageName: string
9
+ private packageDescription: string
10
+ private gitNamespace: string
11
+ private installDir: string
12
+
13
+ protected constructor(options: AutopackageOptions) {
14
+ const { name, description, gitNamespace, installDir } = options
15
+
16
+ this.packageName = name
17
+ this.packageDescription = description
18
+ this.gitNamespace = gitNamespace
19
+ this.installDir = installDir
20
+ }
21
+
22
+ public static async Create(options: AutopackageOptions) {
23
+ const instance = new (this.Class ?? this)(options)
24
+ await instance.createPackage()
25
+
26
+ return instance
27
+ }
28
+
29
+ public async createPackage() {
30
+ this.execCreateModule()
31
+ this.execGitSetup()
32
+ this.execSetupVscode()
33
+ }
34
+
35
+ private execCreateModule() {
36
+ this.chdirToInstallDir()
37
+ this.exec(this.createModuleCmd)
38
+ }
39
+
40
+ private execGitSetup() {
41
+ this.chdirToNewPackageDir()
42
+
43
+ this.gitInit()
44
+ this.gitAdd()
45
+ this.gitCommitCreateModule()
46
+ this.gitRemoteAddOrigin()
47
+ }
48
+
49
+ private gitInit() {
50
+ this.exec(this.initCmd)
51
+ }
52
+
53
+ private gitAdd() {
54
+ this.exec(this.addCmd)
55
+ }
56
+
57
+ private gitCommitCreateModule() {
58
+ this.exec(this.commitCreateCmd)
59
+ }
60
+
61
+ private gitRemoteAddOrigin() {
62
+ this.exec(this.addRemoteCmd)
63
+ }
64
+
65
+ private execSetupVscode() {
66
+ this.exec(this.setupVscodeCmd)
67
+
68
+ this.gitAdd()
69
+ this.gitCommitSetupVscode()
70
+ }
71
+
72
+ private gitCommitSetupVscode() {
73
+ this.exec(this.commitVscodeCmd)
74
+ }
75
+
76
+ private chdirToInstallDir() {
77
+ this.chdir(this.installDir)
78
+ }
79
+
80
+ private chdirToNewPackageDir() {
81
+ this.chdir(this.packageDir)
82
+ }
83
+
84
+ private get packageDir() {
85
+ return `${this.installDir}/${this.packageName}`
86
+ }
87
+
88
+ private get chdir() {
89
+ return NpmAutopackage.chdir
90
+ }
91
+
92
+ private get exec() {
93
+ return NpmAutopackage.execSync
94
+ }
95
+
96
+ private get createModuleCmd() {
97
+ return `spruce create.module --name "${this.packageName}" --destination "${this.installDir}/${this.packageName}" --description "${this.packageDescription}"`
98
+ }
99
+
100
+ private readonly initCmd = 'git init'
101
+ private readonly addCmd = 'git add .'
102
+ private readonly commitCreateCmd = 'git commit -m "patch: create module"'
103
+
104
+ private get addRemoteCmd() {
105
+ return `git remote add origin "https://github.com/${this.gitNamespace}/${this.packageName}.git"`
106
+ }
107
+
108
+ private readonly setupVscodeCmd = 'spruce setup.vscode --all true'
109
+ private readonly commitVscodeCmd = 'git commit -m "patch: setup vscode"'
110
+ }
111
+
112
+ export interface Autopackage {
113
+ createPackage(): Promise<void>
114
+ }
115
+
116
+ export interface AutopackageOptions {
117
+ name: string
118
+ description: string
119
+ gitNamespace: string
120
+ npmNamespace: string
121
+ installDir: string
122
+ }
123
+
124
+ export type AutopackageConstructor = new () => Autopackage
@@ -0,0 +1,25 @@
1
+ import { execSync } from 'child_process'
2
+ import NpmAutopackage from '../modules/NpmAutopackage'
3
+
4
+ async function run() {
5
+ console.log('Running...')
6
+
7
+ await NpmAutopackage.Create({
8
+ name: 'node-xyz',
9
+ description: 'XYZ, yo',
10
+ gitNamespace: 'neurodevs',
11
+ npmNamespace: 'neurodevs',
12
+ installDir: '/Users/ericthecurious/dev',
13
+ })
14
+
15
+ console.log('Opening in VSCode...')
16
+ execSync('code .')
17
+ console.log('Done!')
18
+
19
+ process.exit(0)
20
+ }
21
+
22
+ run().catch((err) => {
23
+ console.error(err)
24
+ process.exit(1)
25
+ })
@@ -0,0 +1,19 @@
1
+ import { Autocloner, AutoclonerOptions } from '../../modules/GitAutocloner'
2
+
3
+ export default class FakeGitAutocloner implements Autocloner {
4
+ public static numCallsToConstructor = 0
5
+ public static callsToRun: AutoclonerOptions[] = []
6
+
7
+ public constructor() {
8
+ FakeGitAutocloner.numCallsToConstructor++
9
+ }
10
+
11
+ public async run(options: AutoclonerOptions) {
12
+ FakeGitAutocloner.callsToRun.push(options)
13
+ }
14
+
15
+ public static resetTestDouble() {
16
+ FakeGitAutocloner.numCallsToConstructor = 0
17
+ FakeGitAutocloner.callsToRun = []
18
+ }
19
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,39 @@
1
+ {
2
+ "compilerOptions": {
3
+ "skipLibCheck": true,
4
+ "module": "commonjs",
5
+ "esModuleInterop": true,
6
+ "target": "ES2020",
7
+ "lib": [
8
+ "DOM",
9
+ "ES2022"
10
+ ],
11
+ "declaration": true,
12
+ "noImplicitAny": true,
13
+ "allowJs": true,
14
+ "forceConsistentCasingInFileNames": true,
15
+ "noImplicitReturns": true,
16
+ "strict": true,
17
+ "noUnusedLocals": true,
18
+ "resolveJsonModule": true,
19
+ "moduleResolution": "node",
20
+ "sourceMap": false,
21
+ "outDir": "build",
22
+ "baseUrl": "src",
23
+ "experimentalDecorators": true,
24
+ "paths": {
25
+ "#spruce/*": [
26
+ ".spruce/*"
27
+ ]
28
+ }
29
+ },
30
+ "include": [
31
+ "./src/*.ts",
32
+ "./src/**/*.ts",
33
+ "./src/.spruce/**/*"
34
+ ],
35
+ "exclude": [
36
+ "build",
37
+ "esm"
38
+ ]
39
+ }