From d91f61cf49729bee78930f1f871409cbb2aa0073 Mon Sep 17 00:00:00 2001 From: Ayush Date: Wed, 11 Sep 2024 02:13:20 +0530 Subject: [PATCH 1/4] fix .cjs and package.json in distribution --- package.json | 25 ++++++++++++--------- post-build.mjs | 61 ++++++++++++++++++++++++++++++++++++++++++++++++++ tsconfig.json | 9 ++++---- 3 files changed, 80 insertions(+), 15 deletions(-) create mode 100644 post-build.mjs diff --git a/package.json b/package.json index 93a284b..45ce437 100644 --- a/package.json +++ b/package.json @@ -2,29 +2,32 @@ "name": "@solana-developers/helpers", "version": "2.5.4", "description": "Solana helper functions", - "main": "./dist/cjs/index.js", - "module": "./dist/esm/index.js", - "types": "./dist/esm/index.d.ts", "type": "module", - "private": false, + "main": "./dist/esm/index.js", + "module": "./dist/esm/index.js", + "types": "./dist/types/index.d.ts", "exports": { ".": { - "import": "./dist/esm/index.js", - "require": "./dist/cjs/index.js" - }, - "./node": { - "import": "./dist/esm/node.js", - "require": "./dist/cjs/node.js" + "import": { + "types": "./dist/esm/index.d.ts", + "default": "./dist/esm/index.js" + }, + "require": { + "types": "./dist/cjs/index.d.ts", + "default": "./dist/cjs/index.cjs" + } } }, + "private": false, + "sideEffects": false, "files": [ "dist" ], - "sideEffects": false, "scripts": { "build": "npm run build:esm && npm run build:cjs", "build:esm": "tsc -p tsconfig.json", "build:cjs": "tsc -p tsconfig.cjs.json", + "postbuild": "node post-build.mjs", "clean": "rm -rf dist", "test": "cd tests && npm run test", "test:ci": "cd tests && npm run test:ci" diff --git a/post-build.mjs b/post-build.mjs new file mode 100644 index 0000000..f580663 --- /dev/null +++ b/post-build.mjs @@ -0,0 +1,61 @@ +import { promises as fs } from 'fs'; +import path from 'path'; + +const __dirname = dirname(fileURLToPath(import.meta.url)); +const CJS_DIR = path.join(__dirname, 'dist', 'cjs'); +const ESM_DIR = path.join(__dirname, 'dist', 'esm'); + +async function createPackageJson(dir, type) { + const content = JSON.stringify({ type }, null, 2); + await fs.writeFile(path.join(dir, 'package.json'), content); + console.log(`Created package.json in ${dir}`); +} + +async function renameIndexFile() { + const oldPath = path.join(CJS_DIR, 'index.js'); + const newPath = path.join(CJS_DIR, 'index.cjs'); + await fs.rename(oldPath, newPath); + console.log('Renamed CJS index file to index.cjs'); +} + +async function processEsmFiles(dir) { + const entries = await fs.readdir(dir, { withFileTypes: true }); + for (const entry of entries) { + const fullPath = path.join(dir, entry.name); + if (entry.isDirectory()) { + await processEsmFiles(fullPath); + } else if (entry.isFile() && entry.name.endsWith('.js')) { + let content = await fs.readFile(fullPath, 'utf8'); + + // Add .js extension to import statements + content = content.replace(/from\s+['"](\.[^'"]+)['"]/g, "from '$1.js'"); + + // Add .js extension to export statements + content = content.replace(/export\s+\*\s+from\s+['"](\.[^'"]+)['"]/g, "export * from '$1.js'"); + + await fs.writeFile(fullPath, content); + console.log(`Processed ESM file: ${fullPath}`); + } + } + } + +async function postbuild() { + try { + // Create package.json files + await createPackageJson(CJS_DIR, 'commonjs'); + await createPackageJson(ESM_DIR, 'module'); + + // Rename index.js to index.cjs in CJS directory + await renameIndexFile(); + + // Process ESM files to add .js extensions + await processEsmFiles(ESM_DIR); + + console.log('Postbuild completed successfully!'); + } catch (error) { + console.error('Postbuild failed:', error); + process.exit(1); + } +} + +postbuild(); \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json index 7935e9b..78de056 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,19 +1,20 @@ { "compilerOptions": { "target": "ES2018", + "module": "ESNext", "lib": ["ES2018", "DOM"], "moduleResolution": "node", "outDir": "./dist/esm", "rootDir": "./src", + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true, "declaration": true, "declarationMap": true, "sourceMap": true, - "esModuleInterop": true, - "forceConsistentCasingInFileNames": true, "strict": true, "skipLibCheck": true, - "module": "ESNext", - "isolatedModules": true + "isolatedModules": true, + "preserveConstEnums": true }, "include": ["src/**/*"], "exclude": ["node_modules", "dist"] From f8ee6e5d3da77558a27f183a2dbfe114347a55d8 Mon Sep 17 00:00:00 2001 From: Ayush Date: Wed, 11 Sep 2024 02:37:37 +0530 Subject: [PATCH 2/4] add types as a distribution --- post-build.mjs | 17 +++++++++-------- tsconfig.json | 2 +- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/post-build.mjs b/post-build.mjs index f580663..faade01 100644 --- a/post-build.mjs +++ b/post-build.mjs @@ -1,19 +1,20 @@ -import { promises as fs } from 'fs'; -import path from 'path'; +import { promises as fs } from 'node:fs'; +import { dirname, join } from 'node:path'; +import { fileURLToPath } from 'node:url'; const __dirname = dirname(fileURLToPath(import.meta.url)); -const CJS_DIR = path.join(__dirname, 'dist', 'cjs'); -const ESM_DIR = path.join(__dirname, 'dist', 'esm'); +const CJS_DIR = join(__dirname, 'dist', 'cjs'); +const ESM_DIR = join(__dirname, 'dist', 'esm'); async function createPackageJson(dir, type) { const content = JSON.stringify({ type }, null, 2); - await fs.writeFile(path.join(dir, 'package.json'), content); + await fs.writeFile(join(dir, 'package.json'), content); console.log(`Created package.json in ${dir}`); } async function renameIndexFile() { - const oldPath = path.join(CJS_DIR, 'index.js'); - const newPath = path.join(CJS_DIR, 'index.cjs'); + const oldPath = join(CJS_DIR, 'index.js'); + const newPath = join(CJS_DIR, 'index.cjs'); await fs.rename(oldPath, newPath); console.log('Renamed CJS index file to index.cjs'); } @@ -21,7 +22,7 @@ async function renameIndexFile() { async function processEsmFiles(dir) { const entries = await fs.readdir(dir, { withFileTypes: true }); for (const entry of entries) { - const fullPath = path.join(dir, entry.name); + const fullPath = join(dir, entry.name); if (entry.isDirectory()) { await processEsmFiles(fullPath); } else if (entry.isFile() && entry.name.endsWith('.js')) { diff --git a/tsconfig.json b/tsconfig.json index 78de056..dfcd51e 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -9,7 +9,7 @@ "esModuleInterop": true, "forceConsistentCasingInFileNames": true, "declaration": true, - "declarationMap": true, + "declarationDir": "./dist/types", "sourceMap": true, "strict": true, "skipLibCheck": true, From 0e84b3f94b0619eb77bf79d7e15580c23c8809a3 Mon Sep 17 00:00:00 2001 From: Ayush Date: Wed, 11 Sep 2024 02:49:52 +0530 Subject: [PATCH 3/4] seperate tsconfigs for types, emit declaration only --- package.json | 9 +++++---- tsconfig.cjs.json | 3 ++- tsconfig.esm.json | 8 ++++++++ tsconfig.json | 9 ++------- tsconfig.types.json | 10 ++++++++++ 5 files changed, 27 insertions(+), 12 deletions(-) create mode 100644 tsconfig.esm.json create mode 100644 tsconfig.types.json diff --git a/package.json b/package.json index 45ce437..796e36b 100644 --- a/package.json +++ b/package.json @@ -9,11 +9,10 @@ "exports": { ".": { "import": { - "types": "./dist/esm/index.d.ts", + "types": "./dist/types/index.d.ts", "default": "./dist/esm/index.js" }, "require": { - "types": "./dist/cjs/index.d.ts", "default": "./dist/cjs/index.cjs" } } @@ -24,9 +23,11 @@ "dist" ], "scripts": { - "build": "npm run build:esm && npm run build:cjs", - "build:esm": "tsc -p tsconfig.json", + "prebuild": "npm run clean", + "build": "npm run build:esm && npm run build:cjs && npm run build:types", + "build:esm": "tsc -p tsconfig.esm.json", "build:cjs": "tsc -p tsconfig.cjs.json", + "build:types": "tsc -p tsconfig.types.json", "postbuild": "node post-build.mjs", "clean": "rm -rf dist", "test": "cd tests && npm run test", diff --git a/tsconfig.cjs.json b/tsconfig.cjs.json index 181de34..724684a 100644 --- a/tsconfig.cjs.json +++ b/tsconfig.cjs.json @@ -2,6 +2,7 @@ "extends": "./tsconfig.json", "compilerOptions": { "module": "CommonJS", - "outDir": "./dist/cjs" + "outDir": "./dist/cjs", + "sourceMap": true } } \ No newline at end of file diff --git a/tsconfig.esm.json b/tsconfig.esm.json new file mode 100644 index 0000000..a430db8 --- /dev/null +++ b/tsconfig.esm.json @@ -0,0 +1,8 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "module": "ESNext", + "outDir": "./dist/esm", + "sourceMap": true + } +} \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json index dfcd51e..1f88001 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,20 +1,15 @@ { "compilerOptions": { "target": "ES2018", - "module": "ESNext", "lib": ["ES2018", "DOM"], "moduleResolution": "node", - "outDir": "./dist/esm", - "rootDir": "./src", "esModuleInterop": true, "forceConsistentCasingInFileNames": true, - "declaration": true, - "declarationDir": "./dist/types", - "sourceMap": true, "strict": true, "skipLibCheck": true, "isolatedModules": true, - "preserveConstEnums": true + "preserveConstEnums": true, + "rootDir": "./src" }, "include": ["src/**/*"], "exclude": ["node_modules", "dist"] diff --git a/tsconfig.types.json b/tsconfig.types.json new file mode 100644 index 0000000..606e9b0 --- /dev/null +++ b/tsconfig.types.json @@ -0,0 +1,10 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "module": "ESNext", + "declaration": true, + "declarationMap": true, + "emitDeclarationOnly": true, + "outDir": "./dist/types" + } +} \ No newline at end of file From 45fa5a092b2e3e8d555a4ce80a4ac096cf0779ec Mon Sep 17 00:00:00 2001 From: Ayush Date: Wed, 11 Sep 2024 04:12:24 +0530 Subject: [PATCH 4/4] add comment in post-build.mjs script --- post-build.mjs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/post-build.mjs b/post-build.mjs index faade01..21b05aa 100644 --- a/post-build.mjs +++ b/post-build.mjs @@ -1,3 +1,9 @@ +// In some cases, where you have { type: module } in package.json at the root +// We will workaround builds manually, since we aren't using any bundler +// tsc is missing extensions with esm exports +// and tsc doesn't export .cjs hence, index.js won't be read as cjs in cjs distribution +// See https://github.com/microsoft/TypeScript/issues/54593 + import { promises as fs } from 'node:fs'; import { dirname, join } from 'node:path'; import { fileURLToPath } from 'node:url';