@komaci/esm-generator 242.0.0 → 242.1.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 (41) hide show
  1. package/build/__tests__/adgAstGeneration.spec.d.ts +2 -0
  2. package/build/__tests__/adgAstGeneration.spec.js +31 -0
  3. package/build/__tests__/compositionAstGeneration.spec.d.ts +2 -0
  4. package/build/__tests__/compositionAstGeneration.spec.js +394 -0
  5. package/build/__tests__/functionAstGeneration.spec.d.ts +2 -0
  6. package/build/__tests__/functionAstGeneration.spec.js +412 -0
  7. package/build/__tests__/general-komaci-docs/template-component/source.js +3 -3
  8. package/build/__tests__/genericAstGeneration.spec.d.ts +2 -0
  9. package/build/__tests__/genericAstGeneration.spec.js +586 -0
  10. package/build/__tests__/index.spec.js +8 -8
  11. package/build/__tests__/komaci-ast-unit.spec.js +240 -448
  12. package/build/__tests__/komaci-bundle-module.fixtures.spec.js +1 -0
  13. package/build/__tests__/komaci-script-module.fixtures.spec.js +5 -1
  14. package/build/__tests__/komaci-template-module.fixtures.spec.js +2 -1
  15. package/build/componentAstProcessing.d.ts +34 -0
  16. package/build/componentAstProcessing.js +105 -0
  17. package/build/compositionAstGeneration.d.ts +76 -0
  18. package/build/compositionAstGeneration.js +299 -0
  19. package/build/functionAstGeneration.d.ts +81 -0
  20. package/build/functionAstGeneration.js +337 -0
  21. package/build/genericAstGeneration.d.ts +107 -0
  22. package/build/genericAstGeneration.js +600 -0
  23. package/build/index.d.ts +2 -3
  24. package/build/index.js +19 -36
  25. package/build/types.d.ts +13 -2
  26. package/build/types.js +69 -1
  27. package/package.json +4 -4
  28. package/build/__tests__/modGenScript.spec.d.ts +0 -2
  29. package/build/__tests__/modGenScript.spec.js +0 -110
  30. package/build/__tests__/modGenTemplate.spec.d.ts +0 -2
  31. package/build/__tests__/modGenTemplate.spec.js +0 -196
  32. package/build/__tests__/shared.spec.d.ts +0 -2
  33. package/build/__tests__/shared.spec.js +0 -66
  34. package/build/__tests__/templateStrings.spec.d.ts +0 -2
  35. package/build/__tests__/templateStrings.spec.js +0 -130
  36. package/build/modGenScript.d.ts +0 -38
  37. package/build/modGenScript.js +0 -1031
  38. package/build/modGenTemplate.d.ts +0 -37
  39. package/build/modGenTemplate.js +0 -406
  40. package/build/shared.d.ts +0 -149
  41. package/build/shared.js +0 -480
