@lwc-bolts/sf2ts 0.0.1 → 0.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -3,10 +3,77 @@
3
3
  var webTreeSitterSfapex = require('web-tree-sitter-sfapex');
4
4
  var xml2js = require('xml2js');
5
5
 
6
- /** @import Parser from "web-tree-sitter" */
7
- /** @import { Component, ConvertedComponent } from "../index.mjs" */
6
+ /** @import { MapPair } from "./index.mjs" */
8
7
 
9
- // TOOD: Apex Continuation
8
+ /**
9
+ * @typedef MapDelta
10
+ * @property {number | null} sourcePos
11
+ * @property {number} destDeltaPos
12
+ */
13
+
14
+ /**
15
+ *
16
+ * @param {MapDelta[]} mappings
17
+ */
18
+ function getMappings(mappings) {
19
+ // increase destination position as an aggregate
20
+ /** @type {MapPair[]} */
21
+ let filteredMappings = [];
22
+ let lastDestPos = 0;
23
+ mappings.forEach((m) => {
24
+ m.destDeltaPos += lastDestPos;
25
+ lastDestPos = m.destDeltaPos;
26
+ if (m.sourcePos !== null) {
27
+ filteredMappings.push({
28
+ sourcePos: m.sourcePos,
29
+ destPos: m.destDeltaPos,
30
+ });
31
+ }
32
+ });
33
+ return filteredMappings;
34
+ }
35
+
36
+ class PositionAwareTextBuilder {
37
+ /** @type {MapDelta[]} */
38
+ mappings = [];
39
+ /** @type {string[]} */
40
+ textParts = [];
41
+
42
+ lastTextLen = 0;
43
+
44
+ /**
45
+ *
46
+ * @param {string} text
47
+ * @param {number?} sourceStartPos
48
+ * @param {number?} sourceEndPos
49
+ */
50
+ addText(text, sourceStartPos = null, sourceEndPos = null) {
51
+ this.mappings.push({
52
+ sourcePos: sourceStartPos,
53
+ destDeltaPos: this.lastTextLen,
54
+ });
55
+ this.lastTextLen = text.length;
56
+ if (sourceEndPos != null) {
57
+ this.mappings.push({
58
+ sourcePos: sourceEndPos,
59
+ destDeltaPos: this.lastTextLen,
60
+ });
61
+ this.lastTextLen = 0;
62
+ }
63
+ this.textParts.push(text);
64
+ }
65
+
66
+ build() {
67
+ return this.textParts.join("");
68
+ }
69
+
70
+ getMappings() {
71
+ return getMappings(this.mappings);
72
+ }
73
+ }
74
+
75
+ /** @import Parser from "web-tree-sitter" */
76
+ /** @import { Component, ConvertedComponent, MapPair } from "../index.mjs" */
10
77
 
11
78
  /** @type { Parser } */
12
79
  let prsr;
@@ -29,33 +96,25 @@ function ApexClass(comp) {
29
96
  throw err;
30
97
  }
31
98
 
32
- const [className, declarationContent, mappingContent] =
33
- buildDeclarationForApexFile(prsr, comp.path, comp.content, false);
99
+ const [declarationContent, mappingContent] = buildDeclarationForApexFile(
100
+ prsr,
101
+ comp.content,
102
+ false
103
+ );
34
104
  if (declarationContent === undefined) {
35
105
  throw new Error("Problem building declaration content");
36
106
  }
107
+ if (mappingContent === undefined) {
108
+ throw new Error("Problem building declaration content mappings");
109
+ }
37
110
 
38
- return { ...comp, declarationContent: declarationContent, mapData: [] };
111
+ return {
112
+ ...comp,
113
+ declarationContent: declarationContent,
114
+ mapData: mappingContent,
115
+ };
39
116
  }
40
117
 
