@komaci/esm-generator 242.1.5 → 242.1.6

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 (19) hide show
  1. package/build/__tests__/adgAstGeneration.spec.js +1 -0
  2. package/build/__tests__/fixtures-combined-files-multiple-templates/invalid-renderFunc-no-valid-imports/c/component/component.d.ts +4 -0
  3. package/build/__tests__/fixtures-combined-files-multiple-templates/invalid-renderFunc-no-valid-imports/c/component/component.js +14 -0
  4. package/build/__tests__/fixtures-combined-files-multiple-templates/valid-render-function-complex/lightning/component/component.d.ts +5 -0
  5. package/build/__tests__/fixtures-combined-files-multiple-templates/valid-render-function-complex/lightning/component/component.js +31 -0
  6. package/build/__tests__/fixtures-combined-files-multiple-templates/valid-render-function-simple/lightning/component/component.d.ts +5 -0
  7. package/build/__tests__/fixtures-combined-files-multiple-templates/valid-render-function-simple/lightning/component/component.js +27 -0
  8. package/build/__tests__/fixtures-source-code/generalMockSourceCode.d.ts +3 -0
  9. package/build/__tests__/fixtures-source-code/generalMockSourceCode.js +35 -1
  10. package/build/__tests__/functionAstGeneration.spec.js +122 -0
  11. package/build/__tests__/genericAstGeneration.spec.js +19 -4
  12. package/build/__tests__/komaci-bundle-multiple-templates-module.fixtures.spec.d.ts +2 -0
  13. package/build/__tests__/komaci-bundle-multiple-templates-module.fixtures.spec.js +117 -0
  14. package/build/componentAstProcessing.d.ts +10 -1
  15. package/build/componentAstProcessing.js +29 -1
  16. package/build/functionAstGeneration.js +15 -1
  17. package/build/genericAstGeneration.d.ts +2 -2
  18. package/build/genericAstGeneration.js +25 -11
  19. package/package.json +4 -4
@@ -14,6 +14,7 @@ describe('getAdgFunctionBody', () => {
14
14
  });
