@komaci/esm-generator 248.1.2 → 248.1.4

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.
@@ -10,7 +10,8 @@ const sfdc_lwc_compiler_1 = require("@lwc-platform/sfdc-lwc-compiler");
10
10
  const compilerConfigs_1 = require("./compilerConfigs");
11
11
  const EXPECTED_SRC_FILENAME = 'expected.src';
12
12
  describe('fixtures', () => {
13
- const fixtures = (0, glob_1.globSync)(path_1.default.resolve(__dirname, '**/expected.src'));
13
+ //Adding filter on the resolvable modules we try to compile until the compiler has been updated to handle imported gql queries. Will be removed in W-14269523
14
+ const fixtures = (0, glob_1.globSync)(path_1.default.resolve(__dirname, '**/expected.src')).filter((e) => e != `${__dirname}/fixtures-gql/multipleGqlQueries/expected.src`);
14
15
  for (const caseEntry of fixtures) {
15
16
  const caseFolder = path_1.default.dirname(caseEntry);
16
17
  const caseName = path_1.default.relative(__dirname, caseFolder);
@@ -20,17 +20,5 @@ export declare const compilerConfigs: ({
20
20
  };
21
21
  compat?: undefined;
22
22
  };
23
- } | {
24
- outputConfig: {
25
- minify: boolean;
26
- sourcemap: boolean;
27
- env: {
28
- NODE_ENV: string;
29
- };
30
- lockerConfig: {
31
- sourcemap: string;
32
- };
33
- compat?: undefined;
34
- };
35
23
  })[];
36
24
  //# sourceMappingURL=compilerConfigs.d.ts.map
@@ -109,7 +109,7 @@ exports.compilerConfigs = [
109
109
  env: {
110
110
  NODE_ENV: 'production',
111
111
  },
112
- lockerConfig: { sourcemap: 'hidden' },
112
+ lockerConfig: { sourcemap: false },
113
113
  },
114
114
  },
115
115
  {
@@ -119,7 +119,7 @@ exports.compilerConfigs = [
119
119
  env: {
120
120
  NODE_ENV: 'development',
121
121
  },
122
- lockerConfig: { sourcemap: 'hidden' },
122
+ lockerConfig: { sourcemap: false },
123
123
  },
124
124
  },
125
125
  ];
