@sprucelabs/spruce-cli 22.2.0 → 23.0.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 (145) hide show
  1. package/.eslintcache +1 -1
  2. package/build/.spruce/errors/errors.types.d.ts +4 -4
  3. package/build/.spruce/errors/options.types.d.ts +3 -3
  4. package/build/.spruce/errors/spruceCli/appControllerAlreadyExists.schema.d.ts +3 -0
  5. package/build/.spruce/errors/spruceCli/appControllerAlreadyExists.schema.js +12 -0
  6. package/build/.spruce/errors/spruceCli/appControllerAlreadyExists.schema.js.map +1 -0
  7. package/build/.spruce/schemas/schemas.types.d.ts +2 -4
  8. package/build/__tests__/behavioral/features/InstallingFeaturesDirectly.test.d.ts +17 -0
  9. package/build/__tests__/behavioral/features/InstallingFeaturesDirectly.test.js +142 -0
  10. package/build/__tests__/behavioral/features/InstallingFeaturesDirectly.test.js.map +1 -0
  11. package/build/__tests__/behavioral/onboard/StartingOnboarding.test.js +17 -7
  12. package/build/__tests__/behavioral/onboard/StartingOnboarding.test.js.map +1 -1
  13. package/build/__tests__/behavioral/schemas/HandlesRelatedSchemas.test.js +1 -1
  14. package/build/__tests__/behavioral/schemas/HandlesRelatedSchemas.test.js.map +1 -1
  15. package/build/__tests__/behavioral/schemas/UsingSchemasInCli.test.js +17 -7
  16. package/build/__tests__/behavioral/schemas/UsingSchemasInCli.test.js.map +1 -1
  17. package/build/__tests__/behavioral/tests/SelectingAnAbstractTestClass.test.js +1 -1
  18. package/build/__tests__/behavioral/tests/SelectingAnAbstractTestClass.test.js.map +1 -1
  19. package/build/__tests__/behavioral/views/{CreatingAnAppViewController.test.d.ts → CreatingAnAppController.test.d.ts} +9 -5
  20. package/build/__tests__/behavioral/views/{CreatingAnAppViewController.test.js → CreatingAnAppController.test.js} +63 -34
  21. package/build/__tests__/behavioral/views/CreatingAnAppController.test.js.map +1 -0
  22. package/build/__tests__/behavioral/views/CreatingViewControllers.test.d.ts +5 -0
  23. package/build/__tests__/behavioral/views/CreatingViewControllers.test.js +37 -0
  24. package/build/__tests__/behavioral/views/CreatingViewControllers.test.js.map +1 -0
  25. package/build/__tests__/behavioral/views/KeepingViewsInSync.test.d.ts +1 -0
  26. package/build/__tests__/behavioral/views/KeepingViewsInSync.test.js +14 -0
  27. package/build/__tests__/behavioral/views/KeepingViewsInSync.test.js.map +1 -1
  28. package/build/__tests__/behavioral/watchers/WatchingForChanges.test.js +5 -10
  29. package/build/__tests__/behavioral/watchers/WatchingForChanges.test.js.map +1 -1
  30. package/build/__tests__/implementation/ArgParser.test.js +17 -7
  31. package/build/__tests__/implementation/ArgParser.test.js.map +1 -1
  32. package/build/__tests__/implementation/BulkImporting.test.js +17 -7
  33. package/build/__tests__/implementation/BulkImporting.test.js.map +1 -1
  34. package/build/__tests__/implementation/CommanderCommandResultMapper.test.js +17 -7
  35. package/build/__tests__/implementation/CommanderCommandResultMapper.test.js.map +1 -1
  36. package/build/__tests__/implementation/EventContractCleanerUtil.test.js +17 -7
  37. package/build/__tests__/implementation/EventContractCleanerUtil.test.js.map +1 -1
  38. package/build/__tests__/implementation/FeaturesUtil.test.js +17 -7
  39. package/build/__tests__/implementation/FeaturesUtil.test.js.map +1 -1
  40. package/build/__tests__/implementation/JestJsonParser.test.js +17 -7
  41. package/build/__tests__/implementation/JestJsonParser.test.js.map +1 -1
  42. package/build/__tests__/implementation/SchemaValueTypeWriter.test.js +1 -1
  43. package/build/__tests__/implementation/SchemaValueTypeWriter.test.js.map +1 -1
  44. package/build/__tests__/implementation/TerminalInterface.test.js +17 -7
  45. package/build/__tests__/implementation/TerminalInterface.test.js.map +1 -1
  46. package/build/errors/SpruceError.js +2 -2
  47. package/build/errors/SpruceError.js.map +1 -1
  48. package/build/errors/{appViewControllerAlreadyExists.builder.js → appControllerAlreadyExists.builder.js} +2 -2
  49. package/build/errors/appControllerAlreadyExists.builder.js.map +1 -0
  50. package/build/features/cache/CacheFeature.d.ts +8 -5
  51. package/build/features/cache/CacheFeature.js.map +1 -1
  52. package/build/features/conversation/ConversationFeature.d.ts +8 -5
  53. package/build/features/conversation/ConversationFeature.js.map +1 -1
  54. package/build/features/dependencies/DependencyFeature.d.ts +8 -5
  55. package/build/features/dependencies/DependencyFeature.js.map +1 -1
  56. package/build/features/deploy/DeployFeature.d.ts +8 -5
  57. package/build/features/deploy/DeployFeature.js.map +1 -1
  58. package/build/features/error/ErrorFeature.d.ts +8 -8
  59. package/build/features/error/ErrorFeature.js.map +1 -1
  60. package/build/features/eventContract/EventContractFeature.d.ts +8 -5
  61. package/build/features/eventContract/EventContractFeature.js.map +1 -1
  62. package/build/features/onboard/OnboardFeature.d.ts +8 -5
  63. package/build/features/onboard/OnboardFeature.js.map +1 -1
  64. package/build/features/organization/OrganizationFeature.d.ts +3 -0
  65. package/build/features/permission/PermissionFeature.d.ts +3 -0
  66. package/build/features/person/PersonFeature.d.ts +3 -0
  67. package/build/features/polish/PolishFeature.d.ts +3 -0
  68. package/build/features/sandbox/SandboxFeature.d.ts +8 -5
  69. package/build/features/sandbox/SandboxFeature.js.map +1 -1
  70. package/build/features/skill/actions/BootAction.d.ts +9 -9
  71. package/build/features/skill/actions/BootAction.js.map +1 -1
  72. package/build/features/skill/actions/InstallFeatureAction.d.ts +37 -0
  73. package/build/features/skill/actions/InstallFeatureAction.js +80 -0
  74. package/build/features/skill/actions/InstallFeatureAction.js.map +1 -0
  75. package/build/features/store/StoreFeature.d.ts +8 -5
  76. package/build/features/store/StoreFeature.js.map +1 -1
  77. package/build/features/test/TestFeature.d.ts +8 -5
  78. package/build/features/test/TestFeature.js.map +1 -1
  79. package/build/features/validateAndNormalize.utility.js.map +1 -1
  80. package/build/features/view/ViewFeature.d.ts +8 -8
  81. package/build/features/view/ViewFeature.js.map +1 -1
  82. package/build/features/view/actions/CreateAppAction.d.ts +1 -0
  83. package/build/features/view/actions/CreateAppAction.js +4 -3
  84. package/build/features/view/actions/CreateAppAction.js.map +1 -1
  85. package/build/features/view/actions/SyncAction.js +6 -6
  86. package/build/features/view/actions/SyncAction.js.map +1 -1
  87. package/build/features/view/writers/ViewWriter.d.ts +2 -1
  88. package/build/features/view/writers/ViewWriter.js +15 -8
  89. package/build/features/view/writers/ViewWriter.js.map +1 -1
  90. package/build/features/vscode/VsCodeFeature.d.ts +8 -5
  91. package/build/features/vscode/VsCodeFeature.js.map +1 -1
  92. package/build/features/watch/WatchFeature.js +1 -2
  93. package/build/features/watch/WatchFeature.js.map +1 -1
  94. package/build/tests/AbstractCliTest.js +17 -7
  95. package/build/tests/AbstractCliTest.js.map +1 -1
  96. package/build/tests/cleanTestData.js +17 -7
  97. package/build/tests/cleanTestData.js.map +1 -1
  98. package/build/utilities/introspection.utility.js +17 -7
  99. package/build/utilities/introspection.utility.js.map +1 -1
  100. package/junit.xml +8 -1773
  101. package/package.json +30 -30
  102. package/src/.spruce/errors/errors.types.ts +4 -4
  103. package/src/.spruce/errors/options.types.ts +3 -3
  104. package/src/.spruce/errors/spruceCli/appControllerAlreadyExists.schema.ts +16 -0
  105. package/src/.spruce/schemas/schemas.types.ts +1 -1
  106. package/src/__tests__/behavioral/features/InstallingFeaturesDirectly.test.ts +149 -0
  107. package/src/__tests__/behavioral/schemas/HandlesRelatedSchemas.test.ts +1 -1
  108. package/src/__tests__/behavioral/tests/SelectingAnAbstractTestClass.test.ts +1 -1
  109. package/src/__tests__/behavioral/views/{CreatingAnAppViewController.test.ts → CreatingAnAppController.test.ts} +57 -25
  110. package/src/__tests__/behavioral/views/CreatingViewControllers.test.ts +28 -0
  111. package/src/__tests__/behavioral/views/KeepingViewsInSync.test.ts +16 -0
  112. package/src/__tests__/behavioral/watchers/WatchingForChanges.test.ts +6 -11
  113. package/src/__tests__/implementation/SchemaValueTypeWriter.test.ts +1 -1
  114. package/src/errors/SpruceError.ts +2 -2
  115. package/src/errors/{appViewControllerAlreadyExists.builder.ts → appControllerAlreadyExists.builder.ts} +1 -1
  116. package/src/features/cache/CacheFeature.ts +10 -6
  117. package/src/features/conversation/ConversationFeature.ts +10 -6
  118. package/src/features/dependencies/DependencyFeature.ts +10 -6
  119. package/src/features/deploy/DeployFeature.ts +10 -6
  120. package/src/features/error/ErrorFeature.ts +10 -10
  121. package/src/features/eventContract/EventContractFeature.ts +10 -6
  122. package/src/features/onboard/OnboardFeature.ts +10 -6
  123. package/src/features/organization/OrganizationFeature.ts +4 -0
  124. package/src/features/permission/PermissionFeature.ts +4 -0
  125. package/src/features/person/PersonFeature.ts +4 -0
  126. package/src/features/polish/PolishFeature.ts +4 -0
  127. package/src/features/sandbox/SandboxFeature.ts +10 -6
  128. package/src/features/skill/actions/BootAction.ts +11 -11
  129. package/src/features/skill/actions/InstallFeatureAction.ts +96 -0
  130. package/src/features/store/StoreFeature.ts +10 -6
  131. package/src/features/test/TestFeature.ts +10 -6
  132. package/src/features/validateAndNormalize.utility.ts +2 -1
  133. package/src/features/view/ViewFeature.ts +10 -10
  134. package/src/features/view/actions/CreateAppAction.ts +8 -4
  135. package/src/features/view/actions/SyncAction.ts +12 -8
  136. package/src/features/view/writers/ViewWriter.ts +34 -9
  137. package/src/features/vscode/VsCodeFeature.ts +9 -6
  138. package/src/features/watch/WatchFeature.ts +2 -3
  139. package/build/.spruce/errors/spruceCli/appViewControllerAlreadyExists.schema.d.ts +0 -3
  140. package/build/.spruce/errors/spruceCli/appViewControllerAlreadyExists.schema.js +0 -12
  141. package/build/.spruce/errors/spruceCli/appViewControllerAlreadyExists.schema.js.map +0 -1
  142. package/build/__tests__/behavioral/views/CreatingAnAppViewController.test.js.map +0 -1
  143. package/build/errors/appViewControllerAlreadyExists.builder.js.map +0 -1
  144. package/src/.spruce/errors/spruceCli/appViewControllerAlreadyExists.schema.ts +0 -16
  145. /package/build/errors/{appViewControllerAlreadyExists.builder.d.ts → appControllerAlreadyExists.builder.d.ts} +0 -0
