From 55360445486b54fda16b369d5d9f15b4808ed1f0 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 27 Apr 2026 13:54:36 +0000 Subject: [PATCH 1/4] chore: drop spurious intra-fixed-group peerDependencies MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Five fixed-group packages declared `peerDependencies` on other fixed-group packages whose only usages were in spec files (or, for `@tko/lifecycle`, a type-only import that's erased at compile). With Changesets' fixed-version group plus its minor→major peer promotion, any minor in the group cascaded to a major version bump for everything — that's the v5.0 trigger from the previous release attempt, not the actual change content. Verified each by grepping for runtime imports in `src/`: | Depender | Peer(s) | Real use | |-----------------------|------------------------------------------------------------|------------------| | @tko/bind | @tko/binding.foreach | spec only | | @tko/binding.template | @tko/binding.if | spec only | | @tko/lifecycle | @tko/observable | `import type` | | @tko/utils.component | bind, binding.core, computed, provider.multi, .virtual | spec only | | @tko/utils.parser | bind, binding.core, provider.databind | spec only | Workspace-resolved specs do not need devDep declarations in the Bun monorepo. No `src/` imports are affected. Lifecycle's `import type { Observable }` is erased post-compilation; consumers who use the type already have `@tko/observable` via their own deps. Verification: - `bun run build` — all packages build clean - `bun run tsc` — type-check passes - `bunx @changesets/cli status --verbose` — reports 4.1.0 minor for all 27 fixed-group packages with current changesets, no majors https://claude.ai/code/session_01Jnv99bwWtFWFmsyL7A2cJv --- bun.lock | 21 --------------------- packages/bind/package.json | 3 --- packages/binding.template/package.json | 3 --- packages/lifecycle/package.json | 3 --- packages/utils.component/package.json | 7 ------- packages/utils.parser/package.json | 5 ----- 6 files changed, 42 deletions(-) diff --git a/bun.lock b/bun.lock index 0dbc5630a..c7637a11e 100644 --- a/bun.lock +++ b/bun.lock @@ -76,9 +76,6 @@ "@tko/provider": "^4.0.1", "@tko/utils": "^4.0.1", }, - "peerDependencies": { - "@tko/binding.foreach": "^4.0.1", - }, }, "packages/binding.component": { "name": "@tko/binding.component", @@ -130,9 +127,6 @@ "@tko/observable": "^4.0.1", "@tko/utils": "^4.0.1", }, - "peerDependencies": { - "@tko/binding.if": "^4.0.1", - }, }, "packages/builder": { "name": "@tko/builder", @@ -170,9 +164,6 @@ "@tko/computed": "^4.0.1", "@tko/utils": "^4.0.1", }, - "peerDependencies": { - "@tko/observable": "^4.0.1", - }, }, "packages/observable": { "name": "@tko/observable", @@ -276,13 +267,6 @@ "@tko/observable": "^4.0.1", "@tko/utils": "^4.0.1", }, - "peerDependencies": { - "@tko/bind": "^4.0.1", - "@tko/binding.core": "^4.0.1", - "@tko/computed": "^4.0.1", - "@tko/provider.multi": "^4.0.1", - "@tko/provider.virtual": "^4.0.1", - }, }, "packages/utils.functionrewrite": { "name": "@tko/utils.functionrewrite", @@ -307,11 +291,6 @@ "@tko/observable": "^4.0.1", "@tko/utils": "^4.0.1", }, - "peerDependencies": { - "@tko/bind": "^4.0.1", - "@tko/binding.core": "^4.0.1", - "@tko/provider.databind": "^4.0.1", - }, }, }, "packages": { diff --git a/packages/bind/package.json b/packages/bind/package.json index 2ff5d3306..57760e669 100644 --- a/packages/bind/package.json +++ b/packages/bind/package.json @@ -11,9 +11,6 @@ "@tko/utils": "^4.0.1", "@tko/builder": "^4.0.1" }, - "peerDependencies": { - "@tko/binding.foreach": "^4.0.1" - }, "files": [ "dist/" ], diff --git a/packages/binding.template/package.json b/packages/binding.template/package.json index f526228c6..62c735911 100644 --- a/packages/binding.template/package.json +++ b/packages/binding.template/package.json @@ -29,9 +29,6 @@ "@tko/observable": "^4.0.1", "@tko/utils": "^4.0.1" }, - "peerDependencies": { - "@tko/binding.if": "^4.0.1" - }, "licenses": [ { "type": "MIT", diff --git a/packages/lifecycle/package.json b/packages/lifecycle/package.json index 3a04e1849..ffc9fb4c8 100644 --- a/packages/lifecycle/package.json +++ b/packages/lifecycle/package.json @@ -5,9 +5,6 @@ "@tko/computed": "^4.0.1", "@tko/utils": "^4.0.1" }, - "peerDependencies": { - "@tko/observable": "^4.0.1" - }, "files": [ "dist/" ], diff --git a/packages/utils.component/package.json b/packages/utils.component/package.json index 94f08c45d..3479aba02 100644 --- a/packages/utils.component/package.json +++ b/packages/utils.component/package.json @@ -12,13 +12,6 @@ "@tko/observable": "^4.0.1", "@tko/utils": "^4.0.1" }, - "peerDependencies": { - "@tko/bind": "^4.0.1", - "@tko/binding.core": "^4.0.1", - "@tko/computed": "^4.0.1", - "@tko/provider.multi": "^4.0.1", - "@tko/provider.virtual": "^4.0.1" - }, "homepage": "https://tko.io", "licenses": [ { diff --git a/packages/utils.parser/package.json b/packages/utils.parser/package.json index f360fecbb..9f9f73cb1 100644 --- a/packages/utils.parser/package.json +++ b/packages/utils.parser/package.json @@ -11,11 +11,6 @@ "@tko/observable": "^4.0.1", "@tko/utils": "^4.0.1" }, - "peerDependencies": { - "@tko/bind": "^4.0.1", - "@tko/binding.core": "^4.0.1", - "@tko/provider.databind": "^4.0.1" - }, "homepage": "https://tko.io", "licenses": [ { From cc5ddf19b80ef9737ee1388dff9f54aba9378ecc Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 27 Apr 2026 14:02:31 +0000 Subject: [PATCH 2/4] chore: restore removed utils API as compat shims; land at 4.1.0 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The polyfill modernization (commits 6f4b5f2b, 517ddc14) removed four public identifiers from `@tko/utils` and one from `ko.utils`. Each was a trivial wrapper around a now-universal native API; restoring them as inline passthroughs preserves the public surface at zero behavior cost. New `packages/utils/src/compat.ts`: - `createSymbolOrString(id) => Symbol(id)` - `stringTrim(v) => String(v ?? '').trim()` - `stringStartsWith(s, p) => s.startsWith(p)` - `overwriteLengthPropertyIfSupported(fn, d) => Object.defineProperty(fn, 'length', d)` Wired through: - `packages/utils/src/index.ts` — added `export * from './compat'` - `packages/builder/src/Builder.ts` — restored `createSymbolOrString` in import list, `Utils` type, and `utils` object literal so `ko.utils.createSymbolOrString` continues to resolve Changeset updates: - `modernize-utils-dead-polyfills`: demoted from minor → patch for `@tko/utils` and `@tko/builder`. Description updated to call out the passthrough preservation. Internal probes (`useSymbols`, `functionSupportsLengthOverwrite`) had no monorepo callers and stay removed. - `fix-jsx-clean-teardown-race`: promoted from patch → minor for `@tko/utils.jsx`. Adding `options.jsxCleanBatchSize` is a public option — minor by strict semver. Cascades the fixed group to 4.1.0. `bunx @changesets/cli status --verbose` now reports all 27 fixed-group packages bumping to 4.1.0 minor, zero majors. Verification: - `bun run build` clean - `bun run tsc` clean - `createSymbolOrString` confirmed in compiled `dist/compat.js`, bundled `builds/reference/dist/browser.js`, and the `ko.utils` object literal at the same site https://claude.ai/code/session_01Jnv99bwWtFWFmsyL7A2cJv --- .changeset/fix-jsx-clean-teardown-race.md | 2 +- .changeset/modernize-utils-dead-polyfills.md | 28 +++++++++++++------- packages/builder/src/Builder.ts | 3 +++ packages/utils/src/compat.ts | 23 ++++++++++++++++ packages/utils/src/index.ts | 1 + 5 files changed, 47 insertions(+), 10 deletions(-) create mode 100644 packages/utils/src/compat.ts diff --git a/.changeset/fix-jsx-clean-teardown-race.md b/.changeset/fix-jsx-clean-teardown-race.md index 1479c19c6..750af01a4 100644 --- a/.changeset/fix-jsx-clean-teardown-race.md +++ b/.changeset/fix-jsx-clean-teardown-race.md @@ -1,5 +1,5 @@ --- -"@tko/utils.jsx": patch +"@tko/utils.jsx": minor --- Add `options.jsxCleanBatchSize` (default `1000`) controlling JSX node cleanup diff --git a/.changeset/modernize-utils-dead-polyfills.md b/.changeset/modernize-utils-dead-polyfills.md index 49a9fd19f..99e1026cf 100644 --- a/.changeset/modernize-utils-dead-polyfills.md +++ b/.changeset/modernize-utils-dead-polyfills.md @@ -1,28 +1,34 @@ --- -"@tko/utils": minor +"@tko/utils": patch "@tko/utils.parser": patch "@tko/observable": patch "@tko/binding.core": patch "@tko/binding.foreach": patch "@tko/computed": patch "@tko/lifecycle": patch -"@tko/builder": minor +"@tko/builder": patch --- Drop dead polyfill probes from `@tko/utils` Removes runtime feature detection for capabilities that all supported runtimes -(modern browsers, Node, Bun, happy-dom) already expose unconditionally: +(modern browsers, Node, Bun, happy-dom) already expose unconditionally. The +public API surface is preserved as one-line passthroughs in +`packages/utils/src/compat.ts` so existing consumers continue to work; these +shims are slated for removal in the next major. - `functionSupportsLengthOverwrite` + `overwriteLengthPropertyIfSupported` — `Object.defineProperty(fn, 'length', …)` has worked since IE9. Call sites - in `@tko/observable` now invoke `Object.defineProperty` directly. + in `@tko/observable` now invoke `Object.defineProperty` directly. The + internal probe is gone; `overwriteLengthPropertyIfSupported` is preserved + on `@tko/utils` exports as an inline `Object.defineProperty` call. - `useSymbols` + `createSymbolOrString` — `Symbol` is always defined; call - sites now use `Symbol(identifier)` directly. `createSymbolOrString` is no - longer exposed on `ko.utils` (public API removal — minor bump for - `@tko/utils` and `@tko/builder`). -- `stringTrim` + `stringStartsWith` — removed; call sites use - `String(value ?? '').trim()` / `value.startsWith(prefix)` inline. + sites now use `Symbol(identifier)` directly. `createSymbolOrString` is + preserved as `s => Symbol(s)` on both `@tko/utils` exports and + `ko.utils.createSymbolOrString`. +- `stringTrim` + `stringStartsWith` — call sites use `String(value ?? '') + .trim()` / `value.startsWith(prefix)` inline. Both names remain exported + from `@tko/utils` as inline passthroughs. - `toggleDomNodeCssClass` SVGAnimatedString fallback — `classList` is available on every supported `Element` (including SVG since SVG2). - `parseJson` no longer routes through `stringTrim`; it trims inline when the @@ -31,3 +37,7 @@ Removes runtime feature detection for capabilities that all supported runtimes `packages/utils.parser/src/preparse.ts` also guards `str.match(bindingToken)` against the `null` return case using `?? []` — previously relied on the match never returning `null` for the transformed input. + +Patch-level for all packages: zero observable surface change for consumers +not reaching into internal probes (`useSymbols`, `functionSupportsLengthOverwrite`), +which had no monorepo callers. diff --git a/packages/builder/src/Builder.ts b/packages/builder/src/Builder.ts index 3295ba213..a5e1da4be 100644 --- a/packages/builder/src/Builder.ts +++ b/packages/builder/src/Builder.ts @@ -17,6 +17,7 @@ import { cleanNode, cloneNodes, compareArrays, + createSymbolOrString, domData, extend, memoization, @@ -115,6 +116,7 @@ export type Utils = { arrayRemoveItem: typeof arrayRemoveItem cloneNodes: typeof cloneNodes compareArrays: typeof compareArrays + createSymbolOrString: typeof createSymbolOrString domData: typeof domData domNodeDisposal: typeof domNodeDisposal extend: typeof extend @@ -147,6 +149,7 @@ const utils: Utils = { arrayRemoveItem, cloneNodes, compareArrays, + createSymbolOrString, domData, domNodeDisposal, extend, diff --git a/packages/utils/src/compat.ts b/packages/utils/src/compat.ts new file mode 100644 index 000000000..2a9bbf3a9 --- /dev/null +++ b/packages/utils/src/compat.ts @@ -0,0 +1,23 @@ +// Compat passthroughs preserving the public @tko/utils API after the +// post-Symbol/post-IE9 polyfill removals. Each function delegates to a +// native API; kept so consumers importing these names continue to work. +// Removal slated for the next major version. + +export function createSymbolOrString(identifier: string): symbol { + return Symbol(identifier) +} + +export function stringTrim(value: any): string { + return String(value ?? '').trim() +} + +export function stringStartsWith(value: string, prefix: string): boolean { + return value.startsWith(prefix) +} + +export function overwriteLengthPropertyIfSupported( + fn: Function, + descriptor: PropertyDescriptor, +): void { + Object.defineProperty(fn, 'length', descriptor) +} diff --git a/packages/utils/src/index.ts b/packages/utils/src/index.ts index a55923b00..607e4121f 100644 --- a/packages/utils/src/index.ts +++ b/packages/utils/src/index.ts @@ -6,6 +6,7 @@ export * from './array' export * from './async' +export * from './compat' export * from './error' export * from './object' export * from './string' From 52b008392a64423ba9277ef5bf5f4eb3c49daf06 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 27 Apr 2026 14:04:05 +0000 Subject: [PATCH 3/4] chore(utils): mark compat shims @deprecated with native-API replacements MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit JSDoc on each passthrough so IDEs strike through usage and signal the native equivalent: - createSymbolOrString → Symbol(identifier) - stringTrim → String(value ?? '').trim() - stringStartsWith → String.prototype.startsWith - overwriteLengthPropertyIfSupported → Object.defineProperty(fn, 'length', d) All four scheduled for removal in the next major. https://claude.ai/code/session_01Jnv99bwWtFWFmsyL7A2cJv --- packages/utils/src/compat.ts | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/packages/utils/src/compat.ts b/packages/utils/src/compat.ts index 2a9bbf3a9..077afbf6b 100644 --- a/packages/utils/src/compat.ts +++ b/packages/utils/src/compat.ts @@ -1,20 +1,34 @@ // Compat passthroughs preserving the public @tko/utils API after the // post-Symbol/post-IE9 polyfill removals. Each function delegates to a // native API; kept so consumers importing these names continue to work. -// Removal slated for the next major version. +// All entries here are slated for removal in the next major version. +/** + * @deprecated Use `Symbol(identifier)` directly. Will be removed in a future major. + */ export function createSymbolOrString(identifier: string): symbol { return Symbol(identifier) } +/** + * @deprecated Use `String(value ?? '').trim()` directly (or `String.prototype.trim` + * when the input is known to be a string). Will be removed in a future major. + */ export function stringTrim(value: any): string { return String(value ?? '').trim() } +/** + * @deprecated Use `String.prototype.startsWith` directly. Will be removed in a future major. + */ export function stringStartsWith(value: string, prefix: string): boolean { return value.startsWith(prefix) } +/** + * @deprecated Use `Object.defineProperty(fn, 'length', descriptor)` directly. + * Will be removed in a future major. + */ export function overwriteLengthPropertyIfSupported( fn: Function, descriptor: PropertyDescriptor, From 8c35203f74e819b0b6e35e396e34f1921655e9e9 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 27 Apr 2026 14:31:42 +0000 Subject: [PATCH 4/4] chore: address PR review on 4.1.0 prep MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Three fixes from review on #371: 1. **stringStartsWith null safety (P1, codex)** — original `stringStartsWith(string, startsWith)` did `string = string || ''`, coercing falsy/null/undefined to empty so the call returned `false` without throwing. The shim was calling `.startsWith` on the raw value and would throw on `null`/`undefined`. Restored with `(value ?? '') .startsWith(prefix)`. `stringTrim` already handled null via `String(value ?? '').trim()` and stays as-is. 2. **Lifecycle's @tko/observable (P2, codex)** — `LifeCycle.subscribe` has signature `subscribe(observable: Observable, ...)`, where `Observable` is imported from `@tko/observable`. The type appears in the emitted `.d.ts`, so consumers under strict-isolation installs (pnpm-style, yarn pnp) need `@tko/observable` resolvable directly rather than transitively through `@tko/computed`. Added to `dependencies` (correct home for type-imports in public surface; was overkill as a peerDependency). 3. **Trailing-comma on overwriteLengthPropertyIfSupported (P2, coderabbitai)** — Biome's actual complaint was that the param list fits on one line under the 120-col limit and so should be collapsed, not the comma per se (Biome enforces trailing commas in genuinely multi-line lists by default). Collapsed to single line. Verification: - `bun run build` clean - `bun run tsc` clean - `bunx @biomejs/biome check` clean - `bunx @changesets/cli status` still 4.1.0 minor across the fixed group https://claude.ai/code/session_01Jnv99bwWtFWFmsyL7A2cJv --- packages/lifecycle/package.json | 1 + packages/utils/src/compat.ts | 7 ++----- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/packages/lifecycle/package.json b/packages/lifecycle/package.json index ffc9fb4c8..8afc1b335 100644 --- a/packages/lifecycle/package.json +++ b/packages/lifecycle/package.json @@ -3,6 +3,7 @@ "module": "dist/index.js", "dependencies": { "@tko/computed": "^4.0.1", + "@tko/observable": "^4.0.1", "@tko/utils": "^4.0.1" }, "files": [ diff --git a/packages/utils/src/compat.ts b/packages/utils/src/compat.ts index 077afbf6b..ca5bc4693 100644 --- a/packages/utils/src/compat.ts +++ b/packages/utils/src/compat.ts @@ -22,16 +22,13 @@ export function stringTrim(value: any): string { * @deprecated Use `String.prototype.startsWith` directly. Will be removed in a future major. */ export function stringStartsWith(value: string, prefix: string): boolean { - return value.startsWith(prefix) + return (value ?? '').startsWith(prefix) } /** * @deprecated Use `Object.defineProperty(fn, 'length', descriptor)` directly. * Will be removed in a future major. */ -export function overwriteLengthPropertyIfSupported( - fn: Function, - descriptor: PropertyDescriptor, -): void { +export function overwriteLengthPropertyIfSupported(fn: Function, descriptor: PropertyDescriptor): void { Object.defineProperty(fn, 'length', descriptor) }