Skip to content

Commit

Permalink
Fix js-experimental ImportMap by not rendering empty statements
Browse files Browse the repository at this point in the history
  • Loading branch information
lorisleiva committed Jan 10, 2024
1 parent 9388a84 commit f0ef13f
Show file tree
Hide file tree
Showing 3 changed files with 91 additions and 3 deletions.
5 changes: 5 additions & 0 deletions .changeset/tiny-ducks-love.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@metaplex-foundation/kinobi': patch
---

Fix js-experimental ImportMap by not rendering empty statements
12 changes: 9 additions & 3 deletions src/renderers/js-experimental/ImportMap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,11 @@ export class ImportMap {
new Map();

add(module: ImportFrom, imports: string | string[] | Set<string>): ImportMap {
const newImports = new Set(
typeof imports === 'string' ? [imports] : imports
);
if (newImports.size === 0) return this;
const currentImports = this._imports.get(module) ?? new Set();
const newImports = typeof imports === 'string' ? [imports] : imports;
newImports.forEach((i) => currentImports.add(i));
this._imports.set(module, currentImports);
return this;
Expand All @@ -47,8 +50,11 @@ export class ImportMap {
module: ImportFrom,
imports: string | string[] | Set<string>
): ImportMap {
const importsToRemove = new Set(
typeof imports === 'string' ? [imports] : imports
);
if (importsToRemove.size === 0) return this;
const currentImports = this._imports.get(module) ?? new Set();
const importsToRemove = typeof imports === 'string' ? [imports] : imports;
importsToRemove.forEach((i) => currentImports.delete(i));
if (currentImports.size === 0) {
this._imports.delete(module);
Expand Down Expand Up @@ -93,7 +99,7 @@ export class ImportMap {
return this._imports.size === 0;
}

toString(dependencies: Record<ImportFrom, string>): string {
toString(dependencies: Record<ImportFrom, string> = {}): string {
const dependencyMap = { ...DEFAULT_MODULE_MAP, ...dependencies };
const importStatements = [...this._imports.entries()]
.map(([module, imports]) => {
Expand Down
77 changes: 77 additions & 0 deletions test/renderers/js-experimental/ImportMap.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import test from 'ava';
import { ImportMap } from '../../../src/renderers/js-experimental/ImportMap';

test('it renders JavaScript import statements', (t) => {
// Given an import map with 3 imports from 2 sources.
const importMap = new ImportMap()
.add('@solana/addresses', ['getAddressEncoder', 'Address'])
.add('@solana/transactions', 'Transaction');

// When we render it.
const importStatements = importMap.toString();

// Then we expect the following import statements.
t.is(
importStatements,
"import { Address, getAddressEncoder } from '@solana/addresses';\n" +
"import { Transaction } from '@solana/transactions';"
);
});

test('it renders JavaScript import aliases', (t) => {
// Given an import map with an import alias.
const importMap = new ImportMap()
.add('@solana/addresses', 'Address')
.addAlias('@solana/addresses', 'Address', 'SolanaAddress');

// When we render it.
const importStatements = importMap.toString();

// Then we expect the following import statement.
t.is(
importStatements,
"import { Address as SolanaAddress } from '@solana/addresses';"
);
});

test('it offers some default dependency mappings', (t) => {
// Given an import map with some recognized dependency keys.
const importMap = new ImportMap()
.add('solanaAddresses', 'Address')
.add('solanaCodecsCore', 'Codec')
.add('generatedTypes', 'MyType')
.add('shared', 'myHelper')
.add('hooked', 'MyCustomType');

// When we render it.
const importStatements = importMap.toString();

// Then we expect the following import statements.
t.is(
importStatements,
"import { Address } from '@solana/addresses';\n" +
"import { Codec } from '@solana/codecs-core';\n" +
"import { MyCustomType } from '../../hooked';\n" +
"import { myHelper } from '../shared';\n" +
"import { MyType } from '../types';"
);
});

test('it supports custom dependency mappings', (t) => {
// Given an import map with some custom dependency keys.
const importMap = new ImportMap().add('myDependency', 'MyType');

// When we render it whilst providing custom dependency mappings.
const importStatements = importMap.toString({
myDependency: 'my/custom/path',
});

// Then we expect the following import statement.
t.is(importStatements, "import { MyType } from 'my/custom/path';");
});

test('it does not render empty import statements', (t) => {
t.is(new ImportMap().toString(), '');
t.is(new ImportMap().add('shared', []).toString(), '');
t.is(new ImportMap().addAlias('shared', 'Foo', 'Bar').toString(), '');
});

0 comments on commit f0ef13f

Please sign in to comment.