@@ -0,0 +1,15 @@
1
+ export default class KomaciAction extends LightningElement {
2
+ recordId: any;
3
+ temp: string;
4
+ accountQuery: any;
5
+ contactQuery: any;
6
+ get gqlFromGetter(): any;
7
+ get badGqlFromGetter(): any;
8
+ get variables(): {
9
+ id: any;
10
+ };
11
+ graphqlRecord: any;
12
+ graphqlContactRecord: any;
13
+ }
14
+ import { LightningElement } from "lwc";
15
+ //# sourceMappingURL=component.d.ts.map
@@ -0,0 +1,104 @@
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
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ const lwc_1 = require("lwc");
10
+ //an import to gql will still get hoisted since contactQuery will not be getting swapped out.
11
+ const uiGraphQLApi_1 = require("lightning/uiGraphQLApi");
12
+ class KomaciAction extends lwc_1.LightningElement {
13
+ constructor() {
14
+ super(...arguments);
15
+ this.temp = 'temp';
16
+ //Valid Query, all on one line.
17
+ // prettier-ignore
18
+ this.accountQuery = (0, uiGraphQLApi_1.gql) `query accountById($id: ID) {uiapi {query {Account(where: { Id: { eq: $id } }) @category(name: "recordQuery") {edges {node { Name @category(name: "StringValue") {valuedisplayValue}}}}}}}`;
19
+ //cannot apply metaschema directives, has expressions
20
+ this.contactQuery = (0, uiGraphQLApi_1.gql) `
21
+ query accountById($id: ID) {
22
+ uiapi {
23
+ query {
24
+ Contact(where: { Id: { eq: $id } }) @category(name: ${this.temp}) {
25
+ edges {
26
+ node {
27
+ Name @category(name: "StringValue") {
28
+ value
29
+ displayValue
30
+ }
31
+ }
32
+ }
33
+ }
34
+ }
35
+ }
36
+ }
37
+ `;
38
+ }
39
+ //Getter with valid gql query, getter needs to return imported gql query.
40
+ get gqlFromGetter() {
41
+ return (0, uiGraphQLApi_1.gql) `
42
+ query accountById($id: ID) {
43
+ uiapi {
44
+ query {
45
+ Contact(where: { Id: { eq: $id } })
46
+ @category(name: "recordQuery") {
47
+ edges {
48
+ node {
49
+ Name @category(name: "StringValue") {
50
+ value
51
+ displayValue
52
+ }
53
+ }
54
+ }
55
+ }
56
+ }
57
+ }
58
+ }
59
+ `;
60
+ }
61
+ //cannot apply metaschema directives, has expressions
62
+ get badGqlFromGetter() {
63
+ return (0, uiGraphQLApi_1.gql) `
64
+ query accountById($id: ID) {
65
+ uiapi {
66
+ query {
67
+ Contact(where: { Id: { eq: $id } }) @category(name: "recordQuery") {
68
+ edges {
69
+ node {
70
+ Name @category(name: ${this.temp}) {
71
+ value
72
+ displayValue
73
+ }
74
+ }
75
+ }
76
+ }
77
+ }
78
+ }
79
+ }
80
+ `;
81
+ }
82
+ get variables() {
83
+ return {
84
+ id: this.recordId,
85
+ };
86
+ }
87
+ }
88
+ __decorate([
89
+ lwc_1.api
90
+ ], KomaciAction.prototype, "recordId", void 0);
91
+ __decorate([
92
+ (0, lwc_1.wire)(uiGraphQLApi_1.unstable_graphql, {
93
+ query: '$accountQuery',
94
+ variables: '$variables',
95
+ })
96
+ ], KomaciAction.prototype, "graphqlRecord", void 0);
97
+ __decorate([
98
+ (0, lwc_1.wire)(uiGraphQLApi_1.unstable_graphql, {
99
+ query: '$contactQuery',
100
+ variables: '$variables',
101
+ })
102
+ ], KomaciAction.prototype, "graphqlContactRecord", void 0);
103
+ exports.default = KomaciAction;
104
+ //# sourceMappingURL=component.js.map
@@ -0,0 +1,3 @@
1
+ export declare const mockGqlQueries = "import { api, wire, LightningElement } from 'lwc';\nimport { gql, unstable_graphql } from 'lightning/uiGraphQLApi'; \n \nexport default class KomaciAction extends LightningElement {\n @api recordId;\n\n temp = \"temp\"; \n\n accountQuery = gql`\n query accountById($id: ID) {\n uiapi {\n query {\n Account(where: { Id: { eq: $id } }) @category(name: \"recordQuery\") {\n edges {\n node {\n Name @category(name: \"StringValue\") {\n value\n displayValue\n }\n }\n }\n }\n }\n }\n }\n `;\n\n contactQuery = gql`\n query accountById($id: ID) {\n uiapi {\n query {\n Contact(where: { Id: { eq: $id } }) @category(name: ${this.temp}) {\n edges {\n node {\n Name @category(name: \"StringValue\") {\n value\n displayValue\n }\n }\n }\n }\n }\n }\n }\n`;\n\nget gqlFromGetter(){\n return gql`\n query accountById($id: ID) {\n uiapi {\n query {\n Contact(where: { Id: { eq: $id } }) @category(name: \"recordQuery\") {\n edges {\n node {\n Name @category(name: \"StringValue\") {\n value\n displayValue\n }\n }\n }\n }\n }\n }\n }\n`;\n}\n\n get variables() {\n return {\n id: this.recordId,\n };\n }\n\n @wire(unstable_graphql, {\n query: '$accountQuery',\n variables: '$variables',\n })\n graphqlRecord;\n\n @wire(unstable_graphql, {\n query: '$contactQuery',\n variables: '$variables',\n })\n graphqlContactRecord;\n} \n";
2
+ export declare const expectedGetterWithGql = "\nfunction g0(props) {\nreturn gql0;\n}\n";
3
+ //# sourceMappingURL=gqlMockSource.d.ts.map
@@ -0,0 +1,95 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.expectedGetterWithGql = exports.mockGqlQueries = void 0;
4
+ exports.mockGqlQueries = `import { api, wire, LightningElement } from 'lwc';
5
+ import { gql, unstable_graphql } from 'lightning/uiGraphQLApi';
6
+
7
+ export default class KomaciAction extends LightningElement {
8
+ @api recordId;
9
+
10
+ temp = "temp";
11
+
12
+ accountQuery = gql\`
13
+ query accountById($id: ID) {
14
+ uiapi {
15
+ query {
16
+ Account(where: { Id: { eq: $id } }) @category(name: "recordQuery") {
17
+ edges {
18
+ node {
19
+ Name @category(name: "StringValue") {
20
+ value
21
+ displayValue
22
+ }
23
+ }
24
+ }
25
+ }
26
+ }
27
+ }
28
+ }
29
+ \`;
30
+
31
+ contactQuery = gql\`
32
+ query accountById($id: ID) {
33
+ uiapi {
34
+ query {
35
+ Contact(where: { Id: { eq: $id } }) @category(name: \${this.temp}) {
36
+ edges {
37
+ node {
38
+ Name @category(name: "StringValue") {
39
+ value
40
+ displayValue
41
+ }
42
+ }
43
+ }
44
+ }
45
+ }
46
+ }
47
+ }
48
+ \`;
49
+
50
+ get gqlFromGetter(){
51
+ return gql\`
52
+ query accountById($id: ID) {
53
+ uiapi {
54
+ query {
55
+ Contact(where: { Id: { eq: $id } }) @category(name: "recordQuery") {
56
+ edges {
57
+ node {
58
+ Name @category(name: "StringValue") {
59
+ value
60
+ displayValue
61
+ }
62
+ }
63
+ }
64
+ }
65
+ }
66
+ }
67
+ }
68
+ \`;
69
+ }
70
+
71
+ get variables() {
72
+ return {
73
+ id: this.recordId,
74
+ };
75
+ }
76
+
77
+ @wire(unstable_graphql, {
78
+ query: '$accountQuery',
79
+ variables: '$variables',
80
+ })
81
+ graphqlRecord;
82
+
83
+ @wire(unstable_graphql, {
84
+ query: '$contactQuery',
85
+ variables: '$variables',
86
+ })
87
+ graphqlContactRecord;
88
+ }
89
+ `;
90
+ exports.expectedGetterWithGql = `
91
+ function g0(props) {
92
+ return gql0;
93
+ }
94
+ `;
95
+ //# sourceMappingURL=gqlMockSource.js.map
@@ -36,6 +36,7 @@ const generator_1 = __importDefault(require("@babel/generator"));
36
36
  const badImportRef_1 = require("./fixtures-source-code/badImportRef");
