@komaci/common-shared 264.5.0 → 266.3.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.
@@ -29,16 +29,20 @@ export declare const initializeImportMetdataFromKomaciDocument: (doc: KomaciDocu
29
29
  * @param isSupported if it's from a valid namespace
30
30
  * @param komaciDocImportRef reference index in komaci document
31
31
  * @param moduleMetadata the metadata object
32
+ * @param importAlias optional local alias used for this import in the source module
33
+ * @param isTypeOnly true when the import was declared as TypeScript type-only (`import type ...` or per-specifier `import { type Foo }`)
32
34
  *
33
35
  * @return the import metadata object in case anything needs to be modified
34
36
  */
35
- export declare const composeImportMetadata: (name: string, resourceName: string, isSupported: boolean, komaciDocImportRef: string, moduleMetadata: ModuleMetadata, importAlias?: string) => ImportMetadata;
37
+ export declare const composeImportMetadata: (name: string, resourceName: string, isSupported: boolean, komaciDocImportRef: string, moduleMetadata: ModuleMetadata, importAlias: string | undefined, isTypeOnly: boolean) => ImportMetadata;
36
38
  /**
37
39
  * collect all the imports for a given ast and then execute a callback with information about the import
38
40
  * @param ast The babel ast
39
- * @param cb function to call for acting on import information
41
+ * @param cb function to call for acting on import information. The `isTypeOnly` arg is true when the
42
+ * specifier is part of an `import type ...` declaration or has a per-specifier `type` modifier
43
+ * (`import { type Foo, bar }`).
40
44
  */
41
- export declare const traverseAstImports: (ast: t.File, cb: (lookupName: string, referencedName: string, resourceName: string, originalImportName?: string) => void) => void;
45
+ export declare const traverseAstImports: (ast: t.File, cb: (lookupName: string, referencedName: string, resourceName: string, originalImportName: string | undefined, isTypeOnly: boolean) => void) => void;
42
46
  /**
43
47
  * given the name of a resource see if we have information about it. if we don't compose the base object for later reference.
44
48
  * @param resourceName The import path
@@ -62,8 +66,9 @@ export declare const reconcileImport: (name: string, importPath: string, moduleM
62
66
  * @param namespace the metadata about the import namespace
63
67
  * @param moduleMetadata the metadata about the module
64
68
  * @param originalImportName (optional) the original name of the import that has been aliases. undefined if no alias.
69
+ * @param isTypeOnly true when the import was declared as TypeScript type-only (`import type ...` or per-specifier `import { type Foo }`)
65
70
  */
66
- export declare const addNewImportFromAst: (referencedName: string, namespace: ImportDetail, moduleMetadata: ModuleMetadata, originalImportName?: string) => void;
71
+ export declare const addNewImportFromAst: (referencedName: string, namespace: ImportDetail, moduleMetadata: ModuleMetadata, originalImportName: string | undefined, isTypeOnly: boolean) => void;
67
72
  /**
68
73
  * Komaci Documents don't keep track of import aliases but sometimes they're referenced in code so we want to makes sure we have them.
69
74
  * @param lookupName the name used as the holdover key tor eference this import
@@ -73,7 +73,7 @@ const initializeImportMetdataFromKomaciDocument = (doc, moduleMetadata, template
73
73
  (0, exports.composeImportMetadata)(name, importNamespace.resourceName, isSupported, templateAdgIndex !== undefined
74
74
  ? `t${templateAdgIndex}-` + komaciDocImportRef
75
75
  : komaciDocImportRef, // to prevent collision in references
76
- moduleMetadata, importAlias);
76
+ moduleMetadata, importAlias, false);
77
77
  }
78
78
  /*
79
79
  * For imports from other resolvable modules we know that they will always be only a default import.
@@ -99,10 +99,12 @@ exports.initializeImportMetdataFromKomaciDocument = initializeImportMetdataFromK
99
99
  * @param isSupported if it's from a valid namespace
100
100
  * @param komaciDocImportRef reference index in komaci document
101
101
  * @param moduleMetadata the metadata object
102
+ * @param importAlias optional local alias used for this import in the source module
103
+ * @param isTypeOnly true when the import was declared as TypeScript type-only (`import type ...` or per-specifier `import { type Foo }`)
102
104
  *
103
105
  * @return the import metadata object in case anything needs to be modified
104
106
  */
105
- const composeImportMetadata = (name, resourceName, isSupported, komaciDocImportRef, moduleMetadata, importAlias) => {
107
+ const composeImportMetadata = (name, resourceName, isSupported, komaciDocImportRef, moduleMetadata, importAlias, isTypeOnly) => {
106
108
  const generatorIndex = isSupported
107
109
  ? moduleMetadata.importGeneratorIndex++
108
110
  : moduleMetadata.importGeneratorIndex;
@@ -128,6 +130,7 @@ const composeImportMetadata = (name, resourceName, isSupported, komaciDocImportR
128
130
  isFromSupportedLibrary: (0, allowlistNamespaces_1.isLibraryValid)(resourceName),
129
131
  usedInPriming: false,
130
132
  staticallyAnalyzable: true,
133
+ isTypeOnly,
131
134
  };
132
135
  if (allowlistNamespaces_1.isLocalHtmlImportReference.test(resourceName)) {
133
136
  const templateKomaciDoc = getImportTemplateKomaciDocByResourceName(resourceName, moduleMetadata.templateKomaciDocMap);
@@ -153,7 +156,9 @@ exports.composeImportMetadata = composeImportMetadata;
153
156
  /**
154
157
  * collect all the imports for a given ast and then execute a callback with information about the import
155
158
  * @param ast The babel ast
156
- * @param cb function to call for acting on import information
159
+ * @param cb function to call for acting on import information. The `isTypeOnly` arg is true when the
160
+ * specifier is part of an `import type ...` declaration or has a per-specifier `type` modifier
161
+ * (`import { type Foo, bar }`).
157
162
  */
158
163
  const traverseAstImports = (ast, cb) => {
159
164
  const program = ast.program;
@@ -162,6 +167,8 @@ const traverseAstImports = (ast, cb) => {
162
167
  importDeclarations.forEach((currentDec) => {
163
168
  const specifiers = currentDec.specifiers;
164
169
  const resourceName = currentDec.source.value;
170
+ // `import type { ... } from '...'` and `import type Foo from '...'` set importKind on the declaration.
171
+ const declarationIsTypeOnly = currentDec.importKind === 'type';
165
172
  specifiers.forEach((specifier) => {
166
173
  let referencedName;
167
174
  let originalImportName;
@@ -189,7 +196,10 @@ const traverseAstImports = (ast, cb) => {
189
196
  referencedName = (0, utils_1.getFromIdentifierOrStringLiteral)(specifier.imported);
190
197
  lookupName = referencedName;
191
198
  }
192
- cb(lookupName, referencedName, resourceName, originalImportName);
199
+ // Per-specifier `import { type Foo, bar }` sets importKind on the specifier.
200
+ const specifierIsTypeOnly = specifier.type === 'ImportSpecifier' && specifier.importKind === 'type';
201
+ const isTypeOnly = declarationIsTypeOnly || specifierIsTypeOnly;
202
+ cb(lookupName, referencedName, resourceName, originalImportName, isTypeOnly);
193
203
  });
194
204
  });
195
205
  };
@@ -233,7 +243,7 @@ const reconcileImport = (name, importPath, moduleMetadata) => {
233
243
  return existingImport;
234
244
  }
235
245
  else {
236
- const newImport = (0, exports.composeImportMetadata)(name, importPath, (0, allowlistNamespaces_1.isNamespaceInternal)((0, allowlistNamespaces_1.getNamespaceFromImport)(importPath)), exports.NO_KOMACI_DOC_REF, moduleMetadata);
246
+ const newImport = (0, exports.composeImportMetadata)(name, importPath, (0, allowlistNamespaces_1.isNamespaceInternal)((0, allowlistNamespaces_1.getNamespaceFromImport)(importPath)), exports.NO_KOMACI_DOC_REF, moduleMetadata, undefined, false);
237
247
  const namespace = (0, exports.reconcileNamespace)(importPath, moduleMetadata);
238
248
  namespace.names.add(newImport.name);
239
249
  return newImport;
@@ -246,12 +256,13 @@ exports.reconcileImport = reconcileImport;
246
256
  * @param namespace the metadata about the import namespace
247
257
  * @param moduleMetadata the metadata about the module
248
258
  * @param originalImportName (optional) the original name of the import that has been aliases. undefined if no alias.
259
+ * @param isTypeOnly true when the import was declared as TypeScript type-only (`import type ...` or per-specifier `import { type Foo }`)
249
260
  */
250
- const addNewImportFromAst = (referencedName, namespace, moduleMetadata, originalImportName) => {
261
+ const addNewImportFromAst = (referencedName, namespace, moduleMetadata, originalImportName, isTypeOnly) => {
251
262
  const importAlias = originalImportName && referencedName !== originalImportName
252
263
  ? referencedName
253
264
  : undefined;
254
- const importMetadata = (0, exports.composeImportMetadata)(originalImportName || referencedName, namespace.resourceName, namespace.isSupported, exports.NO_KOMACI_DOC_REF, moduleMetadata, importAlias);
265
+ const importMetadata = (0, exports.composeImportMetadata)(originalImportName || referencedName, namespace.resourceName, namespace.isSupported, exports.NO_KOMACI_DOC_REF, moduleMetadata, importAlias, isTypeOnly);
255
266
  importMetadata.staticallyAnalyzable = false;
256
267
  // this code might need to go in composeImportMetadata() method
257
268
  // SFS would like to make static resources available offline. This code will allow for priming resources from @salesforce/resource imports to make this possible.
@@ -345,16 +356,30 @@ exports.getImportFromNamespace = getImportFromNamespace;
345
356
  * @param ast ast for the given component
346
357
  */
347
358
  const collectImportMetadataFromAst = (ast, moduleMetadata) => {
348
- (0, exports.traverseAstImports)(ast, (lookupName, referencedName, resourceName, originalImportName) => {
359
+ (0, exports.traverseAstImports)(ast, (lookupName, referencedName, resourceName, originalImportName, isTypeOnly) => {
349
360
  const namespace = (0, exports.reconcileNamespace)(resourceName, moduleMetadata);
350
361
  const existingImportMetadata = getImportFromNamespace(lookupName, resourceName, moduleMetadata);
351
362
  if (!namespace.originalNames.has(originalImportName || referencedName)) {
352
- (0, exports.addNewImportFromAst)(referencedName, namespace, moduleMetadata, originalImportName);
363
+ (0, exports.addNewImportFromAst)(referencedName, namespace, moduleMetadata, originalImportName, isTypeOnly);
353
364
  }
354
365
  else {
355
366
  const importMetadata = (0, exports.findOtherAlias)(resourceName, originalImportName || referencedName, moduleMetadata);
356
367
  if (importMetadata) {
357
368
  moduleMetadata.importsByName.set(referencedName, importMetadata);
369
+ // When the same imported name is brought in under multiple local aliases
370
+ // (once as type-only and once as a value) both aliases share a single
371
+ // metadata object (looked up via findOtherAlias). If we observe the type-
372
+ // only declaration first the shared object starts with `isTypeOnly: true`,
373
+ // so when the value alias is later observed we must downgrade the shared flag to
374
+ // `false` to keep the runtime alias callable in the generated ADG.
375
+ //
376
+ // Example (covered by the `value reference wins over a prior type-only reference`
377
+ // test):
378
+ // import type { Foo as A } from 'force/shared'; // pass 1: A → new metadata, isTypeOnly=true
379
+ // import { Foo as B } from 'force/shared'; // pass 2: B → reuses A's metadata; flip to isTypeOnly=false
380
+ if (importMetadata.isTypeOnly && !isTypeOnly) {
381
+ importMetadata.isTypeOnly = false;
382
+ }
358
383
  }
359
384
  }
360
385
  if (existingImportMetadata &&
package/build/types.d.ts CHANGED
@@ -145,6 +145,11 @@ export declare type BasicImportMetadata = {
145
145
  usedInPriming: boolean;
146
146
  /** flag representing if this import was statically picked up as part of the komaci document. we have to keep all statically analyzable imports */
147
147
  staticallyAnalyzable: boolean;
148
+ /**
149
+ * flag representing if this import is a TypeScript type-only import (`import type ...` or per-specifier `import { type Foo }`).
150
+ * type-only imports are preserved in the generated ADG so the LWC compiler's TS-strip pass can erase them at runtime.
151
+ */
152
+ isTypeOnly: boolean;
148
153
  /**
149
154
  * component id for if this import maps to a component used in a template
150
155
  * this is only managed as part of processTemplateImports
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@komaci/common-shared",
3
- "version": "264.5.0",
3
+ "version": "266.3.0",
4
4
  "description": "Assets that are shared across Komaci commonjs packages",
5
5
  "homepage": "https://komaci.dev/",
6
6
  "repository": {