Repository navigation
[javascript] Create @seleniumhq/atoms npm package from TypeScript atoms - #17459
Conversation
Refactors the three TypeScript atoms (get-attribute, find-elements,
is-displayed) from IIFE closures to proper ES modules with export
default, then produces two compilation targets from the same sources:
- IIFE path (language bindings): ts_project --module commonjs →
cjs-to-iife.js → browser-injectable (function(){…return fn;})()
so py/rb/java/dotnet consumers are unchanged.
- npm path: ts_project --module esnext + declaration → dist/ published
as @seleniumhq/atoms with full TypeScript type declarations.
Key changes:
* Remove outer IIFE from all three atom .ts files; add export default.
* Add cjs-to-iife.js replacing strip-trailing-semicolon.js in the
IIFE pipeline. Strips CJS boilerplate and wraps the body in an IIFE
that returns the exported default function.
* Update wrap-as-global scripts to parse CJS-compiled input instead of
asserting (function () at the start.
* Switch BUILD.bazel from js_run_binary+tsc(--module none --outFile)
to ts_project for each atom, plus a new npm_package target.
* Add tsconfig.json (esnext, declaration) and tsconfig-cjs.json for
the two compilation paths.
* Add index.ts as the package entry point.
* Promote javascript/atoms/package.json to @seleniumhq/atoms v4.45.x.
* Add get_attribute_typescript and find-elements-typescript CJS module
targets to selenium-webdriver/lib/atoms/BUILD.bazel.
All 25 Python unit tests pass; //javascript/atoms:closure-test passes.
…roject targets When multiple ts_project targets share a single tsconfig with no files/include restriction, tsc compiles all .ts files for each target. On Windows, Bazel marks outputs read-only after the first action completes; parallel actions then fail with TS5033 EPERM trying to overwrite the same files. Give each per-atom ts_project its own tsconfig that lists only the one .ts file it is responsible for, eliminating the cross-target output collision.
0c73842 to
8146e8d
Compare
npm packaging: changes needed before
|
The npm artifact was declared but not consumable. Addresses the integration review on #17459: - Drop the `require` conditions and `main` pointing at `dist/*.cjs`; no CJS compilation exists on the branch, so every `require` entry resolved to a file that is never built. Ship ESM-only and declare `engines.node >= 22.12.0`, where Node's `require(esm)` covers CommonJS consumers. - Add `index.ts` extension specifiers. Extensionless specifiers are emitted verbatim under `module: esnext`, so `import('@seleniumhq/atoms')` failed with ERR_MODULE_NOT_FOUND for every consumer. - Ship LICENSE/NOTICE, as Apache-2.0 4(a) requires. - Put `types` first in each `exports` entry; condition order is significant and resolvers take the first match. - Publish the `.ts` sources so the emitted `.d.ts.map` / `.js.map` resolve instead of pointing outside the tarball. - Drive the version from `node:version` rather than a hardcoded value six minors behind trunk. - Rename the four CommonJS build tools to `.cjs` so they no longer depend on `"type": "module"` not reaching them via runfiles staging. - Add a consumer-facing `README.npm.md`, renamed to README.md on packaging so the contributor README stays in place. - Drop the `google-closure-deps` devDependency left over from when this manifest was the private selenium-atoms build-tools package. Verified by packing the built directory and installing it: both `require` and `import` resolve, all four export paths resolve under node10/node16/bundler per @arethetypeswrong/cli, and the IIFE path for the language bindings is unchanged.
…8133) The npm package landed in #17459 but nothing published it. Wire it into the existing Node release path alongside selenium-webdriver. * node:release publishes //javascript/atoms:selenium-atoms-package.publish before selenium-webdriver.publish. The "already published" rescue is extracted into publish_npm_package so both share it. * node:verify checks both packages; node:build builds both. * setup_github_npm_auth redirects the atoms registry for the nightly GitHub Packages path. The name is already scoped so it needs no rename, but the npmjs access flag is stripped — GitHub Packages derives visibility from the repository. * Add publishConfig.access: public to javascript/atoms/package.json. Scoped packages default to restricted on npmjs, so without this the first publish is rejected. * node:version now fails if the two versions have drifted. The bump works by substituting old_version, so drift would silently leave atoms stale and only surface as a node:verify failure after the release shipped. * Convert the path/target literals to methods rather than constants. Rakefile loads this file twice (as node: and aliased as javascript:), which made constants warn on every invocation. ./go javascript:release dry-run passes end to end for both packages.
🔗 Related Issues
Builds on the Closure → TypeScript atom migrations (#17458 and siblings), which are already on trunk.
💥 What does this PR do?
Turns the three TypeScript atoms (
get-attribute,find-elements,is-displayed) into real ES modules and compiles them down two independent paths from the same sources:ts_projectwith--module commonjs, then a newcjs-to-iife.jspost-processor emits browser-injectable(function(){ … return fn; })(). Python, Ruby, Java and .NET consumers see byte-compatible output and are unchanged.ts_projectwith--module esnext,declaration,declarationMapandsourceMapintodist/, packaged as@seleniumhq/atomswith full.d.tstype declarations.Both paths type-check the same
.tssources, so the published package and the injected atoms can't drift apart.🔧 Implementation Notes
Atom sources
get-attribute.ts,find-elements.tsandis-displayed.ts; each now ends inexport default <fn>.index.tsas the package entry point, re-exporting the three atoms asgetAttribute,findElementsandisDisplayed.Build wiring (
javascript/atoms/BUILD.bazel)js_run_binary+tsc --module none --outFileinvocations withts_projecttargets.strip_trailing_semicolonbinary withcjs_to_iife, which strips the CommonJS boilerplatetscemits and wraps the remaining body in an IIFE returning the default export.wrap-*-as-global.jsscripts to parse CJS-compiled input rather than asserting the file starts with(function () {.atoms-npm-compiled(ts_project→dist/) andselenium-atoms-package(npm_package,publishable = True, taggedrelease-artifact).One tsconfig per
ts_projecttargetEach atom gets its own
tsconfig-<atom>.jsonwith a single-entryfileslist, rather than sharing onetsconfig-cjs.jsonacross all three. A shared tsconfig makes severalts_projecttargets declare the same file as an input, which Bazel materialises concurrently into the same sandbox path — on Windows that races and fails withEPERM. Per-target configs give each action a disjoint input set. (tsconfig.jsonat the package root stays shared, because onlyatoms-npm-compileduses it.)Package metadata
javascript/atoms/package.jsonis promoted to@seleniumhq/atomswithexportsentries for the package root and each individual atom.✅ Verification
bazel build //javascript/atoms:selenium-atoms-package //javascript/atoms:atoms-npm-compiledplus the three*-typescript-compiledtargets — clean.bazel build //javascript/selenium-webdriver/lib/atoms:all //rb/lib/selenium/webdriver/atoms:all— clean; the generated IIFE output still ends inreturn get; })();, so the injection path is unchanged for bindings.💡 Additional Considerations
package.jsoncurrently declares"main": "./dist/index.cjs"and a"require"condition on every export, but the npm path only emits ESM.js+.d.ts— no.cjsis produced. Either the CJS conditions should be dropped (ESM-only package) or a secondts_projectshould emit the.cjsoutputs before this is published. Flagging for a decision before release.🤖 AI assistance
🔄 Types of changes