37
37
  const t = __importStar(require("@babel/types"));
38
38
  const generalMockSourceCode_1 = require("./fixtures-source-code/generalMockSourceCode");
39
+ const gqlMockSource_1 = require("./fixtures-source-code/gqlMockSource");
39
40
  describe('hoistLocalFunction', () => {
40
41
  const baseFilesPath = (0, path_1.join)(__dirname, 'general-komaci-docs/assorted-template-strings');
41
42
  const src = (0, fs_1.readFileSync)((0, path_1.join)(baseFilesPath, 'source.js'), {
@@ -76,8 +77,10 @@ describe('hoistLocalFunction', () => {
76
77
  usedInPriming: true,
77
78
  staticallyAnalyzable: false,
78
79
  });
79
- const hoistedFirstFunc = (0, functionAstGeneration_1.hoistLocalFunction)(firstTemplateStringFunc, imports);
80
- const hoistedSecondFunc = (0, functionAstGeneration_1.hoistLocalFunction)(secondTemplateStringFunc, imports);
80
+ const moduleMetadata = (0, common_shared_1.initModuleMetadataObject)();
81
+ moduleMetadata.importsByName = imports;
82
+ const hoistedFirstFunc = (0, functionAstGeneration_1.hoistLocalFunction)(firstTemplateStringFunc, moduleMetadata);
83
+ const hoistedSecondFunc = (0, functionAstGeneration_1.hoistLocalFunction)(secondTemplateStringFunc, moduleMetadata);
81
84
  it('can compose a template string for a public api prop', () => {
82
85
  expect(hoistedFirstFunc).not.toBeUndefined();
83
86
  // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
@@ -164,7 +167,7 @@ describe('hoistlocalfunction for render function', () => {
164
167
  requiredProperties: ['templateOne'],
165
168
  generatedName: `hoistedRenderFunction`,
166
169
  };
167
- const hoistedRenderFunction = (0, functionAstGeneration_1.hoistLocalFunction)(renderFunctionMetadata, moduleMetadata.importsByName);
170
+ const hoistedRenderFunction = (0, functionAstGeneration_1.hoistLocalFunction)(renderFunctionMetadata, moduleMetadata);
168
171
  expect(hoistedRenderFunction).not.toBeUndefined();
169
172
  const hoistedBodyStatements = hoistedRenderFunction?.body.body;
170
173
  expect(hoistedBodyStatements).not.toBeUndefined();
@@ -190,7 +193,7 @@ describe('hoistlocalfunction for render function', () => {
190
193
  requiredProperties: ['templateOne'],
191
194
  generatedName: `hoistedRenderFunction`,
192
195
  };
193
- const hoistedRenderFunction = (0, functionAstGeneration_1.hoistLocalFunction)(renderFunctionMetadata, moduleMetadata.importsByName);
196
+ const hoistedRenderFunction = (0, functionAstGeneration_1.hoistLocalFunction)(renderFunctionMetadata, moduleMetadata);
194
197
  expect(hoistedRenderFunction).not.toBeUndefined();
195
198
  const hoistedBodyStatements = hoistedRenderFunction?.body.body;
196
199
  expect(hoistedBodyStatements).not.toBeUndefined();
@@ -214,7 +217,7 @@ describe('hoistlocalfunction for render function', () => {
214
217
  requiredProperties: ['templateOne'],
215
218
  generatedName: `hoistedRenderFunction`,
216
219
  };
217
- const hoistedRenderFunction = (0, functionAstGeneration_1.hoistLocalFunction)(renderFunctionMetadata, moduleMetadata.importsByName);
220
+ const hoistedRenderFunction = (0, functionAstGeneration_1.hoistLocalFunction)(renderFunctionMetadata, moduleMetadata);
218
221
  expect(hoistedRenderFunction).not.toBeUndefined();
219
222
  const hoistedBodyStatements = hoistedRenderFunction?.body.body;
220
223
  expect(hoistedBodyStatements).not.toBeUndefined();
@@ -261,14 +264,14 @@ describe('sanitizeFunction', () => {
261
264
  komaciDocImportRef: '1/names/0',
262
265
  });
263
266
  it('should be able to clean up and hoist a function with valid import references', () => {
264
- (0, functionAstGeneration_1.sanitizeFunction)(getters[0], imports);
267
+ (0, functionAstGeneration_1.sanitizeFunction)(getters[0], imports, new Map());
265
268
  const hoisted = (0, types_1.functionDeclaration)((0, types_1.identifier)('g0'), [(0, types_1.identifier)('props')], // make 'props' an input parameter to the hoisted getter
266
269
  getters[0].node.body);
267
270
  const generatedFunction = (0, generator_1.default)((0, types_1.file)((0, types_1.program)([hoisted])));
268
271
  expect(generatedFunction.code).toBe(badImportRef_1.expectedGoodHoist);
269
272
  });
270
273
  it('should throw an error if we try to reference a bad input', () => {
271
- expect(() => (0, functionAstGeneration_1.sanitizeFunction)(getters[1], imports)).toThrowError(new Error(`${common_shared_1.ERROR_PREFIX}: 'bad' does not map to valid import`));
274
+ expect(() => (0, functionAstGeneration_1.sanitizeFunction)(getters[1], imports, new Map())).toThrowError(new Error(`${common_shared_1.ERROR_PREFIX}: 'bad' does not map to valid import`));
272
275
  });
273
276
  });
274
277
  describe('adgToExpression', () => {
@@ -582,4 +585,83 @@ describe('composeSelfServiceAssignmentExpression', () => {
582
585
  expect(right.value).toBeTruthy();
583
586
  });
584
587
  });
588
+ describe('sanitizeFunction gql usecases', () => {
589
+ const ast = (0, common_shared_1.generateAstFromSrcCode)(gqlMockSource_1.mockGqlQueries);
590
+ const { getters, templateStrings } = (0, common_shared_1.getPropertyMetadataFromAst)(ast);
591
+ const imports = new Map();
592
+ const gqlMetadata = new Map();
593
+ //Gql query from getter
594
+ const gqlMetadata0 = {
595
+ hash: '123456',
596
+ hasExpressions: false,
597
+ location: {
598
+ startLine: 0,
599
+ endLine: 0,
600
+ startColumn: 0,
601
+ endColumn: 0,
602
+ start: 1345,
603
+ end: 1845,
604
+ },
605
+ isHoisted: false,
606
+ valid: true,
607
+ generatedImportAlias: 'gql0',
608
+ importPath: 'temp/path',
609
+ };
610
+ gqlMetadata.set('loc_1354_1845', gqlMetadata0);
611
+ //Invalid gql query
612
+ const gqlMetadata1 = {
613
+ hash: '123456',
614
+ hasExpressions: true,
615
+ location: {
616
+ startLine: 0,
617
+ endLine: 0,
618
+ startColumn: 0,
619
+ endColumn: 0,
620
+ start: 826,
621
+ end: 1316,
622
+ },
623
+ isHoisted: false,
624
+ valid: false,
625
+ generatedImportAlias: 'gql1',
626
+ importPath: 'temp/path',
627
+ };
628
+ gqlMetadata.set('loc_826_1316', gqlMetadata1);
629
+ //valid gql query
630
+ const gqlMetadata2 = {
631
+ hash: '123456',
632
+ hasExpressions: false,
633
+ location: {
634
+ startLine: 0,
635
+ endLine: 0,
636
+ startColumn: 0,
637
+ endColumn: 0,
638
+ start: 242,
639
+ end: 801,
640
+ },
641
+ isHoisted: false,
642
+ valid: true,
643
+ generatedImportAlias: 'gql2',
644
+ importPath: 'temp/path',
645
+ };
646
+ gqlMetadata.set('loc_242_801', gqlMetadata2);
647
+ it('should replace getter return with proper import id', () => {
648
+ (0, functionAstGeneration_1.sanitizeFunction)(getters[0], imports, gqlMetadata);
649
+ const hoisted = (0, types_1.functionDeclaration)((0, types_1.identifier)('g0'), [(0, types_1.identifier)('props')], // make 'props' an input parameter to the hoisted getter
650
+ getters[0].node.body);
651
+ const generatedFunction = (0, generator_1.default)((0, types_1.file)((0, types_1.program)([hoisted])));
652
+ expect(generatedFunction.code.trim).toBe(gqlMockSource_1.expectedGetterWithGql.trim);
653
+ });
654
+ it('swaps out the gql query with the proper generated import alias', () => {
655
+ (0, functionAstGeneration_1.sanitizeFunction)(templateStrings[0], imports, gqlMetadata);
656
+ const tmplString = templateStrings[0];
657
+ expect(tmplString.node.value?.type).toBe('Identifier');
658
+ const id = tmplString.node.value.name;
659
+ expect(id).toBe('gql2');
660
+ });
661
+ it('does not swap out gql query if has expression or is invalid', () => {
662
+ (0, functionAstGeneration_1.sanitizeFunction)(templateStrings[1], imports, gqlMetadata);
663
+ const tmplString = templateStrings[1];
664
+ expect(tmplString.node.value?.type).toBe('TaggedTemplateExpression');
665
+ });
666
+ });
585
667
  //# sourceMappingURL=functionAstGeneration.spec.js.map
@@ -966,4 +966,48 @@ describe('valueReferenceToExpression', () => {
966
966
  expect(obj.properties[1].value.value).toBe('reference');
967
967
  });
968
968
  });
969
+ describe('generateGqlImportStatement', () => {
970
+ it('generates the import statement properly', () => {
971
+ const gqlMetadataMap = new Map();
972
+ const gqlMetadata = {
973
+ hash: '123456',
974
+ hasExpressions: false,
975
+ location: {
976
+ startLine: 0,
977
+ endLine: 0,
978
+ startColumn: 0,
979
+ endColumn: 0,
980
+ start: 242,
981
+ end: 801,
982
+ },
983
+ isHoisted: false,
984
+ valid: true,
985
+ generatedImportAlias: '_123456',
986
+ importPath: '@salesforce/lds/c__component',
987
+ };
988
+ gqlMetadataMap.set('loc_242_801', gqlMetadata);
989
+ const gqlMetadata2 = {
990
+ hash: '123456789',
991
+ hasExpressions: true,
992
+ location: {
993
+ startLine: 0,
994
+ endLine: 0,
995
+ startColumn: 0,
996
+ endColumn: 0,
997
+ start: 826,
998
+ end: 1316,
999
+ },
1000
+ isHoisted: false,
1001
+ valid: false,
1002
+ generatedImportAlias: '_123456789',
1003
+ importPath: 'temp/path',
1004
+ };
1005
+ gqlMetadataMap.set('loc_826_1316', gqlMetadata2);
1006
+ const statements = [];
1007
+ (0, genericAstGeneration_1.generateGqlImportStatements)(gqlMetadataMap, statements);
1008
+ expect(statements).toHaveLength(1);
1009
+ const code = (0, generator_1.default)(statements[0]).code;
1010
+ expect(code).toBe('import { _123456 } from "@salesforce/lds/c__component";');
1011
+ });
1012
+ });
969
1013
  //# sourceMappingURL=genericAstGeneration.spec.js.map
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=komaci-gql.fixtures.spec.d.ts.map
@@ -0,0 +1,123 @@
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 fs_1 = __importDefault(require("fs"));
7
+ const glob_1 = require("glob");
8
+ const path_1 = __importDefault(require("path"));
9
+ const index_1 = require("../index");
10
+ const fs_2 = require("fs");
11
+ const path_2 = require("path");
12
+ const metadata_1 = require("@lwc/metadata");
13
+ const FIXTURES_DIR = path_1.default.join(__dirname, 'fixtures-gql');
14
+ const EXPECTED_JS_FILENAME = 'expected.src';
15
+ // eslint-disable-next-line jest/no-disabled-tests
16
+ describe('fixtures', () => {
17
+ // find all folder paths containing a directory called component. This gives us the flexability to name the parent directory
18
+ // either lightning for external comps and c for internal comps.
19
+ const fixturePath = path_1.default.resolve(FIXTURES_DIR, '**/*/component');
20
+ const fixtures = (0, glob_1.globSync)(fixturePath);
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
+ enableLuvio: true,
42
+ }).output.modGenOutput;
43
+ let expectedModuleSrc = readFixtureFile(expectedFilePath);
44
+ if (expectedModuleSrc == '') {
45
+ // write file if doesn't exist (ie new fixture)
46
+ expectedModuleSrc = actualModuleSrc;
47
+ writeFixtureFile(expectedFilePath, expectedModuleSrc);
48
+ }
49
+ // check that the actual newly generated mod source matches expected
50
+ expect(actualModuleSrc).toEqual(expectedModuleSrc);
51
+ });
52
+ }
53
+ });
54
+ /**
55
+ * Finds all .js, .mjs, .css, and .html files within the given directory, reads their contents, and combines them into a bundle,
56
+ * and returning the array of BundleFile containing the file's fileName and source
57
+ * @param path
58
+ * @returns An array of BundleFile
59
+ */
60
+ function readBundle(path) {
61
+ path = (0, path_2.resolve)(path);
62
+ if ((0, fs_2.existsSync)(path)) {
63
+ const contents = (0, fs_2.readdirSync)(path);
64
+ const LWC_EXT = ['.js', '.mjs', '.css', '.html'];
65
+ const lwcBundleFiles = contents.filter((filename) => {
66
+ return LWC_EXT.includes((0, path_2.extname)(filename));
67
+ });
68
+ return lwcBundleFiles.map((fileName) => ({
69
+ fileName,
70
+ source: (0, fs_2.readFileSync)((0, path_2.resolve)(path, fileName), 'utf-8').toString(),
71
+ }));
72
+ }
73
+ else {
74
+ throw new Error(`path doesn't exist: ${path}`);
75
+ }
76
+ }
77
+ /**
78
+ * Takes the directory path of an LWC module bundle and an optional set of config overrides. Returns the ParsedBundle, inlcuding
79
+ * the bundle's 1) LWC Metadata and 2) Komaci / Resolvable module.
80
+ * @param path
81
+ * @param configOverrides
82
+ * @returns ParsedBundle that includes the BundleConfig & GeneratorInput inputs, and BundleMetadata and generated module output
83
+ */
84
+ function readAndParseBundle(path, configOverrides) {
85
+ const files = readBundle(path);
86
+ const name = (0, path_2.basename)(path);
87
+ const namespace = (0, path_2.basename)((0, path_2.dirname)(path));
88
+ const bundleConfig = {
89
+ namespace,
90
+ name,
91
+ type: 'internal',
92
+ namespaceMapping: {},
93
+ files,
94
+ enableKomaci: true,
95
+ ...configOverrides,
96
+ };
97
+ const metadata = (0, metadata_1.collectBundleMetadata)(bundleConfig);
98
+ // Create input to module generator.
99
+ const srcFileMap = files.reduce((map, { fileName, source }) => ({ ...map, [fileName]: source }), {});
100
+ const inputFiles = Object.fromEntries(metadata.files
101
+ .map(({ fileName, komaciDoc }) => [fileName, komaciDoc])
102
+ .filter(([, komaciDoc]) => !!komaciDoc));
103
+ //Need to come back and clean this up, will be taken care of in a futire WI
104
+ const luvioMetadata = metadata.files.filter((file) => file.fileType == 'js' &&
105
+ file.luvioMetadata != undefined &&
106
+ file.luvioMetadata.gqlTag.length > 0).map((file) => file.luvioMetadata)[0];
107
+ const generatorInput = {
108
+ moduleInfo: {
109
+ name,
110
+ namespace: bundleConfig.namespace,
111
+ type: 'bundle',
112
+ files: inputFiles,
113
+ },
114
+ srcFileMap,
115
+ luvioMetadata: luvioMetadata,
116
+ };
117
+ const modGenOutput = (0, index_1.generateKomaciModule)(generatorInput);
118
+ return {
119
+ input: { bundleConfig, generatorInput },
120
+ output: { modGenOutput, metadata },
121
+ };
122
+ }
123
+ //# sourceMappingURL=komaci-gql.fixtures.spec.js.map
@@ -1,6 +1,6 @@
1
1
  import { NodePath } from '@babel/core';
