@neurodevs/meta-node 0.0.1 → 0.2.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 (53) hide show
  1. package/.vscode/tasks.json +18 -0
  2. package/build/__tests__/modules/NodeAutomodule.test.d.ts +20 -0
  3. package/build/__tests__/modules/NodeAutomodule.test.js +166 -0
  4. package/build/__tests__/modules/NodeAutomodule.test.js.map +1 -0
  5. package/build/__tests__/modules/NpmAutopackage.test.d.ts +47 -12
  6. package/build/__tests__/modules/NpmAutopackage.test.js +314 -34
  7. package/build/__tests__/modules/NpmAutopackage.test.js.map +1 -1
  8. package/build/index.d.ts +12 -2
  9. package/build/index.js +23 -6
  10. package/build/index.js.map +1 -1
  11. package/build/modules/GitAutocloner.d.ts +5 -6
  12. package/build/modules/GitAutocloner.js +14 -17
  13. package/build/modules/GitAutocloner.js.map +1 -1
  14. package/build/modules/NodeAutomodule.d.ts +34 -0
  15. package/build/modules/NodeAutomodule.js +102 -0
  16. package/build/modules/NodeAutomodule.js.map +1 -0
  17. package/build/modules/NpmAutopackage.d.ts +49 -16
  18. package/build/modules/NpmAutopackage.js +221 -41
  19. package/build/modules/NpmAutopackage.js.map +1 -1
  20. package/build/modules/pathExists.d.ts +1 -0
  21. package/build/modules/pathExists.js +14 -0
  22. package/build/modules/pathExists.js.map +1 -0
  23. package/build/scripts/runAutomodule.d.ts +1 -0
  24. package/build/scripts/runAutomodule.js +22 -0
  25. package/build/scripts/runAutomodule.js.map +1 -0
  26. package/build/scripts/runAutopackage.js +7 -5
  27. package/build/scripts/runAutopackage.js.map +1 -1
  28. package/build/testDoubles/Automodule/FakeAutomodule.d.ts +8 -0
  29. package/build/testDoubles/Automodule/FakeAutomodule.js +18 -0
  30. package/build/testDoubles/Automodule/FakeAutomodule.js.map +1 -0
  31. package/build/testDoubles/Autopackage/FakeAutopackage.d.ts +8 -0
  32. package/build/testDoubles/Autopackage/FakeAutopackage.js +18 -0
  33. package/build/testDoubles/Autopackage/FakeAutopackage.js.map +1 -0
  34. package/build/testDoubles/fs/fakePathExists.d.ts +3 -0
  35. package/build/testDoubles/fs/fakePathExists.js +13 -0
  36. package/build/testDoubles/fs/fakePathExists.js.map +1 -0
  37. package/build/testDoubles/fs/fakeWriteFile.d.ts +6 -0
  38. package/build/testDoubles/fs/fakeWriteFile.js +13 -0
  39. package/build/testDoubles/fs/fakeWriteFile.js.map +1 -0
  40. package/package.json +5 -1
  41. package/src/__tests__/modules/NodeAutomodule.test.ts +160 -0
  42. package/src/__tests__/modules/NpmAutopackage.test.ts +415 -33
  43. package/src/index.ts +24 -5
  44. package/src/modules/GitAutocloner.ts +18 -22
  45. package/src/modules/NodeAutomodule.ts +136 -0
  46. package/src/modules/NpmAutopackage.ts +272 -42
  47. package/src/modules/pathExists.ts +10 -0
  48. package/src/scripts/runAutomodule.ts +22 -0
  49. package/src/scripts/runAutopackage.ts +7 -5
  50. package/src/testDoubles/Automodule/FakeAutomodule.ts +19 -0
  51. package/src/testDoubles/Autopackage/FakeAutopackage.ts +19 -0
  52. package/src/testDoubles/fs/fakePathExists.ts +9 -0
  53. package/src/testDoubles/fs/fakeWriteFile.ts +9 -0
