@neurodevs/meta-node 0.1.0 → 0.3.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.
Files changed (29) hide show
  1. package/.vscode/tasks.json +18 -0
  2. package/build/__tests__/modules/NpmAutopackage.test.d.ts +47 -12
  3. package/build/__tests__/modules/NpmAutopackage.test.js +316 -34
  4. package/build/__tests__/modules/NpmAutopackage.test.js.map +1 -1
  5. package/build/index.d.ts +6 -2
  6. package/build/index.js +11 -5
  7. package/build/index.js.map +1 -1
  8. package/build/modules/NpmAutopackage.d.ts +52 -19
  9. package/build/modules/NpmAutopackage.js +223 -45
  10. package/build/modules/NpmAutopackage.js.map +1 -1
  11. package/build/scripts/runAutopackage.js +4 -2
  12. package/build/scripts/runAutopackage.js.map +1 -1
  13. package/build/testDoubles/Autopackage/FakeAutopackage.d.ts +8 -0
  14. package/build/testDoubles/Autopackage/FakeAutopackage.js +18 -0
  15. package/build/testDoubles/Autopackage/FakeAutopackage.js.map +1 -0
  16. package/package.json +5 -1
  17. package/src/__tests__/modules/NpmAutopackage.test.ts +417 -33
  18. package/src/index.ts +9 -3
  19. package/src/modules/NpmAutopackage.ts +277 -48
  20. package/src/scripts/runAutopackage.ts +4 -2
  21. package/src/testDoubles/Autopackage/FakeAutopackage.ts +19 -0
  22. package/build/__tests__/modules/PackageJsonUpdater.test.d.ts +0 -7
  23. package/build/__tests__/modules/PackageJsonUpdater.test.js +0 -63
  24. package/build/__tests__/modules/PackageJsonUpdater.test.js.map +0 -1
  25. package/build/modules/PackageJsonUpdater.d.ts +0 -8
  26. package/build/modules/PackageJsonUpdater.js +0 -10
  27. package/build/modules/PackageJsonUpdater.js.map +0 -1
  28. package/src/__tests__/modules/PackageJsonUpdater.test.ts +0 -23
  29. package/src/modules/PackageJsonUpdater.ts +0 -13
@@ -1,88 +1,311 @@
1
1
  import { execSync } from 'child_process'
2
+ import fs from 'fs'
2
3
 
