@sprucelabs/spruce-cli 20.0.0 → 20.0.2

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 (53) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/build/__tests__/behavioral/EnablingAndDisablingCache.test.js +2 -1
  3. package/build/__tests__/behavioral/EnablingAndDisablingCache.test.js.map +1 -1
  4. package/build/__tests__/behavioral/upgrading/UpgradingASkill5.test.js +1 -1
  5. package/build/__tests__/behavioral/upgrading/UpgradingASkill5.test.js.map +1 -1
  6. package/build/__tests__/behavioral/views/CreatingASkillView.test.js +1 -1
  7. package/build/__tests__/behavioral/views/CreatingASkillView.test.js.map +1 -1
  8. package/build/__tests__/behavioral/views/plugins/CreatingAViewPlugin.test.d.ts +4 -0
  9. package/build/__tests__/behavioral/views/plugins/CreatingAViewPlugin.test.js +95 -17
  10. package/build/__tests__/behavioral/views/plugins/CreatingAViewPlugin.test.js.map +1 -1
  11. package/build/__tests__/implementation/EventCacheService.test.d.ts +4 -0
  12. package/build/__tests__/implementation/EventCacheService.test.js +84 -0
  13. package/build/__tests__/implementation/EventCacheService.test.js.map +1 -0
  14. package/build/errors/SpruceError.js +2 -2
  15. package/build/errors/SpruceError.js.map +1 -1
  16. package/build/features/cache/actions/EnableAction.js +3 -1
  17. package/build/features/cache/actions/EnableAction.js.map +1 -1
  18. package/build/features/event/EventFeature.js +2 -2
  19. package/build/features/event/EventFeature.js.map +1 -1
  20. package/build/features/event/actions/SyncAction.js +1 -1
  21. package/build/features/event/actions/SyncAction.js.map +1 -1
  22. package/build/features/event/services/{EventSettingsService.d.ts → EventCacheService.d.ts} +3 -3
  23. package/build/features/event/services/{EventSettingsService.js → EventCacheService.js} +8 -7
  24. package/build/features/event/services/EventCacheService.js.map +1 -0
  25. package/build/features/node/actions/UpgradeAction.d.ts +2 -2
  26. package/build/features/node/actions/UpgradeAction.js.map +1 -1
  27. package/build/features/universalFileDescriptions.js +1 -1
  28. package/build/features/universalFileDescriptions.js.map +1 -1
  29. package/build/features/view/actions/SyncAction.js +2 -0
  30. package/build/features/view/actions/SyncAction.js.map +1 -1
  31. package/build/services/ServiceFactory.d.ts +3 -2
  32. package/build/services/ServiceFactory.js +11 -7
  33. package/build/services/ServiceFactory.js.map +1 -1
  34. package/build/utilities/introspection.utility.d.ts +8 -4
  35. package/build/utilities/introspection.utility.js +189 -46
  36. package/build/utilities/introspection.utility.js.map +1 -1
  37. package/package.json +27 -27
  38. package/src/__tests__/behavioral/EnablingAndDisablingCache.test.ts +1 -0
  39. package/src/__tests__/behavioral/upgrading/UpgradingASkill5.test.ts +1 -1
  40. package/src/__tests__/behavioral/views/CreatingASkillView.test.ts +1 -1
  41. package/src/__tests__/behavioral/views/plugins/CreatingAViewPlugin.test.ts +53 -0
  42. package/src/__tests__/implementation/EventCacheService.test.ts +38 -0
  43. package/src/errors/SpruceError.ts +3 -1
  44. package/src/features/cache/actions/EnableAction.ts +6 -1
  45. package/src/features/event/EventFeature.ts +2 -2
  46. package/src/features/event/actions/SyncAction.ts +1 -1
  47. package/src/features/event/services/{EventSettingsService.ts → EventCacheService.ts} +5 -3
  48. package/src/features/node/actions/UpgradeAction.ts +4 -4
  49. package/src/features/universalFileDescriptions.ts +1 -1
  50. package/src/features/view/actions/SyncAction.ts +2 -0
  51. package/src/services/ServiceFactory.ts +11 -8
  52. package/src/utilities/introspection.utility.ts +233 -79
  53. package/build/features/event/services/EventSettingsService.js.map +0 -1