@@ -1,7 +1,7 @@
1
1
  import { buildErrorSchema } from '@sprucelabs/schema'
2
2
 
3
3
  export default buildErrorSchema({
4
- id: 'appViewControllerAlreadyExists',
4
+ id: 'appControllerAlreadyExists',
5
5
  name: 'App view controller already exists',
6
6
  fields: {},
7
7
  })
@@ -2,12 +2,6 @@ import { diskUtil } from '@sprucelabs/spruce-skill-utils'
2
2
  import AbstractFeature from '../AbstractFeature'
3
3
  import { FeatureCode } from '../features.types'
4
4
 
5
- declare module '../../features/features.types' {
6
- interface FeatureMap {
7
- cache: CacheFeature
8
- }
9
- }
10
-
11
5
  export default class CacheFeature extends AbstractFeature {
12
6
  public description = 'Caching for all things Sprucebot.'
13
7
  public code: FeatureCode = 'cache'
@@ -18,3 +12,13 @@ export default class CacheFeature extends AbstractFeature {
18
12
  return true
19
13
  }
20
14
  }
15
+
16
+ declare module '../../features/features.types' {
17
+ interface FeatureMap {
18
+ cache: CacheFeature
19
+ }
20
+
21
+ interface FeatureOptionsMap {
22
+ cache: undefined
23
+ }
24
+ }
@@ -7,12 +7,6 @@ import AbstractFeature, {
7
7
  } from '../AbstractFeature'
