@sprucelabs/spruce-cli 18.1.5 → 18.1.6
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/CHANGELOG.md +4 -0
- package/build/__tests__/behavioral/WatchingSkillViews.test.d.ts +1 -9
- package/build/__tests__/behavioral/WatchingSkillViews.test.js +25 -463
- package/build/__tests__/behavioral/WatchingSkillViews.test.js.map +1 -1
- package/build/features/AbstractAction.d.ts +1 -1
- package/build/features/AbstractAction.js +4 -4
- package/build/features/AbstractAction.js.map +1 -1
- package/build/features/dependencies/actions/AddAction.js +1 -1
- package/build/features/dependencies/actions/AddAction.js.map +1 -1
- package/build/features/deploy/actions/HerokuAction.js +2 -2
- package/build/features/deploy/actions/HerokuAction.js.map +1 -1
- package/build/features/node/actions/UpdateDependenciesAction.js +1 -1
- package/build/features/node/actions/UpdateDependenciesAction.js.map +1 -1
- package/build/features/node/actions/UpgradeAction.js +1 -1
- package/build/features/node/actions/UpgradeAction.js.map +1 -1
- package/build/features/test/actions/CreateAction.js +2 -2
- package/build/features/test/actions/CreateAction.js.map +1 -1
- package/build/features/view/actions/WatchAction.d.ts +3 -16
- package/build/features/view/actions/WatchAction.js +32 -165
- package/build/features/view/actions/WatchAction.js.map +1 -1
- package/build/services/CommandService.d.ts +6 -6
- package/build/services/CommandService.js.map +1 -1
- package/node_modules/@typescript-eslint/parser/package.json +5 -5
- package/node_modules/@typescript-eslint/scope-manager/package.json +5 -5
- package/node_modules/@typescript-eslint/types/package.json +2 -2
- package/node_modules/@typescript-eslint/typescript-estree/package.json +5 -5
- package/node_modules/@typescript-eslint/visitor-keys/package.json +3 -3
- package/package.json +3 -3
- package/src/__tests__/behavioral/WatchingSkillViews.test.ts +14 -227
- package/src/features/AbstractAction.ts +4 -4
- package/src/features/dependencies/actions/AddAction.ts +1 -1
- package/src/features/deploy/actions/HerokuAction.ts +2 -2
- package/src/features/node/actions/UpdateDependenciesAction.ts +1 -1
- package/src/features/node/actions/UpgradeAction.ts +1 -1
- package/src/features/test/actions/CreateAction.ts +2 -4
- package/src/features/view/actions/WatchAction.ts +25 -89
- package/src/services/CommandService.ts +7 -7
|
@@ -1,7 +1,4 @@
|
|
|
1
|
-
import { SettingsService } from '@sprucelabs/spruce-skill-utils'
|
|
2
1
|
import { test, assert } from '@sprucelabs/test-utils'
|
|
3
|
-
import ps from 'ps-node'
|
|
4
|
-
import BootAction from '../../features/skill/actions/BootAction'
|
|
5
2
|
import WatchAction from '../../features/view/actions/WatchAction'
|
|
6
3
|
import CommandService from '../../services/CommandService'
|
|
7
4
|
import AbstractSkillTest from '../../tests/AbstractSkillTest'
|
|
@@ -9,245 +6,35 @@ import AbstractSkillTest from '../../tests/AbstractSkillTest'
|
|
|
9
6
|
export default class WatchingSkillViewsTest extends AbstractSkillTest {
|
|
10
7
|
protected static skillCacheKey = 'views'
|
|
11
8
|
protected static oldBootExecute: any
|
|
12
|
-
|
|
13
|
-
protected static async beforeAll() {
|
|
14
|
-
await super.beforeAll()
|
|
15
|
-
this.oldBootExecute = BootAction.prototype.execute
|
|
16
|
-
}
|
|
9
|
+
private static action: WatchAction
|
|
17
10
|
|
|
18
11
|
protected static async beforeEach() {
|
|
19
12
|
await super.beforeEach()
|
|
20
|
-
this.
|
|
21
|
-
SettingsService.prototype.isMarkedAsInstalled = () => true
|
|
22
|
-
BootAction.prototype.execute = this.oldBootExecute
|
|
13
|
+
this.action = this.Action('view', 'watch')
|
|
23
14
|
}
|
|
24
15
|
|
|
25
16
|
@test()
|
|
26
17
|
protected static async hasWatchSkillViewsEvent() {
|
|
27
|
-
assert.isFunction(this.
|
|
18
|
+
assert.isFunction(this.action.execute)
|
|
28
19
|
}
|
|
29
20
|
|
|
30
21
|
@test()
|
|
31
22
|
protected static async shouldCallBoot() {
|
|
32
23
|
let wasHit = false
|
|
24
|
+
CommandService.fakeCommand(
|
|
25
|
+
'ENABLED_SKILL_FEATURES=view,event SHOULD_REGISTER_EVENTS_AND_LISTENERS=false SHOULD_WATCH_VIEWS=true MAXIMUM_LOG_PREFIXES_LENGTH=0 yarn boot',
|
|
26
|
+
{
|
|
27
|
+
code: 200,
|
|
28
|
+
callback: () => {
|
|
29
|
+
wasHit = true
|
|
30
|
+
},
|
|
31
|
+
}
|
|
32
|
+
)
|
|
33
33
|
|
|
34
|
-
|
|
35
|
-
code: 0,
|
|
36
|
-
callback: () => {
|
|
37
|
-
wasHit = true
|
|
38
|
-
},
|
|
39
|
-
})
|
|
40
|
-
|
|
41
|
-
const watchAction = this.Action('view', 'watch') as WatchAction
|
|
42
|
-
void watchAction.execute({})
|
|
43
|
-
await this.wait(10)
|
|
44
|
-
assert.isTrue(wasHit)
|
|
45
|
-
|
|
46
|
-
await watchAction.kill()
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
@test()
|
|
50
|
-
protected static async shouldCallBootAgainOnFileChange() {
|
|
51
|
-
let hitCount = 0
|
|
52
|
-
CommandService.fakeCommand(/yarn boot/gis, {
|
|
53
|
-
code: 0,
|
|
54
|
-
callback: () => {
|
|
55
|
-
hitCount++
|
|
56
|
-
},
|
|
57
|
-
})
|
|
58
|
-
|
|
59
|
-
const watchAction = this.Action('view', 'watch') as WatchAction
|
|
60
|
-
|
|
61
|
-
void watchAction.execute({})
|
|
34
|
+
void this.action.execute()
|
|
62
35
|
|
|
63
36
|
await this.wait(10)
|
|
64
37
|
|
|
65
|
-
assert.
|
|
66
|
-
|
|
67
|
-
await this.emitFileChangeEvent()
|
|
68
|
-
|
|
69
|
-
assert.isEqual(hitCount, 2)
|
|
70
|
-
await watchAction.kill()
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
@test()
|
|
74
|
-
protected static async changesDuringBootOfSkillKillSkill() {
|
|
75
|
-
CommandService.fakeCommand(/yarn boot/gis, {
|
|
76
|
-
code: 0,
|
|
77
|
-
})
|
|
78
|
-
|
|
79
|
-
const watchAction = this.Action('view', 'watch') as WatchAction
|
|
80
|
-
|
|
81
|
-
let passedOptions: any = null
|
|
82
|
-
|
|
83
|
-
//@ts-ignore
|
|
84
|
-
BootAction.prototype.execute = (options: any) => {
|
|
85
|
-
passedOptions = options
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
void watchAction.execute()
|
|
89
|
-
|
|
90
|
-
await this.wait(100)
|
|
91
|
-
|
|
92
|
-
assert.isTrue(passedOptions.shouldReturnImmediately)
|
|
93
|
-
|
|
94
|
-
await watchAction.kill()
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
@test()
|
|
98
|
-
protected static async holdsOnAction() {
|
|
99
|
-
CommandService.fakeCommand(/yarn boot/gis, {
|
|
100
|
-
code: 0,
|
|
101
|
-
})
|
|
102
|
-
|
|
103
|
-
const watchAction = this.Action('view', 'watch') as WatchAction
|
|
104
|
-
const actionPromise = watchAction.execute()
|
|
105
|
-
let didWait = false
|
|
106
|
-
const waitPromise = new Promise((resolve) => {
|
|
107
|
-
setTimeout(async () => {
|
|
108
|
-
didWait = true
|
|
109
|
-
await watchAction.kill()
|
|
110
|
-
resolve(null)
|
|
111
|
-
}, 1000)
|
|
112
|
-
})
|
|
113
|
-
|
|
114
|
-
await actionPromise
|
|
115
|
-
await waitPromise
|
|
116
|
-
|
|
117
|
-
assert.isTrue(didWait)
|
|
118
|
-
|
|
119
|
-
await watchAction.kill()
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
@test()
|
|
123
|
-
protected static async canKillAction() {
|
|
124
|
-
CommandService.fakeCommand(/yarn boot/gis, {
|
|
125
|
-
code: 0,
|
|
126
|
-
})
|
|
127
|
-
|
|
128
|
-
const watchAction = this.Action('view', 'watch') as WatchAction
|
|
129
|
-
const actionPromise = watchAction.execute()
|
|
130
|
-
|
|
131
|
-
let didWait = false
|
|
132
|
-
const waitPromise = new Promise((resolve) => {
|
|
133
|
-
setTimeout(() => {
|
|
134
|
-
didWait = true
|
|
135
|
-
resolve(null)
|
|
136
|
-
}, 1000)
|
|
137
|
-
})
|
|
138
|
-
|
|
139
|
-
await this.wait(100)
|
|
140
|
-
|
|
141
|
-
await watchAction.kill()
|
|
142
|
-
|
|
143
|
-
await actionPromise
|
|
144
|
-
|
|
145
|
-
assert.isFalse(didWait)
|
|
146
|
-
|
|
147
|
-
await waitPromise
|
|
148
|
-
|
|
149
|
-
await watchAction.kill()
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
@test()
|
|
153
|
-
protected static async makeSureWatcherIsStartedAndStopped() {
|
|
154
|
-
CommandService.fakeCommand(/yarn boot/gis, {
|
|
155
|
-
code: 0,
|
|
156
|
-
})
|
|
157
|
-
|
|
158
|
-
const watchFeature = this.featureInstaller.getFeature('watch')
|
|
159
|
-
let wasStarted = false
|
|
160
|
-
let wasStopped = false
|
|
161
|
-
|
|
162
|
-
watchFeature.startWatching = async () => {
|
|
163
|
-
wasStarted = true
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
watchFeature.stopWatching = async () => {
|
|
167
|
-
wasStopped = true
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
const watchAction = this.Action('view', 'watch') as WatchAction
|
|
171
|
-
void watchAction.execute()
|
|
172
|
-
|
|
173
|
-
await this.wait(100)
|
|
174
|
-
|
|
175
|
-
assert.isTrue(wasStarted)
|
|
176
|
-
assert.isFalse(wasStopped)
|
|
177
|
-
|
|
178
|
-
await watchAction.kill()
|
|
179
|
-
await this.wait(100)
|
|
180
|
-
|
|
181
|
-
assert.isTrue(wasStarted)
|
|
182
|
-
assert.isTrue(wasStopped)
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
@test()
|
|
186
|
-
protected static async killingActionKillsProcess() {
|
|
187
|
-
await this.FeatureFixture().installCachedFeatures('events')
|
|
188
|
-
await this.getSkillFixture().registerCurrentSkill({
|
|
189
|
-
name: `Watching skill views`,
|
|
190
|
-
})
|
|
191
|
-
|
|
192
|
-
await this.getViewFixture().createViewController({
|
|
193
|
-
nameKebab: 'root',
|
|
194
|
-
namePascal: 'Root',
|
|
195
|
-
})
|
|
196
|
-
|
|
197
|
-
await this.Action('view', 'sync').execute({})
|
|
198
|
-
|
|
199
|
-
await this.Service('build').build()
|
|
200
|
-
|
|
201
|
-
const watchAction = this.Action('view', 'watch') as WatchAction
|
|
202
|
-
const results = await watchAction.execute({ shouldReturnImmediately: true })
|
|
203
|
-
|
|
204
|
-
assert.isFalsy(results.errors)
|
|
205
|
-
|
|
206
|
-
let pid = watchAction.getPid()
|
|
207
|
-
|
|
208
|
-
while (!pid) {
|
|
209
|
-
await this.wait(100)
|
|
210
|
-
pid = watchAction.getPid()
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
await results.meta?.bootPromise
|
|
214
|
-
|
|
215
|
-
await this.assertProcessRunning(pid)
|
|
216
|
-
|
|
217
|
-
await watchAction.kill()
|
|
218
|
-
|
|
219
|
-
await this.wait(500)
|
|
220
|
-
|
|
221
|
-
await assert.doesThrowAsync(() => this.assertProcessRunning(pid as number))
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
private static async assertProcessRunning(pid: number) {
|
|
225
|
-
await new Promise((resolve, reject) => {
|
|
226
|
-
ps.lookup({ pid }, (err: any, results: any) => {
|
|
227
|
-
if (err || results.length !== 1) {
|
|
228
|
-
reject('boot process not running')
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
resolve(results)
|
|
232
|
-
})
|
|
233
|
-
})
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
private static async emitFileChangeEvent() {
|
|
237
|
-
const emitter = this.emitter
|
|
238
|
-
|
|
239
|
-
await emitter.emit('watcher.did-detect-change', {
|
|
240
|
-
changes: [
|
|
241
|
-
{
|
|
242
|
-
schemaId: 'generatedFile',
|
|
243
|
-
version: 'v2020_07_22',
|
|
244
|
-
values: {
|
|
245
|
-
action: 'updated',
|
|
246
|
-
name: 'Cool name!',
|
|
247
|
-
path: '/',
|
|
248
|
-
},
|
|
249
|
-
},
|
|
250
|
-
],
|
|
251
|
-
})
|
|
38
|
+
assert.isTrue(wasHit)
|
|
252
39
|
}
|
|
253
40
|
}
|
|
@@ -39,7 +39,7 @@ export default abstract class AbstractAction<S extends Schema = Schema>
|
|
|
39
39
|
public abstract invocationMessage: string
|
|
40
40
|
|
|
41
41
|
protected parent: AbstractFeature
|
|
42
|
-
protected
|
|
42
|
+
protected features: FeatureInstaller
|
|
43
43
|
protected cwd: string
|
|
44
44
|
protected templates: Templates
|
|
45
45
|
protected ui: GraphicsInterface
|
|
@@ -57,7 +57,7 @@ export default abstract class AbstractAction<S extends Schema = Schema>
|
|
|
57
57
|
this.parent = options.parent
|
|
58
58
|
this.storeFactory = options.storeFactory
|
|
59
59
|
this.serviceFactory = options.serviceFactory
|
|
60
|
-
this.
|
|
60
|
+
this.features = options.featureInstaller
|
|
61
61
|
this.ui = options.ui
|
|
62
62
|
this.writerFactory = options.writerFactory
|
|
63
63
|
this.apiClientFactory = options.apiClientFactory
|
|
@@ -96,11 +96,11 @@ export default abstract class AbstractAction<S extends Schema = Schema>
|
|
|
96
96
|
}
|
|
97
97
|
|
|
98
98
|
protected getFeature<C extends FeatureCode>(code: C) {
|
|
99
|
-
return this.
|
|
99
|
+
return this.features.getFeature(code)
|
|
100
100
|
}
|
|
101
101
|
|
|
102
102
|
protected getFeatureCodes(): FeatureCode[] {
|
|
103
|
-
return this.
|
|
103
|
+
return this.features.getAllCodes()
|
|
104
104
|
}
|
|
105
105
|
|
|
106
106
|
protected validateAndNormalizeOptions(options: SchemaPartialValues<S>) {
|
|
@@ -64,7 +64,7 @@ export default class DeployAction extends AbstractAction<OptionsSchema> {
|
|
|
64
64
|
})
|
|
65
65
|
|
|
66
66
|
const summaryLines = [`Added "${skill.name}" as a dependency!`]
|
|
67
|
-
const isEventInstalled = await this.
|
|
67
|
+
const isEventInstalled = await this.features.isInstalled('event')
|
|
68
68
|
if (isEventInstalled) {
|
|
69
69
|
summaryLines.push(
|
|
70
70
|
'You will need to run `spruce sync.events` before accessing any new events.'
|
|
@@ -295,7 +295,7 @@ export default class DeployAction extends AbstractAction<OptionsSchema> {
|
|
|
295
295
|
private async runTests() {
|
|
296
296
|
let results: FeatureActionResponse = {}
|
|
297
297
|
|
|
298
|
-
const isTestInstalled = await this.
|
|
298
|
+
const isTestInstalled = await this.features.isInstalled('test')
|
|
299
299
|
|
|
300
300
|
if (isTestInstalled) {
|
|
301
301
|
try {
|
|
@@ -321,7 +321,7 @@ export default class DeployAction extends AbstractAction<OptionsSchema> {
|
|
|
321
321
|
private async buildAndLint() {
|
|
322
322
|
let results: FeatureActionResponse = {}
|
|
323
323
|
|
|
324
|
-
const isSkillInstalled = await this.
|
|
324
|
+
const isSkillInstalled = await this.features.isInstalled('skill')
|
|
325
325
|
|
|
326
326
|
if (isSkillInstalled) {
|
|
327
327
|
try {
|
|
@@ -52,7 +52,7 @@ export default class UpdateDependenciesAction extends AbstractAction<OptionsSche
|
|
|
52
52
|
}
|
|
53
53
|
|
|
54
54
|
private async installDependencies() {
|
|
55
|
-
const features = await this.
|
|
55
|
+
const features = await this.features.getInstalledFeatures()
|
|
56
56
|
|
|
57
57
|
const pkg = this.Service('pkg')
|
|
58
58
|
const pkgContents = pkg.readPackage()
|
|
@@ -55,7 +55,7 @@ export default class UpgradeAction extends AbstractAction<OptionsSchema> {
|
|
|
55
55
|
}
|
|
56
56
|
|
|
57
57
|
private async updateScripts(options: { shouldConfirm: boolean }) {
|
|
58
|
-
const features = await this.
|
|
58
|
+
const features = await this.features.getInstalledFeatures()
|
|
59
59
|
|
|
60
60
|
let scripts: Record<string, any> = {}
|
|
61
61
|
|
|
@@ -142,13 +142,11 @@ export default class CreateAction extends AbstractAction<OptionsSchema> {
|
|
|
142
142
|
match: ParentClassCandidate
|
|
143
143
|
) {
|
|
144
144
|
if (match.featureCode) {
|
|
145
|
-
const isInstalled = await this.
|
|
146
|
-
match.featureCode
|
|
147
|
-
)
|
|
145
|
+
const isInstalled = await this.features.isInstalled(match.featureCode)
|
|
148
146
|
|
|
149
147
|
if (!isInstalled) {
|
|
150
148
|
this.ui.startLoading(`Installing ${match.name}...`)
|
|
151
|
-
await this.
|
|
149
|
+
await this.features.install({
|
|
152
150
|
features: [{ code: match.featureCode as any }],
|
|
153
151
|
})
|
|
154
152
|
this.ui.stopLoading()
|
|
@@ -1,112 +1,58 @@
|
|
|
1
|
-
import { buildSchema
|
|
1
|
+
import { buildSchema } from '@sprucelabs/schema'
|
|
2
2
|
import { heartwoodRemoteUtil } from '@sprucelabs/spruce-event-utils'
|
|
3
|
-
import { GraphicsTextEffect } from '@sprucelabs/spruce-skill-utils'
|
|
4
3
|
import AbstractAction from '../../AbstractAction'
|
|
5
4
|
import { FeatureActionResponse } from '../../features.types'
|
|
6
|
-
import { BootMeta } from '../../skill/actions/BootAction'
|
|
7
|
-
import WatchFeature from '../../watch/WatchFeature'
|
|
8
5
|
|
|
9
6
|
const optionsSchema = buildSchema({
|
|
10
7
|
id: 'watchViewsOptions',
|
|
11
8
|
description: 'Watch for view changes and preview them in real time.',
|
|
12
|
-
fields: {
|
|
13
|
-
shouldReturnImmediately: {
|
|
14
|
-
type: 'boolean',
|
|
15
|
-
hint: "For testing so we don't wait until the process is killed to get the results.",
|
|
16
|
-
},
|
|
17
|
-
},
|
|
9
|
+
fields: {},
|
|
18
10
|
})
|
|
19
11
|
|
|
20
12
|
type OptionsSchema = typeof optionsSchema
|
|
21
|
-
type Options = SchemaValues<OptionsSchema>
|
|
22
13
|
|
|
23
14
|
export default class WatchAction extends AbstractAction<OptionsSchema> {
|
|
24
15
|
public commandAliases = ['watch.views']
|
|
25
16
|
public optionsSchema: OptionsSchema = optionsSchema
|
|
26
17
|
public invocationMessage = 'Watching views... 🤩'
|
|
27
|
-
private resolve?: () => void
|
|
28
|
-
private bootControls?: BootMeta
|
|
29
18
|
private skillName!: string
|
|
30
|
-
private bootMessage!: string
|
|
31
|
-
private watchFeature!: WatchFeature
|
|
32
|
-
|
|
33
|
-
public async execute(options?: Options): Promise<FeatureActionResponse> {
|
|
34
|
-
const { shouldReturnImmediately } = this.validateAndNormalizeOptions(
|
|
35
|
-
options ?? {}
|
|
36
|
-
)
|
|
37
|
-
|
|
38
|
-
this.watchFeature = this.featureInstaller.getFeature('watch')
|
|
39
|
-
await this.watchFeature.startWatching({ delay: 2000 })
|
|
40
19
|
|
|
20
|
+
public async execute(): Promise<FeatureActionResponse> {
|
|
41
21
|
const skill = await this.Store('skill').loadCurrentSkill()
|
|
42
|
-
|
|
43
22
|
this.skillName = skill.name
|
|
44
|
-
this.bootControls = await this.boot()
|
|
45
|
-
|
|
46
|
-
await this.emitter.on('watcher.did-detect-change', async () => {
|
|
47
|
-
this.bootControls?.kill()
|
|
48
|
-
this.bootControls = await this.boot(
|
|
49
|
-
'Changes detected, rebooting skill...'
|
|
50
|
-
)
|
|
51
|
-
})
|
|
52
|
-
|
|
53
|
-
if (!shouldReturnImmediately) {
|
|
54
|
-
await new Promise((resolve) => {
|
|
55
|
-
//@ts-ignore
|
|
56
|
-
this.resolve = resolve
|
|
57
|
-
})
|
|
58
23
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
24
|
+
this.resetUi()
|
|
25
|
+
const commands = this.Service('command')
|
|
26
|
+
await commands.execute(
|
|
27
|
+
'ENABLED_SKILL_FEATURES=view,event SHOULD_REGISTER_EVENTS_AND_LISTENERS=false SHOULD_WATCH_VIEWS=true MAXIMUM_LOG_PREFIXES_LENGTH=0 yarn boot',
|
|
28
|
+
{
|
|
29
|
+
onData: (data) => {
|
|
30
|
+
const line = this.popLastLine(data)
|
|
31
|
+
this.ui.startLoading(line)
|
|
32
|
+
},
|
|
33
|
+
}
|
|
34
|
+
)
|
|
62
35
|
|
|
63
36
|
return {
|
|
64
37
|
summaryLines: [`Done watching...`],
|
|
65
|
-
meta: {
|
|
66
|
-
bootPromise: this.bootControls.bootPromise,
|
|
67
|
-
},
|
|
68
38
|
}
|
|
69
39
|
}
|
|
70
40
|
|
|
41
|
+
private popLastLine(data: string) {
|
|
42
|
+
const line = data
|
|
43
|
+
.trim()
|
|
44
|
+
.split('\n')
|
|
45
|
+
.filter((s) => !!s)
|
|
46
|
+
.pop()
|
|
47
|
+
|
|
48
|
+
return line && line.length > 0 ? line.trim() : 'Waiting for changes'
|
|
49
|
+
}
|
|
50
|
+
|
|
71
51
|
private getPreviewUrl() {
|
|
72
52
|
const remote = this.Service('remote').getRemote() as any
|
|
73
53
|
return heartwoodRemoteUtil.buildUrl(remote) + '/#views/heartwood.watch'
|
|
74
54
|
}
|
|
75
55
|
|
|
76
|
-
private async boot(bootMessage = 'Booting skill...') {
|
|
77
|
-
this.bootMessage = bootMessage
|
|
78
|
-
this.resetUi()
|
|
79
|
-
|
|
80
|
-
const results = await this.Action('skill', 'boot').execute({
|
|
81
|
-
shouldReturnImmediately: true,
|
|
82
|
-
onData: (msg: string) => {
|
|
83
|
-
if (!msg.includes('node build/index') && !msg.includes('yarn run')) {
|
|
84
|
-
this.ui.stopLoading()
|
|
85
|
-
this.ui.renderLine(msg.trim())
|
|
86
|
-
this.ui.startLoading(this.bootMessage)
|
|
87
|
-
}
|
|
88
|
-
},
|
|
89
|
-
onError: (msg: string) => {
|
|
90
|
-
if (!msg.includes('No license field')) {
|
|
91
|
-
this.ui.stopLoading()
|
|
92
|
-
this.ui.renderLine(msg, [GraphicsTextEffect.Red])
|
|
93
|
-
this.ui.startLoading()
|
|
94
|
-
}
|
|
95
|
-
},
|
|
96
|
-
})
|
|
97
|
-
|
|
98
|
-
results.meta?.bootPromise?.then(() => {
|
|
99
|
-
this.bootMessage = 'Skill booted. Waiting for changes...'
|
|
100
|
-
this.ui.startLoading(this.bootMessage)
|
|
101
|
-
})
|
|
102
|
-
|
|
103
|
-
if (results.errors) {
|
|
104
|
-
throw results.errors[0]
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
return results.meta as BootMeta
|
|
108
|
-
}
|
|
109
|
-
|
|
110
56
|
private resetUi() {
|
|
111
57
|
this.ui.clear()
|
|
112
58
|
this.ui.renderHero('Heartwood')
|
|
@@ -119,16 +65,6 @@ export default class WatchAction extends AbstractAction<OptionsSchema> {
|
|
|
119
65
|
])
|
|
120
66
|
this.ui.renderDivider()
|
|
121
67
|
this.ui.renderLine('')
|
|
122
|
-
this.ui.startLoading(
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
public async kill() {
|
|
126
|
-
await this.watchFeature.stopWatching()
|
|
127
|
-
this.bootControls?.kill()
|
|
128
|
-
this.resolve?.()
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
public getPid() {
|
|
132
|
-
return this.bootControls?.pid
|
|
68
|
+
this.ui.startLoading('Watching for changes')
|
|
133
69
|
}
|
|
134
70
|
}
|
|
@@ -9,13 +9,6 @@ import SpruceError from '../errors/SpruceError'
|
|
|
9
9
|
|
|
10
10
|
process.setMaxListeners(100)
|
|
11
11
|
|
|
12
|
-
interface MockResponse {
|
|
13
|
-
code: number
|
|
14
|
-
stdout?: string
|
|
15
|
-
stderr?: string
|
|
16
|
-
callback?: (executable: string, args: any[]) => void
|
|
17
|
-
}
|
|
18
|
-
|
|
19
12
|
export default class CommandService {
|
|
20
13
|
public cwd: string
|
|
21
14
|
private activeChildProcess: ChildProcess | undefined
|
|
@@ -195,3 +188,10 @@ export default class CommandService {
|
|
|
195
188
|
this.mockResponses = []
|
|
196
189
|
}
|
|
197
190
|
}
|
|
191
|
+
|
|
192
|
+
interface MockResponse {
|
|
193
|
+
code: number
|
|
194
|
+
stdout?: string
|
|
195
|
+
stderr?: string
|
|
196
|
+
callback?: (executable: string, args: any[]) => void
|
|
197
|
+
}
|