@teleporthq/teleport-uidl-validator 0.18.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 (84) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +14 -0
  3. package/__tests__/parser/componennt-with-referenced-styles.json +111 -0
  4. package/__tests__/parser/component-parsing.ts +116 -0
  5. package/__tests__/parser/component-referenced.ts +50 -0
  6. package/__tests__/parser/component-with-primitive-values.json +61 -0
  7. package/__tests__/parser/component-with-proper-values.json +97 -0
  8. package/__tests__/parser/component-with-reusalble-styles.json +117 -0
  9. package/__tests__/validator/component-element-with-empty-name.json +36 -0
  10. package/__tests__/validator/component-invalid-sample.json +184 -0
  11. package/__tests__/validator/component-uidl-with-event-modifier-undefined.json +45 -0
  12. package/__tests__/validator/component-uidl-with-null-undefined.json +24 -0
  13. package/__tests__/validator/index.ts +216 -0
  14. package/__tests__/validator/old-project-invalid-sample.json +317 -0
  15. package/__tests__/validator/project-invalid-sample-no-route.json +667 -0
  16. package/__tests__/validator/project-invalid-sample.json +671 -0
  17. package/__tests__/validator/project-sample.json +667 -0
  18. package/dist/cjs/decoders/component-decoder.d.ts +4 -0
  19. package/dist/cjs/decoders/component-decoder.js +30 -0
  20. package/dist/cjs/decoders/component-decoder.js.map +1 -0
  21. package/dist/cjs/decoders/custom-combinators.d.ts +8 -0
  22. package/dist/cjs/decoders/custom-combinators.js +59 -0
  23. package/dist/cjs/decoders/custom-combinators.js.map +1 -0
  24. package/dist/cjs/decoders/index.d.ts +2 -0
  25. package/dist/cjs/decoders/index.js +9 -0
  26. package/dist/cjs/decoders/index.js.map +1 -0
  27. package/dist/cjs/decoders/project-decoder.d.ts +5 -0
  28. package/dist/cjs/decoders/project-decoder.js +38 -0
  29. package/dist/cjs/decoders/project-decoder.js.map +1 -0
  30. package/dist/cjs/decoders/utils.d.ts +59 -0
  31. package/dist/cjs/decoders/utils.js +305 -0
  32. package/dist/cjs/decoders/utils.js.map +1 -0
  33. package/dist/cjs/index.d.ts +7 -0
  34. package/dist/cjs/index.js +38 -0
  35. package/dist/cjs/index.js.map +1 -0
  36. package/dist/cjs/parser/index.d.ts +10 -0
  37. package/dist/cjs/parser/index.js +156 -0
  38. package/dist/cjs/parser/index.js.map +1 -0
  39. package/dist/cjs/tsconfig.tsbuildinfo +1 -0
  40. package/dist/cjs/validator/index.d.ts +15 -0
  41. package/dist/cjs/validator/index.js +94 -0
  42. package/dist/cjs/validator/index.js.map +1 -0
  43. package/dist/cjs/validator/utils.d.ts +16 -0
  44. package/dist/cjs/validator/utils.js +373 -0
  45. package/dist/cjs/validator/utils.js.map +1 -0
  46. package/dist/esm/decoders/component-decoder.d.ts +4 -0
  47. package/dist/esm/decoders/component-decoder.js +27 -0
  48. package/dist/esm/decoders/component-decoder.js.map +1 -0
  49. package/dist/esm/decoders/custom-combinators.d.ts +8 -0
  50. package/dist/esm/decoders/custom-combinators.js +56 -0
  51. package/dist/esm/decoders/custom-combinators.js.map +1 -0
  52. package/dist/esm/decoders/index.d.ts +2 -0
  53. package/dist/esm/decoders/index.js +3 -0
  54. package/dist/esm/decoders/index.js.map +1 -0
  55. package/dist/esm/decoders/project-decoder.d.ts +5 -0
  56. package/dist/esm/decoders/project-decoder.js +35 -0
  57. package/dist/esm/decoders/project-decoder.js.map +1 -0
  58. package/dist/esm/decoders/utils.d.ts +59 -0
  59. package/dist/esm/decoders/utils.js +301 -0
  60. package/dist/esm/decoders/utils.js.map +1 -0
  61. package/dist/esm/index.d.ts +7 -0
  62. package/dist/esm/index.js +8 -0
  63. package/dist/esm/index.js.map +1 -0
  64. package/dist/esm/parser/index.d.ts +10 -0
  65. package/dist/esm/parser/index.js +151 -0
  66. package/dist/esm/parser/index.js.map +1 -0
  67. package/dist/esm/tsconfig.tsbuildinfo +1 -0
  68. package/dist/esm/validator/index.d.ts +15 -0
  69. package/dist/esm/validator/index.js +73 -0
  70. package/dist/esm/validator/index.js.map +1 -0
  71. package/dist/esm/validator/utils.d.ts +16 -0
  72. package/dist/esm/validator/utils.js +359 -0
  73. package/dist/esm/validator/utils.js.map +1 -0
  74. package/package.json +32 -0
  75. package/src/decoders/component-decoder.ts +48 -0
  76. package/src/decoders/custom-combinators.ts +59 -0
  77. package/src/decoders/index.ts +2 -0
  78. package/src/decoders/project-decoder.ts +40 -0
  79. package/src/decoders/utils.ts +571 -0
  80. package/src/index.ts +9 -0
  81. package/src/parser/index.ts +227 -0
  82. package/src/validator/index.ts +105 -0
  83. package/src/validator/utils.ts +463 -0
  84. package/tsconfig.json +9 -0