2
2
  import * as t from '@babel/types';
3
- import { AdgMetadata, HoistedFunctionMetadata, IdKeys, ImportMetadata, ModuleMetadata } from '@komaci/common-shared';
3
+ import { AdgMetadata, HoistedFunctionMetadata, IdKeys, ImportMetadata, ModuleMetadata, GqlMetadata } from '@komaci/common-shared';
4
4
  import { Composition } from '@komaci/types';
5
5
  /**
6
6
  * Take a local function (getter, template string, etc) and prepare it for the resolvable module
@@ -13,7 +13,7 @@ import { Composition } from '@komaci/types';
13
13
  * @returns a composed module level function or undefined if we don't have the
14
14
  * information for composing the funciton
15
15
  */
16
- export declare function hoistLocalFunction(functionMetadata: HoistedFunctionMetadata, importMetadata: Map<string, ImportMetadata>): t.FunctionDeclaration | undefined;
16
+ export declare function hoistLocalFunction(functionMetadata: HoistedFunctionMetadata, ModuleMetadata: ModuleMetadata): t.FunctionDeclaration | undefined;
17
17
  /**
18
18
  * Take a function defined on a class and sanitize it's interactions in preparation to be hoisted into resolvable module/
19
19
  *
@@ -24,7 +24,7 @@ export declare function hoistLocalFunction(functionMetadata: HoistedFunctionMeta
24
24
  * @param nodePath The node to sanitize
25
25
  * @param importMetadata Metadata about all the imports we know about
26
26
  */
