@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.
- package/CHANGELOG.md +19 -0
- package/build/__tests__/behavioral/events/DifferentEventOptions.test.d.ts +16 -0
- package/build/__tests__/behavioral/events/DifferentEventOptions.test.js +105 -0
- package/build/__tests__/behavioral/events/DifferentEventOptions.test.js.map +1 -0
- package/build/__tests__/behavioral/events/KeepingEventsInSync.test.js.map +1 -1
- package/build/__tests__/behavioral/skill/RegisteringAGoSkill.test.d.ts +5 -0
- package/build/__tests__/behavioral/skill/RegisteringAGoSkill.test.js +41 -0
- package/build/__tests__/behavioral/skill/RegisteringAGoSkill.test.js.map +1 -0
- package/build/__tests__/behavioral/skill/UnregisteringASkill.test.d.ts +23 -0
- package/build/__tests__/behavioral/skill/UnregisteringASkill.test.js +143 -0
- package/build/__tests__/behavioral/skill/UnregisteringASkill.test.js.map +1 -0
- package/build/__tests__/support/EventFaker.d.ts +10 -2
- package/build/__tests__/support/EventFaker.js +49 -2
- package/build/__tests__/support/EventFaker.js.map +1 -1
- package/build/errors/SpruceError.js +1 -1
- package/build/errors/SpruceError.js.map +1 -1
- package/build/features/FeatureInstaller.d.ts +1 -1
- package/build/features/FeatureInstallerFactory.js +3 -0
- package/build/features/FeatureInstallerFactory.js.map +1 -1
- package/build/features/global/GlobalFeature.d.ts +21 -0
- package/build/features/global/GlobalFeature.js +21 -0
- package/build/features/global/GlobalFeature.js.map +1 -0
- package/build/features/global/actions/UnregisterSkillAction.d.ts +18 -0
- package/build/features/global/actions/UnregisterSkillAction.js +59 -0
- package/build/features/global/actions/UnregisterSkillAction.js.map +1 -0
- package/build/features/skill/stores/SkillStore.d.ts +1 -0
- package/build/features/skill/stores/SkillStore.js +3 -0
- package/build/features/skill/stores/SkillStore.js.map +1 -1
- package/build/widgets/terminalKit/TkTextWidget.js +3 -2
- package/build/widgets/terminalKit/TkTextWidget.js.map +1 -1
- package/package.json +4 -4
- package/src/__tests__/behavioral/events/DifferentEventOptions.test.ts +134 -0
- package/src/__tests__/behavioral/events/KeepingEventsInSync.test.ts +0 -1
- package/src/__tests__/behavioral/skill/RegisteringAGoSkill.test.ts +29 -0
- package/src/__tests__/behavioral/skill/UnregisteringASkill.test.ts +160 -0
- package/src/__tests__/support/EventFaker.ts +75 -4
- package/src/errors/SpruceError.ts +1 -1
- package/src/features/FeatureInstallerFactory.ts +3 -0
- package/src/features/global/GlobalFeature.ts +29 -0
- package/src/features/global/actions/UnregisterSkillAction.ts +67 -0
- package/src/features/skill/stores/SkillStore.ts +4 -0
- 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(
|
|
35
|
-
|
|
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
|
|
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 (
|
|
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
|
|
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
|
|