nomyo-js/rollup.config.mjs

62 lines
2 KiB
JavaScript
Raw Normal View History

2026-01-17 12:02:08 +01:00
import typescript from '@rollup/plugin-typescript';
import resolve from '@rollup/plugin-node-resolve';
import commonjs from '@rollup/plugin-commonjs';
const target = process.env.TARGET || 'node';
const config = {
input: target === 'browser' ? 'src/browser.ts' : 'src/node.ts',
plugins: [
resolve(),
commonjs(),
typescript({
tsconfig: './tsconfig.json',
declaration: false,
declarationDir: undefined
})
]
};
fix: correct package entry points and publish contents Five packaging defects, all pre-existing: 1. dist/esm/index.js held ESM syntax while the package is not "type": "module", so Node classified it as CommonJS. It failed outright on Node 18 ("Unexpected token 'export'") and only worked on Node >= 22 because Node re-parses after guessing the module type, paying that cost on every import. Bundles now carry explicit extensions: .mjs for ES output, .cjs/.js for CommonJS. The browser build gained a real CommonJS output too — the exports map previously pointed the browser "require" condition at an ES module. The exports map now also leads with "types" and ends with a "default" fallback for resolvers matching neither "node" nor "browser". 2. files: ["native"] published the local build directory: a 94.6 kB Linux-x64 .node binary, a 148 kB object file and generated Makefiles. node-gyp-build checks build/Release before prebuilds, so every consumer on every platform would have found this machine's binary, skipped compiling, and failed to load it. It fails safe (native/ index.js catches and returns null), but the addon could never work for anyone else. Narrowed to the four source files. 3. binding.gyp resolves node-addon-api at build time, but nothing declared it: it was a devDependency of the root, absent from native/package.json. The build only succeeded here because a dev install populates the root node_modules. Declared as a dependency of the native package, where it is actually needed. 4. No clean step, so stale output shipped — the tarball carried both dist/types/core/** and a dist/types/src/** tree left over from before rootDir was set. build now runs clean first. 5. test:browser ran `karma start` with no karma.conf.js anywhere in the repo, and tests/browser is an empty directory. Removed the script and the karma devDependency rather than leave a script that cannot run. Verified: CommonJS require and ESM import both resolve on Node 18.19.1 and 24.18.0; TypeScript resolves types under both bundler and node16; npm pack now produces 35 files / 103.8 kB with no build artefacts. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-19 12:39:09 +02:00
// Extensions are explicit rather than bare `.js`: the package is not
// "type": "module", so Node treats a .js file as CommonJS. An ES-format bundle
// named .js therefore fails to import on Node < 22, and only works above that
// because Node re-parses it after guessing — at a cost on every import.
2026-01-17 12:02:08 +01:00
if (target === 'node') {
config.output = [
{
file: 'dist/node/index.js',
format: 'cjs',
exports: 'named'
},
{
fix: correct package entry points and publish contents Five packaging defects, all pre-existing: 1. dist/esm/index.js held ESM syntax while the package is not "type": "module", so Node classified it as CommonJS. It failed outright on Node 18 ("Unexpected token 'export'") and only worked on Node >= 22 because Node re-parses after guessing the module type, paying that cost on every import. Bundles now carry explicit extensions: .mjs for ES output, .cjs/.js for CommonJS. The browser build gained a real CommonJS output too — the exports map previously pointed the browser "require" condition at an ES module. The exports map now also leads with "types" and ends with a "default" fallback for resolvers matching neither "node" nor "browser". 2. files: ["native"] published the local build directory: a 94.6 kB Linux-x64 .node binary, a 148 kB object file and generated Makefiles. node-gyp-build checks build/Release before prebuilds, so every consumer on every platform would have found this machine's binary, skipped compiling, and failed to load it. It fails safe (native/ index.js catches and returns null), but the addon could never work for anyone else. Narrowed to the four source files. 3. binding.gyp resolves node-addon-api at build time, but nothing declared it: it was a devDependency of the root, absent from native/package.json. The build only succeeded here because a dev install populates the root node_modules. Declared as a dependency of the native package, where it is actually needed. 4. No clean step, so stale output shipped — the tarball carried both dist/types/core/** and a dist/types/src/** tree left over from before rootDir was set. build now runs clean first. 5. test:browser ran `karma start` with no karma.conf.js anywhere in the repo, and tests/browser is an empty directory. Removed the script and the karma devDependency rather than leave a script that cannot run. Verified: CommonJS require and ESM import both resolve on Node 18.19.1 and 24.18.0; TypeScript resolves types under both bundler and node16; npm pack now produces 35 files / 103.8 kB with no build artefacts. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-19 12:39:09 +02:00
file: 'dist/esm/index.mjs',
fix: repair platform resolution in the built bundles The published package could not be used at all. `require('nomyo-js')` succeeded, but constructing a client threw: Cannot find module './node' Platform selection was done with a runtime require: const NodeSecureMemory = require('./node').NodeSecureMemory; Rollup flattens every module into one file, so './node' and './browser' no longer exist at runtime — and because the calls sit inside function bodies, rollup left them as literal runtime requires rather than resolving them. The failure was therefore deferred to first use: module load and Object.keys() both looked fine, so nothing noticed. The SecureCompletionClient constructor calls createSecureMemory() and createHttpClient(), which made every client unconstructable. Confirmed present at 057ff6c, this branch's merge base, so the npm package has never worked. Platform implementations are now injected by the entry points, which is what src/node.ts and src/browser.ts always claimed to do (they merely re-exported ./index). createSecureMemory/createHttpClient consult a registered factory and throw a directive error if none was registered. No require fallback is kept: leaving one would put an unresolvable relative require back in the bundle, and bundlers resolve requires statically, so webpack/vite would fail on a path that does not exist in dist/. Jest registers the platform via tests/setup.ts instead. This also keeps the Node HTTP client and the optional native addon out of the browser bundle, which previously carried both. Second defect found while verifying: dist/esm/index.mjs contained 13 require() calls (crypto, fs, path, jose, nomyo-native) that the source loads lazily. `require` does not exist in ES module scope, so an ESM consumer crashed with "require is not defined" as soon as one ran — using keyDir for key persistence would have hit it on every Node version. Node 24 masked the crypto case by having a global crypto. The ESM output now carries a createRequire shim. tests/integration/bundle.test.ts covers the artefact that actually ships: both bundles construct a client, expose the API, resolve the platform layer, keep Node-only modules out of the browser build, and the ESM entry is imported and used by a real spawned Node process. Every other suite runs against src/ through ts-jest, where these paths resolve normally — which is precisely why this went unnoticed. Verified end to end by installing the packed tarball into a clean project: CommonJS and ESM both construct a client and run fs-backed key generation on Node 18.19.1 and 24.18.0. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-19 12:59:24 +02:00
format: 'es',
// The source loads several modules lazily via require(): the crypto
// fallback, fs/path for key persistence, the optional native addon,
// and jose. `require` does not exist in ES module scope, so without
// this shim an ESM consumer crashes with "require is not defined"
// the moment one of those paths runs. Node-only output, so
// node:module is safe here.
banner: "import { createRequire as __nomyoCreateRequire } from 'node:module';\n"
+ 'const require = __nomyoCreateRequire(import.meta.url);'
2026-01-17 12:02:08 +01:00
}
];
config.external = ['crypto', 'https', 'fs', 'path'];
} else if (target === 'browser') {
fix: correct package entry points and publish contents Five packaging defects, all pre-existing: 1. dist/esm/index.js held ESM syntax while the package is not "type": "module", so Node classified it as CommonJS. It failed outright on Node 18 ("Unexpected token 'export'") and only worked on Node >= 22 because Node re-parses after guessing the module type, paying that cost on every import. Bundles now carry explicit extensions: .mjs for ES output, .cjs/.js for CommonJS. The browser build gained a real CommonJS output too — the exports map previously pointed the browser "require" condition at an ES module. The exports map now also leads with "types" and ends with a "default" fallback for resolvers matching neither "node" nor "browser". 2. files: ["native"] published the local build directory: a 94.6 kB Linux-x64 .node binary, a 148 kB object file and generated Makefiles. node-gyp-build checks build/Release before prebuilds, so every consumer on every platform would have found this machine's binary, skipped compiling, and failed to load it. It fails safe (native/ index.js catches and returns null), but the addon could never work for anyone else. Narrowed to the four source files. 3. binding.gyp resolves node-addon-api at build time, but nothing declared it: it was a devDependency of the root, absent from native/package.json. The build only succeeded here because a dev install populates the root node_modules. Declared as a dependency of the native package, where it is actually needed. 4. No clean step, so stale output shipped — the tarball carried both dist/types/core/** and a dist/types/src/** tree left over from before rootDir was set. build now runs clean first. 5. test:browser ran `karma start` with no karma.conf.js anywhere in the repo, and tests/browser is an empty directory. Removed the script and the karma devDependency rather than leave a script that cannot run. Verified: CommonJS require and ESM import both resolve on Node 18.19.1 and 24.18.0; TypeScript resolves types under both bundler and node16; npm pack now produces 35 files / 103.8 kB with no build artefacts. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-19 12:39:09 +02:00
config.output = [
{
file: 'dist/browser/index.mjs',
format: 'es',
name: 'Nomyo'
},
{
file: 'dist/browser/index.cjs',
format: 'cjs',
exports: 'named',
name: 'Nomyo'
}
];
2026-01-17 12:02:08 +01:00
}
export default config;