You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Ship the package as both ESM and CommonJS, so import and require are each first-class.
Why
Every source file is CommonJS today: require(...) and module.exports. The README, however, documents import api from "gettyimages-api" in all of its examples. Those examples work through Node's interop, so ESM consumers are not blocked. They are not getting real ESM either.
The goal is dual output rather than a pure ESM conversion. A pure conversion would break existing CommonJS consumers, for two reasons:
On Node before 22.12, require("gettyimages-api") throws ERR_REQUIRE_ESM.
On every Node version, the export shape changes. The entry point currently uses module.exports = GettyImagesApi, so require(...) returns the class directly. Under ESM, require(...) returns the module namespace object, and callers need .default.
The second point breaks working code silently. Dual output avoids both problems, so nobody has to rewrite an integration.
Approach
Author the source in one format and generate the other. TypeScript is already a devDependency for the declaration work, therefore tsc is the obvious tool.
require("gettyimages-api") then keeps returning the class directly, and import gets real ESM.
Scope
18 files under lib/, plus the gettyimages-api.js entry point.
Roughly 20 test files, all of which use require.
lib/webhelper.js reads require("../package.json") for the user-agent string. Under ESM this needs an import attribute or a createRequire shim.
The package currently ships source directly from the repository root. Moving to a dist/ layout means files in package.json and the publish flow both need updating. The build step itself comes from Convert the source to TypeScript #85.
Add a test that loads the package both ways, to catch a regression in either entry point.
Convert the source to TypeScript #85 (TypeScript conversion) introduces the build step this issue needs. Once tsc is building the package, dual output is mostly a tsconfig output setting plus the exports map shown above. Doing this issue first means adding a build step purely to transform module syntax, then reworking it.
Expose execute() as async #65 (async execute()) changes the public surface. The API shape should settle before the package is built two ways.
Notes
Known hazard: if a consumer's dependency graph loads both the ESM and CJS copies, instanceof checks across the two fail. The risk is low here, because the exported class is instantiated by consumers rather than passed between libraries, and there is no module-level shared state.
Ship the package as both ESM and CommonJS, so
importandrequireare each first-class.Why
Every source file is CommonJS today:
require(...)andmodule.exports. The README, however, documentsimport api from "gettyimages-api"in all of its examples. Those examples work through Node's interop, so ESM consumers are not blocked. They are not getting real ESM either.The goal is dual output rather than a pure ESM conversion. A pure conversion would break existing CommonJS consumers, for two reasons:
require("gettyimages-api")throwsERR_REQUIRE_ESM.module.exports = GettyImagesApi, sorequire(...)returns the class directly. Under ESM,require(...)returns the module namespace object, and callers need.default.The second point breaks working code silently. Dual output avoids both problems, so nobody has to rewrite an integration.
Approach
Author the source in one format and generate the other. TypeScript is already a devDependency for the declaration work, therefore
tscis the obvious tool.Add an
exportsmap to package.json:{ "exports": { ".": { "types": "./gettyimages-api.d.ts", "import": "./dist/esm/gettyimages-api.js", "require": "./dist/cjs/gettyimages-api.js" } }, "main": "./dist/cjs/gettyimages-api.js", "types": "./gettyimages-api.d.ts" }require("gettyimages-api")then keeps returning the class directly, andimportgets real ESM.Scope
lib/, plus thegettyimages-api.jsentry point.require.lib/webhelper.jsreadsrequire("../package.json")for the user-agent string. Under ESM this needs an import attribute or acreateRequireshim.dist/layout meansfilesin package.json and the publish flow both need updating. The build step itself comes from Convert the source to TypeScript #85.Sequencing
Do this last in the milestone, after #85 and #65.
tscis building the package, dual output is mostly atsconfigoutput setting plus theexportsmap shown above. Doing this issue first means adding a build step purely to transform module syntax, then reworking it.execute()) changes the public surface. The API shape should settle before the package is built two ways.Notes
instanceofchecks across the two fail. The risk is low here, because the exported class is instantiated by consumers rather than passed between libraries, and there is no module-level shared state.