diff --git a/.changeset/fix-deep-extend-prototype-pollution.md b/.changeset/fix-deep-extend-prototype-pollution.md new file mode 100644 index 00000000..83daf394 --- /dev/null +++ b/.changeset/fix-deep-extend-prototype-pollution.md @@ -0,0 +1,5 @@ +--- +"@cleverbrush/deep": patch +--- + +Prevent `deepExtend()` from merging prototype-polluting keys. diff --git a/.changeset/xpenser-framework-affordances.md b/.changeset/xpenser-framework-affordances.md deleted file mode 100644 index f2c92ef7..00000000 --- a/.changeset/xpenser-framework-affordances.md +++ /dev/null @@ -1,27 +0,0 @@ ---- -'@cleverbrush/client': minor -'@cleverbrush/env': minor -'@cleverbrush/knex-schema': minor -'@cleverbrush/orm': minor -'@cleverbrush/orm-cli': minor -'@cleverbrush/server': minor ---- - -Add framework affordances discovered while reviewing Xpenser: - -- `@cleverbrush/env`: add `envBoolean()` for environment-style boolean values - such as `1`, `0`, `yes`, `no`, `on`, and `off`. -- `@cleverbrush/server`: parse `application/x-www-form-urlencoded` request - bodies by default, add `ActionResult.raw()`, and allow ordered - authentication fallback with `trySchemes`. -- `@cleverbrush/client`: add `externalCacheTags()` to - `@cleverbrush/client/cache` for framework-agnostic external cache tag - invalidation, including Next.js `revalidateTag()` as one supported callback. -- `@cleverbrush/knex-schema` / `@cleverbrush/orm`: add - `InferDatabaseRow` / `InferDatabaseValue` row typing helpers and support raw - update expressions plus conditional `where` callbacks in - `onConflict().merge()`. -- `@cleverbrush/orm-cli`: add read-only `cb-orm validate` for live schema drift - checks. - -Docs and package READMEs were updated; see https://docs.cleverbrush.com. diff --git a/libs/async/CHANGELOG.md b/libs/async/CHANGELOG.md index a166c795..8d8990c3 100644 --- a/libs/async/CHANGELOG.md +++ b/libs/async/CHANGELOG.md @@ -1,5 +1,7 @@ # @cleverbrush/async +## 4.4.0 + ## 4.3.2 ### Patch Changes diff --git a/libs/async/package.json b/libs/async/package.json index 6e398b81..246b744f 100644 --- a/libs/async/package.json +++ b/libs/async/package.json @@ -38,5 +38,5 @@ }, "type": "module", "types": "./dist/index.d.ts", - "version": "4.3.2" + "version": "4.4.0" } diff --git a/libs/auth/CHANGELOG.md b/libs/auth/CHANGELOG.md index c3b20f6f..ccd259d2 100644 --- a/libs/auth/CHANGELOG.md +++ b/libs/auth/CHANGELOG.md @@ -1,5 +1,11 @@ # @cleverbrush/auth +## 4.4.0 + +### Patch Changes + +- @cleverbrush/schema@4.4.0 + ## 4.3.2 ### Patch Changes diff --git a/libs/auth/package.json b/libs/auth/package.json index c1382e4b..e106c40f 100644 --- a/libs/auth/package.json +++ b/libs/auth/package.json @@ -5,7 +5,7 @@ "email": "andrew_zol@cleverbrush.com" }, "dependencies": { - "@cleverbrush/schema": "^4.3.2" + "@cleverbrush/schema": "^4.4.0" }, "description": "Transport-agnostic authentication & authorization — JWT, cookies, role-based policies, schema-typed principals", "files": [ @@ -43,5 +43,5 @@ }, "type": "module", "types": "./dist/index.d.ts", - "version": "4.3.2" + "version": "4.4.0" } diff --git a/libs/client/CHANGELOG.md b/libs/client/CHANGELOG.md index 50f9a40c..7ef8d9da 100644 --- a/libs/client/CHANGELOG.md +++ b/libs/client/CHANGELOG.md @@ -1,5 +1,34 @@ # @cleverbrush/client +## 4.4.0 + +### Minor Changes + +- c75bff4: Add framework affordances discovered while reviewing Xpenser: + + - `@cleverbrush/env`: add `envBoolean()` for environment-style boolean values + such as `1`, `0`, `yes`, `no`, `on`, and `off`. + - `@cleverbrush/server`: parse `application/x-www-form-urlencoded` request + bodies by default, add `ActionResult.raw()`, and allow ordered + authentication fallback with `trySchemes`. + - `@cleverbrush/client`: add `externalCacheTags()` to + `@cleverbrush/client/cache` for framework-agnostic external cache tag + invalidation, including Next.js `revalidateTag()` as one supported callback. + - `@cleverbrush/knex-schema` / `@cleverbrush/orm`: add + `InferDatabaseRow` / `InferDatabaseValue` row typing helpers and support raw + update expressions plus conditional `where` callbacks in + `onConflict().merge()`. + - `@cleverbrush/orm-cli`: add read-only `cb-orm validate` for live schema drift + checks. + + Docs and package READMEs were updated; see https://docs.cleverbrush.com. + +### Patch Changes + +- Updated dependencies [c75bff4] + - @cleverbrush/server@4.4.0 + - @cleverbrush/schema@4.4.0 + ## 4.3.2 ### Patch Changes diff --git a/libs/client/package.json b/libs/client/package.json index d3cf9f7d..b6ac4e98 100644 --- a/libs/client/package.json +++ b/libs/client/package.json @@ -5,8 +5,8 @@ "email": "andrew_zol@cleverbrush.com" }, "dependencies": { - "@cleverbrush/schema": "^4.3.2", - "@cleverbrush/server": "^4.3.2" + "@cleverbrush/schema": "^4.4.0", + "@cleverbrush/server": "^4.4.0" }, "devDependencies": { "@tanstack/react-query": "^5.75.0", @@ -102,5 +102,5 @@ }, "type": "module", "types": "./dist/index.d.ts", - "version": "4.3.2" + "version": "4.4.0" } diff --git a/libs/deep/CHANGELOG.md b/libs/deep/CHANGELOG.md index 6eb1332e..d5255f6c 100644 --- a/libs/deep/CHANGELOG.md +++ b/libs/deep/CHANGELOG.md @@ -1,5 +1,7 @@ # @cleverbrush/deep +## 4.4.0 + ## 4.3.2 ### Patch Changes diff --git a/libs/deep/README.md b/libs/deep/README.md index 62358e91..2149c114 100644 --- a/libs/deep/README.md +++ b/libs/deep/README.md @@ -56,6 +56,7 @@ deepEqual([1, 2, 3], [3, 1, 2], { disregardArrayOrder: true }); Deeply merges multiple objects. Works like `Object.assign`, but recursively merges nested objects instead of overwriting them. All arguments must be non-null objects. Returns a new object that is the deep merge of all provided objects. +Keys that can mutate the prototype chain (`__proto__`, `constructor`, and `prototype`) are ignored. ```typescript import { deepExtend } from '@cleverbrush/deep'; @@ -156,4 +157,3 @@ const hash = HashObject({ name: 'John', age: 30 }); ## License BSD-3-Clause - diff --git a/libs/deep/package.json b/libs/deep/package.json index 5f9836be..929f05b9 100644 --- a/libs/deep/package.json +++ b/libs/deep/package.json @@ -37,5 +37,5 @@ }, "type": "module", "types": "./dist/index.d.ts", - "version": "4.3.2" + "version": "4.4.0" } diff --git a/libs/deep/src/deepExtend.test.ts b/libs/deep/src/deepExtend.test.ts index 1b9be0b9..0ccc4116 100644 --- a/libs/deep/src/deepExtend.test.ts +++ b/libs/deep/src/deepExtend.test.ts @@ -70,3 +70,96 @@ test('deepExtend - 13', () => { a: null }); }); + +test('deepExtend skips top-level __proto__ keys', () => { + removePollutedMarker(); + + try { + const payload = JSON.parse( + '{"__proto__":{"polluted":"pp"},"safe":"ok"}' + ) as Record; + + const result = deepExtend({}, payload) as Record; + + expect(result.safe).toBe('ok'); + expect(Object.hasOwn(result, '__proto__')).toBe(false); + expect(({} as any).polluted).toBeUndefined(); + } finally { + removePollutedMarker(); + } +}); + +test('deepExtend skips nested __proto__ keys', () => { + removePollutedMarker(); + + try { + const payload = JSON.parse( + '{"a":{"__proto__":{"polluted":"pp"},"safe":1}}' + ) as any; + + const result = deepExtend({ a: {} }, payload) as any; + + expect(result.a.safe).toBe(1); + expect(Object.hasOwn(result.a, '__proto__')).toBe(false); + expect(({} as any).polluted).toBeUndefined(); + } finally { + removePollutedMarker(); + } +}); + +test('deepExtend skips constructor and prototype keys', () => { + removePollutedMarker(); + + try { + const payload = JSON.parse( + '{"constructor":{"prototype":{"polluted":true}},' + + '"prototype":{"polluted":true},"safe":"ok"}' + ) as Record; + + const result = deepExtend({}, payload) as Record; + + expect(result.safe).toBe('ok'); + expect(Object.hasOwn(result, 'constructor')).toBe(false); + expect(Object.hasOwn(result, 'prototype')).toBe(false); + expect(({} as any).polluted).toBeUndefined(); + } finally { + removePollutedMarker(); + } +}); + +test('deepExtend filters unsafe keys from a single source object', () => { + removePollutedMarker(); + + try { + const payload = JSON.parse( + '{"__proto__":{"polluted":"pp"},"safe":"ok"}' + ) as Record; + + const result = deepExtend(payload) as Record; + + expect(result).not.toBe(payload); + expect(result.safe).toBe('ok'); + expect(Object.hasOwn(result, '__proto__')).toBe(false); + expect(({} as any).polluted).toBeUndefined(); + } finally { + removePollutedMarker(); + } +}); + +test('deepExtend does not recurse into inherited target properties', () => { + const inheritedRetry = { maxRetries: 1 }; + const options = Object.create({ retry: inheritedRetry }); + + const result = deepExtend( + { options }, + { options: { retry: { minDelay: 10 } } } + ) as any; + + expect(inheritedRetry).toEqual({ maxRetries: 1 }); + expect(result.options.retry).toEqual({ minDelay: 10 }); + expect(Object.hasOwn(result.options, 'retry')).toBe(true); +}); + +function removePollutedMarker(): void { + delete (Object.prototype as { polluted?: unknown }).polluted; +} diff --git a/libs/deep/src/deepExtend.ts b/libs/deep/src/deepExtend.ts index fc860b3b..33c98556 100644 --- a/libs/deep/src/deepExtend.ts +++ b/libs/deep/src/deepExtend.ts @@ -1,23 +1,40 @@ +type UnsafeMergeKey = '__proto__' | 'constructor' | 'prototype'; + +type SafeMergeProps = Omit; + +type SafeProp = K extends keyof SafeMergeProps + ? SafeMergeProps[K] + : never; + /** Properties that exist in both `T1` and `T2`, typed as `T2`'s version. */ export type CommonProps = { - [k in keyof T1 & keyof T2]: T1[k] extends never + [k in keyof SafeMergeProps & keyof SafeMergeProps]: SafeProp< + T1, + k + > extends never ? never - : T2[k] extends never + : SafeProp extends never ? never - : T2[k]; + : SafeProp; }; /** Properties present in `T1` but not in `T2`. */ -export type PropsInFirstOnly = Omit; +export type PropsInFirstOnly = Omit< + SafeMergeProps, + keyof SafeMergeProps +>; /** Recursively merges two object types. Matching keys are merged; unique keys are kept. */ export type MergeTwo = PropsInFirstOnly & PropsInFirstOnly & { - [k in keyof CommonProps]: T1[k] extends Record - ? T2[k] extends Record - ? MergeTwo - : T2[k] - : T2[k]; + [k in keyof CommonProps]: SafeProp extends Record< + string, + unknown + > + ? SafeProp extends Record + ? MergeTwo, SafeProp> + : SafeProp + : SafeProp; }; /** Recursively merges a tuple of object types from left to right. */ @@ -26,7 +43,7 @@ export type Merge = T['length'] extends 3 : T['length'] extends 2 ? MergeTwo : T['length'] extends 1 - ? T[0] + ? SafeMergeProps : T extends [...infer K, infer PL, infer L] ? Merge<[Merge<[...K]>, MergeTwo]> : never; @@ -34,6 +51,8 @@ export type Merge = T['length'] extends 3 /** * Deep-merges multiple objects into one. Later values override earlier ones; * nested objects are merged recursively rather than replaced. + * Prototype-polluting keys (`__proto__`, `constructor`, and `prototype`) are + * ignored. * * @example * ```ts @@ -51,7 +70,6 @@ export const deepExtend = ((...rest) => { if (rest.length === 0) throw new Error('no arguments'); if (typeof rest[0] !== 'object' || rest[0] === null) throw new Error('not a non-null object'); - if (rest.length === 1) return rest[0]; const result = {}; @@ -59,20 +77,23 @@ export const deepExtend = ((...rest) => { const keys = Object.keys(o2); for (let i = 0; i < keys.length; i++) { + const key = keys[i]; + if (isUnsafeMergeKey(key)) continue; + if ( - !Reflect.has(o1, keys[i]) || + !Object.hasOwn(o1, key) || !( - typeof o1[keys[i]] === 'object' && - o1[keys[i]] !== null && - typeof o2[keys[i]] === 'object' + typeof o1[key] === 'object' && + o1[key] !== null && + typeof o2[key] === 'object' ) ) { - o1[keys[i]] = o2[keys[i]]; + o1[key] = o2[key]; } else { - if (o1[keys[i]] == null || o2[keys[i]] == null) { - o1[keys[i]] = o2[keys[i]]; + if (o1[key] == null || o2[key] == null) { + o1[key] = o2[key]; } else { - extendObject(o1[keys[i]], o2[keys[i]]); + extendObject(o1[key], o2[key]); } } } @@ -88,3 +109,7 @@ export const deepExtend = ((...rest) => { return result; }) as (...args: T) => Merge; + +function isUnsafeMergeKey(key: string): boolean { + return key === '__proto__' || key === 'constructor' || key === 'prototype'; +} diff --git a/libs/di/CHANGELOG.md b/libs/di/CHANGELOG.md index 80dc921a..f9370c75 100644 --- a/libs/di/CHANGELOG.md +++ b/libs/di/CHANGELOG.md @@ -1,5 +1,11 @@ # @cleverbrush/di +## 4.4.0 + +### Patch Changes + +- @cleverbrush/schema@4.4.0 + ## 4.3.2 ### Patch Changes diff --git a/libs/di/package.json b/libs/di/package.json index f7ffa01c..a4de7c04 100644 --- a/libs/di/package.json +++ b/libs/di/package.json @@ -5,7 +5,7 @@ "email": "andrew_zol@cleverbrush.com" }, "dependencies": { - "@cleverbrush/schema": "^4.3.2" + "@cleverbrush/schema": "^4.4.0" }, "description": ".NET-style dependency injection container for TypeScript — schema-driven service registration, three lifetimes, function injection", "files": [ @@ -43,5 +43,5 @@ }, "type": "module", "types": "./dist/index.d.ts", - "version": "4.3.2" + "version": "4.4.0" } diff --git a/libs/env/CHANGELOG.md b/libs/env/CHANGELOG.md index 0371c50a..5a526fde 100644 --- a/libs/env/CHANGELOG.md +++ b/libs/env/CHANGELOG.md @@ -1,5 +1,32 @@ # @cleverbrush/env +## 4.4.0 + +### Minor Changes + +- c75bff4: Add framework affordances discovered while reviewing Xpenser: + + - `@cleverbrush/env`: add `envBoolean()` for environment-style boolean values + such as `1`, `0`, `yes`, `no`, `on`, and `off`. + - `@cleverbrush/server`: parse `application/x-www-form-urlencoded` request + bodies by default, add `ActionResult.raw()`, and allow ordered + authentication fallback with `trySchemes`. + - `@cleverbrush/client`: add `externalCacheTags()` to + `@cleverbrush/client/cache` for framework-agnostic external cache tag + invalidation, including Next.js `revalidateTag()` as one supported callback. + - `@cleverbrush/knex-schema` / `@cleverbrush/orm`: add + `InferDatabaseRow` / `InferDatabaseValue` row typing helpers and support raw + update expressions plus conditional `where` callbacks in + `onConflict().merge()`. + - `@cleverbrush/orm-cli`: add read-only `cb-orm validate` for live schema drift + checks. + + Docs and package READMEs were updated; see https://docs.cleverbrush.com. + +### Patch Changes + +- @cleverbrush/deep@4.4.0 + ## 4.3.2 ### Patch Changes diff --git a/libs/env/package.json b/libs/env/package.json index 97708e36..caaa0087 100644 --- a/libs/env/package.json +++ b/libs/env/package.json @@ -5,7 +5,7 @@ "email": "andrew_zol@cleverbrush.com" }, "dependencies": { - "@cleverbrush/deep": "^4.3.2" + "@cleverbrush/deep": "^4.4.0" }, "peerDependencies": { "@cleverbrush/schema": "^4.0.0" @@ -50,5 +50,5 @@ "@types/node": "^25.4.0" }, "types": "./dist/index.d.ts", - "version": "4.3.2" + "version": "4.4.0" } diff --git a/libs/knex-clickhouse/CHANGELOG.md b/libs/knex-clickhouse/CHANGELOG.md index 11067c2e..478ac1f6 100644 --- a/libs/knex-clickhouse/CHANGELOG.md +++ b/libs/knex-clickhouse/CHANGELOG.md @@ -1,5 +1,12 @@ # @cleverbrush/knex-clickhouse +## 4.4.0 + +### Patch Changes + +- @cleverbrush/deep@4.4.0 +- @cleverbrush/async@4.4.0 + ## 4.3.2 ### Patch Changes diff --git a/libs/knex-clickhouse/package.json b/libs/knex-clickhouse/package.json index 3494ffc1..ab454ac4 100644 --- a/libs/knex-clickhouse/package.json +++ b/libs/knex-clickhouse/package.json @@ -5,8 +5,8 @@ "email": "andrew_zol@cleverbrush.com" }, "dependencies": { - "@cleverbrush/async": "^4.3.2", - "@cleverbrush/deep": "^4.3.2", + "@cleverbrush/async": "^4.4.0", + "@cleverbrush/deep": "^4.4.0", "@clickhouse/client": "^1.18.2" }, "peerDependencies": { @@ -45,5 +45,5 @@ }, "type": "module", "types": "./dist/index.d.ts", - "version": "4.3.2" + "version": "4.4.0" } diff --git a/libs/knex-schema/CHANGELOG.md b/libs/knex-schema/CHANGELOG.md index b7e262eb..f3d5f232 100644 --- a/libs/knex-schema/CHANGELOG.md +++ b/libs/knex-schema/CHANGELOG.md @@ -1,5 +1,32 @@ # @cleverbrush/knex-schema +## 4.4.0 + +### Minor Changes + +- c75bff4: Add framework affordances discovered while reviewing Xpenser: + + - `@cleverbrush/env`: add `envBoolean()` for environment-style boolean values + such as `1`, `0`, `yes`, `no`, `on`, and `off`. + - `@cleverbrush/server`: parse `application/x-www-form-urlencoded` request + bodies by default, add `ActionResult.raw()`, and allow ordered + authentication fallback with `trySchemes`. + - `@cleverbrush/client`: add `externalCacheTags()` to + `@cleverbrush/client/cache` for framework-agnostic external cache tag + invalidation, including Next.js `revalidateTag()` as one supported callback. + - `@cleverbrush/knex-schema` / `@cleverbrush/orm`: add + `InferDatabaseRow` / `InferDatabaseValue` row typing helpers and support raw + update expressions plus conditional `where` callbacks in + `onConflict().merge()`. + - `@cleverbrush/orm-cli`: add read-only `cb-orm validate` for live schema drift + checks. + + Docs and package READMEs were updated; see https://docs.cleverbrush.com. + +### Patch Changes + +- @cleverbrush/schema@4.4.0 + ## 4.3.2 ### Patch Changes diff --git a/libs/knex-schema/package.json b/libs/knex-schema/package.json index 77f5679b..5c1a3b77 100644 --- a/libs/knex-schema/package.json +++ b/libs/knex-schema/package.json @@ -5,7 +5,7 @@ "email": "andrew_zol@cleverbrush.com" }, "dependencies": { - "@cleverbrush/schema": "^4.3.2" + "@cleverbrush/schema": "^4.4.0" }, "peerDependencies": { "knex": ">=3.1.0" @@ -52,5 +52,5 @@ }, "type": "module", "types": "./dist/index.d.ts", - "version": "4.3.2" + "version": "4.4.0" } diff --git a/libs/log/CHANGELOG.md b/libs/log/CHANGELOG.md index f0edf1db..3ce30468 100644 --- a/libs/log/CHANGELOG.md +++ b/libs/log/CHANGELOG.md @@ -1,5 +1,12 @@ # @cleverbrush/log +## 4.4.0 + +### Patch Changes + +- @cleverbrush/schema@4.4.0 +- @cleverbrush/async@4.4.0 + ## 4.3.2 ### Patch Changes diff --git a/libs/log/package.json b/libs/log/package.json index 2ff0bb46..1599e44d 100644 --- a/libs/log/package.json +++ b/libs/log/package.json @@ -41,8 +41,8 @@ "clean": "rm -rf dist tsconfig.tsbuildinfo" }, "dependencies": { - "@cleverbrush/schema": "^4.3.2", - "@cleverbrush/async": "^4.3.2" + "@cleverbrush/schema": "^4.4.0", + "@cleverbrush/async": "^4.4.0" }, "peerDependencies": { "@cleverbrush/di": "^4.0.0", @@ -65,5 +65,5 @@ }, "type": "module", "types": "./dist/index.d.ts", - "version": "4.3.2" + "version": "4.4.0" } diff --git a/libs/mapper/CHANGELOG.md b/libs/mapper/CHANGELOG.md index 08c02447..b9b66a6e 100644 --- a/libs/mapper/CHANGELOG.md +++ b/libs/mapper/CHANGELOG.md @@ -1,5 +1,11 @@ # @cleverbrush/mapper +## 4.4.0 + +### Patch Changes + +- @cleverbrush/schema@4.4.0 + ## 4.3.2 ### Patch Changes diff --git a/libs/mapper/package.json b/libs/mapper/package.json index 2b0a5b32..b78f1de6 100644 --- a/libs/mapper/package.json +++ b/libs/mapper/package.json @@ -5,7 +5,7 @@ "email": "andrew_zol@cleverbrush.com" }, "dependencies": { - "@cleverbrush/schema": "^4.3.2" + "@cleverbrush/schema": "^4.4.0" }, "description": "Type-safe, schema-driven object mapper for @cleverbrush/schema — compile-time completeness, selector-based field mapping, auto-mapping", "files": [ @@ -42,5 +42,5 @@ }, "type": "module", "types": "./dist/index.d.ts", - "version": "4.3.2" + "version": "4.4.0" } diff --git a/libs/orm-cli/CHANGELOG.md b/libs/orm-cli/CHANGELOG.md index ac0585ac..4d200d71 100644 --- a/libs/orm-cli/CHANGELOG.md +++ b/libs/orm-cli/CHANGELOG.md @@ -1,5 +1,33 @@ # @cleverbrush/orm-cli +## 4.4.0 + +### Minor Changes + +- c75bff4: Add framework affordances discovered while reviewing Xpenser: + + - `@cleverbrush/env`: add `envBoolean()` for environment-style boolean values + such as `1`, `0`, `yes`, `no`, `on`, and `off`. + - `@cleverbrush/server`: parse `application/x-www-form-urlencoded` request + bodies by default, add `ActionResult.raw()`, and allow ordered + authentication fallback with `trySchemes`. + - `@cleverbrush/client`: add `externalCacheTags()` to + `@cleverbrush/client/cache` for framework-agnostic external cache tag + invalidation, including Next.js `revalidateTag()` as one supported callback. + - `@cleverbrush/knex-schema` / `@cleverbrush/orm`: add + `InferDatabaseRow` / `InferDatabaseValue` row typing helpers and support raw + update expressions plus conditional `where` callbacks in + `onConflict().merge()`. + - `@cleverbrush/orm-cli`: add read-only `cb-orm validate` for live schema drift + checks. + + Docs and package READMEs were updated; see https://docs.cleverbrush.com. + +### Patch Changes + +- Updated dependencies [c75bff4] + - @cleverbrush/knex-schema@4.4.0 + ## 4.3.2 ### Patch Changes diff --git a/libs/orm-cli/package.json b/libs/orm-cli/package.json index 06af18e8..fe9d0b0d 100644 --- a/libs/orm-cli/package.json +++ b/libs/orm-cli/package.json @@ -48,5 +48,5 @@ }, "type": "module", "types": "./dist/index.d.ts", - "version": "4.3.2" + "version": "4.4.0" } diff --git a/libs/orm/CHANGELOG.md b/libs/orm/CHANGELOG.md index dd9b62b9..f8a9a9dc 100644 --- a/libs/orm/CHANGELOG.md +++ b/libs/orm/CHANGELOG.md @@ -1,5 +1,34 @@ # @cleverbrush/orm +## 4.4.0 + +### Minor Changes + +- c75bff4: Add framework affordances discovered while reviewing Xpenser: + + - `@cleverbrush/env`: add `envBoolean()` for environment-style boolean values + such as `1`, `0`, `yes`, `no`, `on`, and `off`. + - `@cleverbrush/server`: parse `application/x-www-form-urlencoded` request + bodies by default, add `ActionResult.raw()`, and allow ordered + authentication fallback with `trySchemes`. + - `@cleverbrush/client`: add `externalCacheTags()` to + `@cleverbrush/client/cache` for framework-agnostic external cache tag + invalidation, including Next.js `revalidateTag()` as one supported callback. + - `@cleverbrush/knex-schema` / `@cleverbrush/orm`: add + `InferDatabaseRow` / `InferDatabaseValue` row typing helpers and support raw + update expressions plus conditional `where` callbacks in + `onConflict().merge()`. + - `@cleverbrush/orm-cli`: add read-only `cb-orm validate` for live schema drift + checks. + + Docs and package READMEs were updated; see https://docs.cleverbrush.com. + +### Patch Changes + +- Updated dependencies [c75bff4] + - @cleverbrush/knex-schema@4.4.0 + - @cleverbrush/schema@4.4.0 + ## 4.3.2 ### Patch Changes diff --git a/libs/orm/package.json b/libs/orm/package.json index 54e3bdbc..85110314 100644 --- a/libs/orm/package.json +++ b/libs/orm/package.json @@ -5,8 +5,8 @@ "email": "andrew_zol@cleverbrush.com" }, "dependencies": { - "@cleverbrush/schema": "^4.3.2", - "@cleverbrush/knex-schema": "^4.3.2" + "@cleverbrush/schema": "^4.4.0", + "@cleverbrush/knex-schema": "^4.4.0" }, "peerDependencies": { "knex": ">=3.1.0" @@ -53,5 +53,5 @@ }, "type": "module", "types": "./dist/index.d.ts", - "version": "4.3.2" + "version": "4.4.0" } diff --git a/libs/otel/CHANGELOG.md b/libs/otel/CHANGELOG.md index 42081a3f..488b61ea 100644 --- a/libs/otel/CHANGELOG.md +++ b/libs/otel/CHANGELOG.md @@ -1,5 +1,7 @@ # @cleverbrush/otel +## 4.4.0 + ## 4.3.2 ### Patch Changes diff --git a/libs/otel/package.json b/libs/otel/package.json index 6f069860..7d9491eb 100644 --- a/libs/otel/package.json +++ b/libs/otel/package.json @@ -107,5 +107,5 @@ }, "type": "module", "types": "./dist/index.d.ts", - "version": "4.3.2" + "version": "4.4.0" } diff --git a/libs/react-form/CHANGELOG.md b/libs/react-form/CHANGELOG.md index 3a7d6d2f..7e5e5449 100644 --- a/libs/react-form/CHANGELOG.md +++ b/libs/react-form/CHANGELOG.md @@ -1,5 +1,11 @@ # @cleverbrush/react-form +## 4.4.0 + +### Patch Changes + +- @cleverbrush/schema@4.4.0 + ## 4.3.2 ### Patch Changes diff --git a/libs/react-form/package.json b/libs/react-form/package.json index 8de172ed..4431e540 100644 --- a/libs/react-form/package.json +++ b/libs/react-form/package.json @@ -5,7 +5,7 @@ "email": "andrew_zol@cleverbrush.com" }, "dependencies": { - "@cleverbrush/schema": "^4.3.2" + "@cleverbrush/schema": "^4.4.0" }, "devDependencies": { "@types/react": "^19.0.0", @@ -47,5 +47,5 @@ }, "type": "module", "types": "./dist/index.d.ts", - "version": "4.3.2" + "version": "4.4.0" } diff --git a/libs/scheduler/CHANGELOG.md b/libs/scheduler/CHANGELOG.md index 052e6253..6b177380 100644 --- a/libs/scheduler/CHANGELOG.md +++ b/libs/scheduler/CHANGELOG.md @@ -1,5 +1,11 @@ # @cleverbrush/scheduler +## 4.4.0 + +### Patch Changes + +- @cleverbrush/schema@4.4.0 + ## 4.3.2 ### Patch Changes diff --git a/libs/scheduler/package.json b/libs/scheduler/package.json index 16100d08..8bbf6bc5 100644 --- a/libs/scheduler/package.json +++ b/libs/scheduler/package.json @@ -5,7 +5,7 @@ "email": "andrew_zol@cleverbrush.com" }, "dependencies": { - "@cleverbrush/schema": "^4.3.2" + "@cleverbrush/schema": "^4.4.0" }, "devDependencies": { "@types/node": "^25.4.0" @@ -43,5 +43,5 @@ }, "type": "module", "types": "./dist/index.d.ts", - "version": "4.3.2" + "version": "4.4.0" } diff --git a/libs/schema-json/CHANGELOG.md b/libs/schema-json/CHANGELOG.md index 8c618644..34e3096f 100644 --- a/libs/schema-json/CHANGELOG.md +++ b/libs/schema-json/CHANGELOG.md @@ -1,5 +1,7 @@ # @cleverbrush/schema-json +## 4.4.0 + ## 4.3.2 ### Patch Changes diff --git a/libs/schema-json/package.json b/libs/schema-json/package.json index 521b8b3a..7172aec8 100644 --- a/libs/schema-json/package.json +++ b/libs/schema-json/package.json @@ -41,5 +41,5 @@ }, "type": "module", "types": "./dist/index.d.ts", - "version": "4.3.2" + "version": "4.4.0" } diff --git a/libs/schema/CHANGELOG.md b/libs/schema/CHANGELOG.md index 723ff9fd..cad78f3f 100644 --- a/libs/schema/CHANGELOG.md +++ b/libs/schema/CHANGELOG.md @@ -1,5 +1,7 @@ # @cleverbrush/schema +## 4.4.0 + ## 4.3.2 ### Patch Changes diff --git a/libs/schema/package.json b/libs/schema/package.json index f02126c0..14f83964 100644 --- a/libs/schema/package.json +++ b/libs/schema/package.json @@ -106,9 +106,9 @@ }, "type": "module", "types": "./dist/index.d.ts", - "version": "4.3.2", + "version": "4.4.0", "devDependencies": { - "@cleverbrush/deep": "^4.3.2" + "@cleverbrush/deep": "^4.4.0" }, "peerDependencies": { "@standard-schema/spec": "^1.1.0" diff --git a/libs/server-openapi/CHANGELOG.md b/libs/server-openapi/CHANGELOG.md index 3bb84bf1..f6894aed 100644 --- a/libs/server-openapi/CHANGELOG.md +++ b/libs/server-openapi/CHANGELOG.md @@ -1,5 +1,7 @@ # @cleverbrush/server-openapi +## 4.4.0 + ## 4.3.2 ### Patch Changes diff --git a/libs/server-openapi/package.json b/libs/server-openapi/package.json index 69860693..7b23abfc 100644 --- a/libs/server-openapi/package.json +++ b/libs/server-openapi/package.json @@ -45,5 +45,5 @@ }, "type": "module", "types": "./dist/index.d.ts", - "version": "4.3.2" + "version": "4.4.0" } diff --git a/libs/server/CHANGELOG.md b/libs/server/CHANGELOG.md index d25ca7be..9fb877ad 100644 --- a/libs/server/CHANGELOG.md +++ b/libs/server/CHANGELOG.md @@ -1,5 +1,34 @@ # @cleverbrush/server +## 4.4.0 + +### Minor Changes + +- c75bff4: Add framework affordances discovered while reviewing Xpenser: + + - `@cleverbrush/env`: add `envBoolean()` for environment-style boolean values + such as `1`, `0`, `yes`, `no`, `on`, and `off`. + - `@cleverbrush/server`: parse `application/x-www-form-urlencoded` request + bodies by default, add `ActionResult.raw()`, and allow ordered + authentication fallback with `trySchemes`. + - `@cleverbrush/client`: add `externalCacheTags()` to + `@cleverbrush/client/cache` for framework-agnostic external cache tag + invalidation, including Next.js `revalidateTag()` as one supported callback. + - `@cleverbrush/knex-schema` / `@cleverbrush/orm`: add + `InferDatabaseRow` / `InferDatabaseValue` row typing helpers and support raw + update expressions plus conditional `where` callbacks in + `onConflict().merge()`. + - `@cleverbrush/orm-cli`: add read-only `cb-orm validate` for live schema drift + checks. + + Docs and package READMEs were updated; see https://docs.cleverbrush.com. + +### Patch Changes + +- @cleverbrush/schema@4.4.0 +- @cleverbrush/auth@4.4.0 +- @cleverbrush/di@4.4.0 + ## 4.3.2 ### Patch Changes diff --git a/libs/server/package.json b/libs/server/package.json index da0d49f0..50b23df7 100644 --- a/libs/server/package.json +++ b/libs/server/package.json @@ -5,9 +5,9 @@ "email": "andrew_zol@cleverbrush.com" }, "dependencies": { - "@cleverbrush/auth": "^4.3.2", - "@cleverbrush/di": "^4.3.2", - "@cleverbrush/schema": "^4.3.2", + "@cleverbrush/auth": "^4.4.0", + "@cleverbrush/di": "^4.4.0", + "@cleverbrush/schema": "^4.4.0", "@fastify/busboy": "^3.2.0", "ws": "^8.20.0" }, @@ -55,5 +55,5 @@ }, "type": "module", "types": "./dist/index.d.ts", - "version": "4.3.2" + "version": "4.4.0" } diff --git a/websites/docs/public/api-docs/index.html b/websites/docs/public/api-docs/index.html index 7394005e..089fc982 100644 --- a/websites/docs/public/api-docs/index.html +++ b/websites/docs/public/api-docs/index.html @@ -40,6 +40,8 @@

Previous Versions

+ + @@ -59,6 +61,7 @@

Previous Versions