8
8
  import { FeatureCode } from '../features.types'
9
9
 
10
- declare module '../../features/features.types' {
11
- interface FeatureMap {
12
- conversation: ConversationFeature
13
- }
14
- }
15
-
16
10
  export default class ConversationFeature extends AbstractFeature {
17
11
  public nameReadable = 'Conversation'
18
12
  public code: FeatureCode = 'conversation'
@@ -68,3 +62,13 @@ export default class ConversationFeature extends AbstractFeature {
68
62
  return this.Writer('conversation').writePlugin(this.cwd)
69
63
  }
70
64
  }
65
+
66
+ declare module '../../features/features.types' {
67
+ interface FeatureMap {
68
+ conversation: ConversationFeature
69
+ }
70
+
71
+ interface FeatureOptionsMap {
72
+ conversation: undefined
73
+ }
74
+ }
@@ -2,12 +2,6 @@ import { diskUtil } from '@sprucelabs/spruce-skill-utils'
2
2
  import AbstractFeature, { FeatureDependency } from '../AbstractFeature'
3
3
  import { FeatureCode } from '../features.types'
4
4
 
5
- declare module '../../features/features.types' {
6
- interface FeatureMap {
7
- dependency: DependencyFeature
8
- }
9
- }
10
-
11
5
  export default class DependencyFeature extends AbstractFeature {
12
6
  public description = 'Tell me which skills you depend on.'
13
7
  public code: FeatureCode = 'dependency'
@@ -25,3 +19,13 @@ export default class DependencyFeature extends AbstractFeature {
25
19
  return this.features.isInstalled('skill')
26
20
  }
27
21
  }
