@sprucelabs/spruce-cli 18.0.0 → 18.1.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 (158) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/build/__tests__/behavioral/EnablingAndDisablingCache.test.js +1 -1
  3. package/build/__tests__/behavioral/EnablingAndDisablingCache.test.js.map +1 -1
  4. package/build/__tests__/behavioral/RememberingUpgradeSelections.test.js +1 -1
  5. package/build/__tests__/behavioral/RememberingUpgradeSelections.test.js.map +1 -1
  6. package/build/__tests__/behavioral/SettingUpSchemasForModuleDistribution.test.js +4 -4
  7. package/build/__tests__/behavioral/SettingUpSchemasForModuleDistribution.test.js.map +1 -1
  8. package/build/__tests__/behavioral/WatchingSkillViews.test.js +3 -3
  9. package/build/__tests__/behavioral/WatchingSkillViews.test.js.map +1 -1
  10. package/build/__tests__/behavioral/errors/SettingUpErrors.test.js +1 -1
  11. package/build/__tests__/behavioral/errors/SettingUpErrors.test.js.map +1 -1
  12. package/build/__tests__/behavioral/events/CreatingAListener.test.d.ts +2 -0
  13. package/build/__tests__/behavioral/events/CreatingAListener.test.js +118 -59
  14. package/build/__tests__/behavioral/events/CreatingAListener.test.js.map +1 -1
  15. package/build/__tests__/behavioral/events/EverythingInstalledInstaller.d.ts +17 -0
  16. package/build/__tests__/behavioral/events/EverythingInstalledInstaller.js +137 -0
  17. package/build/__tests__/behavioral/events/EverythingInstalledInstaller.js.map +1 -0
  18. package/build/__tests__/behavioral/onboard/StartingOnboarding.test.js +46 -45
  19. package/build/__tests__/behavioral/onboard/StartingOnboarding.test.js.map +1 -1
  20. package/build/__tests__/behavioral/tests/CreatingATest.test.js +1 -1
  21. package/build/__tests__/behavioral/tests/CreatingATest.test.js.map +1 -1
  22. package/build/__tests__/behavioral/tests/SelectingAnAbstractTestClass.test.js +4 -4
  23. package/build/__tests__/behavioral/tests/SelectingAnAbstractTestClass.test.js.map +1 -1
  24. package/build/__tests__/behavioral/upgrading/UpdatingDependencies2.test.js +2 -2
  25. package/build/__tests__/behavioral/upgrading/UpdatingDependencies2.test.js.map +1 -1
  26. package/build/__tests__/behavioral/upgrading/UpgradingANodeModule.test.js +2 -2
  27. package/build/__tests__/behavioral/upgrading/UpgradingANodeModule.test.js.map +1 -1
  28. package/build/__tests__/behavioral/upgrading/UpgradingASkill5.test.js +2 -2
  29. package/build/__tests__/behavioral/upgrading/UpgradingASkill5.test.js.map +1 -1
  30. package/build/__tests__/behavioral/upgrading/UpgradingWithListeners.test.js +2 -2
  31. package/build/__tests__/behavioral/upgrading/UpgradingWithListeners.test.js.map +1 -1
  32. package/build/__tests__/behavioral/views/CreatingASkillView.test.js +1 -1
  33. package/build/__tests__/behavioral/views/CreatingASkillView.test.js.map +1 -1
  34. package/build/__tests__/behavioral/views/CreatingATheme.test.js +1 -1
  35. package/build/__tests__/behavioral/views/CreatingATheme.test.js.map +1 -1
  36. package/build/__tests__/behavioral/watchers/WatchingForChanges.test.d.ts +3 -3
  37. package/build/__tests__/behavioral/watchers/WatchingForChanges.test.js +153 -156
  38. package/build/__tests__/behavioral/watchers/WatchingForChanges.test.js.map +1 -1
  39. package/build/__tests__/implementation/ActionExecuter.test.js +2 -2
  40. package/build/__tests__/implementation/ActionExecuter.test.js.map +1 -1
  41. package/build/__tests__/implementation/ActionExecuter2.test.js +1 -1
  42. package/build/__tests__/implementation/ActionExecuter2.test.js.map +1 -1
  43. package/build/__tests__/implementation/ActionExecuter4.test.js +1 -1
  44. package/build/__tests__/implementation/ActionExecuter4.test.js.map +1 -1
  45. package/build/__tests__/implementation/FeatureInstaller.test.js +8 -4
  46. package/build/__tests__/implementation/FeatureInstaller.test.js.map +1 -1
  47. package/build/__tests__/implementation/GlobalEmitter.d.ts +1 -1
  48. package/build/__tests__/implementation/GlobalEmitter.js +9 -10
  49. package/build/__tests__/implementation/GlobalEmitter.js.map +1 -1
  50. package/build/__tests__/implementation/SettingUpANodeModule.test.js +1 -1
  51. package/build/__tests__/implementation/SettingUpANodeModule.test.js.map +1 -1
  52. package/build/__tests__/implementation/SkillStore.test.d.ts +3 -1
  53. package/build/__tests__/implementation/SkillStore.test.js +67 -50
  54. package/build/__tests__/implementation/SkillStore.test.js.map +1 -1
  55. package/build/__tests__/implementation/StoreFeature.test.js +1 -1
  56. package/build/__tests__/implementation/StoreFeature.test.js.map +1 -1
  57. package/build/cli.js +3 -3
  58. package/build/cli.js.map +1 -1
  59. package/build/features/AbstractAction.d.ts +2 -2
  60. package/build/features/AbstractAction.js.map +1 -1
  61. package/build/features/AbstractFeature.d.ts +22 -22
  62. package/build/features/AbstractFeature.js.map +1 -1
  63. package/build/features/ActionExecuter.d.ts +8 -8
  64. package/build/features/ActionExecuter.js.map +1 -1
  65. package/build/features/FeatureInstaller.d.ts +15 -2
  66. package/build/features/FeatureInstaller.js +36 -36
  67. package/build/features/FeatureInstaller.js.map +1 -1
  68. package/build/features/FeatureInstallerFactory.d.ts +12 -10
  69. package/build/features/FeatureInstallerFactory.js +2 -2
  70. package/build/features/FeatureInstallerFactory.js.map +1 -1
  71. package/build/features/OverrideActionDecorator.js +4 -5
  72. package/build/features/OverrideActionDecorator.js.map +1 -1
  73. package/build/features/event/actions/ListenAction.js.map +1 -1
  74. package/build/features/event/actions/SetRemoteAction.d.ts +1 -0
  75. package/build/features/event/actions/SetRemoteAction.js +2 -1
  76. package/build/features/event/actions/SetRemoteAction.js.map +1 -1
  77. package/build/features/event/actions/SyncListenersAction.js.map +1 -1
  78. package/build/features/node/NodeFeature.js.map +1 -1
  79. package/build/features/skill/SkillFeature.js.map +1 -1
  80. package/build/features/skill/stores/SkillStore.d.ts +4 -1
  81. package/build/features/skill/stores/SkillStore.js +127 -100
  82. package/build/features/skill/stores/SkillStore.js.map +1 -1
  83. package/build/features/watch/WatchFeature.js +1 -1
  84. package/build/features/watch/WatchFeature.js.map +1 -1
  85. package/build/interfaces/SpyInterface.d.ts +2 -0
  86. package/build/interfaces/SpyInterface.js +16 -4
  87. package/build/interfaces/SpyInterface.js.map +1 -1
  88. package/build/stores/AbstractStore.d.ts +9 -7
  89. package/build/stores/AbstractStore.js.map +1 -1
  90. package/build/stores/StoreFactory.d.ts +19 -13
  91. package/build/stores/StoreFactory.js +15 -13
  92. package/build/stores/StoreFactory.js.map +1 -1
  93. package/build/tests/AbstractCliTest.d.ts +9 -6
  94. package/build/tests/AbstractCliTest.js +53 -45
  95. package/build/tests/AbstractCliTest.js.map +1 -1
  96. package/build/tests/AbstractSchemaTest.js +18 -20
  97. package/build/tests/AbstractSchemaTest.js.map +1 -1
  98. package/build/utilities/action.utility.js +3 -1
  99. package/build/utilities/action.utility.js.map +1 -1
  100. package/node_modules/@typescript-eslint/parser/package.json +5 -5
  101. package/node_modules/@typescript-eslint/scope-manager/package.json +5 -5
  102. package/node_modules/@typescript-eslint/types/package.json +2 -2
  103. package/node_modules/@typescript-eslint/typescript-estree/package.json +5 -5
  104. package/node_modules/@typescript-eslint/visitor-keys/package.json +3 -3
  105. package/package.json +32 -90
  106. package/src/__tests__/behavioral/EnablingAndDisablingCache.test.ts +1 -1
  107. package/src/__tests__/behavioral/RememberingUpgradeSelections.test.ts +1 -1
  108. package/src/__tests__/behavioral/SettingUpSchemasForModuleDistribution.test.ts +4 -4
  109. package/src/__tests__/behavioral/WatchingSkillViews.test.ts +3 -3
  110. package/src/__tests__/behavioral/errors/SettingUpErrors.test.ts +1 -1
  111. package/src/__tests__/behavioral/events/CreatingAListener.test.ts +41 -14
  112. package/src/__tests__/behavioral/events/EverythingInstalledInstaller.ts +46 -0
  113. package/src/__tests__/behavioral/onboard/StartingOnboarding.test.ts +10 -5
  114. package/src/__tests__/behavioral/tests/CreatingATest.test.ts +1 -1
  115. package/src/__tests__/behavioral/tests/SelectingAnAbstractTestClass.test.ts +4 -4
  116. package/src/__tests__/behavioral/upgrading/UpdatingDependencies2.test.ts +2 -2
  117. package/src/__tests__/behavioral/upgrading/UpgradingANodeModule.test.ts +2 -2
  118. package/src/__tests__/behavioral/upgrading/UpgradingASkill5.test.ts +2 -2
  119. package/src/__tests__/behavioral/upgrading/UpgradingWithListeners.test.ts +2 -2
  120. package/src/__tests__/behavioral/views/CreatingASkillView.test.ts +1 -1
  121. package/src/__tests__/behavioral/views/CreatingATheme.test.ts +1 -1
  122. package/src/__tests__/behavioral/watchers/WatchingForChanges.test.ts +35 -35
  123. package/src/__tests__/implementation/ActionExecuter.test.ts +2 -2
  124. package/src/__tests__/implementation/ActionExecuter2.test.ts +1 -1
  125. package/src/__tests__/implementation/ActionExecuter4.test.ts +1 -1
  126. package/src/__tests__/implementation/FeatureInstaller.test.ts +8 -1
  127. package/src/__tests__/implementation/GlobalEmitter.ts +2 -4
  128. package/src/__tests__/implementation/SettingUpANodeModule.test.ts +1 -1
  129. package/src/__tests__/implementation/SkillStore.test.ts +23 -24
  130. package/src/__tests__/implementation/StoreFeature.test.ts +1 -1
  131. package/src/cli.ts +7 -3
  132. package/src/features/AbstractAction.ts +3 -3
  133. package/src/features/AbstractFeature.ts +26 -26
  134. package/src/features/ActionExecuter.ts +9 -9
  135. package/src/features/FeatureInstaller.ts +32 -12
  136. package/src/features/FeatureInstallerFactory.ts +17 -13
  137. package/src/features/OverrideActionDecorator.ts +2 -5
  138. package/src/features/event/actions/ListenAction.ts +1 -0
  139. package/src/features/event/actions/SetRemoteAction.ts +2 -1
  140. package/src/features/event/actions/SyncListenersAction.ts +0 -1
  141. package/src/features/node/NodeFeature.ts +3 -1
  142. package/src/features/skill/SkillFeature.ts +3 -3
  143. package/src/features/skill/stores/SkillStore.ts +18 -11
  144. package/src/features/watch/WatchFeature.ts +1 -1
  145. package/src/interfaces/SpyInterface.ts +10 -0
  146. package/src/stores/AbstractStore.ts +14 -8
  147. package/src/stores/StoreFactory.ts +56 -44
  148. package/src/tests/AbstractCliTest.ts +53 -45
  149. package/src/tests/AbstractSchemaTest.ts +1 -3
  150. package/src/utilities/action.utility.ts +3 -1
  151. package/.DS_Store +0 -0
  152. package/.env +0 -25
  153. package/.eslintcache +0 -1
  154. package/build/.spruce/tmp/cached-skills.json +0 -3
  155. package/junit.xml +0 -7
  156. package/src/.DS_Store +0 -0
  157. package/src/.spruce/tmp/cached-skills.json +0 -3
  158. package/yarn-error.log +0 -12174
