UNPKG

@esmx/core

Version:

A high-performance microfrontend framework supporting Vue, React, Preact, Solid, and Svelte with SSR and Module Linking capabilities.

1,403 lines (1,315 loc) 62.7 kB
import { assert, describe, test } from 'vitest'; import { compressImportMap, createImportMap, createImportsMap, createScopesMap, fixImportMapNestedScopes } from './import-map'; import type { GetImportMapOptions, ImportMapManifest } from './import-map'; describe('createImportsMap', () => { test('should return empty object for empty manifests', () => { const result = createImportsMap([], (name, file) => `${name}/${file}`); assert.deepEqual(result, {}); }); test('should process all exports including package exports', () => { const manifests: ImportMapManifest[] = [ { name: 'test-module', exports: { component: { name: 'component', pkg: false, file: 'component.js', identifier: 'test-module/component' }, vue: { name: 'vue', pkg: true, file: 'vue.js', identifier: 'test-module/vue' } }, scopes: {} } ]; const result = createImportsMap( manifests, (name, file) => `${name}/${file}` ); assert.deepEqual(result, { 'test-module/component': 'test-module/component.js', 'test-module/vue': 'test-module/vue.js' }); }); test('should create aliases for index suffixes', () => { const manifests: ImportMapManifest[] = [ { name: 'test-module', exports: { 'src/index': { name: 'src/index', pkg: false, file: 'src/index.js', identifier: 'test-module/src/index' } }, scopes: {} } ]; const result = createImportsMap( manifests, (name, file) => `${name}/${file}` ); assert.deepEqual(result, { 'test-module/src/index': 'test-module/src/index.js', 'test-module/src': 'test-module/src/index.js' }); }); test('should handle multiple manifests', () => { const manifests: ImportMapManifest[] = [ { name: 'module-a', exports: { utils: { name: 'utils', pkg: false, file: 'utils.js', identifier: 'module-a/utils' } }, scopes: {} }, { name: 'module-b', exports: {}, scopes: {} } ]; const result = createImportsMap( manifests, (name, file) => `${name}/${file}` ); assert.deepEqual(result, { 'module-a/utils': 'module-a/utils.js' }); }); test('should handle empty exports', () => { const manifests: ImportMapManifest[] = [ { name: 'test-module', exports: {}, scopes: {} } ]; const result = createImportsMap( manifests, (name, file) => `${name}/${file}` ); assert.deepEqual(result, {}); }); test('should handle duplicate alias creation', () => { const manifests: ImportMapManifest[] = [ { name: 'test-module', exports: { 'src/components/index': { name: 'src/components/index', pkg: false, file: 'src/components/index.js', identifier: 'test-module/src/components/index' } }, scopes: {} } ]; const result = createImportsMap( manifests, (name, file) => `${name}/${file}` ); assert.deepEqual(result, { 'test-module/src/components/index': 'test-module/src/components/index.js', 'test-module/src/components': 'test-module/src/components/index.js' }); }); test('should handle identifier conflicts across modules', () => { const manifests: ImportMapManifest[] = [ { name: 'module-a', exports: { utils: { name: 'utils', pkg: false, file: 'utils-a.js', identifier: 'module-a/utils' } }, scopes: {} }, { name: 'module-b', exports: { utils: { name: 'utils', pkg: false, file: 'utils-b.js', identifier: 'module-b/utils' } }, scopes: {} } ]; const result = createImportsMap( manifests, (name, file) => `${name}/${file}` ); assert.deepEqual(result, { 'module-a/utils': 'module-a/utils-a.js', 'module-b/utils': 'module-b/utils-b.js' }); }); test('should handle nested index aliases', () => { const manifests: ImportMapManifest[] = [ { name: 'test-module', exports: { 'src/components/utils/index': { name: 'src/components/utils/index', pkg: false, file: 'src/components/utils/index.js', identifier: 'test-module/src/components/utils/index' } }, scopes: {} } ]; const result = createImportsMap( manifests, (name, file) => `${name}/${file}` ); assert.deepEqual(result, { 'test-module/src/components/utils/index': 'test-module/src/components/utils/index.js', 'test-module/src/components/utils': 'test-module/src/components/utils/index.js' }); }); }); describe('fixImportMapNestedScopes', () => { test('should return unchanged import map for empty scopes', () => { const importMap = { imports: { 'shared-modules/vue': '/shared-modules/vue.620a1e89.final.mjs' }, scopes: {} }; const result = fixImportMapNestedScopes(importMap); assert.deepEqual(result, importMap); }); test('should return unchanged import map for shallow scopes only', () => { const importMap = { imports: { 'shared-modules/vue': '/shared-modules/vue.620a1e89.final.mjs' }, scopes: { '/shared-modules/': { vue: '/shared-modules/vue.620a1e89.final.mjs' } } }; const result = fixImportMapNestedScopes(importMap); assert.deepEqual(result, importMap); }); test('should create file-level scopes for nested scopes', () => { const importMap = { imports: { 'shared-modules/vue2': '/shared-modules/vue2.a1b2c3d4.final.mjs', 'shared-modules/vue2/@esmx/router-vue': '/shared-modules/vue2/@esmx/router-vue.e5f6g7h8.final.mjs', 'shared-modules/vue2/index': '/shared-modules/vue2/index.i9j0k1l2.final.mjs', 'shared-modules/vue': '/shared-modules/vue.m3n4o5p6.final.mjs' }, scopes: { '/shared-modules/': { vue: '/shared-modules/vue.m3n4o5p6.final.mjs' }, '/shared-modules/vue2/': { vue: '/shared-modules/vue2.a1b2c3d4.final.mjs' } } }; const expected = { imports: { 'shared-modules/vue2': '/shared-modules/vue2.a1b2c3d4.final.mjs', 'shared-modules/vue2/@esmx/router-vue': '/shared-modules/vue2/@esmx/router-vue.e5f6g7h8.final.mjs', 'shared-modules/vue2/index': '/shared-modules/vue2/index.i9j0k1l2.final.mjs', 'shared-modules/vue': '/shared-modules/vue.m3n4o5p6.final.mjs' }, scopes: { '/shared-modules/vue.m3n4o5p6.final.mjs': { vue: '/shared-modules/vue.m3n4o5p6.final.mjs' }, '/shared-modules/vue2.a1b2c3d4.final.mjs': { vue: '/shared-modules/vue.m3n4o5p6.final.mjs' }, '/shared-modules/vue2/@esmx/router-vue.e5f6g7h8.final.mjs': { vue: '/shared-modules/vue2.a1b2c3d4.final.mjs' }, '/shared-modules/vue2/index.i9j0k1l2.final.mjs': { vue: '/shared-modules/vue2.a1b2c3d4.final.mjs' } } }; const result = fixImportMapNestedScopes(importMap); assert.deepEqual(result, expected); }); test('should handle multiple nested scopes correctly', () => { const importMap = { imports: { 'shared-modules/vue2': '/shared-modules/vue2.q7r8s9t0.final.mjs', 'shared-modules/vue2/component': '/shared-modules/vue2/component.u1v2w3x4.final.mjs', 'shared-modules/vue3': '/shared-modules/vue3.y5z6a7b8.final.mjs', 'shared-modules/vue3/component': '/shared-modules/vue3/component.c9d0e1f2.final.mjs', 'shared-modules/vue': '/shared-modules/vue.g3h4i5j6.final.mjs' }, scopes: { '/shared-modules/': { vue: '/shared-modules/vue.g3h4i5j6.final.mjs' }, '/shared-modules/vue2/': { vue: '/shared-modules/vue2.q7r8s9t0.final.mjs' }, '/shared-modules/vue3/': { vue: '/shared-modules/vue3.y5z6a7b8.final.mjs' } } }; const expected = { imports: { 'shared-modules/vue2': '/shared-modules/vue2.q7r8s9t0.final.mjs', 'shared-modules/vue2/component': '/shared-modules/vue2/component.u1v2w3x4.final.mjs', 'shared-modules/vue3': '/shared-modules/vue3.y5z6a7b8.final.mjs', 'shared-modules/vue3/component': '/shared-modules/vue3/component.c9d0e1f2.final.mjs', 'shared-modules/vue': '/shared-modules/vue.g3h4i5j6.final.mjs' }, scopes: { '/shared-modules/vue.g3h4i5j6.final.mjs': { vue: '/shared-modules/vue.g3h4i5j6.final.mjs' }, '/shared-modules/vue2.q7r8s9t0.final.mjs': { vue: '/shared-modules/vue.g3h4i5j6.final.mjs' }, '/shared-modules/vue2/component.u1v2w3x4.final.mjs': { vue: '/shared-modules/vue2.q7r8s9t0.final.mjs' }, '/shared-modules/vue3.y5z6a7b8.final.mjs': { vue: '/shared-modules/vue.g3h4i5j6.final.mjs' }, '/shared-modules/vue3/component.c9d0e1f2.final.mjs': { vue: '/shared-modules/vue3.y5z6a7b8.final.mjs' } } }; const result = fixImportMapNestedScopes(importMap); assert.deepEqual(result, expected); }); test('should handle deeply nested scopes', () => { const importMap = { imports: { 'shared-modules/vue2/components/button': '/shared-modules/vue2/components/button.k7l8m9n0.final.mjs', 'shared-modules/vue2/components/input': '/shared-modules/vue2/components/input.o1p2q3r4.final.mjs' }, scopes: { '/shared-modules/vue2/components/': { vue: '/shared-modules/vue2.s5t6u7v8.final.mjs' } } }; const expected = { imports: { 'shared-modules/vue2/components/button': '/shared-modules/vue2/components/button.k7l8m9n0.final.mjs', 'shared-modules/vue2/components/input': '/shared-modules/vue2/components/input.o1p2q3r4.final.mjs' }, scopes: { '/shared-modules/vue2/components/button.k7l8m9n0.final.mjs': { vue: '/shared-modules/vue2.s5t6u7v8.final.mjs' }, '/shared-modules/vue2/components/input.o1p2q3r4.final.mjs': { vue: '/shared-modules/vue2.s5t6u7v8.final.mjs' } } }; const result = fixImportMapNestedScopes(importMap); assert.deepEqual(result, expected); }); test('should not create file-level scopes for imports not matching nested scope', () => { const importMap = { imports: { 'shared-modules/vue': '/shared-modules/vue.w9x0y1z2.final.mjs', 'shared-modules/vue2/component': '/shared-modules/vue2/component.a3b4c5d6.final.mjs', 'other-modules/component': '/other-modules/component.e7f8g9h0.final.mjs' }, scopes: { '/shared-modules/vue2/': { vue: '/shared-modules/vue2.i1j2k3l4.final.mjs' } } }; const expected = { imports: importMap.imports, scopes: { '/shared-modules/vue2/component.a3b4c5d6.final.mjs': { vue: '/shared-modules/vue2.i1j2k3l4.final.mjs' } } }; const result = fixImportMapNestedScopes(importMap); assert.deepEqual(result, expected); }); test('should handle empty imports', () => { const importMap = { imports: {}, scopes: { '/shared-modules/vue2/': { vue: '/shared-modules/vue2.m5n6o7p8.final.mjs' } } }; const expected = { imports: {}, scopes: {} }; const result = fixImportMapNestedScopes(importMap); assert.deepEqual(result, expected); }); test('should preserve original import map structure', () => { const importMap = { imports: { 'shared-modules/vue2': '/shared-modules/vue2.q9r8s7t6.final.mjs', 'shared-modules/vue2/component': '/shared-modules/vue2/component.u5v4w3x2.final.mjs' }, scopes: { '/shared-modules/vue2/': { vue: '/shared-modules/vue2.q9r8s7t6.final.mjs', 'vue-router': '/shared-modules/vue2/router.y1z0a9b8.final.mjs' } } }; const result = fixImportMapNestedScopes(importMap); const expected = { imports: importMap.imports, scopes: { '/shared-modules/vue2/component.u5v4w3x2.final.mjs': { vue: '/shared-modules/vue2.q9r8s7t6.final.mjs', 'vue-router': '/shared-modules/vue2/router.y1z0a9b8.final.mjs' } } }; assert.deepEqual(result, expected); }); test('should handle complex priority scenarios with multiple nested levels', () => { const importMap = { imports: { 'shared-modules/vue2': '/shared-modules/vue2.c7d8e9f0.final.mjs', 'shared-modules/vue2/test': '/shared-modules/vue2/test.a1b2c3d4.final.mjs', 'shared-modules/vue2/test/component': '/shared-modules/vue2/test/component.e5f6g7h8.final.mjs', 'shared-modules/vue': '/shared-modules/vue.i9j0k1l2.final.mjs' }, scopes: { '/shared-modules/': { vue: '/shared-modules/vue.i9j0k1l2.final.mjs', 'vue-router': '/shared-modules/@esmx/router.m3n4o5p6.final.mjs' }, '/shared-modules/vue2/': { vue: '/shared-modules/vue2.c7d8e9f0.final.mjs', 'vue-router': '/shared-modules/vue2/@esmx/router-vue.q7r8s9t0.final.mjs' }, '/shared-modules/vue2/test/': { vue: '/shared-modules/vue2.c7d8e9f0.final.mjs', 'test-utils': '/shared-modules/vue2/test/utils.u1v2w3x4.final.mjs' } } }; const expected = { imports: { 'shared-modules/vue2': '/shared-modules/vue2.c7d8e9f0.final.mjs', 'shared-modules/vue2/test': '/shared-modules/vue2/test.a1b2c3d4.final.mjs', 'shared-modules/vue2/test/component': '/shared-modules/vue2/test/component.e5f6g7h8.final.mjs', 'shared-modules/vue': '/shared-modules/vue.i9j0k1l2.final.mjs' }, scopes: { '/shared-modules/vue.i9j0k1l2.final.mjs': { vue: '/shared-modules/vue.i9j0k1l2.final.mjs', 'vue-router': '/shared-modules/@esmx/router.m3n4o5p6.final.mjs' }, '/shared-modules/vue2.c7d8e9f0.final.mjs': { vue: '/shared-modules/vue.i9j0k1l2.final.mjs', 'vue-router': '/shared-modules/@esmx/router.m3n4o5p6.final.mjs' }, '/shared-modules/vue2/test.a1b2c3d4.final.mjs': { vue: '/shared-modules/vue2.c7d8e9f0.final.mjs', 'vue-router': '/shared-modules/vue2/@esmx/router-vue.q7r8s9t0.final.mjs' }, '/shared-modules/vue2/test/component.e5f6g7h8.final.mjs': { vue: '/shared-modules/vue2.c7d8e9f0.final.mjs', 'test-utils': '/shared-modules/vue2/test/utils.u1v2w3x4.final.mjs', 'vue-router': '/shared-modules/vue2/@esmx/router-vue.q7r8s9t0.final.mjs' } } }; const result = fixImportMapNestedScopes(importMap); assert.deepEqual(result, expected); }); test('should handle priority with overlapping nested scopes', () => { const importMap = { imports: { 'shared-modules/vue2': '/shared-modules/vue2.n3o4p5q6.final.mjs', 'shared-modules/vue2/components': '/shared-modules/vue2/components.r7s8t9u0.final.mjs', 'shared-modules/vue2/components/button': '/shared-modules/vue2/components/button.v1w2x3y4.final.mjs', 'shared-modules/vue2/components/input': '/shared-modules/vue2/components/input.z5a6b7c8.final.mjs' }, scopes: { '/shared-modules/vue2/': { vue: '/shared-modules/vue2.n3o4p5q6.final.mjs', 'vue-router': '/shared-modules/vue2/@esmx/router-vue.d9e0f1g2.final.mjs' }, '/shared-modules/vue2/components/': { vue: '/shared-modules/vue2.n3o4p5q6.final.mjs', 'component-utils': '/shared-modules/vue2/components/utils.h3i4j5k6.final.mjs' } } }; const expected = { imports: { 'shared-modules/vue2': '/shared-modules/vue2.n3o4p5q6.final.mjs', 'shared-modules/vue2/components': '/shared-modules/vue2/components.r7s8t9u0.final.mjs', 'shared-modules/vue2/components/button': '/shared-modules/vue2/components/button.v1w2x3y4.final.mjs', 'shared-modules/vue2/components/input': '/shared-modules/vue2/components/input.z5a6b7c8.final.mjs' }, scopes: { '/shared-modules/vue2/components.r7s8t9u0.final.mjs': { vue: '/shared-modules/vue2.n3o4p5q6.final.mjs', 'vue-router': '/shared-modules/vue2/@esmx/router-vue.d9e0f1g2.final.mjs' }, '/shared-modules/vue2/components/button.v1w2x3y4.final.mjs': { 'component-utils': '/shared-modules/vue2/components/utils.h3i4j5k6.final.mjs', vue: '/shared-modules/vue2.n3o4p5q6.final.mjs', 'vue-router': '/shared-modules/vue2/@esmx/router-vue.d9e0f1g2.final.mjs' }, '/shared-modules/vue2/components/input.z5a6b7c8.final.mjs': { 'component-utils': '/shared-modules/vue2/components/utils.h3i4j5k6.final.mjs', vue: '/shared-modules/vue2.n3o4p5q6.final.mjs', 'vue-router': '/shared-modules/vue2/@esmx/router-vue.d9e0f1g2.final.mjs' } } }; const result = fixImportMapNestedScopes(importMap); assert.deepEqual(result, expected); }); test('should handle very deeply nested scope priority scenarios', () => { const importMap = { imports: { 'shared-modules/vue2': '/shared-modules/vue2.l7m8n9o0.final.mjs', 'shared-modules/vue2/test': '/shared-modules/vue2/test.p1q2r3s4.final.mjs', 'shared-modules/vue2/test/unit': '/shared-modules/vue2/test/unit.t5u6v7w8.final.mjs', 'shared-modules/vue2/test/unit/component': '/shared-modules/vue2/test/unit/component.x9y0z1a2.final.mjs' }, scopes: { '/shared-modules/': { vue: '/shared-modules/vue.b3c4d5e6.final.mjs' }, '/shared-modules/vue2/': { vue: '/shared-modules/vue2.l7m8n9o0.final.mjs' }, '/shared-modules/vue2/test/': { vue: '/shared-modules/vue2.l7m8n9o0.final.mjs', 'test-utils': '/shared-modules/vue2/test/utils.f7g8h9i0.final.mjs' }, '/shared-modules/vue2/test/unit/': { vue: '/shared-modules/vue2.l7m8n9o0.final.mjs', 'test-utils': '/shared-modules/vue2/test/utils.f7g8h9i0.final.mjs' } } }; const expected = { imports: { 'shared-modules/vue2': '/shared-modules/vue2.l7m8n9o0.final.mjs', 'shared-modules/vue2/test': '/shared-modules/vue2/test.p1q2r3s4.final.mjs', 'shared-modules/vue2/test/unit': '/shared-modules/vue2/test/unit.t5u6v7w8.final.mjs', 'shared-modules/vue2/test/unit/component': '/shared-modules/vue2/test/unit/component.x9y0z1a2.final.mjs' }, scopes: { '/shared-modules/vue2.l7m8n9o0.final.mjs': { vue: '/shared-modules/vue.b3c4d5e6.final.mjs' }, '/shared-modules/vue2/test.p1q2r3s4.final.mjs': { vue: '/shared-modules/vue2.l7m8n9o0.final.mjs' }, '/shared-modules/vue2/test/unit.t5u6v7w8.final.mjs': { vue: '/shared-modules/vue2.l7m8n9o0.final.mjs', 'test-utils': '/shared-modules/vue2/test/utils.f7g8h9i0.final.mjs' }, '/shared-modules/vue2/test/unit/component.x9y0z1a2.final.mjs': { vue: '/shared-modules/vue2.l7m8n9o0.final.mjs', 'test-utils': '/shared-modules/vue2/test/utils.f7g8h9i0.final.mjs' } } }; const result = fixImportMapNestedScopes(importMap); assert.deepEqual(result, expected); }); test('should ensure different directory levels have distinct values for proper testing', () => { const importMap = { imports: { 'shared-modules/level1': '/shared-modules/level1.a1b2c3d4.final.mjs', 'shared-modules/level1/level2': '/shared-modules/level1/level2.e5f6g7h8.final.mjs', 'shared-modules/level1/level2/level3': '/shared-modules/level1/level2/level3.i9j0k1l2.final.mjs' }, scopes: { '/shared-modules/level1/': { vue: '/shared-modules/level1.a1b2c3d4.final.mjs' }, '/shared-modules/level1/level2/': { vue: '/shared-modules/level1/level2.e5f6g7h8.final.mjs' } } }; const expected = { imports: { 'shared-modules/level1': '/shared-modules/level1.a1b2c3d4.final.mjs', 'shared-modules/level1/level2': '/shared-modules/level1/level2.e5f6g7h8.final.mjs', 'shared-modules/level1/level2/level3': '/shared-modules/level1/level2/level3.i9j0k1l2.final.mjs' }, scopes: { '/shared-modules/level1/level2.e5f6g7h8.final.mjs': { vue: '/shared-modules/level1.a1b2c3d4.final.mjs' }, '/shared-modules/level1/level2/level3.i9j0k1l2.final.mjs': { vue: '/shared-modules/level1/level2.e5f6g7h8.final.mjs' } } }; const result = fixImportMapNestedScopes(importMap); assert.deepEqual(result, expected); assert.equal( result.scopes['/shared-modules/level1/level2.e5f6g7h8.final.mjs'] .vue, '/shared-modules/level1.a1b2c3d4.final.mjs' ); assert.equal( result.scopes[ '/shared-modules/level1/level2/level3.i9j0k1l2.final.mjs' ].vue, '/shared-modules/level1/level2.e5f6g7h8.final.mjs' ); }); test('should successfully delete properties using Reflect.deleteProperty', () => { const importMap = { imports: { 'shared/modules/vue2': '/shared/modules/vue2.a1b2c3d4.final.mjs' }, scopes: { '/shared/modules/vue2/': { vue: '/shared/modules/vue2.a1b2c3d4.final.mjs' } } }; const result = fixImportMapNestedScopes(importMap); const expected = { imports: importMap.imports, scopes: {} }; assert.deepEqual(result, expected); assert.doesNotThrow(() => { fixImportMapNestedScopes(importMap); }); }); describe('scope path processing logic', () => { test('should process all scope paths regardless of format', () => { const importMap = { imports: { 'shared/modules/vue2': '/shared/modules/vue2.a1b2c3d4.final.mjs', 'shared/vue': '/shared/vue.e5f6g7h8.final.mjs' }, scopes: { 'shared/modules/vue2/': { vue: '/shared/modules/vue2.a1b2c3d4.final.mjs' }, '/shared/modules/vue2': { vue: '/shared/modules/vue2.a1b2c3d4.final.mjs' }, '/shared/': { vue: '/shared/vue.e5f6g7h8.final.mjs' }, '/shared/modules/vue2/': { vue: '/shared/modules/vue2.a1b2c3d4.final.mjs' } } }; const expected = { imports: { 'shared/modules/vue2': '/shared/modules/vue2.a1b2c3d4.final.mjs', 'shared/vue': '/shared/vue.e5f6g7h8.final.mjs' }, scopes: { '/shared/modules/vue2.a1b2c3d4.final.mjs': { vue: '/shared/modules/vue2.a1b2c3d4.final.mjs' }, '/shared/vue.e5f6g7h8.final.mjs': { vue: '/shared/vue.e5f6g7h8.final.mjs' } } }; const result = fixImportMapNestedScopes(importMap); assert.deepEqual(result, expected); }); test('should handle scope paths with any depth', () => { const importMap = { imports: { 'a/b/c': '/a/b/c.a1b2c3d4.final.mjs' }, scopes: { '/a/b/c/': { vue: '/a/b/c.a1b2c3d4.final.mjs' } } }; const expected = { imports: { 'a/b/c': '/a/b/c.a1b2c3d4.final.mjs' }, scopes: {} }; const result = fixImportMapNestedScopes(importMap); assert.deepEqual(result, expected); }); test('should handle very deep nested scope paths', () => { const importMap = { imports: { 'a/b/c/d/e/f': '/a/b/c/d/e/f.a1b2c3d4.final.mjs' }, scopes: { '/a/b/c/d/e/f/': { vue: '/a/b/c/d/e/f.a1b2c3d4.final.mjs' } } }; const expected = { imports: { 'a/b/c/d/e/f': '/a/b/c/d/e/f.a1b2c3d4.final.mjs' }, scopes: {} }; const result = fixImportMapNestedScopes(importMap); assert.deepEqual(result, expected); }); test('should create file-level scopes for all scope paths', () => { const importMap = { imports: { 'modules/vue': '/modules/vue.a1b2c3d4.final.mjs', 'shared/vue': '/shared/vue.e5f6g7h8.final.mjs' }, scopes: { '/modules/': { vue: '/modules/vue.a1b2c3d4.final.mjs' }, '/shared/': { vue: '/shared/vue.e5f6g7h8.final.mjs' } } }; const expected = { imports: { 'modules/vue': '/modules/vue.a1b2c3d4.final.mjs', 'shared/vue': '/shared/vue.e5f6g7h8.final.mjs' }, scopes: { '/modules/vue.a1b2c3d4.final.mjs': { vue: '/modules/vue.a1b2c3d4.final.mjs' }, '/shared/vue.e5f6g7h8.final.mjs': { vue: '/shared/vue.e5f6g7h8.final.mjs' } } }; const result = fixImportMapNestedScopes(importMap); assert.deepEqual(result, expected); }); test('should process multiple scope paths in correct order by depth', () => { const importMap = { imports: { 'shared/modules/vue2': '/shared/modules/vue2.a1b2c3d4.final.mjs', 'shared/modules/vue2/component': '/shared/modules/vue2/component.e5f6g7h8.final.mjs', 'shared/modules/vue2/utils': '/shared/modules/vue2/utils.i9j0k1l2.final.mjs' }, scopes: { '/shared/modules/vue2/': { vue: '/shared/modules/vue2.a1b2c3d4.final.mjs' }, '/shared/modules/vue2/utils/': { 'test-utils': '/shared/modules/vue2/utils.i9j0k1l2.final.mjs' } } }; const expected = { imports: { 'shared/modules/vue2': '/shared/modules/vue2.a1b2c3d4.final.mjs', 'shared/modules/vue2/component': '/shared/modules/vue2/component.e5f6g7h8.final.mjs', 'shared/modules/vue2/utils': '/shared/modules/vue2/utils.i9j0k1l2.final.mjs' }, scopes: { '/shared/modules/vue2/component.e5f6g7h8.final.mjs': { vue: '/shared/modules/vue2.a1b2c3d4.final.mjs' }, '/shared/modules/vue2/utils.i9j0k1l2.final.mjs': { vue: '/shared/modules/vue2.a1b2c3d4.final.mjs' } } }; const result = fixImportMapNestedScopes(importMap); assert.deepEqual(result, expected); }); }); }); describe('createScopesMap', () => { test('should return empty object for empty manifests', () => { const imports = {}; const manifests: ImportMapManifest[] = []; const result = createScopesMap( imports, manifests, (name, scope) => `${name}/${scope}` ); assert.deepEqual(result, {}); }); test('should return empty object when manifests have no scopes', () => { const imports = { 'test-module/component': 'test-module/component.js' }; const manifests: ImportMapManifest[] = [ { name: 'test-module', exports: { component: { name: 'component', pkg: false, file: 'component.js', identifier: 'test-module/component' } }, scopes: {} } ]; const result = createScopesMap( imports, manifests, (name, scope) => `${name}/${scope}` ); assert.deepEqual(result, {}); }); test('should build scopes map with basic scope configuration', () => { const imports = { 'test-module/component': 'test-module/component.js', 'test-module/utils': 'test-module/utils.js' }; const manifests: ImportMapManifest[] = [ { name: 'test-module', exports: { component: { name: 'component', pkg: false, file: 'component.js', identifier: 'test-module/component' }, utils: { name: 'utils', pkg: false, file: 'utils.js', identifier: 'test-module/utils' } }, scopes: { node_modules: { react: 'test-module/component', lodash: 'test-module/utils' } } } ]; const result = createScopesMap( imports, manifests, (name, scope) => `${name}/${scope}` ); assert.deepEqual(result, { 'test-module//node_modules': { react: 'test-module/component.js', lodash: 'test-module/utils.js' } }); }); test('should handle scope with non-existent identifiers', () => { const imports = { 'test-module/component': 'test-module/component.js' }; const manifests: ImportMapManifest[] = [ { name: 'test-module', exports: { component: { name: 'component', pkg: false, file: 'component.js', identifier: 'test-module/component' } }, scopes: { node_modules: { react: 'test-module/component', 'non-existent': 'test-module/non-existent' } } } ]; const result = createScopesMap( imports, manifests, (name, scope) => `${name}/${scope}` ); assert.deepEqual(result, { 'test-module//node_modules': { react: 'test-module/component.js', 'non-existent': 'test-module/non-existent' } }); }); test('should handle scope with external URLs', () => { const imports = { 'test-module/component': 'test-module/component.js' }; const manifests: ImportMapManifest[] = [ { name: 'test-module', exports: { component: { name: 'component', pkg: false, file: 'component.js', identifier: 'test-module/component' } }, scopes: { node_modules: { react: 'https://cdn.com/react.js', 'local-component': 'test-module/component' } } } ]; const result = createScopesMap( imports, manifests, (name, scope) => `${name}/${scope}` ); assert.deepEqual(result, { 'test-module//node_modules': { react: 'https://cdn.com/react.js', 'local-component': 'test-module/component.js' } }); }); test('should use scope path from imports when available', () => { const imports = { 'test-module/node_modules': 'test-module/node_modules/index.js', 'test-module/component': 'test-module/component.js' }; const manifests: ImportMapManifest[] = [ { name: 'test-module', exports: { node_modules: { name: 'node_modules', pkg: false, file: 'node_modules/index.js', identifier: 'test-module/node_modules' }, component: { name: 'component', pkg: false, file: 'component.js', identifier: 'test-module/component' } }, scopes: { node_modules: { react: 'test-module/component' } } } ]; const result = createScopesMap( imports, manifests, (name, scope) => `${name}/${scope}` ); assert.deepEqual(result, { 'test-module/test-module/node_modules/index.js': { react: 'test-module/component.js' } }); }); test('should fall back to scope path when not found in imports', () => { const imports = { 'test-module/component': 'test-module/component.js' }; const manifests: ImportMapManifest[] = [ { name: 'test-module', exports: { component: { name: 'component', pkg: false, file: 'component.js', identifier: 'test-module/component' } }, scopes: { node_modules: { react: 'test-module/component' } } } ]; const result = createScopesMap( imports, manifests, (name, scope) => `${name}/${scope}` ); assert.deepEqual(result, { 'test-module//node_modules': { react: 'test-module/component.js' } }); }); test('should handle multiple scopes in single manifest', () => { const imports = { 'test-module/component': 'test-module/component.js', 'test-module/utils': 'test-module/utils.js' }; const manifests: ImportMapManifest[] = [ { name: 'test-module', exports: { component: { name: 'component', pkg: false, file: 'component.js', identifier: 'test-module/component' }, utils: { name: 'utils', pkg: false, file: 'utils.js', identifier: 'test-module/utils' } }, scopes: { node_modules: { react: 'test-module/component' }, vendor: { lodash: 'test-module/utils' } } } ]; const result = createScopesMap( imports, manifests, (name, scope) => `${name}/${scope}` ); assert.deepEqual(result, { 'test-module//node_modules': { react: 'test-module/component.js' }, 'test-module//vendor': { lodash: 'test-module/utils.js' } }); }); test('should handle multiple manifests with scopes', () => { const imports = { 'module-a/component': 'module-a/component.js', 'module-b/utils': 'module-b/utils.js' }; const manifests: ImportMapManifest[] = [ { name: 'module-a', exports: { component: { name: 'component', pkg: false, file: 'component.js', identifier: 'module-a/component' } }, scopes: { node_modules: { react: 'module-a/component' } } }, { name: 'module-b', exports: { utils: { name: 'utils', pkg: false, file: 'utils.js', identifier: 'module-b/utils' } }, scopes: { vendor: { lodash: 'module-b/utils' } } } ]; const result = createScopesMap( imports, manifests, (name, scope) => `${name}/${scope}` ); assert.deepEqual(result, { 'module-a//node_modules': { react: 'module-a/component.js' }, 'module-b//vendor': { lodash: 'module-b/utils.js' } }); }); test('should handle empty scope specifier map', () => { const imports = { 'test-module/component': 'test-module/component.js' }; const manifests: ImportMapManifest[] = [ { name: 'test-module', exports: { component: { name: 'component', pkg: false, file: 'component.js', identifier: 'test-module/component' } }, scopes: { './node_modules': {} } } ]; const result = createScopesMap( imports, manifests, (name, scope) => `${name}/${scope}` ); assert.deepEqual(result, { 'test-module//./node_modules': {} }); }); test('should handle undefined scopes property', () => { const imports = { 'test-module/component': 'test-module/component.js' }; const manifests: ImportMapManifest[] = [ { name: 'test-module', exports: { component: { name: 'component', pkg: false, file: 'component.js', identifier: 'test-module/component' } }, scopes: undefined as any } ]; const result = createScopesMap( imports, manifests, (name, scope) => `${name}/${scope}` ); assert.deepEqual(result, {}); }); }); describe('createImportMap', () => { test('should return empty import map for empty manifests', () => { const options: GetImportMapOptions = { manifests: [], getFile: (name, file) => `${name}/${file}`, getScope: (name, scope) => `${name}/${scope}` }; const result = createImportMap(options); assert.deepEqual(result, { imports: {}, scopes: {} }); }); test('should build complete import map with exports and scopes', () => { const options: GetImportMapOptions = { manifests: [ { name: 'test-module', exports: { component: { name: 'component', pkg: false, file: 'component.js', identifier: 'test-module/component' }, utils: { name: 'utils', pkg: false, file: 'utils.js', identifier: 'test-module/utils' } }, scopes: { node_modules: { react: 'test-module/component', lodash: 'test-module/utils' } } } ], getFile: (name, file) => `${name}/${file}`, getScope: (name, scope) => `${name}/${scope}` }; const result = createImportMap(options); assert.deepEqual(result, { imports: { 'test-module/component': 'test-module/component.js', 'test-module/utils': 'test-module/utils.js' }, scopes: { 'test-module//node_modules': { react: 'test-module/component.js', lodash: 'test-module/utils.js' } } }); }); test('should handle complex multi-module scenario', () => { const options: GetImportMapOptions = { manifests: [ { name: 'module-a', exports: { utils: { name: 'utils', pkg: false, file: 'utils.js', identifier: 'module-a/utils' } }, scopes: { node_modules: { react: 'module-a/utils' } } }, { name: 'module-b', exports: { component: { name: 'component', pkg: false, file: 'component.js', identifier: 'module-b/component' } }, sco