22
+
23
+ declare module '../../features/features.types' {
24
+ interface FeatureMap {
25
+ dependency: DependencyFeature
26
+ }
27
+
28
+ interface FeatureOptionsMap {
29
+ dependency: undefined
30
+ }
31
+ }
@@ -5,12 +5,6 @@ import AbstractFeature, {
5
5
  } from '../AbstractFeature'
6
6
  import { FeatureCode } from '../features.types'
7
7
 
8
- declare module '../../features/features.types' {
9
- interface FeatureMap {
10
- deploy: DeployFeature
11
- }
12
- }
13
-
14
8
  export default class DeployFeature extends AbstractFeature {
15
9
  public description = 'Deploy your skill with ease.'
16
10
  public code: FeatureCode = 'deploy'
@@ -35,3 +29,13 @@ export default class DeployFeature extends AbstractFeature {
35
29
  }
36
30
  }
37
31
  }
32
+
33
+ declare module '../../features/features.types' {
34
+ interface FeatureMap {
35
+ deploy: DeployFeature
36
+ }
37
+
38
+ interface FeatureOptionsMap {
39
+ deploy: undefined
40
+ }
41
+ }
@@ -7,16 +7,6 @@ import AbstractFeature, {
7
7
  } from '../AbstractFeature'
8
8
  import { FeatureCode } from '../features.types'
9
9
 
10
- declare module '../../features/features.types' {
11
- interface FeatureMap {
12
- error: ErrorFeature
13
- }
14
-
15
- interface FeatureOptionsMap {
16
- error: undefined
17
- }
18
- }
19
-
20
10
  export default class ErrorFeature extends AbstractFeature {
21
11
  public nameReadable = 'error handling'
22
12
  public description =
@@ -102,3 +92,13 @@ export default class ErrorFeature extends AbstractFeature {
102
92
  return this.Writer('error').writePlugin(this.cwd)
103
93
  }
104
94
  }
95
+
96
+ declare module '../../features/features.types' {
97
+ interface FeatureMap {
98
+ error: ErrorFeature
99
+ }
100
+
101
+ interface FeatureOptionsMap {
102
+ error: undefined
103
+ }
104
+ }
@@ -3,12 +3,6 @@ import { FileDescription } from '../../types/cli.types'
3
3
  import AbstractFeature, { FeatureDependency } from '../AbstractFeature'
4
4
  import { FeatureCode } from '../features.types'
5
5
 