@@ -1,38 +1,9 @@
1
+ import { dirname } from 'path'
2
+ import { diskUtil } from '@sprucelabs/spruce-skill-utils'
1
3
  import _ from 'lodash'
2
4
  import * as tsutils from 'tsutils'
3
5
  import * as ts from 'typescript'
4
6
 
5
- export interface IntrospectionClass {
6
- className: string
7
- classPath: string
8
- parentClassName: string | undefined
9
- parentClassPath: string | undefined
10
- optionsInterfaceName: string | undefined
11
- isAbstract: boolean
12
- staticProperties: StaticProperties
13
- }
14
-
15
- type StaticProperties = Record<string, any>
16
-
17
- interface IntrospectionInterface {
18
- interfaceName: string
19
- }
20
-
21
- export interface Introspection {
22
- classes: IntrospectionClass[]
23
- interfaces: IntrospectionInterface[]
24
- }
25
-
26
- interface DocEntry {
27
- name?: string
28
- fileName?: string
29
- documentation?: string
30
- type?: string
31
- constructors?: DocEntry[]
32
- parameters?: DocEntry[]
33
- returnType?: string
34
- }
35
-
36
7
  const serializeSymbol = (options: {
37
8
  checker: ts.TypeChecker
38
9
  symbol: ts.Symbol
@@ -84,59 +55,54 @@ const introspectionUtil = {
84
55
  const sourceFile = program.getSourceFile(tsFile)
85
56
  const results: Introspection = { classes: [], interfaces: [] }
86
57
  if (sourceFile && _.includes(filePaths, sourceFile.fileName)) {
87
- ts.forEachChild(sourceFile, (node) => {
88
- // if this is a class declaration
89
- if (ts.isClassDeclaration(node) && node.name) {
90
- const symbol = checker.getSymbolAtLocation(node.name)
91
-
92
- if (symbol?.valueDeclaration) {
93
- const details = serializeSymbol({ checker, symbol })
94
- // Get the construct signatures
95
- const constructorType = checker.getTypeOfSymbolAtLocation(
96
- symbol,
97
- symbol.valueDeclaration
58
+ if (!this.hasClassDefinition(sourceFile)) {
59
+ const exports = this.getExports(sourceFile)
60
+ const firstExport = exports[0]
61
+ if (firstExport) {
62
+ const declaration = this.getClassDeclarationFromImportedFile(
63
+ firstExport,
64
+ dirname(tsFile),
65
+ program
66
+ )
67
+
68
+ if (declaration) {
69
+ const { classes, interfaces } = getDeclarationsFromNode(
70
+ declaration,
71
+ checker,
72
+ sourceFile
98
73
  )
74
+ results.classes.push(...classes)
75
+ results.interfaces.push(...interfaces)
76
+ } else {
77
+ // must have imported from somewhere else (another node module)
78
+ const className = //@ts-ignore
79
+ firstExport.exportClause?.elements?.[0]?.propertyName?.text
99
80
 
100
- let parentClassSymbol: ts.Symbol | undefined
101
- if (node.heritageClauses && node.heritageClauses[0]) {
102
- parentClassSymbol = checker
103
- .getTypeAtLocation(node.heritageClauses[0].types[0])
104
- .getSymbol()
81
+ if (className) {
82
+ results.classes.push({
83
+ className,
84
+ classPath: tsFile,
85
+ isAbstract: false,
86
+ optionsInterfaceName: undefined,
87
+ parentClassName: undefined,
88
+ parentClassPath: undefined,
89
+ staticProperties: {},
90
+ })
105
91
  }
106
-
107
- const parentClassName =
108
- // @ts-ignore
109
- parentClassSymbol?.valueDeclaration?.name?.text
110
- // @ts-ignore
111
- const parentClassPath = parentClassSymbol?.parent
112
- ?.getName()
113
- .replace('"', '')
114
-
115
- const isAbstractClass = tsutils.isModifierFlagSet(
116
- node,
117
- ts.ModifierFlags.Abstract
118
- )
119
- details.constructors = constructorType
120
- .getConstructSignatures()
121
- .map((s) => serializeSignature({ signature: s, checker }))
122
-
123
- results.classes.push({
124
- className: node.name.text,
125
- classPath: sourceFile.fileName,
126
- parentClassName,
127
- parentClassPath,
128
- staticProperties: pluckStaticProperties(node),
129
- optionsInterfaceName:
130
- details.constructors?.[0].parameters?.[0]?.type,
131
- isAbstract: isAbstractClass,
132
- })
133
92
  }
134
- } else if (ts.isInterfaceDeclaration(node)) {
135
- results.interfaces.push({
136
- interfaceName: node.name.text,
137
- })
138
93
  }
139
- })
94
+ } else {
95
+ ts.forEachChild(sourceFile, (node) => {
96
+ const { classes, interfaces } = getDeclarationsFromNode(
97
+ node,
98
+ checker,
99
+ sourceFile
100
+ )
101
+
102
+ results.classes.push(...classes)
103
+ results.interfaces.push(...interfaces)
104
+ })
105
+ }
140
106
  }
141
107
 
142
108
  introspects.push(results)
@@ -144,10 +110,167 @@ const introspectionUtil = {
144
110
 
145
111
  return introspects
146
112
  },
113
+
114
+ getExports(sourceFile: ts.SourceFile): ts.Node[] {
115
+ const exports: ts.Node[] = []
116
+
117
+ const traverse = (node: ts.Node) => {
118
+ if (ts.isExportDeclaration(node)) {
119
+ exports.push(node)
120
+ }
121
+
122
+ ts.forEachChild(node, traverse)
123
+ }
124
+
125
+ traverse(sourceFile)
126
+
127
+ return exports
128
+ },
129
+
130
+ getClassDeclarationFromImportedFile(
131
+ exportDeclaration: ts.Node,
132
+ dirName: string,
133
+ program: ts.Program
134
+ ): ts.ClassDeclaration | undefined {
135
+ if (!ts.isExportDeclaration(exportDeclaration)) {
136
+ return undefined
137
+ }
138
+
139
+ const exportClause = exportDeclaration.exportClause
140
+ if (!exportClause || !ts.isNamedExports(exportClause)) {
141
+ return undefined
142
+ }
143
+
144
+ for (const element of exportClause.elements) {
145
+ if (element.propertyName) {
146
+ const propertyName = element.propertyName.text
147
+ const moduleSpecifier = (
148
+ exportDeclaration.moduleSpecifier as ts.StringLiteral
149
+ ).text
150
+
151
+ const sourceFile = diskUtil.resolveFile(
152
+ dirName,
153
+ moduleSpecifier.replace(/^\.\//, '')
154
+ )
155
+
156
+ if (!sourceFile) {
157
+ return undefined
158
+ }
159
+
160
+ // Load the source file containing the class declaration
161
+ const declarationSourceFile = program.getSourceFile(sourceFile)
162
+ if (!declarationSourceFile) {
163
+ return undefined
164
+ }
165
+
166
+ const traverse = (node: ts.Node): ts.ClassDeclaration | undefined => {
167
+ if (
168
+ ts.isClassDeclaration(node) &&
169
+ node.name &&
170
+ node.name.text === propertyName
171
+ ) {
172
+ return node
173
+ }
174
+
175
+ for (const child of node.getChildren(declarationSourceFile)) {
176
+ const result = traverse(child)
177
+ if (result) {
178
+ return result
179
+ }
180
+ }
181
+
182
+ return undefined
183
+ }
184
+
185
+ return traverse(declarationSourceFile)
186
+ }
187
+ }
188
+
189
+ return undefined
190
+ },
191
+
192
+ hasClassDefinition(sourceFile: ts.SourceFile): boolean {
193
+ let hasClass = false
194
+
195
+ const traverse = (node: ts.Node) => {
196
+ if (ts.isClassDeclaration(node)) {
197
+ hasClass = true
198
+ }
199
+
200
+ if (!hasClass) {
201
+ ts.forEachChild(node, traverse)
202
+ }
203
+ }
204
+
205
+ traverse(sourceFile)
206
+
207
+ return hasClass
208
+ },
147
209
  }
148
210
 
149
211
  export default introspectionUtil
150
212
 
213
+ function getDeclarationsFromNode(
214
+ node: ts.Node,
215
+ checker: ts.TypeChecker,
216
+ sourceFile: ts.SourceFile
217
+ ) {
218
+ const classes: IntrospectionClass[] = []
219
+ const interfaces: IntrospectionInterface[] = []
220
+
221
+ // if this is a class declaration
222
+ if (ts.isClassDeclaration(node) && node.name) {
223
+ const symbol = checker.getSymbolAtLocation(node.name)
224
+
225
+ if (symbol?.valueDeclaration) {
226
+ const details = serializeSymbol({ checker, symbol })
227
+ // Get the construct signatures
228
+ const constructorType = checker.getTypeOfSymbolAtLocation(
229
+ symbol,
230
+ symbol.valueDeclaration
231
+ )
232
+
233
+ let parentClassSymbol: ts.Symbol | undefined
234
+ if (node.heritageClauses && node.heritageClauses[0]) {
235
+ parentClassSymbol = checker
236
+ .getTypeAtLocation(node.heritageClauses[0].types[0])
237
+ .getSymbol()
238
+ }
239
+
240
+ const parentClassName =
241
+ // @ts-ignore
242
+ parentClassSymbol?.valueDeclaration?.name?.text
243
+ // @ts-ignore
244
+ const parentClassPath = parentClassSymbol?.parent
245
+ ?.getName()
246
+ .replace('"', '')
247
+
248
+ const isAbstractClass = tsutils.isModifierFlagSet(
249
+ node,
250
+ ts.ModifierFlags.Abstract
251
+ )
252
+ details.constructors = constructorType
253
+ .getConstructSignatures()
254
+ .map((s) => serializeSignature({ signature: s, checker }))
255
+
256
+ classes.push({
257
+ className: node.name.text,
258
+ classPath: sourceFile.fileName,
259
+ parentClassName,
260
+ parentClassPath,
261
+ staticProperties: pluckStaticProperties(node),
262
+ optionsInterfaceName: details.constructors?.[0].parameters?.[0]?.type,
263
+ isAbstract: isAbstractClass,
264
+ })
265
+ }
266
+ } else if (ts.isInterfaceDeclaration(node)) {
267
+ interfaces.push({
268
+ interfaceName: node.name.text,
269
+ })
270
+ }
271
+ return { classes, interfaces }
272
+ }
273
+
151
274
  function pluckStaticProperties(node: ts.ClassDeclaration): StaticProperties {
152
275
  const staticProps: StaticProperties = {}
153
276
 
@@ -164,3 +287,34 @@ function pluckStaticProperties(node: ts.ClassDeclaration): StaticProperties {
164
287
 
165
288
  return staticProps
166
289
  }
290
+
291
+ export interface IntrospectionClass {
292
+ className: string
293
+ classPath: string
294
+ parentClassName: string | undefined
295
+ parentClassPath: string | undefined
296
+ optionsInterfaceName: string | undefined
297
+ isAbstract: boolean
298
+ staticProperties: StaticProperties
299
+ }
300
+
301
+ type StaticProperties = Record<string, any>
302
+
303
+ interface IntrospectionInterface {
304
+ interfaceName: string
305
+ }
306
+
307
+ export interface Introspection {
308
+ classes: IntrospectionClass[]
309
+ interfaces: IntrospectionInterface[]
310
+ }
311
+
312
+ interface DocEntry {
313
+ name?: string
314
+ fileName?: string
315
+ documentation?: string
316
+ type?: string
317
+ constructors?: DocEntry[]
318
+ parameters?: DocEntry[]
319
+ returnType?: string
320
+ }
@@ -1 +0,0 @@
1
- {"version":3,"file":"EventSettingsService.js","names":["EventSettingsService","exports","settings","_classCallCheck2","_defineProperty2","_createClass2","key","value","getLastSyncOptions","get","setLastSyncOptions","options","set","setListenerCache","clearListenerCache","unset","getListenerCache"],"sources":["../../../../src/features/event/services/EventSettingsService.ts"],"sourcesContent":["import { SettingsService } from '@sprucelabs/spruce-skill-utils'\n\nexport default class EventSettingsService {\n\tprivate settings: SettingsService<string>\n\tpublic constructor(settings: SettingsService) {\n\t\tthis.settings = settings\n\t}\n\n\tpublic getLastSyncOptions() {\n\t\treturn this.settings.get('events.lastSync')\n\t}\n\n\tpublic setLastSyncOptions(options: {\n\t\tshouldSyncOnlyCoreEvents?: boolean | null\n\t}) {\n\t\tthis.settings.set('events.lastSync', options)\n\t}\n\n\tpublic setListenerCache(value: Record<string, any>) {\n\t\tthis.settings.set('events.listenerCacheKeys', value)\n\t}\n\n\tpublic clearListenerCache() {\n\t\tthis.settings.unset('events.listenerCacheKeys')\n\t}\n\n\tpublic getListenerCache() {\n\t\treturn this.settings.get('events.listenerCacheKeys')\n\t}\n}\n"],"mappings":";;;;;;;;;;IAEqBA,oBAAoB,GAAAC,OAAA;EAExC,SAAAD,qBAAmBE,QAAyB,EAAE;IAAA,IAAAC,gBAAA,mBAAAH,oBAAA;IAAA,IAAAI,gBAAA;IAC7C,IAAI,CAACF,QAAQ,GAAGA,QAAQ;EACzB;EAAC,WAAAG,aAAA,aAAAL,oBAAA;IAAAM,GAAA;IAAAC,KAAA,EAED,SAAAC,mBAAA,EAA4B;MAC3B,OAAO,IAAI,CAACN,QAAQ,CAACO,GAAG,CAAC,iBAAiB,CAAC;IAC5C;EAAC;IAAAH,GAAA;IAAAC,KAAA,EAED,SAAAG,mBAA0BC,OAEzB,EAAE;MACF,IAAI,CAACT,QAAQ,CAACU,GAAG,CAAC,iBAAiB,EAAED,OAAO,CAAC;IAC9C;EAAC;IAAAL,GAAA;IAAAC,KAAA,EAED,SAAAM,iBAAwBN,KAA0B,EAAE;MACnD,IAAI,CAACL,QAAQ,CAACU,GAAG,CAAC,0BAA0B,EAAEL,KAAK,CAAC;IACrD;EAAC;IAAAD,GAAA;IAAAC,KAAA,EAED,SAAAO,mBAAA,EAA4B;MAC3B,IAAI,CAACZ,QAAQ,CAACa,KAAK,CAAC,0BAA0B,CAAC;IAChD;EAAC;IAAAT,GAAA;IAAAC,KAAA,EAED,SAAAS,iBAAA,EAA0B;MACzB,OAAO,IAAI,CAACd,QAAQ,CAACO,GAAG,CAAC,0BAA0B,CAAC;IACrD;EAAC;AAAA","ignoreList":[]}