@@ -0,0 +1,463 @@
1
+ import { UIDLUtils } from '@teleporthq/teleport-shared'
2
+
3
+ import {
4
+ ProjectUIDL,
5
+ UIDLElement,
6
+ ComponentUIDL,
7
+ UIDLNode,
8
+ UIDLStyleSetDefinition,
9
+ UIDLStaticValue,
10
+ UIDLExternalDependency,
11
+ UIDLElementNodeProjectReferencedStyle,
12
+ UIDLStyleValue,
13
+ UIDLElementNodeInlineReferencedStyle,
14
+ UIDLReferencedStyles,
15
+ UIDLStyleSetTokenReference,
16
+ ComponentValidationError,
17
+ } from '@teleporthq/teleport-types'
18
+
19
+ // Prop definitions and state definitions should have different keys
20
+ export const checkForDuplicateDefinitions = (input: ComponentUIDL) => {
21
+ const props = Object.keys(input.propDefinitions || {})
22
+ const states = Object.keys(input.stateDefinitions || {})
23
+ const imports = Object.keys(input.importDefinitions || {})
24
+
25
+ props
26
+ .filter((x) => states.includes(x) || imports.includes(x))
27
+ .forEach((duplicate) =>
28
+ console.warn(
29
+ `\n"${duplicate}" is defined both as a prop and as a state. If you are using VUE Code Generators this can cause bad behavior.`
30
+ )
31
+ )
32
+ }
33
+
34
+ // In "repeat" node:
35
+ // If index is used, "useIndex" must be declared in "meta"
36
+ // If custom local variable is used, it's name must be specified inside "meta" as "iteratorName"
37
+ export const checkForLocalVariables = (input: ComponentUIDL) => {
38
+ const errors: string[] = []
39
+
40
+ UIDLUtils.traverseRepeats(input.node, (repeatContent) => {
41
+ UIDLUtils.traverseNodes(repeatContent.node, (childNode) => {
42
+ if (childNode.type === 'dynamic' && childNode.content.referenceType === 'local') {
43
+ if (childNode.content.id === 'index') {
44
+ if (!repeatContent.meta.useIndex) {
45
+ const errorMsg = `\nIndex variable is used but the "useIndex" meta information is false.`
46
+ errors.push(errorMsg)
47
+ }
48
+
49
+ // we are dealing with local index here
50
+ return
51
+ }
52
+
53
+ if (!validLocalVariableUsage(childNode.content.id, repeatContent.meta.iteratorName)) {
54
+ const errorMsg = `\n"${childNode.content.id}" is used in the "repeat" structure but the iterator name has this value: "${repeatContent.meta.iteratorName}"`
55
+ errors.push(errorMsg)
56
+ }
57
+ }
58
+ })
59
+ })
60
+ return errors
61
+ }
62
+
63
+ const validLocalVariableUsage = (dynamicId: string, repeatIteratorName: string) => {
64
+ const iteratorName = repeatIteratorName || 'item'
65
+
66
+ if (!dynamicId.includes('.')) {
67
+ return dynamicId === iteratorName
68
+ }
69
+
70
+ const dynamicIdRoot = dynamicId.split('.')[0]
71
+ return dynamicIdRoot === iteratorName
72
+ }
73
+
74
+ /* All referenced props, states and importRefs should be previously defined in the
75
+ "propDefinitions" and "stateDefinitions" and "importDefinitions" sections
76
+ If props or states are defined and not used, a warning witll be displayed */
77
+ export const checkDynamicDefinitions = (input: Record<string, unknown>) => {
78
+ const propKeys = Object.keys(input.propDefinitions || {})
79
+ const stateKeys = Object.keys(input.stateDefinitions || {})
80
+ let importKeys = Object.keys(input.importDefinitions || {})
81
+ const componentStyleSetKyes = Object.keys(input.styleSetDefinitions || {})
82
+
83
+ const importDefinitions: { [key: string]: UIDLExternalDependency } = (input?.importDefinitions ??
84
+ {}) as unknown as { [key: string]: UIDLExternalDependency }
85
+
86
+ if (Object.keys(importKeys).length > 0) {
87
+ importKeys = importKeys.reduce((acc, importRef) => {
88
+ if (importDefinitions[importRef]?.meta?.importJustPath) {
89
+ return acc
90
+ }
91
+
92
+ acc.push(importRef)
93
+ return acc
94
+ }, [])
95
+ }
96
+
97
+ const usedPropKeys: string[] = []
98
+ const usedStateKeys: string[] = []
99
+ const usedImportKeys: string[] = []
100
+ const errors: string[] = []
101
+
102
+ UIDLUtils.traverseNodes(input.node as UIDLNode, (node) => {
103
+ if (node.type === 'element') {
104
+ Object.keys(node.content?.events || {}).forEach((eventKey) => {
105
+ node.content.events[eventKey].forEach((event) => {
106
+ if (event.type === 'stateChange' && !stateKeys.includes(event.modifies)) {
107
+ const errorMsg = `"${event.modifies}" is used in events, but not defined. Please add it in stateDefinitions`
108
+ errors.push(errorMsg)
109
+ return
110
+ }
111
+
112
+ if (event.type === 'propCall' && !propKeys.includes(event.calls)) {
113
+ errors.push(
114
+ `"${event.calls}" is used in events, but missing from propDefinitons. Please add it in propDefinitions `
115
+ )
116
+ return
117
+ }
118
+ })
119
+ })
120
+
121
+ const dynamicVariants: string[] = []
122
+ Object.values(node.content?.referencedStyles || {}).forEach((styleRef) => {
123
+ if (
124
+ styleRef.content.mapType === 'component-referenced' &&
125
+ styleRef.content.content.type === 'dynamic'
126
+ ) {
127
+ if (styleRef.content.content.content.referenceType === 'prop') {
128
+ const referencedProp = styleRef.content.content.content.id
129
+ if (!dynamicPathExistsInDefinitions(referencedProp, propKeys)) {
130
+ const errorMsg = `"${referencedProp}" is used but not defined. Please add it in propDefinitions`
131
+ errors.push(errorMsg)
132
+ return
133
+ }
134
+ dynamicVariants.push(referencedProp)
135
+ usedPropKeys.push(referencedProp)
136
+ }
137
+
138
+ if (styleRef.content.content.content.referenceType === 'comp') {
139
+ const compStyleRefId = styleRef.content.content.content.id
140
+
141
+ if (!componentStyleSetKyes.includes(compStyleRefId)) {
142
+ errors.push(
143
+ `${compStyleRefId} is used, but not defined in Component Style Sheet in ${input.name}. Please add it in StyleSetDefinitions of the component`
144
+ )
145
+ }
146
+ }
147
+ }
148
+ })
149
+
150
+ if (dynamicVariants.length > 1) {
151
+ errors.push(`Node ${
152
+ node.content?.name || node.content?.key
153
+ } is using multiple dynamic variants using propDefinitions.
154
+ We can have only one dynamic variant at once`)
155
+ }
156
+ }
157
+
158
+ if (node.type === 'dynamic' && node.content.referenceType === 'prop') {
159
+ if (!dynamicPathExistsInDefinitions(node.content.id, propKeys)) {
160
+ const errorMsg = `"${node.content.id}" is used but not defined. Please add it in propDefinitions`
161
+ errors.push(errorMsg)
162
+ }
163
+
164
+ // for member expression we check the root
165
+ // if value has no `.` it will be checked as it is
166
+ const dynamicIdRoot = node.content.id.split('.')[0]
167
+ usedPropKeys.push(dynamicIdRoot)
168
+ }
169
+
170
+ if (node.type === 'dynamic' && node.content.referenceType === 'state') {
171
+ if (!dynamicPathExistsInDefinitions(node.content.id, stateKeys)) {
172
+ const errorMsg = `\n"${node.content.id}" is used but not defined. Please add it in stateDefinitions`
173
+ errors.push(errorMsg)
174
+ }
175
+
176
+ // for member expression we check the root
177
+ // if value has no `.` it will be checked as it is
178
+ const dynamicIdRoot = node.content.id.split('.')[0]
179
+ usedStateKeys.push(dynamicIdRoot)
180
+ }
181
+
182
+ if (node.type === 'import') {
183
+ if (!dynamicPathExistsInDefinitions(node.content.id, importKeys)) {
184
+ const errorMsg = `\n"${node.content.id}" is used but not defined. Please add it in importDefinitions`
185
+ errors.push(errorMsg)
186
+ }
187
+
188
+ // for member expression we check the root
189
+ // if value has no `.` it will be checked as it is
190
+ const dynamicIdRoot = node.content.id.split('.')[0]
191
+ usedImportKeys.push(dynamicIdRoot)
192
+ }
193
+ })
194
+
195
+ propKeys
196
+ .filter((x) => !usedPropKeys.includes(x))
197
+ .forEach((diff) =>
198
+ console.warn(`"${diff}" is defined in propDefinitions but it is not used in the UIDL.`)
199
+ )
200
+
201
+ stateKeys
202
+ .filter((x) => !usedStateKeys.includes(x))
203
+ .forEach((diff) =>
204
+ console.warn(`"${diff}" is defined in stateDefinitions but it is not used in the UIDL.`)
205
+ )
206
+
207
+ importKeys
208
+ .filter((x) => !usedImportKeys.includes(x))
209
+ .forEach((diff) =>
210
+ console.warn(`"${diff}" is defined in importDefinitions but it is not used in the UIDL.`)
211
+ )
212
+
213
+ return errors
214
+ }
215
+
216
+ const dynamicPathExistsInDefinitions = (path: string, defKeys: string[]) => {
217
+ if (!path.includes('.')) {
218
+ // prop/state is a scalar value, not a dot notation
219
+ return defKeys.includes(path)
220
+ }
221
+
222
+ // TODO: Expand validation logic to check if the path exists on the prop/state definition
223
+ // ex: if prop reference is `user.name`, we should check that prop type is object and has a valid field name
224
+ const rootIdentifier = path.split('.')[0]
225
+ return defKeys.includes(rootIdentifier)
226
+ }
227
+
228
+ // A projectUIDL must contain "route" key
229
+ export const checkRouteDefinition = (input: ProjectUIDL) => {
230
+ const errors = []
231
+
232
+ const keys = Object.keys(input.root.stateDefinitions || {})
233
+ if (!keys.includes('route')) {
234
+ const errorMsg = 'Route is not defined in stateDefinitions'
235
+ errors.push(errorMsg)
236
+ }
237
+ return errors
238
+ }
239
+
240
+ // All referenced components inside of the projectUIDL should be defined
241
+ // in the components section and all the project-referenced styles and tokens
242
+ export const checkComponentExistenceAndReferences = (input: ProjectUIDL) => {
243
+ const errors: string[] = []
244
+ const components = Object.keys(input.components || {})
245
+ const styleSetDefinitions = Object.keys(input.root?.styleSetDefinitions || {})
246
+ const tokens: string[] = Object.keys(input.root?.designLanguage?.tokens || {})
247
+ const nodesToParse = [
248
+ input.root.node,
249
+ ...Object.values(input.components || {}).map((component) => component.node),
250
+ ]
251
+ let usedReferencedStyles: string[] = []
252
+
253
+ if (input.root?.styleSetDefinitions) {
254
+ Object.values(input.root.styleSetDefinitions || {}).forEach((style) => {
255
+ const { content, conditions = [] } = style
256
+ errors.push(...checkForTokensInstyles(content, tokens))
257
+ conditions.forEach((condition) => {
258
+ if (condition?.content) {
259
+ errors.push(...checkForTokensInstyles(condition.content, tokens))
260
+ }
261
+ })
262
+ })
263
+ }
264
+
265
+ nodesToParse.forEach((node) => {
266
+ UIDLUtils.traverseElements(node, (element) => {
267
+ /* Checking for project-referenced styles */
268
+ if (element?.referencedStyles) {
269
+ const { errorsInRferences, usedStyleRefrences } = checkForReferencedStylesUsed(
270
+ element.referencedStyles,
271
+ styleSetDefinitions,
272
+ tokens
273
+ )
274
+ errors.push(...errorsInRferences)
275
+ usedReferencedStyles = [...usedReferencedStyles, ...usedStyleRefrences]
276
+ }
277
+
278
+ /* Checking for token references used in styles */
279
+ if (element?.style) {
280
+ errors.push(...checkForTokensInstyles(element.style, tokens))
281
+ }
282
+
283
+ if (
284
+ element.dependency &&
285
+ element.dependency.type === 'local' &&
286
+ !components.includes(element.semanticType)
287
+ ) {
288
+ const errorMsg = `\nThe component "${element.semanticType}" is not defined in the UIDL's component section.`
289
+ errors.push(errorMsg)
290
+ }
291
+ })
292
+ })
293
+
294
+ styleSetDefinitions.forEach((key) => {
295
+ if (!usedReferencedStyles.includes(key)) {
296
+ console.warn(`${key} styleSet is defined but not used in the project.`)
297
+ }
298
+ })
299
+
300
+ return errors
301
+ }
302
+
303
+ const checkForReferencedStylesUsed = (
304
+ referencedStyles: UIDLReferencedStyles,
305
+ styleSetDefinitions: string[],
306
+ tokens: string[]
307
+ ) => {
308
+ const errorsInRferences: string[] = []
309
+ const usedStyleRefrences: string[] = []
310
+ Object.values(referencedStyles || {}).forEach((styleRef) => {
311
+ const { mapType } = styleRef.content
312
+
313
+ if (mapType === 'inlined') {
314
+ errorsInRferences.push(
315
+ ...checkForTokensInstyles(
316
+ (styleRef as UIDLElementNodeInlineReferencedStyle).content.styles,
317
+ tokens
318
+ )
319
+ )
320
+ }
321
+
322
+ if (mapType === 'project-referenced') {
323
+ const { referenceId } = (styleRef as UIDLElementNodeProjectReferencedStyle).content
324
+ usedStyleRefrences.push(referenceId)
325
+ if (!styleSetDefinitions.includes(referenceId)) {
326
+ errorsInRferences.push(
327
+ `\n ${referenceId} is missing from the styleSetDefinitions, please check the reference id.`
328
+ )
329
+ }
330
+ }
331
+ })
332
+ return {
333
+ errorsInRferences,
334
+ usedStyleRefrences,
335
+ }
336
+ }
337
+
338
+ const checkForTokensInstyles = (styles: Record<string, UIDLStyleValue>, tokens: string[]) => {
339
+ const errors: string[] = []
340
+ Object.values(styles || {}).forEach((style: UIDLStyleValue) => {
341
+ if (
342
+ style.type === 'dynamic' &&
343
+ style.content.referenceType === 'token' &&
344
+ !tokens.includes(style.content.id)
345
+ ) {
346
+ errors.push(`\nToken ${style.content.id} is missing from the project UIDL.`)
347
+ }
348
+ })
349
+ return errors
350
+ }
351
+
352
+ // All components should have the same key as the value of their name key
353
+ // Example:
354
+ // "components": {
355
+ // "OneComponent": {
356
+ // "name": "OneComponent",
357
+ // ..
358
+ // }
359
+ // }
360
+ export const checkComponentNaming = (input: ProjectUIDL) => {
361
+ const errors: string[] = []
362
+ const namesUsed = Object.keys(input.components || {})
363
+
364
+ const diffs = namesUsed.filter((name) => input.components[name].name !== name)
365
+
366
+ if (diffs.length > 0) {
367
+ const errorMsg = `\nThe following components have different name than their key: ${diffs}`
368
+ errors.push(errorMsg)
369
+ }
370
+
371
+ return errors
372
+ }
373
+
374
+ export const checkProjectStyleSet = (input: ProjectUIDL) => {
375
+ const errors: string[] = []
376
+ const styleSet = input.root.styleSetDefinitions
377
+ if (styleSet) {
378
+ Object.values(styleSet).forEach((styleSetObj: UIDLStyleSetDefinition) => {
379
+ const { content, conditions = [] } = styleSetObj
380
+
381
+ Object.values(conditions).forEach((style) => {
382
+ errors.push(...checStylekContentForErrors(style.content))
383
+ })
384
+
385
+ errors.push(...checStylekContentForErrors(content))
386
+ })
387
+ }
388
+ return errors
389
+ }
390
+
391
+ export const checStylekContentForErrors = (
392
+ content: Record<string, UIDLStaticValue | UIDLStyleSetTokenReference>
393
+ ) => {
394
+ const errors: string[] = []
395
+ Object.values(content).forEach((styleContent) => {
396
+ if (styleContent.type === 'dynamic' && styleContent.content.referenceType !== 'token') {
397
+ errors.push(`Dynamic nodes in styleSetDefinitions supports only tokens`)
398
+ }
399
+
400
+ if (
401
+ styleContent.type === 'static' &&
402
+ typeof styleContent.content !== 'string' &&
403
+ typeof styleContent.content !== 'number'
404
+ ) {
405
+ errors.push(
406
+ `Project Style sheet / styleSetDefinitions only support styles with static
407
+ content and dynamic tokens, received ${styleContent}`
408
+ )
409
+ }
410
+ })
411
+ return errors
412
+ }
413
+
414
+ // The "root" node should contain only elements of type "conditional"
415
+ export const checkRootComponent = (input: ProjectUIDL) => {
416
+ const errors = []
417
+ const routeNaming: string[] = []
418
+ const rootNode = input.root.node.content as UIDLElement
419
+ rootNode.children.forEach((child) => {
420
+ if (child.type !== 'conditional') {
421
+ const errorMsg = `\nRoot Node contains elements of type "${child.type}". It should contain only elements of type "conditional"`
422
+ errors.push(errorMsg)
423
+ } else {
424
+ routeNaming.push(child.content.value.toString())
425
+ }
426
+ })
427
+
428
+ const routeValues = input.root.stateDefinitions.route.values
429
+ if (!routeValues || routeValues.length <= 0) {
430
+ errors.push(
431
+ '\nThe `route` state definition from the root node does not contain the possible route values'
432
+ )
433
+ } else {
434
+ input.root.stateDefinitions.route.values
435
+ .filter((route) => !routeNaming.includes(route.value.toString()))
436
+ .forEach((route) => {
437
+ const errorMsg = `\nRoot Node contains a route that don't have a specified state: ${route.value}.`
438
+ errors.push(errorMsg)
439
+ })
440
+ }
441
+
442
+ return errors
443
+ }
444
+
445
+ // The errors should be displayed in a human-readeable way
446
+ export const formatErrors = (errors: Array<{ kind: string; at: string; message: string }>) => {
447
+ const listOfErrors: string[] = []
448
+ errors.forEach((error) => {
449
+ const message = `\n - Path ${error.at}: ${error.message}. \n is a ${error.kind} \n`
450
+ listOfErrors.push(message)
451
+ })
452
+
453
+ return `UIDL Format Validation Error. Please check the following: ${listOfErrors}`
454
+ }
455
+
456
+ export const validateNulls = (uidl: Record<string, unknown>) => {
457
+ return JSON.parse(JSON.stringify(uidl), (key, value) => {
458
+ if (value === undefined || value == null) {
459
+ throw new ComponentValidationError(`Validation error, Received ${value} at ${key}`)
460
+ }
461
+ return value
462
+ })
463
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,9 @@
1
+ {
2
+ "extends": "../../tsconfig.json",
3
+ "compilerOptions": {
4
+ "outDir": "dist/esm"
5
+ },
6
+ "include": [
7
+ "./src"
8
+ ]
9
+ }