@@ -1,1031 +0,0 @@
1
- "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || function (mod) {
19
- if (mod && mod.__esModule) return mod;
20
- var result = {};
21
- if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
- __setModuleDefault(result, mod);
23
- return result;
24
- };
25
- Object.defineProperty(exports, "__esModule", { value: true });
26
- exports.produceErrorAdgFunction = exports.generateCombinedModule = exports.updateImportsWithGetterConsumption = exports.generateScriptModule = void 0;
27
- /* eslint-disable @typescript-eslint/no-use-before-define */
28
- const t = __importStar(require("@babel/types"));
29
- const static_analyzer_1 = require("@komaci/static-analyzer");
30
- const shared_1 = require("./shared");
31
- const types_1 = require("./types");
32
- const modGenTemplate_1 = require("./modGenTemplate");
33
- const common_shared_1 = require("@komaci/common-shared");
34
- const IMPORT_TARGET = 'importTarget';
35
- const FUNC_NAME_IMPORT = 'import';
36
- const CONST_TYPE = 'const';
37
- const CONTEXT_MAPPING = {
38
- cpr: 'CurrentPageReference',
39
- };
40
- /**
41
- * Generate the resolvable module for a single JS Script
42
- * @param {GeneratorState} generatorState the state of the ESM generator
43
- * @param {KomaciDocument} komaciDoc the KomaciDocument representation of the JS Script
44
- * @returns {File} babel/types File representation of the entire JS Script. In other works, the Abstract systax tree
45
- * of the generated resolvable module.
46
- */
47
- function generateScriptModule(generatorState, komaciDoc) {
48
- const statements = [];
49
- // gathers information about properties in a JS class and whether they are being used by wire functions
50
- const properties = (0, common_shared_1.collectPropertyMetadataFromScriptDoc)(komaciDoc);
51
- const src = (0, shared_1.getComponentSrcJs)(generatorState);
52
- const moduleLevelConsumption = {
53
- consumedImports: new Map(),
54
- };
55
- let processedGetterContext;
56
- let processedTemplateStrings;
57
- if (src) {
58
- const ast = (0, common_shared_1.generateAstFromSrcCode)(src);
59
- generatorState.scriptGenState.ast = ast;
60
- const { getters, templateStrings } = (0, common_shared_1.getPropertyMetadataFromAst)(ast);
61
- const moduleContext = {
62
- astContext: (0, common_shared_1.getAstContextObject)(ast),
63
- isExternal: (0, common_shared_1.isExternalModule)(generatorState.input.moduleInfo.namespace),
64
- };
65
- generatorState.scriptGenState.importMetadata =
66
- moduleContext.astContext.importDeclarations;
67
- // determine which getters are valid, as well as which imports are being by those getters
68
- processedGetterContext = (0, shared_1.processGetters)(properties, moduleContext, moduleLevelConsumption, getters);
69
- processedTemplateStrings = (0, shared_1.processTemplateStrings)(properties, moduleContext, moduleLevelConsumption, templateStrings);
70
- // once we know what getters are using which imports, modify the functions array in the komaci documents
71
- // (in memory) as well property references in the Properties array
72
- updateImportsWithGetterConsumption(komaciDoc, moduleLevelConsumption.consumedImports);
73
- (0, common_shared_1.updateKomaciDocumentWithValidGetters)(komaciDoc, processedGetterContext);
74
- (0, common_shared_1.updateKomaciDocumentWithValidTemplatedStrings)(komaciDoc, processedTemplateStrings);
75
- }
76
- // Import default composition if not in-lined into the ADGs.
77
- importDefaultCompositionIfNotInlinedIntoADG(generatorState, komaciDoc.adgs, statements);
78
- // Add import declarations for all the Imports in the Komaci doc.
79
- addImportStatements(generatorState, komaciDoc, statements, moduleLevelConsumption, properties, {
80
- calledFromGenerateCombinedModule: false,
81
- });
82
- // Create map that maintains adg indexes to it's names
83
- createAdgNameMap(generatorState, komaciDoc);
84
- // Process the exports in the Komaci doc, including the Adgs which are being exported.
85
- processExports(generatorState, komaciDoc, statements);
86
- // Process the adgs that are not exported.
87
- processNonExportAdgs(generatorState, komaciDoc, statements);
88
- // add default export from AdgReference (if not already added).
89
- addDefaultExportFromAdgReferenceIfNoneExists(generatorState, statements);
90
- // remove invalid imports that are only used in wire adapters
91
- removeInvalidImportsOnlyUsedInWireAdapter(generatorState, statements);
92
- // append priming adapter imports and perform any final changes and return generated source file
93
- const generatedFile = appendPrimingAdapterImportsAndGenerateFinalFile(generatorState, statements);
94
- // transform getters in the generated source file AST by hoisting them to the module level
95
- if (processedGetterContext &&
96
- generatorState.scriptGenState.ast &&
97
- generatorState.scriptGenState.importMetadata &&
98
- generatedFile) {
99
- // needs fully generated, final source file AST, so transformGetters call is done last
100
- (0, shared_1.transformGetters)(generatedFile, generatorState.scriptGenState.importRefsMap, generatorState.scriptGenState.importMetadata, processedGetterContext);
101
- }
102
- if (processedTemplateStrings &&
103
- generatorState.scriptGenState.ast &&
104
- generatorState.scriptGenState.importMetadata &&
105
- generatedFile) {
106
- (0, shared_1.hoistTemplateStrings)(generatedFile, generatorState.scriptGenState.importRefsMap, generatorState.scriptGenState.importMetadata, processedTemplateStrings);
107
- }
108
- return generatedFile;
109
- }
110
- exports.generateScriptModule = generateScriptModule;
111
- /**
112
- * Given information about what imports a getter consumes, we check the komaci doc to make sure all the
113
- * import info is available
114
- * @param komaciScriptDoc The Komaci doc to process
115
- * @param consumedImports metadata about getter import consumption
116
- */
117
- function updateImportsWithGetterConsumption(komaciScriptDoc, consumedImports) {
118
- if (!komaciScriptDoc.imports) {
119
- komaciScriptDoc.imports = [];
120
- }
121
- for (const consumedImportInfo of consumedImports.values()) {
122
- const index = komaciScriptDoc.imports.findIndex((current) => current.resourceName === consumedImportInfo.resourceName);
123
- if (index !== -1 && !consumedImportInfo.isNamespaceSpecifier) {
124
- // we update komaciScriptDoc with any import specs that might be missing, from the getter
125
- // consumption, and not the other way around
126
- const komaciImportSpecifiers = new Set(komaciScriptDoc.imports[index].names);
127
- const consumedImportsSpecifiers = Array.from(consumedImportInfo.names);
128
- consumedImportsSpecifiers.forEach((consumedSpec) => {
129
- if (!komaciImportSpecifiers.has(consumedSpec) &&
130
- komaciScriptDoc?.imports) {
131
- komaciScriptDoc.imports[index].names.push(consumedSpec);
132
- }
133
- });
134
- }
135
- else if (index !== -1 && consumedImportInfo.isNamespaceSpecifier) {
136
- komaciScriptDoc.imports[index].names = ['*'];
137
- }
138
- else if (consumedImportInfo.isNamespaceSpecifier) {
139
- komaciScriptDoc.imports.push({
140
- resourceName: consumedImportInfo.resourceName,
141
- names: ['*'],
142
- });
143
- }
144
- else {
145
- komaciScriptDoc.imports.push({
146
- resourceName: consumedImportInfo.resourceName,
147
- names: Array.from(consumedImportInfo.names),
148
- });
149
- }
150
- }
151
- }
152
- exports.updateImportsWithGetterConsumption = updateImportsWithGetterConsumption;
153
- /**
154
- * Generates the resolvable runtime module for a script and template file.
155
- * @param {GeneratorState} generatorState the state of the ESM generator
156
- * @param {KomaciDocument} komaciScriptDoc the Komaci doc for the script file
157
- * @param {KomaciDocument} komaciTemplateDoc the Komaci doc for the template file
158
- * @returns babel/types File representing the generated, combined resolvable runtime module. In other words,
159
- * the Abstract Syntax Tree of the combined, resolvable module.
160
- */
161
- function generateCombinedModule(generatorState, komaciScriptDoc, komaciTemplateDoc) {
162
- // script module generation code
163
- const statements = [];
164
- // gathers information about properties in a JS class and whether they are being used by wire functions
165
- const properties = (0, common_shared_1.collectPropertyMetadataFromScriptDoc)(komaciScriptDoc);
166
- (0, common_shared_1.updatePropertyMetadataFromTemplateDoc)(komaciTemplateDoc, properties);
167
- const src = (0, shared_1.getComponentSrcJs)(generatorState);
168
- const moduleLevelConsumption = {
169
- consumedImports: new Map(),
170
- };
171
- let processedGetterContext;
172
- let processedTemplateStrings;
173
- if (src) {
174
- const ast = (0, common_shared_1.generateAstFromSrcCode)(src);
175
- const { getters, templateStrings } = (0, common_shared_1.getPropertyMetadataFromAst)(ast);
176
- generatorState.scriptGenState.ast = ast;
177
- const moduleContext = {
178
- astContext: (0, common_shared_1.getAstContextObject)(ast),
179
- isExternal: (0, common_shared_1.isExternalModule)(generatorState.input.moduleInfo.namespace),
180
- };
181
- generatorState.scriptGenState.importMetadata =
182
- moduleContext.astContext.importDeclarations;
183
- // determine which getters are valid, as well as which imports are being by those getters
184
- processedGetterContext = (0, shared_1.processGetters)(properties, moduleContext, moduleLevelConsumption, getters);
185
- processedTemplateStrings = (0, shared_1.processTemplateStrings)(properties, moduleContext, moduleLevelConsumption, templateStrings);
186
- // once we know what getters are using which imports, modify the functions array in the komaci documents
187
- // (in memory) as well property references in the Properties array
188
- updateImportsWithGetterConsumption(komaciScriptDoc, moduleLevelConsumption.consumedImports);
189
- (0, common_shared_1.updateKomaciDocumentWithValidGetters)(komaciScriptDoc, processedGetterContext);
190
- (0, common_shared_1.updateKomaciDocumentWithValidTemplatedStrings)(komaciScriptDoc, processedTemplateStrings);
191
- }
192
- generatorState.inlineTemplateDoc = komaciTemplateDoc;
193
- if (doesScriptHaveADGs(komaciScriptDoc)) {
194
- (0, modGenTemplate_1.processTemplateImports)(komaciTemplateDoc, generatorState, statements);
195
- }
196
- // Add import declarations for all the Imports in the Komaci doc.
197
- addImportStatements(generatorState, komaciScriptDoc, statements, moduleLevelConsumption, properties, {
198
- calledFromGenerateCombinedModule: true,
199
- });
200
- // Create map that maintains adg indexes to it's names
201
- createAdgNameMap(generatorState, komaciScriptDoc);
202
- // Process the exports in the Komaci doc, including the Adgs which are being exported.
203
- processExports(generatorState, komaciScriptDoc, statements);
204
- // Process the adgs that are not exported.
205
- processNonExportAdgs(generatorState, komaciScriptDoc, statements);
206
- // add default export if not already added.
207
- addDefaultExportFromAdgReferenceIfNoneExists(generatorState, statements);
208
- // add dynamic import for target module (for bundle only)
209
- addDynamicImportOfTargetModuleForBundle(generatorState, statements);
210
- // remove invalid imports that are only used in a wire adapter
211
- removeInvalidImportsOnlyUsedInWireAdapter(generatorState, statements);
212
- // append priming adapter imports and perform any final changes and return generated source file
213
- const generatedFile = appendPrimingAdapterImportsAndGenerateFinalFile(generatorState, statements);
214
- // transform getters in the generated source file AST by hoisting them to the module level
215
- if (processedGetterContext &&
216
- generatorState.scriptGenState.ast &&
217
- generatorState.scriptGenState.importMetadata &&
218
- generatedFile) {
219
- // needs fully generated source file AST, so transformGetters call is last
220
- (0, shared_1.transformGetters)(generatedFile, generatorState.scriptGenState.importRefsMap, generatorState.scriptGenState.importMetadata, processedGetterContext);
221
- }
222
- if (processedTemplateStrings &&
223
- generatorState.scriptGenState.ast &&
224
- generatorState.scriptGenState.importMetadata &&
225
- generatedFile) {
226
- (0, shared_1.hoistTemplateStrings)(generatedFile, generatorState.scriptGenState.importRefsMap, generatorState.scriptGenState.importMetadata, processedTemplateStrings);
227
- }
228
- return generatedFile;
229
- }
230
- exports.generateCombinedModule = generateCombinedModule;
231
- /**
232
- * Performs any remaining modifications and creates a final File representing the entire program.
233
- *
234
- * @param {GeneratorState} generatorState the GeneratorState for this module generation run
235
- * @param {Statement[]} statements t.Statement[] the statements of the analyzed program, up to this point
236
- * @returns babel/types File, i.e. the AST of generated resolvable module
237
- */
238
- function appendPrimingAdapterImportsAndGenerateFinalFile(generatorState, statements) {
239
- // append import statements for priming adapters
240
- const allStatements = [
241
- ...generatorState.scriptGenState.primingAdapterImportDeclarations,
242
- ...statements,
243
- ];
244
- // generate the program
245
- const program = t.program(allStatements);
246
- const file = t.file(program);
247
- return file;
248
- }
249
- /**
250
- * Removes invalid imports (or import specifiers therein) that are only used in wire adapter annotation (and nowhere else).
251
- *
252
- * Note: While this method does not return anything, it does modify the input Statement array.
253
- *
254
- * @param {GeneratorState} generatorState the current state of the esm generator
255
- * @param {Statement[]} statements t.Statement[] the statements of the analyzed program, up to this point.
256
- */
257
- function removeInvalidImportsOnlyUsedInWireAdapter(generatorState, statements) {
258
- // gather all of the ImportInfos for the ImportSpecifiers that should be removed
259
- const importInfosToRemove = findImportInfosToRemove(generatorState);
260
- // remove ImportSpecifiers and ImportDeclarations as appropriate
261
- for (const importInfo of importInfosToRemove) {
262
- const importDeclaration = importInfo.importDeclaration;
263
- if (importDeclaration?.specifiers && importInfo.importSpecifier) {
264
- importDeclaration.specifiers.splice(importDeclaration.specifiers.indexOf(importInfo.importSpecifier), 1);
265
- }
266
- if (importDeclaration?.specifiers.length === 0) {
267
- // there are no more valid wire adapters left as specifiers, remove whole import statement
268
- statements.splice(statements.indexOf(importDeclaration), 1);
269
- }
270
- }
271
- return;
272
- }
273
- /**
274
- * Finds the ImportInfos of the ImportSpecifiers that need to be removed due not representing a
275
- * supported wire adapter.
276
- * @param {GeneratorState} generatorState the current state of the esm generator
277
- * @returns ImportInfo[] corresponding to all ImportSpecifiers that need to be removed because they
278
- * represent unsupported wire adapters
279
- */
280
- function findImportInfosToRemove(generatorState) {
281
- const importInfosToRemove = [];
282
- for (const importInfo of generatorState.scriptGenState.importInfosForWireAdapter) {
283
- // if it's used by something other than a wire adapter, we can't remove it, so might as well skip this iteration.
284
- if (importInfo.importUsages.size > 1) {
285
- continue;
286
- }
287
- if (importInfo.primingAdapterImportNames) {
288
- // if it's for a priming adapter then we want to remove the
289
- // import for the original wire adapter.
290
- importInfosToRemove.push(importInfo);
291
- }
292
- else if (importInfo.importSpecifier.type === 'ImportSpecifier') {
293
- // if it's not a supported wire adapter, remove it.
294
- const identifier = (importInfo.importSpecifier.imported);
295
- const exportName = identifier.name;
296
- if (!(0, static_analyzer_1.isSupportedWireAdapter)(importInfo.resourceName, exportName)) {
297
- importInfosToRemove.push(importInfo);
298
- }
299
- }
300
- }
301
- return importInfosToRemove;
302
- }
303
- /**
304
- * Determines whether Komaci JS document has any ADGs defined within it
305
- * @param {KomaciDocument} komaciScriptDoc a KomaciDocument representation of a Javascript project
306
- * @returns boolean true is the Komaci JS document has any ADGs defined within it
307
- */
308
- function doesScriptHaveADGs(komaciScriptDoc) {
309
- return (komaciScriptDoc.adgs?.length || 0) > 0;
310
- }
311
- /**
312
- * Detects if the composition has not been in-lined into the ADG(s).
313
- * If not, then generate an import declaration for the default composition file.
314
- *
315
- * Note: While this method does not return anything, it does modify the input Statement array.
316
- *
317
- * @param {GeneratorState} generatorState the current state of the esm generator
318
- * @param {Adg[] | undefined} adgs an array of Adg in which to search for compositions
319
- * @param {Statement[]} statements Array of Statement to be modified by this method
320
- */
321
- function importDefaultCompositionIfNotInlinedIntoADG(generatorState, adgs, statements) {
322
- if (adgs) {
323
- const adgNoComposition = adgs.find((adg) => {
324
- return !adg.compositions || adg.compositions.length === 0;
325
- });
326
- if (adgNoComposition) {
327
- // If we find adg without composition, then we'll need to import
328
- // it in order to be referenced later.
329
- const namespace = generatorState.input.moduleInfo.namespace;
330
- const name = generatorState.input.moduleInfo.name;
331
- const resource = t.stringLiteral(`@salesforce/komaci/${namespace}__${name}__${name}.html`);
332
- statements.push(t.importDeclaration([t.importDefaultSpecifier(shared_1.ID.DEFAULT_COMP)], resource));
333
- generatorState.defaultCompImported = true;
334
- }
335
- }
336
- }
337
- /**
338
- * Adds a babel import decleration to the AST for each Komaci import
339
- *
340
- * Note: While this method does not return anything, it does modify the input Statement array.
341
- *
342
- * @param {GeneratorState} generatorState the current state of the esm generator
343
- * @param {KomaciDocument} komaciScriptDoc the Komaci doc for the script file
344
- * @param {Statement[]} statements Array of Statement to be modified by this method for this program
345
- * @param {ModuleLevelConsumption | undefined} moduleLevelConsumption ModuleLevelConsumption object containing the Map of
346
- * imports which are being consumed
347
- * @param {ClassPropertyContexts} properties Map of class properties and all their relevant metadata
348
- * @param {{ calledFromGenerateCombinedModule: boolean }} options flag to distinguish whether we have been called
349
- * to generate a combined module or not.
350
- */
351
- function addImportStatements(generatorState, komaciScriptDoc, statements, moduleLevelConsumption, properties, options) {
352
- const imports = komaciScriptDoc.imports;
353
- if (imports) {
354
- for (let importIdx = 0; importIdx < imports.length; ++importIdx) {
355
- // outer for loop for import statement
356
- const komaciImport = imports[importIdx];
357
- const specifiers = [];
358
- const importInfosForDecl = [];
359
- for (let nameIdx = 0; nameIdx < komaciImport.names.length; ++nameIdx) {
360
- // inner for loop for import specifiers
361
- const exportName = komaciImport.names[nameIdx];
362
- if ((0, static_analyzer_1.isSupportedNamespace)(komaciImport.resourceName)) {
363
- ++generatorState.importAliasSuffix;
364
- }
365
- const localName = (0, static_analyzer_1.isSupportedNamespace)(komaciImport.resourceName)
366
- ? t.identifier(`i${generatorState.importAliasSuffix}`)
367
- : t.identifier(shared_1.UNRESOLVED);
368
- let specifier;
369
- if (exportName === 'default') {
370
- // e.g. `import i1 from "@salesforce/user/Id";`
371
- specifier = t.importDefaultSpecifier(localName);
372
- specifiers.unshift(specifier);
373
- }
374
- else if (exportName === '*' && komaciImport.names.length === 1) {
375
- // e.g. `import i1 from "@salesforce/user/Id";`
376
- specifier = t.importNamespaceSpecifier(localName);
377
- specifiers.push(specifier);
378
- }
379
- else {
380
- // e.g. `import { getRecord as i1 } from "lightning/uiRecordApi";`.
381
- // `getRecord` is the exportName, `i1` is the localName
382
- specifier = t.importSpecifier(localName, t.identifier(exportName));
383
- specifiers.push(specifier);
384
- }
385
- const importInfo = {
386
- localName,
387
- resourceName: komaciImport.resourceName,
388
- exportName: exportName,
389
- importUsages: new Set(),
390
- importSpecifier: specifier,
391
- importDeclaration: undefined,
392
- };
393
- // Helpful state for translation between import ref and local name.
394
- const importRefId = `${importIdx}/names/${nameIdx}`;
395
- // skip this if it is an import, whose export is assigned to a memeber, but that member is not used in either a
396
- // wire input, or in a composition.
397
- generatorState.scriptGenState.importRefsMap[importRefId] = importInfo;
398
- // store the ImportInfo in the area for later use
399
- importInfosForDecl.push(importInfo);
400
- } // end import inner loop for exports
401
- // only write the import statement if it is from a supported
402
- // namespace (in lines above, we still keep the state in the importRefsMap)
403
- let resourceName = komaciImport.resourceName;
404
- if ((0, static_analyzer_1.isSupportedNamespace)(resourceName) && specifiers.length > 0) {
405
- if (options.calledFromGenerateCombinedModule &&
406
- resourceName.startsWith('@salesforce/komaci')) {
407
- // @salesforce/komaci/c__foo__foo.js -> @salesforce/komaci/c__foo
408
- const lastIndex = resourceName.lastIndexOf('__');
409
- resourceName = resourceName.slice(0, lastIndex);
410
- }
411
- const resource = t.stringLiteral(resourceName);
412
- const importDeclaration = t.importDeclaration(specifiers, resource);
413
- statements.push(importDeclaration);
414
- // this object here will need to go into importInfo so it can be located/removed from the statements array later
415
- importInfosForDecl.forEach((importInfo) => {
416
- importInfo.importDeclaration = importDeclaration;
417
- });
418
- }
419
- } // end import outer loop for import declarations
420
- }
421
- }
422
- /**
423
- * Creates a Map that maintains ADG indexes to its corresponding names, generating a new
424
- * entry if it is not available
425
- * @param {GeneratorState} generatorState the current state of the esm generator
426
- * @param {KomaciDocument} komaciScriptDoc the Komaci doc for the script file
427
- */
428
- function createAdgNameMap(generatorState, komaciScriptDoc) {
429
- const exports = komaciScriptDoc.exports;
430
- if (exports) {
431
- Object.keys(exports).forEach((key) => {
432
- const keyedExport = exports[key];
433
- if (keyedExport && keyedExport.type === 'AdgReference') {
434
- generatorState.adgNameMap[keyedExport.value] = key;
435
- }
436
- });
437
- }
438
- // generate names if it is not avaialble
439
- komaciScriptDoc.adgs?.forEach((_adg, index) => {
440
- if (!generatorState.adgNameMap[index]) {
441
- generatorState.adgNameMap[index] = 'adg' + index;
442
- }
443
- });
444
- }
445
- /**
446
- * Process exports in the Komaci Script document, which produces functions to return ADG definitions
447
- *
448
- * Note: While this method does not return anything, it does modify the input Statement array.
449
- *
450
- * @param {GeneratorState} generatorState the current state of the esm generator
451
- * @param {KomaciDocument} komaciScriptDoc the Komaci doc for the script file
452
- * @param {Statement[]} statements Array of Statement to be modified by this method for this program
453
- */
454
- function processExports(generatorState, komaciScriptDoc, statements) {
455
- if (komaciScriptDoc.exports) {
456
- for (const [exportName, komaciExport] of Object.entries(komaciScriptDoc.exports)) {
457
- if (komaciExport &&
458
- (komaciExport.type === 'AdgReference' ||
459
- komaciExport.type === 'CompositionReference')) {
460
- // Validate integrity of komaci doc.
461
- if (!komaciScriptDoc.adgs ||
462
- komaciExport.value < 0 ||
463
- komaciExport.value > komaciScriptDoc.adgs.length) {
464
- throw new Error(shared_1.ERROR_PREFIX +
465
- 'komaciDoc contains invalid ADG or composition references');
466
- }
467
- // For each exported Adg create a corresponding export of a function
468
- // which returns the AdgDefinition described in Resolver API.
469
- const komaciAdg = komaciScriptDoc.adgs[komaciExport.value];
470
- const body = getAdgFunctionBody(generatorState, komaciAdg);
471
- if (exportName === 'default') {
472
- generatorState.isDefaultExportFound = true;
473
- // e.g. `export default function (fct, ctx) {`
474
- statements.push(t.exportDefaultDeclaration(t.functionDeclaration(null, [shared_1.ID.FACTORY, shared_1.ID.CONTEXT], body)));
475
- }
476
- else {
477
- // e.g. `export function MyComponentClass(fct, ctx) {`
478
- statements.push(t.exportNamedDeclaration(t.functionDeclaration(t.identifier(exportName), [shared_1.ID.FACTORY, shared_1.ID.CONTEXT], body)));
479
- }
480
- }
481
- }
482
- }
483
- }
484
- /**
485
- * Processes the ADGs that are not exported
486
- *
487
- * Note: While this method does not return anything, it does modify the input Statement array.
488
- *
489
- * @param {GeneratorState} generatorState the current state of the esm generator
490
- * @param {KomaciDocument} komaciScriptDoc the Komaci doc for the script file
491
- * @param {Statement[]} statements Array of Statement to be modified by this method for this program
492
- */
493
- function processNonExportAdgs(generatorState, komaciScriptDoc, statements) {
494
- komaciScriptDoc.adgs?.forEach((adg, index) => {
495
- const localGeneratedName = generatorState.adgNameMap[index];
496
- if (localGeneratedName.startsWith('adg')) {
497
- const body = getAdgFunctionBody(generatorState, adg);
498
- statements.push(t.functionDeclaration(t.identifier(localGeneratedName), [shared_1.ID.FACTORY, shared_1.ID.CONTEXT], body));
499
- }
500
- });
501
- }
502
- /**
503
- * Compose the function that calls the `adg` function with all of it's needful info
504
- * @param {GeneratorState} generatorState the current state of the esm generator
505
- * @param {Adg} adg The current ADG for which to compose the babel statements
506
- * @returns the babel statements to represent the function
507
- */
508
- function getAdgFunctionBody(generatorState, adg) {
509
- const adgFuncCall = adgToExpression(generatorState, adg);
510
- const fctFuncs = (0, shared_1.getFactoryFuncDeclaration)(generatorState, true);
511
- const funcStatements = [];
512
- const body = t.blockStatement(funcStatements);
513
- // Function body will be destructuring of factory object and the return
514
- // statement for the adg() function call from Resolver API.
515
- // e.g. `{ const { adg } = fct; return adg({...}); }`
516
- if (fctFuncs) {
517
- funcStatements.push(fctFuncs);
518
- }
519
- funcStatements.push(t.returnStatement(adgFuncCall));
520
- return body;
521
- }
522
- /**
523
- * Adds a default export to the program statements, if no default export that is derived from an AdgReference already exists
524
- *
525
- * Note: While this method does not return anything, it does modify the input Statement array.
526
- *
527
- * @param {GeneratorState} generatorState The GeneratorState, from which the moduleInfo type is checked
528
- * @param {Statement[]} statements The babel/types array of Statement, representing statements of the JS Script
529
- */
530
- function addDefaultExportFromAdgReferenceIfNoneExists(generatorState, statements) {
531
- // If no default export of an AdgReference (e.g. an LWC library module) currently exists, then we
532
- // must still include one within the generated module.
533
- if (!generatorState.isDefaultExportFound) {
534
- statements.push(
535
- // `export default function () { return undefined; }`
536
- t.exportDefaultDeclaration(t.functionDeclaration(null, [], t.blockStatement([t.returnStatement(shared_1.ID.UNDEFINED)]))));
537
- }
538
- }
539
- /**
540
- * Adds the dynamic import of target module, but only for bundles (if moduleInfo.type === "bundle").
541
- * This method modifies the input statements array, and does not return anything.
542
- *
543
- * Note: While this method does not return anything, it does modify the input Statement array.
544
- *
545
- * @param {GeneratorState} generatorState The GeneratorState, from which the moduleInfo type is checked
546
- * @param {Statement[]} statements The babel/types array of Statement, representing statements of the JS Script
547
- */
548
- function addDynamicImportOfTargetModuleForBundle(generatorState, statements) {
549
- // dynamic import of target module (generated only if moduleInfo.type is "bundle")
550
- // e.g.
551
- // ```
552
- // export const importTarget = () => {
553
- // return import("lightning/input");
554
- // };
555
- // ```
556
- if (generatorState?.input?.moduleInfo?.type === 'bundle') {
557
- statements.push(exportNamedDeclarationForDynamicImport(generatorState));
558
- }
559
- }
560
- /**
561
- * Returns an export named declaration. The declaration is assigned an arrowFunctionExpression, which returns
562
- * a dynamic import based on the moduleInfo namespace and name.
563
- * @param generatorState The GeneratorState, from which the resourceName for the import is determined
564
- * @returns ExportNamedDeclaration containing the statement of the dynamic import of the target module
565
- */
566
- function exportNamedDeclarationForDynamicImport(generatorState) {
567
- const moduleResourceName = generatorState.input.options?.targetModule ||
568
- generatorState.input.moduleInfo?.namespace +
569
- '/' +
570
- generatorState.input.moduleInfo?.name;
571
- const returnStatement = t.returnStatement(t.callExpression(t.identifier(FUNC_NAME_IMPORT), [
572
- t.stringLiteral(moduleResourceName),
573
- ]));
574
- return t.exportNamedDeclaration(t.variableDeclaration(CONST_TYPE, [
575
- t.variableDeclarator(t.identifier(IMPORT_TARGET), t.arrowFunctionExpression([], t.blockStatement([returnStatement]))),
576
- ]));
577
- }
578
- /**
579
- * Converts a Komaci ADG into a CallExpression to the ADG factory function
580
- * call for the Resolver API.
581
- * @param {GeneratorState} generatorState the current state of the esm generator
582
- * @param {Adg} adg the current ADG to convert into an Expression
583
- * @returns {t.Expression} Babel Expression representation of the adg() factory function call
584
- */
585
- function adgToExpression(generatorState, adg) {
586
- const params = [];
587
- generatorState.scriptGenState.requiredFactoryFunctions.add(shared_1.ID.ADG_FUNC);
588
- // arg1: Parent Class.
589
- if (adg.parentClass) {
590
- let exp;
591
- if (adg.parentClass.type === 'Unresolved') {
592
- generatorState.scriptGenState.requiredFactoryFunctions.add(shared_1.ID.UNRESOLVED_VALUE);
593
- params.push(shared_1.ID.UNRESOLVED_VALUE);
594
- }
595
- else if (adg.parentClass.type === 'ImportReference' &&
596
- !(0, static_analyzer_1.isSupportedNamespace)(generatorState.scriptGenState.importRefsMap[adg.parentClass.value]
597
- ?.resourceName)) {
598
- generatorState.scriptGenState.requiredFactoryFunctions.add(shared_1.ID.UNRESOLVED_VALUE);
599
- params.push(shared_1.ID.UNRESOLVED_VALUE);
600
- }
601
- else {
602
- if (adg.parentClass.type === 'AdgReference') {
603
- const name = generatorState.adgNameMap[adg.parentClass.value];
604
- exp = t.identifier(name);
605
- }
606
- else {
607
- exp = (0, shared_1.valueToExpression)(generatorState, adg.parentClass, true, types_1.ImportUsageState.parentadg);
608
- }
609
- const parentFunc = t.callExpression(exp, [shared_1.ID.FACTORY, shared_1.ID.CONTEXT]);
610
- params.push(parentFunc);
611
- }
612
- }
613
- else {
614
- params.push(shared_1.ID.UNDEFINED);
615
- }
616
- // arg2: Properties object.
617
- if (adg.properties) {
618
- const objProps = [];
619
- for (const [propName, propValue] of Object.entries(adg.properties)) {
620
- objProps.push(t.objectProperty(t.identifier(propName), propertyToExpression(generatorState, adg, propValue)));
621
- }
622
- params.push(t.objectExpression(objProps));
623
- }
624
- else {
625
- params.push(t.objectExpression([]));
626
- }
627
- // arg3: Functions array.
628
- const functionsArray = [];
629
- if (adg.functions) {
630
- adg.functions.forEach((adgFunc) => {
631
- const expr = functionToExpression(generatorState, adgFunc);
632
- if (expr) {
633
- functionsArray.push(expr);
634
- }
635
- else {
636
- functionsArray.push(null);
637
- }
638
- });
639
- }
640
- if (functionsArray.length) {
641
- params.push(t.arrayExpression(functionsArray));
642
- }
643
- else {
644
- params.push(t.arrayExpression([]));
645
- }
646
- // arg4: Imported in-line composition function.
647
- if (generatorState && generatorState.inlineTemplateDoc) {
648
- const compositions = [];
649
- if (generatorState.inlineTemplateDoc.compositions &&
650
- generatorState.inlineTemplateDoc.compositions.length > 0) {
651
- // current assumption: comp for templateDoc is in first element
652
- compositions.push(generatorState.inlineTemplateDoc.compositions[0]);
653
- } // otherwise, if we are processing an empty in-line templateDoc, pass in an empty array
654
- params.push(getInlineFunctionFromTemplateCompositions(generatorState, compositions));
655
- }
656
- else if (generatorState.defaultCompImported) {
657
- params.push(shared_1.ID.DEFAULT_COMP);
658
- }
659
- // arg5: pass properties that the template references (only if processing a bundle)
660
- if (generatorState.input.moduleInfo.type === 'bundle') {
661
- // this array of t.stringLiterals may include properties mentioned the Template that aren't necessarily
662
- // defined in the Script. Resolution engine has logic to handle these
663
- params.push(t.arrayExpression(Array.from(generatorState.templateGenState.refProps).map((v) => t.stringLiteral(v))));
664
- }
665
- else {
666
- params.push(t.arrayExpression([]));
667
- }
668
- return t.callExpression(shared_1.ID.ADG_FUNC, params);
669
- }
670
- /**
671
- * Converts array of template Compositions into a representation that is an inline function
672
- * @param {GeneratorState} generatorState the current state of esm-generator
673
- * @param {Composition[]} compositions array of Compositions to convert
674
- * @returns {t.ArrowFunctionExpression} an inline ArrowFunctionExpression representing the input Compositions
675
- */
676
- function getInlineFunctionFromTemplateCompositions(generatorState, compositions) {
677
- const params = [shared_1.ID.FACTORY, shared_1.ID.CONTEXT];
678
- const statements = [];
679
- const body = t.blockStatement(statements);
680
- const emptyCompositionsArray = compositions.length < 1;
681
- const compositionArrayExpr = emptyCompositionsArray
682
- ? t.arrayExpression([])
683
- : (0, modGenTemplate_1.compositionsToArrayExpression)(generatorState, true, compositions) ||
684
- t.arrayExpression([]);
685
- // function body destructured factory object. e.g. `const { cg } = fct;`
686
- const fctFuncs = (0, shared_1.getFactoryFuncDeclaration)(generatorState, false); // passing in false because we are not processing the script file in this method
687
- if (fctFuncs && !emptyCompositionsArray) {
688
- statements.push(fctFuncs);
689
- }
690
- statements.push(t.returnStatement(compositionArrayExpr));
691
- return t.arrowFunctionExpression(params, body);
692
- }
693
- /**
694
- * Convert a single Komaci property to an object expression in the shape of
695
- * a PropertyDefinition as defined in Resolver API.
696
- * @param {GeneratorState} generatorState the current state of esm-generator
697
- * @param {Adg} adg the current ADG from which to seek out FunctionReferences
698
- * @param {Propery} property the Komaci property to process
699
- * @returns {Expression} the komaci property converted to an object Expression
700
- */
701
- function propertyToExpression(generatorState, adg, property) {
702
- const objProps = [];
703
- // Whether the prop is public or not, e.g. `a: true`.
704
- objProps.push(t.objectProperty(shared_1.ID.PROP_API, t.booleanLiteral(!!property.isPublic)));
705
- if (property.initial) {
706
- // initial value
707
- // Initial value of the prop, e.g. `i: 5`.
708
- objProps.push(t.objectProperty(shared_1.ID.PROP_INIT, (0, shared_1.valueToExpression)(generatorState, property.initial, true, types_1.ImportUsageState.initialvalue)));
709
- }
710
- if (property.input) {
711
- if (property.input.type === 'FunctionReference') {
712
- // Index of function where this property receives input, e.g. `f: 0`.
713
- const funcIdx = property.input.value;
714
- if (!adg.functions || funcIdx < 0 || funcIdx >= adg.functions.length) {
715
- throw new Error(shared_1.ERROR_PREFIX + 'komaciDoc contains invalid function reference');
716
- }
717
- // if the property input type is a FunctionReference that refers to a Wire Function, then make sure its
718
- // corresponding ImportReference does not refer to a unsupported resourceName; if it does, then
719
- // replace the `f: functionIndex`, with `g: unresolved`
720
- const resourceKey = adg.functions[funcIdx].reference.value;
721
- const importInfo = (0, shared_1.retrieveImportInfo)(generatorState, resourceKey, true);
722
- const resourceName = importInfo?.resourceName;
723
- const exportName = importInfo?.exportName;
724
- if (adg.functions[funcIdx].type == shared_1.WIRE_FUNCTION &&
725
- (adg.functions[funcIdx].reference.type === 'Unresolved' ||
726
- !(0, static_analyzer_1.isSupportedNamespace)(resourceName) ||
727
- !(0, static_analyzer_1.isSupportedWireAdapter)(resourceName, exportName))) {
728
- objProps.push(t.objectProperty(shared_1.ID.PROP_GETTER, shared_1.ID.UNRESOLVED_VALUE));
729
- generatorState.scriptGenState.requiredFactoryFunctions.add(shared_1.ID.UNRESOLVED_VALUE);
730
- }
731
- else {
732
- objProps.push(t.objectProperty(shared_1.ID.PROP_FUNC, t.numericLiteral(funcIdx)));
733
- }
734
- }
735
- else {
736
- // setting up modgen for getter (static values returned via getter)
737
- // If associated w/ getter, then the hardcoded value from the getter,
738
- // e.g. `g: 'some hardcoded string'`
739
- objProps.push(t.objectProperty(shared_1.ID.PROP_GETTER, (0, shared_1.valueToExpression)(generatorState, property.input, true, types_1.ImportUsageState.getter)));
740
- }
741
- }
742
- return t.objectExpression(objProps);
743
- }
744
- /**
745
- * Convert a single Komaci function to an object expression in the shape of a
746
- * FunctionDefinition as defined in Resolver API.
747
- * @param {GeneratorState} generatorState the current esm generator state
748
- * @param {FunctionType} adgFunc a function from the adg functions arrray.
749
- * @returns {Expression} a babel Expression if propertly processed or undefined.
750
- */
751
- function functionToExpression(generatorState,
752
- // eslint-disable-next-line @typescript-eslint/ban-types
753
- adgFunc) {
754
- let importInfo;
755
- if (adgFunc.type === shared_1.GETTER_FUNCTION) {
756
- const getterFuncObjPropArr = processLocalFunction(adgFunc, shared_1.GETTER_FUNCTION);
757
- return t.objectExpression(getterFuncObjPropArr);
758
- }
759
- else if (adgFunc.type === common_shared_1.TEMPLATED_STRING_FUNCTION) {
760
- return t.objectExpression(processLocalFunction(adgFunc, common_shared_1.TEMPLATED_STRING_FUNCTION));
761
- }
762
- else if (adgFunc.type === shared_1.ERROR_FUNCTION) {
763
- return t.objectExpression(processErrorFunction(generatorState, adgFunc));
764
- }
765
- // Use import map to set function id to local alias name, e.g. `f: i1`.
766
- if (adgFunc.reference.type === 'ImportReference') {
767
- importInfo = (0, shared_1.updateImportInfoState)(generatorState, adgFunc.reference.value, true, types_1.ImportUsageState.wireadapter); // wireadapter import usage
768
- }
769
- else {
770
- // UnresolvedValue
771
- return undefined;
772
- }
773
- // Validate and set function type, e.g. `t: "WireFunction"`
774
- if (adgFunc.type !== shared_1.WIRE_FUNCTION) {
775
- throw new Error(shared_1.ERROR_PREFIX + 'ADG function has invalid type');
776
- }
777
- const wireFunctionObjArr = processWireFunctionType(importInfo, generatorState, adgFunc);
778
- if (wireFunctionObjArr) {
779
- return t.objectExpression(wireFunctionObjArr);
780
- }
781
- return undefined;
782
- }
783
- function processErrorFunction(generatorState, adgFunc) {
784
- const funcObjProps = [];
785
- const t_value = t.stringLiteral(shared_1.ERROR_FUNCTION);
786
- const configObjExpr = (0, shared_1.valueToExpression)(generatorState,
787
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
788
- adgFunc.input[0], true, types_1.ImportUsageState.initialvalue);
789
- funcObjProps.push(t.objectProperty(shared_1.ID.FUNC_TYPE, t_value), t.objectProperty(shared_1.ID.FUNC_CONFIG, configObjExpr));
790
- return funcObjProps;
791
- }
792
- /**
793
- * Function to create the object property array for a local function
794
- * @param {FunctionType} adgFunc a function from the adg functions array.
795
- * @param {string} type The type of function. getter or templated string
796
- * @returns {ObjectProperty[]} a babel object property array.
797
- */
798
- function processLocalFunction(adgFunc, type) {
799
- const funcObjProps = [];
800
- const f_reference = {
801
- type: 'Identifier',
802
- name: adgFunc.reference.value,
803
- leadingComments: null,
804
- innerComments: null,
805
- trailingComments: null,
806
- start: null,
807
- end: null,
808
- loc: null,
809
- };
810
- const t_value = t.stringLiteral(type);
811
- funcObjProps.push(t.objectProperty(shared_1.ID.FUNC_ID, f_reference), t.objectProperty(shared_1.ID.FUNC_TYPE, t_value));
812
- if (adgFunc.input) {
813
- const inputArray = adgFunc.input.filter((entry) => entry.type === 'ArrayValue')[0];
814
- const in_value = t.arrayExpression(inputArray.value.map((v) => t.stringLiteral(v.value)));
815
- funcObjProps.push(t.objectProperty(shared_1.ID.FUNC_INPUT, in_value));
816
- }
817
- return funcObjProps;
818
- }
819
- /**
820
- * Function to generate the object property array for a wire function node type.
821
- *
822
- * NOTE: if the obj representing the function is from an unsupported namespace, and it
823
- * is for a wire function, then leave out the function node from the generated resolvable
824
- * module, by returning undefined.
825
- * @param {ImportInfo} importInfo import information against which to check the wire function's validity
826
- * @param {GeneratorState} generatorState the current state of the esm generator
827
- * @param {FunctionType} adgFunc a wire function from the adg functions array.
828
- * @returns {ObjectProperty[]} an representation of the wire function node as array of ObjectProperty
829
- */
830
- function processWireFunctionType(importInfo, generatorState, adgFunc) {
831
- const funcObjProps = [];
832
- // if the obj representing the function is from an unsupported namespace, and it is for a wire function,
833
- // then leave out the function node form the generated resolvable module, by returning undefined.
834
- const resourceName = importInfo.resourceName;
835
- const exportName = importInfo.exportName;
836
- if (!exportName ||
837
- !(0, static_analyzer_1.isSupportedNamespace)(resourceName) ||
838
- !(0, static_analyzer_1.isSupportedWireAdapter)(resourceName, exportName)) {
839
- return undefined;
840
- }
841
- // If we don't already know, check to see if this is a priming adapter.
842
- if (!importInfo.primingAdapterImportNames) {
843
- const primingAdapterDef = (0, static_analyzer_1.getPrimingAdapter)(resourceName, exportName);
844
- if (primingAdapterDef) {
845
- // create imports and store local names in this importInfo.
846
- importInfo.primingAdapterImportNames = createPrimingAdapterImports(generatorState, primingAdapterDef);
847
- }
848
- }
849
- if (importInfo.primingAdapterImportNames) {
850
- const primingAdapterDef = importInfo.primingAdapterImportNames.primingAdapterDef;
851
- // Add props for imports relating to this priming adapter.
852
- funcObjProps.push(t.objectProperty(shared_1.ID.FUNC_ID, importInfo.primingAdapterImportNames.adapter), t.objectProperty(shared_1.ID.FUNC_NAME, t.stringLiteral(primingAdapterDef.prime.identifier)));
853
- if (importInfo.primingAdapterImportNames.batchAdapter &&
854
- primingAdapterDef.batch) {
855
- funcObjProps.push(t.objectProperty(shared_1.ID.BATCH_FUNC_ID, importInfo.primingAdapterImportNames.batchAdapter), t.objectProperty(shared_1.ID.BATCH_FUNC_NAME, t.stringLiteral(primingAdapterDef.batch.prime.identifier)));
856
- }
857
- if (importInfo.primingAdapterImportNames.reducer) {
858
- funcObjProps.push(t.objectProperty(shared_1.ID.REDUCER_FUNC_ID, importInfo.primingAdapterImportNames.reducer));
859
- }
860
- funcObjProps.push(t.objectProperty(shared_1.ID.FUNC_TYPE, t.stringLiteral(shared_1.PRIMING_FUNCTION)));
861
- }
862
- else {
863
- // Traditional wire adapter.
864
- funcObjProps.push(t.objectProperty(shared_1.ID.FUNC_ID, importInfo.localName), t.objectProperty(shared_1.ID.FUNC_NAME, t.stringLiteral(getWireName(resourceName, exportName))), t.objectProperty(shared_1.ID.FUNC_TYPE, t.stringLiteral(shared_1.WIRE_FUNCTION)));
865
- // Check if the export name matches one of the supported context wires. If so we set
866
- // wire type. e.g. `wt: "cpr"`
867
- if (isSupportedContextWire(exportName)) {
868
- const contextWireName = Object.keys(CONTEXT_MAPPING).find((key) => CONTEXT_MAPPING[key] === exportName);
869
- if (contextWireName) {
870
- funcObjProps.push(t.objectProperty(shared_1.ID.WIRE_TYPE, t.stringLiteral(contextWireName)));
871
- }
872
- }
873
- else if (isApexWire(resourceName)) {
874
- funcObjProps.push(t.objectProperty(shared_1.ID.WIRE_TYPE, t.stringLiteral('apex')));
875
- }
876
- }
877
- // Construct function to return config object and list of input properties.
878
- let configObjExpr;
879
- const inputProps = new Set();
880
- if (adgFunc.input && adgFunc.input.length > 0) {
881
- if (adgFunc.input.length !== 1 || adgFunc.input[0].type !== 'ObjectValue') {
882
- // Only valid input according to Wire Adapter Protocol.
883
- throw new Error(shared_1.ERROR_PREFIX + 'WireFunction has invalid input');
884
- }
885
- const inputObject = adgFunc.input[0];
886
- configObjExpr = (0, shared_1.valueToExpression)(generatorState, inputObject, true, types_1.ImportUsageState.wireconfig); // wireconfig import usage
887
- // Create list of property names which are inputs into the function.
888
- for (const propValue of Object.values(inputObject.value)) {
889
- // NOTE: LWC doesn't allow for property references to be nested in
890
- // objects or arrays, so only need to check the top-level props.
891
- if (propValue.type === 'PropertyReference') {
892
- inputProps.add(propValue.value.split('/')[0]);
893
- }
894
- }
895
- }
896
- else {
897
- // Matches LWC compiler behavior which always pass an object into a wire's
898
- // update() method. Even if original source doesn't provide config.
899
- configObjExpr = t.objectExpression([]);
900
- }
901
- // e.g. `c: ctx => ({ recordId: "001RM000004UZqLYAW" })`
902
- const configFunc = t.arrowFunctionExpression([shared_1.ID.CONTEXT], configObjExpr);
903
- funcObjProps.push(t.objectProperty(shared_1.ID.FUNC_CONFIG, configFunc));
904
- // e.g. in: ['recordId', 'fields']
905
- if (inputProps.size) {
906
- funcObjProps.push(t.objectProperty(shared_1.ID.FUNC_INPUT, t.arrayExpression(Array.from(inputProps).map((v) => t.stringLiteral(v)))));
907
- }
908
- return funcObjProps;
909
- }
910
- /**
911
- * Create imports for the provided priming adapter, and stores then in the GeneratorState
912
- * @param {GeneratorState} generatorState the current state of the esm generator
913
- * @param {PrimingAdapterDefinition} primingAdapterDef the PrimingAdapterDefinition from which to find the Priming
914
- * Adapter import name identifiers
915
- * @returns {PrimingAdapterImportNames} an object containing the Priming adapter import names (adapter, batch adapter, and reducer)
916
- */
917
- function createPrimingAdapterImports(generatorState, primingAdapterDef) {
918
- const adapterLocalName = t.identifier(`i${++generatorState.importAliasSuffix}`);
919
- const primingAdapterImportNames = {
920
- primingAdapterDef,
921
- adapter: adapterLocalName,
922
- };
923
- // create import for priming adapter and store in generator state
924
- // to be appended to statements array for this script.
925
- const adapterSpecifier = t.importSpecifier(adapterLocalName, t.identifier(primingAdapterDef.prime.identifier));
926
- generatorState.scriptGenState.primingAdapterImportDeclarations.push(t.importDeclaration([adapterSpecifier], t.stringLiteral(primingAdapterDef.prime.importPath)));
927
- primingAdapterImportNames.adapter = adapterLocalName;
928
- // optionally create imports for batch adapter and reducer.
929
- if (primingAdapterDef.batch) {
930
- if (primingAdapterDef.batch.prime.importPath ===
931
- primingAdapterDef.prime.importPath &&
932
- primingAdapterDef.batch.prime.identifier ===
933
- primingAdapterDef.prime.identifier) {
934
- // Special case where batch adapter uses same priming adapter (e.g. getObjectInfos).
935
- // Don't create new import, just reuse local name of non-batch adapter.
936
- primingAdapterImportNames.batchAdapter = adapterLocalName;
937
- }
938
- else {
939
- const batchLocalName = t.identifier(`i${++generatorState.importAliasSuffix}`);
940
- const batchSpecifier = t.importSpecifier(batchLocalName, t.identifier(primingAdapterDef.batch.prime.identifier));
941
- generatorState.scriptGenState.primingAdapterImportDeclarations.push(t.importDeclaration([batchSpecifier], t.stringLiteral(primingAdapterDef.batch.prime.importPath)));
942
- primingAdapterImportNames.batchAdapter = batchLocalName;
943
- }
944
- const reducerLocalName = t.identifier(`i${++generatorState.importAliasSuffix}`);
945
- const reducerSpecifier = t.importSpecifier(reducerLocalName, t.identifier(primingAdapterDef.batch.reducer.identifier));
946
- generatorState.scriptGenState.primingAdapterImportDeclarations.push(t.importDeclaration([reducerSpecifier], t.stringLiteral(primingAdapterDef.batch.reducer.importPath)));
947
- primingAdapterImportNames.reducer = reducerLocalName;
948
- }
949
- return primingAdapterImportNames;
950
- }
951
- /**
952
- * Determines whether an export name matches one of the supported context wires
953
- * @param {string | undefined} exportName the exportName of an import statement
954
- * @returns {boolean} boolean true if the the export name matches a supported context wire
955
- */
956
- function isSupportedContextWire(exportName) {
957
- return (exportName !== undefined && Object.values(CONTEXT_MAPPING).includes(exportName));
958
- }
959
- /**
960
- * Determines whether the resourceName of an import statement is that of an Apex wire
961
- * @param {string | undefined} resourceName a string representing the resource name (ex: '@salesforce/apex/myApexwire')
962
- * @returns {boolean} true if the resource name represent that of an Apex wire, false otherwise
963
- */
964
- function isApexWire(resourceName) {
965
- return !!(resourceName && resourceName.startsWith('@salesforce/apex/'));
966
- }
967
- /**
968
- * Retrieves the name of an Apex wire
969
- * @param {string} resourceName a string representing the resource name (ex: '@salesforce/apex/ContactController.getContactList')
970
- * @param {string} exportName a string representing the name of the export (ex: `awire` in `import awire from '@salesforce/apex/awire'`)
971
- * @returns {string} the Apex wire name, as a string
972
- */
973
- function getWireName(resourceName, exportName) {
974
- if (isApexWire(resourceName)) {
975
- // eg. @salesforce/apex/ContactController.getContactList -> ContactController.getContactList
976
- return resourceName.substring('@salesforce/apex/'.length);
977
- }
978
- return exportName;
979
- }
980
- /**
981
- * A barebones resolvable module default export with a singular node describing the context of an error.
982
- *
983
- * We return this instead of a real resolvable module if something throws an error during resolvable module generation
984
- * @param generatorState The state of the generator for pass through to adgToExpression
985
- * @param error The error that was thrown
986
- * @returns A default export representing the error state for this resolvable module
987
- */
988
- function produceErrorAdgFunction(generatorState, error) {
989
- const functionValues = {
990
- error: {
991
- type: 'PrimitiveValue',
992
- value: error instanceof Error
993
- ? error.message
994
- : shared_1.ERROR_PREFIX + 'Something that is not an error was thrown',
995
- },
996
- };
997
- if (error instanceof Error && error.stack) {
998
- functionValues.stack = {
999
- type: 'PrimitiveValue',
1000
- value: error.stack,
1001
- };
1002
- }
1003
- const adgFuncCall = adgToExpression(generatorState, {
1004
- functions: [
1005
- {
1006
- type: 'ErrorFunction',
1007
- input: [
1008
- {
1009
- type: 'ObjectValue',
1010
- value: functionValues,
1011
- },
1012
- ],
1013
- reference: {
1014
- type: 'Unresolved',
1015
- value: '',
1016
- },
1017
- },
1018
- ],
1019
- });
1020
- const factoryFuncs = (0, shared_1.getFactoryFuncDeclaration)(generatorState, true);
1021
- return t.program([
1022
- t.exportDefaultDeclaration(t.functionDeclaration(null, [shared_1.ID.FACTORY, shared_1.ID.CONTEXT], t.blockStatement([
1023
- // it is literally impossible for this to be undefined given the adgToExpression call
1024
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
1025
- factoryFuncs,
1026
- t.returnStatement(adgFuncCall),
1027
- ]))),
1028
- ]);
1029
- }
1030
- exports.produceErrorAdgFunction = produceErrorAdgFunction;
1031
- //# sourceMappingURL=modGenScript.js.map