@komaci/common-shared 240.1.3

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.
@@ -0,0 +1,120 @@
1
+ import { ClassPropertyContext, ClassPropertyContexts, ImportPropertyContext, InputTraversalCallback, PropertyTypes, WirePropertyContext } from './types';
2
+ import { FunctionType, FunctionReference, KomaciDocument, Property, Import, Adg, Value, Composition, ComposedAdg, Iteration, Binding, Image, PrimitiveValue } from '@komaci/types';
3
+ /**
4
+ * Check if the composition is an Iteration
5
+ * @param composition composition obj to check
6
+ * @returns if composition is an Iteration
7
+ */
8
+ export declare function isCompositionAnIteration(composition: Composition): composition is Iteration;
9
+ /**
10
+ * Check if the composition is a ComposedAdg
11
+ * @param composition composition obj to check
12
+ * @returns if composition is a ComposedAdg
13
+ */
14
+ export declare function isCompositionAComposedAdg(composition: Composition): composition is ComposedAdg;
15
+ /**
16
+ * Type guard: Check if the given Composition is an Image
17
+ * @param {Composition} composition the compositions whose type we will check
18
+ * @returns {boolean} true if this Composition is an Image, false if not
19
+ */
20
+ export declare function isCompositionAnImage(composition: Composition): composition is Image;
21
+ /**
22
+ * Type guard: Check if the given src attribute is a PrimitiveValue
23
+ * @param {PrimitiveValue | Binding} src the attribute whose type we will check
24
+ * @returns {boolean} true if the input attribute was a PrimitiveValue, false if it is not
25
+ */
26
+ export declare function isSrcPrimitiveValue(src: PrimitiveValue | Binding): src is PrimitiveValue;
27
+ /**
28
+ * Type guard: Check if the given src attribute is a Binding
29
+ * @param {Binding | PrimitiveValue} src the attribute whose type we will check
30
+ * @returns {boolean} true if the input attribute was a Binding, false if it was a Primitive Value
31
+ */
32
+ export declare function isSrcABinding(src: Binding | PrimitiveValue): src is Binding;
33
+ /**
34
+ * Check if input is a Function reference
35
+ * @param node input to check
36
+ * @returns if it is a function reference
37
+ */
38
+ export declare function isFunctionReference(node: Property['input']): node is FunctionReference;
39
+ /**
40
+ * Confirm if a function object is of a specfic type
41
+ * @param type The type to validate against
42
+ * @param detail the property detail that references the function
43
+ * @param functions The function array to look in for the referenced function
44
+ * @returns If the referenced function matches the provided type
45
+ */
46
+ export declare function isAFunctionOfType(type: string, detail: Property, functions?: FunctionType[]): boolean;
47
+ /**
48
+ * Helper to check if a referenced import in a Komaci Doc is defined
49
+ * @param importIndex The import index to view
50
+ * @param nameIndex The index in the names key of an import to view
51
+ * @param imports The full array of import objects
52
+ * @returns if it is good or not
53
+ */
54
+ export declare function isImportValid(importIndex: number, nameIndex: number, imports?: Import[]): boolean;
55
+ /**
56
+ * In Komaci Documents, if a value is referenced like record.data.key, it shows up as record/data/key.
57
+ * record is the property we care about so if we are in one of these cases we want to strip off everything after the slash
58
+ * @param value
59
+ * @returns
60
+ */
61
+ export declare function stripChildReferenceFromValue(value: string): string;
62
+ /**
63
+ * Inflate a map with Class Property metadata in the most generic way possible so later we can update as needed.
64
+ *
65
+ * This function along with collectPropertyMetadataFromScriptDoc and updatePropertyMetadataFromTemplateDoc can be
66
+ * called in sequence to get all the needful data about properties for a given set of komaci documents. Currently
67
+ * consumed directly in modGenScript and static-analyzer so check to see if this has already been called
68
+ * before calling it
69
+ *
70
+ * @param component The component ADG to process
71
+ * @param doc The full komaci doc we are looking in
72
+ * @returns The inflated properties map
73
+ */
74
+ export declare function initializePropertiesMap(component: Adg, doc: KomaciDocument, properties: ClassPropertyContexts): ClassPropertyContexts;
75
+ /**
76
+ * Traverse the input of a Function object (as definged in a Komaci Document) generically. When we get to a specific value
77
+ * in the tree, we run the provided callback. The callback can return `true` if we should stop
78
+ * traversal down this path.
79
+ *
80
+ * @param input Function Input
81
+ * @param cb Callback to trigger for any "Real" value
82
+ * @param key Sometimes as we go through the tree, a real value will be mapped to some key in a higher
83
+ * context so we make that available in case consumers need it
84
+ * @returns If we have stopped traversal down this path
85
+ */
86
+ export declare function traverseInput(input: Value | Value[], cb: InputTraversalCallback, key?: string): boolean;
87
+ export declare function traverseParentAdgs(component: Adg, doc: KomaciDocument, cb: (component: Adg) => void): void;
88
+ /**
89
+ * Traverse the Komaci Document for a script file and collect property usages.
90
+ *
91
+ * This function:
92
+ * 1. prepares the properties object with initial values
93
+ * 2. collects usages of properties from wire functions
94
+ * @param doc Komaci Script Doc to traverse
95
+ * @returns contextual information about properties
96
+ */
97
+ export declare function collectPropertyMetadataFromScriptDoc(doc: KomaciDocument): ClassPropertyContexts;
98
+ /**
99
+ * Recursively probe a composition and it's children for usages of properties.
100
+ * @param composition Current composition
101
+ * @param properties The map of properties to update
102
+ */
103
+ export declare function updatePropertiesForComposition(composition: Composition, properties: ClassPropertyContexts): void;
104
+ /**
105
+ * Collect usages of properties from compositions in a Komaci Template Document
106
+ * @param doc Komaci Document
107
+ * @param properties The current map of properties, this is just updating them.
108
+ */
109
+ export declare function updatePropertyMetadataFromTemplateDoc(doc: KomaciDocument, properties: ClassPropertyContexts): void;
110
+ /**
111
+ * Updates used properties to record whether they were used in Priming.
112
+ * @param prop the name of the getter under consideration
113
+ * @param identifiers list of member identifiers used in getters
114
+ * @param properties Map for all class properties and their basic, KomaciDoc analyzable metadata.
115
+ * @param type The property type so we can make sure the metadata has the right value
116
+ */
117
+ export declare function updatePropertyUsage(prop: string, identifiers: string[], properties: ClassPropertyContexts, type: PropertyTypes): void;
118
+ export declare function isPropertyAWire(property: ClassPropertyContext): property is WirePropertyContext;
119
+ export declare function isPropertyFromImport(property: ClassPropertyContext): property is ImportPropertyContext;
120
+ //# sourceMappingURL=komaciDocumentIntrospection.d.ts.map
@@ -0,0 +1,366 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.isPropertyFromImport = exports.isPropertyAWire = exports.updatePropertyUsage = exports.updatePropertyMetadataFromTemplateDoc = exports.updatePropertiesForComposition = exports.collectPropertyMetadataFromScriptDoc = exports.traverseParentAdgs = exports.traverseInput = exports.initializePropertiesMap = exports.stripChildReferenceFromValue = exports.isImportValid = exports.isAFunctionOfType = exports.isFunctionReference = exports.isSrcABinding = exports.isSrcPrimitiveValue = exports.isCompositionAnImage = exports.isCompositionAComposedAdg = exports.isCompositionAnIteration = void 0;
4
+ const types_1 = require("./types");
5
+ /**
6
+ * Check if the composition is an Iteration
7
+ * @param composition composition obj to check
8
+ * @returns if composition is an Iteration
9
+ */
10
+ function isCompositionAnIteration(composition) {
11
+ return composition?.type === 'Iteration';
12
+ }
13
+ exports.isCompositionAnIteration = isCompositionAnIteration;
14
+ /**
15
+ * Check if the composition is a ComposedAdg
16
+ * @param composition composition obj to check
17
+ * @returns if composition is a ComposedAdg
18
+ */
19
+ function isCompositionAComposedAdg(composition) {
20
+ return composition?.type === 'ComposedAdg';
21
+ }
22
+ exports.isCompositionAComposedAdg = isCompositionAComposedAdg;
23
+ /**
24
+ * Type guard: Check if the given Composition is an Image
25
+ * @param {Composition} composition the compositions whose type we will check
26
+ * @returns {boolean} true if this Composition is an Image, false if not
27
+ */
28
+ function isCompositionAnImage(composition) {
29
+ return composition?.type === 'Image';
30
+ }
31
+ exports.isCompositionAnImage = isCompositionAnImage;
32
+ /**
33
+ * Type guard: Check if the given src attribute is a PrimitiveValue
34
+ * @param {PrimitiveValue | Binding} src the attribute whose type we will check
35
+ * @returns {boolean} true if the input attribute was a PrimitiveValue, false if it is not
36
+ */
37
+ function isSrcPrimitiveValue(src) {
38
+ return src.type === 'PrimitiveValue';
39
+ }
40
+ exports.isSrcPrimitiveValue = isSrcPrimitiveValue;
41
+ /**
42
+ * Type guard: Check if the given src attribute is a Binding
43
+ * @param {Binding | PrimitiveValue} src the attribute whose type we will check
44
+ * @returns {boolean} true if the input attribute was a Binding, false if it was a Primitive Value
45
+ */
46
+ function isSrcABinding(src) {
47
+ return src.type === 'Binding' && typeof src.value === 'string';
48
+ }
49
+ exports.isSrcABinding = isSrcABinding;
50
+ /**
51
+ * Check if input is a Function reference
52
+ * @param node input to check
53
+ * @returns if it is a function reference
54
+ */
55
+ function isFunctionReference(node) {
56
+ return node?.type === 'FunctionReference';
57
+ }
58
+ exports.isFunctionReference = isFunctionReference;
59
+ /**
60
+ * Confirm if a function object is of a specfic type
61
+ * @param type The type to validate against
62
+ * @param detail the property detail that references the function
63
+ * @param functions The function array to look in for the referenced function
64
+ * @returns If the referenced function matches the provided type
65
+ */
66
+ function isAFunctionOfType(type, detail, functions) {
67
+ return (isFunctionReference(detail.input) &&
68
+ functions?.[detail.input.value]?.type === type);
69
+ }
70
+ exports.isAFunctionOfType = isAFunctionOfType;
71
+ /**
72
+ * Helper to check if a referenced import in a Komaci Doc is defined
73
+ * @param importIndex The import index to view
74
+ * @param nameIndex The index in the names key of an import to view
75
+ * @param imports The full array of import objects
76
+ * @returns if it is good or not
77
+ */
78
+ function isImportValid(importIndex, nameIndex, imports) {
79
+ return imports?.[importIndex]?.names?.[nameIndex] !== undefined;
80
+ }
81
+ exports.isImportValid = isImportValid;
82
+ /**
83
+ * In Komaci Documents, if a value is referenced like record.data.key, it shows up as record/data/key.
84
+ * record is the property we care about so if we are in one of these cases we want to strip off everything after the slash
85
+ * @param value
86
+ * @returns
87
+ */
88
+ function stripChildReferenceFromValue(value) {
89
+ let result = value;
90
+ const index = value.indexOf('/');
91
+ if (index !== -1) {
92
+ result = value.substring(0, index);
93
+ }
94
+ return result;
95
+ }
96
+ exports.stripChildReferenceFromValue = stripChildReferenceFromValue;
97
+ /**
98
+ * Inflate a map with Class Property metadata in the most generic way possible so later we can update as needed.
99
+ *
100
+ * This function along with collectPropertyMetadataFromScriptDoc and updatePropertyMetadataFromTemplateDoc can be
101
+ * called in sequence to get all the needful data about properties for a given set of komaci documents. Currently
102
+ * consumed directly in modGenScript and static-analyzer so check to see if this has already been called
103
+ * before calling it
104
+ *
105
+ * @param component The component ADG to process
106
+ * @param doc The full komaci doc we are looking in
107
+ * @returns The inflated properties map
108
+ */
109
+ function initializePropertiesMap(component, doc, properties) {
110
+ if (component.properties) {
111
+ for (const [name, detail] of Object.entries(component.properties)) {
112
+ const property = {
113
+ usedInPriming: false,
114
+ type: types_1.PropertyTypes.INTERNAL,
115
+ };
116
+ if (detail.isPublic) {
117
+ property.type = types_1.PropertyTypes.PUBLIC;
118
+ }
119
+ else if (isAFunctionOfType('WireFunction', detail, component.functions) &&
120
+ doc.imports) {
121
+ //ts rules and this is how types work ig
122
+ const functionDetail = component.functions?.[detail.input.value];
123
+ if (functionDetail) {
124
+ const importIndex = parseInt(functionDetail.reference.value.charAt(0));
125
+ const nameIndex = parseInt(functionDetail?.reference.value.charAt(functionDetail?.reference.value.length - 1));
126
+ if (isImportValid(importIndex, nameIndex, doc.imports)) {
127
+ property.type = types_1.PropertyTypes.WIRE;
128
+ property.usedInPriming = true;
129
+ property.wire = {
130
+ name: doc.imports[importIndex].names[nameIndex],
131
+ resourceName: doc.imports[importIndex].resourceName,
132
+ komaciDocImportRef: functionDetail.reference.value,
133
+ };
134
+ }
135
+ }
136
+ }
137
+ if (detail.initial?.type === 'ImportReference' && doc.imports) {
138
+ const importIndex = parseInt(detail.initial.value.charAt(0));
139
+ const nameIndex = parseInt(detail.initial.value.charAt(detail.initial.value.length - 1));
140
+ if (isImportValid(importIndex, nameIndex, doc.imports)) {
141
+ property.imports = {
142
+ [detail.initial.value]: {
143
+ name: doc.imports[importIndex].names[nameIndex],
144
+ resourceName: doc.imports[importIndex].resourceName,
145
+ komaciDocImportRef: detail.initial.value,
146
+ },
147
+ };
148
+ }
149
+ }
150
+ else if (detail.initial && doc.imports) {
151
+ const imports = {};
152
+ let totalImportRefs = 0;
153
+ traverseInput(detail.initial, (potentialImportRef) => {
154
+ if (potentialImportRef.type === 'ImportReference') {
155
+ totalImportRefs++;
156
+ const importIndex = parseInt(potentialImportRef.value.charAt(0));
157
+ const nameIndex = parseInt(potentialImportRef.value.charAt(potentialImportRef.value.length - 1));
158
+ if (doc.imports &&
159
+ isImportValid(importIndex, nameIndex, doc.imports)) {
160
+ imports[potentialImportRef.value] = {
161
+ name: doc.imports[importIndex].names[nameIndex],
162
+ resourceName: doc.imports[importIndex].resourceName,
163
+ komaciDocImportRef: potentialImportRef.value,
164
+ };
165
+ }
166
+ }
167
+ return false;
168
+ });
169
+ if (totalImportRefs !== 0) {
170
+ property.imports = imports;
171
+ }
172
+ }
173
+ properties.set(name, property);
174
+ }
175
+ }
176
+ return properties;
177
+ }
178
+ exports.initializePropertiesMap = initializePropertiesMap;
179
+ /**
180
+ * Traverse the input of a Function object (as definged in a Komaci Document) generically. When we get to a specific value
181
+ * in the tree, we run the provided callback. The callback can return `true` if we should stop
182
+ * traversal down this path.
183
+ *
184
+ * @param input Function Input
185
+ * @param cb Callback to trigger for any "Real" value
186
+ * @param key Sometimes as we go through the tree, a real value will be mapped to some key in a higher
187
+ * context so we make that available in case consumers need it
188
+ * @returns If we have stopped traversal down this path
189
+ */
190
+ function traverseInput(input, cb, key) {
191
+ let shouldEarlyExit = false;
192
+ if (!Array.isArray(input) &&
193
+ !(input.type === 'ArrayValue' || input.type === 'ObjectValue')) {
194
+ shouldEarlyExit = cb(input, key);
195
+ }
196
+ else if (Array.isArray(input)) {
197
+ let i = 0;
198
+ while (!shouldEarlyExit && i < input.length) {
199
+ shouldEarlyExit = traverseInput(input[i], cb);
200
+ i++;
201
+ }
202
+ }
203
+ else if (input.type === 'ObjectValue') {
204
+ const entries = Object.entries(input.value);
205
+ let i = 0;
206
+ while (!shouldEarlyExit && i < entries.length) {
207
+ shouldEarlyExit = traverseInput(entries[i][1], cb, entries[i][0]);
208
+ i++;
209
+ }
210
+ }
211
+ else if (input.type === 'ArrayValue') {
212
+ const entries = input.value;
213
+ let i = 0;
214
+ while (!shouldEarlyExit && i < entries.length) {
215
+ shouldEarlyExit = traverseInput(entries[i], cb);
216
+ i++;
217
+ }
218
+ }
219
+ return shouldEarlyExit;
220
+ }
221
+ exports.traverseInput = traverseInput;
222
+ function traverseParentAdgs(component, doc, cb) {
223
+ if (component.parentClass &&
224
+ component.parentClass.type === 'AdgReference' &&
225
+ doc.adgs?.[component.parentClass.value]) {
226
+ traverseParentAdgs(doc.adgs?.[component.parentClass.value], doc, cb);
227
+ }
228
+ cb(component);
229
+ }
230
+ exports.traverseParentAdgs = traverseParentAdgs;
231
+ /**
232
+ * Traverse the Komaci Document for a script file and collect property usages.
233
+ *
234
+ * This function:
235
+ * 1. prepares the properties object with initial values
236
+ * 2. collects usages of properties from wire functions
237
+ * @param doc Komaci Script Doc to traverse
238
+ * @returns contextual information about properties
239
+ */
240
+ function collectPropertyMetadataFromScriptDoc(doc) {
241
+ if (doc?.exports?.default?.type === 'AdgReference' &&
242
+ doc?.adgs?.[doc.exports?.default?.value]) {
243
+ const component = doc.adgs[doc.exports.default.value];
244
+ let properties = new Map();
245
+ traverseParentAdgs(component, doc, (currentComponent) => {
246
+ properties = initializePropertiesMap(currentComponent, doc, properties);
247
+ for (const functionDetail of currentComponent.functions || []) {
248
+ if (functionDetail.type === 'WireFunction' && functionDetail.input) {
249
+ traverseInput(functionDetail.input, (value) => {
250
+ if (value.type === 'PropertyReference' &&
251
+ properties.has(value.value)) {
252
+ const property = properties.get(value.value);
253
+ if (property) {
254
+ property.usedInPriming = true;
255
+ }
256
+ }
257
+ return false;
258
+ });
259
+ }
260
+ }
261
+ });
262
+ return properties;
263
+ }
264
+ return new Map();
265
+ }
266
+ exports.collectPropertyMetadataFromScriptDoc = collectPropertyMetadataFromScriptDoc;
267
+ /**
268
+ * Helper to clean up a potential property, see if it exists and update if it does
269
+ * @param value potential property. could be in the form of record/data/whatever
270
+ * @param properties map of properties
271
+ * @param key key to update
272
+ */
273
+ function updatePropertyIfExists(value, properties, key) {
274
+ const cleanedUpValue = stripChildReferenceFromValue(value);
275
+ if (properties.has(cleanedUpValue)) {
276
+ const property = properties.get(cleanedUpValue);
277
+ properties.set(cleanedUpValue, {
278
+ ...property,
279
+ [key]: true,
280
+ });
281
+ }
282
+ }
283
+ /**
284
+ * Recursively probe a composition and it's children for usages of properties.
285
+ * @param composition Current composition
286
+ * @param properties The map of properties to update
287
+ */
288
+ function updatePropertiesForComposition(composition, properties) {
289
+ if (composition && composition.key) {
290
+ const container = composition;
291
+ if (container.key && container.key.type === 'Binding') {
292
+ updatePropertyIfExists(container.key.value, properties, 'usedInPriming');
293
+ }
294
+ }
295
+ if (composition && composition.isActive) {
296
+ updatePropertyIfExists(composition.isActive.input.value, properties, 'usedInPriming');
297
+ }
298
+ if (isCompositionAnIteration(composition)) {
299
+ updatePropertyIfExists(composition.input.value, properties, 'usedInPriming');
300
+ }
301
+ if (isCompositionAComposedAdg(composition) && composition.properties) {
302
+ for (const property of Object.values(composition.properties || {})) {
303
+ if (property.type === 'Binding') {
304
+ updatePropertyIfExists(property.value, properties, 'usedInPriming');
305
+ }
306
+ }
307
+ if (composition.input.type === 'Binding') {
308
+ updatePropertyIfExists(composition.input.value, properties, 'usedInPriming');
309
+ }
310
+ }
311
+ if (isCompositionAnImage(composition)) {
312
+ // if img.src is a Binding, then let's update the property to note it is used in Priming
313
+ if (isSrcABinding(composition.src)) {
314
+ const binding = composition.src;
315
+ updatePropertyIfExists(binding.value, properties, 'usedInPriming');
316
+ }
317
+ }
318
+ if (composition && composition.compositions) {
319
+ for (const value of composition.compositions) {
320
+ updatePropertiesForComposition(value, properties);
321
+ }
322
+ }
323
+ }
324
+ exports.updatePropertiesForComposition = updatePropertiesForComposition;
325
+ /**
326
+ * Collect usages of properties from compositions in a Komaci Template Document
327
+ * @param doc Komaci Document
328
+ * @param properties The current map of properties, this is just updating them.
329
+ */
330
+ function updatePropertyMetadataFromTemplateDoc(doc, properties) {
331
+ if (doc?.exports?.default?.type === 'CompositionReference' &&
332
+ doc.compositions?.[doc.exports.default.value]) {
333
+ const composition = doc.compositions[doc.exports.default.value];
334
+ updatePropertiesForComposition(composition, properties);
335
+ }
336
+ }
337
+ exports.updatePropertyMetadataFromTemplateDoc = updatePropertyMetadataFromTemplateDoc;
338
+ /**
339
+ * Updates used properties to record whether they were used in Priming.
340
+ * @param prop the name of the getter under consideration
341
+ * @param identifiers list of member identifiers used in getters
342
+ * @param properties Map for all class properties and their basic, KomaciDoc analyzable metadata.
343
+ * @param type The property type so we can make sure the metadata has the right value
344
+ */
345
+ function updatePropertyUsage(prop, identifiers, properties, type) {
346
+ const getterProperty = properties.get(prop);
347
+ if (getterProperty) {
348
+ getterProperty.type = type;
349
+ }
350
+ identifiers.forEach((identifier) => {
351
+ const property = properties.get(identifier);
352
+ if (property && getterProperty?.usedInPriming) {
353
+ property.usedInPriming = true;
354
+ }
355
+ });
356
+ }
357
+ exports.updatePropertyUsage = updatePropertyUsage;
358
+ function isPropertyAWire(property) {
359
+ return property.type === types_1.PropertyTypes.WIRE;
360
+ }
361
+ exports.isPropertyAWire = isPropertyAWire;
362
+ function isPropertyFromImport(property) {
363
+ return property.imports !== undefined;
364
+ }
365
+ exports.isPropertyFromImport = isPropertyFromImport;
366
+ //# sourceMappingURL=komaciDocumentIntrospection.js.map
@@ -0,0 +1,9 @@
1
+ import { File } from '@babel/types';
2
+ /**
3
+ * Function that consumes src code from the LWC compiler and returns an AST
4
+ * Note that there is a possibility of babel throwning an error while parsing src code.
5
+ * @param srcCode code that will be getting paresd by babel.
6
+ * @returns an ast representation of the provided srcCode
7
+ */
8
+ export declare function generateAstFromSrcCode(srcCode: string): File;
9
+ //# sourceMappingURL=parser.d.ts.map
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.generateAstFromSrcCode = void 0;
4
+ const parser_1 = require("@babel/parser");
5
+ /**
6
+ * Function that consumes src code from the LWC compiler and returns an AST
7
+ * Note that there is a possibility of babel throwning an error while parsing src code.
8
+ * @param srcCode code that will be getting paresd by babel.
9
+ * @returns an ast representation of the provided srcCode
10
+ */
11
+ function generateAstFromSrcCode(srcCode) {
12
+ const ast = (0, parser_1.parse)(srcCode, {
13
+ sourceType: 'module',
14
+ plugins: [['decorators', { decoratorsBeforeExport: true }]],
15
+ });
16
+ return ast;
17
+ }
18
+ exports.generateAstFromSrcCode = generateAstFromSrcCode;
19
+ //# sourceMappingURL=parser.js.map