@komaci/esm-generator 260.38.0 → 260.40.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.
|
@@ -363,7 +363,7 @@ export default class Component extends LightningElement {
|
|
|
363
363
|
// Test that bundles with .ts files are processed correctly
|
|
364
364
|
expect(() => {
|
|
365
365
|
const bundleConfig = {
|
|
366
|
-
namespace: '
|
|
366
|
+
namespace: 'lightning',
|
|
367
367
|
name: 'tsComponent',
|
|
368
368
|
type: 'internal',
|
|
369
369
|
namespaceMapping: {},
|
|
@@ -25,6 +25,7 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|
|
25
25
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
26
|
const __1 = require("..");
|
|
27
27
|
const modgen = __importStar(require("../genericAstGeneration"));
|
|
28
|
+
const metadata_1 = require("@lwc/metadata");
|
|
28
29
|
describe('Handling errors that throw inside a call to generateKomaciModule', () => {
|
|
29
30
|
it('should return error adg when an error is produced', () => {
|
|
30
31
|
const input = {
|
|
@@ -290,4 +291,203 @@ describe('normalizeSrcFileKeys', () => {
|
|
|
290
291
|
expect(input.srcFileMap['templates/test2.html']).not.toBeUndefined();
|
|
291
292
|
});
|
|
292
293
|
});
|
|
294
|
+
describe('Bundle processing', () => {
|
|
295
|
+
it('when both .js and .ts files exist with for the component name', () => {
|
|
296
|
+
const bundleSrcFileMap = {
|
|
297
|
+
'test.js': {},
|
|
298
|
+
'test.ts': {},
|
|
299
|
+
'test.html': {},
|
|
300
|
+
};
|
|
301
|
+
const input = {
|
|
302
|
+
moduleInfo: {
|
|
303
|
+
name: 'test',
|
|
304
|
+
namespace: 'lightning',
|
|
305
|
+
type: 'bundle',
|
|
306
|
+
files: bundleSrcFileMap,
|
|
307
|
+
},
|
|
308
|
+
srcFileMap: {
|
|
309
|
+
'test.js': 'export default class Test {}',
|
|
310
|
+
'test.ts': 'export default class Test {}',
|
|
311
|
+
'test.html': '<template><div>Test</div></template>',
|
|
312
|
+
'test.css': 'p { text-align: center; }',
|
|
313
|
+
},
|
|
314
|
+
};
|
|
315
|
+
const res = (0, __1.generateKomaciModule)(input);
|
|
316
|
+
expect(res).toContain('ErrorFunction');
|
|
317
|
+
expect(res).toContain('[komaci esm-generator] multiple component script files with the same name found in bundle: test');
|
|
318
|
+
});
|
|
319
|
+
it('can handle multiple script files with the same name in different directories', () => {
|
|
320
|
+
const bundleSrcFileMap = {
|
|
321
|
+
'test.js': {},
|
|
322
|
+
'subdir/test.js': {},
|
|
323
|
+
'test.html': {},
|
|
324
|
+
};
|
|
325
|
+
const input = {
|
|
326
|
+
moduleInfo: {
|
|
327
|
+
name: 'test',
|
|
328
|
+
namespace: 'c',
|
|
329
|
+
type: 'bundle',
|
|
330
|
+
files: bundleSrcFileMap,
|
|
331
|
+
},
|
|
332
|
+
srcFileMap: {
|
|
333
|
+
'test.js': 'export default class Test {}',
|
|
334
|
+
'subdir/test.js': 'export default class Test {}',
|
|
335
|
+
'test.html': '<template><div>Test</div></template>',
|
|
336
|
+
'test.css': 'p { text-align: center; }',
|
|
337
|
+
},
|
|
338
|
+
};
|
|
339
|
+
const res = (0, __1.generateKomaciModule)(input);
|
|
340
|
+
expect(res).not.toContain('ErrorFunction');
|
|
341
|
+
expect(res).toContain('registerAdgFunction');
|
|
342
|
+
});
|
|
343
|
+
it('can handle multiple script files with different names in same directory', () => {
|
|
344
|
+
const testJsSource = `export default class Test extends LightningElement {
|
|
345
|
+
get testProp() {
|
|
346
|
+
return 'test';
|
|
347
|
+
}
|
|
348
|
+
}`;
|
|
349
|
+
const fooJsSource = `export default class Foo {
|
|
350
|
+
get fooProp() {
|
|
351
|
+
return 'foo';
|
|
352
|
+
}
|
|
353
|
+
}`;
|
|
354
|
+
const bundleConfig = {
|
|
355
|
+
namespace: 'c',
|
|
356
|
+
name: 'test',
|
|
357
|
+
type: 'internal',
|
|
358
|
+
files: [
|
|
359
|
+
{ fileName: 'test.js', source: testJsSource },
|
|
360
|
+
{ fileName: 'foo.js', source: fooJsSource },
|
|
361
|
+
{ fileName: 'test.html', source: '<template><div>Test</div></template>' },
|
|
362
|
+
{ fileName: 'test.css', source: 'p { text-align: center; }' },
|
|
363
|
+
],
|
|
364
|
+
enableKomaci: true,
|
|
365
|
+
namespaceMapping: {},
|
|
366
|
+
npmModuleMapping: {},
|
|
367
|
+
};
|
|
368
|
+
const metadata = (0, metadata_1.collectBundleMetadata)(bundleConfig);
|
|
369
|
+
const inputFiles = Object.fromEntries(metadata.files
|
|
370
|
+
.map(({ fileName, komaciDoc }) => [fileName, komaciDoc])
|
|
371
|
+
.filter(([, komaciDoc]) => !!komaciDoc));
|
|
372
|
+
const input = {
|
|
373
|
+
moduleInfo: {
|
|
374
|
+
name: 'test',
|
|
375
|
+
namespace: 'c',
|
|
376
|
+
type: 'bundle',
|
|
377
|
+
files: inputFiles,
|
|
378
|
+
},
|
|
379
|
+
srcFileMap: {
|
|
380
|
+
'test.js': testJsSource,
|
|
381
|
+
'foo.js': fooJsSource,
|
|
382
|
+
'test.html': '<template><div>Test</div></template>',
|
|
383
|
+
'test.css': 'p { text-align: center; }',
|
|
384
|
+
},
|
|
385
|
+
};
|
|
386
|
+
const res = (0, __1.generateKomaciModule)(input);
|
|
387
|
+
expect(res).not.toContain('ErrorFunction');
|
|
388
|
+
expect(res).toContain('registerAdgFunction');
|
|
389
|
+
expect(res).toContain('testProp');
|
|
390
|
+
expect(res).not.toContain('fooProp');
|
|
391
|
+
});
|
|
392
|
+
it('can process typescript files in the lightning namespace', () => {
|
|
393
|
+
const testTsSource = `import { LightningElement } from 'lwc';
|
|
394
|
+
|
|
395
|
+
export default class TestComponent extends LightningElement {
|
|
396
|
+
private count: number = 0;
|
|
397
|
+
|
|
398
|
+
get doubleCount(): number {
|
|
399
|
+
return this.count * 2;
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
increment(): void {
|
|
403
|
+
this.count++;
|
|
404
|
+
}
|
|
405
|
+
}`;
|
|
406
|
+
const bundleConfig = {
|
|
407
|
+
namespace: 'lightning',
|
|
408
|
+
name: 'testComponent',
|
|
409
|
+
type: 'internal',
|
|
410
|
+
files: [
|
|
411
|
+
{ fileName: 'testComponent.ts', source: testTsSource },
|
|
412
|
+
{
|
|
413
|
+
fileName: 'testComponent.html',
|
|
414
|
+
source: '<template><div>Test</div></template>',
|
|
415
|
+
},
|
|
416
|
+
],
|
|
417
|
+
enableKomaci: true,
|
|
418
|
+
namespaceMapping: {},
|
|
419
|
+
npmModuleMapping: {},
|
|
420
|
+
};
|
|
421
|
+
const metadata = (0, metadata_1.collectBundleMetadata)(bundleConfig);
|
|
422
|
+
const inputFiles = Object.fromEntries(metadata.files
|
|
423
|
+
.map(({ fileName, komaciDoc }) => [fileName, komaciDoc])
|
|
424
|
+
.filter(([, komaciDoc]) => !!komaciDoc));
|
|
425
|
+
const input = {
|
|
426
|
+
moduleInfo: {
|
|
427
|
+
name: 'testComponent',
|
|
428
|
+
namespace: 'lightning',
|
|
429
|
+
type: 'bundle',
|
|
430
|
+
files: inputFiles,
|
|
431
|
+
},
|
|
432
|
+
srcFileMap: {
|
|
433
|
+
'testComponent.ts': testTsSource,
|
|
434
|
+
'testComponent.html': '<template><div>Test</div></template>',
|
|
435
|
+
},
|
|
436
|
+
};
|
|
437
|
+
const res = (0, __1.generateKomaciModule)(input);
|
|
438
|
+
expect(res).not.toContain('ErrorFunction');
|
|
439
|
+
expect(res).toContain('registerAdgFunction');
|
|
440
|
+
expect(res).toContain('doubleCount');
|
|
441
|
+
});
|
|
442
|
+
it('throws error for typescript files in non-lightning namespace', () => {
|
|
443
|
+
const testTsSource = `import { LightningElement } from 'lwc';
|
|
444
|
+
|
|
445
|
+
export default class TestComponent extends LightningElement {
|
|
446
|
+
private count: number = 0;
|
|
447
|
+
|
|
448
|
+
get doubleCount(): number {
|
|
449
|
+
return this.count * 2;
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
increment(): void {
|
|
453
|
+
this.count++;
|
|
454
|
+
}
|
|
455
|
+
}`;
|
|
456
|
+
const bundleConfig = {
|
|
457
|
+
namespace: 'c',
|
|
458
|
+
name: 'testComponent',
|
|
459
|
+
type: 'internal',
|
|
460
|
+
files: [
|
|
461
|
+
{ fileName: 'testComponent.ts', source: testTsSource },
|
|
462
|
+
{
|
|
463
|
+
fileName: 'testComponent.html',
|
|
464
|
+
source: '<template><div>Test</div></template>',
|
|
465
|
+
},
|
|
466
|
+
],
|
|
467
|
+
enableKomaci: true,
|
|
468
|
+
namespaceMapping: {},
|
|
469
|
+
npmModuleMapping: {},
|
|
470
|
+
};
|
|
471
|
+
const metadata = (0, metadata_1.collectBundleMetadata)(bundleConfig);
|
|
472
|
+
const inputFiles = Object.fromEntries(metadata.files
|
|
473
|
+
.map(({ fileName, komaciDoc }) => [fileName, komaciDoc])
|
|
474
|
+
.filter(([, komaciDoc]) => !!komaciDoc));
|
|
475
|
+
const input = {
|
|
476
|
+
moduleInfo: {
|
|
477
|
+
name: 'testComponent',
|
|
478
|
+
namespace: 'c',
|
|
479
|
+
type: 'bundle',
|
|
480
|
+
files: inputFiles,
|
|
481
|
+
},
|
|
482
|
+
srcFileMap: {
|
|
483
|
+
'testComponent.ts': testTsSource,
|
|
484
|
+
'testComponent.html': '<template><div>Test</div></template>',
|
|
485
|
+
},
|
|
486
|
+
};
|
|
487
|
+
const res = (0, __1.generateKomaciModule)(input);
|
|
488
|
+
// TypeScript files in non-lightning namespaces should now throw an error
|
|
489
|
+
expect(res).toContain('ErrorFunction');
|
|
490
|
+
expect(res).toContain('unsupported file extension: ts');
|
|
491
|
+
});
|
|
492
|
+
});
|
|
293
493
|
//# sourceMappingURL=index.spec.js.map
|
|
@@ -5,11 +5,12 @@ import { ModuleContext, ModuleMetadata, HoistedFunctionMetadata } from '@komaci/
|
|
|
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
|
|
8
|
+
* @param allowTypeScript Optional parameter to control whether TypeScript files should be considered. Defaults to true for backward compatibility.
|
|
8
9
|
* @returns Returns raw source code as string for the js of a component if it exists in the srcFileMap
|
|
9
10
|
* Returns undefined if no JS source file (whose filename also matches the LWC module name) was included in the
|
|
10
11
|
* GeneratorState.GeneratorInput by lwc-platform, other calling code.
|
|
11
12
|
*/
|
|
12
|
-
export declare function getComponentSrcJs(generatorInput: GeneratorInput): string | undefined;
|
|
13
|
+
export declare function getComponentSrcJs(generatorInput: GeneratorInput, allowTypeScript?: boolean): string | undefined;
|
|
13
14
|
/**
|
|
14
15
|
* AST is traversed to see if they contain getter functions that are not valid. For each getter that is valid, we will
|
|
15
16
|
* update contextual information about the class and pass back info about the valid getters.
|
|
@@ -7,15 +7,17 @@ const common_shared_1 = require("@komaci/common-shared");
|
|
|
7
7
|
/**
|
|
8
8
|
* Retrieve the file path for the js of a component
|
|
9
9
|
* @param generatorState GeneratorState containg the GeneratorInput, which in turn contains the JS raw source file
|
|
10
|
+
* @param allowTypeScript Optional parameter to control whether TypeScript files should be considered. Defaults to true for backward compatibility.
|
|
10
11
|
* @returns Returns raw source code as string for the js of a component if it exists in the srcFileMap
|
|
11
12
|
* Returns undefined if no JS source file (whose filename also matches the LWC module name) was included in the
|
|
12
13
|
* GeneratorState.GeneratorInput by lwc-platform, other calling code.
|
|
13
14
|
*/
|
|
14
|
-
function getComponentSrcJs(generatorInput) {
|
|
15
|
+
function getComponentSrcJs(generatorInput, allowTypeScript = true) {
|
|
15
16
|
let sourceCode;
|
|
16
17
|
const moduleName = generatorInput.moduleInfo.name;
|
|
17
18
|
if (generatorInput.srcFileMap) {
|
|
18
|
-
const filename = Object.keys(generatorInput.srcFileMap).find((filename) => (filename.endsWith('.js') ||
|
|
19
|
+
const filename = Object.keys(generatorInput.srcFileMap).find((filename) => (filename.endsWith('.js') ||
|
|
20
|
+
(filename.endsWith('.ts') && allowTypeScript)) &&
|
|
19
21
|
filename.startsWith(moduleName));
|
|
20
22
|
if (filename) {
|
|
21
23
|
sourceCode = generatorInput.srcFileMap[filename];
|
package/build/index.js
CHANGED
|
@@ -86,6 +86,15 @@ function normalizeSrcFileKeys(input) {
|
|
|
86
86
|
}
|
|
87
87
|
}
|
|
88
88
|
exports.normalizeSrcFileKeys = normalizeSrcFileKeys;
|
|
89
|
+
/**
|
|
90
|
+
* Determines if TypeScript files should be processed for the given namespace.
|
|
91
|
+
* TypeScript files are only processed for lightning and lightning/interop namespaces.
|
|
92
|
+
* @param namespace the module namespace
|
|
93
|
+
* @returns true if TypeScript files should be processed
|
|
94
|
+
*/
|
|
95
|
+
function shouldProcessTypeScriptForNamespace(namespace) {
|
|
96
|
+
return namespace === 'lightning' || namespace.startsWith('lightning/interop');
|
|
97
|
+
}
|
|
89
98
|
/**
|
|
90
99
|
* Helper function to process and build the resolvable module based off the generator input and inital generator state.
|
|
91
100
|
* @param input the Generator input
|
|
@@ -97,14 +106,16 @@ function processGeneratorInputAndState(input) {
|
|
|
97
106
|
// Determine file type based on extension in file name.
|
|
98
107
|
const segments = (0, common_shared_1.getFilepathSegments)(input.moduleInfo.fileName);
|
|
99
108
|
const fileExt = segments[segments.length - 1];
|
|
109
|
+
const namespace = input.moduleInfo.namespace;
|
|
110
|
+
const isTypeScriptAllowed = shouldProcessTypeScriptForNamespace(namespace);
|
|
100
111
|
let sourceFile;
|
|
101
|
-
const source = (0, componentAstProcessing_1.getComponentSrcJs)(input);
|
|
112
|
+
const source = (0, componentAstProcessing_1.getComponentSrcJs)(input, isTypeScriptAllowed);
|
|
102
113
|
if (fileExt === 'html') {
|
|
103
114
|
const templateMap = {};
|
|
104
115
|
templateMap[input.moduleInfo.name] = input.moduleInfo.komaciDoc;
|
|
105
116
|
sourceFile = (0, genericAstGeneration_1.generateResolvableModule)(input, undefined, templateMap, source);
|
|
106
117
|
}
|
|
107
|
-
else if (fileExt === 'js' || fileExt === 'ts') {
|
|
118
|
+
else if (fileExt === 'js' || (fileExt === 'ts' && isTypeScriptAllowed)) {
|
|
108
119
|
sourceFile = (0, genericAstGeneration_1.generateResolvableModule)(input, input.moduleInfo.komaciDoc, undefined, source);
|
|
109
120
|
}
|
|
110
121
|
else {
|
|
@@ -116,38 +127,38 @@ function processGeneratorInputAndState(input) {
|
|
|
116
127
|
else if (input.moduleInfo.type === 'bundle') {
|
|
117
128
|
// code to process a bundle
|
|
118
129
|
let filename = '', fileExt;
|
|
119
|
-
const
|
|
120
|
-
const
|
|
130
|
+
const namespace = input.moduleInfo.namespace;
|
|
131
|
+
const isTypeScriptAllowed = shouldProcessTypeScriptForNamespace(namespace);
|
|
132
|
+
const scriptDocs = {}; // {'test.js' : { filename: 'test', komaciDoc: KomaciDoc1 }}
|
|
133
|
+
const htmlDocs = {};
|
|
121
134
|
let sourceFile;
|
|
122
|
-
for (const [
|
|
135
|
+
for (const [filePath, komaciDoc] of Object.entries(input.moduleInfo.files)) {
|
|
123
136
|
// Determine file type based on extension in file name.
|
|
124
|
-
const segments = (0, common_shared_1.getFilepathSegments)(
|
|
137
|
+
const segments = (0, common_shared_1.getFilepathSegments)(filePath);
|
|
125
138
|
filename = segments[0]; // the filename, up to but not including, the file separator character
|
|
126
139
|
fileExt = segments[segments.length - 1]; // filename extension, not including the separator
|
|
127
|
-
let filesObj = {};
|
|
128
|
-
// check for existing map entry in order to append to it
|
|
129
|
-
// to support multiple files per filetype in the future
|
|
130
|
-
if (filesMap[fileExt]) {
|
|
131
|
-
filesObj = filesMap[fileExt];
|
|
132
|
-
}
|
|
133
|
-
filesObj[filename] = komaciDoc;
|
|
134
140
|
if (fileExt == 'html') {
|
|
135
|
-
|
|
141
|
+
htmlDocs[filename] = komaciDoc;
|
|
136
142
|
}
|
|
137
|
-
else if (fileExt === 'js' || fileExt === 'ts') {
|
|
138
|
-
|
|
143
|
+
else if (fileExt === 'js' || (fileExt === 'ts' && isTypeScriptAllowed)) {
|
|
144
|
+
scriptDocs[filePath] = { filename, komaciDoc };
|
|
139
145
|
}
|
|
140
146
|
else {
|
|
141
147
|
throw new Error(types_1.ERROR_PREFIX + 'unsupported file extension: ' + fileExt);
|
|
142
148
|
}
|
|
143
149
|
}
|
|
144
|
-
const source = (0, componentAstProcessing_1.getComponentSrcJs)(input);
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
150
|
+
const source = (0, componentAstProcessing_1.getComponentSrcJs)(input, isTypeScriptAllowed);
|
|
151
|
+
// Find the main component script file(s)
|
|
152
|
+
const mainComponentScriptFiles = Object.values(scriptDocs).filter(({ filename }) => filename === input.moduleInfo.name);
|
|
153
|
+
// For now we only support one main component script file.
|
|
154
|
+
if (mainComponentScriptFiles.length > 1) {
|
|
155
|
+
throw new Error(types_1.ERROR_PREFIX +
|
|
156
|
+
'multiple component script files with the same name found in bundle: ' +
|
|
157
|
+
input.moduleInfo.name);
|
|
158
|
+
}
|
|
159
|
+
const uniqueMainComponentScriptDoc = mainComponentScriptFiles[0]?.komaciDoc ?? {};
|
|
149
160
|
// eslint-disable-next-line prefer-const
|
|
150
|
-
sourceFile = (0, genericAstGeneration_1.generateResolvableModule)(input,
|
|
161
|
+
sourceFile = (0, genericAstGeneration_1.generateResolvableModule)(input, uniqueMainComponentScriptDoc, htmlDocs, source);
|
|
151
162
|
// Generate source from constructed AST.
|
|
152
163
|
const babelOutput = (0, generator_1.default)(sourceFile);
|
|
153
164
|
return babelOutput.code;
|