@komaci/esm-generator 240.1.3 → 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.
- package/build/__tests__/adgAstGeneration.spec.d.ts +2 -0
- package/build/__tests__/adgAstGeneration.spec.js +31 -0
- package/build/__tests__/compositionAstGeneration.spec.d.ts +2 -0
- package/build/__tests__/compositionAstGeneration.spec.js +394 -0
- package/build/__tests__/fixtures-combined-files/exclude-partial-classProps-indirect-importRef-getter/actual.js +5 -1
- package/build/__tests__/fixtures-combined-files/include-all-indirect-importRef-getter-complex/actual.js +5 -1
- package/build/__tests__/fixtures-combined-files/include-class-prop-indirect-importRef-getter/actual.js +5 -1
- package/build/__tests__/fixtures-script-files/imports/actual.js +5 -1
- package/build/__tests__/fixtures-script-files/imports-namespaced/actual.js +5 -1
- package/build/__tests__/fixtures-script-files/wire-imports/actual.js +5 -1
- package/build/__tests__/functionAstGeneration.spec.d.ts +2 -0
- package/build/__tests__/functionAstGeneration.spec.js +412 -0
- package/build/__tests__/general-komaci-docs/import-types/source.js +5 -1
- package/build/__tests__/general-komaci-docs/template-component/source.js +3 -3
- package/build/__tests__/genericAstGeneration.spec.d.ts +2 -0
- package/build/__tests__/genericAstGeneration.spec.js +586 -0
- package/build/__tests__/index.spec.js +13 -9
- package/build/__tests__/komaci-ast-unit.spec.js +240 -448
- package/build/__tests__/komaci-bundle-module.fixtures.spec.js +1 -0
- package/build/__tests__/komaci-script-module.fixtures.spec.js +5 -1
- package/build/__tests__/komaci-template-module.fixtures.spec.js +2 -1
- package/build/componentAstProcessing.d.ts +34 -0
- package/build/componentAstProcessing.js +105 -0
- package/build/compositionAstGeneration.d.ts +76 -0
- package/build/compositionAstGeneration.js +299 -0
- package/build/functionAstGeneration.d.ts +81 -0
- package/build/functionAstGeneration.js +337 -0
- package/build/genericAstGeneration.d.ts +107 -0
- package/build/genericAstGeneration.js +600 -0
- package/build/index.d.ts +6 -0
- package/build/index.js +85 -88
- package/build/types.d.ts +13 -2
- package/build/types.js +69 -1
- package/package.json +4 -4
- package/build/__tests__/modGenScript.spec.d.ts +0 -2
- package/build/__tests__/modGenScript.spec.js +0 -110
- package/build/__tests__/modGenTemplate.spec.d.ts +0 -2
- package/build/__tests__/modGenTemplate.spec.js +0 -196
- package/build/__tests__/shared.spec.d.ts +0 -2
- package/build/__tests__/shared.spec.js +0 -62
- package/build/__tests__/templateStrings.spec.d.ts +0 -2
- package/build/__tests__/templateStrings.spec.js +0 -130
- package/build/modGenScript.d.ts +0 -38
- package/build/modGenScript.js +0 -1027
- package/build/modGenTemplate.d.ts +0 -37
- package/build/modGenTemplate.js +0 -402
- package/build/shared.d.ts +0 -170
- package/build/shared.js +0 -588
|
@@ -0,0 +1,600 @@
|
|
|
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.exportNamedDeclarationForDynamicImport = exports.addUndefinedDefaultExport = exports.propertyToExpression = exports.functionToExpression = exports.bindingToExpression = exports.primitiveToExpression = exports.valueToExpression = exports.processWireFunctionType = exports.processErrorFunction = exports.addImportStatements = exports.generateResolvableModule = void 0;
|
|
27
|
+
const common_shared_1 = require("@komaci/common-shared");
|
|
28
|
+
const static_analyzer_1 = require("@komaci/static-analyzer");
|
|
29
|
+
const t = __importStar(require("@babel/types"));
|
|
30
|
+
const compositionAstGeneration_1 = require("./compositionAstGeneration");
|
|
31
|
+
const componentAstProcessing_1 = require("./componentAstProcessing");
|
|
32
|
+
const types_1 = require("./types");
|
|
33
|
+
const functionAstGeneration_1 = require("./functionAstGeneration");
|
|
34
|
+
const CONTEXT_MAPPING = {
|
|
35
|
+
cpr: 'CurrentPageReference',
|
|
36
|
+
};
|
|
37
|
+
/**
|
|
38
|
+
* Compose a resolvable module for a component. There are three types of outputted resolvable modules
|
|
39
|
+
* - A resolvable module built from a component with ONLY a template
|
|
40
|
+
* - A resolvable module built from a component with ONLY a js file
|
|
41
|
+
* - A resolvable module that has both a template a js file
|
|
42
|
+
*
|
|
43
|
+
* Currently we only support JS and template files that match the names of components
|
|
44
|
+
*
|
|
45
|
+
* @param input Generator input
|
|
46
|
+
* @param scriptKomaciDoc The js komaci doc if it exists
|
|
47
|
+
* @param templateKomaciDoc The tempalte komaci doc if it exists
|
|
48
|
+
* @param source string pointing to the source of the script doc if it exists
|
|
49
|
+
* @returns The babel AST for the generated resolvable module
|
|
50
|
+
*/
|
|
51
|
+
function generateResolvableModule(input, scriptKomaciDoc, templateKomaciDoc, source) {
|
|
52
|
+
const moduleMetadata = (0, common_shared_1.initModuleMetadataObject)();
|
|
53
|
+
let componentDefaultAdgIndex;
|
|
54
|
+
const hasScriptKomaciDoc = scriptKomaciDoc && Object.keys(scriptKomaciDoc).length !== 0;
|
|
55
|
+
const hasTemplateKomaciDoc = templateKomaciDoc && Object.keys(templateKomaciDoc).length !== 0;
|
|
56
|
+
const combinedModule = scriptKomaciDoc !== undefined && templateKomaciDoc !== undefined;
|
|
57
|
+
const isBundle = input.moduleInfo.type === 'bundle';
|
|
58
|
+
// start of metadata collection
|
|
59
|
+
if (scriptKomaciDoc) {
|
|
60
|
+
(0, common_shared_1.initializeImportMetdataFromKomaciDocument)(scriptKomaciDoc, moduleMetadata);
|
|
61
|
+
let ast;
|
|
62
|
+
if (source) {
|
|
63
|
+
ast = (0, common_shared_1.generateAstFromSrcCode)(source);
|
|
64
|
+
(0, common_shared_1.collectImportMetadataFromAst)(ast, moduleMetadata);
|
|
65
|
+
}
|
|
66
|
+
componentDefaultAdgIndex = scriptKomaciDoc.exports?.default?.value;
|
|
67
|
+
scriptKomaciDoc.adgs?.forEach((_, index) => (0, common_shared_1.initalizeAdgMetadata)(index, scriptKomaciDoc, moduleMetadata, componentDefaultAdgIndex === index && ast !== undefined, isBundle));
|
|
68
|
+
(0, common_shared_1.mapExportNamesToAdgs)(scriptKomaciDoc.exports, moduleMetadata);
|
|
69
|
+
if (ast && componentDefaultAdgIndex !== undefined) {
|
|
70
|
+
const { getters, templateStrings } = (0, common_shared_1.getPropertyMetadataFromAst)(ast);
|
|
71
|
+
const moduleContext = {
|
|
72
|
+
astContext: (0, common_shared_1.getAstContextObject)(ast),
|
|
73
|
+
isExternal: (0, common_shared_1.isExternalModule)(input.moduleInfo.namespace),
|
|
74
|
+
};
|
|
75
|
+
(0, componentAstProcessing_1.processGetters)(componentDefaultAdgIndex, moduleContext, moduleMetadata, getters);
|
|
76
|
+
(0, componentAstProcessing_1.processTemplateStrings)(componentDefaultAdgIndex, moduleContext, moduleMetadata, templateStrings);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
if (hasTemplateKomaciDoc) {
|
|
80
|
+
componentDefaultAdgIndex = (0, common_shared_1.reconcileDefaultAdg)(componentDefaultAdgIndex, moduleMetadata);
|
|
81
|
+
(0, common_shared_1.initializeImportMetdataFromKomaciDocument)(templateKomaciDoc, moduleMetadata, true);
|
|
82
|
+
(0, common_shared_1.addTemplateUsageForDefaultAdg)(templateKomaciDoc, componentDefaultAdgIndex, moduleMetadata);
|
|
83
|
+
if (isBundle && !hasScriptKomaciDoc) {
|
|
84
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
85
|
+
(0, common_shared_1.upliftFakePropsFromTemplate)(moduleMetadata.adgs.get(componentDefaultAdgIndex));
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
// for script only docs we assume there there is still a html file around so we build the import to reference that html
|
|
89
|
+
if (!isBundle && hasScriptKomaciDoc && !hasTemplateKomaciDoc) {
|
|
90
|
+
const newImport = (0, common_shared_1.composeImportMetadata)('default', `@salesforce/komaci/${input.moduleInfo.namespace}__${input.moduleInfo.name}__${input.moduleInfo.name}.html`, true, common_shared_1.NO_KOMACI_DOC_REF, moduleMetadata, common_shared_1.IdKeys.DEFAULT_COMP);
|
|
91
|
+
newImport.usedInPriming = true;
|
|
92
|
+
newImport.isFromSupportedLibrary = true;
|
|
93
|
+
newImport.generatorAlias = 'comp1';
|
|
94
|
+
}
|
|
95
|
+
// all metadata collected at this point, time to start building ast
|
|
96
|
+
const statements = [];
|
|
97
|
+
const program = t.program(statements);
|
|
98
|
+
const file = t.file(program);
|
|
99
|
+
addImportStatements(moduleMetadata, statements, {
|
|
100
|
+
calledFromGenerateCombinedModule: combinedModule,
|
|
101
|
+
});
|
|
102
|
+
// template only resolvable modules are composed completely differently (for now)
|
|
103
|
+
if (!combinedModule && hasTemplateKomaciDoc) {
|
|
104
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
105
|
+
const adg = moduleMetadata.adgs.get(componentDefaultAdgIndex);
|
|
106
|
+
const compositionsArray = (0, compositionAstGeneration_1.compositionsToArrayExpression)(moduleMetadata, templateKomaciDoc.compositions) || t.arrayExpression([]);
|
|
107
|
+
// Create default export of the main template function.
|
|
108
|
+
// e.g. `export default function (fct, ctx) {...}`
|
|
109
|
+
const params = [types_1.ID.FACTORY, types_1.ID.CONTEXT];
|
|
110
|
+
const compositionFunction = [];
|
|
111
|
+
const body = t.blockStatement(compositionFunction);
|
|
112
|
+
// Destructuring of factory functions.
|
|
113
|
+
const fctFuncs = (0, functionAstGeneration_1.getFactoryFuncDeclaration)(adg.requiredCompositionFactoryFunctions);
|
|
114
|
+
if (fctFuncs) {
|
|
115
|
+
compositionFunction.push(fctFuncs);
|
|
116
|
+
}
|
|
117
|
+
// Return the array of composition expressions.
|
|
118
|
+
compositionFunction.push(t.returnStatement(compositionsArray));
|
|
119
|
+
statements.push(t.exportDefaultDeclaration(t.functionDeclaration(null, params, body)));
|
|
120
|
+
}
|
|
121
|
+
else {
|
|
122
|
+
// uplift local functions from default exported adg
|
|
123
|
+
if (componentDefaultAdgIndex !== undefined) {
|
|
124
|
+
const defaultAdg = moduleMetadata.adgs.get(componentDefaultAdgIndex);
|
|
125
|
+
defaultAdg?.functions.forEach((func) => {
|
|
126
|
+
if (func.type === common_shared_1.FunctionTypes.GETTER_FUNCTION ||
|
|
127
|
+
func.type === common_shared_1.FunctionTypes.TEMPLATE_STRING) {
|
|
128
|
+
const hoistedFunction = (0, functionAstGeneration_1.hoistLocalFunction)(func, moduleMetadata.importsByName);
|
|
129
|
+
if (hoistedFunction) {
|
|
130
|
+
statements.push(hoistedFunction);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
else {
|
|
136
|
+
statements.push(addUndefinedDefaultExport());
|
|
137
|
+
}
|
|
138
|
+
for (const adg of moduleMetadata.adgs.values()) {
|
|
139
|
+
statements.push((0, functionAstGeneration_1.composeAdgFunction)(adg, moduleMetadata));
|
|
140
|
+
}
|
|
141
|
+
for (const [exportName, adg] of Object.entries(moduleMetadata.exports)) {
|
|
142
|
+
statements.push((0, functionAstGeneration_1.addExportStatement)(adg.defaultGeneratedName, exportName));
|
|
143
|
+
}
|
|
144
|
+
if (input.moduleInfo.type === 'bundle') {
|
|
145
|
+
statements.push(exportNamedDeclarationForDynamicImport(input.moduleInfo.name, input.moduleInfo.namespace, input.options?.targetModule));
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
return file;
|
|
149
|
+
}
|
|
150
|
+
exports.generateResolvableModule = generateResolvableModule;
|
|
151
|
+
/**
|
|
152
|
+
* Adds a babel import decleration to the AST for each Komaci import
|
|
153
|
+
*
|
|
154
|
+
* Note: While this method does not return anything, it does modify the input Statement array.
|
|
155
|
+
*
|
|
156
|
+
* @param {ModuleMetadata} moduleMetadata metadata about the lwc module we are building a resolvable module for
|
|
157
|
+
* @param {Statement[]} statements Array of Statement to be modified by this method for this program
|
|
158
|
+
* @param {{ calledFromGenerateCombinedModule: boolean }} options flag to distinguish whether we have been called
|
|
159
|
+
* to generate a combined module or not.
|
|
160
|
+
*/
|
|
161
|
+
function addImportStatements(moduleMetadata, statements, options) {
|
|
162
|
+
if (moduleMetadata.importsByName.size > 0) {
|
|
163
|
+
const imports = Array.from(moduleMetadata.importsByName.values())
|
|
164
|
+
.sort((a, b) => {
|
|
165
|
+
if (a.resourceName < b.resourceName) {
|
|
166
|
+
return -1;
|
|
167
|
+
}
|
|
168
|
+
else if (a.resourceName > b.resourceName) {
|
|
169
|
+
return 1;
|
|
170
|
+
}
|
|
171
|
+
else {
|
|
172
|
+
return 0;
|
|
173
|
+
}
|
|
174
|
+
})
|
|
175
|
+
.filter((value) => value.isFromInternalNamespace && value.usedInPriming);
|
|
176
|
+
let i = 0;
|
|
177
|
+
while (i < imports.length) {
|
|
178
|
+
const specifiers = [];
|
|
179
|
+
let resourceName = imports[i].resourceName;
|
|
180
|
+
while (i < imports.length && imports[i].resourceName === resourceName) {
|
|
181
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
182
|
+
const localName = t.identifier(imports[i].generatorAlias);
|
|
183
|
+
let specifier;
|
|
184
|
+
const exportName = imports[i].name;
|
|
185
|
+
if (exportName === 'default') {
|
|
186
|
+
// e.g. `import i1 from "@salesforce/user/Id";`
|
|
187
|
+
specifier = t.importDefaultSpecifier(localName);
|
|
188
|
+
specifiers.unshift(specifier);
|
|
189
|
+
}
|
|
190
|
+
else if (exportName === '*' &&
|
|
191
|
+
moduleMetadata.importsByNamespace.get(resourceName)?.names.size === 1) {
|
|
192
|
+
// e.g. `import i1 from "@salesforce/user/Id";`
|
|
193
|
+
specifier = t.importNamespaceSpecifier(localName);
|
|
194
|
+
specifiers.push(specifier);
|
|
195
|
+
}
|
|
196
|
+
else {
|
|
197
|
+
// e.g. `import { getRecord as i1 } from "lightning/uiRecordApi";`.
|
|
198
|
+
// `getRecord` is the exportName, `i1` is the localName
|
|
199
|
+
specifier = t.importSpecifier(localName, t.identifier(exportName));
|
|
200
|
+
specifiers.push(specifier);
|
|
201
|
+
}
|
|
202
|
+
i++;
|
|
203
|
+
}
|
|
204
|
+
if ((0, static_analyzer_1.isSupportedNamespace)(resourceName) && specifiers.length > 0) {
|
|
205
|
+
if (options.calledFromGenerateCombinedModule &&
|
|
206
|
+
resourceName.startsWith('@salesforce/komaci')) {
|
|
207
|
+
// @salesforce/komaci/c__foo__foo.js -> @salesforce/komaci/c__foo
|
|
208
|
+
const lastIndex = resourceName.lastIndexOf('__');
|
|
209
|
+
resourceName = resourceName.slice(0, lastIndex);
|
|
210
|
+
}
|
|
211
|
+
const resource = t.stringLiteral(resourceName);
|
|
212
|
+
const importDeclaration = t.importDeclaration(specifiers, resource);
|
|
213
|
+
statements.push(importDeclaration);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
exports.addImportStatements = addImportStatements;
|
|
219
|
+
/**
|
|
220
|
+
* Make ast statements for the details about an error we received
|
|
221
|
+
* @param adgFunc The error function metadata
|
|
222
|
+
* @param moduleMetadata metadata about the module as whole
|
|
223
|
+
* @returns ast statemenets representing config for this function node
|
|
224
|
+
*/
|
|
225
|
+
function processErrorFunction(adgFunc, moduleMetadata) {
|
|
226
|
+
const funcObjProps = [];
|
|
227
|
+
const t_value = t.stringLiteral(types_1.ERROR_FUNCTION);
|
|
228
|
+
const configObjExpr = valueToExpression(adgFunc.input[0], moduleMetadata);
|
|
229
|
+
funcObjProps.push(t.objectProperty(types_1.ID.FUNC_TYPE, t_value), t.objectProperty(types_1.ID.FUNC_CONFIG, configObjExpr));
|
|
230
|
+
return funcObjProps;
|
|
231
|
+
}
|
|
232
|
+
exports.processErrorFunction = processErrorFunction;
|
|
233
|
+
/**
|
|
234
|
+
* Function to generate the object property array for a wire function node type.
|
|
235
|
+
*
|
|
236
|
+
* NOTE: if the obj representing the function is from an unsupported namespace, and it
|
|
237
|
+
* is for a wire function, then leave out the function node from the generated resolvable
|
|
238
|
+
* module, by returning undefined.
|
|
239
|
+
* @param {ImportInfo} importInfo import information against which to check the wire function's validity
|
|
240
|
+
* @param {GeneratorState} generatorState the current state of the esm generator
|
|
241
|
+
* @param {FunctionType} adgFunc a wire function from the adg functions array.
|
|
242
|
+
* @returns {ObjectProperty[]} an representation of the wire function node as array of ObjectProperty
|
|
243
|
+
*/
|
|
244
|
+
function processWireFunctionType(adgFunc, moduleMetadata) {
|
|
245
|
+
// Validate and set function type, e.g. `t: "WireFunction"`
|
|
246
|
+
if (adgFunc.type !== common_shared_1.FunctionTypes.WIRE_FUNCTION &&
|
|
247
|
+
adgFunc.type !== common_shared_1.FunctionTypes.PRIMING_FUNCTION) {
|
|
248
|
+
throw new Error(common_shared_1.ERROR_PREFIX + 'ADG function has invalid type');
|
|
249
|
+
}
|
|
250
|
+
const adapterImport = moduleMetadata.importsByName.get(adgFunc.importReference.functionName);
|
|
251
|
+
if (adapterImport) {
|
|
252
|
+
const funcObjProps = [];
|
|
253
|
+
// if the obj representing the function is from an unsupported namespace, and it is for a wire function,
|
|
254
|
+
// then leave out the function node form the generated resolvable module, by returning undefined.
|
|
255
|
+
const resourceName = adapterImport.resourceName;
|
|
256
|
+
const exportName = adapterImport.name;
|
|
257
|
+
if (!exportName ||
|
|
258
|
+
!(0, static_analyzer_1.isSupportedNamespace)(resourceName) ||
|
|
259
|
+
(adgFunc.type === common_shared_1.FunctionTypes.WIRE_FUNCTION &&
|
|
260
|
+
!(0, common_shared_1.isSupportedWireAdapter)(resourceName, exportName))) {
|
|
261
|
+
return undefined;
|
|
262
|
+
}
|
|
263
|
+
if (adgFunc.type === common_shared_1.FunctionTypes.PRIMING_FUNCTION) {
|
|
264
|
+
// Add props for imports relating to this priming adapter.
|
|
265
|
+
funcObjProps.push(t.objectProperty(types_1.ID.FUNC_ID, t.identifier(adapterImport.generatorAlias)), t.objectProperty(types_1.ID.FUNC_NAME, t.stringLiteral(adgFunc.importReference.functionName)));
|
|
266
|
+
if (adgFunc.importReference.batchingName &&
|
|
267
|
+
moduleMetadata.importsByName.has(adgFunc.importReference.batchingName)) {
|
|
268
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
269
|
+
const batchImport = moduleMetadata.importsByName.get(adgFunc.importReference.batchingName);
|
|
270
|
+
funcObjProps.push(t.objectProperty(types_1.ID.BATCH_FUNC_ID, t.identifier(batchImport.generatorAlias)), t.objectProperty(types_1.ID.BATCH_FUNC_NAME, t.stringLiteral(adgFunc.importReference.batchingName)));
|
|
271
|
+
}
|
|
272
|
+
if (adgFunc.importReference.reducer &&
|
|
273
|
+
moduleMetadata.importsByName.has(adgFunc.importReference.reducer)) {
|
|
274
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
275
|
+
const reducerImport = moduleMetadata.importsByName.get(adgFunc.importReference.reducer);
|
|
276
|
+
funcObjProps.push(t.objectProperty(types_1.ID.REDUCER_FUNC_ID, t.identifier(reducerImport.generatorAlias)));
|
|
277
|
+
}
|
|
278
|
+
funcObjProps.push(t.objectProperty(types_1.ID.FUNC_TYPE, t.stringLiteral(types_1.PRIMING_FUNCTION)));
|
|
279
|
+
}
|
|
280
|
+
else {
|
|
281
|
+
// Traditional wire adapter.
|
|
282
|
+
funcObjProps.push(t.objectProperty(types_1.ID.FUNC_ID, t.identifier(adapterImport.generatorAlias)), t.objectProperty(types_1.ID.FUNC_NAME, t.stringLiteral(getWireName(resourceName, exportName))), t.objectProperty(types_1.ID.FUNC_TYPE, t.stringLiteral(types_1.WIRE_FUNCTION)));
|
|
283
|
+
// Check if the export name matches one of the supported context wires. If so we set
|
|
284
|
+
// wire type. e.g. `wt: "cpr"`
|
|
285
|
+
if (isSupportedContextWire(exportName)) {
|
|
286
|
+
const contextWireName = Object.keys(CONTEXT_MAPPING).find((key) => CONTEXT_MAPPING[key] === exportName);
|
|
287
|
+
if (contextWireName) {
|
|
288
|
+
funcObjProps.push(t.objectProperty(types_1.ID.WIRE_TYPE, t.stringLiteral(contextWireName)));
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
else if (isApexWire(resourceName)) {
|
|
292
|
+
funcObjProps.push(t.objectProperty(types_1.ID.WIRE_TYPE, t.stringLiteral('apex')));
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
// Construct function to return config object and list of input properties.
|
|
296
|
+
let configObjExpr;
|
|
297
|
+
const inputProps = new Set();
|
|
298
|
+
if (adgFunc.input && adgFunc.input.length > 0) {
|
|
299
|
+
if (adgFunc.input.length !== 1 || adgFunc.input[0].type !== 'ObjectValue') {
|
|
300
|
+
// Only valid input according to Wire Adapter Protocol.
|
|
301
|
+
throw new Error(common_shared_1.ERROR_PREFIX + 'WireFunction has invalid input');
|
|
302
|
+
}
|
|
303
|
+
const inputObject = adgFunc.input[0];
|
|
304
|
+
configObjExpr = t.objectExpression([]);
|
|
305
|
+
configObjExpr = valueToExpression(inputObject, moduleMetadata); // wireconfig import usage
|
|
306
|
+
// Create list of property names which are inputs into the function.
|
|
307
|
+
for (const propValue of Object.values(inputObject.value)) {
|
|
308
|
+
// NOTE: LWC doesn't allow for property references to be nested in
|
|
309
|
+
// objects or arrays, so only need to check the top-level props.
|
|
310
|
+
if (propValue.type === 'PropertyReference') {
|
|
311
|
+
inputProps.add(propValue.value.split('/')[0]);
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
else {
|
|
316
|
+
// Matches LWC compiler behavior which always pass an object into a wire's
|
|
317
|
+
// update() method. Even if original source doesn't provide config.
|
|
318
|
+
configObjExpr = t.objectExpression([]);
|
|
319
|
+
}
|
|
320
|
+
// e.g. `c: ctx => ({ recordId: "001RM000004UZqLYAW" })`
|
|
321
|
+
const configFunc = t.arrowFunctionExpression([types_1.ID.CONTEXT], configObjExpr);
|
|
322
|
+
funcObjProps.push(t.objectProperty(types_1.ID.FUNC_CONFIG, configFunc));
|
|
323
|
+
// e.g. in: ['recordId', 'fields']
|
|
324
|
+
if (inputProps.size) {
|
|
325
|
+
funcObjProps.push(t.objectProperty(types_1.ID.FUNC_INPUT, t.arrayExpression(Array.from(inputProps).map((v) => t.stringLiteral(v)))));
|
|
326
|
+
}
|
|
327
|
+
return funcObjProps;
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
exports.processWireFunctionType = processWireFunctionType;
|
|
331
|
+
/**
|
|
332
|
+
* Determines whether an export name matches one of the supported context wires
|
|
333
|
+
* @param {string | undefined} exportName the exportName of an import statement
|
|
334
|
+
* @returns {boolean} boolean true if the the export name matches a supported context wire
|
|
335
|
+
*/
|
|
336
|
+
function isSupportedContextWire(exportName) {
|
|
337
|
+
return (exportName !== undefined && Object.values(CONTEXT_MAPPING).includes(exportName));
|
|
338
|
+
}
|
|
339
|
+
/**
|
|
340
|
+
* Determines whether the resourceName of an import statement is that of an Apex wire
|
|
341
|
+
* @param {string | undefined} resourceName a string representing the resource name (ex: '@salesforce/apex/myApexwire')
|
|
342
|
+
* @returns {boolean} true if the resource name represent that of an Apex wire, false otherwise
|
|
343
|
+
*/
|
|
344
|
+
function isApexWire(resourceName) {
|
|
345
|
+
return !!(resourceName && resourceName.startsWith('@salesforce/apex/'));
|
|
346
|
+
}
|
|
347
|
+
/**
|
|
348
|
+
* Retrieves the name of an Apex wire
|
|
349
|
+
* @param {string} resourceName a string representing the resource name (ex: '@salesforce/apex/ContactController.getContactList')
|
|
350
|
+
* @param {string} exportName a string representing the name of the export (ex: `awire` in `import awire from '@salesforce/apex/awire'`)
|
|
351
|
+
* @returns {string} the Apex wire name, as a string
|
|
352
|
+
*/
|
|
353
|
+
function getWireName(resourceName, exportName) {
|
|
354
|
+
if (isApexWire(resourceName)) {
|
|
355
|
+
// eg. @salesforce/apex/ContactController.getContactList -> ContactController.getContactList
|
|
356
|
+
return resourceName.substring('@salesforce/apex/'.length);
|
|
357
|
+
}
|
|
358
|
+
return exportName;
|
|
359
|
+
}
|
|
360
|
+
/**
|
|
361
|
+
* Convert any possible value within a Komaci ADG to a babel expression.
|
|
362
|
+
* @param komaciValue the komaci value
|
|
363
|
+
* @param moduleMetadata the module meta data object
|
|
364
|
+
* @returns a babel expression for the komaci value.
|
|
365
|
+
*/
|
|
366
|
+
function valueToExpression(komaciValue, moduleMetadata) {
|
|
367
|
+
let newExpression;
|
|
368
|
+
switch (komaciValue.type) {
|
|
369
|
+
case 'PrimitiveValue':
|
|
370
|
+
newExpression = primitiveToExpression(komaciValue);
|
|
371
|
+
break;
|
|
372
|
+
case 'ImportReference': {
|
|
373
|
+
const importIndexReference = moduleMetadata.importIndexReference.get(komaciValue.value);
|
|
374
|
+
if (importIndexReference) {
|
|
375
|
+
const importMetadata = moduleMetadata.importsByName.get(importIndexReference);
|
|
376
|
+
newExpression =
|
|
377
|
+
importMetadata?.isFromInternalNamespace &&
|
|
378
|
+
importMetadata?.isFromSupportedLibrary &&
|
|
379
|
+
importMetadata.generatorAlias
|
|
380
|
+
? t.identifier(importMetadata.generatorAlias)
|
|
381
|
+
: t.identifier(types_1.UNRESOLVED);
|
|
382
|
+
}
|
|
383
|
+
else {
|
|
384
|
+
newExpression = t.identifier(types_1.UNRESOLVED);
|
|
385
|
+
}
|
|
386
|
+
if (newExpression?.name !== types_1.UNRESOLVED && komaciValue.namespacedMember) {
|
|
387
|
+
newExpression = t.memberExpression(newExpression, t.identifier(komaciValue.namespacedMember));
|
|
388
|
+
}
|
|
389
|
+
break;
|
|
390
|
+
}
|
|
391
|
+
case 'PropertyReference': {
|
|
392
|
+
return bindingToExpression(komaciValue);
|
|
393
|
+
}
|
|
394
|
+
case 'Unresolved':
|
|
395
|
+
newExpression = types_1.ID.UNRESOLVED_VALUE;
|
|
396
|
+
break;
|
|
397
|
+
case 'ArrayValue': {
|
|
398
|
+
const elements = [];
|
|
399
|
+
komaciValue.value.forEach((element) => {
|
|
400
|
+
elements.push(valueToExpression(element, moduleMetadata));
|
|
401
|
+
});
|
|
402
|
+
newExpression = t.arrayExpression(elements);
|
|
403
|
+
break;
|
|
404
|
+
}
|
|
405
|
+
case 'ObjectValue': {
|
|
406
|
+
const objProps = [];
|
|
407
|
+
for (const [propName, propValue] of Object.entries(komaciValue.value)) {
|
|
408
|
+
objProps.push(t.objectProperty(t.stringLiteral(propName), valueToExpression(propValue, moduleMetadata)));
|
|
409
|
+
}
|
|
410
|
+
newExpression = t.objectExpression(objProps);
|
|
411
|
+
break;
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
if (!newExpression) {
|
|
415
|
+
throw new Error(`${common_shared_1.ERROR_PREFIX}: Unrecognized value type`);
|
|
416
|
+
}
|
|
417
|
+
return newExpression;
|
|
418
|
+
}
|
|
419
|
+
exports.valueToExpression = valueToExpression;
|
|
420
|
+
/**
|
|
421
|
+
* Convert a Komaci primitive value to babel expression.
|
|
422
|
+
* @param primitive a primitve value
|
|
423
|
+
* @returns an expression that represents the primitive value.
|
|
424
|
+
*/
|
|
425
|
+
function primitiveToExpression(primitive) {
|
|
426
|
+
switch (typeof primitive.value) {
|
|
427
|
+
case 'number':
|
|
428
|
+
return t.numericLiteral(primitive.value);
|
|
429
|
+
case 'string':
|
|
430
|
+
return t.stringLiteral(primitive.value);
|
|
431
|
+
case 'boolean':
|
|
432
|
+
return t.booleanLiteral(primitive.value);
|
|
433
|
+
case 'undefined':
|
|
434
|
+
return types_1.ID.UNDEFINED;
|
|
435
|
+
default:
|
|
436
|
+
return t.nullLiteral();
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
exports.primitiveToExpression = primitiveToExpression;
|
|
440
|
+
/**
|
|
441
|
+
* Convert binding (or PropertyReference) to a babel expr (e.g. record.value?.Id).
|
|
442
|
+
* @param binding The binding object
|
|
443
|
+
* @param iterationContext If this binding is inside an iteration we need the contextual details about the iteration to build the proper expression
|
|
444
|
+
* @param parseRootOnly There are some cases where we only care about the first piece of the binding. in the example above we might need to only check `record` instead of `record.value?.Id`
|
|
445
|
+
* @returns A composed member expression
|
|
446
|
+
*/
|
|
447
|
+
function bindingToExpression(binding, iterationContext, parseRootOnly = false) {
|
|
448
|
+
if (!binding.value.length) {
|
|
449
|
+
if (binding.type === 'Binding') {
|
|
450
|
+
throw new Error(common_shared_1.ERROR_PREFIX + 'encountered empty binding');
|
|
451
|
+
}
|
|
452
|
+
throw new Error(common_shared_1.ERROR_PREFIX + 'encountered empty property reference');
|
|
453
|
+
}
|
|
454
|
+
let segments = binding.value.split('/'); // segments[0] === propertyName
|
|
455
|
+
if (parseRootOnly) {
|
|
456
|
+
segments = [segments[0]];
|
|
457
|
+
}
|
|
458
|
+
let chainingStartIdx = 2;
|
|
459
|
+
let iteratorBinding = false;
|
|
460
|
+
// Am I in the context of an iteration?
|
|
461
|
+
if (iterationContext && iterationContext.includes(segments[0])) {
|
|
462
|
+
// Referencing property of an iteration
|
|
463
|
+
iteratorBinding = true; // flag to distinguish whether we are in the context of an iteration
|
|
464
|
+
chainingStartIdx = 1;
|
|
465
|
+
}
|
|
466
|
+
else {
|
|
467
|
+
chainingStartIdx = 2;
|
|
468
|
+
segments.unshift(common_shared_1.CONTEXT, common_shared_1.PROPS); // Referencing property in context, so prepend ctx.props
|
|
469
|
+
}
|
|
470
|
+
// Build member expression w/ optional chaining to prevent runtime TypeError.
|
|
471
|
+
// If we are in the context of an iterator binding, we must prepend the user variable prefix
|
|
472
|
+
let expr = iteratorBinding
|
|
473
|
+
? t.identifier(types_1.USER_VARIABLE_PREFIX + segments[0])
|
|
474
|
+
: t.identifier(segments[0]);
|
|
475
|
+
for (let i = 1; i < segments.length; ++i) {
|
|
476
|
+
expr = t.optionalMemberExpression(expr, t.identifier(segments[i]), false, i > chainingStartIdx);
|
|
477
|
+
}
|
|
478
|
+
return expr;
|
|
479
|
+
}
|
|
480
|
+
exports.bindingToExpression = bindingToExpression;
|
|
481
|
+
/**
|
|
482
|
+
* Convert a single Komaci function to an object expression in the shape of a
|
|
483
|
+
* FunctionDefinition as defined in Resolver API.
|
|
484
|
+
* @param {GeneratorState} generatorState the current esm generator state
|
|
485
|
+
* @param {FunctionType} adgFunc a function from the adg functions arrray.
|
|
486
|
+
* @returns {Expression} a babel Expression if propertly processed or undefined.
|
|
487
|
+
*/
|
|
488
|
+
function functionToExpression(moduleMetadata, adgFunc) {
|
|
489
|
+
if (adgFunc.type === common_shared_1.FunctionTypes.GETTER_FUNCTION) {
|
|
490
|
+
const getterFuncObjPropArr = processLocalFunction(adgFunc, common_shared_1.GETTER_FUNCTION);
|
|
491
|
+
return t.objectExpression(getterFuncObjPropArr);
|
|
492
|
+
}
|
|
493
|
+
else if (adgFunc.type === common_shared_1.FunctionTypes.TEMPLATE_STRING) {
|
|
494
|
+
return t.objectExpression(processLocalFunction(adgFunc, common_shared_1.TEMPLATED_STRING_FUNCTION));
|
|
495
|
+
}
|
|
496
|
+
else if (adgFunc.type === common_shared_1.FunctionTypes.ERROR) {
|
|
497
|
+
return t.objectExpression(processErrorFunction(adgFunc, moduleMetadata));
|
|
498
|
+
}
|
|
499
|
+
else if (adgFunc.type === common_shared_1.FunctionTypes.WIRE_FUNCTION ||
|
|
500
|
+
adgFunc.type === common_shared_1.FunctionTypes.PRIMING_FUNCTION) {
|
|
501
|
+
const wireFunctionObjArr = processWireFunctionType(adgFunc, moduleMetadata);
|
|
502
|
+
if (wireFunctionObjArr) {
|
|
503
|
+
return t.objectExpression(wireFunctionObjArr);
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
return undefined;
|
|
507
|
+
}
|
|
508
|
+
exports.functionToExpression = functionToExpression;
|
|
509
|
+
/**
|
|
510
|
+
* Function to create the object property array for a local function
|
|
511
|
+
* @param {FunctionType} adgFunc a function from the adg functions array.
|
|
512
|
+
* @param {string} type The type of function. getter or templated string
|
|
513
|
+
* @returns {ObjectProperty[]} a babel object property array.
|
|
514
|
+
*/
|
|
515
|
+
function processLocalFunction(hoistedFunc, type) {
|
|
516
|
+
const funcObjProps = [];
|
|
517
|
+
const f_reference = {
|
|
518
|
+
type: 'Identifier',
|
|
519
|
+
name: hoistedFunc.generatedName ? hoistedFunc.generatedName : types_1.UNRESOLVED,
|
|
520
|
+
leadingComments: null,
|
|
521
|
+
innerComments: null,
|
|
522
|
+
trailingComments: null,
|
|
523
|
+
start: null,
|
|
524
|
+
end: null,
|
|
525
|
+
loc: null,
|
|
526
|
+
};
|
|
527
|
+
const t_value = t.stringLiteral(type);
|
|
528
|
+
funcObjProps.push(t.objectProperty(types_1.ID.FUNC_ID, f_reference), t.objectProperty(types_1.ID.FUNC_TYPE, t_value));
|
|
529
|
+
hoistedFunc.requiredProperties;
|
|
530
|
+
if (hoistedFunc.requiredProperties) {
|
|
531
|
+
const in_value = t.arrayExpression(hoistedFunc.requiredProperties.map((v) => t.stringLiteral(v)));
|
|
532
|
+
funcObjProps.push(t.objectProperty(types_1.ID.FUNC_INPUT, in_value));
|
|
533
|
+
}
|
|
534
|
+
return funcObjProps;
|
|
535
|
+
}
|
|
536
|
+
/**
|
|
537
|
+
* Convert a single Komaci property to an object expression in the shape of
|
|
538
|
+
* a PropertyDefinition as defined in Resolver API.
|
|
539
|
+
* @param {GeneratorState} generatorState the current state of esm-generator
|
|
540
|
+
* @param {Adg} adg the current ADG from which to seek out FunctionReferences
|
|
541
|
+
* @param {Propery} property the Komaci property to process
|
|
542
|
+
* @returns {Expression} the komaci property converted to an object Expression
|
|
543
|
+
*/
|
|
544
|
+
function propertyToExpression(moduleMetadata, property) {
|
|
545
|
+
const objProps = [];
|
|
546
|
+
// Whether the prop is public or not, e.g. `a: true`.
|
|
547
|
+
objProps.push(t.objectProperty(types_1.ID.PROP_API, t.booleanLiteral(property.isPublic)));
|
|
548
|
+
if (property.inital) {
|
|
549
|
+
// initial value
|
|
550
|
+
// Initial value of the prop, e.g. `i: 5`.
|
|
551
|
+
objProps.push(t.objectProperty(types_1.ID.PROP_INIT, valueToExpression(property.inital, moduleMetadata)));
|
|
552
|
+
}
|
|
553
|
+
if (property.type === common_shared_1.PropertyTypes.GETTER ||
|
|
554
|
+
property.type === common_shared_1.PropertyTypes.WIRE ||
|
|
555
|
+
property.type === common_shared_1.PropertyTypes.TEMPLATE_STRING) {
|
|
556
|
+
// Index of function where this property receives input, e.g. `f: 0`.
|
|
557
|
+
const funcIdx = property.functionIndex;
|
|
558
|
+
if (funcIdx === common_shared_1.UNSUPPORTED_FUNCTION) {
|
|
559
|
+
objProps.push(t.objectProperty(types_1.ID.PROP_GETTER, types_1.ID.UNRESOLVED_VALUE));
|
|
560
|
+
}
|
|
561
|
+
else {
|
|
562
|
+
objProps.push(t.objectProperty(types_1.ID.PROP_FUNC, t.numericLiteral(funcIdx)));
|
|
563
|
+
}
|
|
564
|
+
}
|
|
565
|
+
return t.objectExpression(objProps);
|
|
566
|
+
}
|
|
567
|
+
exports.propertyToExpression = propertyToExpression;
|
|
568
|
+
/**
|
|
569
|
+
* Adds a default export to the program statements, if no default export that is derived from an AdgReference already exists
|
|
570
|
+
*
|
|
571
|
+
* @returns composed AST statement for undefined default export
|
|
572
|
+
*/
|
|
573
|
+
function addUndefinedDefaultExport() {
|
|
574
|
+
return t.exportDefaultDeclaration(t.functionDeclaration(null, [], t.blockStatement([t.returnStatement(types_1.ID.UNDEFINED)])));
|
|
575
|
+
}
|
|
576
|
+
exports.addUndefinedDefaultExport = addUndefinedDefaultExport;
|
|
577
|
+
/**
|
|
578
|
+
* Adds the dynamic import of target module, but only for bundles (if moduleInfo.type === "bundle").
|
|
579
|
+
*
|
|
580
|
+
* Returns an export named declaration. The declaration is assigned an arrowFunctionExpression, which returns
|
|
581
|
+
* a dynamic import based on the moduleInfo namespace and name.
|
|
582
|
+
* @param moduleName The name of module we're making
|
|
583
|
+
* @param moduleNamespace the namespace for this given module
|
|
584
|
+
* @param targetModule name of the target module if it exists
|
|
585
|
+
* @returns ExportNamedDeclaration containing the statement of the dynamic import of the target module
|
|
586
|
+
*/
|
|
587
|
+
function exportNamedDeclarationForDynamicImport(moduleName, moduleNamespace, targetModule) {
|
|
588
|
+
const IMPORT_TARGET = 'importTarget';
|
|
589
|
+
const FUNC_NAME_IMPORT = 'import';
|
|
590
|
+
const CONST_TYPE = 'const';
|
|
591
|
+
const moduleResourceName = targetModule || moduleNamespace + '/' + moduleName;
|
|
592
|
+
const returnStatement = t.returnStatement(t.callExpression(t.identifier(FUNC_NAME_IMPORT), [
|
|
593
|
+
t.stringLiteral(moduleResourceName),
|
|
594
|
+
]));
|
|
595
|
+
return t.exportNamedDeclaration(t.variableDeclaration(CONST_TYPE, [
|
|
596
|
+
t.variableDeclarator(t.identifier(IMPORT_TARGET), t.arrowFunctionExpression([], t.blockStatement([returnStatement]))),
|
|
597
|
+
]));
|
|
598
|
+
}
|
|
599
|
+
exports.exportNamedDeclarationForDynamicImport = exportNamedDeclarationForDynamicImport;
|
|
600
|
+
//# sourceMappingURL=genericAstGeneration.js.map
|
package/build/index.d.ts
CHANGED
|
@@ -1,4 +1,10 @@
|
|
|
1
1
|
import { GeneratorInput } from './types';
|
|
2
2
|
export { GeneratorInput } from './types';
|
|
3
3
|
export declare function generateKomaciModule(input: GeneratorInput): string;
|
|
4
|
+
/**
|
|
5
|
+
* Helper function to process and build the resolvable module based off the generator input and inital generator state.
|
|
6
|
+
* @param input the Generator input
|
|
7
|
+
* @returns the resolvable module.
|
|
8
|
+
*/
|
|
9
|
+
export declare function processGeneratorInputAndState(input: GeneratorInput): string;
|
|
4
10
|
//# sourceMappingURL=index.d.ts.map
|