6
- declare module '../../features/features.types' {
7
- interface FeatureMap {
8
- eventContract: EventContractFeature
9
- }
10
- }
11
-
12
6
  export default class EventContractFeature extends AbstractFeature {
13
7
  public code: FeatureCode = 'eventContract'
14
8
  public nameReadable = 'Event Contract'
@@ -22,3 +16,13 @@ export default class EventContractFeature extends AbstractFeature {
22
16
 
23
17
  public isInstalled = async () => true
24
18
  }
19
+
20
+ declare module '../../features/features.types' {
21
+ interface FeatureMap {
22
+ eventContract: EventContractFeature
23
+ }
24
+
25
+ interface FeatureOptionsMap {
26
+ eventContract: undefined
27
+ }
28
+ }
@@ -9,12 +9,6 @@ import { FeatureCode } from '../features.types'
9
9
  import ScriptLoader from './ScriptLoader'
10
10
  import OnboardingStore from './stores/OnboardingStore'
11
11
 
12
- declare module '../../features/features.types' {
13
- interface FeatureMap {
14
- onboard: OnboardFeature
15
- }
16
- }
17
-
18
12
  export default class OnboardFeature extends AbstractFeature {
19
13
  public code: FeatureCode = 'onboard'
20
14
  public nameReadable = 'Onboard'
@@ -150,3 +144,13 @@ export default class OnboardFeature extends AbstractFeature {
150
144
  return isExpectedCommand
151
145
  }
152
146
  }
147
+
148
+ declare module '../../features/features.types' {
149
+ interface FeatureMap {
150
+ onboard: OnboardFeature
151
+ }
152
+
153
+ interface FeatureOptionsMap {
154
+ onboard: undefined
155
+ }
156
+ }
@@ -25,4 +25,8 @@ declare module '../../features/features.types' {
25
25
  interface FeatureMap {
26
26
  organization: OrganizationFeature
27
27
  }
28
+
29
+ interface FeatureOptionsMap {
30
+ organization: undefined
31
+ }
28
32
  }
@@ -81,4 +81,8 @@ declare module '../../features/features.types' {
81
81
  interface FeatureMap {
82
82
  permission: PermissionFeature
83
83
  }
84
+
85
+ interface FeatureOptionsMap {
86
+ permission: undefined
87
+ }
84
88
  }
@@ -20,4 +20,8 @@ declare module '../../features/features.types' {
20
20
  interface FeatureMap {
21
21
  person: PersonFeature
22
22
  }
23
+
24
+ interface FeatureOptionsMap {
25
+ person: undefined
26
+ }
23
27
  }
@@ -30,4 +30,8 @@ declare module '../../features/features.types' {
30
30
  interface FeatureMap {
31
31
  polish: PolishFeature
32
32
  }
33
+
34
+ interface FeatureOptionsMap {
35
+ polish: undefined
36
+ }
33
37
  }
@@ -3,12 +3,6 @@ import uiUtil from '../../utilities/ui.utility'
3
3
  import AbstractFeature, { FeatureDependency } from '../AbstractFeature'
4
4
  import { ActionOptions, FeatureCode } from '../features.types'
5
5
 
6
- declare module '../../features/features.types' {
7
- interface FeatureMap {
8
- sandbox: SandboxFeature
9
- }
10
- }
11
-
12
6
  export default class SandboxFeature extends AbstractFeature {
13
7
  public code: FeatureCode = 'sandbox'
14
8
  public nameReadable = 'Sandbox'
@@ -45,3 +39,13 @@ export default class SandboxFeature extends AbstractFeature {
45
39
  })
46
40
  }
47
41
  }
42
+
43
+ declare module '../../features/features.types' {
44
+ interface FeatureMap {
45
+ sandbox: SandboxFeature
46
+ }
47
+
48
+ interface FeatureOptionsMap {
49
+ sandbox: undefined
50
+ }
51
+ }
@@ -5,17 +5,6 @@ import CommandService from '../../../services/CommandService'
5
5
  import AbstractAction from '../../AbstractAction'
6
6
  import { FeatureActionResponse } from '../../features.types'
7
7
 
8
- type OptionsSchema = SpruceSchemas.SpruceCli.v2020_07_22.BootSkillOptionsSchema
9
- type Options = SpruceSchemas.SpruceCli.v2020_07_22.BootSkillOptions
10
-
11
- export interface BootMeta {
12
- kill: () => void
13
- pid: number
14
- promise: Promise<void>
15
- isBooted: boolean
16
- bootPromise: Promise<void>
17
- }
18
-
19
8
  export default class BootAction extends AbstractAction<OptionsSchema> {
20
9
  public optionsSchema: OptionsSchema = bootSkillOptionsSchema
21
10
  public commandAliases = ['boot']
@@ -125,3 +114,14 @@ export default class BootAction extends AbstractAction<OptionsSchema> {
125
114
  return null
126
115
  }
127
116
  }
