@sprucelabs/spruce-cli 19.1.42 → 19.2.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 +12 -0
- package/build/.spruce/errors/errors.types.d.ts +19 -0
- package/build/.spruce/errors/errors.types.js.map +1 -1
- package/build/.spruce/errors/options.types.d.ts +4 -1
- package/build/.spruce/errors/options.types.js.map +1 -1
- package/build/.spruce/errors/spruceCli/viewPluginAlreadyExists.schema.d.ts +3 -0
- package/build/.spruce/errors/spruceCli/viewPluginAlreadyExists.schema.js +23 -0
- package/build/.spruce/errors/spruceCli/viewPluginAlreadyExists.schema.js.map +1 -0
- package/build/__tests__/behavioral/views/CreatingASkillView.test.d.ts +1 -1
- package/build/__tests__/behavioral/views/CreatingASkillView.test.js +6 -6
- package/build/__tests__/behavioral/views/CreatingASkillView.test.js.map +1 -1
- package/build/__tests__/behavioral/views/KeepingViewsInSync.test.d.ts +1 -1
- package/build/__tests__/behavioral/views/KeepingViewsInSync.test.js +6 -6
- package/build/__tests__/behavioral/views/KeepingViewsInSync.test.js.map +1 -1
- package/build/__tests__/behavioral/views/plugins/CreatingAViewPlugin.test.d.ts +23 -0
- package/build/__tests__/behavioral/views/plugins/CreatingAViewPlugin.test.js +355 -0
- package/build/__tests__/behavioral/views/plugins/CreatingAViewPlugin.test.js.map +1 -0
- package/build/errors/SpruceError.js +3 -0
- package/build/errors/SpruceError.js.map +1 -1
- package/build/errors/viewPluginAlreadyExists.builder.d.ts +11 -0
- package/build/errors/viewPluginAlreadyExists.builder.js +18 -0
- package/build/errors/viewPluginAlreadyExists.builder.js.map +1 -0
- package/build/features/view/actions/CreateAction.d.ts +6 -6
- package/build/features/view/actions/CreateAction.js +59 -59
- package/build/features/view/actions/CreateAction.js.map +1 -1
- package/build/features/view/actions/CreatePluginAction.d.ts +56 -0
- package/build/features/view/actions/CreatePluginAction.js +95 -0
- package/build/features/view/actions/CreatePluginAction.js.map +1 -0
- package/build/features/view/actions/SyncAction.d.ts +6 -6
- package/build/features/view/actions/SyncAction.js +29 -15
- package/build/features/view/actions/SyncAction.js.map +1 -1
- package/build/features/view/writers/ViewWriter.d.ts +5 -0
- package/build/features/view/writers/ViewWriter.js +44 -7
- package/build/features/view/writers/ViewWriter.js.map +1 -1
- package/package.json +3 -3
- package/src/.spruce/errors/errors.types.ts +29 -0
- package/src/.spruce/errors/options.types.ts +4 -1
- package/src/.spruce/errors/spruceCli/viewPluginAlreadyExists.schema.ts +22 -0
- package/src/__tests__/behavioral/views/CreatingASkillView.test.ts +1 -1
- package/src/__tests__/behavioral/views/KeepingViewsInSync.test.ts +1 -1
- package/src/__tests__/behavioral/views/plugins/CreatingAViewPlugin.test.ts +161 -0
- package/src/errors/SpruceError.ts +4 -0
- package/src/errors/viewPluginAlreadyExists.builder.ts +12 -0
- package/src/features/view/actions/CreateAction.ts +72 -72
- package/src/features/view/actions/CreatePluginAction.ts +54 -0
- package/src/features/view/actions/SyncAction.ts +30 -14
- package/src/features/view/writers/ViewWriter.ts +45 -5
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { SchemaValues, buildSchema } from '@sprucelabs/schema'
|
|
2
|
+
import { namesUtil } from '@sprucelabs/spruce-skill-utils'
|
|
3
|
+
import namedTemplateItemBuilder from '../../../schemas/v2020_07_22/namedTemplateItem.builder'
|
|
4
|
+
import actionUtil from '../../../utilities/action.utility'
|
|
5
|
+
import AbstractAction from '../../AbstractAction'
|
|
6
|
+
import { FeatureActionResponse } from '../../features.types'
|
|
7
|
+
|
|
8
|
+
export default class CreatePluginAction extends AbstractAction<OptionsSchema> {
|
|
9
|
+
public optionsSchema = optionsSchema
|
|
10
|
+
public invocationMessage = 'Creating a new view plugin... 🖼️'
|
|
11
|
+
public commandAliases: string[] = ['create.view.plugin']
|
|
12
|
+
|
|
13
|
+
public async execute(
|
|
14
|
+
options: SchemaValues<OptionsSchema>
|
|
15
|
+
): Promise<FeatureActionResponse> {
|
|
16
|
+
const { nameReadable, nameCamel, namePascal } =
|
|
17
|
+
this.validateAndNormalizeOptions(options)
|
|
18
|
+
|
|
19
|
+
const normalizedNameCamel = nameCamel ?? namesUtil.toCamel(nameReadable)
|
|
20
|
+
const normalizedNamePascal =
|
|
21
|
+
namePascal ?? namesUtil.toPascal(normalizedNameCamel)
|
|
22
|
+
|
|
23
|
+
const writer = this.Writer('view')
|
|
24
|
+
const files = await writer.writeViewControllerPlugin({
|
|
25
|
+
cwd: this.cwd,
|
|
26
|
+
nameCamel: normalizedNameCamel,
|
|
27
|
+
namePascal: normalizedNamePascal,
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
const sync = await this.Action('view', 'sync').execute({})
|
|
31
|
+
|
|
32
|
+
return actionUtil.mergeActionResults({ files }, sync)
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const optionsSchema = buildSchema({
|
|
37
|
+
id: 'createViewPluginOptions',
|
|
38
|
+
fields: {
|
|
39
|
+
nameReadable: {
|
|
40
|
+
...namedTemplateItemBuilder.fields.nameReadable,
|
|
41
|
+
label: 'Plugin name',
|
|
42
|
+
},
|
|
43
|
+
nameCamel: {
|
|
44
|
+
...namedTemplateItemBuilder.fields.nameCamel,
|
|
45
|
+
isRequired: false,
|
|
46
|
+
},
|
|
47
|
+
namePascal: {
|
|
48
|
+
...namedTemplateItemBuilder.fields.namePascal,
|
|
49
|
+
isRequired: false,
|
|
50
|
+
},
|
|
51
|
+
},
|
|
52
|
+
})
|
|
53
|
+
|
|
54
|
+
type OptionsSchema = typeof optionsSchema
|
|
@@ -1,21 +1,16 @@
|
|
|
1
1
|
import globby from '@sprucelabs/globby'
|
|
2
2
|
import { buildSchema, SchemaValues } from '@sprucelabs/schema'
|
|
3
3
|
import { diskUtil, namesUtil } from '@sprucelabs/spruce-skill-utils'
|
|
4
|
-
import {
|
|
4
|
+
import {
|
|
5
|
+
VcTemplateItem,
|
|
6
|
+
ViewControllerPluginItem,
|
|
7
|
+
} from '../../../../../spruce-templates/build'
|
|
5
8
|
import introspectionUtil, {
|
|
6
9
|
IntrospectionClass,
|
|
7
10
|
} from '../../../utilities/introspection.utility'
|
|
8
11
|
import AbstractAction from '../../AbstractAction'
|
|
9
12
|
import { FeatureActionResponse } from '../../features.types'
|
|
10
13
|
|
|
11
|
-
const optionsSchema = buildSchema({
|
|
12
|
-
id: 'syncViewsOptions',
|
|
13
|
-
description: 'Keep types and generated files based on views in sync.',
|
|
14
|
-
fields: {},
|
|
15
|
-
})
|
|
16
|
-
|
|
17
|
-
type OptionsSchema = typeof optionsSchema
|
|
18
|
-
|
|
19
14
|
export default class SyncAction extends AbstractAction<OptionsSchema> {
|
|
20
15
|
public optionsSchema: OptionsSchema = optionsSchema
|
|
21
16
|
public commandAliases = ['sync.views']
|
|
@@ -25,9 +20,12 @@ export default class SyncAction extends AbstractAction<OptionsSchema> {
|
|
|
25
20
|
_options: SchemaValues<OptionsSchema>
|
|
26
21
|
): Promise<FeatureActionResponse> {
|
|
27
22
|
const targetDir = diskUtil.resolvePath(this.cwd, 'src')
|
|
28
|
-
const matches = await globby(
|
|
29
|
-
|
|
30
|
-
|
|
23
|
+
const matches = await globby(
|
|
24
|
+
['**/*.svc.ts', '**/*.vc.ts', '**/*.view.plugin.ts'],
|
|
25
|
+
{
|
|
26
|
+
cwd: targetDir,
|
|
27
|
+
}
|
|
28
|
+
)
|
|
31
29
|
|
|
32
30
|
if (matches.length === 0) {
|
|
33
31
|
return {}
|
|
@@ -38,13 +36,17 @@ export default class SyncAction extends AbstractAction<OptionsSchema> {
|
|
|
38
36
|
|
|
39
37
|
const vcTemplateItems: VcTemplateItem[] = []
|
|
40
38
|
const svcTemplateItems: VcTemplateItem[] = []
|
|
39
|
+
const viewPluginItems: ViewControllerPluginItem[] = []
|
|
41
40
|
|
|
42
41
|
introspect.forEach(({ classes }) => {
|
|
43
42
|
for (const thisClass of classes) {
|
|
44
|
-
const { vc, svc } =
|
|
43
|
+
const { vc, svc, plugin } =
|
|
44
|
+
this.mapIntrospectedClassToTemplateItem(thisClass)
|
|
45
45
|
|
|
46
46
|
if (vc) {
|
|
47
47
|
vcTemplateItems.push(vc)
|
|
48
|
+
} else if (plugin) {
|
|
49
|
+
viewPluginItems.push(plugin)
|
|
48
50
|
} else if (svc) {
|
|
49
51
|
svcTemplateItems.push(svc)
|
|
50
52
|
}
|
|
@@ -56,6 +58,7 @@ export default class SyncAction extends AbstractAction<OptionsSchema> {
|
|
|
56
58
|
namespaceKebab: namesUtil.toKebab(namespace),
|
|
57
59
|
vcTemplateItems,
|
|
58
60
|
svcTemplateItems,
|
|
61
|
+
viewPluginItems,
|
|
59
62
|
})
|
|
60
63
|
|
|
61
64
|
return {
|
|
@@ -66,6 +69,7 @@ export default class SyncAction extends AbstractAction<OptionsSchema> {
|
|
|
66
69
|
private mapIntrospectedClassToTemplateItem(c: IntrospectionClass): {
|
|
67
70
|
vc?: VcTemplateItem
|
|
68
71
|
svc?: VcTemplateItem
|
|
72
|
+
plugin?: ViewControllerPluginItem
|
|
69
73
|
} {
|
|
70
74
|
const item = {
|
|
71
75
|
id: c.staticProperties.id,
|
|
@@ -75,13 +79,25 @@ export default class SyncAction extends AbstractAction<OptionsSchema> {
|
|
|
75
79
|
|
|
76
80
|
let vc: VcTemplateItem | undefined
|
|
77
81
|
let svc: VcTemplateItem | undefined
|
|
82
|
+
let plugin: ViewControllerPluginItem | undefined
|
|
78
83
|
|
|
79
84
|
if (c.classPath.endsWith('.svc.ts')) {
|
|
80
85
|
svc = item
|
|
86
|
+
} else if (c.classPath.endsWith('view.plugin.ts')) {
|
|
87
|
+
const nameCamel = c.classPath.match(/([^/]+).view.plugin.ts$/)![1]
|
|
88
|
+
plugin = { ...item, nameCamel }
|
|
81
89
|
} else {
|
|
82
90
|
vc = item
|
|
83
91
|
}
|
|
84
92
|
|
|
85
|
-
return { svc, vc }
|
|
93
|
+
return { svc, vc, plugin }
|
|
86
94
|
}
|
|
87
95
|
}
|
|
96
|
+
|
|
97
|
+
const optionsSchema = buildSchema({
|
|
98
|
+
id: 'syncViewsOptions',
|
|
99
|
+
description: 'Keep types and generated files based on views in sync.',
|
|
100
|
+
fields: {},
|
|
101
|
+
})
|
|
102
|
+
|
|
103
|
+
type OptionsSchema = typeof optionsSchema
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { diskUtil } from '@sprucelabs/spruce-skill-utils'
|
|
2
2
|
import {
|
|
3
3
|
VcTemplateItem,
|
|
4
|
+
ViewControllerPluginItem,
|
|
4
5
|
ViewsOptions,
|
|
5
6
|
} from '../../../../../spruce-templates/build'
|
|
6
7
|
import SpruceError from '../../../errors/SpruceError'
|
|
@@ -24,7 +25,8 @@ export default class ViewWriter extends AbstractWriter {
|
|
|
24
25
|
}
|
|
25
26
|
|
|
26
27
|
public async writeCombinedViewsFile(cwd: string, options: ViewsOptions) {
|
|
27
|
-
let { vcTemplateItems, svcTemplateItems, ...rest } =
|
|
28
|
+
let { vcTemplateItems, svcTemplateItems, viewPluginItems, ...rest } =
|
|
29
|
+
options
|
|
28
30
|
|
|
29
31
|
const destinationDir = diskUtil.resolveHashSprucePath(cwd, 'views')
|
|
30
32
|
const destination = diskUtil.resolvePath(destinationDir, 'views.ts')
|
|
@@ -39,9 +41,15 @@ export default class ViewWriter extends AbstractWriter {
|
|
|
39
41
|
destinationDir
|
|
40
42
|
)
|
|
41
43
|
|
|
44
|
+
viewPluginItems = this.removeFileExtensionsFromTemplateItems(
|
|
45
|
+
viewPluginItems,
|
|
46
|
+
destinationDir
|
|
47
|
+
)
|
|
48
|
+
|
|
42
49
|
const contents = this.templates.views({
|
|
43
50
|
vcTemplateItems,
|
|
44
51
|
svcTemplateItems,
|
|
52
|
+
viewPluginItems,
|
|
45
53
|
...rest,
|
|
46
54
|
})
|
|
47
55
|
|
|
@@ -54,10 +62,9 @@ export default class ViewWriter extends AbstractWriter {
|
|
|
54
62
|
return results
|
|
55
63
|
}
|
|
56
64
|
|
|
57
|
-
private removeFileExtensionsFromTemplateItems
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
): VcTemplateItem[] {
|
|
65
|
+
private removeFileExtensionsFromTemplateItems<
|
|
66
|
+
T extends VcTemplateItem | ViewControllerPluginItem,
|
|
67
|
+
>(vcTemplateItems: T[], destinationDir: string): T[] {
|
|
61
68
|
return vcTemplateItems.map((i) => ({
|
|
62
69
|
...i,
|
|
63
70
|
path: diskUtil
|
|
@@ -111,6 +118,39 @@ export default class ViewWriter extends AbstractWriter {
|
|
|
111
118
|
return diskUtil.doesFileExist(path)
|
|
112
119
|
}
|
|
113
120
|
|
|
121
|
+
public async writeViewControllerPlugin(options: {
|
|
122
|
+
cwd: string
|
|
123
|
+
nameCamel: string
|
|
124
|
+
namePascal: string
|
|
125
|
+
}) {
|
|
126
|
+
const { nameCamel, namePascal, cwd } = options
|
|
127
|
+
|
|
128
|
+
const destination = diskUtil.resolvePath(
|
|
129
|
+
cwd,
|
|
130
|
+
'src',
|
|
131
|
+
'viewPlugins',
|
|
132
|
+
`${nameCamel}.view.plugin.ts`
|
|
133
|
+
)
|
|
134
|
+
|
|
135
|
+
const contents = this.templates.viewControllerPlugin({
|
|
136
|
+
nameCamel,
|
|
137
|
+
namePascal,
|
|
138
|
+
})
|
|
139
|
+
|
|
140
|
+
if (diskUtil.doesFileExist(destination)) {
|
|
141
|
+
throw new SpruceError({
|
|
142
|
+
code: 'VIEW_PLUGIN_ALREADY_EXISTS',
|
|
143
|
+
name: nameCamel,
|
|
144
|
+
})
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
return this.writeFileIfChangedMixinResults(
|
|
148
|
+
destination,
|
|
149
|
+
contents,
|
|
150
|
+
`Your new view plugin!`
|
|
151
|
+
)
|
|
152
|
+
}
|
|
153
|
+
|
|
114
154
|
public writePlugin(cwd: string) {
|
|
115
155
|
const destination = diskUtil.resolveHashSprucePath(
|
|
116
156
|
cwd,
|