27
- export declare function sanitizeFunction(nodePath: NodePath<t.ClassProperty | t.ClassMethod>, importMetadata: Map<string, ImportMetadata>): void;
27
+ export declare function sanitizeFunction(nodePath: NodePath<t.ClassProperty | t.ClassMethod>, importMetadata: Map<string, ImportMetadata>, gqlMetadataMap: Map<string, GqlMetadata>): void;
28
28
  /**
29
29
  * Converts a Komaci ADG into a CallExpression to the ADG factory function
30
30
  * call for the Resolver API.
@@ -40,9 +40,9 @@ const types_1 = require("./types");
40
40
  * @returns a composed module level function or undefined if we don't have the
41
41
  * information for composing the funciton
42
42
  */
43
- function hoistLocalFunction(functionMetadata, importMetadata) {
43
+ function hoistLocalFunction(functionMetadata, ModuleMetadata) {
44
44
  if (functionMetadata.componentAstNode && functionMetadata.generatedName) {
45
- sanitizeFunction(functionMetadata.componentAstNode, importMetadata);
45
+ sanitizeFunction(functionMetadata.componentAstNode, ModuleMetadata.importsByName, ModuleMetadata.gqlMetadata);
46
46
  const propsId = t.identifier(common_shared_1.PROPS);
47
47
  const functionBody = t.isClassMethod(functionMetadata.componentAstNode.node)
48
48
  ? functionMetadata.componentAstNode.node.body
@@ -66,7 +66,7 @@ exports.hoistLocalFunction = hoistLocalFunction;
66
66
  * @param nodePath The node to sanitize
67
67
  * @param importMetadata Metadata about all the imports we know about
68
68
  */
69
- function sanitizeFunction(nodePath, importMetadata) {
69
+ function sanitizeFunction(nodePath, importMetadata, gqlMetadataMap) {
70
70
  const Visitors = {
71
71
  Identifier(path) {
72
72
  if ((path.parent.type === 'MemberExpression' &&
@@ -106,6 +106,14 @@ function sanitizeFunction(nodePath, importMetadata) {
106
106
  path.replaceWith(t.memberExpression(t.identifier(common_shared_1.PROPS), path.node.property)); // replace this.<var> with props.<var>
107
107
  }
108
108
  },
109
+ TaggedTemplateExpression(path) {
110
+ const taggedTmplExpr = path.node;
111
+ const taggedTmplLiteral = taggedTmplExpr.quasi;
112
+ const gqlMetadata = (0, common_shared_1.getGqlMetadataForTaggedTemplate)(taggedTmplLiteral, gqlMetadataMap);
113
+ if (gqlMetadata && gqlMetadata.valid) {
114
+ path.replaceWith(t.identifier(gqlMetadata.generatedImportAlias));
115
+ }
116
+ },
109
117
  };
110
118
  nodePath.traverse(Visitors);
111
119
  }
@@ -1,4 +1,4 @@
1
- import { ClassPropertyContext, ErrorFunctionMetadata, FunctionMetadata, ModuleMetadata, WireFunctionMetadata } from '@komaci/common-shared';
1
+ import { ClassPropertyContext, ErrorFunctionMetadata, FunctionMetadata, ModuleMetadata, WireFunctionMetadata, GqlMetadata } from '@komaci/common-shared';
2
2
  import * as t from '@babel/types';
3
3
  import { GeneratorInput } from './types';
4
4
  import { Binding, PrimitiveValue, PropertyReference, Value, KomaciDocument } from '@komaci/types';
@@ -32,6 +32,12 @@ export declare function generateResolvableModule(input: GeneratorInput, scriptKo
32
32
  export declare function addImportStatements(moduleMetadata: ModuleMetadata, statements: t.Statement[], options: {
33
33
  isComposingFromBundle: boolean;
34
34
  }): void;
35
+ /**
36
+ * Function to generate an import statement for a valid Gql Query
37
+ * @param gqlMetadata the gql metadata object
38
+ * @param statements the ast statement array.
39
+ */
40
+ export declare function generateGqlImportStatements(gqlMetadata: Map<string, GqlMetadata>, statements: t.Statement[]): void;
35
41
  /**
36
42
  * Make ast statements for the details about an error we received
37
43
  * @param adgFunc The error function metadata
@@ -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.collectMetadataForImportedTemplates = exports.exportNamedDeclarationForDynamicImport = exports.addUndefinedDefaultExport = exports.propertyToExpression = exports.functionToExpression = exports.valueReferenceToExpression = 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.valueReferenceToExpression = exports.bindingToExpression = exports.primitiveToExpression = exports.valueToExpression = exports.processWireFunctionType = exports.processErrorFunction = exports.generateGqlImportStatements = 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"));
@@ -83,6 +83,10 @@ function generateResolvableModule(input, scriptKomaciDoc, templateKomaciDocMap,
83
83
  componentDefaultAdgIndex = scriptKomaciDoc.exports?.default?.value;
84
84
  scriptKomaciDoc.adgs?.forEach((_, index) => (0, common_shared_1.initalizeAdgMetadata)(index, scriptKomaciDoc, moduleMetadata, componentDefaultAdgIndex === index && ast !== undefined, isBundle));
85
85
  (0, common_shared_1.mapExportNamesToAdgs)(scriptKomaciDoc.exports, moduleMetadata);
86
+ //we have a gql tag init the map
87
+ if (input.luvioMetadata && input.luvioMetadata?.gqlTag.length > 0) {
88
+ (0, common_shared_1.initGqlMetadata)(input.luvioMetadata.gqlTag, moduleMetadata, input.moduleInfo.namespace, input.moduleInfo.name);
89
+ }
86
90
  if (ast && componentDefaultAdgIndex !== undefined) {
87
91
  const { getters, templateStrings, renderFunction } = (0, common_shared_1.getPropertyMetadataFromAst)(ast);
88
92
  const moduleContext = {
@@ -136,6 +140,10 @@ function generateResolvableModule(input, scriptKomaciDoc, templateKomaciDocMap,
136
140
  addImportStatements(moduleMetadata, statements, {
137
141
  isComposingFromBundle: isBundle,
138
142
  });
143
+ //we have the potential for valid gql queries that need import statements.
144
+ if (moduleMetadata.gqlMetadata.size > 0) {
145
+ generateGqlImportStatements(moduleMetadata.gqlMetadata, statements);
146
+ }
139
147
  // template only resolvable modules are composed completely differently (for now)
140
148
  if (!combinedModule && hasTemplateKomaciDoc) {
141
149
  // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
@@ -167,14 +175,14 @@ function generateResolvableModule(input, scriptKomaciDoc, templateKomaciDocMap,
167
175
  defaultAdg?.functions.forEach((func) => {
168
176
  if (func.type === common_shared_1.FunctionTypes.GETTER_FUNCTION ||
169
177
  func.type === common_shared_1.FunctionTypes.TEMPLATE_STRING) {
170
- const hoistedFunction = (0, functionAstGeneration_1.hoistLocalFunction)(func, moduleMetadata.importsByName);
178
+ const hoistedFunction = (0, functionAstGeneration_1.hoistLocalFunction)(func, moduleMetadata);
171
179
  if (hoistedFunction) {
172
180
  statements.push(hoistedFunction);
173
181
  }
174
182
  }
175
183
  });
176
184
  if (renderFunctionMetadata) {
177
- const hoistedRenderFunction = (0, functionAstGeneration_1.hoistLocalFunction)(renderFunctionMetadata, moduleMetadata.importsByName);
185
+ const hoistedRenderFunction = (0, functionAstGeneration_1.hoistLocalFunction)(renderFunctionMetadata, moduleMetadata);
178
186
  if (hoistedRenderFunction) {
179
187
  statements.push(hoistedRenderFunction);
180
188
  }
@@ -285,6 +293,28 @@ function addImportStatements(moduleMetadata, statements, options) {
285
293
  }
286
294
  }
287
295
  exports.addImportStatements = addImportStatements;
296
+ /**
297
+ * Function to generate an import statement for a valid Gql Query
298
+ * @param gqlMetadata the gql metadata object
299
+ * @param statements the ast statement array.
300
+ */
301
+ function generateGqlImportStatements(gqlMetadata, statements) {
302
+ const importsToMake = new Map();
303
+ gqlMetadata.forEach((value) => {
304
+ if (value.valid) {
305
+ let imports = [];
306
+ if (!importsToMake.has(value.importPath)) {
307
+ importsToMake.set(value.importPath, imports);
308
+ const importStatement = t.importDeclaration(imports, t.stringLiteral(value.importPath));
309
+ statements.push(importStatement);
310
+ }
311
+ imports = importsToMake.get(value.importPath);
312
+ const aliasIdentifier = t.identifier(value.generatedImportAlias);
313
+ imports.push(t.importSpecifier(aliasIdentifier, aliasIdentifier));
314
+ }
315
+ });
316
+ }
317
+ exports.generateGqlImportStatements = generateGqlImportStatements;
288
318
  /**
289
319
  * Make ast statements for the details about an error we received
290
320
  * @param adgFunc The error function metadata
package/build/types.d.ts CHANGED
@@ -19,7 +19,8 @@ export declare type GeneratorInput = {
19
19
  srcFileMap?: {
20
20
  [filename: string]: string;
21
21
  };
22
- luvioMetadata?: Map<string, LuvioMetadata | undefined>;
22
+ /** This will always be the luvio metadata for the core js file for a component. */
23
+ luvioMetadata?: LuvioMetadata | undefined;
23
24
  };
24
25
  declare type ModuleInfo = {
25
26
  type: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@komaci/esm-generator",
3
- "version": "248.1.2",
3
+ "version": "248.1.4",
4
4
  "description": "Komaci generator for ADG ES modules",
5
5
  "homepage": "https://komaci.dev/",
6
6
  "repository": {
@@ -29,12 +29,12 @@
29
29
  "@babel/core": "^7.9.0",
30
30
  "@babel/generator": "^7.9.0",
31
31
  "@babel/types": "^7.9.0",
32
- "@komaci/common-shared": "248.1.2",
33
- "@komaci/static-analyzer": "248.1.2"
32
+ "@komaci/common-shared": "248.1.4",
33
+ "@komaci/static-analyzer": "248.1.4"
34
34
  },
35
35
  "devDependencies": {
36
- "@komaci/types": "248.1.2",
37
- "@lwc-platform/sfdc-lwc-compiler": "244.17.2-2.40.0",
38
- "@lwc/metadata": "2.40.0-0"
36
+ "@komaci/types": "248.1.4",
37
+ "@lwc-platform/sfdc-lwc-compiler": "248.3.9-3.5.0",
38
+ "@lwc/metadata": "3.5.0-0"
39
39
  }
40
40
  }