117
+
118
+ type OptionsSchema = SpruceSchemas.SpruceCli.v2020_07_22.BootSkillOptionsSchema
119
+ type Options = SpruceSchemas.SpruceCli.v2020_07_22.BootSkillOptions
120
+
121
+ export interface BootMeta {
122
+ kill: () => void
123
+ pid: number
124
+ promise: Promise<void>
125
+ isBooted: boolean
126
+ bootPromise: Promise<void>
127
+ }
@@ -0,0 +1,96 @@
1
+ import { buildSchema, SchemaValues } from '@sprucelabs/schema'
2
+ import { SelectChoice } from '@sprucelabs/spruce-core-schemas'
3
+ import AbstractAction from '../../AbstractAction'
4
+ import { FeatureActionResponse, FeatureCode } from '../../features.types'
5
+
6
+ export default class InstallFeatureAction extends AbstractAction<OptionsSchema> {
7
+ public optionsSchema = optionsSchema
8
+ public invocationMessage = 'Installing a feature... 🚀'
9
+ public commandAliases = ['install.feature']
10
+
11
+ public async execute(
12
+ options: InstallFeatureActionOptions
13
+ ): Promise<FeatureActionResponse> {
14
+ let { code } = options ?? {}
15
+
16
+ if (!code) {
17
+ const choices: SelectChoice[] = await this.buildFeatureChoices()
18
+
19
+ if (!choices.length) {
20
+ return {
21
+ summaryLines: [
22
+ 'Nothing to install, you have already installed everything!',
23
+ ],
24
+ }
25
+ }
26
+
27
+ code = await this.promptForFeature(choices)
28
+ }
29
+
30
+ this.ui.startLoading('Installing feature...')
31
+
32
+ const results = await this.features.install({
33
+ features: [{ code: code as any }],
34
+ })
35
+
36
+ return results
37
+ }
38
+
39
+ private async promptForFeature(choices: SelectChoice[]) {
40
+ return await this.ui.prompt({
41
+ type: 'select',
42
+ label: 'Which feature do you want to install?',
43
+ isRequired: true,
44
+ options: {
45
+ choices,
46
+ },
47
+ })
48
+ }
49
+
50
+ private async buildFeatureChoices() {
51
+ const choices: SelectChoice[] = []
52
+
53
+ for (const key in features) {
54
+ const isInstalled = await this.features.isInstalled(
55
+ key as FeatureCode
56
+ )
57
+ if (!isInstalled) {
58
+ choices.push({
59
+ label: features[key as keyof typeof features],
60
+ value: key,
61
+ })
62
+ }
63
+ }
64
+ return choices
65
+ }
66
+ }
67
+
68
+ const features = {
69
+ error: 'Errors',
70
+ event: 'Events',
71
+ schema: 'Schemas',
72
+ store: 'Stores (including database support)',
73
+ test: 'Tests',
74
+ view: 'Views',
75
+ }
76
+
77
+ const allFeatureChoices: SelectChoice[] = Object.keys(features).map((key) => ({
78
+ label: features[key as keyof typeof features],
79
+ value: key,
80
+ }))
81
+
82
+ const optionsSchema = buildSchema({
83
+ id: 'installFeature',
84
+ fields: {
85
+ code: {
86
+ type: 'select',
87
+ label: 'Feature to install',
88
+ options: {
89
+ choices: allFeatureChoices,
90
+ },
91
+ },
92
+ },
93
+ })
94
+
95
+ type OptionsSchema = typeof optionsSchema
96
+ export type InstallFeatureActionOptions = SchemaValues<OptionsSchema>
@@ -6,12 +6,6 @@ import AbstractFeature, {
6
6
  } from '../AbstractFeature'
7
7
  import { FeatureCode } from '../features.types'
8
8
 
9
- declare module '../../features/features.types' {
10
- interface FeatureMap {
11
- store: StoreFeature
12
- }
13
- }
14
-
15
9
  export default class StoreFeature extends AbstractFeature {
16
10
  public nameReadable = 'Data Stores'
17
11
  public description = 'For working with remote places of storage.'
@@ -87,3 +81,13 @@ export default class StoreFeature extends AbstractFeature {
87
81
  }
88
82
  }
89
83
  }
84
+
85
+ declare module '../../features/features.types' {
86
+ interface FeatureMap {
87
+ store: StoreFeature
88
+ }
89
+
90
+ interface FeatureOptionsMap {
91
+ store: undefined
92
+ }
93
+ }
@@ -8,12 +8,6 @@ import AbstractFeature, { FeatureDependency } from '../AbstractFeature'
8
8
  import ParentTestFinder from '../error/ParentTestFinder'
9
9
  import { FeatureCode } from '../features.types'
10
10
 
11
- declare module '../../features/features.types' {
12
- interface FeatureMap {
13
- test: TestFeature
14
- }
15
- }
16
-
17
11
  export interface ParentClassCandidate {
18
12
  name: string
19
13
  label: string
@@ -149,3 +143,13 @@ export default class TestFeature extends AbstractFeature {
149
143
  return candidates
150
144
  }
151
145
  }
146
+
147
+ declare module '../../features/features.types' {
148
+ interface FeatureMap {
149
+ test: TestFeature
150
+ }
151
+
152
+ interface FeatureOptionsMap {
153
+ test: undefined
154
+ }
155
+ }
@@ -3,6 +3,7 @@ import {
3
3
  normalizeSchemaValues,
4
4
  Schema,
5
5
  SchemaPartialValues,
6
+ SchemaValues,
6
7
  SchemaValuesWithDefaults,
7
8
  validateSchemaValues,
8
9
  } from '@sprucelabs/schema'
