From 7e6fa5156882bd45795a0d958a4a07018bd483bf Mon Sep 17 00:00:00 2001 From: Seth Herr Date: Sat, 25 Jul 2026 08:45:13 -0700 Subject: [PATCH 1/3] Bundle luxon into @bikeindex/time-localizer, release 0.4.0 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The published package left luxon as an external import, so dist/index.js shipped a bare `import{DateTime}from"luxon"` specifier for the consumer to resolve. This contradicted the README, which already claimed luxon was bundled. bike_index uses importmap-rails with no bundler, so that bare specifier meant a second CDN pin and two chained cross-origin round trips (3.3 KB, then 254 KB of unminified luxon) gating every Stimulus controller on every page, since both are static imports. - Drop --external:luxon from the esbuild build; dist/index.js is now self-contained at 72.4 KB minified. - Delete peerDependencies — luxon stays in devDependencies, which is all esbuild needs at build time. - Bump to 0.4.0. main, exports and files still point at dist/index.js, and index.js is unchanged, so the public API and pinned artifact path are stable. Co-Authored-By: Claude --- package-lock.json | 7 ++----- package.json | 7 ++----- 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/package-lock.json b/package-lock.json index f09631a..e55f13c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,21 +1,18 @@ { "name": "@bikeindex/time-localizer", - "version": "0.3.0", + "version": "0.4.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@bikeindex/time-localizer", - "version": "0.3.0", + "version": "0.4.0", "license": "MIT", "devDependencies": { "esbuild": "^0.28.0", "jsdom": "^26.0.0", "luxon": "^3.0.0", "vitest": "^3.0.0" - }, - "peerDependencies": { - "luxon": "^3.0.0" } }, "node_modules/@asamuzakjp/css-color": { diff --git a/package.json b/package.json index 76871b2..4dabb80 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@bikeindex/time-localizer", - "version": "0.3.0", + "version": "0.4.0", "description": "Localizes time elements to the user's timezone using Luxon", "type": "module", "main": "dist/index.js", @@ -11,13 +11,10 @@ "dist/index.js" ], "scripts": { - "build": "esbuild index.js --bundle --format=esm --minify --external:luxon --outfile=dist/index.js", + "build": "esbuild index.js --bundle --format=esm --minify --outfile=dist/index.js", "prepublishOnly": "npm run build", "test": "vitest run" }, - "peerDependencies": { - "luxon": "^3.0.0" - }, "devDependencies": { "esbuild": "^0.28.0", "jsdom": "^26.0.0", From 5941aaf7548a3a96fb4e0bd4d3a9e1eaf0bd6120 Mon Sep 17 00:00:00 2001 From: Seth Herr Date: Sat, 25 Jul 2026 09:25:02 -0700 Subject: [PATCH 2/3] Ship a standalone bundle alongside the external build MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bundling luxon unconditionally would have regressed consumers that use luxon directly: two copies means two module-scoped Settings objects, so their Settings.defaultLocale / defaultZone / now would silently stop applying to time-localizer's output. Verified with luxon 3.7.2 — Settings.defaultLocale = 'fr' rendered "2 nov." from the consumer's copy but "Nov 2" from the bundled one, with no error. Ship both builds of the same source instead: - dist/index.js keeps luxon external (peerDependency restored), so bundler consumers keep one deduped copy and their Settings apply. - dist/index.bundle.js inlines luxon for consumers with no bundler, reachable as @bikeindex/time-localizer/bundle or by file path. - README documents which build to use and warns against pairing the bundled one with your own luxon. Both are outputs of one source file, rebuilt together by prepublishOnly. Co-Authored-By: Claude --- README.md | 13 +++++++++++-- package.json | 13 ++++++++++--- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 847c4f6..5920b9a 100644 --- a/README.md +++ b/README.md @@ -59,9 +59,18 @@ end ## npm package -This repo also publishes `@bikeindex/time-localizer`, an npm package for localizing time elements in the browser. Luxon is bundled into the published package, so consumers don't need to install it separately. +This repo also publishes `@bikeindex/time-localizer`, an npm package for localizing time elements in the browser. It ships two builds of the same source: -To publish a new version: update the version in `package.json`, then run `npm publish` from the repo root (requires npm login with access to the `@bikeindex` scope). The `prepublishOnly` script automatically builds `dist/index.js` before publishing. +| Build | Luxon | Use when | +| --- | --- | --- | +| `dist/index.js` (default) | external — install it yourself | You have a bundler. Luxon stays deduped with your own copy, so `Settings.defaultLocale`, `Settings.now` etc. apply to both. | +| `dist/index.bundle.js` | bundled in | You have no bundler (e.g. importmap-rails). One request, nothing to resolve. | + +Import the default as `@bikeindex/time-localizer` and the standalone as `@bikeindex/time-localizer/bundle`, or reference either file path directly over a CDN. + +Don't use the bundled build alongside your own Luxon: you'd ship two copies, and because Luxon's `Settings` are module-scoped, your global config would silently apply to only one of them. + +To publish a new version: update the version in `package.json`, then run `npm publish` from the repo root (requires npm login with access to the `@bikeindex` scope). The `prepublishOnly` script builds both artifacts before publishing. ## Releasing diff --git a/package.json b/package.json index 4dabb80..7bb5c49 100644 --- a/package.json +++ b/package.json @@ -5,16 +5,23 @@ "type": "module", "main": "dist/index.js", "exports": { - ".": "./dist/index.js" + ".": "./dist/index.js", + "./bundle": "./dist/index.bundle.js" }, "files": [ - "dist/index.js" + "dist/index.js", + "dist/index.bundle.js" ], "scripts": { - "build": "esbuild index.js --bundle --format=esm --minify --outfile=dist/index.js", + "build": "npm run build:esm && npm run build:bundle", + "build:esm": "esbuild index.js --bundle --format=esm --minify --external:luxon --outfile=dist/index.js", + "build:bundle": "esbuild index.js --bundle --format=esm --minify --outfile=dist/index.bundle.js", "prepublishOnly": "npm run build", "test": "vitest run" }, + "peerDependencies": { + "luxon": "^3.0.0" + }, "devDependencies": { "esbuild": "^0.28.0", "jsdom": "^26.0.0", From c823e873f24abb11ccfc97b90cf785ce6820d8b1 Mon Sep 17 00:00:00 2001 From: Seth Herr Date: Sat, 25 Jul 2026 09:25:38 -0700 Subject: [PATCH 3/3] Sync package-lock.json with the restored luxon peerDependency The lockfile was regenerated when peerDependencies was briefly removed and not refreshed when it came back, so it no longer matched package.json. Co-Authored-By: Claude --- package-lock.json | 3 +++ 1 file changed, 3 insertions(+) diff --git a/package-lock.json b/package-lock.json index e55f13c..e59c4b6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,6 +13,9 @@ "jsdom": "^26.0.0", "luxon": "^3.0.0", "vitest": "^3.0.0" + }, + "peerDependencies": { + "luxon": "^3.0.0" } }, "node_modules/@asamuzakjp/css-color": {