@hkdigital/lib-core 0.5.69 → 0.5.70
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.
- package/package.json +1 -1
- package/scripts/validate-imports.mjs +61 -25
package/package.json
CHANGED
|
@@ -240,38 +240,74 @@ async function findExternalBarrelExport(importPath, targetName) {
|
|
|
240
240
|
|
|
241
241
|
if (!shouldCheck) return null;
|
|
242
242
|
|
|
243
|
+
// Read package.json to check for exports mapping
|
|
244
|
+
let exportsMapping = null;
|
|
245
|
+
try {
|
|
246
|
+
const pkgJsonPath = join(nodeModulesPath, 'package.json');
|
|
247
|
+
const pkgJsonContent = await readFile(pkgJsonPath, 'utf-8');
|
|
248
|
+
const pkgJson = JSON.parse(pkgJsonContent);
|
|
249
|
+
|
|
250
|
+
// Check if there's a "./*" export mapping
|
|
251
|
+
if (pkgJson.exports && pkgJson.exports['./*']) {
|
|
252
|
+
const mapping = pkgJson.exports['./*'];
|
|
253
|
+
const mappingStr = typeof mapping === 'string' ?
|
|
254
|
+
mapping : mapping.default;
|
|
255
|
+
|
|
256
|
+
// Extract prefix from mapping like "./dist/*" -> "dist/"
|
|
257
|
+
if (mappingStr && mappingStr.includes('*')) {
|
|
258
|
+
exportsMapping = mappingStr.replace(/\/?\*$/, '');
|
|
259
|
+
if (exportsMapping.startsWith('./')) {
|
|
260
|
+
exportsMapping = exportsMapping.slice(2);
|
|
261
|
+
}
|
|
262
|
+
if (exportsMapping && !exportsMapping.endsWith('/')) {
|
|
263
|
+
exportsMapping += '/';
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
} catch {
|
|
268
|
+
// Could not read package.json, continue without mapping
|
|
269
|
+
}
|
|
270
|
+
|
|
243
271
|
// Try progressively higher-level barrel files
|
|
244
272
|
for (let i = 1; i < pathInPackage.length; i++) {
|
|
245
273
|
const barrelPath = pathInPackage.slice(0, i).join('/') + '.js';
|
|
246
|
-
const fsBarrelPath = join(nodeModulesPath, barrelPath);
|
|
247
274
|
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
275
|
+
// Try both with and without exports mapping
|
|
276
|
+
const pathsToTry = [
|
|
277
|
+
join(nodeModulesPath, barrelPath),
|
|
278
|
+
exportsMapping ?
|
|
279
|
+
join(nodeModulesPath, exportsMapping + barrelPath) : null
|
|
280
|
+
].filter(Boolean);
|
|
252
281
|
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
282
|
+
for (const fsBarrelPath of pathsToTry) {
|
|
283
|
+
try {
|
|
284
|
+
const stats = await stat(fsBarrelPath);
|
|
285
|
+
if (stats.isFile()) {
|
|
286
|
+
const content = await readFile(fsBarrelPath, 'utf-8');
|
|
287
|
+
|
|
288
|
+
// Check if this barrel exports our target
|
|
289
|
+
// Patterns to match:
|
|
290
|
+
// export { TextButton } from './path';
|
|
291
|
+
// export * from './path';
|
|
292
|
+
const exportPatterns = [
|
|
293
|
+
// Named export with exact name
|
|
294
|
+
new RegExp(
|
|
295
|
+
`export\\s+\\{[^}]*\\b${targetName}\\b[^}]*\\}`,
|
|
296
|
+
'm'
|
|
297
|
+
),
|
|
298
|
+
// Re-export all
|
|
299
|
+
/export\s+\*\s+from/,
|
|
300
|
+
// Default export
|
|
301
|
+
new RegExp(`export\\s+default\\s+${targetName}\\b`, 'm')
|
|
302
|
+
];
|
|
303
|
+
|
|
304
|
+
if (exportPatterns.some(pattern => pattern.test(content))) {
|
|
305
|
+
return `${pkgName}/${barrelPath}`;
|
|
306
|
+
}
|
|
271
307
|
}
|
|
308
|
+
} catch {
|
|
309
|
+
// File doesn't exist, continue
|
|
272
310
|
}
|
|
273
|
-
} catch {
|
|
274
|
-
// File doesn't exist, continue
|
|
275
311
|
}
|
|
276
312
|
}
|
|
277
313
|
|