@@ -19,7 +20,7 @@ const validateAndNormalizer = {
19
20
  const values = {
20
21
  ...defaultSchemaValues(schema),
21
22
  ...this.stripUndefined(options),
22
- } as SchemaPartialValues<S, false>
23
+ } as SchemaValues<S>
23
24
 
24
25
  validateSchemaValues(schema, values, {})
25
26
 
@@ -3,16 +3,6 @@ import { NpmPackage } from '../../types/cli.types'
3
3
  import AbstractFeature, { FeatureDependency } from '../AbstractFeature'
4
4
  import { ActionOptions, FeatureCode } from '../features.types'
5
5
 
6
- declare module '../../features/features.types' {
7
- interface FeatureMap {
8
- view: ViewFeature
9
- }
10
-
11
- interface FeatureOptionsMap {
12
- view: undefined
13
- }
14
- }
15
-
16
6
  export default class ViewFeature extends AbstractFeature {
17
7
  public nameReadable = 'views'
18
8
  public description = 'Views: Create views using the Heartwood framework.'
@@ -98,3 +88,13 @@ export default class ViewFeature extends AbstractFeature {
98
88
  return { files }
99
89
  }
100
90
  }
91
+
92
+ declare module '../../features/features.types' {
93
+ interface FeatureMap {
94
+ view: ViewFeature
95
+ }
96
+
97
+ interface FeatureOptionsMap {
98
+ view: undefined
99
+ }
100
+ }
@@ -6,10 +6,16 @@ import { FeatureActionResponse } from '../../features.types'
6
6
  export default class CreateAppAction extends AbstractAction<OptionsSchema> {
7
7
  public optionsSchema = optionsSchema
8
8
  public invocationMessage = 'Creating new app view controller... '
9
+ public readonly commandAliases = ['create.avc', 'create.app']
9
10
 
10
11
  public async execute(): Promise<FeatureActionResponse> {
11
12
  const writer = this.Writer('view', {})
12
- const files = await writer.writeAppViewController(this.cwd)
13
+ const id = await this.Store('skill').loadCurrentSkillsNamespace()
14
+ const files = await writer.writeAppController(
15
+ this.cwd,
16
+ id.toLocaleLowerCase(),
17
+ id
18
+ )
13
19
 
14
20
  const results = await this.Action('view', 'sync').execute({})
15
21
  const merged = actionUtil.mergeActionResults(
@@ -19,14 +25,12 @@ export default class CreateAppAction extends AbstractAction<OptionsSchema> {
19
25
  results
20
26
  )
21
27
 
22
- debugger
23
-
24
28
  return merged
25
29
  }
26
30
  }
27
31
 
28
32
  const optionsSchema = buildSchema({
29
- id: 'createAppViewControllerOptions',
33
+ id: 'createAppControllerOptions',
30
34
  fields: {},
31
35
  })
32
36
 
@@ -19,7 +19,7 @@ export default class SyncAction extends AbstractAction<OptionsSchema> {
19
19
  public async execute(): Promise<FeatureActionResponse> {
20
20
  const targetDir = diskUtil.resolvePath(this.cwd, 'src')
21
21
  const matches = await globby(
22
- ['**/*.svc.ts', '**/*.vc.ts', '**/*.view.plugin.ts', '**/*.avc.ts'],
22
+ ['**/*.svc.ts', '**/*.vc.ts', '**/*.view.plugin.ts', '**/*.ac.ts'],
23
23
  {
24
24
  cwd: targetDir,
25
25
  }
@@ -39,8 +39,12 @@ export default class SyncAction extends AbstractAction<OptionsSchema> {
39
39
 
40
40
  introspect.forEach(({ classes }) => {
41
41
  for (const thisClass of classes) {
42
- const { vc, svc, plugin, avc } =
43
- this.mapIntrospectedClassToTemplateItem(thisClass)
42
+ const {
43
+ vc,
44
+ svc,
45
+ plugin,
46
+ ac: avc,
47
+ } = this.mapIntrospectedClassToTemplateItem(thisClass)
44
48
 
45
49
  if (vc) {
46
50
  vcTemplateItems.push(vc)
@@ -77,7 +81,7 @@ export default class SyncAction extends AbstractAction<OptionsSchema> {
77
81
  vc?: VcTemplateItem
78
82
  svc?: VcTemplateItem
79
83
  plugin?: ViewControllerPluginItem
80
- avc?: VcTemplateItem
84
+ ac?: VcTemplateItem
81
85
  } {
82
86
  const item = {
83
87
  id: c.staticProperties.id,
@@ -87,13 +91,13 @@ export default class SyncAction extends AbstractAction<OptionsSchema> {
87
91
 
88
92
  let vc: VcTemplateItem | undefined
89
93
  let svc: VcTemplateItem | undefined
90
- let avc: VcTemplateItem | undefined
94
+ let ac: VcTemplateItem | undefined
91
95
  let plugin: ViewControllerPluginItem | undefined
92
96
 
93
97
  if (c.classPath.endsWith('.svc.ts')) {
94
98
  svc = item
95
- } else if (c.classPath.endsWith('avc.ts')) {
96
- avc = item
99
+ } else if (c.classPath.endsWith('ac.ts')) {
100
+ ac = item
97
101
  } else if (c.classPath.endsWith('view.plugin.ts')) {
98
102
  const nameCamel = c.classPath.match(/([^/]+).view.plugin.ts$/)![1]
99
103
  plugin = { ...item, nameCamel }
@@ -101,7 +105,7 @@ export default class SyncAction extends AbstractAction<OptionsSchema> {
101
105
  vc = item
102
106
  }
103
107
 
104
- return { svc, vc, plugin, avc }
108
+ return { svc, vc, plugin, ac }
105
109
  }
106
110
  }
107
111
 
@@ -26,8 +26,13 @@ export default class ViewWriter extends AbstractWriter {
26
26
  }
27
27
 
28
28
  public async writeCombinedViewsFile(cwd: string, options: ViewsOptions) {
29
- let { vcTemplateItems, svcTemplateItems, viewPluginItems, ...rest } =
30
- options
29
+ let {
30
+ vcTemplateItems,
31
+ svcTemplateItems,
32
+ viewPluginItems,
33
+ appTemplateItem,
34
+ ...rest
35
+ } = options
31
36
 
32
37
  const destinationDir = diskUtil.resolveHashSprucePath(cwd, 'views')
33
38
  const destination = diskUtil.resolvePath(destinationDir, 'views.ts')
@@ -47,10 +52,18 @@ export default class ViewWriter extends AbstractWriter {
47
52
  destinationDir
48
53
  )
49
54
 
55
+ if (appTemplateItem) {
56
+ appTemplateItem = this.makePathRelative(
57
+ appTemplateItem,
58
+ destinationDir
59
+ )
60
+ }
61
+
50
62
  const contents = this.templates.views({
51
63
  vcTemplateItems,
52
64
  svcTemplateItems,
53
65
  viewPluginItems,
66
+ appTemplateItem,
54
67
  ...rest,
55
68
  })
56
69
 
@@ -66,12 +79,20 @@ export default class ViewWriter extends AbstractWriter {
66
79
  private removeFileExtensionsFromTemplateItems<
67
80
  T extends VcTemplateItem | ViewControllerPluginItem,
68
81
  >(vcTemplateItems: T[], destinationDir: string): T[] {
69
- return vcTemplateItems.map((i) => ({
82
+ return vcTemplateItems.map((i) =>
83
+ this.makePathRelative<T>(i, destinationDir)
84
+ )
85
+ }
86
+
87
+ private makePathRelative<
88
+ T extends VcTemplateItem | ViewControllerPluginItem,
89
+ >(i: T, destinationDir: string): T & { path: string } {
90
+ return {
70
91
  ...i,
71
92
  path: diskUtil
72
93
  .resolveRelativePath(destinationDir, i.path)
73
94
  .replace('.ts', ''),
74
- }))
95
+ }
75
96
  }
76
97
 
77
98
  public writeViewController(
@@ -215,17 +236,21 @@ export default class ViewWriter extends AbstractWriter {
215
236
  return { path, filename }
216
237
  }
217
238
 
218
- public async writeAppViewController(cwd: string) {
219
- const match = await globby(cwd + '/**/App.avc.ts')
239
+ public async writeAppController(
240
+ cwd: string,
241
+ id: string,
242
+ namespacePascal: string
243
+ ) {
244
+ const match = await globby(cwd + '/**/App.ac.ts')
220
245
 
221
246
  if (match.length > 0) {
222
247
  throw new SpruceError({
223
- code: 'APP_VIEW_CONTROLLER_ALREADY_EXISTS',
248
+ code: 'APP_CONTROLLER_ALREADY_EXISTS',
224
249
  })
225
250
  }
226
251
 
227
- const destination = diskUtil.resolvePath(cwd, 'src', 'App.avc.ts')
228
- const contents = this.templates.appViewController()
252
+ const destination = diskUtil.resolvePath(cwd, 'src', 'App.ac.ts')
253
+ const contents = this.templates.appController({ id, namespacePascal })
229
254
 
230
255
  return this.writeFileIfChangedMixinResults(
231
256
  destination,