3
4
  export default class NpmAutopackage implements Autopackage {
4
5
  public static Class?: AutopackageConstructor
5
6
  public static chdir = process.chdir
6
7
  public static execSync = execSync
8
+ public static existsSync = fs.existsSync
9
+ public static fetch = globalThis.fetch
10
+ public static readFileSync = fs.readFileSync
11
+ public static writeFileSync = fs.writeFileSync
7
12
 
8
13
  private packageName: string
9
14
  private packageDescription: string
10
15
  private gitNamespace: string
11
16
  private installDir: string
17
+ private keywords?: string[]
18
+ private license?: string
19
+ private author?: string
12
20
 
13
21
  protected constructor(options: AutopackageOptions) {
14
- const { name, description, gitNamespace, installDir } = options
22
+ const {
23
+ name,
24
+ description,
25
+ gitNamespace,
26
+ installDir,
27
+ license,
28
+ author,
29
+ keywords,
30
+ } = options
15
31
 
16
32
  this.packageName = name
17
33
  this.packageDescription = description
18
34
  this.gitNamespace = gitNamespace
19
35
  this.installDir = installDir
36
+ this.keywords = keywords
37
+ this.license = license
38
+ this.author = author
20
39
  }
21
40
 
22
41
  public static async Create(options: AutopackageOptions) {
23
- const instance = new (this.Class ?? this)(options)
24
- await instance.createPackage()
42
+ return new (this.Class ?? this)(options)
43
+ }
44
+
45
+ public async run() {
46
+ this.throwIfGithubTokenNotInEnv()
47
+
48
+ await this.createRepoInGithubOrg()
25
49
 
26
- return instance
50
+ this.chdirToInstallDir()
51
+ this.cloneGitRepo()
52
+ this.chdirToPackageDir()
53
+ this.spruceCreateModule()
54
+ this.updatePackage()
55
+ this.updateGitignore()
56
+ this.setupVscode()
27
57
  }
28
58
 
29
- public async createPackage() {
30
- this.execCreateModule()
31
- this.execGitSetup()
32
- this.execSetupVscode()
59
+ private throwIfGithubTokenNotInEnv() {
60
+ if (!this.githubToken) {
61
+ throw new Error('\n\nPlease set process.env.GITHUB_TOKEN!\n')
62
+ }
33
63
  }
34
64
 
35
- private execCreateModule() {
36
- this.chdirToInstallDir()
37
- this.exec(this.createModuleCmd)
65
+ private get githubToken() {
66
+ return process.env.GITHUB_TOKEN
38
67
  }
39
68
 
40
- private execGitSetup() {
41
- this.chdirToNewPackageDir()
69
+ private async createRepoInGithubOrg() {
70
+ await this.fetch(
71
+ `https://api.github.com/orgs/${this.gitNamespace}/repos`,
72
+ {
73
+ method: 'POST',
74
+ headers: {
75
+ Authorization: `token ${this.githubToken}`,
76
+ Accept: 'application/vnd.github+json',
77
+ 'Content-Type': 'application/json',
78
+ },
79
+ body: JSON.stringify({
80
+ name: this.packageName,
81
+ private: false,
82
+ description: this.packageDescription,
83
+ auto_init: true,
84
+ gitignore_template: 'Node',
85
+ license_template: 'mit',
86
+ }),
87
+ }
88
+ )
89
+ }
42
90
 
43
- this.gitInit()
44
- this.gitAdd()
45
- this.gitCommitCreateModule()
46
- this.gitRemoteAddOrigin()
91
+ private chdirToInstallDir() {
92
+ this.chdir(this.installDir)
47
93
  }
48
94
 
49
- private gitInit() {
50
- this.exec(this.initCmd)
95
+ private cloneGitRepo() {
96
+ if (!this.packageDirExists) {
97
+ this.exec(`git clone ${this.gitUrl}`)
98
+ }
51
99
  }
52
100
 
53
- private gitAdd() {
54
- this.exec(this.addCmd)
101
+ private get packageDirExists() {
102
+ return this.existsSync(this.packageDir)
55
103
  }
56
104
 
57
- private gitCommitCreateModule() {
58
- this.exec(this.commitCreateCmd)
105
+ private get packageDir() {
106
+ return `${this.installDir}/${this.packageName}`
59
107
  }
60
108
 
61
- private gitRemoteAddOrigin() {
62
- this.exec(this.addRemoteCmd)
109
+ private get gitUrl() {
110
+ return `https://github.com/${this.gitNamespace}/${this.packageName}.git`
63
111
  }
64
112
 
65
- private execSetupVscode() {
66
- this.exec(this.setupVscodeCmd)
113
+ private chdirToPackageDir() {
114
+ this.chdir(this.packageDir)
115
+ }
67
116
 
68
- this.gitAdd()
69
- this.gitCommitSetupVscode()
117
+ private spruceCreateModule() {
118
+ if (!this.packageJsonExists) {
119
+ this.execSpruceCreateModule()
120
+ this.commitCreatePackage()
121
+ }
70
122
  }
71
123
 
72
- private gitCommitSetupVscode() {
73
- this.exec(this.commitVscodeCmd)
124
+ private get packageJsonExists() {
125
+ return this.existsSync(this.packageJsonPath)
74
126
  }
75
127
 
76
- private chdirToInstallDir() {
77
- this.chdir(this.installDir)
128
+ private get packageJsonPath() {
129
+ return `${this.packageDir}/package.json`
78
130
  }
79
131
 
80
- private chdirToNewPackageDir() {
81
- this.chdir(this.packageDir)
132
+ private execSpruceCreateModule() {
133
+ this.exec(
134
+ `spruce create.module --name "${this.packageName}" --destination "${this.installDir}/${this.packageName}" --description "${this.packageDescription}"`
135
+ )
82
136
  }
83
137
 
84
- private get packageDir() {
85
- return `${this.installDir}/${this.packageName}`
138
+ private commitCreatePackage() {
139
+ this.gitAddAll()
140
+ this.gitCommitCreatePackage()
141
+ this.gitPush()
142
+ }
143
+
144
+ private gitAddAll() {
145
+ this.exec('git add .')
146
+ }
147
+
148
+ private gitCommitCreatePackage() {
149
+ this.exec('git commit -m "patch: create package"')
150
+ }
151
+
152
+ private gitPush() {
153
+ this.exec('git push')
154
+ }
155
+
156
+ private updatePackage() {
157
+ if (!this.packageUpdated) {
158
+ this.updatePackageJson()
159
+ this.commitUpdatePackage()
160
+ }
161
+ }
162
+
163
+ private get packageUpdated() {
164
+ return this.pkg.name === `@${this.scopedPackage}`
165
+ }
166
+
167
+ private get pkg() {
168
+ const raw = this.readFileSync(this.packageJsonPath, {
169
+ encoding: 'utf-8',
170
+ })
171
+ return JSON.parse(raw)
172
+ }
173
+
174
+ private updatePackageJson() {
175
+ const updated = { ...this.pkg, ...this.updatedJsonFile }
176
+ const ordered = this.orderJsonKeys(updated, [
177
+ 'name',
178
+ 'version',
179
+ 'description',
180
+ 'keywords',
181
+ 'license',
182
+ 'author',
183
+ 'homepage',
184
+ 'repository',
185
+ 'bugs',
186
+ 'main',
187
+ 'scripts',
188
+ 'dependencies',
189
+ 'devDependencies',
190
+ 'jest',
191
+ 'skill',
192
+ ])
193
+
194
+ this.writeFileSync(
195
+ this.packageJsonPath,
196
+ JSON.stringify(ordered, null, 2) + '\n',
197
+ { encoding: 'utf-8' }
198
+ )
199
+ }
200
+
201
+ private get updatedJsonFile() {
202
+ return {
203
+ name: `@${this.scopedPackage}`,
204
+ keywords: this.keywords ?? [],
205
+ license: this.license,
206
+ author: this.author,
207
+ main: 'build/index.js',
208
+ homepage: `https://github.com/${this.gitNamespace}/${this.packageName}`,
209
+ repository: {
210
+ type: 'git',
211
+ url: `git+https://github.com/${this.gitNamespace}/${this.packageName}.git`,
212
+ },
213
+ bugs: {
214
+ url: `https://github.com/${this.gitNamespace}/${this.packageName}/issues`,
215
+ },
216
+ dependencies: {},
217
+ }
218
+ }
219
+
220
+ private get scopedPackage() {
221
+ return `${this.gitNamespace}/${this.packageName}`
222
+ }
223
+
224
+ private orderJsonKeys(json: Record<string, unknown>, keyOrder: string[]) {
225
+ const ordered: Record<string, any> = {}
226
+
227
+ for (const key of keyOrder) {
228
+ if (key in json) {
229
+ ordered[key] = json[key]
230
+ }
231
+ }
232
+
233
+ const remainingKeys = Object.keys(json)
234
+ .filter((k) => !keyOrder.includes(k))
235
+ .sort()
236
+
237
+ for (const key of remainingKeys) {
238
+ ordered[key] = json[key]
239
+ }
240
+
241
+ return ordered
242
+ }
243
+
244
+ private commitUpdatePackage() {
245
+ this.gitAddAll()
246
+ this.gitCommitUpdatePackage()
247
+ this.gitPush()
248
+ }
249
+
250
+ private gitCommitUpdatePackage() {
251
+ this.exec('git commit -m "patch: update package"')
252
+ }
253
+
254
+ private updateGitignore() {
255
+ if (!this.gitignoreUpdated) {
256
+ this.writeFileSync(this.gitignorePath, '\nbuild/\n', {
257
+ encoding: 'utf-8',
258
+ flag: 'a',
259
+ })
260
+ this.commitUpdateGitignore()
261
+ }
262
+ }
263
+
264
+ private get gitignoreUpdated() {
265
+ const content = this.readFileSync(this.gitignorePath, {
266
+ encoding: 'utf-8',
267
+ })
268
+ const lines = content.split(/\r?\n/).map((line) => line.trim())
269
+ return lines.includes('build/')
270
+ }
271
+
272
+ private get gitignorePath() {
273
+ return `${this.packageDir}/.gitignore`
274
+ }
275
+
276
+ private commitUpdateGitignore() {
277
+ this.gitAddAll()
278
+ this.gitCommitUpdateGitignore()
279
+ this.gitPush()
280
+ }
281
+
282
+ private gitCommitUpdateGitignore() {
283
+ this.exec('git commit -m "patch: add build dir to gitignore"')
284
+ }
285
+
286
+ private setupVscode() {
287
+ if (!this.vscodeSettingsExists) {
288
+ this.spruceSetupVscode()
289
+ this.commitSetupVscode()
290
+ }
291
+ }
292
+
293
+ private get vscodeSettingsExists() {
294
+ return this.existsSync(`${this.packageDir}/.vscode/settings.json`)
295
+ }
296
+
297
+ private spruceSetupVscode() {
298
+ this.exec('spruce setup.vscode --all true')
299
+ }
300
+
301
+ private commitSetupVscode() {
302
+ this.gitAddAll()
303
+ this.gitCommitSetup()
304
+ this.gitPush()
305
+ }
306
+
307
+ private gitCommitSetup() {
308
+ this.exec('git commit -m "patch: setup vscode"')
86
309
  }
87
310
 
88
311
  private get chdir() {
@@ -93,24 +316,25 @@ export default class NpmAutopackage implements Autopackage {
93
316
  return NpmAutopackage.execSync
94
317
  }
95
318
 
96
- private get createModuleCmd() {
97
- return `spruce create.module --name "${this.packageName}" --destination "${this.installDir}/${this.packageName}" --description "${this.packageDescription}"`
319
+ private get existsSync() {
320
+ return NpmAutopackage.existsSync
98
321
  }
99
322
 
100
- private readonly initCmd = 'git init'
101
- private readonly addCmd = 'git add .'
102
- private readonly commitCreateCmd = 'git commit -m "patch: create module"'
323
+ private get fetch() {
324
+ return NpmAutopackage.fetch
325
+ }
103
326
 
104
- private get addRemoteCmd() {
105
- return `git remote add origin "https://github.com/${this.gitNamespace}/${this.packageName}.git"`
327
+ private get readFileSync() {
328
+ return NpmAutopackage.readFileSync
106
329
  }
107
330
 
108
- private readonly setupVscodeCmd = 'spruce setup.vscode --all true'
109
- private readonly commitVscodeCmd = 'git commit -m "patch: setup vscode"'
331
+ private get writeFileSync() {
332
+ return NpmAutopackage.writeFileSync
333
+ }
110
334
  }
111
335
 
112
336
  export interface Autopackage {
113
- createPackage(): Promise<void>
337
+ run(): Promise<void>
114
338
  }
115
339
 
116
340
  export interface AutopackageOptions {
@@ -119,6 +343,11 @@ export interface AutopackageOptions {
119
343
  gitNamespace: string
120
344
  npmNamespace: string
121
345
  installDir: string
346
+ keywords?: string[]
347
+ license?: string
348
+ author?: string
122
349
  }
123
350
 
124
- export type AutopackageConstructor = new () => Autopackage
351
+ export type AutopackageConstructor = new (
352
+ options: AutopackageOptions
353
+ ) => Autopackage
@@ -5,11 +5,13 @@ async function main() {
5
5
  console.log('Running autopackage...')
6
6
 
7
7
  await NpmAutopackage.Create({
8
- name: 'node-xyz',
9
- description: 'XYZ, yo',
8
+ name: 'node-osf',
9
+ description: 'Node.js client for the Open Science Framework (OSF) API',
10
10
  gitNamespace: 'neurodevs',
11
11
  npmNamespace: 'neurodevs',
12
12
  installDir: '/Users/ericthecurious/dev',
13
+ license: 'MIT',
14
+ author: 'Eric Yates <hello@ericthecurious.com>',
13
15
  })
14
16
 
15
17
  console.log('Opening in VSCode...')
@@ -0,0 +1,19 @@
1
+ import { Autopackage, AutopackageOptions } from '../../modules/NpmAutopackage'
2
+
3
+ export default class FakeAutopackage implements Autopackage {
4
+ public static callsToConstructor: AutopackageOptions[] = []
5
+ public static numCallsToCreatePackage = 0
6
+
7
+ public constructor(options: AutopackageOptions) {
8
+ FakeAutopackage.callsToConstructor.push(options)
9
+ }
10
+
11
+ public async run() {
12
+ FakeAutopackage.numCallsToCreatePackage++
13
+ }
14
+
15
+ public static resetTestDouble() {
16
+ this.callsToConstructor = []
17
+ this.numCallsToCreatePackage = 0
18
+ }
19
+ }
@@ -1,7 +0,0 @@
1
- import AbstractSpruceTest from '@sprucelabs/test-utils';
2
- export default class PackageJsonUpdaterTest extends AbstractSpruceTest {
3
- private static instance;
4
- protected static beforeEach(): Promise<void>;
5
- protected static createsInstance(): Promise<void>;
6
- private static PackageJsonUpdater;
7
- }
@@ -1,63 +0,0 @@
1
- "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
19
- var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
20
- if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
21
- else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
22
- return c > 3 && r && Object.defineProperty(target, key, r), r;
23
- };
24
- var __importStar = (this && this.__importStar) || (function () {
25
- var ownKeys = function(o) {
26
- ownKeys = Object.getOwnPropertyNames || function (o) {
27
- var ar = [];
28
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
29
- return ar;
30
- };
31
- return ownKeys(o);
32
- };
33
- return function (mod) {
34
- if (mod && mod.__esModule) return mod;
35
- var result = {};
36
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
37
- __setModuleDefault(result, mod);
38
- return result;
39
- };
40
- })();
41
- var __importDefault = (this && this.__importDefault) || function (mod) {
42
- return (mod && mod.__esModule) ? mod : { "default": mod };
43
- };
44
- Object.defineProperty(exports, "__esModule", { value: true });
45
- const test_utils_1 = __importStar(require("@sprucelabs/test-utils"));
46
- const PackageJsonUpdater_1 = __importDefault(require("../../modules/PackageJsonUpdater"));
47
- class PackageJsonUpdaterTest extends test_utils_1.default {
48
- static async beforeEach() {
49
- await super.beforeEach();
50
- this.instance = this.PackageJsonUpdater();
51
- }
52
- static async createsInstance() {
53
- test_utils_1.assert.isTruthy(this.instance, 'Failed to create instance!');
54
- }
55
- static PackageJsonUpdater() {
56
- return PackageJsonUpdater_1.default.Create();
57
- }
58
- }
59
- exports.default = PackageJsonUpdaterTest;
60
- __decorate([
61
- (0, test_utils_1.test)()
62
- ], PackageJsonUpdaterTest, "createsInstance", null);
63
- //# sourceMappingURL=PackageJsonUpdater.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"PackageJsonUpdater.test.js","sourceRoot":"","sources":["../../../src/__tests__/modules/PackageJsonUpdater.test.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,qEAAyE;AACzE,0FAEyC;AAEzC,MAAqB,sBAAuB,SAAQ,oBAAkB;IAGxD,MAAM,CAAC,KAAK,CAAC,UAAU;QAC7B,MAAM,KAAK,CAAC,UAAU,EAAE,CAAA;QAExB,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,kBAAkB,EAAE,CAAA;IAC7C,CAAC;IAGsB,AAAb,MAAM,CAAC,KAAK,CAAC,eAAe;QAClC,mBAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,QAAQ,EAAE,4BAA4B,CAAC,CAAA;IAChE,CAAC;IAEO,MAAM,CAAC,kBAAkB;QAC7B,OAAO,4BAAkB,CAAC,MAAM,EAAE,CAAA;IACtC,CAAC;CACJ;AAjBD,yCAiBC;AAP0B;IADtB,IAAA,iBAAI,GAAE;mDAGN"}
@@ -1,8 +0,0 @@
1
- export default class PackageJsonUpdater implements JsonUpdater {
2
- static Class?: JsonUpdateConstructor;
3
- protected constructor();
4
- static Create(): PackageJsonUpdater;
5
- }
6
- export interface JsonUpdater {
7
- }
8
- export type JsonUpdateConstructor = new () => JsonUpdater;
@@ -1,10 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- class PackageJsonUpdater {
4
- constructor() { }
5
- static Create() {
6
- return new (this.Class ?? this)();
7
- }
8
- }
9
- exports.default = PackageJsonUpdater;
10
- //# sourceMappingURL=PackageJsonUpdater.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"PackageJsonUpdater.js","sourceRoot":"","sources":["../../src/modules/PackageJsonUpdater.ts"],"names":[],"mappings":";;AAAA,MAAqB,kBAAkB;IAGnC,gBAAyB,CAAC;IAEnB,MAAM,CAAC,MAAM;QAChB,OAAO,IAAI,CAAC,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,EAAE,CAAA;IACrC,CAAC;CACJ;AARD,qCAQC"}
@@ -1,23 +0,0 @@
1
- import AbstractSpruceTest, { test, assert } from '@sprucelabs/test-utils'
2
- import PackageJsonUpdater, {
3
- JsonUpdater,
4
- } from '../../modules/PackageJsonUpdater'
5
-
6
- export default class PackageJsonUpdaterTest extends AbstractSpruceTest {
7
- private static instance: JsonUpdater
8
-
9
- protected static async beforeEach() {
10
- await super.beforeEach()
11
-
12
- this.instance = this.PackageJsonUpdater()
13
- }
14
-
15
- @test()
16
- protected static async createsInstance() {
17
- assert.isTruthy(this.instance, 'Failed to create instance!')
18
- }
19
-
20
- private static PackageJsonUpdater() {
21
- return PackageJsonUpdater.Create()
22
- }
23
- }
@@ -1,13 +0,0 @@
1
- export default class PackageJsonUpdater implements JsonUpdater {
2
- public static Class?: JsonUpdateConstructor
3
-
4
- protected constructor() {}
5
-
6
- public static Create() {
7
- return new (this.Class ?? this)()
8
- }
9
- }
10
-
11
- export interface JsonUpdater {}
12
-
13
- export type JsonUpdateConstructor = new () => JsonUpdater