@@ -1,22 +1,25 @@
1
1
  import { test, assert } from '@sprucelabs/test-utils'
2
2
  import { errorAssert } from '@sprucelabs/test-utils'
3
+ import SkillStore from '../../features/skill/stores/SkillStore'
3
4
  import AbstractCliTest from '../../tests/AbstractCliTest'
4
5
 
5
6
  export default class SkillStoreTest extends AbstractCliTest {
6
- @test()
7
- protected static async canInstantiateSkillStore() {
8
- assert.isTruthy(this.Store('skill'))
7
+ private static store: SkillStore
8
+
9
+ protected static async beforeEach() {
10
+ await super.beforeEach()
11
+ this.store = this.SkillStore()
9
12
  }
10
13
 
11
14
  @test()
12
15
  protected static async hasRegisterMethod() {
13
- assert.isFunction(this.Store('skill').register)
16
+ assert.isFunction(this.store.register)
14
17
  }
15
18
 
16
19
  @test()
17
20
  protected static async cantRegisterIfNotInSkill() {
18
21
  const err = await assert.doesThrowAsync(() =>
19
- this.Store('skill').register({
22
+ this.store.register({
20
23
  name: 'awesome skill',
21
24
  slug: 'awesome-skill',
22
25
  })
@@ -26,16 +29,14 @@ export default class SkillStoreTest extends AbstractCliTest {
26
29
 
27
30
  @test()
28
31
  protected static async cantLoadcurrentSkillIfNotInSkill() {
29
- const err = await assert.doesThrowAsync(() =>
30
- this.Store('skill').loadCurrentSkill()
31
- )
32
+ const err = await assert.doesThrowAsync(() => this.store.loadCurrentSkill())
32
33
  errorAssert.assertError(err, 'DIRECTORY_NOT_SKILL')
33
34
  }
34
35
 
35
36
  @test()
36
37
  protected static async cantCheckIfSkillIsRegisteredNotInSkill() {
37
38
  const err = await assert.doesThrowAsync(() =>
38
- this.Store('skill').isCurrentSkillRegistered()
39
+ this.store.isCurrentSkillRegistered()
39
40
  )
40
41
  errorAssert.assertError(err, 'DIRECTORY_NOT_SKILL')
41
42
  }
@@ -43,8 +44,7 @@ export default class SkillStoreTest extends AbstractCliTest {
43
44
  @test()
44
45
  protected static async canGetNamespace() {
45
46
  await this.FeatureFixture().installCachedFeatures('skills')
46
-
47
- const namespace = await this.Store('skill').loadCurrentSkillsNamespace()
47
+ const namespace = await this.store.loadCurrentSkillsNamespace()
48
48
  assert.isEqual(namespace, 'TestSkill')
49
49
  }
50
50
 
@@ -52,12 +52,9 @@ export default class SkillStoreTest extends AbstractCliTest {
52
52
  protected static async canSetNamespace() {
53
53
  await this.FeatureFixture().installCachedFeatures('skills')
54
54
 
55
- const store = this.Store('skill')
56
- let namespace = await store.loadCurrentSkillsNamespace()
57
-
58
- await this.Store('skill').setCurrentSkillsNamespace('new-namespace')
59
-
60
- namespace = await store.loadCurrentSkillsNamespace()
55
+ let namespace = await this.store.loadCurrentSkillsNamespace()
56
+ await this.store.setCurrentSkillsNamespace('new-namespace')
57
+ namespace = await this.store.loadCurrentSkillsNamespace()
61
58
  assert.isEqual(namespace, 'NewNamespace')
62
59
  }
63
60
 
@@ -68,12 +65,10 @@ export default class SkillStoreTest extends AbstractCliTest {
68
65
  const slug = `awesome-skill-${new Date().getTime()}`
69
66
  await this.people.loginAsDemoPerson()
70
67
 
71
- const skillStore = this.Store('skill')
72
-
73
- let isRegistered = await skillStore.isCurrentSkillRegistered()
68
+ let isRegistered = await this.store.isCurrentSkillRegistered()
74
69
  assert.isFalse(isRegistered)
75
70
 
76
- const skill = await skillStore.register({
71
+ const skill = await this.store.register({
77
72
  name: 'awesome skill',
78
73
  slug,
79
74
  })
@@ -92,10 +87,10 @@ export default class SkillStoreTest extends AbstractCliTest {
92
87
 
93
88
  assert.isEqual(results.skill?.id, skill.id)
94
89
 
95
- isRegistered = await skillStore.isCurrentSkillRegistered()
90
+ isRegistered = await this.store.isCurrentSkillRegistered()
96
91
  assert.isTrue(isRegistered)
97
92
 
98
- const currentSkill = await skillStore.loadCurrentSkill()
93
+ const currentSkill = await this.store.loadCurrentSkill()
99
94
 
100
95
  assert.isEqual(currentSkill.id, skill.id)
101
96
  assert.isTrue(currentSkill.isRegistered)
@@ -109,7 +104,7 @@ export default class SkillStoreTest extends AbstractCliTest {
109
104
  assert.isEqual(env.get('SKILL_API_KEY'), skill.apiKey)
110
105
 
111
106
  const err = await assert.doesThrowAsync(() =>
112
- skillStore.setCurrentSkillsNamespace('test')
107
+ this.store.setCurrentSkillsNamespace('test')
113
108
  )
114
109
 
115
110
  errorAssert.assertError(err, 'GENERIC')
@@ -118,4 +113,8 @@ export default class SkillStoreTest extends AbstractCliTest {
118
113
  const namespace = pkg.get('skill.namespace')
119
114
  assert.isEqual(namespace, slug)
120
115
  }
116
+
117
+ private static SkillStore(): SkillStore {
118
+ return this.Store('skill', {})
119
+ }
121
120
  }
@@ -12,7 +12,7 @@ export default class StoreFeatureTest extends AbstractCliTest {
12
12
  })
13
13
 
14
14
  let hitCount = 0
15
- const emitter = this.getEmitter()
15
+ const emitter = this.emitter
16
16
  await emitter.on(
17
17
  'feature.will-execute',
18
18
  async ({ featureCode, actionCode }) => {
package/src/cli.ts CHANGED
@@ -20,7 +20,9 @@ import FeatureCommandAttacher, {
20
20
  BlockedCommands,
21
21
  OptionOverrides,
22
22
  } from './features/FeatureCommandAttacher'
23
- import FeatureInstaller from './features/FeatureInstaller'
23
+ import FeatureInstaller, {
24
+ FeatureInstallerImpl,
25
+ } from './features/FeatureInstaller'
24
26
  import FeatureInstallerFactory from './features/FeatureInstallerFactory'
25
27
  import { FeatureCode, InstallFeatureOptions } from './features/features.types'
26
28
  import CliGlobalEmitter, {
@@ -471,14 +473,16 @@ async function setupInFlightEntertainment(ui: TerminalInterface) {
471
473
  const command = new CommandService(diskUtil.resolvePath(__dirname, '../'))
472
474
  InFlightEntertainment.setup({ command, ui })
473
475
 
474
- FeatureInstaller.startInFlightIntertainmentHandler = (didUpdateHandler) => {
476
+ FeatureInstallerImpl.startInFlightIntertainmentHandler = (
477
+ didUpdateHandler
478
+ ) => {
475
479
  InFlightEntertainment.start()
476
480
  didUpdateHandler((message) => {
477
481
  InFlightEntertainment.writeStatus(message)
478
482
  })
479
483
  }
480
484
 
481
- FeatureInstaller.stopInFlightIntertainmentHandler = () => {
485
+ FeatureInstallerImpl.stopInFlightIntertainmentHandler = () => {
482
486
  InFlightEntertainment.stop()
483
487
  }
484
488
  }
@@ -9,7 +9,7 @@ import ServiceFactory, {
9
9
  } from '../services/ServiceFactory'
10
10
  import StoreFactory, {
11
11
  StoreCode,
12
- StoreFactoryMethodOptions,
12
+ CreateStoreOptions,
13
13
  StoreMap,
14
14
  } from '../stores/StoreFactory'
15
15
  import {
@@ -79,9 +79,9 @@ export default abstract class AbstractAction<S extends Schema = Schema>
79
79
 
80
80
  protected Store<C extends StoreCode>(
81
81
  code: C,
82
- options?: StoreFactoryMethodOptions
82
+ options?: CreateStoreOptions<C>
83
83
  ): StoreMap[C] {
84
- return this.storeFactory.Store(code, { cwd: this.cwd, ...options })
84
+ return this.storeFactory.Store(code, { cwd: this.cwd, ...(options as any) })
85
85
  }
86
86
 
87
87
  protected Writer<C extends WriterCode>(
@@ -10,7 +10,7 @@ import ServiceFactory, {
10
10
  } from '../services/ServiceFactory'
11
11
  import StoreFactory, {
12
12
  StoreCode,
13
- StoreFactoryMethodOptions,
13
+ CreateStoreOptions,
14
14
  StoreMap,
15
15
  } from '../stores/StoreFactory'
16
16
  import {
@@ -28,29 +28,6 @@ import featuresUtil from './feature.utilities'
28
28
  import FeatureInstaller from './FeatureInstaller'
29
29
  import { FeatureCode } from './features.types'
30
30
 
31
- export interface InstallResults {
32
- files?: GeneratedFile[]
33
- cwd?: string
34
- }
35
-
36
- export interface FeatureDependency {
37
- isRequired: boolean
38
- code: FeatureCode
39
- }
40
-
41
- export interface FeatureOptions {
42
- cwd: string
43
- serviceFactory: ServiceFactory
44
- templates: Templates
45
- storeFactory: StoreFactory
46
- actionFactory?: ActionFactory
47
- featureInstaller: FeatureInstaller
48
- ui: GraphicsInterface
49
- emitter: GlobalEmitter
50
- apiClientFactory: ApiClientFactory
51
- actionExecuter: ActionExecuter
52
- }
53
-
54
31
  export default abstract class AbstractFeature<
55
32
  S extends Schema | undefined = Schema | undefined
56
33
  > implements ServiceProvider
@@ -162,9 +139,9 @@ export default abstract class AbstractFeature<
162
139
 
163
140
  public Store<C extends StoreCode>(
164
141
  code: C,
165
- options?: StoreFactoryMethodOptions
142
+ options?: CreateStoreOptions<C>
166
143
  ): StoreMap[C] {
167
- return this.storeFactory.Store(code, { cwd: this.cwd, ...options })
144
+ return this.storeFactory.Store(code, { cwd: this.cwd, ...(options as any) })
168
145
  }
169
146
 
170
147
  protected async connectToApi(
@@ -173,3 +150,26 @@ export default abstract class AbstractFeature<
173
150
  return this.apiClientFactory(options)
174
151
  }
175
152
  }
153
+
154
+ export interface InstallResults {
155
+ files?: GeneratedFile[]
156
+ cwd?: string
157
+ }
158
+
159
+ export interface FeatureDependency {
160
+ isRequired: boolean
161
+ code: FeatureCode
162
+ }
163
+
164
+ export interface FeatureOptions {
165
+ cwd: string
166
+ serviceFactory: ServiceFactory
167
+ templates: Templates
168
+ storeFactory: StoreFactory
169
+ actionFactory?: ActionFactory
170
+ featureInstaller: FeatureInstaller
171
+ ui: GraphicsInterface
172
+ emitter: GlobalEmitter
173
+ apiClientFactory: ApiClientFactory
174
+ actionExecuter: ActionExecuter
175
+ }
@@ -14,15 +14,6 @@ import {
14
14
  FeatureActionResponse,
15
15
  } from './features.types'
16
16
 
17
- export interface ActionExecuterOptions {
18
- ui: GraphicsInterface
19
- emitter: GlobalEmitter
20
- actionFactory: ActionFactory
21
- featureInstallerFactory: () => FeatureInstaller
22
- shouldAutoHandleDependencies?: boolean
23
- shouldThrowOnListenerError?: boolean
24
- }
25
-
26
17
  export default class ActionExecuter {
27
18
  private emitter: GlobalEmitter
28
19
  private ui: GraphicsInterface
@@ -201,3 +192,12 @@ export default class ActionExecuter {
201
192
  return action as any
202
193
  }
203
194
  }
195
+
196
+ export interface ActionExecuterOptions {
197
+ ui: GraphicsInterface
198
+ emitter: GlobalEmitter
199
+ actionFactory: ActionFactory
200
+ featureInstallerFactory: () => FeatureInstaller
201
+ shouldAutoHandleDependencies?: boolean
202
+ shouldThrowOnListenerError?: boolean
203
+ }
@@ -17,7 +17,7 @@ import {
17
17
  FeatureMap,
18
18
  } from './features.types'
19
19
 
20
- export default class FeatureInstaller implements ServiceProvider {
20
+ export class FeatureInstallerImpl implements ServiceProvider, FeatureInstaller {
21
21
  public cwd: string
22
22
 
23
23
  private featureMap: Partial<FeatureMap> = {}
@@ -97,12 +97,12 @@ export default class FeatureInstaller implements ServiceProvider {
97
97
  }
98
98
 
99
99
  public getFeatureDependencies<C extends FeatureCode>(
100
- featureCode: C,
101
- trackedFeatures: FeatureDependency[] = []
100
+ featureCode: C
101
+ // trackedFeatures: FeatureDependency[] = []
102
102
  ): FeatureDependency[] {
103
103
  let deps = this.getFeatureDependenciesIncludingSelf(
104
104
  { code: featureCode, isRequired: true },
105
- trackedFeatures
105
+ [] // trackedFeatures
106
106
  ).filter((f) => f.code !== featureCode)
107
107
 
108
108
  deps = this.sortFeatures(deps)
@@ -170,10 +170,10 @@ export default class FeatureInstaller implements ServiceProvider {
170
170
  const shouldAllowEntertainment = !!features.find((f) => f.code === 'skill')
171
171
 
172
172
  if (
173
- FeatureInstaller.startInFlightIntertainmentHandler &&
173
+ FeatureInstallerImpl.startInFlightIntertainmentHandler &&
174
174
  shouldAllowEntertainment
175
175
  ) {
176
- FeatureInstaller.startInFlightIntertainmentHandler(
176
+ FeatureInstallerImpl.startInFlightIntertainmentHandler(
177
177
  (handler: InternalUpdateHandler) => {
178
178
  didUpdateHandler = handler
179
179
  }
@@ -193,6 +193,7 @@ export default class FeatureInstaller implements ServiceProvider {
193
193
  didUpdateHandler?.(`Checking if ${code} is installed...`)
194
194
 
195
195
  const isInstalled = await this.isInstalled(code)
196
+
196
197
  if (!isInstalled && installFeatureDependencies) {
197
198
  didUpdateHandler?.(`It is not, checking dependencies...`)
198
199
  dependenciesToInstall = dependenciesToInstall.concat(
@@ -227,6 +228,7 @@ export default class FeatureInstaller implements ServiceProvider {
227
228
  installFeature,
228
229
  didUpdateHandler
229
230
  )
231
+
230
232
  results = merge(results, installResults)
231
233
  }
232
234
  }
@@ -235,10 +237,10 @@ export default class FeatureInstaller implements ServiceProvider {
235
237
  results = merge(results, pendingResults)
236
238
 
237
239
  if (
238
- FeatureInstaller.stopInFlightIntertainmentHandler &&
240
+ FeatureInstallerImpl.stopInFlightIntertainmentHandler &&
239
241
  shouldAllowEntertainment
240
242
  ) {
241
- FeatureInstaller.stopInFlightIntertainmentHandler()
243
+ FeatureInstallerImpl.stopInFlightIntertainmentHandler()
242
244
  }
243
245
 
244
246
  return results
@@ -308,8 +310,8 @@ export default class FeatureInstaller implements ServiceProvider {
308
310
  features: AbstractFeature[],
309
311
  didUpdateHandler?: InternalUpdateHandler
310
312
  ) {
311
- if (FeatureInstaller.startInFlightIntertainmentHandler) {
312
- FeatureInstaller.startInFlightIntertainmentHandler(
313
+ if (FeatureInstallerImpl.startInFlightIntertainmentHandler) {
314
+ FeatureInstallerImpl.startInFlightIntertainmentHandler(
313
315
  (handler: InternalUpdateHandler) => {
314
316
  didUpdateHandler = handler
315
317
  }
@@ -325,8 +327,8 @@ export default class FeatureInstaller implements ServiceProvider {
325
327
 
326
328
  await this.installAllPending(didUpdateHandler)
327
329
 
328
- if (FeatureInstaller.stopInFlightIntertainmentHandler) {
329
- FeatureInstaller.stopInFlightIntertainmentHandler()
330
+ if (FeatureInstallerImpl.stopInFlightIntertainmentHandler) {
331
+ FeatureInstallerImpl.stopInFlightIntertainmentHandler()
330
332
  }
331
333
  }
332
334
 
@@ -341,6 +343,7 @@ export default class FeatureInstaller implements ServiceProvider {
341
343
  this.packagesToInstall.length === 1 ? '' : 's'
342
344
  }. Please be patient.`
343
345
  )
346
+
344
347
  await pkgService.install(this.packagesToInstall, {})
345
348
  }
346
349
 
@@ -350,6 +353,7 @@ export default class FeatureInstaller implements ServiceProvider {
350
353
  this.devPackagesToInstall.length === 1 ? '' : 's'
351
354
  }. Please be patient.`
352
355
  )
356
+
353
357
  await pkgService.install(this.devPackagesToInstall, {
354
358
  isDev: true,
355
359
  })
@@ -491,3 +495,19 @@ export default class FeatureInstaller implements ServiceProvider {
491
495
  return installed.filter((f) => !!f) as FeatureMap[keyof FeatureMap][]
492
496
  }
493
497
  }
498
+
499
+ export default interface FeatureInstaller {
500
+ isInstalled(code: FeatureCode): Promise<boolean>
501
+ markAsSkippedThisRun(code: FeatureCode): void
502
+ markAsPermanentlySkipped(code: FeatureCode): void
503
+ isMarkedAsSkipped(code: FeatureCode): boolean
504
+ getFeature<C extends FeatureCode>(code: C): FeatureMap[C]
505
+ areInstalled(codes: FeatureCode[]): Promise<boolean>
506
+ install(options: InstallFeatureOptions): Promise<FeatureInstallResponse>
507
+ getInstalledFeatures(): Promise<FeatureMap[keyof FeatureMap][]>
508
+ getFeatureDependencies<C extends FeatureCode>(
509
+ featureCode: C
510
+ ): FeatureDependency[]
511
+ getAllCodes(): FeatureCode[]
512
+ mapFeature<C extends FeatureCode>(code: C, feature: FeatureMap[C]): void
513
+ }
@@ -13,7 +13,7 @@ import DeployFeature from './deploy/DeployFeature'
13
13
  import ErrorFeature from './error/ErrorFeature'
14
14
  import EventFeature from './event/EventFeature'
15
15
  import EventContractFeature from './eventContract/EventContractFeature'
16
- import FeatureInstaller from './FeatureInstaller'
16
+ import FeatureInstaller, { FeatureInstallerImpl } from './FeatureInstaller'
17
17
  import { FeatureCode } from './features.types'
18
18
  import LogFeature from './log/LogFeature'
19
19
  import NodeFeature from './node/NodeFeature'
@@ -30,6 +30,7 @@ import TestFeature from './test/TestFeature'
30
30
  import ViewFeature from './view/ViewFeature'
31
31
  import VsCodeFeature from './vscode/VsCodeFeature'
32
32
  import WatchFeature from './watch/WatchFeature'
33
+
33
34
  export default class FeatureInstallerFactory {
34
35
  private static readonly features: any[] = [
35
36
  ErrorFeature,
@@ -81,21 +82,14 @@ export default class FeatureInstallerFactory {
81
82
  'permission',
82
83
  ]
83
84
 
84
- public static WithAllFeatures(options: {
85
- cwd: string
86
- serviceFactory: ServiceFactory
87
- storeFactory: StoreFactory
88
- featureInstaller?: FeatureInstaller
89
- ui: GraphicsInterface
90
- emitter: GlobalEmitter
91
- apiClientFactory: ApiClientFactory
92
- actionExecuter: ActionExecuter
93
- }): FeatureInstaller {
85
+ public static WithAllFeatures(
86
+ options: InstallerWithAllFeaturesOptions
87
+ ): FeatureInstaller {
94
88
  const { cwd, serviceFactory, storeFactory, ui, emitter, actionExecuter } =
95
89
  options
96
90
 
97
91
  const featureInstaller =
98
- options.featureInstaller ?? new FeatureInstaller(cwd, serviceFactory)
92
+ options.featureInstaller ?? new FeatureInstallerImpl(cwd, serviceFactory)
99
93
 
100
94
  const featureOptions: FeatureOptions = {
101
95
  cwd,
@@ -111,10 +105,20 @@ export default class FeatureInstallerFactory {
111
105
 
112
106
  this.features.forEach((Feature) => {
113
107
  const feature = new Feature(featureOptions)
114
-
115
108
  featureInstaller.mapFeature(feature.code, feature)
116
109
  })
117
110
 
118
111
  return featureInstaller
119
112
  }
120
113
  }
114
+
115
+ interface InstallerWithAllFeaturesOptions {
116
+ cwd: string
117
+ serviceFactory: ServiceFactory
118
+ storeFactory: StoreFactory
119
+ featureInstaller?: FeatureInstaller
120
+ ui: GraphicsInterface
121
+ emitter: GlobalEmitter
122
+ apiClientFactory: ApiClientFactory
123
+ actionExecuter: ActionExecuter
124
+ }
@@ -109,11 +109,8 @@ export default class OverrideActionDecorator implements FeatureAction {
109
109
  public execute = async (optionsArg: any) => {
110
110
  this.assertCommandIsNotBlocked()
111
111
 
112
- let { ...options } = optionsArg
113
-
114
- options = this.mixinOptionOverrides(options)
115
-
116
- let response = await this.childAction.execute(options)
112
+ const options = this.mixinOptionOverrides(optionsArg)
113
+ const response = await this.childAction.execute(options)
117
114
 
118
115
  return response
119
116
  }
@@ -157,6 +157,7 @@ export default class ListenAction extends AbstractAction<OptionsSchema> {
157
157
 
158
158
  private async fetchEventContracts(namespace?: string) {
159
159
  const eventStore = this.Store('event')
160
+
160
161
  const skill = await this.Store('skill').loadCurrentSkill()
161
162
 
162
163
  const namespacesForFetch =
@@ -8,7 +8,8 @@ const optionsSchema = buildSchema({
8
8
  description: 'Point your skill to different Mercury environments.',
9
9
  fields: {
10
10
  remote: {
11
- label: 'Where should remote point?',
11
+ label: 'Set remote',
12
+ hint: 'Start with developer and read more here: https://developer.spruce.bot/#/skills/index',
12
13
  type: 'select',
13
14
  isRequired: true,
14
15
  options: {
@@ -18,7 +18,6 @@ export default class SyncListenerAction extends AbstractAction<OptionsSchema> {
18
18
  public async execute() {
19
19
  const listeners = await this.Store('listener').loadListeners()
20
20
  const builder = new ListenerTemplateItemBuilder()
21
-
22
21
  const templateItems = builder.buildTemplateItems({
23
22
  listeners,
24
23
  cwd: this.cwd,
@@ -128,7 +128,9 @@ export default class NodeFeature<
128
128
  pkg.unset('main')
129
129
  pkg.unset('license')
130
130
 
131
- await this.Store('skill', { cwd }).setCurrentSkillsNamespace(options.name)
131
+ await this.Store('skill', {
132
+ cwd,
133
+ }).setCurrentSkillsNamespace(options.name)
132
134
 
133
135
  return {}
134
136
  }
@@ -134,9 +134,9 @@ export default class SkillFeature<
134
134
 
135
135
  public async afterPackageInstall(options: SkillFeatureOptions) {
136
136
  const destination = this.resolveDestination(options)
137
- await this.Store('skill', { cwd: destination }).setCurrentSkillsNamespace(
138
- options.name
139
- )
137
+ await this.Store('skill', {
138
+ cwd: destination,
139
+ }).setCurrentSkillsNamespace(options.name)
140
140
  return {}
141
141
  }
142
142
 
@@ -1,13 +1,17 @@
1
1
  import { eventResponseUtil } from '@sprucelabs/spruce-event-utils'
2
2
  import { namesUtil } from '@sprucelabs/spruce-skill-utils'
3
3
  import SpruceError from '../../../errors/SpruceError'
4
- import AbstractStore from '../../../stores/AbstractStore'
4
+ import AbstractStore, { StoreOptions } from '../../../stores/AbstractStore'
5
5
  import { CurrentSkill, RegisteredSkill } from '../../../types/cli.types'
6
6
 
7
7
  export default class SkillStore extends AbstractStore {
8
8
  public readonly name = 'skill'
9
9
  private static currentSkill?: CurrentSkill
10
10
 
11
+ public constructor(options: StoreOptions<SkillStoreOptions>) {
12
+ super(options)
13
+ }
14
+
11
15
  public static clearCurrentSkill() {
12
16
  this.currentSkill = undefined
13
17
  }
@@ -19,7 +23,7 @@ export default class SkillStore extends AbstractStore {
19
23
  const isRegisteringCurrentSkill =
20
24
  options?.isRegisteringCurrentSkill !== false
21
25
 
22
- isRegisteringCurrentSkill && this.assertInSkill()
26
+ isRegisteringCurrentSkill && (await this.assertInSkill())
23
27
 
24
28
  const { name, slug, description, isPublished } = values
25
29
  const client = await this.connectToApi()
@@ -43,7 +47,7 @@ export default class SkillStore extends AbstractStore {
43
47
  return skill
44
48
  }
45
49
 
46
- private assertInSkill() {
50
+ private async assertInSkill() {
47
51
  const isInstalled = this.Service('settings').isMarkedAsInstalled('skill')
48
52
 
49
53
  if (!isInstalled) {
@@ -56,7 +60,7 @@ export default class SkillStore extends AbstractStore {
56
60
  return SkillStore.currentSkill
57
61
  }
58
62
 
59
- this.assertInSkill()
63
+ await this.assertInSkill()
60
64
 
61
65
  const currentSkill = this.Service('auth').getCurrentSkill()
62
66
 
@@ -169,13 +173,14 @@ export default class SkillStore extends AbstractStore {
169
173
  }) {
170
174
  const client = await this.connectToApi()
171
175
 
172
- const response = await client.emit('list-skills::v2020_12_25', {
173
- payload: {
174
- ...query,
175
- },
176
- })
177
-
178
- const { skills } = eventResponseUtil.getFirstResponseOrThrow(response)
176
+ const [{ skills }] = await client.emitAndFlattenResponses(
177
+ 'list-skills::v2020_12_25',
178
+ {
179
+ payload: {
180
+ ...query,
181
+ },
182
+ }
183
+ )
179
184
 
180
185
  return skills
181
186
  }
@@ -191,3 +196,5 @@ export interface CreateSkill {
191
196
  export interface RegisterSkillOptions {
192
197
  isRegisteringCurrentSkill?: boolean
193
198
  }
199
+
200
+ export interface SkillStoreOptions {}
@@ -89,7 +89,7 @@ export default class WatchFeature extends AbstractFeature {
89
89
  const changes = this.changesSinceLastChange
90
90
  this.changesSinceLastChange = []
91
91
 
92
- await this.emitter.emit('watcher.did-detect-change', {
92
+ await this.emitter.emitAndFlattenResponses('watcher.did-detect-change', {
93
93
  changes,
94
94
  })
95
95
  }
@@ -28,6 +28,7 @@ export default class SpyInterface implements GraphicsInterface {
28
28
  private term?: TerminalInterface
29
29
  private startTime: number
30
30
  private promptTimeout?: any
31
+ private error?: Error
31
32
 
32
33
  public constructor() {
33
34
  this.startTime = new Date().getTime()
@@ -80,6 +81,10 @@ export default class SpyInterface implements GraphicsInterface {
80
81
  clearTimeout(this.promptTimeout)
81
82
  }
82
83
 
84
+ public setError(err: Error) {
85
+ this.error = err
86
+ }
87
+
83
88
  public getLastInvocation() {
84
89
  return this.invocations[this.invocations.length - 1]
85
90
  }
@@ -298,6 +303,11 @@ export default class SpyInterface implements GraphicsInterface {
298
303
  testUtil.log('waitForInput timeout reset because of new output.')
299
304
  }
300
305
  }
306
+
307
+ if (this.error) {
308
+ throw this.error
309
+ }
310
+
301
311
  await new Promise((resolve) => setTimeout(resolve, checkInterval))
302
312
  }
303
313
  }