@neurodevs/ndx-cli 0.1.32 → 0.1.33
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/build/__tests__/modules/CliCommandRunner.test.d.ts +10 -2
- package/build/__tests__/modules/CliCommandRunner.test.js +73 -6
- package/build/__tests__/modules/CliCommandRunner.test.js.map +1 -1
- package/build/modules/CliCommandRunner.d.ts +2 -52
- package/build/modules/CliCommandRunner.js +18 -278
- package/build/modules/CliCommandRunner.js.map +1 -1
- package/build/modules/commands/CreateImplCommand.d.ts +17 -0
- package/build/modules/commands/CreateImplCommand.js +68 -0
- package/build/modules/commands/CreateImplCommand.js.map +1 -0
- package/build/modules/commands/CreatePackageCommand.d.ts +16 -0
- package/build/modules/commands/CreatePackageCommand.js +79 -0
- package/build/modules/commands/CreatePackageCommand.js.map +1 -0
- package/build/modules/commands/CreateUiCommand.d.ts +34 -0
- package/build/modules/commands/CreateUiCommand.js +185 -0
- package/build/modules/commands/CreateUiCommand.js.map +1 -0
- package/build/modules/commands/UpgradePackageCommand.d.ts +12 -0
- package/build/modules/commands/UpgradePackageCommand.js +50 -0
- package/build/modules/commands/UpgradePackageCommand.js.map +1 -0
- package/package.json +1 -1
- package/src/__tests__/modules/CliCommandRunner.test.ts +111 -7
- package/src/modules/CliCommandRunner.ts +18 -381
- package/src/modules/commands/CreateImplCommand.ts +81 -0
- package/src/modules/commands/CreatePackageCommand.ts +94 -0
- package/src/modules/commands/CreateUiCommand.ts +243 -0
- package/src/modules/commands/UpgradePackageCommand.ts +58 -0
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import os from 'os'
|
|
2
|
+
import path from 'path'
|
|
3
|
+
import { NpmAutopackage } from '@neurodevs/meta-node'
|
|
4
|
+
import CliCommandRunner from '../CliCommandRunner'
|
|
5
|
+
|
|
6
|
+
export default class CreatePackageCommand {
|
|
7
|
+
private packageName!: string
|
|
8
|
+
private description!: string
|
|
9
|
+
private keywords!: string[]
|
|
10
|
+
|
|
11
|
+
public constructor() {}
|
|
12
|
+
|
|
13
|
+
public async run() {
|
|
14
|
+
const { packageName, description, keywords } =
|
|
15
|
+
await this.promptForAutopackage()
|
|
16
|
+
|
|
17
|
+
this.packageName = packageName
|
|
18
|
+
this.description = description
|
|
19
|
+
this.keywords = keywords
|
|
20
|
+
|
|
21
|
+
if (!this.userInputExistsForCreatePackage) {
|
|
22
|
+
return
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const autopackage = this.NpmAutopackage()
|
|
26
|
+
await autopackage.run()
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
private async promptForAutopackage() {
|
|
30
|
+
return await this.prompts([
|
|
31
|
+
{
|
|
32
|
+
type: 'text',
|
|
33
|
+
name: 'packageName',
|
|
34
|
+
message: this.packageNameMessage,
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
type: 'text',
|
|
38
|
+
name: 'description',
|
|
39
|
+
message: this.descriptionMessage,
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
type: 'text',
|
|
43
|
+
name: 'keywords',
|
|
44
|
+
message: this.keywordsMessage,
|
|
45
|
+
initial: '',
|
|
46
|
+
format: (value) =>
|
|
47
|
+
value ? this.splitOnCommaOrWhitespace(value) : [],
|
|
48
|
+
},
|
|
49
|
+
])
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
private readonly packageNameMessage =
|
|
53
|
+
'What should the package be called? Example: useful-package'
|
|
54
|
+
|
|
55
|
+
private readonly descriptionMessage =
|
|
56
|
+
'What should the package description be? Example: A useful package.'
|
|
57
|
+
|
|
58
|
+
private readonly keywordsMessage =
|
|
59
|
+
'Enter keywords (comma or space separated, lowercase, optional):'
|
|
60
|
+
|
|
61
|
+
private splitOnCommaOrWhitespace(value: string) {
|
|
62
|
+
return value
|
|
63
|
+
.split(/[\s,]+/)
|
|
64
|
+
.map((v: string) => v.trim())
|
|
65
|
+
.filter(Boolean)
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
private get userInputExistsForCreatePackage() {
|
|
69
|
+
return this.packageName && this.description
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
private expandHomeDir(inputPath: string): string {
|
|
73
|
+
return inputPath.startsWith('~')
|
|
74
|
+
? path.join(os.homedir(), inputPath.slice(1))
|
|
75
|
+
: inputPath
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
private get prompts() {
|
|
79
|
+
return CliCommandRunner.prompts
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
private NpmAutopackage() {
|
|
83
|
+
return NpmAutopackage.Create({
|
|
84
|
+
name: this.packageName,
|
|
85
|
+
description: this.description,
|
|
86
|
+
keywords: ['nodejs', 'typescript', 'tdd', ...this.keywords],
|
|
87
|
+
gitNamespace: 'neurodevs',
|
|
88
|
+
npmNamespace: 'neurodevs',
|
|
89
|
+
installDir: this.expandHomeDir('~/dev'),
|
|
90
|
+
license: 'MIT',
|
|
91
|
+
author: 'Eric Yates <hello@ericthecurious.com>',
|
|
92
|
+
})
|
|
93
|
+
}
|
|
94
|
+
}
|
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
import { UiAutomodule } from '@neurodevs/meta-node'
|
|
2
|
+
import CliCommandRunner from '../CliCommandRunner'
|
|
3
|
+
|
|
4
|
+
export default class CreateUiCommand {
|
|
5
|
+
private componentName!: string
|
|
6
|
+
|
|
7
|
+
public constructor() {}
|
|
8
|
+
|
|
9
|
+
public async run() {
|
|
10
|
+
await this.installDependenciesIfNeeded()
|
|
11
|
+
|
|
12
|
+
const { componentName } = await this.promptForUimodule()
|
|
13
|
+
|
|
14
|
+
this.componentName = componentName
|
|
15
|
+
|
|
16
|
+
if (!this.componentName) {
|
|
17
|
+
return
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
await this.makeRequiredUiDirectories()
|
|
21
|
+
|
|
22
|
+
const instance = this.UiAutomodule()
|
|
23
|
+
await instance.run()
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
private async installDependenciesIfNeeded() {
|
|
27
|
+
const isInstalled = await this.checkIfDependenciesAreInstalled()
|
|
28
|
+
|
|
29
|
+
if (!isInstalled) {
|
|
30
|
+
const { shouldInstall } = await this.promptForInstallDependencies()
|
|
31
|
+
|
|
32
|
+
if (shouldInstall) {
|
|
33
|
+
await this.installReactDependencies()
|
|
34
|
+
await this.updateTsconfigForReact()
|
|
35
|
+
await this.createSetupTestsFile()
|
|
36
|
+
await this.addSetupTestsToPackageJson()
|
|
37
|
+
await this.recompileForTsxFiles()
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
private async checkIfDependenciesAreInstalled() {
|
|
43
|
+
const original = await this.loadPackageJson()
|
|
44
|
+
const parsed = JSON.parse(original)
|
|
45
|
+
|
|
46
|
+
const dependencies = Object.keys(parsed.dependencies ?? {})
|
|
47
|
+
|
|
48
|
+
const areDepsInstalled = this.requiredDependencies.every((dep) =>
|
|
49
|
+
dependencies.includes(dep)
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
const devDependencies = Object.keys(parsed.devDependencies ?? {})
|
|
53
|
+
|
|
54
|
+
const areDevDepsInstalled = this.requiredDevDependencies.every((dep) =>
|
|
55
|
+
devDependencies.includes(dep)
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
return areDepsInstalled && areDevDepsInstalled
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
private async loadPackageJson() {
|
|
62
|
+
return await this.readFile(this.packageJsonPath, 'utf-8')
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
private readonly packageJsonPath = 'package.json'
|
|
66
|
+
|
|
67
|
+
private readonly requiredDependencies = ['react', 'react-dom']
|
|
68
|
+
|
|
69
|
+
private readonly requiredDevDependencies = [
|
|
70
|
+
'@types/react',
|
|
71
|
+
'@types/react-dom',
|
|
72
|
+
'@types/jsdom',
|
|
73
|
+
'@testing-library/react',
|
|
74
|
+
'@testing-library/dom',
|
|
75
|
+
'@testing-library/jest-dom',
|
|
76
|
+
'jsdom',
|
|
77
|
+
]
|
|
78
|
+
|
|
79
|
+
private async promptForInstallDependencies() {
|
|
80
|
+
return await this.prompts([
|
|
81
|
+
{
|
|
82
|
+
type: 'confirm',
|
|
83
|
+
name: 'shouldInstall',
|
|
84
|
+
message:
|
|
85
|
+
'Some required dependencies are missing! Press Enter to install, or any other key to abort.',
|
|
86
|
+
initial: true,
|
|
87
|
+
},
|
|
88
|
+
])
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
private async installReactDependencies() {
|
|
92
|
+
await this.installDependencies()
|
|
93
|
+
await this.installDevDependencies()
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
private async installDependencies() {
|
|
97
|
+
console.log('Installing required dependencies...')
|
|
98
|
+
await this.exec('yarn add react react-dom')
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
private async installDevDependencies() {
|
|
102
|
+
console.log('Installing required dev dependencies...')
|
|
103
|
+
await this.exec(
|
|
104
|
+
'yarn add -D @types/react @types/react-dom @types/jsdom @testing-library/react @testing-library/dom @testing-library/jest-dom jsdom'
|
|
105
|
+
)
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
private async updateTsconfigForReact() {
|
|
109
|
+
console.log('Updating tsconfig.json for React...')
|
|
110
|
+
|
|
111
|
+
const original = await this.loadTsconfig()
|
|
112
|
+
const parsed = JSON.parse(original)
|
|
113
|
+
|
|
114
|
+
const updated = JSON.stringify(
|
|
115
|
+
{
|
|
116
|
+
...parsed,
|
|
117
|
+
compilerOptions: {
|
|
118
|
+
jsx: 'react-jsx',
|
|
119
|
+
...parsed.compilerOptions,
|
|
120
|
+
},
|
|
121
|
+
include: ['src'],
|
|
122
|
+
},
|
|
123
|
+
null,
|
|
124
|
+
4
|
|
125
|
+
)
|
|
126
|
+
|
|
127
|
+
await this.writeFile(this.tsconfigPath, updated)
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
private async loadTsconfig() {
|
|
131
|
+
return await this.readFile(this.tsconfigPath, 'utf-8')
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
private readonly tsconfigPath = 'tsconfig.json'
|
|
135
|
+
|
|
136
|
+
private async createSetupTestsFile() {
|
|
137
|
+
console.log('Creating src/setupTests.ts...')
|
|
138
|
+
await this.writeFile('src/__tests__/setupTests.ts', this.setupTestsFile)
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
private async addSetupTestsToPackageJson() {
|
|
142
|
+
console.log('Adding setupTests.ts to package.json...')
|
|
143
|
+
|
|
144
|
+
const original = await this.loadPackageJson()
|
|
145
|
+
const parsed = JSON.parse(original)
|
|
146
|
+
|
|
147
|
+
const updated = JSON.stringify(
|
|
148
|
+
{
|
|
149
|
+
...parsed,
|
|
150
|
+
jest: {
|
|
151
|
+
...parsed.jest,
|
|
152
|
+
setupFiles: ['<rootDir>/build/__tests__/setupTests.js'],
|
|
153
|
+
},
|
|
154
|
+
},
|
|
155
|
+
null,
|
|
156
|
+
4
|
|
157
|
+
)
|
|
158
|
+
|
|
159
|
+
await this.writeFile(this.packageJsonPath, updated)
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
private async recompileForTsxFiles() {
|
|
163
|
+
console.log('Recompiling project for .tsx files...')
|
|
164
|
+
await this.exec('npx tsc')
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
private async promptForUimodule() {
|
|
168
|
+
return await this.prompts([
|
|
169
|
+
{
|
|
170
|
+
type: 'text',
|
|
171
|
+
name: 'componentName',
|
|
172
|
+
message: this.componentNameMessage,
|
|
173
|
+
},
|
|
174
|
+
])
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
private readonly componentNameMessage =
|
|
178
|
+
'What should the component be called? Example: YourComponent'
|
|
179
|
+
|
|
180
|
+
private async makeRequiredUiDirectories() {
|
|
181
|
+
await this.mkdir(this.uiTestSaveDir, { recursive: true })
|
|
182
|
+
await this.mkdir(this.uiModuleSaveDir, { recursive: true })
|
|
183
|
+
await this.mkdir(this.uiFakeSaveDir, { recursive: true })
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
private readonly uiTestSaveDir = 'src/__tests__/ui'
|
|
187
|
+
private readonly uiModuleSaveDir = 'src/ui'
|
|
188
|
+
|
|
189
|
+
private get uiFakeSaveDir() {
|
|
190
|
+
return `src/testDoubles/${this.componentName}`
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
private get exec() {
|
|
194
|
+
return CliCommandRunner.exec
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
private get mkdir() {
|
|
198
|
+
return CliCommandRunner.mkdir
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
private get prompts() {
|
|
202
|
+
return CliCommandRunner.prompts
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
private get readFile() {
|
|
206
|
+
return CliCommandRunner.readFile
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
private get writeFile() {
|
|
210
|
+
return CliCommandRunner.writeFile
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
private readonly setupTestsFile = `
|
|
214
|
+
import { JSDOM } from 'jsdom'
|
|
215
|
+
|
|
216
|
+
const jsdom = new JSDOM('<!doctype html><html><body></body></html>', {
|
|
217
|
+
url: 'http://localhost',
|
|
218
|
+
})
|
|
219
|
+
|
|
220
|
+
global.window = jsdom.window as unknown as Window & typeof globalThis
|
|
221
|
+
global.document = jsdom.window.document
|
|
222
|
+
global.navigator = jsdom.window.navigator
|
|
223
|
+
global.HTMLElement = jsdom.window.HTMLElement
|
|
224
|
+
global.getComputedStyle = jsdom.window.getComputedStyle
|
|
225
|
+
|
|
226
|
+
global.ResizeObserver = class {
|
|
227
|
+
public observe() {}
|
|
228
|
+
public unobserve() {}
|
|
229
|
+
public disconnect() {}
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
global.SVGElement = jsdom.window.SVGElement
|
|
233
|
+
`
|
|
234
|
+
|
|
235
|
+
private UiAutomodule() {
|
|
236
|
+
return UiAutomodule.Create({
|
|
237
|
+
testSaveDir: this.uiTestSaveDir,
|
|
238
|
+
moduleSaveDir: this.uiModuleSaveDir,
|
|
239
|
+
fakeSaveDir: this.uiFakeSaveDir,
|
|
240
|
+
componentName: this.componentName,
|
|
241
|
+
})
|
|
242
|
+
}
|
|
243
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import os from 'os'
|
|
2
|
+
import path from 'path'
|
|
3
|
+
import { NpmAutopackage } from '@neurodevs/meta-node'
|
|
4
|
+
import CliCommandRunner from '../CliCommandRunner'
|
|
5
|
+
|
|
6
|
+
export default class UpgradePackageCommand {
|
|
7
|
+
private packageName!: string
|
|
8
|
+
private description!: string
|
|
9
|
+
private keywords!: string[]
|
|
10
|
+
|
|
11
|
+
public constructor() {}
|
|
12
|
+
|
|
13
|
+
public async run() {
|
|
14
|
+
await this.loadInfoFromPackageJson()
|
|
15
|
+
|
|
16
|
+
const autopackage = this.NpmAutopackage()
|
|
17
|
+
await autopackage.run()
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
private async loadInfoFromPackageJson() {
|
|
21
|
+
const raw = await this.readFile('package.json', 'utf-8')
|
|
22
|
+
const { name, description, keywords } = JSON.parse(raw)
|
|
23
|
+
|
|
24
|
+
this.packageName = name
|
|
25
|
+
this.description = description
|
|
26
|
+
|
|
27
|
+
this.keywords = this.defaultKeywords.every((keyword) =>
|
|
28
|
+
keywords?.includes(keyword)
|
|
29
|
+
)
|
|
30
|
+
? keywords
|
|
31
|
+
: [...this.defaultKeywords, ...(keywords || [])]
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
private readonly defaultKeywords = ['nodejs', 'typescript', 'tdd']
|
|
35
|
+
|
|
36
|
+
private expandHomeDir(inputPath: string): string {
|
|
37
|
+
return inputPath.startsWith('~')
|
|
38
|
+
? path.join(os.homedir(), inputPath.slice(1))
|
|
39
|
+
: inputPath
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
private get readFile() {
|
|
43
|
+
return CliCommandRunner.readFile
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
private NpmAutopackage() {
|
|
47
|
+
return NpmAutopackage.Create({
|
|
48
|
+
name: this.packageName,
|
|
49
|
+
description: this.description,
|
|
50
|
+
keywords: this.keywords,
|
|
51
|
+
gitNamespace: 'neurodevs',
|
|
52
|
+
npmNamespace: 'neurodevs',
|
|
53
|
+
installDir: this.expandHomeDir('~/dev'),
|
|
54
|
+
license: 'MIT',
|
|
55
|
+
author: 'Eric Yates <hello@ericthecurious.com>',
|
|
56
|
+
})
|
|
57
|
+
}
|
|
58
|
+
}
|