@sprucelabs/spruce-cli 29.0.0 → 29.1.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 (42) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/build/__tests__/behavioral/events/DifferentEventOptions.test.d.ts +16 -0
  3. package/build/__tests__/behavioral/events/DifferentEventOptions.test.js +105 -0
  4. package/build/__tests__/behavioral/events/DifferentEventOptions.test.js.map +1 -0
  5. package/build/__tests__/behavioral/events/KeepingEventsInSync.test.js.map +1 -1
  6. package/build/__tests__/behavioral/skill/RegisteringAGoSkill.test.d.ts +5 -0
  7. package/build/__tests__/behavioral/skill/RegisteringAGoSkill.test.js +41 -0
  8. package/build/__tests__/behavioral/skill/RegisteringAGoSkill.test.js.map +1 -0
  9. package/build/__tests__/behavioral/skill/UnregisteringASkill.test.d.ts +23 -0
  10. package/build/__tests__/behavioral/skill/UnregisteringASkill.test.js +143 -0
  11. package/build/__tests__/behavioral/skill/UnregisteringASkill.test.js.map +1 -0
  12. package/build/__tests__/support/EventFaker.d.ts +10 -2
  13. package/build/__tests__/support/EventFaker.js +49 -2
  14. package/build/__tests__/support/EventFaker.js.map +1 -1
  15. package/build/errors/SpruceError.js +1 -1
  16. package/build/errors/SpruceError.js.map +1 -1
  17. package/build/features/FeatureInstaller.d.ts +1 -1
  18. package/build/features/FeatureInstallerFactory.js +3 -0
  19. package/build/features/FeatureInstallerFactory.js.map +1 -1
  20. package/build/features/global/GlobalFeature.d.ts +21 -0
  21. package/build/features/global/GlobalFeature.js +21 -0
  22. package/build/features/global/GlobalFeature.js.map +1 -0
  23. package/build/features/global/actions/UnregisterSkillAction.d.ts +18 -0
  24. package/build/features/global/actions/UnregisterSkillAction.js +59 -0
  25. package/build/features/global/actions/UnregisterSkillAction.js.map +1 -0
  26. package/build/features/skill/stores/SkillStore.d.ts +1 -0
  27. package/build/features/skill/stores/SkillStore.js +3 -0
  28. package/build/features/skill/stores/SkillStore.js.map +1 -1
  29. package/build/widgets/terminalKit/TkTextWidget.js +3 -2
  30. package/build/widgets/terminalKit/TkTextWidget.js.map +1 -1
  31. package/package.json +4 -4
  32. package/src/__tests__/behavioral/events/DifferentEventOptions.test.ts +134 -0
  33. package/src/__tests__/behavioral/events/KeepingEventsInSync.test.ts +0 -1
  34. package/src/__tests__/behavioral/skill/RegisteringAGoSkill.test.ts +29 -0
  35. package/src/__tests__/behavioral/skill/UnregisteringASkill.test.ts +160 -0
  36. package/src/__tests__/support/EventFaker.ts +75 -4
  37. package/src/errors/SpruceError.ts +1 -1
  38. package/src/features/FeatureInstallerFactory.ts +3 -0
  39. package/src/features/global/GlobalFeature.ts +29 -0
  40. package/src/features/global/actions/UnregisterSkillAction.ts +67 -0
  41. package/src/features/skill/stores/SkillStore.ts +4 -0
  42. package/src/widgets/terminalKit/TkTextWidget.ts +3 -2
@@ -1,10 +1,68 @@
1
1
  import { SpruceSchemas } from '@sprucelabs/mercury-types'
2
- import { Organization } from '@sprucelabs/spruce-core-schemas'
2
+ import { Organization, Skill } from '@sprucelabs/spruce-core-schemas'
3
3
  import { eventFaker } from '@sprucelabs/spruce-test-fixtures'
4
4
  import { generateId } from '@sprucelabs/test-utils'
5
5
  import { ListPermContractsTargetAndPayload } from '../../features/permission/stores/PermissionStore'
6
6
 
