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