41
- /**
42
- * @typedef DeltaPoint
43
- * @property {number} rowDelta
44
- * @property {number} column
45
- */
46
-
47
- /**
48
- * @typedef MappingPos
49
- * @property {DeltaPoint} startPosition
50
- * @property {DeltaPoint} endPosition
51
- */
52
-
53
- /**
54
- * @typedef Mapping
55
- * @property { MappingPos } dPos
56
- * @property { {startPosition: Parser.Point, endPosition: Parser.Point }?} sPos
57
- */
58
-
59
118
  /** @type { Record<string, string> } */
60
119
  const typeOverrides = {
61
120
  string: "string",
@@ -71,20 +130,22 @@ let localNestedClasses = [];
71
130
  /** @type { string? } */
72
131
  let outerClassName;
73
132
 
133
+ // TODO: probably don't want this to be a global
134
+ let builder = new PositionAwareTextBuilder();
135
+
74
136
  /**
75
137
  *
76
138
  * @param {Parser} parser
77
- * @param {string} relativeFilePath
78
139
  * @param {string} apexText
79
140
  * @param {boolean} isSobject
80
- * @returns { string[] }
141
+ * @returns { [string, MapPair[]] | [] }
81
142
  */
82
143
  function buildDeclarationForApexFile(
83
144
  parser,
84
- relativeFilePath,
85
145
  apexText,
86
146
  isSobject = false
87
147
  ) {
148
+ builder = new PositionAwareTextBuilder();
88
149
  try {
89
150
  const tree = parser.parse(apexText);
90
151
  // step into top-level class, if any
@@ -95,15 +156,10 @@ function buildDeclarationForApexFile(
95
156
  return []; // this isn't a class
96
157
  }
97
158
 
98
- // TODO: build mapping file
99
- const [className, declarationText, mappings] = processClass(
100
- classes[0],
101
- isSobject
102
- );
103
- const mappingText = getMapFile(className, relativeFilePath, mappings);
159
+ processClass(classes[0], isSobject);
104
160
  localNestedClasses = [];
105
161
  outerClassName = null;
106
- return [className, declarationText, mappingText];
162
+ return [builder.build(), builder.getMappings()];
107
163
  } catch (error) {
108
164
  console.error(error);
109
165
 
@@ -117,20 +173,19 @@ function buildDeclarationForApexFile(
117
173
  *
118
174
  * @param {Parser.SyntaxNode} classNode
119
175
  * @param {boolean} isSobject
120
- * @returns { [string, string, Mapping[]] }
121
176
  */
122
177
  function processClass(classNode, isSobject) {
123
- let className = classNode.childForFieldName("name")?.text ?? "";
178
+ const classNameNode = classNode.childForFieldName("name");
179
+ if (!classNameNode) {
180
+ throw new Error("Class Name Node not found");
181
+ }
182
+ let className = classNameNode?.text ?? "";
124
183
  if (!outerClassName) {
125
184
  outerClassName = className;
126
185
  }
127
186
  let classBody = classNode.childForFieldName("body");
128
- /** @type {Mapping[]} */
129
- const mappings = [];
130
- /** @type {string[]} */
131
- let outputText = [];
132
187
  if (!classBody) {
133
- return [className, outputText.join(""), mappings];
188
+ return;
134
189
  }
135
190
 
136
191
  const methodsToProcess = [];
@@ -157,194 +212,85 @@ function processClass(classNode, isSobject) {
157
212
  }
158
213
  }
159
214
  if (fieldsToProcess.length > 0) {
160
- outputText.push(`declare interface ${className} {\n`);
161
- mappings.push({
162
- dPos: {
163
- startPosition: {
164
- rowDelta: 0,
165
- column: 0,
166
- },
167
- endPosition: {
168
- rowDelta: 0,
169
- column: 0,
170
- },
171
- },
172
- sPos: null,
173
- });
215
+ builder.addText("declare interface ");
216
+ builder.addText(
217
+ className,
218
+ classNameNode.startIndex,
219
+ classNameNode.endIndex
220
+ );
221
+ builder.addText(" {\n");
174
222
  for (let fNode of fieldsToProcess) {
175
- const [newOutputText, newMappings] = transformFieldDeclaration(
176
- fNode,
177
- isSobject
178
- );
179
- outputText.push(newOutputText);
180
- mappings.push(...newMappings);
223
+ transformFieldDeclaration(fNode, isSobject);
181
224
  }
182
- outputText.push("}\n");
183
- mappings.push({
184
- dPos: {
185
- startPosition: {
186
- rowDelta: 1,
187
- column: 0,
188
- },
189
- endPosition: {
190
- rowDelta: 0,
191
- column: 0,
192
- },
193
- },
194
- sPos: null,
195
- });
225
+ builder.addText("}\n");
196
226
  }
197
227
 
198
228
  if (classesToProcess.length > 0) {
199
- outputText.push(`declare namespace ${className} {\n`);
200
- mappings.push({
201
- dPos: {
202
- startPosition: {
203
- rowDelta: 2,
204
- column: 0,
205
- },
206
- endPosition: {
207
- rowDelta: 0,
208
- column: 0,
209
- },
210
- },
211
- sPos: null,
212
- });
229
+ builder.addText("declare namespace ");
230
+ builder.addText(
231
+ className,
232
+ classNameNode.startIndex,
233
+ classNameNode.endIndex
234
+ );
235
+ builder.addText(" {\n");
213
236
  for (const cNode of classesToProcess) {
214
- const [className, newOutputText, newMappings] = processClass(
215
- cNode,
216
- isSobject
217
- );
218
- if (newOutputText.length > 0) {
219
- outputText.push(" " + newOutputText.replaceAll(/\n(.)/g, "\n $1"));
220
- mappings.push(...newMappings);
221
- }
237
+ processClass(cNode, isSobject);
222
238
  // TODO: somehow queue up local classes for type resolution
223
239
  }
224
240
 
225
- outputText.push(`}\n`);
226
- mappings.push({
227
- dPos: {
228
- startPosition: {
229
- rowDelta: 2,
230
- column: 0,
231
- },
232
- endPosition: {
233
- rowDelta: 0,
234
- column: 0,
235
- },
236
- },
237
- sPos: null,
238
- });
241
+ builder.addText("}\n");
239
242
  }
240
243
 
241
244
  for (const mNode of methodsToProcess) {
242
- const [newOutputText, newMappings] = transformMethodDeclaration(
243
- className,
244
- mNode
245
- );
246
- outputText.push(newOutputText);
247
- mappings.push(...newMappings);
245
+ transformMethodDeclaration(classNameNode, mNode);
248
246
  }
249
- return [className, outputText.join(""), mappings];
250
247
  }
251
248
 
252
249
  /**
253
250
  *
254
- * @param {string} className
251
+ * @param {Parser.SyntaxNode} classNameNode
255
252
  * @param {Parser.SyntaxNode} methodNode
256
- * @returns {[string, Mapping[]]}
257
253
  */
258
- function transformMethodDeclaration(className, methodNode) {
259
- /** @type {Mapping[]} */
260
- const mappings = [];
254
+ function transformMethodDeclaration(classNameNode, methodNode) {
261
255
  const methodNameNode = methodNode.childForFieldName("name");
262
256
  if (!methodNameNode) {
263
- return ["", mappings];
257
+ return;
264
258
  }
265
- const methodName = methodNameNode.text;
259
+ methodNameNode.text;
266
260
  const returnType = methodNode.childForFieldName("type");
267
261
  if (!returnType) {
268
- return ["", mappings];
262
+ return;
269
263
  }
270
264
  const parameters = getMethodParameters(methodNode);
271
265
 
272
266
  const auraEnabledNode = getAuraEnabledAnnotation(methodNode);
273
267
  if (!auraEnabledNode) {
274
268
  // method doesn't hold the AuraEnabled Annotation
275
- return ["", mappings];
269
+ return;
276
270
  }
277
271
  const isCacheableEnabled = getAuraEnabledIsCacheable(auraEnabledNode);
272
+ const isContinuation = getAuraEnabledIsContinuation(auraEnabledNode);
278
273
 
279
- const [newOutputText, methodNameMapping] = declarationString(
280
- className,
281
- methodName,
274
+ // TODO: continuation return type is actually the return type of the `continuationMethod` referenced in the Continuation object
275
+ declarationString(
276
+ classNameNode,
277
+ methodNameNode,
282
278
  getType(returnType),
283
279
  parameters,
284
- isCacheableEnabled
280
+ isCacheableEnabled,
281
+ isContinuation
285
282
  );
286
- const declarationParts = newOutputText.split("\n");
287
- methodNameMapping.rowDelta;
288
-
289
- mappings.push({
290
- dPos: {
291
- startPosition: methodNameMapping,
292
- endPosition: {
293
- rowDelta: methodNameMapping.rowDelta,
294
- column: methodNameMapping.column + methodName.length,
295
- },
296
- },
297
- sPos: {
298
- startPosition: methodNameNode.startPosition,
299
- endPosition: methodNameNode.endPosition,
300
- },
301
- });
302
- // add consumption of remaining lines
303
- mappings.push({
304
- dPos: {
305
- startPosition: {
306
- rowDelta: declarationParts.length - methodNameMapping.rowDelta,
307
- column: 0,
308
- },
309
- endPosition: {
310
- rowDelta: declarationParts.length - methodNameMapping.rowDelta,
311
- column: 0,
312
- },
313
- },
314
- sPos: null,
315
- });
316
- return [newOutputText, mappings];
317
283
  }
318
284
 
319
285
  /**
320
286
  *
321
287
  * @param {Parser.SyntaxNode} node
322
288
  * @param {boolean} isSobject
323
- * @returns {[string, Mapping[]]}
324
289
  */
325
290
  function transformFieldDeclaration(node, isSobject) {
326
291
  /** @type {string[]} */
327
292
  let deprecatedReasons = [];
328
- let output = "";
329
293
  const modifiers = node.descendantsOfType("modifiers");
330
- /** @type {Mapping} */
331
- const mapping = {
332
- dPos: {
333
- startPosition: {
334
- rowDelta: 1,
335
- column: 2,
336
- },
337
- endPosition: {
338
- // TODO
339
- rowDelta: 0,
340
- column: 0,
341
- },
342
- },
343
- sPos: {
344
- startPosition: node.startPosition,
345
- endPosition: node.endPosition,
346
- },
347
- };
348
294
 
349
295
  if (modifiers.length === 0 || !modifiers[0]) {
350
296
  deprecatedReasons.push("public or global");
@@ -377,21 +323,38 @@ function transformFieldDeclaration(node, isSobject) {
377
323
  deprecatedReasons.push("public or global");
378
324
  }
379
325
  }
380
- /** TODO:
326
+ /**
381
327
  * determine if AuraEnabled & public or global & not static
382
328
  * otherwise mark as deprecated with note (dynamic based on missing access component)
383
329
  * {property}: {getType({type})}?;
384
330
  */
385
331
  if (deprecatedReasons.length > 0) {
386
- mapping.dPos.startPosition.rowDelta++;
387
- output += ` /** @deprecated not exposed; property must be ${deprecatedReasons.join(
388
- ", "
389
- )} */\n`;
390
- }
391
- output += ` ${
392
- node.childForFieldName("declarator")?.childForFieldName("name")?.text ?? ""
393
- }?: ${getType(node.childForFieldName("type"))};\n`;
394
- return [output, [mapping]];
332
+ builder.addText(
333
+ ` /** @deprecated not exposed; property must be ${deprecatedReasons.join(
334
+ ", "
335
+ )} */\n`
336
+ );
337
+ }
338
+ const nameNode = node
339
+ .childForFieldName("declarator")
340
+ ?.childForFieldName("name");
341
+ builder.addText(" ");
342
+ if (!nameNode) {
343
+ throw new Error("Field doesn't have a name");
344
+ }
345
+ builder.addText(
346
+ `${nameNode?.text ?? ""}`,
347
+ nameNode.startIndex,
348
+ nameNode.endIndex
349
+ );
350
+ builder.addText("?: ");
351
+ const typeNode = node.childForFieldName("type");
352
+ if (!typeNode) {
353
+ throw new Error("Type node not found");
354
+ }
355
+ const typeText = getType(typeNode);
356
+ builder.addText(typeText, typeNode.startIndex, typeNode.endIndex);
357
+ builder.addText(";\n");
395
358
  }
396
359
 
397
360
  /**
@@ -418,6 +381,30 @@ function getAuraEnabledIsCacheable(node) {
418
381
  return false;
419
382
  }
420
383
 
384
+ /**
385
+ *
386
+ * @param {Parser.SyntaxNode} node
387
+ * @returns {boolean}
388
+ */
389
+ function getAuraEnabledIsContinuation(node) {
390
+ const args = node.childForFieldName("arguments");
391
+ if (args) {
392
+ for (const a of args.descendantsOfType("annotation_key_value")) {
393
+ const k = a.childForFieldName("key");
394
+ const v = a.childForFieldName("value");
395
+ if (
396
+ k &&
397
+ v &&
398
+ k.text.toLowerCase() === "continuation" &&
399
+ v.text.toLowerCase() === "true"
400
+ ) {
401
+ return true;
402
+ }
403
+ }
404
+ }
405
+ return false;
406
+ }
407
+
421
408
  /**
422
409
  *
423
410
  * @param {Parser.SyntaxNode} node
@@ -456,22 +443,36 @@ function getMethodParameters(node) {
456
443
 
457
444
  /**
458
445
  *
459
- * @param {string} className
460
- * @param {string} methodName
446
+ * @param {Parser.SyntaxNode} classNameNode
447
+ * @param {Parser.SyntaxNode} methodNameNode
461
448
  * @param {string} returnType
462
449
  * @param {Map<string, string>} params
463
450
  * @param {boolean} isCacheable
464
- * @returns {[string, DeltaPoint]}
451
+ * @param {boolean} isContinuation
465
452
  */
466
453
  function declarationString(
467
- className,
468
- methodName,
454
+ classNameNode,
455
+ methodNameNode,
469
456
  returnType,
470
457
  params,
471
- isCacheable
458
+ isCacheable,
459
+ isContinuation
472
460
  ) {
473
- let text = `declare module "@salesforce/apex/${className}.${methodName}" {
474
- const ${methodName}: {
461
+ builder.addText("declare module ");
462
+ // if method has Containuation
463
+ builder.addText(
464
+ `"@salesforce/apex${isContinuation ? "Continuation" : ""}/${classNameNode.text}.${methodNameNode.text}"`,
465
+ methodNameNode.startIndex,
466
+ methodNameNode.endIndex
467
+ );
468
+ builder.addText(` {
469
+ const `);
470
+ builder.addText(
471
+ methodNameNode.text,
472
+ methodNameNode.startIndex,
473
+ methodNameNode.endIndex
474
+ );
475
+ builder.addText(`: {
475
476
  (${
476
477
  params.size === 0
477
478
  ? ""
@@ -496,62 +497,9 @@ function declarationString(
496
497
  >;`
497
498
  }
498
499
  };
499
- export default `;
500
- // analyze how much text we're adding before the method name
501
- const lines = text.split("\n");
502
- /** @type {DeltaPoint} */
503
- const m = {
504
- rowDelta: lines.length - 1,
505
- column: lines[lines.length - 1]?.length ?? 0,
506
- };
507
- // finish building
508
- text += `${methodName};
500
+ export default ${methodNameNode.text};
509
501
  }
510
- `;
511
- return [text, m];
512
- }
513
-
514
- /**
515
- *
516
- * @param {string} className
517
- * @param {string} relativeClassPath
518
- * @param {Mapping[]} mappings
519
- * @returns
520
- */
521
- function getMapFile(className, relativeClassPath, mappings) {
522
- let mappingsString = "";
523
- for (const m of mappings) {
524
- mappingsString += ";".repeat(m.dPos.startPosition.rowDelta);
525
- if (!m.sPos) {
526
- continue;
527
- }
528
- /**
529
- * Generated column
530
- * Original file this appeared in
531
- * Original line number relative to last given value in this field
532
- * Original column relative to last given value in this field
533
- */
534
- // const incrementalColumnCount =
535
- // m.sPos.startPosition.column - lastMethodColumnNum;
536
-
537
- // mappingsString += `${encode(m.dPos.startPosition.column)}${encode(
538
- // 0
539
- // )}${encode(m.sPos.startPosition.row - lastSourceRow)}${encode(
540
- // incrementalColumnCount
541
- // )}`;
542
-
543
- m.sPos.startPosition.column;
544
- m.sPos.startPosition.row;
545
- }
546
- return JSON.stringify({
547
- version: 3,
548
- file: `${className}.d.ts`,
549
- sourceRoot: "",
550
- // TODO: not so badly hardcoded
551
- sources: [`../../../../../${relativeClassPath}`],
552
- names: [],
553
- mappings: mappingsString,
554
- });
502
+ `);
555
503
  }
556
504
 
557
505
  /**
@@ -608,11 +556,34 @@ function ContentAsset(component) {
608
556
  }
609
557
  asset = result;
610
558
  });
611
- const dec = `declare module "@salesforce/contentAssetUrl/${asset.ContentAsset.masterLabel}" {
612
- var ${asset.ContentAsset.masterLabel}: string;
613
- export default ${asset.ContentAsset.masterLabel};
614
- }`;
615
- return { declarationContent: dec, mapData: [], ...component };
559
+ const label = asset.ContentAsset.masterLabel[0];
560
+ const namePosStart =
561
+ component.content.indexOf("<masterLabel>") + "<masterLabel>".length;
562
+ const namePosEnd = namePosStart + label.length;
563
+
564
+ const builder = new PositionAwareTextBuilder();
565
+
566
+ builder.addText(`declare module `);
567
+ builder.addText(
568
+ `"@salesforce/contentAssetUrl/${label}"`,
569
+ namePosStart,
570
+ namePosEnd
571
+ );
572
+ builder.addText(
573
+ ` {
574
+ const `
575
+ );
576
+ builder.addText(label, namePosStart, namePosEnd);
577
+ builder.addText(
578
+ `: string;
579
+ export default ${label};
580
+ }`
581
+ );
582
+ return {
583
+ declarationContent: builder.build(),
584
+ mapData: builder.getMappings(),
585
+ ...component,
586
+ };
616
587
  }
617
588
 
618
589
  /** @import { Component, ConvertedComponent } from "../index.mjs" */
@@ -623,7 +594,6 @@ function ContentAsset(component) {
623
594
  * @returns {ConvertedComponent}
624
595
  */
625
596
  function CustomPermission(component) {
626
- // generate d.ts
627
597
  /** @type {any} */
628
598
  let perm;
629
599
  xml2js.parseString(component.content, (error, result) => {
@@ -633,16 +603,37 @@ function CustomPermission(component) {
633
603
  perm = result;
634
604
  });
635
605
  const permName = component.path.split("/").pop()?.split(".")[0];
636
- const dec = `declare module "@salesforce/customPermission/${permName}" {
606
+ const namePosStart = component.content.indexOf("<label>") + "<label>".length;
607
+ const namePosEnd = component.content.indexOf("</label>");
608
+
609
+ const builder = new PositionAwareTextBuilder();
610
+ builder.addText("declare module ");
611
+ builder.addText(
612
+ `"@salesforce/customPermission/${permName}"`,
613
+ namePosStart,
614
+ namePosEnd
615
+ );
616
+
617
+ builder.addText(
618
+ ` {
637
619
  /**
638
620
  * ${perm.CustomPermission.label}
639
621
  *
640
622
  * @description ${perm.CustomPermission.description}
641
623
  */
642
- const has${permName}:boolean;
624
+ const `
625
+ );
626
+ builder.addText(`has${permName}`, namePosStart, namePosEnd);
627
+ builder.addText(
628
+ `:boolean;
643
629
  export default has${permName};
644
- }`;
645
- return { declarationContent: dec, mapData: [], ...component };
630
+ }`
631
+ );
632
+ return {
633
+ declarationContent: builder.build(),
634
+ mapData: builder.getMappings(),
635
+ ...component,
636
+ };
646
637
  }
647
638
 
648
639
  /** @import { Component, ConvertedComponent } from "../index.mjs" */
@@ -664,20 +655,47 @@ function CustomField(component) {
664
655
  });
665
656
  const pathParts = component.path.split("/");
666
657
  const fieldName = pathParts.pop()?.split(".")[0];
658
+ if (!fieldName) {
659
+ throw new Error("Unable to resolve field name from file path");
660
+ }
667
661
  pathParts?.pop(); // discard `fields`
668
662
  const objectName = pathParts.pop();
669
- const dec = `declare module '@salesforce/schema/${objectName}.${fieldName}' {
663
+
664
+ const namePosStart =
665
+ component.content.indexOf("<fullName>") + "<fullName>".length;
666
+ const namePosEnd = namePosStart + fieldName.length;
667
+
668
+ const builder = new PositionAwareTextBuilder();
669
+ builder.addText(`declare module `);
670
+ builder.addText(
671
+ `"@salesforce/schema/${objectName}.${fieldName}"`,
672
+ namePosStart,
673
+ namePosEnd
674
+ );
675
+ builder.addText(
676
+ ` {
670
677
  /**
671
678
  * @description ${field.CustomField.inlineHelpText}
672
679
  * @description ${field.CustomField.description}
673
680
  */
674
- const ${fieldName}: {
681
+ const `
682
+ );
683
+
684
+ builder.addText(`${fieldName}`, namePosStart, namePosEnd);
685
+
686
+ builder.addText(
687
+ `: {
675
688
  fieldApiName: '${fieldName}';
676
689
  objectApiName: '${objectName}';
677
690
  }
678
691
  export default ${fieldName};
679
- }`;
680
- return { declarationContent: dec, mapData: [], ...component };
692
+ }`
693
+ );
694
+ return {
695
+ declarationContent: builder.build(),
696
+ mapData: builder.getMappings(),
697
+ ...component,
698
+ };
681
699
  }
682
700
 
683
701
  /** @import { Component, ConvertedComponent } from "../index.mjs" */
@@ -700,18 +718,40 @@ function CustomLabels(component) {
700
718
  if (!Array.isArray(labels.CustomLabels.labels)) {
701
719
  labels.CustomLabels.labels = [labels.CustomLabels.labels];
702
720
  }
703
- let dec = "";
721
+
722
+ const builder = new PositionAwareTextBuilder();
704
723
  for (let label of labels.CustomLabels.labels) {
705
- dec += `declare module "@salesforce/label/c.${label.fullName}" {
724
+ const labelName = label.fullName[0];
725
+ const namePosStart =
726
+ component.content.indexOf(`<fullName>${labelName}`) + `<fullName>`.length;
727
+ const namePosEnd = namePosStart + labelName.length;
728
+
729
+ builder.addText(`declare module `);
730
+ builder.addText(
731
+ `"@salesforce/label/c.${labelName}"`,
732
+ namePosStart,
733
+ namePosEnd
734
+ );
735
+ builder.addText(
736
+ ` {
706
737
  /**
707
738
  * @description ${label.shortDescription}
708
739
  */
709
- const lbl${label.fullName} = '${label.value}';
740
+ const `
741
+ );
742
+ builder.addText(`lbl${label.fullName}`, namePosStart, namePosEnd);
743
+ builder.addText(
744
+ ` = '${label.value}';
710
745
  export default lbl${label.fullName};
711
746
  }
712
- `;
747
+ `
748
+ );
713
749
  }
714
- return { declarationContent: dec, mapData: [], ...component };
750
+ return {
751
+ declarationContent: builder.build(),
752
+ mapData: builder.getMappings(),
753
+ ...component,
754
+ };
715
755
  }
716
756
 
717
757
  /** @import { Component, ConvertedComponent } from "../index.mjs" */
@@ -732,16 +772,36 @@ function CustomObject(component) {
732
772
  obj = result;
733
773
  });
734
774
  const objectName = component.path.split("/").pop()?.split(".")[0];
735
- const dec = `declare module '@salesforce/schema/${objectName}' {
775
+ if (!objectName) {
776
+ throw new Error("Unable to find Object Name");
777
+ }
778
+
779
+ const namePos = component.content.indexOf("<label>") + "<label>".length;
780
+ const namePosEnd = component.content.indexOf("</label>");
781
+
782
+ const builder = new PositionAwareTextBuilder();
783
+ builder.addText(`declare module `);
784
+ builder.addText(`"@salesforce/schema/${objectName}"`, namePos, namePosEnd);
785
+ builder.addText(
786
+ ` {
736
787
  /**
737
788
  * @description ${obj.CustomObject.description}
738
789
  */
739
- const ${objectName}: {
790
+ const `
791
+ );
792
+ builder.addText(`${objectName}`, namePos, namePosEnd);
793
+ builder.addText(
794
+ `: {
740
795
  objectApiName: '${objectName}';
741
796
  }
742
797
  export default ${objectName};
743
- }`;
744
- return { declarationContent: dec, mapData: [], ...component };
798
+ }`
799
+ );
800
+ return {
801
+ declarationContent: builder.build(),
802
+ mapData: builder.getMappings(),
803
+ ...component,
804
+ };
745
805
  }
746
806
 
747
807
  /** @import { Component, ConvertedComponent } from "../index.mjs" */
@@ -762,15 +822,41 @@ function StaticResource(component) {
762
822
  resource = result;
763
823
  });
764
824
  const resourceName = component.path.split("/").pop()?.split(".")[0];
765
- const dec = `declare module "@salesforce/resourceUrl/${resourceName}" {
825
+ const namePosStart =
826
+ component.content.indexOf("<description>") + "<description>".length;
827
+ const namePosEnd = component.content.indexOf("</description>");
828
+
829
+ const builder = new PositionAwareTextBuilder();
830
+
831
+ builder.addText("declare module ");
832
+
833
+ builder.addText(
834
+ `"@salesforce/resourceUrl/${resourceName}"`,
835
+ namePosStart,
836
+ namePosEnd
837
+ );
838
+
839
+ builder.addText(
840
+ ` {
766
841
  /**
767
842
  * @description ${resource.StaticResource.description}
768
843
  * @access ${resource.StaticResource.cacheControl}
769
844
  */
770
- const ${resourceName}:string;
845
+ const `
846
+ );
847
+
848
+ builder.addText(`${resourceName}`, namePosStart, namePosEnd);
849
+
850
+ builder.addText(
851
+ `:string;
771
852
  export default ${resourceName};
772
- }`;
773
- return { declarationContent: dec, mapData: [], ...component };
853
+ }`
854
+ );
855
+ return {
856
+ declarationContent: builder.build(),
857
+ mapData: builder.getMappings(),
858
+ ...component,
859
+ };
774
860
  }
775
861
 
776
862
  var converters = /*#__PURE__*/Object.freeze({