7
7
  export default class EventFaker {
8
+ public async fakeUnregisterSkill(
9
+ cb?: (targetAndPayload: UnregisterSkillTargetAndPayload) => void
10
+ ) {
11
+ await eventFaker.on(
12
+ 'unregister-skill::v2020_12_25',
13
+ (targetAndPayload) => {
14
+ cb?.(targetAndPayload)
15
+ return {}
16
+ }
17
+ )
18
+ }
19
+ public async fakeRegisterSkill(
20
+ cb?: (targetAndPayload: RegisterSkillTargetAndPayload) => void | Skill
21
+ ) {
22
+ await eventFaker.on(
23
+ 'register-skill::v2020_12_25',
24
+ (targetAndPayload) => {
25
+ return {
26
+ skill: cb?.(targetAndPayload) ?? {
27
+ id: generateId(),
28
+ name: generateId(),
29
+ slug: generateId(),
30
+ apiKey: generateId(),
31
+ dateCreated: Date.now(),
32
+ creators: [],
33
+ },
34
+ }
35
+ }
36
+ )
37
+ }
38
+
39
+ public async fakeSyncPermissionContracts() {
40
+ await eventFaker.on('sync-permission-contracts::v2020_12_25', () => {
41
+ return {
42
+ contractRecords: [],
43
+ }
44
+ })
45
+ }
46
+ public async fakeRegisterEvents(cb?: () => void) {
47
+ await eventFaker.on('register-events::v2020_12_25', () => {
48
+ cb?.()
49
+ return {
50
+ fqens: [],
51
+ }
52
+ })
53
+ }
54
+ public async fakeGetEventContracts() {
55
+ await eventFaker.on('get-event-contracts::v2020_12_25', () => {
56
+ return {
57
+ contracts: [
58
+ {
59
+ id: generateId(),
60
+ eventSignatures: {},
61
+ },
62
+ ],
63
+ }
64
+ })
65
+ }
8
66
  public async fakeCreateOrganization(
9
67
  cb?: (
10
68
  targetAndPayload: CreateOrganizationTargetAndPayload
@@ -31,10 +89,14 @@ export default class EventFaker {
31
89
  }
32
90
  }
33
91
 
34
- public async fakeListSkills(cb?: () => void | ListSkill[]) {
35
- await eventFaker.on('list-skills::v2020_12_25', () => {
92
+ public async fakeListSkills(
93
+ cb?: (
94
+ targetAndPayload: ListSkillsTargetAndPayload
95
+ ) => void | ListSkill[]
96
+ ) {
97
+ await eventFaker.on('list-skills::v2020_12_25', (targetAndPayload) => {
36
98
  return {
37
- skills: cb?.() ?? [],
99
+ skills: cb?.(targetAndPayload) ?? [],
38
100
  }
39
101
  })
40
102
  }
@@ -81,3 +143,12 @@ export default class EventFaker {
81
143
  export type ListSkill = SpruceSchemas.Mercury.v2020_12_25.ListSkillsSkill
82
144
  export type CreateOrganizationTargetAndPayload =
83
145
  SpruceSchemas.Mercury.v2020_12_25.CreateOrganizationEmitTargetAndPayload
146
+
147
+ export type RegisterSkillTargetAndPayload =
148
+ SpruceSchemas.Mercury.v2020_12_25.RegisterSkillEmitTargetAndPayload
149
+
150
+ export type ListSkillsTargetAndPayload =
151
+ SpruceSchemas.Mercury.v2020_12_25.ListSkillsEmitTargetAndPayload
152
+
153
+ export type UnregisterSkillTargetAndPayload =
154
+ SpruceSchemas.Mercury.v2020_12_25.UnregisterSkillEmitTargetAndPayload
@@ -174,7 +174,7 @@ export default class SpruceError extends AbstractSpruceError<ErrorOptions> {
174
174
  break
175
175
 
176
176
  case 'SKILL_NOT_REGISTERED':
177
- message = `Dang! I can't continue until you register your skill! Run \`spruce login\` and then \`spruce register.skill\` to get the ball rolling!`
177
+ message = `Dang! I can't continue until you register your skill! Run \`spruce login\` and then \`spruce register\` to get the ball rolling!`
178
178
  break
179
179
 
180
180
  case 'NO_ORGANIZATIONS_FOUND':
@@ -16,6 +16,7 @@ import EventFeature from './event/EventFeature'
16
16
  import EventContractFeature from './eventContract/EventContractFeature'
17
17
  import FeatureInstaller, { FeatureInstallerImpl } from './FeatureInstaller'
18
18
  import { FeatureCode } from './features.types'
19
+ import GlobalFeature from './global/GlobalFeature'
19
20
  import LogFeature from './log/LogFeature'
20
21
  import NodeFeature from './node/NodeFeature'
21
22
  import OnboardFeature from './onboard/OnboardFeature'
@@ -57,6 +58,7 @@ export default class FeatureInstallerFactory {
57
58
  PolishFeature,
58
59
  PermissionFeature,
59
60
  AgentFeature,
61
+ GlobalFeature,
60
62
  ]
61
63
 
62
64
  public static readonly featureCodes: FeatureCode[] = [
@@ -83,6 +85,7 @@ export default class FeatureInstallerFactory {
83
85
  'polish',
84
86
  'permission',
85
87
  'agent',
88
+ 'global',
86
89
  ]
87
90
 
88
91
  public static WithAllFeatures(
@@ -0,0 +1,29 @@
1
+ import { diskUtil, NpmPackage } from '@sprucelabs/spruce-skill-utils'
2
+ import AbstractFeature, { FeatureDependency } from '../AbstractFeature'
3
+ import { FeatureCode } from '../features.types'
4
+
5
+ export default class GlobalFeature extends AbstractFeature {
6
+ public code: FeatureCode = 'global'
7
+ public nameReadable = 'Global'
8
+ public description =
9
+ 'Place for all global actions that affect your Spruce account (outside your profile).'
10
+ public dependencies: FeatureDependency[] = []
11
+ public _packageDependencies: NpmPackage[] = []
12
+
13
+ public actionsDir = diskUtil.resolvePath(__dirname, 'actions')
14
+ public scripts = {}
15
+
16
+ public async isInstalled(): Promise<boolean> {
17
+ return true
18
+ }
19
+ }
20
+
21
+ declare module '../../features/features.types' {
22
+ interface FeatureMap {
23
+ global: GlobalFeature
24
+ }
25
+
26
+ interface FeatureOptionsMap {
27
+ global: undefined
28
+ }
29
+ }
@@ -0,0 +1,67 @@
1
+ import { buildSchema } from '@sprucelabs/schema'
2
+ import { ListSkill } from '../../../__tests__/support/EventFaker'
3
+ import SpruceError from '../../../errors/SpruceError'
4
+ import AbstractAction from '../../AbstractAction'
5
+ import { ActionOptions, FeatureActionResponse } from '../../features.types'
6
+ import { SkillStore } from '../../skill/stores/SkillStore'
7
+
8
+ const optionsSchema = buildSchema({
9
+ id: 'unregisterSkill',
10
+ description: 'Unregister a skill from your account.',
11
+ fields: {},
12
+ })
13
+
14
+ type OptionsSchema = typeof optionsSchema
15
+
16
+ export default class UnregisterSkillAction extends AbstractAction<OptionsSchema> {
17
+ public optionsSchema: OptionsSchema = optionsSchema
18
+ public commandAliases = ['unregister.skill']
19
+ public invocationMessage = 'Unregistering skill... 🔧'
20
+ private skills: SkillStore
21
+
22
+ public constructor(options: ActionOptions) {
23
+ super(options)
24
+ this.skills = this.Store('skill')
25
+ }
26
+
27
+ public async execute(): Promise<FeatureActionResponse> {
28
+ const response: FeatureActionResponse = {}
29
+
30
+ const skills = await this.skills.fetchMySkills()
31
+ if (skills.length > 0) {
32
+ const skillId = await this.ui.prompt({
33
+ type: 'select',
34
+ isRequired: true,
35
+ options: {
36
+ choices: skills.map((skill) => this.skillToChoices(skill)),
37
+ },
38
+ })
39
+
40
+ const match = skills.find((s) => s.id === skillId)
41
+
42
+ const confirm = await this.ui.confirm(
43
+ `Are you sure you want to unregister the skill "${match?.name}"?`
44
+ )
45
+
46
+ if (confirm) {
47
+ await this.skills.unregisterSkill(skillId)
48
+ response.summaryLines = [`Unregistered ${match?.name}`]
49
+ } else {
50
+ response.summaryLines = ['Unregister cancelled.']
51
+ }
52
+ } else {
53
+ response.errors = [
54
+ new SpruceError({ code: 'NO_SKILLS_REGISTERED' }),
55
+ ]
56
+ }
57
+
58
+ return response
59
+ }
60
+
61
+ private skillToChoices(skill: ListSkill): { value: string; label: string } {
62
+ return {
63
+ value: skill.id,
64
+ label: `${skill.slug}: ${skill.name}`,
65
+ }
66
+ }
67
+ }
@@ -242,6 +242,10 @@ export default class SkillStoreImpl
242
242
  return this.fetchAllSkills({ shouldOnlyShowMine: true })
243
243
  }
244
244
 
245
+ public static setCurrentSkill(skill: CurrentSkill) {
246
+ this.currentSkill = skill
247
+ }
248
+
245
249
  public async fetchAllSkills(query?: {
246
250
  shouldOnlyShowMine?: boolean
247
251
  namespaces?: string[]
@@ -154,9 +154,10 @@ export default class TkTextWidget extends TkBaseWidget implements TextWidget {
154
154
  return segment
155
155
  }
156
156
 
157
- if ('{}[]()'.includes(segment)) {
157
+ if (segment.trim().length > 0) {
158
158
  // Terminal-kit drops single-character chunks when parsing ANSI
159
- // sequences, so pad with a zero-width space to keep braces visible.
159
+ // sequences, so pad with a zero-width space to keep visible
160
+ // single characters (digits, braces, etc.) from disappearing.
160
161
  return `${segment}​`
161
162
  }
162
163