@@ -0,0 +1,136 @@
1
+ import { writeFile } from 'fs/promises'
2
+ import path from 'path'
3
+ import pathExists from './pathExists'
4
+
5
+ export default class NodeAutomodule implements Automodule {
6
+ public static Class?: AutomoduleConstructor
7
+ public static pathExists = pathExists
8
+ public static writeFile = writeFile
9
+
10
+ private testSaveDir: string
11
+ private moduleSaveDir: string
12
+ private interfaceName: string
13
+ private implName: string
14
+
15
+ protected constructor(options: AutomoduleOptions) {
16
+ const { testSaveDir, moduleSaveDir, interfaceName, implName } = options
17
+
18
+ this.testSaveDir = testSaveDir
19
+ this.moduleSaveDir = moduleSaveDir
20
+ this.interfaceName = interfaceName
21
+ this.implName = implName
22
+ }
23
+
24
+ public static Create(options: AutomoduleOptions) {
25
+ return new (this.Class ?? this)(options)
26
+ }
27
+
28
+ public async run() {
29
+ await this.throwIfTestDirDoesNotExist()
30
+ await this.throwIfModuleDirDoesNotExist()
31
+
32
+ await this.createTestFile()
33
+ await this.createModuleFile()
34
+ }
35
+
36
+ private async throwIfTestDirDoesNotExist() {
37
+ const testDirExists = await this.pathExists(this.testSaveDir)
38
+
39
+ if (!testDirExists) {
40
+ throw new Error(`testSaveDir does not exist: ${this.testSaveDir}!`)
41
+ }
42
+ }
43
+
44
+ private async throwIfModuleDirDoesNotExist() {
45
+ const moduleDirExists = await this.pathExists(this.moduleSaveDir)
46
+
47
+ if (!moduleDirExists) {
48
+ throw new Error(
49
+ `moduleSaveDir does not exist: ${this.moduleSaveDir}!`
50
+ )
51
+ }
52
+ }
53
+
54
+ private async createTestFile() {
55
+ await this.writeFile(this.testFileName, this.testFilePattern)
56
+ }
57
+
58
+ private get testFileName() {
59
+ return path.join(this.testSaveDir, `${this.implName}.test.ts`)
60
+ }
61
+
62
+ private async createModuleFile() {
63
+ await this.writeFile(this.moduleFileName, this.moduleFilePattern)
64
+ }
65
+
66
+ private get moduleFileName() {
67
+ return path.join(this.moduleSaveDir, `${this.implName}.ts`)
68
+ }
69
+
70
+ private get pathExists() {
71
+ return NodeAutomodule.pathExists
72
+ }
73
+
74
+ private get writeFile() {
75
+ return NodeAutomodule.writeFile
76
+ }
77
+
78
+ private get testFilePattern() {
79
+ return `
80
+ import AbstractSpruceTest, { test, assert } from '@sprucelabs/test-utils'
81
+ import ${this.implName}, { ${this.interfaceName} } from '../../modules/${this.implName}'
82
+
83
+ export default class ${this.implName}Test extends AbstractSpruceTest {
84
+ private static instance: ${this.interfaceName}
85
+
86
+ protected static async beforeEach() {
87
+ await super.beforeEach()
88
+
89
+ this.instance = this.${this.implName}()
90
+ }
91
+
92
+ @test()
93
+ protected static async createsInstance() {
94
+ assert.isTruthy(this.instance, 'Failed to create instance!')
95
+ }
96
+
97
+ private static ${this.implName}() {
98
+ return ${this.implName}.Create()
99
+ }
100
+ }
101
+ `
102
+ }
103
+
104
+ private get moduleFilePattern() {
105
+ return `
106
+ export default class ${this.implName} implements ${this.interfaceName} {
107
+ public static Class?: ${this.interfaceName}Constructor
108
+
109
+ protected constructor() {}
110
+
111
+ public static Create() {
112
+ return new (this.Class ?? this)()
113
+ }
114
+ }
115
+
116
+ export interface ${this.interfaceName} {}
117
+
118
+ export type ${this.interfaceName}Constructor = new () => ${this.interfaceName}
119
+ `
120
+ }
121
+ }
122
+
123
+ export interface Automodule {
124
+ run(): Promise<void>
125
+ }
126
+
127
+ export type AutomoduleConstructor = new (
128
+ options: AutomoduleOptions
129
+ ) => Automodule
130
+
131
+ export interface AutomoduleOptions {
132
+ testSaveDir: string
133
+ moduleSaveDir: string
134
+ interfaceName: string
135
+ implName: string
136
+ }
@@ -1,22 +1,41 @@
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) {
@@ -27,62 +46,269 @@ export default class NpmAutopackage implements Autopackage {
27
46
  }
28
47
 
29
48
  public async createPackage() {
30
- this.execCreateModule()
31
- this.execGitSetup()
32
- this.execSetupVscode()
33
- }
49
+ this.throwIfGithubTokenNotInEnv()
50
+
51
+ await this.createRepoInGithubOrg()
34
52
 
35
- private execCreateModule() {
36
53
  this.chdirToInstallDir()
37
- this.exec(this.createModuleCmd)
54
+ this.cloneGitRepo()
55
+ this.chdirToPackageDir()
56
+ this.spruceCreateModule()
57
+ this.updatePackage()
58
+ this.updateGitignore()
59
+ this.setupVscode()
38
60
  }
39
61
 
40
- private execGitSetup() {
41
- this.chdirToNewPackageDir()
62
+ private throwIfGithubTokenNotInEnv() {
63
+ if (!this.githubToken) {
64
+ throw new Error('\n\nPlease set process.env.GITHUB_TOKEN!\n')
65
+ }
66
+ }
67
+
68
+ private get githubToken() {
69
+ return process.env.GITHUB_TOKEN
70
+ }
42
71
 
43
- this.gitInit()
44
- this.gitAdd()
45
- this.gitCommitCreateModule()
46
- this.gitRemoteAddOrigin()
72
+ private async createRepoInGithubOrg() {
73
+ await this.fetch(
74
+ `https://api.github.com/orgs/${this.gitNamespace}/repos`,
75
+ {
76
+ method: 'POST',
77
+ headers: {
78
+ Authorization: `token ${this.githubToken}`,
79
+ Accept: 'application/vnd.github+json',
80
+ 'Content-Type': 'application/json',
81
+ },
82
+ body: JSON.stringify({
83
+ name: this.packageName,
84
+ private: false,
85
+ description: this.packageDescription,
86
+ auto_init: true,
87
+ gitignore_template: 'Node',
88
+ license_template: 'mit',
89
+ }),
90
+ }
91
+ )
92
+ }
93
+
94
+ private chdirToInstallDir() {
95
+ this.chdir(this.installDir)
47
96
  }
48
97
 
49
- private gitInit() {
50
- this.exec(this.initCmd)
98
+ private cloneGitRepo() {
99
+ if (!this.packageDirExists) {
100
+ this.exec(`git clone ${this.gitUrl}`)
101
+ }
51
102
  }
52
103
 
53
- private gitAdd() {
54
- this.exec(this.addCmd)
104
+ private get packageDirExists() {
105
+ return this.existsSync(this.packageDir)
55
106
  }
56
107
 
57
- private gitCommitCreateModule() {
58
- this.exec(this.commitCreateCmd)
108
+ private get packageDir() {
109
+ return `${this.installDir}/${this.packageName}`
59
110
  }
60
111
 
61
- private gitRemoteAddOrigin() {
62
- this.exec(this.addRemoteCmd)
112
+ private get gitUrl() {
113
+ return `https://github.com/${this.gitNamespace}/${this.packageName}.git`
63
114
  }
64
115
 
65
- private execSetupVscode() {
66
- this.exec(this.setupVscodeCmd)
116
+ private chdirToPackageDir() {
117
+ this.chdir(this.packageDir)
118
+ }
67
119
 
68
- this.gitAdd()
69
- this.gitCommitSetupVscode()
120
+ private spruceCreateModule() {
121
+ if (!this.packageJsonExists) {
122
+ this.execSpruceCreateModule()
123
+ this.commitCreatePackage()
124
+ }
70
125
  }
71
126
 
72
- private gitCommitSetupVscode() {
73
- this.exec(this.commitVscodeCmd)
127
+ private get packageJsonExists() {
128
+ return this.existsSync(this.packageJsonPath)
74
129
  }
75
130
 
76
- private chdirToInstallDir() {
77
- this.chdir(this.installDir)
131
+ private get packageJsonPath() {
132
+ return `${this.packageDir}/package.json`
78
133
  }
79
134
 
80
- private chdirToNewPackageDir() {
81
- this.chdir(this.packageDir)
135
+ private execSpruceCreateModule() {
136
+ this.exec(
137
+ `spruce create.module --name "${this.packageName}" --destination "${this.installDir}/${this.packageName}" --description "${this.packageDescription}"`
138
+ )
82
139
  }
83
140
 
84
- private get packageDir() {
85
- return `${this.installDir}/${this.packageName}`
141
+ private commitCreatePackage() {
142
+ this.gitAddAll()
143
+ this.gitCommitCreatePackage()
144
+ this.gitPush()
145
+ }
146
+
147
+ private gitAddAll() {
148
+ this.exec('git add .')
149
+ }
150
+
151
+ private gitCommitCreatePackage() {
152
+ this.exec('git commit -m "patch: create package"')
153
+ }
154
+
155
+ private gitPush() {
156
+ this.exec('git push')
157
+ }
158
+
159
+ private updatePackage() {
160
+ if (!this.packageUpdated) {
161
+ this.updatePackageJson()
162
+ this.commitUpdatePackage()
163
+ }
164
+ }
165
+
166
+ private get packageUpdated() {
167
+ return this.pkg.name === `@${this.scopedPackage}`
168
+ }
169
+
170
+ private get pkg() {
171
+ const raw = this.readFileSync(this.packageJsonPath, {
172
+ encoding: 'utf-8',
173
+ })
174
+ return JSON.parse(raw)
175
+ }
176
+
177
+ private updatePackageJson() {
178
+ const updated = { ...this.pkg, ...this.updatedJsonFile }
179
+ const ordered = this.orderJsonKeys(updated, [
180
+ 'name',
181
+ 'version',
182
+ 'description',
183
+ 'keywords',
184
+ 'license',
185
+ 'author',
186
+ 'homepage',
187
+ 'repository',
188
+ 'bugs',
189
+ 'main',
190
+ 'scripts',
191
+ 'dependencies',
192
+ 'devDependencies',
193
+ 'jest',
194
+ 'skill',
195
+ ])
196
+
197
+ this.writeFileSync(
198
+ this.packageJsonPath,
199
+ JSON.stringify(ordered, null, 2) + '\n',
200
+ { encoding: 'utf-8' }
201
+ )
202
+ }
203
+
204
+ private get updatedJsonFile() {
205
+ return {
206
+ name: `@${this.scopedPackage}`,
207
+ keywords: this.keywords ?? [],
208
+ license: this.license,
209
+ author: this.author,
210
+ main: 'build/index.js',
211
+ homepage: `https://github.com/${this.gitNamespace}/${this.packageName}`,
212
+ repository: {
213
+ type: 'git',
214
+ url: `git+https://github.com/${this.gitNamespace}/${this.packageName}.git`,
215
+ },
216
+ bugs: {
217
+ url: `https://github.com/${this.gitNamespace}/${this.packageName}/issues`,
218
+ },
219
+ dependencies: {},
220
+ }
221
+ }
222
+
223
+ private get scopedPackage() {
224
+ return `${this.gitNamespace}/${this.packageName}`
225
+ }
226
+
227
+ private orderJsonKeys(json: Record<string, unknown>, keyOrder: string[]) {
228
+ const ordered: Record<string, any> = {}
229
+
230
+ for (const key of keyOrder) {
231
+ if (key in json) {
232
+ ordered[key] = json[key]
233
+ }
234
+ }
235
+
236
+ const remainingKeys = Object.keys(json)
237
+ .filter((k) => !keyOrder.includes(k))
238
+ .sort()
239
+
240
+ for (const key of remainingKeys) {
241
+ ordered[key] = json[key]
242
+ }
243
+
244
+ return ordered
245
+ }
246
+
247
+ private commitUpdatePackage() {
248
+ this.gitAddAll()
249
+ this.gitCommitUpdatePackage()
250
+ this.gitPush()
251
+ }
252
+
253
+ private gitCommitUpdatePackage() {
254
+ this.exec('git commit -m "patch: update package"')
255
+ }
256
+
257
+ private updateGitignore() {
258
+ if (!this.gitignoreUpdated) {
259
+ this.writeFileSync(this.gitignorePath, '\nbuild/\n', {
260
+ encoding: 'utf-8',
261
+ flag: 'a',
262
+ })
263
+ this.commitUpdateGitignore()
264
+ }
265
+ }
266
+
267
+ private get gitignoreUpdated() {
268
+ const content = this.readFileSync(this.gitignorePath, {
269
+ encoding: 'utf-8',
270
+ })
271
+ const lines = content.split(/\r?\n/).map((line) => line.trim())
272
+ return lines.includes('build/')
273
+ }
274
+
275
+ private get gitignorePath() {
276
+ return `${this.packageDir}/.gitignore`
277
+ }
278
+
279
+ private commitUpdateGitignore() {
280
+ this.gitAddAll()
281
+ this.gitCommitUpdateGitignore()
282
+ this.gitPush()
283
+ }
284
+
285
+ private gitCommitUpdateGitignore() {
286
+ this.exec('git commit -m "patch: add build dir to gitignore"')
287
+ }
288
+
289
+ private setupVscode() {
290
+ if (!this.vscodeSettingsExists) {
291
+ this.spruceSetupVscode()
292
+ this.commitSetupVscode()
293
+ }
294
+ }
295
+
296
+ private get vscodeSettingsExists() {
297
+ return this.existsSync(`${this.packageDir}/.vscode/settings.json`)
298
+ }
299
+
300
+ private spruceSetupVscode() {
301
+ this.exec('spruce setup.vscode --all true')
302
+ }
303
+
304
+ private commitSetupVscode() {
305
+ this.gitAddAll()
306
+ this.gitCommitSetup()
307
+ this.gitPush()
308
+ }
309
+
310
+ private gitCommitSetup() {
311
+ this.exec('git commit -m "patch: setup vscode"')
86
312
  }
87
313
 
88
314
  private get chdir() {
@@ -93,20 +319,21 @@ export default class NpmAutopackage implements Autopackage {
93
319
  return NpmAutopackage.execSync
94
320
  }
95
321
 
96
- private get createModuleCmd() {
97
- return `spruce create.module --name "${this.packageName}" --destination "${this.installDir}/${this.packageName}" --description "${this.packageDescription}"`
322
+ private get existsSync() {
323
+ return NpmAutopackage.existsSync
98
324
  }
99
325
 
100
- private readonly initCmd = 'git init'
101
- private readonly addCmd = 'git add .'
102
- private readonly commitCreateCmd = 'git commit -m "patch: create module"'
326
+ private get fetch() {
327
+ return NpmAutopackage.fetch
328
+ }
103
329
 
104
- private get addRemoteCmd() {
105
- return `git remote add origin "https://github.com/${this.gitNamespace}/${this.packageName}.git"`
330
+ private get readFileSync() {
331
+ return NpmAutopackage.readFileSync
106
332
  }
107
333
 
108
- private readonly setupVscodeCmd = 'spruce setup.vscode --all true'
109
- private readonly commitVscodeCmd = 'git commit -m "patch: setup vscode"'
334
+ private get writeFileSync() {
335
+ return NpmAutopackage.writeFileSync
336
+ }
110
337
  }
111
338
 
112
339
  export interface Autopackage {
@@ -119,6 +346,9 @@ export interface AutopackageOptions {
119
346
  gitNamespace: string
120
347
  npmNamespace: string
121
348
  installDir: string
349
+ keywords?: string[]
350
+ license?: string
351
+ author?: string
122
352
  }
123
353
 
124
354
  export type AutopackageConstructor = new () => Autopackage
@@ -0,0 +1,10 @@
1
+ import { access } from 'fs/promises'
2
+
3
+ export default async function pathExists(path: string) {
4
+ try {
5
+ await access(path)
6
+ return true
7
+ } catch {
8
+ return false
9
+ }
10
+ }
@@ -0,0 +1,22 @@
1
+ import NodeAutomodule from '../modules/NodeAutomodule'
2
+
3
+ async function main() {
4
+ console.log('\nRunning automodule...')
5
+
6
+ const instance = NodeAutomodule.Create({
7
+ testSaveDir:
8
+ '/Users/ericthecurious/dev/meta-node/src/__tests__/modules',
9
+ moduleSaveDir: '/Users/ericthecurious/dev/meta-node/src/modules',
10
+ interfaceName: 'Autocomponent',
11
+ implName: 'ReactAutocomponent',
12
+ })
13
+
14
+ await instance.run()
15
+
16
+ console.log('Finished running automodule!\n')
17
+ }
18
+
19
+ main().catch((err) => {
20
+ console.error(err)
21
+ process.exit(1)
22
+ })
@@ -1,15 +1,17 @@
1
1
  import { execSync } from 'child_process'
2
2
  import NpmAutopackage from '../modules/NpmAutopackage'
3
3
 
4
- async function run() {
5
- console.log('Running...')
4
+ async function main() {
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...')
@@ -19,7 +21,7 @@ async function run() {
19
21
  process.exit(0)
20
22
  }
21
23
 
22
- run().catch((err) => {
24
+ main().catch((err) => {
23
25
  console.error(err)
24
26
  process.exit(1)
25
27
  })
@@ -0,0 +1,19 @@
1
+ import { Automodule, AutomoduleOptions } from '../../modules/NodeAutomodule'
2
+
3
+ export default class FakeAutomodule implements Automodule {
4
+ public static callsToConstructor: AutomoduleOptions[] = []
5
+ public static numCallsToRun = 0
6
+
7
+ public constructor(options: AutomoduleOptions) {
8
+ FakeAutomodule.callsToConstructor.push(options)
9
+ }
10
+
11
+ public async run() {
12
+ FakeAutomodule.numCallsToRun++
13
+ }
14
+
15
+ public static resetTestDouble() {
16
+ this.callsToConstructor = []
17
+ this.numCallsToRun = 0
18
+ }
19
+ }
@@ -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 createPackage() {
12
+ FakeAutopackage.numCallsToCreatePackage++
13
+ }
14
+
15
+ public static resetTestDouble() {
16
+ this.callsToConstructor = []
17
+ this.numCallsToCreatePackage = 0
18
+ }
19
+ }
@@ -0,0 +1,9 @@
1
+ export let pathShouldExist: Record<string, boolean> = {}
2
+
3
+ export function setPathShouldExist(path: string, shouldExist: boolean) {
4
+ pathShouldExist[path] = shouldExist
5
+ }
6
+
7
+ export default async function fakePathExists(path: string) {
8
+ return pathShouldExist[path]
9
+ }
@@ -0,0 +1,9 @@
1
+ export let callsToWriteFile: { file: string; data: string }[] = []
2
+
3
+ export function resetCallsToWriteFile() {
4
+ callsToWriteFile = []
5
+ }
6
+
7
+ export default async function fakeWriteFile(file: string, data: string) {
8
+ callsToWriteFile.push({ file, data })
9
+ }