Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 51 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,54 @@
"version": "6.3.1",
"description": "Meta Names SDK",
"main": "dist/index.js",
"module": "dist/esm/index.js",
"types": "dist/index.d.ts",
"sideEffects": false,
"exports": {
".": {
"types": "./dist/index.d.ts",
"import": "./dist/esm/index.js",
"require": "./dist/index.js",
"default": "./dist/index.js"
},
"./models/domain": {
"types": "./dist/models/domain.d.ts",
"import": "./dist/esm/models/domain.js",
"require": "./dist/models/domain.js",
"default": "./dist/models/domain.js"
},
"./providers/config": {
"types": "./dist/providers/config.d.ts",
"import": "./dist/esm/providers/config.js",
"require": "./dist/providers/config.js",
"default": "./dist/providers/config.js"
},
"./interface": {
"types": "./dist/interface.d.ts",
"import": "./dist/esm/interface.js",
"require": "./dist/interface.js",
"default": "./dist/interface.js"
},
"./transactions/ledger": {
"types": "./dist/transactions/ledger.d.ts",
"import": "./dist/esm/transactions/ledger.js",
"require": "./dist/transactions/ledger.js",
"default": "./dist/transactions/ledger.js"
},
"./dist/*.js": {
"types": "./dist/*.d.ts",
"import": "./dist/esm/*.js",
"require": "./dist/*.js",
"default": "./dist/*.js"
},
"./dist/*": {
"types": "./dist/*.d.ts",
"import": "./dist/esm/*.js",
"require": "./dist/*.js",
"default": "./dist/*.js"
},
"./package.json": "./package.json"
},
"repository": "https://github.com/MetaNames/sdk.git",
"author": "Yeboster <marco@yeboster.com>",
"license": "MIT",
Expand All @@ -14,12 +61,14 @@
"dist"
],
"scripts": {
"build": "yarn tsc",
"build": "yarn build:cjs && yarn build:esm",
"docs": "typedoc --out docs src",
"format": "eslint --fix src",
"test": "jest -i",
"prepublishOnly": "yarn build",
"audit-ci": "bash scripts/audit-ci.sh"
"audit-ci": "bash scripts/audit-ci.sh",
"build:cjs": "tsc",
"build:esm": "tsc -p tsconfig.esm.json && node scripts/finalize-esm.js"
},
"dependencies": {
"@ledgerhq/hw-transport": "^6.34.0",
Expand Down
83 changes: 83 additions & 0 deletions scripts/finalize-esm.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
#!/usr/bin/env node
/**
* Makes dist/esm loadable as real ESM.
*
* TypeScript emits relative import specifiers exactly as written in the source,
* and this codebase writes them without a file extension. That is fine for
* CommonJS and for bundlers, but Node's ESM resolver does not guess extensions
* or directory indexes, so `import './models'` would fail at runtime. This
* rewrites every relative specifier to the file it actually resolves to and
* marks the directory as ESM.
*/
const fs = require('fs')
const path = require('path')

const root = path.join(__dirname, '..', 'dist', 'esm')

function walk (dir) {
return fs.readdirSync(dir, { withFileTypes: true }).flatMap(entry => {
const full = path.join(dir, entry.name)
if (entry.isDirectory()) return walk(full)
return entry.name.endsWith('.js') ? [full] : []
})
}

const nodeModules = path.join(__dirname, '..', 'node_modules')

/** './models' -> './models/index.js', './interface' -> './interface.js' */
function addExtension (target, specifier) {
if (fs.existsSync(`${target}.js`)) return `${specifier}.js`
if (fs.existsSync(path.join(target, 'index.js'))) return `${specifier}/index.js`
return null
}

function resolveSpecifier (fromFile, specifier) {
if (path.extname(specifier)) return specifier

if (specifier.startsWith('.')) {
const resolved = addExtension(path.resolve(path.dirname(fromFile), specifier), specifier)
if (resolved) return resolved
throw new Error(`cannot resolve ${specifier} from ${fromFile}`)
}

// Deep imports into a dependency ("pkg/lib/main/thing") need the same
// treatment: Node's ESM resolver will not add the extension for them either,
// and these dependencies publish CommonJS without an "exports" map.
const segments = specifier.split('/')
const depth = specifier.startsWith('@') ? 2 : 1
if (segments.length <= depth) return specifier

return addExtension(path.join(nodeModules, specifier), specifier) ?? specifier
}

if (!fs.existsSync(root)) {
console.error('dist/esm does not exist -- run the esm build first')
process.exit(1)
}

const files = walk(root)
let rewritten = 0

for (const file of files) {
const source = fs.readFileSync(file, 'utf8')
const updated = source.replace(
/(\bfrom\s*|\bimport\s*\(\s*)(['"])([^'"]+)\2/g,
(match, prefix, quote, specifier) => {
const resolved = resolveSpecifier(file, specifier)
if (resolved !== specifier) rewritten++
return `${prefix}${quote}${resolved}${quote}`
}
)
if (updated !== source) fs.writeFileSync(file, updated)
}

// Node decides module format from the nearest package.json; the root one has no
// "type", so without this every file here would be parsed as CommonJS. That
// also makes this the nearest manifest for bundlers, so "sideEffects" has to be
// repeated here or the root declaration stops applying to these files.
fs.writeFileSync(
path.join(root, 'package.json'),
JSON.stringify({ type: 'module', sideEffects: false }, null, 2) + '\n'
)

console.log(`finalized ${files.length} esm files, rewrote ${rewritten} specifiers`)
13 changes: 13 additions & 0 deletions tsconfig.esm.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
/* ES2022 modules so bundlers can tree-shake the barrel exports. */
"module": "ES2022",
"moduleResolution": "Bundler",
"outDir": "./dist/esm",
/* The CJS build is the one that emits .d.ts; duplicating them here would
only make the two copies drift. */
"declaration": false,
"declarationMap": false
}
}
Loading