15
15
  it('only contains a return statement if no factory functions are needed', () => {
16
16
  const adg = (0, common_shared_1.initAdgMetadataObject)('adg0');
17
+ adg.requiredAdgFactoryFunctions.delete(common_shared_1.IdKeys.ADG_FUNC);
17
18
  const res = (0, functionAstGeneration_1.getAdgFunctionBody)(adg, moduleMetadata);
18
19
  expect(res.body).toHaveLength(1);
19
20
  expect(res.body[0].type).toBe('ReturnStatement');
@@ -0,0 +1,4 @@
1
+ export default class KomaciAction {
2
+ render(): any;
3
+ }
4
+ //# sourceMappingURL=component.d.ts.map
@@ -0,0 +1,14 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const lwc_1 = require("lwc");
7
+ const shared_1 = __importDefault(require("force/shared"));
8
+ class KomaciAction extends lwc_1.LightningElement {
9
+ render() {
10
+ return shared_1.default; //invalid, not returning an imported template.
11
+ }
12
+ }
13
+ exports.default = KomaciAction;
14
+ //# sourceMappingURL=component.js.map
@@ -0,0 +1,5 @@
1
+ export default class KomaciAction {
2
+ showTemplateOne: boolean;
3
+ render(): any;
4
+ }
5
+ //# sourceMappingURL=component.d.ts.map
@@ -0,0 +1,31 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __importDefault = (this && this.__importDefault) || function (mod) {
9
+ return (mod && mod.__esModule) ? mod : { "default": mod };
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ const lwc_1 = require("lwc");
13
+ const component_html_1 = __importDefault(require("./component.html"));
14
+ const templateOne_html_1 = __importDefault(require("./templateOne.html"));
15
+ class KomaciAction extends lwc_1.LightningElement {
16
+ constructor() {
17
+ super(...arguments);
18
+ this.showTemplateOne = true;
19
+ }
20
+ render() {
21
+ if (this.showTemplateOne) {
22
+ return templateOne_html_1.default;
23
+ }
24
+ return component_html_1.default;
25
+ }
26
+ }
27
+ __decorate([
28
+ lwc_1.api
29
+ ], KomaciAction.prototype, "showTemplateOne", void 0);
30
+ exports.default = KomaciAction;
31
+ //# sourceMappingURL=component.js.map
@@ -0,0 +1,5 @@
1
+ export default class Component {
2
+ showTemplateOne: boolean;
3
+ render(): any;
4
+ }
5
+ //# sourceMappingURL=component.d.ts.map
@@ -0,0 +1,27 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __importDefault = (this && this.__importDefault) || function (mod) {
9
+ return (mod && mod.__esModule) ? mod : { "default": mod };
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ const lwc_1 = require("lwc");
13
+ const component_html_1 = __importDefault(require("./component.html"));
14
+ class Component extends lwc_1.LightningElement {
15
+ constructor() {
16
+ super(...arguments);
17
+ this.showTemplateOne = true;
18
+ }
19
+ render() {
20
+ return component_html_1.default;
21
+ }
22
+ }
23
+ __decorate([
24
+ lwc_1.api
25
+ ], Component.prototype, "showTemplateOne", void 0);
26
+ exports.default = Component;
27
+ //# sourceMappingURL=component.js.map
@@ -2,4 +2,7 @@ export declare const mockOneBadGetter = "import { LightningElement, wire, api }
2
2
  export declare const mockOnlyBadGetter = "import { LightningElement, wire, api } from 'lwc';\nimport { getRecord } from 'lightning/uiRecordApi';\nimport findContacts from '@salesforce/apex/ContactController.findContacts';\n\nexport default class Example extends LightningElement {\n @api\n recordId;\n\n get searchKey() {\n const recordName = this.record?.data?.Fields?.name;\n this.blah = \"asdf\"; //invalid\n if(recordName) {\n return '%' + recordName + '%';\n }\n return 'Default Search Key';\n }\n\n @wire(getRecord, { recordId: '$recordId', layoutTypes: ['Full'], modes: ['View'] })\n record = {};\n\n @wire(findContacts, { searchKey: '$searchKey' })\n contacts;\n}";
3
3
  export declare const oneGoodMockWithGetterImportUse = "import { LightningElement, wire, api } from 'lwc';\nimport { getRecord } from 'lightning/uiRecordApi';\nimport findContacts from '@salesforce/apex/ContactController.findContacts';\nimport Foo from 'force/shared';\nimport { Bar } from 'force/shared';\n\nexport default class Example extends LightningElement {\n @api\n recordId;\n\n get searchKey() {\n const recordName = this.record?.data?.Fields?.name;\n this.blah = \"asdf\"; //invalid\n if(recordName) {\n return '%' + recordName + '%';\n }\n return 'Default Search Key';\n }\n\n get perfectlyGood() {\n const recordName = this.record?.data?.Fields?.name;\n return Foo;\n }\n\n get perfectlyGood2() {\n return Bar;\n }\n\n @wire(getRecord, { recordId: '$recordId', layoutTypes: ['Full'], modes: ['View'] })\n record = {};\n\n @wire(findContacts, { searchKey: '$searchKey', filter: '$perfectlyGood', split: '$perfectlyGood2' })\n contacts;\n}";
4
4
  export declare const emptyProgram = "";
5
+ export declare const mockSrcCode_Pass_Valid_Render_Conditional = "import { LightningElement, api } from 'lwc';\nimport templateOne from './templateOne.html';\nimport templateTwo from './templateTwo.html';\n\nexport default class MiscMultipleTemplates extends LightningElement {\n @api templateOne = true;\n\n render() {\n return this.templateOne ? templateOne : templateTwo;\n }\n}";
6
+ export declare const mockSrcCode_Pass_Valid_Render_DefaultTemplate = "import { LightningElement, api } from 'lwc';\nimport defaultTemplate from './komaciAction.html';\n\nexport default class KomaciAction extends LightningElement {\n \n render() {\n return defaultTemplate;\n }\n}";
7
+ export declare const mockSrcCode_Pass_Valid_Render_MultipleReturns = "import { LightningElement, api } from 'lwc';\nimport templateOne from './templateOne.html';\nimport defaultTemplate from './komaciAction.html';\n\nexport default class KomaciAction extends LightningElement {\n @api showTemplateOne = true;\n\n render() {\n if(this.templateOne){\n return templateOne; \n }\n return defaultTemplate\n }\n}";
5
8
  //# sourceMappingURL=generalMockSourceCode.d.ts.map
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.emptyProgram = exports.oneGoodMockWithGetterImportUse = exports.mockOnlyBadGetter = exports.mockOneBadGetter = void 0;
3
+ exports.mockSrcCode_Pass_Valid_Render_MultipleReturns = exports.mockSrcCode_Pass_Valid_Render_DefaultTemplate = exports.mockSrcCode_Pass_Valid_Render_Conditional = exports.emptyProgram = exports.oneGoodMockWithGetterImportUse = exports.mockOnlyBadGetter = exports.mockOneBadGetter = void 0;
4
4
  exports.mockOneBadGetter = `import { LightningElement, wire, api } from 'lwc';
5
5
  import { getRecord } from 'lightning/uiRecordApi';
6
6
  import findContacts from '@salesforce/apex/ContactController.findContacts';
@@ -90,4 +90,38 @@ export default class Example extends LightningElement {
90
90
  contacts;
91
91
  }`;
92
92
  exports.emptyProgram = ``;
93
+ exports.mockSrcCode_Pass_Valid_Render_Conditional = `import { LightningElement, api } from 'lwc';
94
+ import templateOne from './templateOne.html';
95
+ import templateTwo from './templateTwo.html';
96
+
97
+ export default class MiscMultipleTemplates extends LightningElement {
98
+ @api templateOne = true;
99
+
100
+ render() {
101
+ return this.templateOne ? templateOne : templateTwo;
102
+ }
103
+ }`;
104
+ exports.mockSrcCode_Pass_Valid_Render_DefaultTemplate = `import { LightningElement, api } from 'lwc';
105
+ import defaultTemplate from './komaciAction.html';
106
+
107
+ export default class KomaciAction extends LightningElement {
108
+
109
+ render() {
110
+ return defaultTemplate;
111
+ }
112
+ }`;
113
+ exports.mockSrcCode_Pass_Valid_Render_MultipleReturns = `import { LightningElement, api } from 'lwc';
114
+ import templateOne from './templateOne.html';
115
+ import defaultTemplate from './komaciAction.html';
116
+
117
+ export default class KomaciAction extends LightningElement {
118
+ @api showTemplateOne = true;
119
+
120
+ render() {
121
+ if(this.templateOne){
122
+ return templateOne;
123
+ }
124
+ return defaultTemplate
125
+ }
126
+ }`;
93
127
  //# sourceMappingURL=generalMockSourceCode.js.map
@@ -11,6 +11,7 @@ const types_1 = require("@babel/types");
11
11
  const functionAstGeneration_1 = require("../functionAstGeneration");
12
12
  const generator_1 = __importDefault(require("@babel/generator"));
13
13
  const badImportRef_1 = require("./fixtures-source-code/badImportRef");
14
+ const generalMockSourceCode_1 = require("./fixtures-source-code/generalMockSourceCode");
14
15
  describe('hoistLocalFunction', () => {
15
16
  const baseFilesPath = (0, path_1.join)(__dirname, 'general-komaci-docs/assorted-template-strings');
16
17
  const src = (0, fs_1.readFileSync)((0, path_1.join)(baseFilesPath, 'source.js'), {
@@ -90,6 +91,127 @@ describe('hoistLocalFunction', () => {
90
91
  .body[0].argument.tag.name).toBe('i1');
91
92
  });
92
93
  });
94
+ describe('hoistlocalfunction for render function', () => {
95
+ const templateOneImportMetaData = {
96
+ name: 'i0',
97
+ generatorAlias: 'templateOne',
98
+ resourceName: './templateOne.html',
99
+ komaciDocImportRef: 'nil',
100
+ isFromInternalNamespace: true,
101
+ isFromSupportedLibrary: true,
102
+ usedInPriming: false,
103
+ staticallyAnalyzable: false,
104
+ templateKomaciDoc: {},
105
+ adgReference: 'adg1',
106
+ };
107
+ const templateTwoImportMetaData = {
108
+ name: 'i1',
109
+ generatorAlias: 'templateTwo',
110
+ resourceName: './templateTwo.html',
111
+ komaciDocImportRef: 'nil',
112
+ isFromInternalNamespace: true,
113
+ isFromSupportedLibrary: true,
114
+ usedInPriming: false,
115
+ staticallyAnalyzable: false,
116
+ templateKomaciDoc: {},
117
+ adgReference: 'adg2',
118
+ };
119
+ const defaultTemplateImportMetadata = {
120
+ name: 'i0',
121
+ generatorAlias: 'defaultTemplate',
122
+ resourceName: './komaciAction.html',
123
+ komaciDocImportRef: 'nil',
124
+ isFromInternalNamespace: true,
125
+ isFromSupportedLibrary: true,
126
+ usedInPriming: false,
127
+ staticallyAnalyzable: false,
128
+ templateKomaciDoc: {},
129
+ adgReference: 'adg0',
130
+ };
131
+ it('can hoist a validated render function, conditional return', () => {
132
+ const moduleMetadata = (0, common_shared_1.initModuleMetadataObject)();
133
+ moduleMetadata.importsByName.set('templateOne', templateOneImportMetaData);
134
+ moduleMetadata.importsByName.set('templateTwo', templateTwoImportMetaData);
135
+ const renderFunctionExampleAst = (0, common_shared_1.generateAstFromSrcCode)(generalMockSourceCode_1.mockSrcCode_Pass_Valid_Render_Conditional);
136
+ const { renderFunction } = (0, common_shared_1.getPropertyMetadataFromAst)(renderFunctionExampleAst);
137
+ const renderFunctionMetadata = {
138
+ type: common_shared_1.FunctionTypes.RENDER_FUNCTION,
139
+ componentAstNode: renderFunction,
140
+ requiredProperties: ['templateOne'],
141
+ generatedName: `hoistedRenderFunction`,
142
+ };
143
+ const hoistedRenderFunction = (0, functionAstGeneration_1.hoistLocalFunction)(renderFunctionMetadata, moduleMetadata.importsByName);
144
+ expect(hoistedRenderFunction).not.toBeUndefined();
145
+ const hoistedBodyStatements = hoistedRenderFunction?.body.body;
146
+ expect(hoistedBodyStatements).not.toBeUndefined();
147
+ expect(hoistedBodyStatements).toHaveLength(1);
148
+ const returnStmt = hoistedBodyStatements != undefined ? hoistedBodyStatements[0] : undefined;
149
+ expect(returnStmt).not.toBeUndefined();
150
+ expect(returnStmt?.type).toBe('ReturnStatement');
151
+ const argument = returnStmt.argument;
152
+ expect(argument?.type).toBe('ConditionalExpression');
153
+ const consequent = argument.consequent;
154
+ const alternate = argument.alternate;
155
+ expect(consequent.name).toBe(templateOneImportMetaData.adgReference);
156
+ expect(alternate.name).toBe(templateTwoImportMetaData.adgReference);
157
+ });
158
+ it('can hoist a validated render when returning default template', () => {
159
+ const moduleMetadata = (0, common_shared_1.initModuleMetadataObject)();
160
+ moduleMetadata.importsByName.set('defaultTemplate', defaultTemplateImportMetadata);
161
+ const renderFunctionExampleAst = (0, common_shared_1.generateAstFromSrcCode)(generalMockSourceCode_1.mockSrcCode_Pass_Valid_Render_DefaultTemplate);
162
+ const { renderFunction } = (0, common_shared_1.getPropertyMetadataFromAst)(renderFunctionExampleAst);
163
+ const renderFunctionMetadata = {
164
+ type: common_shared_1.FunctionTypes.RENDER_FUNCTION,
165
+ componentAstNode: renderFunction,
166
+ requiredProperties: ['templateOne'],
167
+ generatedName: `hoistedRenderFunction`,
168
+ };
169
+ const hoistedRenderFunction = (0, functionAstGeneration_1.hoistLocalFunction)(renderFunctionMetadata, moduleMetadata.importsByName);
170
+ expect(hoistedRenderFunction).not.toBeUndefined();
171
+ const hoistedBodyStatements = hoistedRenderFunction?.body.body;
172
+ expect(hoistedBodyStatements).not.toBeUndefined();
173
+ expect(hoistedBodyStatements).toHaveLength(1);
174
+ const returnStmt = hoistedBodyStatements != undefined ? hoistedBodyStatements[0] : undefined;
175
+ expect(returnStmt).not.toBeUndefined();
176
+ expect(returnStmt?.type).toBe('ReturnStatement');
177
+ const argument = returnStmt.argument;
178
+ expect(argument?.type).toBe('Identifier');
179
+ expect(argument.name).toBe(defaultTemplateImportMetadata.adgReference);
180
+ });
181
+ it('can hoist a validated render function with multiple valid returns', () => {
182
+ const moduleMetadata = (0, common_shared_1.initModuleMetadataObject)();
183
+ moduleMetadata.importsByName.set('templateOne', templateOneImportMetaData);
184
+ moduleMetadata.importsByName.set('defaultTemplate', defaultTemplateImportMetadata);
185
+ const renderFunctionExampleAst = (0, common_shared_1.generateAstFromSrcCode)(generalMockSourceCode_1.mockSrcCode_Pass_Valid_Render_MultipleReturns);
186
+ const { renderFunction } = (0, common_shared_1.getPropertyMetadataFromAst)(renderFunctionExampleAst);
187
+ const renderFunctionMetadata = {
188
+ type: common_shared_1.FunctionTypes.RENDER_FUNCTION,
189
+ componentAstNode: renderFunction,
190
+ requiredProperties: ['templateOne'],
191
+ generatedName: `hoistedRenderFunction`,
192
+ };
193
+ const hoistedRenderFunction = (0, functionAstGeneration_1.hoistLocalFunction)(renderFunctionMetadata, moduleMetadata.importsByName);
194
+ expect(hoistedRenderFunction).not.toBeUndefined();
195
+ const hoistedBodyStatements = hoistedRenderFunction?.body.body;
196
+ expect(hoistedBodyStatements).not.toBeUndefined();
197
+ expect(hoistedBodyStatements).not.toBeUndefined();
198
+ expect(hoistedBodyStatements).toHaveLength(2);
199
+ const ifStmt = hoistedBodyStatements != undefined ? hoistedBodyStatements[0] : undefined;
200
+ expect(ifStmt).not.toBeUndefined();
201
+ expect(ifStmt?.type).toBe('IfStatement');
202
+ const ifBody = ifStmt.consequent.body;
203
+ expect(ifBody).toHaveLength(1);
204
+ const ifReturnStmt = ifBody[0];
205
+ expect(ifReturnStmt).not.toBeUndefined();
206
+ expect(ifReturnStmt.argument.name).toBe(templateOneImportMetaData.adgReference);
207
+ const returnStmt = hoistedBodyStatements != undefined ? hoistedBodyStatements[1] : undefined;
208
+ expect(returnStmt).not.toBeUndefined();
209
+ expect(returnStmt?.type).toBe('ReturnStatement');
210
+ const argument = returnStmt.argument;
211
+ expect(argument?.type).toBe('Identifier');
212
+ expect(argument.name).toBe(defaultTemplateImportMetadata.adgReference);
213
+ });
214
+ });
93
215
  describe('sanitizeFunction', () => {
94
216
  const ast = (0, common_shared_1.generateAstFromSrcCode)(badImportRef_1.sourceClass);
95
217
  const { getters } = (0, common_shared_1.getPropertyMetadataFromAst)(ast);
@@ -30,6 +30,18 @@ const generator_1 = __importDefault(require("@babel/generator"));
30
30
  const common_shared_1 = require("@komaci/common-shared");
31
31
  const genericAstGeneration_1 = require("../genericAstGeneration");
32
32
  const t = __importStar(require("@babel/types"));
33
+ /**
34
+ * A function to validate all adgs against to make sure we are doing the bare minimum stuff
35
+ * @param adgs list of all adgs
36
+ */
37
+ const confirmBaselineAdgExpectations = (adgs, extraValidation) => {
38
+ for (const adg of adgs) {
39
+ expect(adg.requiredAdgFactoryFunctions.has(common_shared_1.IdKeys.ADG_FUNC)).toBeTruthy();
40
+ if (extraValidation) {
41
+ extraValidation(adg);
42
+ }
43
+ }
44
+ };
33
45
  describe('valueToExpression', () => {
34
46
  it('composes proper statement for complex object. Includes ObjectValue, ArrayValue, PropertyReference, and Primitive Value', () => {
35
47
  const wireFunctionObject = {
@@ -583,7 +595,7 @@ describe('addImportStatements', () => {
583
595
  expect(combinedImport).not.toBeUndefined();
584
596
  });
585
597
  });
586
- describe('collectMetadataForNonDefaultTemplates', () => {
598
+ describe('collectMetadataForImportedTemplates', () => {
587
599
  const templateMap = {};
588
600
  beforeEach(() => {
589
601
  // fixture-template-files/component-refernece
@@ -813,7 +825,8 @@ describe('collectMetadataForNonDefaultTemplates', () => {
813
825
  };
814
826
  moduleMetadata.importsByName.set('child1', templateImport);
815
827
  //assuming that component-reference is the default.
816
- (0, genericAstGeneration_1.collectMetadataForNonDefaultTemplates)(moduleMetadata, 'component-reference');
828
+ (0, genericAstGeneration_1.collectMetadataForImportedTemplates)(moduleMetadata, 'component-reference');
829
+ confirmBaselineAdgExpectations(Object.values(moduleMetadata.adgs));
817
830
  expect(moduleMetadata.adgGeneratorIndex).toBe(2);
818
831
  expect(moduleMetadata.importGeneratorIndex).toBe(2);
819
832
  expect(moduleMetadata.importIndexReference.get('t1-0/names/0')).not.toBeUndefined();
@@ -853,7 +866,8 @@ describe('collectMetadataForNonDefaultTemplates', () => {
853
866
  };
854
867
  moduleMetadata.importsByName.set('child2', templateImport2);
855
868
  //assuming that component-reference is the default.
856
- (0, genericAstGeneration_1.collectMetadataForNonDefaultTemplates)(moduleMetadata, 'default-template');
869
+ (0, genericAstGeneration_1.collectMetadataForImportedTemplates)(moduleMetadata, 'default-template');
870
+ confirmBaselineAdgExpectations(Object.values(moduleMetadata.adgs));
857
871
  expect(moduleMetadata.adgGeneratorIndex).toBe(3);
858
872
  expect(moduleMetadata.importGeneratorIndex).toBe(5);
859
873
  expect(moduleMetadata.importIndexReference.get('t1-0/names/0')).not.toBeUndefined();
@@ -869,7 +883,8 @@ describe('collectMetadataForNonDefaultTemplates', () => {
869
883
  const defaultAdg = (0, common_shared_1.initAdgMetadataObject)('adg0');
870
884
  moduleMetadata.adgs.set(0, defaultAdg);
871
885
  //assuming that component-reference is the default.
872
- (0, genericAstGeneration_1.collectMetadataForNonDefaultTemplates)(moduleMetadata, 'component-reference');
886
+ (0, genericAstGeneration_1.collectMetadataForImportedTemplates)(moduleMetadata, 'component-reference');
887
+ confirmBaselineAdgExpectations(Object.values(moduleMetadata.adgs));
873
888
  expect(moduleMetadata.adgGeneratorIndex).toBe(1);
874
889
  expect(moduleMetadata.importGeneratorIndex).toBe(0);
875
890
  });
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=komaci-bundle-multiple-templates-module.fixtures.spec.d.ts.map
@@ -0,0 +1,117 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ /* eslint-disable @typescript-eslint/no-explicit-any */
7
+ const fs_1 = __importDefault(require("fs"));
8
+ const glob_1 = __importDefault(require("glob"));
9
+ const path_1 = __importDefault(require("path"));
10
+ const index_1 = require("../index");
11
+ const fs_2 = require("fs");
12
+ const path_2 = require("path");
13
+ const lwc_metadata_next_1 = require("@lwc-platform/lwc-metadata-next");
14
+ const FIXTURES_DIR = path_1.default.join(__dirname, 'fixtures-combined-files-multiple-templates');
15
+ const EXPECTED_JS_FILENAME = 'expected.src';
16
+ // eslint-disable-next-line jest/no-disabled-tests
17
+ describe('fixtures', () => {
18
+ // find all folder paths containing a directory called component. This gives us the flexability to name the parent directory
19
+ // either lightning for external comps and c for internal comps.
20
+ const fixtures = glob_1.default.sync(path_1.default.resolve(FIXTURES_DIR, '**/*/component'));
21
+ for (const caseEntry of fixtures) {
22
+ const caseFolder = path_1.default.dirname(caseEntry);
23
+ const relativePath = path_1.default.relative(FIXTURES_DIR, caseFolder);
24
+ const caseName = relativePath.split('/')[0];
25
+ const expectedSrcFilePath = () => {
26
+ return (caseFolder.slice(0, caseFolder.lastIndexOf('/')) +
27
+ '/' +
28
+ EXPECTED_JS_FILENAME);
29
+ };
30
+ const readFixtureFile = (filePath) => {
31
+ return fs_1.default.existsSync(filePath) ? fs_1.default.readFileSync(filePath, 'utf-8') : null;
32
+ };
33
+ const writeFixtureFile = (filePath, content) => {
34
+ fs_1.default.writeFileSync(filePath, content, { encoding: 'utf-8' });
35
+ };
36
+ it(`${caseName}`, () => {
37
+ const expectedFilePath = expectedSrcFilePath();
38
+ const actualModuleSrc = readAndParseBundle(caseEntry, {
39
+ enableKomaci: true,
40
+ type: 'internal',
41
+ }).output.modGenOutput;
42
+ let expectedModuleSrc = readFixtureFile(expectedFilePath);
43
+ if (expectedModuleSrc == null) {
44
+ // write file if doesn't exist (ie new fixture)
45
+ expectedModuleSrc = actualModuleSrc;
46
+ writeFixtureFile(expectedFilePath, expectedModuleSrc);
47
+ }
48
+ // check that the actual newly generated mod source matches expected
49
+ expect(actualModuleSrc).toEqual(expectedModuleSrc);
50
+ });
51
+ }
52
+ });
53
+ /**
54
+ * Finds all .js, .mjs, .css, and .html files within the given directory, reads their contents, and combines them into a bundle,
55
+ * and returning the array of BundleFile containing the file's fileName and source
56
+ * @param path
57
+ * @returns An array of BundleFile
58
+ */
59
+ function readBundle(path) {
60
+ path = (0, path_2.resolve)(path);
61
+ if ((0, fs_2.existsSync)(path)) {
62
+ const contents = (0, fs_2.readdirSync)(path);
63
+ const LWC_EXT = ['.js', '.mjs', '.css', '.html'];
64
+ const lwcBundleFiles = contents.filter((filename) => {
65
+ return LWC_EXT.includes((0, path_2.extname)(filename));
66
+ });
67
+ return lwcBundleFiles.map((fileName) => ({
68
+ fileName,
69
+ source: (0, fs_2.readFileSync)((0, path_2.resolve)(path, fileName), 'utf-8').toString(),
70
+ }));
71
+ }
72
+ else {
73
+ throw new Error(`path doesn't exist: ${path}`);
74
+ }
75
+ }
76
+ /**
77
+ * Takes the directory path of an LWC module bundle and an optional set of config overrides. Returns the ParsedBundle, inlcuding
78
+ * the bundle's 1) LWC Metadata and 2) Komaci / Resolvable module.
79
+ * @param path
80
+ * @param configOverrides
81
+ * @returns ParsedBundle that includes the BundleConfig & GeneratorInput inputs, and BundleMetadata and generated module output
82
+ */
83
+ function readAndParseBundle(path, configOverrides) {
84
+ const files = readBundle(path);
85
+ const name = (0, path_2.basename)(path);
86
+ const namespace = (0, path_2.basename)((0, path_2.dirname)(path));
87
+ const bundleConfig = {
88
+ namespace,
89
+ name,
90
+ type: 'internal',
91
+ namespaceMapping: {},
92
+ files,
93
+ enableKomaci: true,
94
+ ...configOverrides,
95
+ };
96
+ const metadata = (0, lwc_metadata_next_1.collectBundleMetadata)(bundleConfig);
97
+ // Create input to module generator.
98
+ const srcFileMap = files.reduce((map, { fileName, source }) => ({ ...map, [fileName]: source }), {});
99
+ const inputFiles = Object.fromEntries(metadata.files
100
+ .map(({ fileName, komaciDoc }) => [fileName, komaciDoc])
101
+ .filter(([, komaciDoc]) => !!komaciDoc));
102
+ const generatorInput = {
103
+ moduleInfo: {
104
+ name,
105
+ namespace: bundleConfig.namespace,
106
+ type: 'bundle',
107
+ files: inputFiles,
108
+ },
109
+ srcFileMap,
110
+ };
111
+ const modGenOutput = (0, index_1.generateKomaciModule)(generatorInput);
112
+ return {
113
+ input: { bundleConfig, generatorInput },
114
+ output: { modGenOutput, metadata },
115
+ };
116
+ }
117
+ //# sourceMappingURL=komaci-bundle-multiple-templates-module.fixtures.spec.js.map
@@ -1,7 +1,7 @@
1
1
  import * as t from '@babel/types';
2
2
  import { GeneratorInput } from './types';
3
3
  import { NodePath } from '@babel/core';
4
- import { ModuleContext, ModuleMetadata } from '@komaci/common-shared';
4
+ import { ModuleContext, ModuleMetadata, HoistedFunctionMetadata } from '@komaci/common-shared';
5
5
  /**
6
6
  * Retrieve the file path for the js of a component
7
7
  * @param generatorState GeneratorState containg the GeneratorInput, which in turn contains the JS raw source file
@@ -31,4 +31,13 @@ export declare function processGetters(adgIndex: number, moduleContext: ModuleCo
31
31
  * @returns Information about valid templates to be added to the resolvable Module.
32
32
  */
33
33
  export declare function processTemplateStrings(adgIndex: number, moduleContext: ModuleContext, moduleMetadata: ModuleMetadata, templateStrings: Array<NodePath<t.ClassProperty>>): void;
34
+ /**
35
+ * Function to validate a render function and compose a HoistedFunctionMetadata object if render function is valid.
36
+ * @param adgIndex the adg index
37
+ * @param moduleContext the module context
38
+ * @param moduleMetadata the moduleMetadata object
39
+ * @param renderFunction the render function babel object
40
+ * @returns a HoistedFunctionMetadata object or undefined
41
+ */
42
+ export declare function processRenderFunction(adgIndex: number, moduleContext: ModuleContext, moduleMetadata: ModuleMetadata, renderFunction: NodePath<t.ClassMethod>): HoistedFunctionMetadata | undefined;
34
43
  //# sourceMappingURL=componentAstProcessing.d.ts.map
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.processTemplateStrings = exports.processGetters = exports.getComponentSrcJs = void 0;
3
+ exports.processRenderFunction = exports.processTemplateStrings = exports.processGetters = exports.getComponentSrcJs = void 0;
4
4
  const static_analyzer_1 = require("@komaci/static-analyzer");
5
5
  const common_shared_1 = require("@komaci/common-shared");
6
6
  /**
@@ -103,4 +103,32 @@ function processTemplateStrings(adgIndex, moduleContext, moduleMetadata, templat
103
103
  });
104
104
  }
105
105
  exports.processTemplateStrings = processTemplateStrings;
106
+ /**
107
+ * Function to validate a render function and compose a HoistedFunctionMetadata object if render function is valid.
108
+ * @param adgIndex the adg index
109
+ * @param moduleContext the module context
110
+ * @param moduleMetadata the moduleMetadata object
111
+ * @param renderFunction the render function babel object
112
+ * @returns a HoistedFunctionMetadata object or undefined
113
+ */
114
+ function processRenderFunction(adgIndex, moduleContext, moduleMetadata, renderFunction) {
115
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
116
+ const adg = moduleMetadata.adgs.get(adgIndex);
117
+ const isRenderFunctionValid = (0, static_analyzer_1.validateRenderFunction)(renderFunction, adgIndex, moduleMetadata, moduleContext, false);
118
+ if (isRenderFunctionValid) {
119
+ const { identifiers } = (0, common_shared_1.implicitConsumptionMetadata)(renderFunction, adgIndex, moduleMetadata);
120
+ const functionMeta = {
121
+ type: common_shared_1.FunctionTypes.RENDER_FUNCTION,
122
+ componentAstNode: renderFunction,
123
+ requiredProperties: identifiers,
124
+ generatedName: `hoistedRenderFunction`,
125
+ };
126
+ (0, common_shared_1.updatePropertyUsage)('hoistedRenderFunction', identifiers, adg.properties, common_shared_1.PropertyTypes.RENDER_FUNCTION);
127
+ return functionMeta;
128
+ }
129
+ else {
130
+ return undefined;
131
+ }
132
+ }
133
+ exports.processRenderFunction = processRenderFunction;
106
134
  //# sourceMappingURL=componentAstProcessing.js.map
@@ -79,7 +79,21 @@ function sanitizeFunction(nodePath, importMetadata) {
79
79
  }
80
80
  const info = importMetadata.get(path.node.name);
81
81
  if (info && info.isFromInternalNamespace && info.isFromSupportedLibrary) {
82
- path.replaceWith(t.identifier(info.generatorAlias)); // replace usage of import specifier
82
+ const templateImport = info;
83
+ const importedTemplateKomaciDoc = templateImport.templateKomaciDoc;
84
+ //the identifier we are looking at is importing a template and we have a komaci doc for it.
85
+ if (importedTemplateKomaciDoc) {
86
+ if (templateImport.adgReference) {
87
+ path.replaceWith(t.identifier(templateImport.adgReference));
88
+ }
89
+ else {
90
+ //This should not happen but here for coverage incase an edge case is missed we will know where to look.
91
+ throw new Error(`${common_shared_1.ERROR_PREFIX}: '${path.node.name}' does not have an associated adg reference`);
92
+ }
93
+ }
94
+ else {
95
+ path.replaceWith(t.identifier(info.generatorAlias)); // replace usage of import specifier
96
+ }
83
97
  }
84
98
  else if (info &&
85
99
  !(info.isFromInternalNamespace && info.isFromSupportedLibrary)) {
@@ -107,9 +107,9 @@ export declare function addUndefinedDefaultExport(): t.ExportDefaultDeclaration;
107
107
  */
108
108
  export declare function exportNamedDeclarationForDynamicImport(moduleName: string, moduleNamespace: string, targetModule?: string): t.ExportNamedDeclaration;
109
109
  /**
110
- * Helper function to collect metadata for non default templates.
110
+ * Helper function to collect metadata for imported templates. NOTE: if the default html doc is being imported it will only update the associated ADG reference
111
111
  * @param templateMap the map of html filenames to its generated komaci document
112
112
  * @param defaultTemplateFileName the name of the default template.
113
113
  */
114
- export declare function collectMetadataForNonDefaultTemplates(moduleMetadata: ModuleMetadata, defaultTemplateFileName: string): void;
114
+ export declare function collectMetadataForImportedTemplates(moduleMetadata: ModuleMetadata, defaultTemplateFileName: string, defaultAdgIndex?: number): void;
115
115
  //# sourceMappingURL=genericAstGeneration.d.ts.map
@@ -23,7 +23,7 @@ var __importStar = (this && this.__importStar) || function (mod) {
23
23
  return result;
24
24
  };
25
25
  Object.defineProperty(exports, "__esModule", { value: true });
26
- exports.collectMetadataForNonDefaultTemplates = exports.exportNamedDeclarationForDynamicImport = exports.addUndefinedDefaultExport = exports.propertyToExpression = exports.functionToExpression = exports.bindingToExpression = exports.primitiveToExpression = exports.valueToExpression = exports.processWireFunctionType = exports.processErrorFunction = exports.addImportStatements = exports.generateResolvableModule = void 0;
26
+ exports.collectMetadataForImportedTemplates = 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
27
  const common_shared_1 = require("@komaci/common-shared");
28
28
  const static_analyzer_1 = require("@komaci/static-analyzer");
29
29
  const t = __importStar(require("@babel/types"));
@@ -63,6 +63,7 @@ function generateResolvableModule(input, scriptKomaciDoc, templateKomaciDocMap,
63
63
  const hasTemplateKomaciDoc = defaultTemplateKomaciDoc && Object.keys(defaultTemplateKomaciDoc).length !== 0;
64
64
  const combinedModule = scriptKomaciDoc !== undefined && defaultTemplateKomaciDoc !== undefined;
65
65
  const isBundle = input.moduleInfo.type === 'bundle';
66
+ let renderFunctionMetadata = undefined;
66
67
  // start of metadata collection
67
68
  if (scriptKomaciDoc) {
68
69
  (0, common_shared_1.initializeImportMetdataFromKomaciDocument)(scriptKomaciDoc, moduleMetadata);
@@ -75,13 +76,17 @@ function generateResolvableModule(input, scriptKomaciDoc, templateKomaciDocMap,
75
76
  scriptKomaciDoc.adgs?.forEach((_, index) => (0, common_shared_1.initalizeAdgMetadata)(index, scriptKomaciDoc, moduleMetadata, componentDefaultAdgIndex === index && ast !== undefined, isBundle));
76
77
  (0, common_shared_1.mapExportNamesToAdgs)(scriptKomaciDoc.exports, moduleMetadata);
77
78
  if (ast && componentDefaultAdgIndex !== undefined) {
78
- const { getters, templateStrings } = (0, common_shared_1.getPropertyMetadataFromAst)(ast);
79
+ const { getters, templateStrings, renderFunction } = (0, common_shared_1.getPropertyMetadataFromAst)(ast);
79
80
  const moduleContext = {
80
81
  astContext: (0, common_shared_1.getAstContextObject)(ast),
81
82
  isExternal: (0, common_shared_1.isExternalModule)(input.moduleInfo.namespace),
82
83
  };
83
84
  (0, componentAstProcessing_1.processGetters)(componentDefaultAdgIndex, moduleContext, moduleMetadata, getters);
84
85
  (0, componentAstProcessing_1.processTemplateStrings)(componentDefaultAdgIndex, moduleContext, moduleMetadata, templateStrings);
86
+ //If there is a render function, process it.
87
+ if (renderFunction) {
88
+ renderFunctionMetadata = (0, componentAstProcessing_1.processRenderFunction)(componentDefaultAdgIndex, moduleContext, moduleMetadata, renderFunction);
89
+ }
85
90
  }
86
91
  }
87
92
  //has a default html file
@@ -104,10 +109,9 @@ function generateResolvableModule(input, scriptKomaciDoc, templateKomaciDocMap,
104
109
  newImport.isFromSupportedLibrary = true;
105
110
  newImport.generatorAlias = 'comp1';
106
111
  }
107
- //if there is a default komaci doc, its already processed. need to process the rest of the template komaci docs that aren't the default if there is any.
108
- if (!hasTemplateKomaciDoc ||
109
- Object.keys(moduleMetadata.templateKomaciDocMap).length > 1) {
110
- collectMetadataForNonDefaultTemplates(moduleMetadata, input.moduleInfo.name);
112
+ //as long as we have at least one template, check to see if its imported. In the case the default html doc is imported, the assocated adg refernce will be set.
113
+ if (Object.keys(moduleMetadata.templateKomaciDocMap).length > 0) {
114
+ collectMetadataForImportedTemplates(moduleMetadata, input.moduleInfo.name, componentDefaultAdgIndex);
111
115
  }
112
116
  // all metadata collected at this point, time to start building ast
113
117
  const statements = [];
@@ -153,6 +157,12 @@ function generateResolvableModule(input, scriptKomaciDoc, templateKomaciDocMap,
153
157
  }
154
158
  }
155
159
  });
160
+ if (renderFunctionMetadata) {
161
+ const hoistedRenderFunction = (0, functionAstGeneration_1.hoistLocalFunction)(renderFunctionMetadata, moduleMetadata.importsByName);
162
+ if (hoistedRenderFunction) {
163
+ statements.push(hoistedRenderFunction);
164
+ }
165
+ }
156
166
  }
157
167
  else {
158
168
  statements.push(addUndefinedDefaultExport());
@@ -620,25 +630,29 @@ function exportNamedDeclarationForDynamicImport(moduleName, moduleNamespace, tar
620
630
  }
621
631
  exports.exportNamedDeclarationForDynamicImport = exportNamedDeclarationForDynamicImport;
622
632
  /**
623
- * Helper function to collect metadata for non default templates.
633
+ * Helper function to collect metadata for imported templates. NOTE: if the default html doc is being imported it will only update the associated ADG reference
624
634
  * @param templateMap the map of html filenames to its generated komaci document
625
635
  * @param defaultTemplateFileName the name of the default template.
626
636
  */
627
- function collectMetadataForNonDefaultTemplates(moduleMetadata, defaultTemplateFileName) {
637
+ function collectMetadataForImportedTemplates(moduleMetadata, defaultTemplateFileName, defaultAdgIndex) {
628
638
  moduleMetadata.importsByName.forEach((importMetadata) => {
629
639
  if ((0, common_shared_1.isTemplateImport)(importMetadata)) {
630
- const templateKomaciDoc = importMetadata
631
- .templateKomaciDoc;
640
+ const importedTemplateMetadata = importMetadata;
641
+ const templateKomaciDoc = importedTemplateMetadata.templateKomaciDoc;
632
642
  const segs = (0, common_shared_1.getFilepathSegments)(importMetadata.resourceName);
633
643
  if (segs[1].replace('/', '') !== defaultTemplateFileName) {
634
644
  const templateAdgIndex = moduleMetadata.adgGeneratorIndex++;
635
645
  const templateAdgMetadata = (0, common_shared_1.initAdgMetadataObject)(`adg${templateAdgIndex}`);
636
646
  moduleMetadata.adgs.set(templateAdgIndex, templateAdgMetadata);
647
+ importedTemplateMetadata.adgReference = `adg${templateAdgIndex}`;
637
648
  (0, common_shared_1.initializeImportMetdataFromKomaciDocument)(templateKomaciDoc, moduleMetadata, templateAdgIndex);
638
649
  (0, common_shared_1.addTemplateUsageForAdg)(templateKomaciDoc, templateAdgIndex, moduleMetadata);
639
650
  }
651
+ else {
652
+ importedTemplateMetadata.adgReference = `adg${defaultAdgIndex}`;
653
+ }
640
654
  }
641
655
  });
642
656
  }
643
- exports.collectMetadataForNonDefaultTemplates = collectMetadataForNonDefaultTemplates;
657
+ exports.collectMetadataForImportedTemplates = collectMetadataForImportedTemplates;
644
658
  //# sourceMappingURL=genericAstGeneration.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@komaci/esm-generator",
3
- "version": "242.1.5",
3
+ "version": "242.1.6",
4
4
  "description": "Komaci generator for ADG ES modules",
5
5
  "homepage": "https://komaci.dev/",
6
6
  "repository": {
@@ -28,13 +28,13 @@
28
28
  "dependencies": {
29
29
  "@babel/core": "^7.9.0",
30
30
  "@babel/generator": "^7.9.0",
31
- "@komaci/common-shared": "242.1.5",
32
- "@komaci/static-analyzer": "242.1.5",
31
+ "@komaci/common-shared": "242.1.6",
32
+ "@komaci/static-analyzer": "242.1.6",
33
33
  "o11y": "^240.7.0"
34
34
  },
35
35
  "devDependencies": {
36
36
  "@babel/types": "^7.9.0",
37
- "@komaci/types": "242.1.5",
37
+ "@komaci/types": "242.1.6",
38
38
  "@lwc-platform/sfdc-lwc-compiler": "^2.18.0-240.2"
39
39
  }
40
40
  }