From 39c02341c0f2c482c29e6f090a7a25cbf28e36a3 Mon Sep 17 00:00:00 2001 From: Andrew Zolotukhin Date: Thu, 15 Oct 2026 14:10:58 +0000 Subject: [PATCH 01/10] Add typed endpoint paths and transaction lock options --- .../typed-paths-and-transaction-locks.md | 12 ++ libs/client/src/path.test.ts | 8 + libs/client/src/path.ts | 8 +- libs/orm/README.md | 24 +++ .../orm/integration/transaction-locks.test.ts | 81 ++++++++++ libs/orm/src/dbcontext.ts | 44 +++++- libs/orm/src/index.ts | 3 +- libs/orm/src/transaction-locks.test.ts | 61 +++++++ .../ObjectSchemaBuilder.boundaries.test.ts | 62 ++++++++ .../src/builders/ObjectSchemaBuilder.ts | 12 +- .../src/builders/PropertyDescriptors.test.ts | 8 +- libs/server/README.md | 21 +++ libs/server/src/EndpointPath.test-d.ts | 28 ++++ libs/server/src/EndpointPath.test.ts | 120 ++++++++++++++ libs/server/src/EndpointPath.ts | 149 ++++++++++++++++++ libs/server/src/Router.ts | 26 +-- libs/server/src/contract.ts | 5 + libs/server/src/index.ts | 5 + libs/server/tests/Router.test.ts | 12 -- vitest.queries.config.mts | 5 +- 20 files changed, 658 insertions(+), 36 deletions(-) create mode 100644 .changeset/typed-paths-and-transaction-locks.md create mode 100644 libs/orm/integration/transaction-locks.test.ts create mode 100644 libs/orm/src/transaction-locks.test.ts create mode 100644 libs/schema/src/builders/ObjectSchemaBuilder.boundaries.test.ts create mode 100644 libs/server/src/EndpointPath.test-d.ts create mode 100644 libs/server/src/EndpointPath.test.ts create mode 100644 libs/server/src/EndpointPath.ts diff --git a/.changeset/typed-paths-and-transaction-locks.md b/.changeset/typed-paths-and-transaction-locks.md new file mode 100644 index 00000000..eea365df --- /dev/null +++ b/.changeset/typed-paths-and-transaction-locks.md @@ -0,0 +1,12 @@ +--- +"@cleverbrush/server": minor +"@cleverbrush/client": patch +"@cleverbrush/orm": minor +"@cleverbrush/schema": patch +--- + +Add typed endpoint pathname construction and matching, shared with client URL generation and server routing. Route parameters are validated and encoded as individual components. + +Add optional PostgreSQL advisory locks to ORM transactions, acquired before callbacks and released with their transaction. + +Reject non-object inputs to open object schemas with inspectable validation errors, including nested arrays, instead of throwing descriptor errors. diff --git a/libs/client/src/path.test.ts b/libs/client/src/path.test.ts index e9797fcb..071b1895 100644 --- a/libs/client/src/path.test.ts +++ b/libs/client/src/path.test.ts @@ -1,7 +1,15 @@ +import { string } from '@cleverbrush/schema'; +import { route } from '@cleverbrush/server/contract'; import { describe, expect, test, vi } from 'vitest'; import { buildPath } from './path.js'; describe('buildPath', () => { + test('encodes real contract parameters without changing literal separators', () => { + const template = route({ id: string() })`/${p => p.id}/content`; + expect(buildPath('/files', template, { id: 'a/b%2F?#' })).toBe( + '/files/a%2Fb%252F%3F%23/content' + ); + }); test('plain string template — appends to basePath', () => { expect(buildPath('/api/todos', '')).toBe('/api/todos'); expect(buildPath('/api/todos', '/active')).toBe('/api/todos/active'); diff --git a/libs/client/src/path.ts b/libs/client/src/path.ts index 673bd162..e7ef0bb6 100644 --- a/libs/client/src/path.ts +++ b/libs/client/src/path.ts @@ -1,3 +1,4 @@ +import { endpointPath } from '@cleverbrush/server/contract'; /** * Builds the full request URL from endpoint metadata and optional path * parameters. @@ -24,7 +25,12 @@ export function buildPath( } if (typeof pathTemplate.serialize === 'function') { - return basePath + pathTemplate.serialize(params ?? {}); + return typeof (pathTemplate as any).introspect === 'function' + ? endpointPath( + { introspect: () => ({ basePath, pathTemplate }) } as any, + params ?? {} + ) + : basePath + pathTemplate.serialize(params ?? {}); } return basePath; diff --git a/libs/orm/README.md b/libs/orm/README.md index 6d3852f6..3c022096 100644 --- a/libs/orm/README.md +++ b/libs/orm/README.md @@ -521,3 +521,27 @@ Editing a nested object or array marks the column modified; replacing it with an equivalent document does not. `entry(entity).reset()` and `discardChanges()` restore independent copies, so subsequent edits cannot mutate the saved snapshot. JSON validation and encoding also apply to ORM saves and tracked updates. + +### Transaction advisory locks + +Use stable, namespaced keys to serialize operations that can race before a row +exists. PostgreSQL releases these locks when their owning transaction commits or +rolls back. The callback receives the same transaction-bound context as ordinary +transactions; tracked contexts retain tracking. + +```ts +await db.transaction(async tx => { + // Read and write the resource under a transaction-scoped lock. +}, { advisoryLocks: [`resource:${resourceId}`] }); +``` + +Keys must be nonempty strings. Duplicate keys are acquired once, in sorted order. +This prevents inconsistent ordering within one lock set; callers must avoid +inconsistent ordering across nested transactions. The database's configured lock +timeout applies. Unsupported dialects reject advisory locks before the callback +runs; ordinary transactions continue to work. Locks do not replace constraints or +authorization. + +## License + +BSD-3-Clause — see [LICENSE](../../LICENSE). diff --git a/libs/orm/integration/transaction-locks.test.ts b/libs/orm/integration/transaction-locks.test.ts new file mode 100644 index 00000000..1dd26266 --- /dev/null +++ b/libs/orm/integration/transaction-locks.test.ts @@ -0,0 +1,81 @@ +import { randomUUID } from 'node:crypto'; +import Knex from 'knex'; +import { afterAll, describe, expect, it } from 'vitest'; +import { createDb } from '../src/index.js'; + +const connection = process.env.QUERY_TEST_DATABASE_URL; +if (!connection) throw new Error('QUERY_TEST_DATABASE_URL is required'); +const knex = Knex({ client: 'pg', connection, pool: { min: 0, max: 5 } }); +const db = createDb(knex, {}); +afterAll(() => knex.destroy()); + +describe('PostgreSQL advisory transactions', () => { + it.each(['commit', 'rollback'])( + 'releases locks after %s and allows unrelated keys', + async outcome => { + const key = `transaction-test:${randomUUID()}`; + let release!: () => void; + let acquired!: () => void; + const ready = new Promise(resolve => { + acquired = resolve; + }); + const hold = new Promise(resolve => { + release = resolve; + }); + const first = db.transaction( + async () => { + acquired(); + await hold; + if (outcome === 'rollback') + throw new Error('rollback fixture'); + }, + { advisoryLocks: [key] } + ); + const finished = first.catch(error => { + if (outcome !== 'rollback') throw error; + }); + try { + await ready; + const locked = await knex.transaction(async trx => { + const result = await trx.raw( + 'SELECT pg_try_advisory_xact_lock(hashtextextended(?, 0)) AS acquired', + [key] + ); + return result.rows[0].acquired; + }); + expect(locked).toBe(false); + expect( + await db.transaction(async () => 'independent', { + advisoryLocks: [key + ':other'] + }) + ).toBe('independent'); + } finally { + release(); + await finished; + } + expect( + await db.transaction(async () => 'reacquired', { + advisoryLocks: [key] + }) + ).toBe('reacquired'); + } + ); + it('serializes callers with the same key', async () => { + const key = `transaction-test:${randomUUID()}`; + let active = 0; + let maximum = 0; + await Promise.all( + Array.from({ length: 4 }, () => + db.transaction( + async scope => { + maximum = Math.max(maximum, ++active); + await scope.knex.raw('SELECT 1'); + active--; + }, + { advisoryLocks: [key] } + ) + ) + ); + expect(maximum).toBe(1); + }); +}); diff --git a/libs/orm/src/dbcontext.ts b/libs/orm/src/dbcontext.ts index 40096b35..fb59ffe3 100644 --- a/libs/orm/src/dbcontext.ts +++ b/libs/orm/src/dbcontext.ts @@ -19,6 +19,37 @@ import { import { type DbSet, makeDbSet } from './dbset.js'; import { PendingChangesError } from './errors.js'; +/** Options applied before a transaction callback runs. */ +export interface TransactionOptions { + /** + * PostgreSQL transaction-scoped advisory locks. Use stable, namespaced keys. + * Keys are deduplicated and sorted to give overlapping batches a consistent + * acquisition order. Locks remain held until the owning transaction ends; + * they do not replace row constraints or authorization. + */ + readonly advisoryLocks?: readonly string[]; +} + +/** Acquire locks using parameter bindings on the transaction's connection. */ +async function acquireTransactionLocks( + trx: Knex.Transaction, + options?: TransactionOptions +): Promise { + const keys = options?.advisoryLocks ?? []; + if (!keys.length) return; + if (!['pg', 'postgres', 'postgresql'].includes(trx.client.config.client)) { + throw new Error('Advisory transaction locks require PostgreSQL.'); + } + if (keys.some(key => typeof key !== 'string' || key.length === 0)) { + throw new TypeError('Advisory lock keys must be nonempty strings.'); + } + for (const key of [...new Set(keys)].sort()) { + await trx.raw('SELECT pg_advisory_xact_lock(hashtextextended(?, 0))', [ + key + ]); + } +} + /** * The map of entity name → entity definition passed to {@link createDb}. * @@ -44,7 +75,10 @@ export type DbContext = { * Run `callback` inside a Knex transaction. The callback receives a new * `DbContext` whose `DbSet`s are bound to the transaction. */ - transaction(callback: (db: DbContext) => Promise): Promise; + transaction( + callback: (db: DbContext) => Promise, + options?: TransactionOptions + ): Promise; /** * Return a new `DbContext` whose `DbSet`s are bound to `trx`. Useful @@ -148,9 +182,11 @@ function buildContext( return buildContext(trx as unknown as Knex, entities); }, async transaction( - callback: (db: DbContext) => Promise + callback: (db: DbContext) => Promise, + options?: TransactionOptions ): Promise { return knex.transaction(async (trx: Knex.Transaction) => { + await acquireTransactionLocks(trx, options); return callback( buildContext(trx as unknown as Knex, entities) ); @@ -198,9 +234,11 @@ function buildTrackedContext( }, async transaction( - callback: (db: DbContext) => Promise + callback: (db: DbContext) => Promise, + options?: TransactionOptions ): Promise { return knex.transaction(async (trx: Knex.Transaction) => { + await acquireTransactionLocks(trx, options); return callback( buildTrackedContext( trx as unknown as Knex, diff --git a/libs/orm/src/index.ts b/libs/orm/src/index.ts index ca290237..da222ed3 100644 --- a/libs/orm/src/index.ts +++ b/libs/orm/src/index.ts @@ -15,7 +15,8 @@ export type { export type { DbContext, EntityMap, - TrackedDbContext + TrackedDbContext, + TransactionOptions } from './dbcontext.js'; export { createDb } from './dbcontext.js'; export type { diff --git a/libs/orm/src/transaction-locks.test.ts b/libs/orm/src/transaction-locks.test.ts new file mode 100644 index 00000000..b1463f8e --- /dev/null +++ b/libs/orm/src/transaction-locks.test.ts @@ -0,0 +1,61 @@ +import type { Knex } from 'knex'; +import { describe, expect, it, vi } from 'vitest'; +import { createDb } from './index.js'; + +function database(client = 'pg', tracking = false) { + const raw = vi.fn().mockResolvedValue(undefined); + const transaction = { client: { config: { client } }, raw }; + const knex = { + transaction: vi.fn(async callback => callback(transaction)) + } as unknown as Knex; + return { db: createDb(knex, {}, { tracking }), raw, transaction }; +} + +describe('advisory transaction options', () => { + it.each([false, true])( + 'locks once in stable order before callback (tracking=%s)', + async tracking => { + const { db, raw, transaction } = database('pg', tracking); + const value = await db.transaction( + async scope => { + expect(scope.knex).toBe(transaction); + expect(raw.mock.calls.map(call => call[1])).toEqual([ + ['asset:a'], + ['asset:z'] + ]); + return 'done'; + }, + { advisoryLocks: ['asset:z', 'asset:a', 'asset:z'] } + ); + expect(value).toBe('done'); + } + ); + it('preserves transactions without locking on other dialects', async () => { + const { db, raw } = database('sqlite3'); + expect(await db.transaction(async () => 7)).toBe(7); + expect(raw).not.toHaveBeenCalled(); + }); + it('rejects unsupported dialects and invalid keys before running the callback', async () => { + const callback = vi.fn(); + await expect( + database('sqlite3').db.transaction(callback, { + advisoryLocks: ['one'] + }) + ).rejects.toThrow('PostgreSQL'); + for (const keys of [[''], [7] as any]) { + await expect( + database().db.transaction(callback, { advisoryLocks: keys }) + ).rejects.toThrow('nonempty strings'); + } + expect(callback).not.toHaveBeenCalled(); + }); + it('propagates lock errors without executing work', async () => { + const { db, raw } = database(); + raw.mockRejectedValue(new Error('lock timeout')); + const callback = vi.fn(); + await expect( + db.transaction(callback, { advisoryLocks: ['one'] }) + ).rejects.toThrow('lock timeout'); + expect(callback).not.toHaveBeenCalled(); + }); +}); diff --git a/libs/schema/src/builders/ObjectSchemaBuilder.boundaries.test.ts b/libs/schema/src/builders/ObjectSchemaBuilder.boundaries.test.ts new file mode 100644 index 00000000..2608e7b7 --- /dev/null +++ b/libs/schema/src/builders/ObjectSchemaBuilder.boundaries.test.ts @@ -0,0 +1,62 @@ +import { describe, expect, it } from 'vitest'; +import { array, object, string } from '../index.js'; + +describe('open object boundaries', () => { + it.each([0, 'text', true, [], [1], null, undefined])( + 'rejects %j with inspectable errors', + async value => { + const schema = object({}).acceptUnknownProps(); + const result = schema.safeParse(value); + expect(result.valid).toBe(false); + const full = schema.validate(value as any, { + doNotStopOnFirstError: true + }); + expect(full.valid).toBe(false); + expect(full.getErrorsFor().isValid).toBe(false); + expect((await schema.validateAsync(value as any)).valid).toBe( + false + ); + const list = array(schema).validate([value] as any); + expect(list.valid).toBe(false); + expect(list.getNestedErrors()[0].getErrorsFor().isValid).toBe( + false + ); + expect( + (await array(schema).validateAsync([value] as any)).valid + ).toBe(false); + } + ); + it('keeps nested extensions and empty arrays without mutating the input', () => { + const schema = object({ + rows: array( + object({ + data: object({}).acceptUnknownProps(), + items: array(string()) + }) + ) + }); + const value = { + rows: [ + { + data: { extension: { empty: [], nullable: null } }, + items: [] + } + ] + }; + const result = schema.parse(value); + expect(result).toEqual(value); + expect(Object.getOwnPropertySymbols(result.rows[0].items)).toEqual([]); + expect(Object.getOwnPropertySymbols(value.rows[0].items)).toEqual([]); + }); + it('preserves optional, nullable and preprocessor behavior', () => { + expect(object({}).optional().safeParse(undefined).valid).toBe(true); + expect(object({}).nullable().safeParse(null).valid).toBe(true); + expect( + object({ name: string() }) + .addPreprocessor(value => + typeof value === 'string' ? { name: value } : value + ) + .parse('Ada' as any) + ).toEqual({ name: 'Ada' }); + }); +}); diff --git a/libs/schema/src/builders/ObjectSchemaBuilder.ts b/libs/schema/src/builders/ObjectSchemaBuilder.ts index 286ebbcb..34f1aeeb 100644 --- a/libs/schema/src/builders/ObjectSchemaBuilder.ts +++ b/libs/schema/src/builders/ObjectSchemaBuilder.ts @@ -872,7 +872,11 @@ export class ObjectSchemaBuilder< }; } - if (typeof objToValidate !== 'object' || objToValidate === null) { + if ( + typeof objToValidate !== 'object' || + objToValidate === null || + Array.isArray(objToValidate) + ) { // Only add "must be an object" when there is no prior error (e.g. // a required-violation error already pushed by preValidateAsync). if (errors.length === 0) { @@ -1356,7 +1360,7 @@ export class ObjectSchemaBuilder< } } as any; } - } else if (typeof object === 'object') { + } else if (typeof object === 'object' && !Array.isArray(object)) { const propKeys = this.#propKeys; // Check for unknown properties @@ -2640,10 +2644,6 @@ export class ObjectSchemaBuilder< const propsNames = Object.keys(introspected.properties); - if (propsNames.length === 0) { - return {} as any; - } - if (typeof selector !== 'function') { selector = o => o; } diff --git a/libs/schema/src/builders/PropertyDescriptors.test.ts b/libs/schema/src/builders/PropertyDescriptors.test.ts index ecf9f02e..62abeaed 100644 --- a/libs/schema/src/builders/PropertyDescriptors.test.ts +++ b/libs/schema/src/builders/PropertyDescriptors.test.ts @@ -15,13 +15,17 @@ test('Throws with not ObjectSchemaBuilder instance', async () => { expect(() => (object as any).getPropertiesFor(number())).toThrow(); }); -test('Returns empty object for empty schema', async () => { +test('Returns a root descriptor without children for an empty schema', async () => { const schema = object(); const tree = object.getPropertiesFor(schema); expect(tree).not.toBeNull(); expect(tree).not.toBeUndefined(); - expect(tree).toEqual({}); + expect(Object.keys(tree)).toEqual([]); + const descriptor = tree[SYMBOL_SCHEMA_PROPERTY_DESCRIPTOR]; + expect(descriptor).toBeDefined(); + const value = {}; + expect(descriptor.getValue(value)).toMatchObject({ success: true, value }); }); test('Properties exists', async () => { diff --git a/libs/server/README.md b/libs/server/README.md index 8cb7fef2..5f196f0b 100644 --- a/libs/server/README.md +++ b/libs/server/README.md @@ -990,6 +990,27 @@ chunks and restore response hooks on failure. See [security guidance](../../SECURITY.md) and the [v4.x-to-v5 migration guide](../../docs/MIGRATION-v5.md). + + +### Endpoint path helpers + +`endpointPath(endpoint, params)` constructs an encoded pathname from a contract. +`matchEndpointPath(endpoint, pathname)` returns validated parameters or `undefined`. +Both are exported from `@cleverbrush/server/contract` for browser use and from the +main package. Matching checks paths only, not methods or authorization. Origins, +query strings and fragments are intentionally separate. + +```ts +import { endpointPath, matchEndpointPath } from '@cleverbrush/server/contract'; + +const path = endpointPath(api.files.content, { id: 'report 1' }); +const params = matchEndpointPath(api.files.content, path); +``` + +Parameters are URI-component encoded and decoded once. Invalid values throw +during construction; mismatches, malformed encoding and invalid parameter values +return `undefined` when matching. One trailing slash is accepted. + ## License BSD-3-Clause — see [LICENSE](../../LICENSE). diff --git a/libs/server/src/EndpointPath.test-d.ts b/libs/server/src/EndpointPath.test-d.ts new file mode 100644 index 00000000..0cb4746d --- /dev/null +++ b/libs/server/src/EndpointPath.test-d.ts @@ -0,0 +1,28 @@ +import { number, string } from '@cleverbrush/schema'; +import { expectTypeOf, test } from 'vitest'; +import { + endpoint, + endpointPath, + matchEndpointPath, + route +} from './contract.js'; + +test('path arguments and matched parameters follow the contract', () => { + const get = endpoint.resource('').get( + route({ + id: number().coerce(), + name: string() + })`/items/${p => p.id}/${p => p.name}` + ); + endpointPath(get, { id: 1, name: 'item' }); + expectTypeOf(matchEndpointPath(get, '/items/1/item')).toEqualTypeOf< + { id: number; name: string } | undefined + >(); + // @ts-expect-error path parameters are required + endpointPath(get); + // @ts-expect-error a renamed property cannot silently construct a stale URL + endpointPath(get, { itemId: 1, name: 'item' }); + // @ts-expect-error input types follow the contract + endpointPath(get, { id: '1', name: 'item' }); + endpointPath(endpoint.get('/health')); +}); diff --git a/libs/server/src/EndpointPath.test.ts b/libs/server/src/EndpointPath.test.ts new file mode 100644 index 00000000..c92540f9 --- /dev/null +++ b/libs/server/src/EndpointPath.test.ts @@ -0,0 +1,120 @@ +import { number, object, string } from '@cleverbrush/schema'; +import { describe, expect, it } from 'vitest'; +import { ActionResult } from './ActionResult.js'; +import { + endpoint, + endpointPath, + matchEndpointPath, + route +} from './contract.js'; +import { createServer } from './Server.js'; + +const content = endpoint + .resource('/api/files') + .get(route({ id: string().minLength(1) })`/${p => p.id}/content`); + +describe('endpoint paths', () => { + it.each([ + 'file-1', + 'report one', + 'a/b', + 'a?b#c', + '100%', + 'a%2Fb', + '日本語' + ])('round trips parameter %s', id => { + const path = endpointPath(content, { id }); + expect(path).toBe(`/api/files/${encodeURIComponent(id)}/content`); + expect(matchEndpointPath(content, path)).toEqual({ id }); + expect(matchEndpointPath(content, path + '/')).toEqual({ id }); + }); + it('supports static paths, resources and nested/coerced parameters', () => { + expect(endpointPath(endpoint.get('/health'))).toBe('/health'); + expect(endpointPath(endpoint.resource('/health').get('/'))).toBe( + '/health' + ); + expect(matchEndpointPath(endpoint.get('/health'), '/health/')).toEqual( + {} + ); + const nested = endpoint.resource('').get( + route({ + owner: object({ id: number().coerce().isInteger().min(1) }) + })`/owners/${p => p.owner.id}` + ); + expect(endpointPath(nested, { owner: { id: 7 } })).toBe('/owners/7'); + expect(matchEndpointPath(nested, '/owners/7')).toEqual({ + owner: { id: 7 } + }); + expect(matchEndpointPath(nested, '/owners/0')).toBeUndefined(); + expect(matchEndpointPath(nested, '/owners/seven')).toBeUndefined(); + expect(() => endpointPath(nested, { owner: { id: 0 } })).toThrow( + 'Invalid path parameter' + ); + }); + it.each([ + '/other/a/content', + '/api/files/%XX/content', + '/api/files/a/content?q=1', + '/api/files/a/content#fragment', + 'https://example.com/api/files/a/content', + '//api/files/a/content' + ])('rejects invalid pathname %s', path => { + expect(matchEndpointPath(content, path)).toBeUndefined(); + }); + it('matches encoded literals without decoding parameter escapes twice', () => { + const item = endpoint + .resource('/café') + .get(route({ id: string() })`/日本/${p => p.id}`); + expect( + matchEndpointPath(item, '/caf%C3%A9/%E6%97%A5%E6%9C%AC/a%252Fb') + ).toEqual({ id: 'a%2Fb' }); + expect(matchEndpointPath(item, '/caf%c3%a9/日本/item')).toEqual({ + id: 'item' + }); + }); + it('retains empty parameters permitted by their schema', () => { + const item = endpoint + .resource('/items') + .get(route({ id: string() })`/${p => p.id}/content`); + expect(matchEndpointPath(item, '/items//content')).toEqual({ id: '' }); + }); + it('preserves multi-segment route parameters', () => { + expect(matchEndpointPath(content, '/api/files/a/b/content')).toEqual({ + id: 'a/b' + }); + }); + it('validates required parameters and escapes literal regex syntax', () => { + expect(() => endpointPath(content, {} as any)).toThrow( + 'Missing path parameter' + ); + expect(() => endpointPath(content, { id: '' })).toThrow( + 'Invalid path parameter' + ); + const literal = endpoint + .resource('') + .get(route({ id: string() })`/files/v1.0/${p => p.id}`); + expect(matchEndpointPath(literal, '/files/v1X0/a')).toBeUndefined(); + expect(matchEndpointPath(literal, '/files/v1.0/a')).toEqual({ + id: 'a' + }); + }); + it('uses the same encoded parameters in the HTTP router', async () => { + const server = await createServer() + .handle(content, ({ params }) => ActionResult.ok(params)) + .listen(0, '127.0.0.1'); + try { + const address = server.address; + const port = + typeof address === 'object' && address ? address.port : 0; + for (const id of ['report one', 'a/b', 'a%2Fb', 'a?b#c']) { + const response = await fetch( + `http://127.0.0.1:${port}${endpointPath(content, { id })}` + ); + expect(response.status).toBe(200); + expect(await response.json()).toEqual({ id }); + } + } finally { + await server.close(); + } + }); +}); diff --git a/libs/server/src/EndpointPath.ts b/libs/server/src/EndpointPath.ts new file mode 100644 index 00000000..dfa7eec0 --- /dev/null +++ b/libs/server/src/EndpointPath.ts @@ -0,0 +1,149 @@ +import type { EndpointBuilder, EndpointMetadata } from './Endpoint.js'; + +type AnyEndpoint = EndpointBuilder< + any, + any, + any, + any, + any, + any, + any, + any, + any, + any +>; +/** The path-parameter type declared by an endpoint. */ +export type EndpointParams = + E extends EndpointBuilder< + infer P, + any, + any, + any, + any, + any, + any, + any, + any, + any + > + ? P + : never; +type PathMetadata = Pick; + +const trimTrailingSlash = (path: string) => + path.length > 1 && path.endsWith('/') ? path.slice(0, -1) : path; +const escapeRegex = (text: string) => + text.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); + +/** Match literal path text before decoding captured parameters. */ +function literalPattern(literal: string): string { + return Array.from(decodeURI(literal), character => { + const encoded = encodeURI(character); + return encoded === character + ? escapeRegex(character) + : `(?:${escapeRegex(character)}|${encoded.replace(/[A-F]/g, c => `[${c}${c.toLowerCase()}]`)})`; + }).join(''); +} + +/** + * Build a relative pathname from an endpoint's contract. Parameters are validated + * and encoded individually, so reserved characters cannot introduce URL syntax. + * Query strings and origins belong to the caller. Throws for invalid parameters. + * @example endpointPath(api.files.content, { id: 'report 1' }) + */ +export function endpointPath( + endpoint: E, + ...args: keyof EndpointParams extends never + ? [params?: EndpointParams] + : [params: EndpointParams] +): string { + const { basePath, pathTemplate } = endpoint.introspect(); + if (typeof pathTemplate === 'string') + return pathTemplate === '/' ? basePath || '/' : basePath + pathTemplate; + const { literals, segments } = pathTemplate.introspect().templateDefinition; + let path = basePath; + for (let index = 0; index < segments.length; index++) { + const segment = segments[index]; + const value = segment.descriptor.getValue(args[0] ?? {}); + if (!value.success || value.value == null) + throw new TypeError(`Missing path parameter: ${segment.path}`); + const checked = segment.schema.safeParse(value.value); + if (!checked.valid) + throw new TypeError(`Invalid path parameter: ${segment.path}`); + path += literals[index] + encodeURIComponent(String(checked.object)); + } + path += literals[segments.length] ?? ''; + return trimTrailingSlash(path) || '/'; +} + +/** + * Match a pathname against one endpoint and return validated path parameters. + * Returns undefined for a different route, invalid encoding/parameters or an + * absolute URL/query/fragment. This does not check HTTP method or authorization. + * One optional trailing slash is accepted, matching server routing. Parameters + * may contain slashes when their schema permits them, as in route templates. + */ +export function matchEndpointPath( + endpoint: E, + pathname: string +): EndpointParams | undefined { + return matchRoutePath(endpoint.introspect(), pathname) as + | EndpointParams + | undefined; +} + +/** @internal Shared by HTTP/WebSocket routing so matching has one implementation. */ +export function matchRoutePath( + meta: PathMetadata, + pathname: string +): Record | undefined { + if ( + !pathname.startsWith('/') || + pathname.startsWith('//') || + /[?#]/.test(pathname) + ) + return undefined; + try { + // Validate percent escapes without decoding dynamic values twice. + decodeURI(pathname); + const { basePath, pathTemplate } = meta; + if (typeof pathTemplate === 'string') { + const expected = + pathTemplate === '/' + ? basePath || '/' + : basePath + pathTemplate; + return trimTrailingSlash(decodeURI(pathname)) === + trimTrailingSlash(decodeURI(expected)) + ? {} + : undefined; + } + const { literals, segments } = + pathTemplate.introspect().templateDefinition; + const pattern = + literalPattern(basePath + (literals[0] ?? '')) + + segments + .map( + (_, index) => + '(.*?)' + literalPattern(literals[index + 1] ?? '') + ) + .join(''); + const matched = new RegExp( + '^' + trimTrailingSlash(pattern) + '/?$' + ).exec(pathname); + if (!matched) return undefined; + const params: Record = {}; + for (let index = 0; index < segments.length; index++) { + const segment = segments[index]; + const result = segment.schema.safeParse( + decodeURIComponent(matched[index + 1]) + ); + if (!result.valid) return undefined; + segment.descriptor.setValue(params, result.object, { + createMissingStructure: true + }); + } + return params; + } catch { + return undefined; + } +} diff --git a/libs/server/src/Router.ts b/libs/server/src/Router.ts index be12f1b7..8f4559bf 100644 --- a/libs/server/src/Router.ts +++ b/libs/server/src/Router.ts @@ -1,4 +1,5 @@ import type { ParseStringSchemaBuilder } from '@cleverbrush/schema'; +import { matchRoutePath } from './EndpointPath.js'; import type { EndpointRegistration, RouteMatch, @@ -256,7 +257,7 @@ export class Router { // Try exact method match first const methodRoutes = this.#routes.get(upperMethod); if (methodRoutes) { - const result = this.#findFirstMatch(methodRoutes, normalized); + const result = this.#findFirstMatch(methodRoutes, normalized, url); if (result) { return { match: result, methodNotAllowed: false }; } @@ -266,7 +267,7 @@ export class Router { const allowedMethods: string[] = []; for (const [m, routes] of this.#routes) { if (m === upperMethod) continue; - if (this.#findFirstMatch(routes, normalized)) { + if (this.#findFirstMatch(routes, normalized, url)) { allowedMethods.push(m); } } @@ -281,16 +282,17 @@ export class Router { /** Returns the first successful match from an indexed route collection. */ #findFirstMatch( collection: RouteCollection, - normalizedUrl: string + normalizedUrl: string, + rawUrl: string ): RegisteredRouteMatch | null { const exactRoute = collection.exactRoutes.get(normalizedUrl); if (exactRoute) { - const match = this.#tryMatch(exactRoute, normalizedUrl); + const match = this.#tryMatch(exactRoute, normalizedUrl, rawUrl); if (match) return match; } for (const route of collection.dynamicRoutes) { - const match = this.#tryMatch(route, normalizedUrl); + const match = this.#tryMatch(route, normalizedUrl, rawUrl); if (match) return match; } @@ -305,7 +307,8 @@ export class Router { #tryMatch( route: RegisteredRoute, - normalizedUrl: string + normalizedUrl: string, + rawUrl: string ): RegisteredRouteMatch | null { const { basePath, routePath } = route; @@ -320,11 +323,14 @@ export class Router { if (isParseStringSchema(routePath)) { // Dynamic route: validate remainder via parseString schema - const result = routePath.validate(remainder); - if (result.valid) { + const result = matchRoutePath( + { basePath, pathTemplate: routePath }, + rawUrl + ); + if (result !== undefined) { return { registration: route.registration, - parsedPath: result.object as Record + parsedPath: result as Record }; } return null; @@ -378,6 +384,6 @@ export class Router { } this.finalize(); - return this.#findFirstMatch(this.#subscriptionRoutes, normalized); + return this.#findFirstMatch(this.#subscriptionRoutes, normalized, url); } } diff --git a/libs/server/src/contract.ts b/libs/server/src/contract.ts index 64f6d252..a4c83826 100644 --- a/libs/server/src/contract.ts +++ b/libs/server/src/contract.ts @@ -310,6 +310,11 @@ export function omitGroups( return Object.freeze(result); } +export { + type EndpointParams, + endpointPath, + matchEndpointPath +} from './EndpointPath.js'; export { file, type UploadConfiguration, diff --git a/libs/server/src/index.ts b/libs/server/src/index.ts index 226cf89a..ebd326c6 100644 --- a/libs/server/src/index.ts +++ b/libs/server/src/index.ts @@ -56,6 +56,11 @@ export type { EndpointOptions, IdempotencyScope } from './EndpointOptions.js'; +export { + type EndpointParams, + endpointPath, + matchEndpointPath +} from './EndpointPath.js'; export { ErrorMap, type ErrorResponse, diff --git a/libs/server/tests/Router.test.ts b/libs/server/tests/Router.test.ts index a48df760..df634cad 100644 --- a/libs/server/tests/Router.test.ts +++ b/libs/server/tests/Router.test.ts @@ -103,7 +103,6 @@ describe('Router', () => { object({ id: string() }), $t => $t`/${t => t.id}/question` ); - const genericValidate = vi.spyOn(GenericPath, 'validate'); const router = new Router(); const generic = makeRegistration('GET', '/sessions', GenericPath); const question = makeRegistration('GET', '/sessions', QuestionPath); @@ -114,7 +113,6 @@ describe('Router', () => { expect(result.match?.registration).toBe(question); expect(result.match?.parsedPath).toEqual({ id: '984' }); - expect(genericValidate).not.toHaveBeenCalled(); }); it('falls back when a more-specific route fails validation', () => { @@ -126,8 +124,6 @@ describe('Router', () => { object({ id: number().coerce() }), $t => $t`/${t => t.id}/question` ); - const specificValidate = vi.spyOn(NumericQuestionPath, 'validate'); - const genericValidate = vi.spyOn(GenericPath, 'validate'); const router = new Router(); const generic = makeRegistration('GET', '/sessions', GenericPath); const numericQuestion = makeRegistration( @@ -144,8 +140,6 @@ describe('Router', () => { expect(result.match?.parsedPath).toEqual({ id: 'not-a-number/question' }); - expect(specificValidate).toHaveBeenCalledOnce(); - expect(genericValidate).toHaveBeenCalledOnce(); }); it('re-finalizes after a route is added following a match', () => { @@ -201,7 +195,6 @@ describe('Router', () => { object({ id: string() }), $t => $t`/${t => t.id}` ); - const genericValidate = vi.spyOn(GenericPath, 'validate'); const router = new Router(); const generic = makeRegistration('GET', '/sessions', GenericPath); const exact = makeRegistration('GET', '/sessions/984/question'); @@ -212,7 +205,6 @@ describe('Router', () => { expect(result.match?.registration).toBe(exact); expect(result.match?.parsedPath).toBeNull(); - expect(genericValidate).not.toHaveBeenCalled(); }); it('indexes zero-interpolation templates as exact routes', () => { @@ -221,7 +213,6 @@ describe('Router', () => { $t => $t`/${t => t.id}` ); const StaticPath = parseString(object({}), $t => $t`/health`); - const genericValidate = vi.spyOn(GenericPath, 'validate'); const router = new Router(); const generic = makeRegistration('GET', '', GenericPath); const exact = makeRegistration('GET', '', StaticPath); @@ -232,7 +223,6 @@ describe('Router', () => { expect(result.match?.registration).toBe(exact); expect(result.match?.parsedPath).toEqual({}); - expect(genericValidate).not.toHaveBeenCalled(); }); it('prefers fewer dynamic segments when literal counts are equal', () => { @@ -433,7 +423,6 @@ describe('Router', () => { object({ id: string() }), $t => $t`/${t => t.id}/question` ); - const genericValidate = vi.spyOn(GenericPath, 'validate'); const router = new Router(); const generic = makeSubscriptionRegistration( '/ws/sessions', @@ -450,7 +439,6 @@ describe('Router', () => { expect(result?.registration).toBe(question); expect(result?.parsedPath).toEqual({ id: '984' }); - expect(genericValidate).not.toHaveBeenCalled(); }); it('uses registration order for equal-specificity subscriptions', () => { diff --git a/vitest.queries.config.mts b/vitest.queries.config.mts index 6339951b..7169b2f5 100644 --- a/vitest.queries.config.mts +++ b/vitest.queries.config.mts @@ -2,7 +2,10 @@ import { defineConfig } from 'vitest/config'; export default defineConfig({ test: { - include: ['libs/knex-schema/integration/**/*.test.ts'], + include: [ + 'libs/knex-schema/integration/**/*.test.ts', + 'libs/orm/integration/**/*.test.ts' + ], testTimeout: 15000, hookTimeout: 30000 } From 5d760495d8f12ac7365988c634f1a9744bd3a3e9 Mon Sep 17 00:00:00 2001 From: Andrew Zolotukhin Date: Sat, 17 Oct 2026 11:06:51 +0000 Subject: [PATCH 02/10] feat(server): add request cancellation and deadline helper --- .changeset/request-cancellation.md | 5 + libs/server/README.md | 24 ++++ libs/server/src/index.ts | 6 + libs/server/src/withRequestSignal.test.ts | 133 ++++++++++++++++++++++ libs/server/src/withRequestSignal.ts | 80 +++++++++++++ 5 files changed, 248 insertions(+) create mode 100644 .changeset/request-cancellation.md create mode 100644 libs/server/src/withRequestSignal.test.ts create mode 100644 libs/server/src/withRequestSignal.ts diff --git a/.changeset/request-cancellation.md b/.changeset/request-cancellation.md new file mode 100644 index 00000000..9376f600 --- /dev/null +++ b/.changeset/request-cancellation.md @@ -0,0 +1,5 @@ +--- +"@cleverbrush/server": minor +--- + +Add withRequestSignal for cooperative request-disconnect, caller and deadline cancellation with deterministic lifecycle cleanup. diff --git a/libs/server/README.md b/libs/server/README.md index 5f196f0b..e7839de9 100644 --- a/libs/server/README.md +++ b/libs/server/README.md @@ -1014,3 +1014,27 @@ return `undefined` when matching. One trailing slash is accepted. ## License BSD-3-Clause — see [LICENSE](../../LICENSE). + +## Request cancellation and deadlines + +Use `withRequestSignal(context, work, { timeoutMs, signal? })` for bounded, +request-owned work. The timeout is an application policy, so it is required and +must be a positive integer no greater than 2,147,483,647 milliseconds. + +```ts +import { withRequestSignal } from '@cleverbrush/server'; + +const result = await withRequestSignal( + context, + signal => reports.generate({ signal }), + { timeoutMs: 30_000, signal: shutdownSignal } +); +``` + +The signal aborts on an unfinished response closing, request abort, deadline, or +optional caller cancellation. A completed response closing normally does not +abort it. Caller cancellation preserves its reason; disconnect and deadline use +`AbortError` and `TimeoutError` DOMExceptions. Already-cancelled work never starts. +Timers and listeners are released on success or failure. Cancellation is +cooperative: the work must observe or forward its signal. This helper neither +races arbitrary work nor changes HTTP error/status policies. diff --git a/libs/server/src/index.ts b/libs/server/src/index.ts index ebd326c6..7ea97989 100644 --- a/libs/server/src/index.ts +++ b/libs/server/src/index.ts @@ -142,3 +142,9 @@ export { type UploadSchema } from './upload.js'; export { defineWebhook, type WebhookDefinition } from './Webhook.js'; + +export { + type RequestSignalContext, + type RequestSignalOptions, + withRequestSignal +} from './withRequestSignal.js'; diff --git a/libs/server/src/withRequestSignal.test.ts b/libs/server/src/withRequestSignal.test.ts new file mode 100644 index 00000000..0fa68c51 --- /dev/null +++ b/libs/server/src/withRequestSignal.test.ts @@ -0,0 +1,133 @@ +import { IncomingMessage, ServerResponse } from 'node:http'; +import { Socket } from 'node:net'; +import { afterEach, describe, expect, it, vi } from 'vitest'; +import { withRequestSignal } from './withRequestSignal.js'; + +const fixture = () => { + const request = new IncomingMessage(new Socket()); + return { request, response: new ServerResponse(request) }; +}; +const untilAbort = (signal: AbortSignal) => + new Promise((_, reject) => { + signal.addEventListener('abort', () => reject(signal.reason), { + once: true + }); + }); +const options = { timeoutMs: 100 }; +afterEach(() => vi.useRealTimers()); + +describe('withRequestSignal', () => { + it('returns the result and removes lifecycle listeners and timer', async () => { + vi.useFakeTimers(); + const context = fixture(); + expect(await withRequestSignal(context, () => 42, options)).toBe(42); + expect(context.request.listenerCount('aborted')).toBe(0); + expect(context.response.listenerCount('close')).toBe(0); + expect(vi.getTimerCount()).toBe(0); + }); + it('cleans up synchronous and asynchronous failures', async () => { + const context = fixture(); + const failure = new Error('work failed'); + for (const work of [ + () => { + throw failure; + }, + async () => { + throw failure; + } + ]) { + await expect( + withRequestSignal(context, work, options) + ).rejects.toBe(failure); + expect(context.request.listenerCount('aborted')).toBe(0); + expect(context.response.listenerCount('close')).toBe(0); + } + }); + it('cancels on an aborted request', async () => { + const context = fixture(); + const work = withRequestSignal(context, untilAbort, options); + context.request.emit('aborted'); + await expect(work).rejects.toMatchObject({ name: 'AbortError' }); + }); + it('cancels on an unfinished response close', async () => { + const context = fixture(); + const work = withRequestSignal(context, untilAbort, options); + context.response.emit('close'); + await expect(work).rejects.toMatchObject({ name: 'AbortError' }); + }); + it('does not cancel on a normally finished response', async () => { + const context = fixture(); + Object.defineProperty(context.response, 'writableFinished', { + value: true + }); + await withRequestSignal( + context, + signal => { + context.response.emit('close'); + expect(signal.aborted).toBe(false); + }, + options + ); + }); + it('cancels at the deadline and removes the timer', async () => { + vi.useFakeTimers(); + const work = withRequestSignal(fixture(), untilAbort, options); + const assertion = expect(work).rejects.toMatchObject({ + name: 'TimeoutError' + }); + await vi.advanceTimersByTimeAsync(100); + await assertion; + expect(vi.getTimerCount()).toBe(0); + }); + it('propagates caller cancellation and removes its listener', async () => { + const context = fixture(); + const caller = new AbortController(); + const remove = vi.spyOn(caller.signal, 'removeEventListener'); + const reason = new Error('shutdown'); + const work = withRequestSignal(context, untilAbort, { + ...options, + signal: caller.signal + }); + caller.abort(reason); + await expect(work).rejects.toBe(reason); + expect(remove).toHaveBeenCalledWith('abort', expect.any(Function)); + }); + it.each(['request', 'response', 'caller'] as const)( + 'does not start already-cancelled %s work', + async kind => { + const context = fixture(); + const caller = new AbortController(); + if (kind === 'request') context.request.aborted = true; + if (kind === 'response') context.response.destroyed = true; + if (kind === 'caller') caller.abort(); + const work = vi.fn(); + await expect( + withRequestSignal(context, work, { + ...options, + signal: caller.signal + }) + ).rejects.toMatchObject({ name: 'AbortError' }); + expect(work).not.toHaveBeenCalled(); + } + ); + it('accepts a finished and destroyed response without a false disconnect', async () => { + const context = fixture(); + context.response.destroyed = true; + Object.defineProperty(context.response, 'writableFinished', { + value: true + }); + expect(await withRequestSignal(context, () => 'done', options)).toBe( + 'done' + ); + }); + it.each([0, -1, NaN, Infinity, 1.5, 2_147_483_648])( + 'rejects invalid deadline %s', + async timeoutMs => { + const context = fixture(); + await expect( + withRequestSignal(context, () => {}, { timeoutMs }) + ).rejects.toBeInstanceOf(RangeError); + expect(context.response.listenerCount('close')).toBe(0); + } + ); +}); diff --git a/libs/server/src/withRequestSignal.ts b/libs/server/src/withRequestSignal.ts new file mode 100644 index 00000000..ff9cb01f --- /dev/null +++ b/libs/server/src/withRequestSignal.ts @@ -0,0 +1,80 @@ +import type { IncomingMessage, ServerResponse } from 'node:http'; + +/** HTTP lifecycle fields required to cancel request-owned work. */ +export interface RequestSignalContext { + readonly request: Pick; + readonly response: Pick< + ServerResponse, + 'destroyed' | 'writableFinished' | 'once' | 'off' + >; +} + +/** Application-owned deadline and optional cancellation for request work. */ +export interface RequestSignalOptions { + /** Positive integer deadline in milliseconds, at most 2,147,483,647. */ + timeoutMs: number; + /** Additional cancellation, such as application shutdown. */ + signal?: AbortSignal; +} + +/** + * Run cooperative work with cancellation on disconnect, deadline or caller abort. + * + * The visitor must observe its signal; this helper does not forcibly interrupt + * arbitrary promises. A normal response finish does not cancel the work. The + * deadline timer and all listeners are removed when work settles, including on + * failure. Already-aborted inputs reject without invoking the visitor. + * + * @example + * ```ts + * await withRequestSignal(context, signal => loadReport(signal), { + * timeoutMs: 30_000 + * }); + * ``` + */ +export async function withRequestSignal( + context: RequestSignalContext, + work: (signal: AbortSignal) => T | PromiseLike, + options: RequestSignalOptions +): Promise { + if ( + !Number.isSafeInteger(options.timeoutMs) || + options.timeoutMs <= 0 || + options.timeoutMs > 2_147_483_647 + ) { + throw new RangeError( + 'timeoutMs must be a positive timer-safe integer.' + ); + } + const controller = new AbortController(); + const disconnected = () => + controller.abort( + new DOMException('Request disconnected.', 'AbortError') + ); + const closed = () => { + if (!context.response.writableFinished) disconnected(); + }; + const cancelled = () => controller.abort(options.signal!.reason); + const timer = setTimeout( + () => + controller.abort( + new DOMException('Request deadline exceeded.', 'TimeoutError') + ), + options.timeoutMs + ); + context.request.once('aborted', disconnected); + context.response.once('close', closed); + options.signal?.addEventListener('abort', cancelled, { once: true }); + try { + if (context.request.aborted || context.response.destroyed) closed(); + if (context.request.aborted) disconnected(); + if (options.signal?.aborted) cancelled(); + controller.signal.throwIfAborted(); + return await work(controller.signal); + } finally { + clearTimeout(timer); + context.request.off('aborted', disconnected); + context.response.off('close', closed); + options.signal?.removeEventListener('abort', cancelled); + } +} From ec87c8f30ae337b09b456c7f872e27df2988da09 Mon Sep 17 00:00:00 2001 From: Andrew Zolotukhin Date: Sat, 17 Oct 2026 11:06:53 +0000 Subject: [PATCH 03/10] feat(deep): add sequential traversal and stable path sorting --- .changeset/deep-traversal-sort.md | 5 ++ libs/deep/README.md | 42 +++++++++ libs/deep/src/deepForEachAsync.test.ts | 120 +++++++++++++++++++++++++ libs/deep/src/deepForEachAsync.ts | 64 +++++++++++++ libs/deep/src/deepSort.test.ts | 39 ++++++++ libs/deep/src/deepSort.ts | 42 +++++++++ libs/deep/src/index.ts | 5 ++ 7 files changed, 317 insertions(+) create mode 100644 .changeset/deep-traversal-sort.md create mode 100644 libs/deep/src/deepForEachAsync.test.ts create mode 100644 libs/deep/src/deepForEachAsync.ts create mode 100644 libs/deep/src/deepSort.test.ts create mode 100644 libs/deep/src/deepSort.ts diff --git a/.changeset/deep-traversal-sort.md b/.changeset/deep-traversal-sort.md new file mode 100644 index 00000000..64991ab9 --- /dev/null +++ b/.changeset/deep-traversal-sort.md @@ -0,0 +1,5 @@ +--- +"@cleverbrush/deep": minor +--- + +Add sequential deepForEachAsync traversal and stable in-place deepSort with typed options, explicit validation and failure propagation. diff --git a/libs/deep/README.md b/libs/deep/README.md index f8c20a5e..2a9e676b 100644 --- a/libs/deep/README.md +++ b/libs/deep/README.md @@ -208,3 +208,45 @@ const hash = HashObject({ name: 'John', age: 30 }); ## License BSD-3-Clause + +### `deepForEachAsync(input, visitor, context?, options?)` + +Visits plain records sequentially in parent-before-child order, awaiting each +visitor before continuing. Arrays, including nested arrays, are containers; +primitives, dates and custom instances are ignored. By default traversal follows +all own array-valued fields on a record. `options.optimizer` selects one such +field instead. Ordinary object-valued fields are not child containers. + +```ts +import { deepForEachAsync } from '@cleverbrush/deep'; + +type Node = { name: string; children?: Node[] }; +await deepForEachAsync(tree, async node => { + await saveNode(node.name); +}, undefined, { optimizer: 'children' }); +``` + +`options.validation(node)` returning false skips that record and its subtree, +while later siblings are still visited. `context` is the visitor's `this` value. +Visitor/validation errors reject the returned promise immediately. Repeated +references are visited at each occurrence; a cycle on the active traversal path +rejects with `TypeError`. Traversal itself does not copy or mutate input; visitors +may mutate the records, and child arrays are read after their parent visitor. + +### `deepSort(items, index, field)` + +Stably sorts and returns the input array in place, using the numeric element at +`item[field][index]`. Equal keys preserve their original order and object identity. + +```ts +import { deepSort } from '@cleverbrush/deep'; + +const nodes = [{ position: [0, 3] }, { position: [0, 1] }]; +deepSort(nodes, 1, 'position'); +// nodes is now [{ position: [0, 1] }, { position: [0, 3] }] +``` + +`index` must be a non-negative integer and exist in every selected field, or a +`RangeError` is thrown. Fields must be arrays containing finite numeric sort keys, +or a `TypeError` is thrown. All keys are checked before the array is changed. +Empty input is valid; path depth is independent of the number of records. diff --git a/libs/deep/src/deepForEachAsync.test.ts b/libs/deep/src/deepForEachAsync.test.ts new file mode 100644 index 00000000..14bb29f6 --- /dev/null +++ b/libs/deep/src/deepForEachAsync.test.ts @@ -0,0 +1,120 @@ +import { describe, expect, it } from 'vitest'; +import { deepForEachAsync } from './deepForEachAsync.js'; + +type Node = { id: string; children?: Node[]; other?: Node[] }; +describe('deepForEachAsync', () => { + it('awaits each parent and child before starting the next sibling', async () => { + const events: string[] = []; + const input = [{ id: 'a', children: [{ id: 'b' }] }, [{ id: 'c' }]]; + await deepForEachAsync(input, async node => { + events.push('start:' + node.id); + await Promise.resolve(); + events.push('end:' + node.id); + }); + expect(events).toEqual([ + 'start:a', + 'end:a', + 'start:b', + 'end:b', + 'start:c', + 'end:c' + ]); + expect(input[0]).toEqual({ id: 'a', children: [{ id: 'b' }] }); + }); + it('uses only the selected own child array and binds context', async () => { + const context = { ids: [] as string[] }; + await deepForEachAsync( + { id: 'a', children: [{ id: 'b' }], other: [{ id: 'c' }] }, + function (this: typeof context, node: Node) { + this.ids.push(node.id); + }, + context, + { optimizer: 'children' } + ); + expect(context.ids).toEqual(['a', 'b']); + }); + it('skips filtered subtrees but keeps visiting later siblings', async () => { + const ids: string[] = []; + await deepForEachAsync( + [{ id: 'skip', children: [{ id: 'hidden' }] }, { id: 'keep' }], + node => ids.push(node.id), + undefined, + { validation: node => node.id !== 'skip' } + ); + expect(ids).toEqual(['keep']); + }); + it('ignores primitives, null, dates and custom objects', async () => { + const seen: object[] = []; + class Opaque {} + await deepForEachAsync( + [ + 1, + null, + undefined, + 'text', + new Date(), + new Opaque(), + { id: 'ok' } + ], + node => seen.push(node) + ); + expect(seen).toEqual([{ id: 'ok' }]); + }); + it('ignores ordinary object-valued properties and inherited arrays', async () => { + const input = { id: 'root', nested: { id: 'not-a-child' } }; + const ids: string[] = []; + await deepForEachAsync( + input, + node => ids.push(node.id), + undefined, + { optimizer: 'children' } + ); + expect(ids).toEqual(['root']); + const inherited = Object.create({ children: [{ id: 'inherited' }] }); + await deepForEachAsync(inherited, () => { + throw new Error('opaque prototype'); + }); + }); + it('visits null-prototype records and repeated references', async () => { + const shared = Object.assign(Object.create(null), { id: 'shared' }); + const ids: string[] = []; + await deepForEachAsync([shared, shared], node => + ids.push(node.id) + ); + expect(ids).toEqual(['shared', 'shared']); + }); + it('rejects record and array cycles', async () => { + const record: Node = { id: 'cycle' }; + record.children = [record]; + const array: unknown[] = []; + array.push(array); + for (const input of [record, array]) { + await expect(deepForEachAsync(input, () => {})).rejects.toThrow( + TypeError + ); + } + }); + it('propagates synchronous and asynchronous visitor failures', async () => { + const failure = new Error('visitor failed'); + for (const visitor of [ + () => { + throw failure; + }, + async () => { + throw failure; + } + ]) { + await expect(deepForEachAsync([{}], visitor)).rejects.toBe(failure); + } + }); + it('propagates validation failures', async () => { + const failure = new Error('validation failed'); + await expect( + deepForEachAsync({}, () => {}, undefined, { + validation: () => { + throw failure; + } + }) + ).rejects.toBe(failure); + }); +}); diff --git a/libs/deep/src/deepForEachAsync.ts b/libs/deep/src/deepForEachAsync.ts new file mode 100644 index 00000000..479d6039 --- /dev/null +++ b/libs/deep/src/deepForEachAsync.ts @@ -0,0 +1,64 @@ +import { isPlainObject } from './data.js'; + +/** Child selection and subtree filtering for sequential record traversal. */ +export interface DeepForEachAsyncOptions { + /** Traverse only this array-valued field; otherwise visit all own array fields. */ + optimizer?: keyof T & string; + /** False skips a record and its descendants, without skipping later siblings. */ + validation?: (node: T) => boolean; +} + +/** + * Visit plain records sequentially, parent before children, awaiting each visitor. + * + * Arrays, including nested arrays, are containers; primitives and opaque objects + * are ignored. Record children are selected from own array-valued properties. + * A shared record is visited at each occurrence; cycles on the active traversal + * path reject with TypeError. This helper does not copy or mutate input, though + * the visitor may mutate its records. Visitor failures reject immediately. + * + * @param input A record or an arbitrarily nested array of records. + * @param visitor Synchronous or asynchronous work for each accepted record. + * @param context Optional visitor `this` value. + * @param options Child-array selection and subtree filtering. + */ +export async function deepForEachAsync< + T extends object = Record, + TContext = undefined +>( + input: unknown, + visitor: (this: TContext, node: T) => unknown, + context?: TContext, + options: DeepForEachAsyncOptions = {} +): Promise { + const active = new Set(); + async function visit(value: unknown): Promise { + const array = Array.isArray(value); + if (!array && !isPlainObject(value)) return; + const node = value as T; + if (!array && options.validation && !options.validation(node)) return; + if (active.has(value as object)) { + throw new TypeError('Cannot traverse circular data.'); + } + active.add(value as object); + try { + if (array) { + for (const child of value as unknown[]) await visit(child); + return; + } + await visitor.call(context as TContext, node); + const keys = + options.optimizer === undefined + ? Object.keys(node) + : [options.optimizer]; + for (const key of keys) { + if (!Object.hasOwn(node, key)) continue; + const child = (node as Record)[key]; + if (Array.isArray(child)) await visit(child); + } + } finally { + active.delete(value as object); + } + } + await visit(input); +} diff --git a/libs/deep/src/deepSort.test.ts b/libs/deep/src/deepSort.test.ts new file mode 100644 index 00000000..1528e06b --- /dev/null +++ b/libs/deep/src/deepSort.test.ts @@ -0,0 +1,39 @@ +import { describe, expect, it } from 'vitest'; +import { deepSort } from './deepSort.js'; + +describe('deepSort', () => { + it('sorts in place and preserves ties and object identity', () => { + const a = { path: [3, 2], id: 'a' }; + const b = { path: [1, 1], id: 'b' }; + const c = { path: [0, 2], id: 'c' }; + const input = [a, b, c]; + expect(deepSort(input, 1, 'path')).toBe(input); + expect(input).toEqual([b, a, c]); + expect(input[1]).toBe(a); + }); + it('validates depth against each path rather than record count', () => { + const input = [{ path: [8, 4, 1] }]; + expect(deepSort(input, 2, 'path')).toEqual(input); + expect(deepSort([], 5, 'path')).toEqual([]); + }); + it.each([-1, 0.5, NaN, Infinity])('rejects invalid index %s', index => { + expect(() => deepSort([{ path: [1] }], index, 'path')).toThrow( + RangeError + ); + }); + it('rejects an out-of-bounds path before mutating', () => { + const input = [{ path: [2, 0] }, { path: [1] }]; + const before = [...input]; + expect(() => deepSort(input, 1, 'path')).toThrow(RangeError); + expect(input).toEqual(before); + }); + it.each([undefined, null, 1, {}, 'value', [NaN], [Infinity], ['1']])( + 'rejects invalid sort field %s', + path => { + expect(() => deepSort([{ path }], 0, 'path')).toThrow(TypeError); + } + ); + it('rejects non-array input', () => { + expect(() => deepSort(null as never, 0, 'path')).toThrow(TypeError); + }); +}); diff --git a/libs/deep/src/deepSort.ts b/libs/deep/src/deepSort.ts new file mode 100644 index 00000000..3e48481e --- /dev/null +++ b/libs/deep/src/deepSort.ts @@ -0,0 +1,42 @@ +/** + * Stably sort records in place by one numeric position in an array-valued field. + * + * All keys are validated before changing the input. An invalid index rejects + * with RangeError; missing/non-array fields and non-finite keys reject with + * TypeError. Empty input is valid. Equal keys retain their original order. + * + * @example + * ```ts + * deepSort([{ path: [2, 0] }, { path: [1, 4] }], 0, 'path'); + * // => [{ path: [1, 4] }, { path: [2, 0] }] + * ``` + */ +export function deepSort( + items: T[], + index: number, + field: keyof T +): T[] { + if (!Number.isSafeInteger(index) || index < 0) { + throw new RangeError('index must be a non-negative integer.'); + } + if (!Array.isArray(items)) throw new TypeError('items must be an array.'); + const sorted = items.map(item => { + const values = item?.[field]; + if (!Array.isArray(values)) { + throw new TypeError('The selected field must be an array.'); + } + if (index >= values.length) { + throw new RangeError('index exceeds a selected field length.'); + } + const key = values[index]; + if (typeof key !== 'number' || !Number.isFinite(key)) { + throw new TypeError('Sort keys must be finite numbers.'); + } + return { item, key }; + }); + sorted.sort((a, b) => a.key - b.key); + sorted.forEach(({ item }, position) => { + items[position] = item; + }); + return items; +} diff --git a/libs/deep/src/index.ts b/libs/deep/src/index.ts index 6d58eb19..e6bde5f9 100644 --- a/libs/deep/src/index.ts +++ b/libs/deep/src/index.ts @@ -3,6 +3,11 @@ import { deepEqual } from './deepEqual.js'; import { deepExtend, type Merge, type MergeTwo } from './deepExtend.js'; import { deepFlatten } from './deepFlatten.js'; +export { + type DeepForEachAsyncOptions, + deepForEachAsync +} from './deepForEachAsync.js'; +export { deepSort } from './deepSort.js'; export { deepClone, deepEqual, From 9207eff3c8dc420e8224d30e5533b7d837d3dc16 Mon Sep 17 00:00:00 2001 From: Andrew Zolotukhin Date: Sat, 17 Oct 2026 11:39:11 +0000 Subject: [PATCH 04/10] fix(deep): reject sparse sort input before mutation --- .changeset/deep-sort-sparse.md | 5 +++++ libs/deep/README.md | 1 + libs/deep/src/deepSort.test.ts | 9 +++++++++ libs/deep/src/deepSort.ts | 3 ++- 4 files changed, 17 insertions(+), 1 deletion(-) create mode 100644 .changeset/deep-sort-sparse.md diff --git a/.changeset/deep-sort-sparse.md b/.changeset/deep-sort-sparse.md new file mode 100644 index 00000000..58f887f7 --- /dev/null +++ b/.changeset/deep-sort-sparse.md @@ -0,0 +1,5 @@ +--- +"@cleverbrush/deep": patch +--- + +Reject sparse record arrays before sorting so missing elements cannot duplicate existing records or partially mutate input. diff --git a/libs/deep/README.md b/libs/deep/README.md index 2a9e676b..7a7302ab 100644 --- a/libs/deep/README.md +++ b/libs/deep/README.md @@ -250,3 +250,4 @@ deepSort(nodes, 1, 'position'); `RangeError` is thrown. Fields must be arrays containing finite numeric sort keys, or a `TypeError` is thrown. All keys are checked before the array is changed. Empty input is valid; path depth is independent of the number of records. +Sparse arrays and missing records are rejected before mutation. diff --git a/libs/deep/src/deepSort.test.ts b/libs/deep/src/deepSort.test.ts index 1528e06b..3ea7ce23 100644 --- a/libs/deep/src/deepSort.test.ts +++ b/libs/deep/src/deepSort.test.ts @@ -37,3 +37,12 @@ describe('deepSort', () => { expect(() => deepSort(null as never, 0, 'path')).toThrow(TypeError); }); }); + +it('rejects sparse input before sorting can duplicate an existing item', () => { + const input = new Array<{ path: number[] }>(2); + const existing = { path: [1] }; + input[1] = existing; + expect(() => deepSort(input, 0, 'path')).toThrow(TypeError); + expect(0 in input).toBe(false); + expect(input[1]).toBe(existing); +}); diff --git a/libs/deep/src/deepSort.ts b/libs/deep/src/deepSort.ts index 3e48481e..e5967b32 100644 --- a/libs/deep/src/deepSort.ts +++ b/libs/deep/src/deepSort.ts @@ -1,6 +1,7 @@ /** * Stably sort records in place by one numeric position in an array-valued field. * + * Input must be a dense array of records; missing entries reject before mutation. * All keys are validated before changing the input. An invalid index rejects * with RangeError; missing/non-array fields and non-finite keys reject with * TypeError. Empty input is valid. Equal keys retain their original order. @@ -20,7 +21,7 @@ export function deepSort( throw new RangeError('index must be a non-negative integer.'); } if (!Array.isArray(items)) throw new TypeError('items must be an array.'); - const sorted = items.map(item => { + const sorted = Array.from(items, item => { const values = item?.[field]; if (!Array.isArray(values)) { throw new TypeError('The selected field must be an array.'); From 0f9d63efa10fdba1360d0dcc939af365f301e766 Mon Sep 17 00:00:00 2001 From: Andrew Zolotukhin Date: Sun, 18 Oct 2026 10:05:23 +0000 Subject: [PATCH 05/10] feat(react-form): add blur validation and invalid submission callbacks --- .changeset/react-form-blur-lifecycle.md | 7 + libs/react-form/README.md | 30 ++- .../react-form/src/blur-submission.test-d.tsx | 32 +++ libs/react-form/src/blur-submission.test.tsx | 227 ++++++++++++++++++ libs/react-form/src/contexts.ts | 5 +- libs/react-form/src/hooks.ts | 23 +- libs/react-form/src/types.ts | 15 +- 7 files changed, 324 insertions(+), 15 deletions(-) create mode 100644 .changeset/react-form-blur-lifecycle.md create mode 100644 libs/react-form/src/blur-submission.test-d.tsx create mode 100644 libs/react-form/src/blur-submission.test.tsx diff --git a/.changeset/react-form-blur-lifecycle.md b/.changeset/react-form-blur-lifecycle.md new file mode 100644 index 00000000..3226733a --- /dev/null +++ b/.changeset/react-form-blur-lifecycle.md @@ -0,0 +1,7 @@ +--- +"@cleverbrush/react-form": minor +--- + +Add opt-in immediate blur validation that touches only the blurred field, and an +awaitable invalid-submission callback with existing duplicate and stale-result +protection. Existing blur and submission defaults remain unchanged. diff --git a/libs/react-form/README.md b/libs/react-form/README.md index f0443fea..06a14aeb 100644 --- a/libs/react-form/README.md +++ b/libs/react-form/README.md @@ -430,7 +430,8 @@ Creates a form instance bound to a schema. Returns field binding and form lifecy ```tsx const form = useSchemaForm(UserSchema, { createMissingStructure: true, // default: true — auto-create parent objects when setting nested values - validateOnMount: false, // default: false — set to true to show errors immediately on mount + validateOnMount: false, // default: false — set to true to show errors immediately + validateOnBlur: true, // opt in; touches only the blurred field on mount validationDebounceMs: 300 // optional — debounce onChange validation (ms); validate()/submit() are always immediate }); ``` @@ -760,3 +761,30 @@ function App() { ## License BSD-3-Clause + +## Blur validation and rejected inline edits + +Set `validateOnBlur: true` to validate immediately when a field blurs, even when +change validation is debounced. Only the blurred field becomes touched; errors on +other fields remain available without forcing their messages to appear. The +option defaults to false, preserving touch-only blur behavior for existing forms. +Explicit `validate()` and submissions continue to touch all fields. + +Managed submission accepts an optional `onInvalid(result)` callback. It runs only +for current invalid validation and is awaited under the same duplicate-submission +lock as a successful submission. Values changed during validation, reset and +unmount suppress stale callbacks. Exceptions from `onInvalid` propagate and are +not translated by `onError`, because no write was attempted. + +```tsx +const form = useSchemaForm(QuantitySchema, { validateOnBlur: true }); +const quantity = form.useField(t => t.quantity); +const commit = form.handleSubmit(saveQuantity, { + onInvalid: () => form.reset(savedQuantity) +}); +// Application policy: an inline editor can restore its saved baseline on blur. +// Explicit form submission can use a handler without onInvalid to keep errors. +``` + +The callback receives the native failed `ValidationResult`; custom validators +can leave `errors` undefined. No UI or reset policy is chosen by the package. diff --git a/libs/react-form/src/blur-submission.test-d.tsx b/libs/react-form/src/blur-submission.test-d.tsx new file mode 100644 index 00000000..6add877e --- /dev/null +++ b/libs/react-form/src/blur-submission.test-d.tsx @@ -0,0 +1,32 @@ +import { object, string, type ValidationResult } from '@cleverbrush/schema'; +import { expectTypeOf, test } from 'vitest'; +import { useSchemaForm } from './hooks.js'; +import type { FormSubmitOptions, UseSchemaFormOptions } from './types.js'; + +const schema = object({ name: string() }); +test('blur and invalid-submit options preserve public value types', () => { + const options: UseSchemaFormOptions = { validateOnBlur: true }; + const form = useSchemaForm(schema, options); + form.handleSubmit( + values => { + expectTypeOf(values).toEqualTypeOf<{ name: string }>(); + }, + { + onInvalid: async result => { + expectTypeOf(result).toEqualTypeOf< + ValidationResult<{ name: string }> + >(); + } + } + ); + const invalidOptions: UseSchemaFormOptions = { + // @ts-expect-error Blur validation is an opt-in boolean. + validateOnBlur: 'always' + }; + const wrongCallback: FormSubmitOptions<{ name: string }> = { + // @ts-expect-error Invalid validation still carries the schema's value type. + onInvalid: (_result: ValidationResult<{ count: number }>) => {} + }; + void invalidOptions; + void wrongCallback; +}); diff --git a/libs/react-form/src/blur-submission.test.tsx b/libs/react-form/src/blur-submission.test.tsx new file mode 100644 index 00000000..2e785cb2 --- /dev/null +++ b/libs/react-form/src/blur-submission.test.tsx @@ -0,0 +1,227 @@ +import { object, string } from '@cleverbrush/schema'; +import { act, cleanup, renderHook, waitFor } from '@testing-library/react'; +import { afterEach, describe, expect, test, vi } from 'vitest'; +import { useSchemaForm } from './hooks.js'; + +const schema = object({ + first: string().minLength(1, 'First required'), + second: string().minLength(1, 'Second required') +}); +function deferred() { + let resolve!: (value: T) => void; + const promise = new Promise(done => { + resolve = done; + }); + return { promise, resolve }; +} +function bound(options = {}) { + return renderHook(() => { + const form = useSchemaForm(schema, options); + return { + form, + first: form.useField(t => t.first), + second: form.useField(t => t.second) + }; + }); +} +afterEach(() => { + cleanup(); + vi.restoreAllMocks(); + vi.useRealTimers(); +}); +describe('opt-in immediate blur validation', () => { + test('keeps touch-only behavior by default', () => { + const validate = vi.spyOn(schema, 'validateAsync'); + const hook = bound(); + act(() => hook.result.current.form.reset({ first: '', second: '' })); + act(() => hook.result.current.first.onBlur()); + expect(hook.result.current.first.touched).toBe(true); + expect(hook.result.current.second.touched).toBe(false); + expect(validate).not.toHaveBeenCalled(); + }); + test('validates untouched empty input and touches only the blurred field', async () => { + const hook = bound({ validateOnBlur: true }); + act(() => hook.result.current.form.reset({ first: '', second: '' })); + act(() => hook.result.current.first.onBlur()); + await waitFor(() => + expect(hook.result.current.first.error).toBe('First required') + ); + expect(hook.result.current.first.touched).toBe(true); + expect(hook.result.current.second.error).toBe('Second required'); + expect(hook.result.current.second.touched).toBe(false); + act(() => hook.result.current.first.onChange('ok')); + await waitFor(() => + expect(hook.result.current.first.error).toBeUndefined() + ); + }); + test('flushes debounce once without a second scheduled validation', async () => { + vi.useFakeTimers(); + const validate = vi.spyOn(schema, 'validateAsync'); + const hook = bound({ validateOnBlur: true, validationDebounceMs: 300 }); + act(() => + hook.result.current.form.reset({ first: 'ok', second: 'ok' }) + ); + act(() => hook.result.current.first.onChange('')); + expect(validate).not.toHaveBeenCalled(); + await act(async () => { + hook.result.current.first.onBlur(); + }); + expect(validate).toHaveBeenCalledTimes(1); + expect(hook.result.current.first.error).toBe('First required'); + await act(() => vi.advanceTimersByTimeAsync(500)); + expect(validate).toHaveBeenCalledTimes(1); + expect(hook.result.current.second.touched).toBe(false); + }); + test.each(['change', 'reset', 'unmount'] as const)( + 'ignores stale blur errors after %s', + async change => { + const pending = deferred<{ + valid: false; + errors: { message: string }[]; + }>(); + const guarded = object({ + name: string().addValidator(() => pending.promise) + }); + const hook = renderHook(() => { + const form = useSchemaForm(guarded, { + validateOnBlur: true, + validationDebounceMs: 300 + }); + return { form, name: form.useField(t => t.name) }; + }); + act(() => hook.result.current.form.reset({ name: 'old' })); + act(() => hook.result.current.name.onBlur()); + if (change === 'change') + act(() => hook.result.current.form.setValue({ name: 'new' })); + else if (change === 'reset') + act(() => hook.result.current.form.reset({ name: 'new' })); + else hook.unmount(); + await act(async () => { + pending.resolve({ + valid: false, + errors: [{ message: 'Old error' }] + }); + }); + if (change !== 'unmount') { + expect(hook.result.current.name.value).toBe('new'); + expect(hook.result.current.name.error).toBeUndefined(); + expect(hook.result.current.name.validating).toBe(false); + } + } + ); +}); +describe('managed invalid submissions', () => { + test('passes failure to application policy without calling the writer', async () => { + const hook = bound(); + act(() => + hook.result.current.form.reset({ first: '', second: 'saved' }) + ); + const write = vi.fn(); + const invalid = vi.fn(result => { + expect(result.valid).toBe(false); + hook.result.current.form.reset({ first: 'saved', second: 'saved' }); + }); + await act(() => + hook.result.current.form.handleSubmit(write, { + onInvalid: invalid + })() + ); + expect(invalid).toHaveBeenCalledOnce(); + expect(write).not.toHaveBeenCalled(); + expect(hook.result.current.form.getValue()).toEqual({ + first: 'saved', + second: 'saved' + }); + expect(hook.result.current.first.touched).toBe(false); + expect(hook.result.current.form.submitting).toBe(false); + }); + test('holds duplicate protection until an asynchronous invalid callback settles', async () => { + const hook = bound(); + act(() => hook.result.current.form.reset({ first: '', second: '' })); + const pending = deferred(); + const invalid = vi.fn(() => pending.promise); + const handler = hook.result.current.form.handleSubmit(vi.fn(), { + onInvalid: invalid + }); + let first!: Promise; + await act(async () => { + first = handler(); + await Promise.resolve(); + }); + await waitFor(() => expect(invalid).toHaveBeenCalledOnce()); + await act(() => handler()); + expect(invalid).toHaveBeenCalledOnce(); + expect(hook.result.current.form.submitting).toBe(true); + await act(async () => { + pending.resolve(); + await first; + }); + expect(hook.result.current.form.submitting).toBe(false); + }); + test('propagates invalid-callback exceptions and releases the lock for retry', async () => { + const hook = bound(); + act(() => hook.result.current.form.reset({ first: '', second: '' })); + const error = new Error('application callback'); + const onError = vi.fn(); + await act(async () => { + await expect( + hook.result.current.form.handleSubmit(vi.fn(), { + onInvalid: () => { + throw error; + }, + onError + })() + ).rejects.toBe(error); + }); + expect(onError).not.toHaveBeenCalled(); + expect(hook.result.current.form.submitting).toBe(false); + act(() => + hook.result.current.form.setValue({ first: 'ok', second: 'ok' }) + ); + const write = vi.fn(); + const invalid = vi.fn(); + await act(() => + hook.result.current.form.handleSubmit(write, { + onInvalid: invalid + })() + ); + expect(write).toHaveBeenCalledOnce(); + expect(invalid).not.toHaveBeenCalled(); + }); + test.each(['change', 'reset', 'unmount'] as const)( + 'suppresses invalid callbacks after %s during validation', + async change => { + const pending = deferred<{ + valid: false; + errors: { message: string }[]; + }>(); + const guarded = object({ + name: string().addValidator(() => pending.promise) + }); + const hook = renderHook(() => useSchemaForm(guarded)); + act(() => hook.result.current.reset({ name: 'old' })); + const write = vi.fn(); + const invalid = vi.fn(); + let submission!: Promise; + act(() => { + submission = hook.result.current.handleSubmit(write, { + onInvalid: invalid + })(); + }); + if (change === 'change') + act(() => hook.result.current.setValue({ name: 'new' })); + else if (change === 'reset') + act(() => hook.result.current.reset({ name: 'new' })); + else hook.unmount(); + await act(async () => { + pending.resolve({ + valid: false, + errors: [{ message: 'Old error' }] + }); + await submission; + }); + expect(invalid).not.toHaveBeenCalled(); + expect(write).not.toHaveBeenCalled(); + } + ); +}); diff --git a/libs/react-form/src/contexts.ts b/libs/react-form/src/contexts.ts index ddea0016..6d903ce4 100644 --- a/libs/react-form/src/contexts.ts +++ b/libs/react-form/src/contexts.ts @@ -22,7 +22,10 @@ export type FormContextValue = { schema: ObjectSchemaBuilder; options: UseSchemaFormOptions; pathMap: Map, string>; - triggerValidation?: (markTouched: boolean) => Promise; + triggerValidation?: ( + markTouched: boolean, + immediate?: boolean + ) => Promise; }; /** diff --git a/libs/react-form/src/hooks.ts b/libs/react-form/src/hooks.ts index 350e61a5..16d31904 100644 --- a/libs/react-form/src/hooks.ts +++ b/libs/react-form/src/hooks.ts @@ -223,10 +223,10 @@ export function useSchemaForm< [store, cancelScheduledValidation] ); const triggerValidation = useCallback( - (markTouched: boolean) => { + (markTouched: boolean, immediate = false) => { cancelScheduledValidation(); const delay = optionsRef.current.validationDebounceMs; - if (delay != null && delay > 0) { + if (!immediate && delay != null && delay > 0) { timerRef.current = setTimeout(() => { timerRef.current = null; void runValidation(markTouched); @@ -260,13 +260,12 @@ export function useSchemaForm< try { const revision = store.getRevision(); const result = await runValidation(true); - if ( - !current() || - revision !== store.getRevision() || - !result.valid || - result.object === undefined - ) + if (!current() || revision !== store.getRevision()) return; + if (!result.valid) { + await submissionOptions?.onInvalid?.(result); return; + } + if (result.object === undefined) return; const values = result.object; let outcome: FormSubmitResult; try { @@ -404,10 +403,10 @@ export function useFieldFromContext( }, [store, path, options.createMissingStructure, triggerValidation] ); - const onBlur = useCallback( - () => store.updateFieldState(path, { touched: true }), - [store, path] - ); + const onBlur = useCallback(() => { + store.updateFieldState(path, { touched: true }); + if (options.validateOnBlur) void triggerValidation?.(false, true); + }, [store, path, options.validateOnBlur, triggerValidation]); return { ...fieldState, onChange, diff --git a/libs/react-form/src/types.ts b/libs/react-form/src/types.ts index d72a6657..83504ece 100644 --- a/libs/react-form/src/types.ts +++ b/libs/react-form/src/types.ts @@ -1,4 +1,4 @@ -import type { SchemaBuilder } from '@cleverbrush/schema'; +import type { SchemaBuilder, ValidationResult } from '@cleverbrush/schema'; import type { FormEvent, ReactNode } from 'react'; /** @@ -123,6 +123,13 @@ export type UseSchemaFormOptions = { * @default false */ validateOnMount?: boolean; + /** + * Validate immediately when a field blurs, cancelling pending debounced + * validation. Only that field becomes touched; other fields keep their state. + * Existing change-triggered validation is unaffected. + * @default false + */ + validateOnBlur?: boolean; /** * Debounce delay in milliseconds for onChange-triggered validation. * When set, rapid field changes only trigger one validation run after @@ -164,6 +171,12 @@ export type FormSubmitResult = /** Application-owned success UI and exception translation. Rethrows propagate. */ export type FormSubmitOptions = { + /** + * Awaited for current invalid validation, before releasing the submission + * lock. Values changed during validation, reset and unmount suppress it. + * Exceptions propagate instead of being translated as failed writes. + */ + onInvalid?: (result: ValidationResult) => void | Promise; onSuccess?: ( data: TData | undefined, values: TValues From 2ea376f398bfd184362c720f9df1e3af6ed1d625 Mon Sep 17 00:00:00 2001 From: Andrew Zolotukhin Date: Sun, 18 Oct 2026 10:22:45 +0000 Subject: [PATCH 06/10] feat(react-form): refresh validation rules without resetting drafts --- .changeset/react-form-blur-lifecycle.md | 3 +- libs/react-form/README.md | 18 ++++ .../react-form/src/blur-submission.test-d.tsx | 5 +- libs/react-form/src/hooks.ts | 13 +++ libs/react-form/src/rule-refresh.test.tsx | 102 ++++++++++++++++++ libs/react-form/src/types.ts | 8 ++ 6 files changed, 147 insertions(+), 2 deletions(-) create mode 100644 libs/react-form/src/rule-refresh.test.tsx diff --git a/.changeset/react-form-blur-lifecycle.md b/.changeset/react-form-blur-lifecycle.md index 3226733a..e0b15f2b 100644 --- a/.changeset/react-form-blur-lifecycle.md +++ b/.changeset/react-form-blur-lifecycle.md @@ -4,4 +4,5 @@ Add opt-in immediate blur validation that touches only the blurred field, and an awaitable invalid-submission callback with existing duplicate and stale-result -protection. Existing blur and submission defaults remain unchanged. +protection. Opt-in validation-rule refresh retains edited values and field state +while adopting current bounds/messages and suppressing stale callbacks. Existing blur and submission defaults remain unchanged. diff --git a/libs/react-form/README.md b/libs/react-form/README.md index 06a14aeb..a0824c7e 100644 --- a/libs/react-form/README.md +++ b/libs/react-form/README.md @@ -788,3 +788,21 @@ const commit = form.handleSubmit(saveQuantity, { The callback receives the native failed `ValidationResult`; custom validators can leave `errors` undefined. No UI or reset policy is chosen by the package. + +## Refreshing validation rules + +Schemas are captured once by default. Set `refreshValidationRules: true` when +bounds or translated messages change while the field names and value types stay +fixed. Memoize the schema by those rule dependencies; do not construct a new +schema on every form-state render. A rule update immediately revalidates without +changing values, initial baselines, dirty state or which fields are touched. Older +validation and managed submission callbacks are ignored. Field renderers keep +the original binding schema; mount a new form when the field structure or types +change, rather than using this option for a different form model. + +```tsx +const schema = useMemo(() => object({ + quantity: number().min(minimum, minimumMessage) +}), [minimum, minimumMessage]); +const form = useSchemaForm(schema, { refreshValidationRules: true }); +``` diff --git a/libs/react-form/src/blur-submission.test-d.tsx b/libs/react-form/src/blur-submission.test-d.tsx index 6add877e..28f4ac6b 100644 --- a/libs/react-form/src/blur-submission.test-d.tsx +++ b/libs/react-form/src/blur-submission.test-d.tsx @@ -5,7 +5,10 @@ import type { FormSubmitOptions, UseSchemaFormOptions } from './types.js'; const schema = object({ name: string() }); test('blur and invalid-submit options preserve public value types', () => { - const options: UseSchemaFormOptions = { validateOnBlur: true }; + const options: UseSchemaFormOptions = { + validateOnBlur: true, + refreshValidationRules: true + }; const form = useSchemaForm(schema, options); form.handleSubmit( values => { diff --git a/libs/react-form/src/hooks.ts b/libs/react-form/src/hooks.ts index 16d31904..3a7bacbf 100644 --- a/libs/react-form/src/hooks.ts +++ b/libs/react-form/src/hooks.ts @@ -13,6 +13,7 @@ import { import { useCallback, useEffect, + useLayoutEffect, useMemo, useRef, useSyncExternalStore @@ -37,6 +38,9 @@ import type { UseSchemaFormOptions } from './types.js'; +const useBeforePaint = + typeof window === 'undefined' ? useEffect : useLayoutEffect; + /** A stable form controller with reactive field and submission subscriptions. */ export type SchemaFormInstance< TSchema extends ObjectSchemaBuilder @@ -200,6 +204,15 @@ export function useSchemaForm< [cancelScheduledValidation, store] ); + useBeforePaint(() => { + if (!options?.refreshValidationRules || schemaRef.current === schema) + return; + schemaRef.current = schema; + epochRef.current++; + validationGenRef.current++; + void runValidation(false); + }, [schema, options?.refreshValidationRules, runValidation]); + const validate = useCallback(() => runValidation(true), [runValidation]); const submit = useCallback(() => validate(), [validate]); const reset = useCallback( diff --git a/libs/react-form/src/rule-refresh.test.tsx b/libs/react-form/src/rule-refresh.test.tsx new file mode 100644 index 00000000..b885d00e --- /dev/null +++ b/libs/react-form/src/rule-refresh.test.tsx @@ -0,0 +1,102 @@ +import { object, string } from '@cleverbrush/schema'; +import { act, cleanup, renderHook, waitFor } from '@testing-library/react'; +import { useMemo } from 'react'; +import { afterEach, expect, test, vi } from 'vitest'; +import { useSchemaForm } from './hooks.js'; + +afterEach(cleanup); +function rules(minimum: number) { + return object({ + name: string().minLength(minimum, `Minimum ${minimum}`), + note: string().optional() + }); +} +function useRules(minimum: number, enabled?: boolean) { + const schema = useMemo(() => rules(minimum), [minimum]); + const form = useSchemaForm(schema, { refreshValidationRules: enabled }); + return { + form, + name: form.useField(t => t.name), + note: form.useField(t => t.note) + }; +} +test('captures the first schema unless refresh is enabled', async () => { + const hook = renderHook(({ minimum }) => useRules(minimum), { + initialProps: { minimum: 1 } + }); + act(() => hook.result.current.form.reset({ name: 'ab' })); + hook.rerender({ minimum: 3 }); + await act(() => hook.result.current.form.validate()); + expect(hook.result.current.name.error).toBeUndefined(); +}); +test('adopts new bounds/messages without discarding values or field state', async () => { + const hook = renderHook(({ minimum }) => useRules(minimum, true), { + initialProps: { minimum: 1 } + }); + act(() => hook.result.current.form.reset({ name: 'saved' })); + act(() => { + hook.result.current.name.onChange('ab'); + hook.result.current.name.onBlur(); + }); + await waitFor(() => + expect(hook.result.current.name.validating).toBe(false) + ); + hook.rerender({ minimum: 3 }); + await waitFor(() => + expect(hook.result.current.name.error).toBe('Minimum 3') + ); + expect(hook.result.current.name).toMatchObject({ + value: 'ab', + initialValue: 'saved', + dirty: true, + touched: true + }); + expect(hook.result.current.note.touched).toBe(false); + hook.rerender({ minimum: 1 }); + await waitFor(() => expect(hook.result.current.name.error).toBeUndefined()); + expect(hook.result.current.name.dirty).toBe(true); +}); +test('discards obsolete managed validation after a rule change', async () => { + let resolve!: (value: { + valid: false; + errors: { message: string }[]; + }) => void; + const pending = new Promise<{ + valid: false; + errors: { message: string }[]; + }>(done => { + resolve = done; + }); + const first = object({ name: string().addValidator(() => pending) }); + const second = object({ name: string() }); + const hook = renderHook( + ({ schema }) => { + const form = useSchemaForm(schema, { + refreshValidationRules: true + }); + return { form, name: form.useField(t => t.name) }; + }, + { initialProps: { schema: first } } + ); + act(() => hook.result.current.form.reset({ name: 'current' })); + const write = vi.fn(), + invalid = vi.fn(); + let submitted!: Promise; + act(() => { + submitted = hook.result.current.form.handleSubmit(write, { + onInvalid: invalid + })(); + }); + hook.rerender({ schema: second }); + await waitFor(() => + expect(hook.result.current.name.validating).toBe(false) + ); + await act(async () => { + resolve({ valid: false, errors: [{ message: 'obsolete' }] }); + await submitted; + }); + expect(write).not.toHaveBeenCalled(); + expect(invalid).not.toHaveBeenCalled(); + expect(hook.result.current.name.error).toBeUndefined(); + expect(hook.result.current.name.value).toBe('current'); +}); diff --git a/libs/react-form/src/types.ts b/libs/react-form/src/types.ts index 83504ece..d82f707e 100644 --- a/libs/react-form/src/types.ts +++ b/libs/react-form/src/types.ts @@ -130,6 +130,14 @@ export type UseSchemaFormOptions = { * @default false */ validateOnBlur?: boolean; + /** + * Adopt changed validation rules without resetting values, touched or dirty. + * Field names and value types must stay fixed for the form's lifetime. + * Changes invalidate older validation/submission callbacks and revalidate + * immediately without touching additional fields. + * @default false + */ + refreshValidationRules?: boolean; /** * Debounce delay in milliseconds for onChange-triggered validation. * When set, rapid field changes only trigger one validation run after From 30e1e3f5ba7fc7521118d6417aa9539dc1f4a84c Mon Sep 17 00:00:00 2001 From: Andrew Zolotukhin Date: Wed, 21 Oct 2026 11:38:14 +0000 Subject: [PATCH 07/10] docs: updated documentation --- .changeset/deep-sort-sparse.md | 5 - .changeset/deep-traversal-sort.md | 5 - .changeset/react-form-blur-lifecycle.md | 8 - .changeset/request-cancellation.md | 5 - .../typed-paths-and-transaction-locks.md | 12 - .dockerignore | 9 +- README.md | 15 + libs/async/CHANGELOG.md | 17 +- libs/async/package.json | 2 +- libs/auth/CHANGELOG.md | 22 +- libs/auth/package.json | 4 +- libs/client/CHANGELOG.md | 32 +- libs/client/package.json | 6 +- libs/deep/CHANGELOG.md | 25 +- libs/deep/package.json | 2 +- libs/di/CHANGELOG.md | 28 +- libs/di/package.json | 4 +- libs/env/CHANGELOG.md | 23 +- libs/env/package.json | 4 +- libs/knex-clickhouse/CHANGELOG.md | 24 +- libs/knex-clickhouse/package.json | 6 +- libs/knex-schema/CHANGELOG.md | 42 +- libs/knex-schema/package.json | 4 +- libs/log/CHANGELOG.md | 23 +- libs/log/package.json | 6 +- libs/mapper/CHANGELOG.md | 28 +- libs/mapper/package.json | 4 +- libs/orm-cli/CHANGELOG.md | 21 +- libs/orm-cli/package.json | 2 +- libs/orm/CHANGELOG.md | 51 +- libs/orm/package.json | 6 +- libs/otel/CHANGELOG.md | 17 +- libs/otel/package.json | 2 +- libs/react-form/CHANGELOG.md | 32 +- libs/react-form/package.json | 6 +- libs/scheduler-postgres/CHANGELOG.md | 23 +- libs/scheduler-postgres/package.json | 10 +- libs/scheduler/CHANGELOG.md | 29 +- libs/scheduler/package.json | 4 +- libs/schema-json/CHANGELOG.md | 17 +- libs/schema-json/package.json | 2 +- libs/schema/CHANGELOG.md | 32 +- libs/schema/package.json | 4 +- libs/server-openapi/CHANGELOG.md | 19 +- libs/server-openapi/package.json | 2 +- libs/server/CHANGELOG.md | 35 +- libs/server/package.json | 8 +- libs/storage-s3/CHANGELOG.md | 12 +- libs/storage-s3/package.json | 4 +- libs/storage/CHANGELOG.md | 8 +- libs/storage/package.json | 2 +- package-lock.json | 128 +- package.json | 2 +- scripts/docs.mjs | 117 + scripts/docs.test.mjs | 199 ++ scripts/snapshot-docs.sh | 14 +- websites/docs/Dockerfile | 34 +- websites/docs/next.config.ts | 8 +- websites/docs/public/api-docs/index.html | 3 + .../docs/public/api-docs/v5.1.0/.nojekyll | 1 + websites/docs/public/api-docs/v5.1.0/LICENSE | 28 + .../api-docs/v5.1.0/assets/hierarchy.js | 1 + .../api-docs/v5.1.0/assets/highlight.css | 176 ++ .../public/api-docs/v5.1.0/assets/icons.js | 18 + .../public/api-docs/v5.1.0/assets/icons.svg | 1 + .../public/api-docs/v5.1.0/assets/main.js | 60 + .../api-docs/v5.1.0/assets/navigation.js | 1 + .../public/api-docs/v5.1.0/assets/search.js | 1 + .../public/api-docs/v5.1.0/assets/style.css | 1648 ++++++++++++++ .../classes/_cleverbrush_async.Collector.html | 662 ++++++ .../_cleverbrush_async.TimeoutError.html | 197 ++ ...cleverbrush_auth.AuthorizationService.html | 115 + .../_cleverbrush_auth.PolicyBuilder.html | 123 + .../classes/_cleverbrush_auth.Principal.html | 162 ++ .../_cleverbrush_client..ApiError.html | 157 ++ .../_cleverbrush_client..NetworkError.html | 122 + .../_cleverbrush_client..OfflineError.html | 115 + .../_cleverbrush_client..TimeoutError.html | 127 ++ .../_cleverbrush_client..WebError.html | 124 + ..._cleverbrush_di.ScopedServiceProvider.html | 169 ++ .../_cleverbrush_di.ServiceCollection.html | 449 ++++ .../_cleverbrush_di.ServiceProvider.html | 238 ++ .../classes/_cleverbrush_di.ServiceScope.html | 200 ++ .../_cleverbrush_env.EnvValidationError.html | 203 ++ ..._knex-clickhouse.ClickhouseKnexClient.html | 1600 +++++++++++++ ...rush_knex-schema..AliasedQueryBuilder.html | 1157 ++++++++++ .../_cleverbrush_knex-schema..Entity.html | 334 +++ ..._cleverbrush_knex-schema..OpaqueQuery.html | 266 +++ ..._knex-schema..PolymorphicQueryBuilder.html | 1347 +++++++++++ ...verbrush_knex-schema..ReadSchemaError.html | 189 ++ ...brush_knex-schema..SchemaQueryBuilder.html | 2004 +++++++++++++++++ .../_cleverbrush_log..BatchingSink.html | 134 ++ .../classes/_cleverbrush_log..Logger.html | 478 ++++ .../classes/_cleverbrush_mapper.Mapper.html | 219 ++ ...brush_mapper.MapperConfigurationError.html | 107 + .../_cleverbrush_mapper.MappingRegistry.html | 194 ++ ...erbrush_mapper.PropertyMappingBuilder.html | 169 ++ .../_cleverbrush_orm.AliasedQueryBuilder.html | 1152 ++++++++++ .../_cleverbrush_orm.ConcurrencyError.html | 216 ++ .../classes/_cleverbrush_orm.Entity.html | 333 +++ .../_cleverbrush_orm.EntityNotFoundError.html | 208 ++ ...everbrush_orm.InvariantViolationError.html | 216 ++ .../classes/_cleverbrush_orm.OpaqueQuery.html | 265 +++ .../_cleverbrush_orm.PendingChangesError.html | 200 ++ ...everbrush_orm.PolymorphicQueryBuilder.html | 1342 +++++++++++ .../_cleverbrush_orm.ReadSchemaError.html | 188 ++ .../_cleverbrush_orm.SchemaQueryBuilder.html | 1999 ++++++++++++++++ ...eduler-postgres.PostgresJobRepository.html | 398 ++++ ...scheduler-postgres.PostgresJobStorage.html | 103 + ...brush_scheduler.InMemoryJobRepository.html | 397 ++++ ...verbrush_scheduler.InMemoryJobStorage.html | 102 + .../_cleverbrush_scheduler.JobRepository.html | 381 ++++ .../_cleverbrush_scheduler.JobScheduler.html | 312 +++ .../_cleverbrush_scheduler.JobWorker.html | 121 + ..._cleverbrush_scheduler.LeaseLostError.html | 182 ++ ...rbrush_scheduler.NonRetryableJobError.html | 193 ++ ...verbrush_scheduler.ScheduleCalculator.html | 314 +++ ...ush_scheduler.SubmissionConflictError.html | 182 ++ .../_cleverbrush_schema.AnySchemaBuilder.html | 1193 ++++++++++ ...cleverbrush_schema.ArraySchemaBuilder.html | 1304 +++++++++++ ...everbrush_schema.BooleanSchemaBuilder.html | 1273 +++++++++++ ..._cleverbrush_schema.DateSchemaBuilder.html | 1471 ++++++++++++ ...leverbrush_schema.ExternSchemaBuilder.html | 1225 ++++++++++ ...verbrush_schema.FunctionSchemaBuilder.html | 1262 +++++++++++ ...everbrush_schema.GenericSchemaBuilder.html | 1242 ++++++++++ ...rush_schema.IntersectionSchemaBuilder.html | 1189 ++++++++++ ..._cleverbrush_schema.LazySchemaBuilder.html | 1189 ++++++++++ ..._cleverbrush_schema.NullSchemaBuilder.html | 1158 ++++++++++ ...leverbrush_schema.NumberSchemaBuilder.html | 1487 ++++++++++++ ...leverbrush_schema.ObjectSchemaBuilder.html | 1828 +++++++++++++++ ...brush_schema.ParseStringSchemaBuilder.html | 1225 ++++++++++ ...everbrush_schema.PromiseSchemaBuilder.html | 1219 ++++++++++ ...leverbrush_schema.RecordSchemaBuilder.html | 1198 ++++++++++ .../_cleverbrush_schema.SchemaBuilder.html | 1283 +++++++++++ ...verbrush_schema.SchemaValidationError.html | 118 + ...leverbrush_schema.StringSchemaBuilder.html | 1480 ++++++++++++ ...cleverbrush_schema.TupleSchemaBuilder.html | 1250 ++++++++++ ...cleverbrush_schema.UnionSchemaBuilder.html | 1282 +++++++++++ ...erbrush_server-openapi.SchemaRegistry.html | 164 ++ .../_cleverbrush_server..ActionResult.html | 446 ++++ ...cleverbrush_server..ApiImplementation.html | 189 ++ .../_cleverbrush_server..BadRequestError.html | 228 ++ .../_cleverbrush_server..ConflictError.html | 228 ++ ...cleverbrush_server..ContentNegotiator.html | 128 ++ .../_cleverbrush_server..ContentResult.html | 482 ++++ .../_cleverbrush_server..EndpointBuilder.html | 823 +++++++ .../_cleverbrush_server..ErrorMap.html | 156 ++ .../_cleverbrush_server..FileResult.html | 482 ++++ .../_cleverbrush_server..ForbiddenError.html | 228 ++ .../_cleverbrush_server..HttpError.html | 240 ++ ...verbrush_server..ImplementationModule.html | 120 + ...everbrush_server..ImplementationScope.html | 158 ++ .../_cleverbrush_server..JsonResult.html | 495 ++++ .../_cleverbrush_server..NoContentResult.html | 448 ++++ .../_cleverbrush_server..NotFoundError.html | 228 ++ .../_cleverbrush_server..RawResult.html | 468 ++++ .../_cleverbrush_server..RedirectResult.html | 476 ++++ .../_cleverbrush_server..RequestContext.html | 238 ++ .../classes/_cleverbrush_server..Server.html | 133 ++ .../_cleverbrush_server..ServerBuilder.html | 377 ++++ ..._cleverbrush_server..StatusCodeResult.html | 483 ++++ .../_cleverbrush_server..StreamResult.html | 482 ++++ ...everbrush_server..SubscriptionBuilder.html | 383 ++++ ...cleverbrush_server..UnauthorizedError.html | 228 ++ .../_cleverbrush_storage-s3.S3Storage.html | 212 ++ .../_cleverbrush_storage.StorageError.html | 192 ++ .../_cleverbrush_di.ServiceLifetime.html | 95 + .../_cleverbrush_async.debounce.html | 64 + .../functions/_cleverbrush_async.dedupe.html | 71 + .../functions/_cleverbrush_async.retry.html | 55 + .../_cleverbrush_async.throttle.html | 56 + .../_cleverbrush_async.withTimeout.html | 72 + ...verbrush_auth.authorizationCodeScheme.html | 58 + ...verbrush_auth.clientCredentialsScheme.html | 58 + .../_cleverbrush_auth.cookieScheme.html | 50 + .../_cleverbrush_auth.defineRoles.html | 58 + .../_cleverbrush_auth.jwtScheme.html | 52 + .../_cleverbrush_auth.oidcScheme.html | 59 + .../_cleverbrush_auth.parseCookies.html | 53 + .../_cleverbrush_auth.requireRole.html | 47 + .../_cleverbrush_auth.serializeCookie.html | 52 + .../functions/_cleverbrush_auth.signJwt.html | 49 + ...cleverbrush_client..composeMiddleware.html | 62 + .../_cleverbrush_client..createClient.html | 76 + ...rbrush_client..decodeValidationIssues.html | 59 + ...cleverbrush_client..getPerCallOptions.html | 57 + .../_cleverbrush_client..isApiError.html | 53 + .../_cleverbrush_client..isNetworkError.html | 45 + .../_cleverbrush_client..isOfflineError.html | 53 + .../_cleverbrush_client..isTimeoutError.html | 53 + .../_cleverbrush_client..isWebError.html | 53 + ..._cleverbrush_client.batching.batching.html | 70 + .../_cleverbrush_client.cache.cacheTags.html | 56 + ...brush_client.cache.computeCacheTagKey.html | 51 + ...brush_client.cache.createCacheTagRoot.html | 47 + ...rbrush_client.cache.externalCacheTags.html | 60 + ...erbrush_client.cache.isMutatingMethod.html | 47 + ...verbrush_client.cache.throttlingCache.html | 59 + .../_cleverbrush_client.dedupe.dedupe.html | 59 + ...rbrush_client.idempotency.idempotency.html | 60 + ...ush_client.offline-queue.offlineQueue.html | 45 + ...nt.optimistic-update.optimisticUpdate.html | 45 + ...brush_client.react.buildGroupQueryKey.html | 59 + ...leverbrush_client.react.buildQueryKey.html | 64 + ...cleverbrush_client.react.createClient.html | 80 + ...sh_client.react.useOptimisticMutation.html | 51 + ...verbrush_client.react.useSubscription.html | 65 + .../_cleverbrush_client.retry.retry.html | 56 + .../_cleverbrush_client.timeout.timeout.html | 58 + .../_cleverbrush_deep.deepClone.html | 54 + .../_cleverbrush_deep.deepEqual.html | 56 + .../_cleverbrush_deep.deepFlatten.html | 53 + .../_cleverbrush_deep.deepForEachAsync.html | 67 + .../functions/_cleverbrush_deep.deepSort.html | 62 + .../_cleverbrush_di.isAsyncDisposable.html | 56 + .../_cleverbrush_di.isDisposable.html | 56 + .../functions/_cleverbrush_env.env.html | 66 + .../_cleverbrush_env.envBoolean.html | 59 + .../functions/_cleverbrush_env.parseEnv.html | 114 + .../_cleverbrush_env.parseEnvFlat.html | 63 + .../functions/_cleverbrush_env.splitBy.html | 62 + ...ex-clickhouse.getClickhouseConnection.html | 54 + .../_cleverbrush_knex-schema..alias.html | 67 + .../_cleverbrush_knex-schema..and.html | 57 + .../_cleverbrush_knex-schema..applyDiff.html | 64 + ...sh_knex-schema..assertParametersBound.html | 51 + ...everbrush_knex-schema..buildColumnMap.html | 49 + .../_cleverbrush_knex-schema..clearRow.html | 63 + ..._cleverbrush_knex-schema..createQuery.html | 47 + ...cleverbrush_knex-schema..defineEntity.html | 58 + .../_cleverbrush_knex-schema..diffSchema.html | 61 + ...erbrush_knex-schema..encodeJsonColumn.html | 50 + ...brush_knex-schema..entitiesToSnapshot.html | 59 + ...knex-schema..entitySchemaToTableState.html | 61 + .../_cleverbrush_knex-schema..eq.html | 48 + ...hema..generateCreatePolymorphicTables.html | 61 + ...rush_knex-schema..generateCreateTable.html | 61 + ...nex-schema..generateCreateTableSource.html | 61 + ...rbrush_knex-schema..generateMigration.html | 61 + ...-schema..generateMigrationsForContext.html | 72 + ...ush_knex-schema..getPrimaryKeyColumns.html | 53 + ...rush_knex-schema..getRowVersionColumn.html | 48 + ...brush_knex-schema..introspectDatabase.html | 62 + ..._cleverbrush_knex-schema..isDiffEmpty.html | 48 + ...cleverbrush_knex-schema..isJsonColumn.html | 47 + ...ush_knex-schema..isParameterizedQuery.html | 50 + ...verbrush_knex-schema..isSqlIdentifier.html | 61 + ...cleverbrush_knex-schema..loadSnapshot.html | 54 + .../_cleverbrush_knex-schema..mapObject.html | 65 + .../_cleverbrush_knex-schema..mapValue.html | 59 + .../_cleverbrush_knex-schema..or.html | 57 + .../_cleverbrush_knex-schema..parameter.html | 59 + .../_cleverbrush_knex-schema..query.html | 105 + .../_cleverbrush_knex-schema..rawQuery.html | 72 + ...erbrush_knex-schema..resolveColumnRef.html | 83 + ...brush_knex-schema..resolvePropertyKey.html | 50 + ...verbrush_knex-schema..tableExistsInDb.html | 59 + ...hema..validateEntitiesAgainstDatabase.html | 56 + ...leverbrush_knex-schema..writeSnapshot.html | 53 + ...chema.extension.applyVariantsToSchema.html | 53 + ...h_knex-schema.extension.getColumnName.html | 49 + ...xtension.getPolymorphicVariantSchemas.html | 49 + ..._knex-schema.extension.getProjections.html | 58 + ...sh_knex-schema.extension.getTableName.html | 48 + ...ush_knex-schema.extension.getVariants.html | 49 + ..._cleverbrush_log..applicationEnricher.html | 50 + .../_cleverbrush_log..callerEnricher.html | 46 + .../_cleverbrush_log..captureProperties.html | 55 + .../_cleverbrush_log..computeEventId.html | 51 + .../_cleverbrush_log..configureLogging.html | 60 + .../_cleverbrush_log..consoleSink.html | 61 + ...leverbrush_log..correlationIdEnricher.html | 45 + ...verbrush_log..correlationIdMiddleware.html | 58 + .../_cleverbrush_log..createLogEvent.html | 60 + .../_cleverbrush_log..createLogger.html | 65 + .../_cleverbrush_log..createSink.html | 56 + ..._cleverbrush_log..environmentEnricher.html | 50 + ...cleverbrush_log..extractCorrelationId.html | 57 + .../functions/_cleverbrush_log..fileSink.html | 57 + .../_cleverbrush_log..formatClef.html | 61 + .../_cleverbrush_log..formatClefBatch.html | 59 + ...leverbrush_log..generateCorrelationId.html | 45 + .../_cleverbrush_log..hostnameEnricher.html | 45 + .../_cleverbrush_log..levelToShortString.html | 47 + .../_cleverbrush_log..levelToString.html | 50 + .../_cleverbrush_log..parseLogLevel.html | 50 + .../_cleverbrush_log..parseTemplate.html | 52 + .../_cleverbrush_log..processIdEnricher.html | 45 + .../_cleverbrush_log..renderTemplate.html | 55 + ...erbrush_log..requestLoggingMiddleware.html | 62 + .../_cleverbrush_log..safeSerialize.html | 63 + .../_cleverbrush_log..samplingFilter.html | 58 + .../functions/_cleverbrush_log..seqSink.html | 59 + .../_cleverbrush_log..useLogging.html | 60 + ...erbrush_log.clickhouse.clickHouseSink.html | 58 + ...rbrush_log.clickhouse.createLogsTable.html | 61 + .../functions/_cleverbrush_mapper.mapper.html | 47 + .../_cleverbrush_orm-cli.defineConfig.html | 52 + .../functions/_cleverbrush_orm.alias.html | 66 + .../functions/_cleverbrush_orm.and.html | 56 + .../functions/_cleverbrush_orm.applyDiff.html | 63 + ...cleverbrush_orm.assertParametersBound.html | 50 + .../_cleverbrush_orm.buildColumnMap.html | 48 + .../functions/_cleverbrush_orm.clearRow.html | 62 + .../functions/_cleverbrush_orm.createDb.html | 86 + .../_cleverbrush_orm.createQuery.html | 46 + .../_cleverbrush_orm.defineEntity.html | 57 + .../_cleverbrush_orm.diffSchema.html | 60 + .../_cleverbrush_orm.encodeJsonColumn.html | 49 + .../_cleverbrush_orm.entitiesToSnapshot.html | 58 + ...verbrush_orm.entitySchemaToTableState.html | 60 + .../v5.1.0/functions/_cleverbrush_orm.eq.html | 47 + ...h_orm.generateCreatePolymorphicTables.html | 60 + .../_cleverbrush_orm.generateCreateTable.html | 60 + ...erbrush_orm.generateCreateTableSource.html | 60 + .../_cleverbrush_orm.generateMigration.html | 60 + ...rush_orm.generateMigrationsForContext.html | 71 + .../_cleverbrush_orm.getColumnName.html | 48 + ...rush_orm.getPolymorphicVariantSchemas.html | 48 + ..._cleverbrush_orm.getPrimaryKeyColumns.html | 52 + .../_cleverbrush_orm.getProjections.html | 57 + .../_cleverbrush_orm.getRowVersionColumn.html | 47 + .../_cleverbrush_orm.getTableName.html | 47 + .../_cleverbrush_orm.getVariants.html | 48 + .../_cleverbrush_orm.introspectDatabase.html | 61 + .../_cleverbrush_orm.isDiffEmpty.html | 47 + .../_cleverbrush_orm.isJsonColumn.html | 46 + ..._cleverbrush_orm.isParameterizedQuery.html | 49 + .../_cleverbrush_orm.isSqlIdentifier.html | 60 + .../_cleverbrush_orm.loadSnapshot.html | 53 + .../functions/_cleverbrush_orm.mapObject.html | 64 + .../functions/_cleverbrush_orm.mapValue.html | 58 + .../v5.1.0/functions/_cleverbrush_orm.or.html | 56 + .../functions/_cleverbrush_orm.parameter.html | 58 + .../functions/_cleverbrush_orm.query.html | 104 + .../functions/_cleverbrush_orm.rawQuery.html | 71 + .../_cleverbrush_orm.resolveColumnRef.html | 82 + .../_cleverbrush_orm.resolvePropertyKey.html | 49 + .../_cleverbrush_orm.tableExistsInDb.html | 58 + ...h_orm.validateEntitiesAgainstDatabase.html | 55 + .../_cleverbrush_orm.writeSnapshot.html | 52 + .../_cleverbrush_otel..configureOtel.html | 61 + .../_cleverbrush_otel..instrumentKnex.html | 73 + .../_cleverbrush_otel..otelLogSink.html | 75 + .../_cleverbrush_otel..setupOtel.html | 62 + .../_cleverbrush_otel..traceEnricher.html | 55 + .../_cleverbrush_otel..tracingMiddleware.html | 74 + .../_cleverbrush_otel..withSpan.html | 88 + ...h_otel.client.clientTracingMiddleware.html | 57 + ...ntations.outboundHttpInstrumentations.html | 56 + ..._otel.instrumentations.runtimeMetrics.html | 53 + .../_cleverbrush_react-form.Field.html | 64 + .../_cleverbrush_react-form.FormProvider.html | 50 + ...erbrush_react-form.FormSystemProvider.html | 53 + ...everbrush_react-form.createFormSystem.html | 55 + ...rbrush_react-form.defineFieldRenderer.html | 52 + .../_cleverbrush_react-form.useField.html | 59 + ..._cleverbrush_react-form.useFormSystem.html | 42 + ..._cleverbrush_react-form.useSchemaForm.html | 51 + ...eduler-postgres.createSchedulerTables.html | 48 + ...cheduler-postgres.dropSchedulerTables.html | 48 + .../_cleverbrush_scheduler.defineJob.html | 52 + ...leverbrush_schema-json.fromJsonSchema.html | 186 ++ ..._cleverbrush_schema-json.toJsonSchema.html | 83 + ...sh_schema-json.withStandardJsonSchema.html | 66 + .../_cleverbrush_schema.defineExtension.html | 116 + ...everbrush_schema.defineMetadataMethod.html | 62 + .../functions/_cleverbrush_schema.enumOf.html | 105 + .../functions/_cleverbrush_schema.extern.html | 75 + .../_cleverbrush_schema.generic.html | 141 ++ .../_cleverbrush_schema.intersection.html | 63 + .../functions/_cleverbrush_schema.lazy.html | 67 + .../functions/_cleverbrush_schema.nul.html | 60 + .../_cleverbrush_schema.parseString.html | 74 + .../_cleverbrush_schema.withExtensions.html | 103 + ...verbrush_server-openapi.convertSchema.html | 56 + ..._server-openapi.createOpenApiEndpoint.html | 54 + ...h_server-openapi.generateAsyncApiSpec.html | 65 + ...sh_server-openapi.generateOpenApiSpec.html | 46 + ...h_server-openapi.mapOperationSecurity.html | 52 + ...ush_server-openapi.mapSecuritySchemes.html | 46 + ...leverbrush_server-openapi.resolvePath.html | 47 + ...verbrush_server-openapi.serveAsyncApi.html | 55 + ...everbrush_server-openapi.serveOpenApi.html | 48 + ...leverbrush_server-openapi.walkSchemas.html | 61 + ...brush_server-openapi.writeOpenApiSpec.html | 58 + .../_cleverbrush_server..cacheResponse.html | 70 + .../_cleverbrush_server..computeCacheKey.html | 59 + ...leverbrush_server..createCacheTagTree.html | 53 + .../_cleverbrush_server..createEndpoints.html | 59 + ...verbrush_server..createProblemDetails.html | 59 + .../_cleverbrush_server..createServer.html | 45 + ...erver..createValidationProblemDetails.html | 50 + .../_cleverbrush_server..defineWebhook.html | 52 + .../_cleverbrush_server..endpointPath.html | 60 + .../_cleverbrush_server..errorMap.html | 49 + .../functions/_cleverbrush_server..file.html | 43 + .../_cleverbrush_server..idempotency.html | 53 + .../_cleverbrush_server..implement.html | 59 + .../_cleverbrush_server..mapHandlers.html | 70 + ...cleverbrush_server..matchEndpointPath.html | 56 + .../functions/_cleverbrush_server..route.html | 93 + .../_cleverbrush_server..serializeTag.html | 56 + .../_cleverbrush_server..tracked.html | 66 + .../_cleverbrush_server..withErrors.html | 65 + ...cleverbrush_server..withRequestSignal.html | 63 + ...cleverbrush_server.contract.defineApi.html | 71 + ...rbrush_server.contract.mergeContracts.html | 80 + ...leverbrush_server.contract.omitGroups.html | 71 + ...leverbrush_server.contract.pickGroups.html | 72 + ...cleverbrush_storage.prefixedObjectKey.html | 47 + .../_cleverbrush_storage.publicObjectUrl.html | 47 + ...cleverbrush_storage.validateObjectKey.html | 46 + ...erbrush_storage.validatePublicBaseUrl.html | 46 + .../public/api-docs/v5.1.0/hierarchy.html | 153 ++ .../docs/public/api-docs/v5.1.0/index.html | 245 ++ ...leverbrush_auth.AuthenticationContext.html | 74 + ...cleverbrush_auth.AuthenticationScheme.html | 105 + ...h_auth.AuthorizationCodeSchemeOptions.html | 108 + ..._cleverbrush_auth.AuthorizationPolicy.html | 68 + ...h_auth.ClientCredentialsSchemeOptions.html | 100 + .../_cleverbrush_auth.CookieOptions.html | 111 + ..._cleverbrush_auth.CookieSchemeOptions.html | 87 + .../_cleverbrush_auth.JwtPayload.html | 102 + .../_cleverbrush_auth.JwtSchemeOptions.html | 116 + .../_cleverbrush_auth.OAuthFlow.html | 78 + .../_cleverbrush_auth.OAuthFlows.html | 82 + .../_cleverbrush_auth.OidcSchemeOptions.html | 84 + .../_cleverbrush_client..ClientHooks.html | 106 + .../_cleverbrush_client..ClientOptions.html | 170 ++ .../_cleverbrush_client..EndpointMeta.html | 198 ++ .../_cleverbrush_client..FilePart.html | 87 + ..._cleverbrush_client..PerCallOverrides.html | 91 + .../_cleverbrush_client..Subscription.html | 123 + ...brush_client.batching.BatchingOptions.html | 131 ++ ...cleverbrush_client.cache.CacheOptions.html | 104 + ...lient.cache.CacheTagMiddlewareOptions.html | 82 + ...cleverbrush_client.cache.CacheTagRoot.html | 79 + ...client.cache.ExternalCacheTagsOptions.html | 90 + ...brush_client.cache.SerializedCacheTag.html | 67 + ...everbrush_client.dedupe.DedupeOptions.html | 76 + ...client.idempotency.IdempotencyOptions.html | 84 + ...ent.offline-queue.OfflineQueueOptions.html | 70 + ...lient.offline-queue.OfflineQueueStore.html | 70 + ...sh_client.offline-queue.QueuedRequest.html | 82 + ...t.optimistic-update.OptimisticFailure.html | 82 + ...mistic-update.OptimisticUpdateOptions.html | 64 + ...timistic-update.OptimisticUpdateStore.html | 58 + ...client.react.OptimisticMutationConfig.html | 87 + ...h_client.react.UseSubscriptionOptions.html | 71 + ...ush_client.react.UseSubscriptionState.html | 108 + ...cleverbrush_client.retry.RetryOptions.html | 131 ++ ...erbrush_client.timeout.TimeoutOptions.html | 64 + ...verbrush_deep.DeepForEachAsyncOptions.html | 74 + .../_cleverbrush_di.IServiceProvider.html | 112 + .../_cleverbrush_di.ServiceDescriptor.html | 105 + ...cleverbrush_di.ServiceProviderOptions.html | 73 + ...erbrush_di.ServiceRegistrationOptions.html | 76 + .../_cleverbrush_env.EnvBooleanOptions.html | 102 + .../_cleverbrush_env.InvalidEnvVar.html | 86 + .../_cleverbrush_env.MissingEnvVar.html | 78 + ...rush_knex-clickhouse.ClickHouseClient.html | 213 ++ ...leverbrush_knex-schema..AddColumnDiff.html | 111 + ...rbrush_knex-schema..AddForeignKeyDiff.html | 95 + ...cleverbrush_knex-schema..AddIndexDiff.html | 79 + ...rush_knex-schema..AggregateExpression.html | 73 + ...erbrush_knex-schema..AggregateOptions.html | 67 + ...leverbrush_knex-schema..AliasedColumn.html | 97 + ...verbrush_knex-schema..AlterColumnDiff.html | 71 + .../_cleverbrush_knex-schema..BoundQuery.html | 124 + ...leverbrush_knex-schema..BoundQuerySql.html | 67 + ...h_knex-schema..CompositeCursorOptions.html | 83 + ...h_knex-schema..CursorPaginationResult.html | 83 + ...rbrush_knex-schema..DatabaseCheckInfo.html | 71 + ...brush_knex-schema..DatabaseColumnInfo.html | 101 + ...h_knex-schema..DatabaseForeignKeyInfo.html | 103 + ...rbrush_knex-schema..DatabaseIndexInfo.html | 87 + ...brush_knex-schema..DatabaseTableState.html | 87 + ...-schema..EntitySchemaValidationResult.html | 79 + ...cleverbrush_knex-schema..JoinManySpec.html | 133 ++ ..._cleverbrush_knex-schema..JoinOneSpec.html | 118 + ...leverbrush_knex-schema..JoinPredicate.html | 61 + ...leverbrush_knex-schema..MigrationDiff.html | 111 + ...cleverbrush_knex-schema..OutputSchema.html | 75 + ...erbrush_knex-schema..PaginationResult.html | 115 + ...verbrush_knex-schema..ParameterReader.html | 70 + ...rbrush_knex-schema..PrimaryKeyColumns.html | 76 + ..._cleverbrush_knex-schema..QueryOutput.html | 67 + ...everbrush_knex-schema..QueryParameter.html | 75 + .../_cleverbrush_knex-schema..QueryScope.html | 836 +++++++ .../_cleverbrush_knex-schema..ReadColumn.html | 124 + ...ush_knex-schema..ReadPredicateBuilder.html | 799 +++++++ ...everbrush_knex-schema..ReadQueryShape.html | 75 + ..._cleverbrush_knex-schema..ReadVariant.html | 87 + ...cleverbrush_knex-schema..ReadVariants.html | 71 + ...cleverbrush_knex-schema..RelationInfo.html | 78 + ...cleverbrush_knex-schema..RelationSpec.html | 107 + ...sh_knex-schema..ResolvedVariantConfig.html | 79 + ...rush_knex-schema..ResolvedVariantSpec.html | 103 + ...erbrush_knex-schema..RowVersionColumn.html | 80 + ...everbrush_knex-schema..SchemaSnapshot.html | 77 + .../_cleverbrush_knex-schema..TableAlias.html | 82 + ...sh_knex-schema..ValidatedJoinManySpec.html | 119 + ...ush_knex-schema..ValidatedJoinOneSpec.html | 103 + ...ema.extension.VariantInputForResolver.html | 100 + ..._cleverbrush_log..BatchingSinkOptions.html | 147 ++ .../_cleverbrush_log..ConsoleSinkOptions.html | 97 + ...h_log..CorrelationIdMiddlewareOptions.html | 97 + .../_cleverbrush_log..CreateSinkOptions.html | 87 + .../_cleverbrush_log..FileSinkOptions.html | 79 + .../_cleverbrush_log..LogContextStore.html | 73 + .../_cleverbrush_log..LogEvent.html | 114 + .../interfaces/_cleverbrush_log..LogSink.html | 107 + .../_cleverbrush_log..LoggerConfig.html | 143 ++ ...leverbrush_log..RequestLoggingOptions.html | 121 + .../_cleverbrush_log..RotationOptions.html | 93 + .../_cleverbrush_log..SeqSinkOptions.html | 127 ++ ...cleverbrush_log..SerializationOptions.html | 83 + .../_cleverbrush_log..TypedTemplate.html | 99 + ...og.clickhouse.ClickHouseColumnMapping.html | 115 + ..._log.clickhouse.ClickHouseSinkOptions.html | 107 + ...log.clickhouse.CreateLogsTableOptions.html | 105 + ..._cleverbrush_orm-cli.MigrationsConfig.html | 87 + .../_cleverbrush_orm-cli.OrmCliConfig.html | 85 + .../_cleverbrush_orm.AddColumnDiff.html | 110 + .../_cleverbrush_orm.AddForeignKeyDiff.html | 94 + .../_cleverbrush_orm.AddIndexDiff.html | 78 + .../_cleverbrush_orm.AggregateExpression.html | 72 + .../_cleverbrush_orm.AggregateOptions.html | 66 + .../_cleverbrush_orm.AliasedColumn.html | 96 + .../_cleverbrush_orm.AlterColumnDiff.html | 70 + .../_cleverbrush_orm.BoundQuery.html | 123 + .../_cleverbrush_orm.BoundQuerySql.html | 66 + ...leverbrush_orm.CompositeCursorOptions.html | 82 + ...leverbrush_orm.CursorPaginationResult.html | 82 + .../_cleverbrush_orm.DatabaseCheckInfo.html | 70 + .../_cleverbrush_orm.DatabaseColumnInfo.html | 100 + ...leverbrush_orm.DatabaseForeignKeyInfo.html | 102 + .../_cleverbrush_orm.DatabaseIndexInfo.html | 86 + .../_cleverbrush_orm.DatabaseTableState.html | 86 + .../_cleverbrush_orm.DbSetOperations.html | 160 ++ .../_cleverbrush_orm.EntityEntry.html | 121 + ...rush_orm.EntitySchemaValidationResult.html | 78 + .../_cleverbrush_orm.JoinManySpec.html | 132 ++ .../_cleverbrush_orm.JoinOneSpec.html | 117 + .../_cleverbrush_orm.JoinPredicate.html | 60 + .../_cleverbrush_orm.MigrationDiff.html | 110 + .../_cleverbrush_orm.OutputSchema.html | 74 + .../_cleverbrush_orm.PaginationResult.html | 114 + .../_cleverbrush_orm.ParameterReader.html | 69 + ...leverbrush_orm.PolymorphicEntityQuery.html | 1263 +++++++++++ .../_cleverbrush_orm.PrimaryKeyColumns.html | 75 + .../_cleverbrush_orm.QueryOutput.html | 66 + .../_cleverbrush_orm.QueryParameter.html | 74 + .../_cleverbrush_orm.QueryScope.html | 835 +++++++ .../_cleverbrush_orm.ReadColumn.html | 123 + ..._cleverbrush_orm.ReadPredicateBuilder.html | 798 +++++++ .../_cleverbrush_orm.ReadQueryShape.html | 74 + .../_cleverbrush_orm.ReadVariant.html | 86 + .../_cleverbrush_orm.ReadVariants.html | 70 + .../_cleverbrush_orm.RelationInfo.html | 77 + .../_cleverbrush_orm.RelationSpec.html | 106 + ...cleverbrush_orm.ResolvedVariantConfig.html | 78 + .../_cleverbrush_orm.ResolvedVariantSpec.html | 102 + .../_cleverbrush_orm.RowVersionColumn.html | 79 + .../_cleverbrush_orm.SchemaSnapshot.html | 76 + .../_cleverbrush_orm.TableAlias.html | 81 + .../_cleverbrush_orm.TableEntityQuery.html | 1851 +++++++++++++++ .../_cleverbrush_orm.TransactionOptions.html | 65 + ...cleverbrush_orm.ValidatedJoinManySpec.html | 118 + ..._cleverbrush_orm.ValidatedJoinOneSpec.html | 102 + .../_cleverbrush_orm.VariantDbSet.html | 1337 +++++++++++ ...leverbrush_otel..ConfigureOtelOptions.html | 91 + ...everbrush_otel..InstrumentKnexOptions.html | 104 + .../_cleverbrush_otel..OtelConfig.html | 222 ++ .../_cleverbrush_otel..OtelHandle.html | 88 + ..._cleverbrush_otel..OtelLogSinkOptions.html | 88 + .../_cleverbrush_otel..SpanHandle.html | 111 + ...rbrush_otel..TracingMiddlewareOptions.html | 132 ++ .../_cleverbrush_otel..WithSpanOptions.html | 99 + ...otel.client.ClientTracingEndpointMeta.html | 99 + ...erbrush_otel.client.ClientTracingInfo.html | 79 + ...client.ClientTracingMiddlewareOptions.html | 110 + .../_cleverbrush_scheduler.JobDefinition.html | 136 ++ .../_cleverbrush_scheduler.JobStorage.html | 77 + ...brush_scheduler.JobStorageTransaction.html | 297 +++ ...a-json.StandardJSONSchemaV1.Converter.html | 71 + ...ema-json.StandardJSONSchemaV1.Options.html | 71 + ...chema-json.StandardJSONSchemaV1.Props.html | 101 + ...chema-json.StandardJSONSchemaV1.Types.html | 84 + ...rush_schema-json.StandardJSONSchemaV1.html | 68 + ...ush_schema-json.StandardTypedV1.Props.html | 90 + ...ush_schema-json.StandardTypedV1.Types.html | 82 + ...everbrush_schema-json.StandardTypedV1.html | 68 + ...erbrush_schema.ArrayBuiltinExtensions.html | 123 + ...verbrush_schema.MetadataMethodBuilder.html | 115 + ...rbrush_schema.NumberBuiltinExtensions.html | 255 +++ ...schema.StandardSchemaV1.FailureResult.html | 63 + ...erbrush_schema.StandardSchemaV1.Issue.html | 71 + ...brush_schema.StandardSchemaV1.Options.html | 60 + ...h_schema.StandardSchemaV1.PathSegment.html | 63 + ...erbrush_schema.StandardSchemaV1.Props.html | 101 + ...schema.StandardSchemaV1.SuccessResult.html | 75 + ...erbrush_schema.StandardSchemaV1.Types.html | 84 + .../_cleverbrush_schema.StandardSchemaV1.html | 68 + ...verbrush_schema.StandardTypedV1.Props.html | 90 + ...verbrush_schema.StandardTypedV1.Types.html | 82 + .../_cleverbrush_schema.StandardTypedV1.html | 68 + ...rbrush_schema.StringBuiltinExtensions.html | 338 +++ ...everbrush_server-openapi.AsyncApiInfo.html | 103 + ...rbrush_server-openapi.AsyncApiOptions.html | 102 + ...sh_server-openapi.AsyncApiServerEntry.html | 97 + ...ver-openapi.AsyncApiServer_ServerLike.html | 65 + ...server-openapi.OpenApiEndpointOptions.html | 115 + ...leverbrush_server-openapi.OpenApiInfo.html | 91 + ...erbrush_server-openapi.OpenApiOptions.html | 129 ++ ..._server-openapi.OpenApiSecurityScheme.html | 101 + ...verbrush_server-openapi.OpenApiServer.html | 67 + ...rver-openapi.OpenApiServer_ServerLike.html | 86 + ...cleverbrush_server-openapi.OpenApiTag.html | 84 + ...rush_server-openapi.PathParameterInfo.html | 67 + ...everbrush_server-openapi.ResolvedPath.html | 71 + ...h_server-openapi.ServeAsyncApiOptions.html | 100 + ...sh_server-openapi.ServeOpenApiOptions.html | 115 + ...verbrush_server..AuthenticationConfig.html | 85 + ...everbrush_server..AuthorizationConfig.html | 65 + ...leverbrush_server..CacheTagDefinition.html | 70 + ...rush_server..CacheTagPropertyAccessor.html | 71 + ...leverbrush_server..CallbackDefinition.html | 124 + ...leverbrush_server..ContentTypeHandler.html | 105 + ...ush_server..EndpointIdempotencyLimits.html | 73 + ..._cleverbrush_server..EndpointMetadata.html | 264 +++ ...verbrush_server..EndpointRegistration.html | 110 + .../_cleverbrush_server..FilePart.html | 87 + .../_cleverbrush_server..HandlerMapping.html | 68 + ...rbrush_server..ImplementationDefaults.html | 86 + ...sh_server..ImplementationGroupOptions.html | 100 + ...erver..ImplementationOperationOptions.html | 120 + .../_cleverbrush_server..LinkDefinition.html | 102 + .../_cleverbrush_server..ProblemDetails.html | 96 + .../_cleverbrush_server..RejectedFile.html | 87 + ...verbrush_server..RequestSignalContext.html | 67 + ...verbrush_server..RequestSignalOptions.html | 71 + ...erbrush_server..ServerBatchingOptions.html | 114 + ...leverbrush_server..ServerCacheOptions.html | 88 + ...cleverbrush_server..ServerCorsOptions.html | 103 + ...rush_server..ServerIdempotencyOptions.html | 105 + .../_cleverbrush_server..ServerOptions.html | 90 + ...verbrush_server..SubscriptionMetadata.html | 149 ++ ...rush_server..SubscriptionRegistration.html | 74 + .../_cleverbrush_server..TrackedEvent.html | 89 + ...everbrush_server..UploadConfiguration.html | 143 ++ .../_cleverbrush_server..UploadOptions.html | 131 ++ ...everbrush_server..ValidationErrorItem.html | 74 + ...cleverbrush_server..WebhookDefinition.html | 120 + ..._cleverbrush_storage-s3.S3Credentials.html | 72 + ...everbrush_storage-s3.S3StorageOptions.html | 136 ++ .../_cleverbrush_storage.ObjectHeaders.html | 87 + .../_cleverbrush_storage.ObjectMetadata.html | 120 + .../_cleverbrush_storage.ObjectStorage.html | 193 ++ .../_cleverbrush_storage.PutOptions.html | 104 + .../_cleverbrush_storage.StorageOptions.html | 66 + ...cleverbrush_storage.StorageReadResult.html | 124 + .../_cleverbrush_storage.StoredObject.html | 78 + .../docs/public/api-docs/v5.1.0/media/LICENSE | 28 + .../api-docs/v5.1.0/media/MIGRATION-v5-1.md | 232 ++ .../api-docs/v5.1.0/media/MIGRATION-v5-2.md | 77 + .../api-docs/v5.1.0/media/MIGRATION-v5.md | 86 + .../public/api-docs/v5.1.0/media/README.md | 22 + .../public/api-docs/v5.1.0/media/SECURITY.md | 32 + .../v5.1.0/media/cache-form-migration.md | 261 +++ .../docs/public/api-docs/v5.1.0/media/ci.yml | 147 ++ .../docs/public/api-docs/v5.1.0/modules.html | 37 + .../v5.1.0/modules/_cleverbrush_async.html | 258 +++ .../v5.1.0/modules/_cleverbrush_auth.html | 127 ++ .../v5.1.0/modules/_cleverbrush_client..html | 65 + .../modules/_cleverbrush_client.batching.html | 43 + .../modules/_cleverbrush_client.cache.html | 43 + .../modules/_cleverbrush_client.dedupe.html | 43 + .../v5.1.0/modules/_cleverbrush_client.html | 893 ++++++++ .../_cleverbrush_client.idempotency.html | 43 + .../_cleverbrush_client.offline-queue.html | 43 + ..._cleverbrush_client.optimistic-update.html | 47 + .../modules/_cleverbrush_client.react.html | 54 + .../modules/_cleverbrush_client.retry.html | 43 + .../modules/_cleverbrush_client.timeout.html | 43 + .../v5.1.0/modules/_cleverbrush_deep.html | 282 +++ .../v5.1.0/modules/_cleverbrush_di.html | 299 +++ .../v5.1.0/modules/_cleverbrush_env.html | 264 +++ .../modules/_cleverbrush_knex-clickhouse.html | 155 ++ .../modules/_cleverbrush_knex-schema..html | 59 + .../_cleverbrush_knex-schema.extension.html | 55 + .../modules/_cleverbrush_knex-schema.html | 873 +++++++ .../v5.1.0/modules/_cleverbrush_log..html | 55 + .../modules/_cleverbrush_log.clickhouse.html | 43 + .../v5.1.0/modules/_cleverbrush_log.html | 91 + .../v5.1.0/modules/_cleverbrush_mapper.html | 304 +++ .../v5.1.0/modules/_cleverbrush_orm-cli.html | 222 ++ .../v5.1.0/modules/_cleverbrush_orm.html | 543 +++++ .../v5.1.0/modules/_cleverbrush_otel..html | 47 + .../modules/_cleverbrush_otel.client.html | 47 + .../v5.1.0/modules/_cleverbrush_otel.html | 156 ++ .../_cleverbrush_otel.instrumentations.html | 48 + .../modules/_cleverbrush_react-form.html | 664 ++++++ .../_cleverbrush_scheduler-postgres.html | 105 + .../modules/_cleverbrush_scheduler.html | 252 +++ ...rush_schema-json.StandardJSONSchemaV1.html | 43 + ...everbrush_schema-json.StandardTypedV1.html | 43 + .../modules/_cleverbrush_schema-json.html | 433 ++++ .../_cleverbrush_schema.StandardSchemaV1.html | 43 + .../_cleverbrush_schema.StandardTypedV1.html | 43 + .../v5.1.0/modules/_cleverbrush_schema.html | 1259 +++++++++++ .../modules/_cleverbrush_server-openapi.html | 326 +++ .../v5.1.0/modules/_cleverbrush_server..html | 59 + .../modules/_cleverbrush_server.contract.html | 60 + .../v5.1.0/modules/_cleverbrush_server.html | 784 +++++++ .../modules/_cleverbrush_storage-s3.html | 197 ++ .../v5.1.0/modules/_cleverbrush_storage.html | 150 ++ ...cleverbrush_auth.AuthenticationResult.html | 42 + ...erbrush_auth.AuthorizationRequirement.html | 50 + ..._cleverbrush_auth.AuthorizationResult.html | 37 + .../_cleverbrush_client..ApiContract.html | 46 + .../_cleverbrush_client..EndpointCall.html | 48 + ..._cleverbrush_client..EndpointCallArgs.html | 59 + ..._cleverbrush_client..EndpointResponse.html | 56 + .../types/_cleverbrush_client..FetchLike.html | 53 + .../_cleverbrush_client..Middleware.html | 57 + ..._cleverbrush_client..SubscriptionCall.html | 46 + ...verbrush_client..SubscriptionCallArgs.html | 42 + ...verbrush_client..SubscriptionIncoming.html | 42 + ...verbrush_client..SubscriptionOutgoing.html | 42 + .../_cleverbrush_client..TypedClient.html | 52 + ...erbrush_client..ValidationIssueSource.html | 38 + ...brush_client.react.EndpointQueryHooks.html | 50 + ...client.react.InfiniteQueryHookOptions.html | 49 + ...rush_client.react.MutationHookOptions.html | 47 + ...erbrush_client.react.QueryHookOptions.html | 45 + ...client.react.SuspenseQueryHookOptions.html | 45 + ...erbrush_client.react.TypedQueryClient.html | 52 + ...verbrush_client.react.TypedQueryGroup.html | 67 + ...leverbrush_client.react.UnifiedClient.html | 52 + ...rush_client.react.UnifiedEndpointCall.html | 53 + ...cleverbrush_client.react.UnifiedGroup.html | 58 + .../v5.1.0/types/_cleverbrush_deep.Merge.html | 41 + .../types/_cleverbrush_deep.MergeTwo.html | 42 + .../types/_cleverbrush_di.ServiceFactory.html | 65 + .../types/_cleverbrush_env.EnvConfig.html | 37 + .../types/_cleverbrush_env.EnvConfigNode.html | 43 + .../types/_cleverbrush_env.EnvField.html | 77 + .../_cleverbrush_env.InferEnvConfig.html | 45 + ...verbrush_knex-schema..AggregateResult.html | 43 + ..._cleverbrush_knex-schema..AliasTables.html | 44 + ...erbrush_knex-schema..AttachParameters.html | 44 + ...rush_knex-schema..CheckParameterState.html | 42 + ...erbrush_knex-schema..ColumnReadSchema.html | 42 + .../_cleverbrush_knex-schema..ColumnRef.html | 42 + ...brush_knex-schema..EntityPropSelector.html | 59 + ...erbrush_knex-schema..EntityReadSchema.html | 44 + ...brush_knex-schema..EntityRelationKeys.html | 44 + ...verbrush_knex-schema..EntityRelations.html | 42 + ...cleverbrush_knex-schema..EntitySchema.html | 42 + ...x-schema..EntitySchemaValidationIssue.html | 38 + ...brush_knex-schema..EntityVariantUnion.html | 43 + ...erbrush_knex-schema..InferDatabaseRow.html | 45 + ...brush_knex-schema..InferDatabaseValue.html | 45 + .../_cleverbrush_knex-schema..InsertType.html | 42 + ...erbrush_knex-schema..JoinedProjection.html | 42 + ...verbrush_knex-schema..MergeParameters.html | 41 + ...erbrush_knex-schema..ObjectReadSchema.html | 43 + ...everbrush_knex-schema..ParameterState.html | 38 + ...brush_knex-schema..ParameterizedQuery.html | 87 + ...cleverbrush_knex-schema..ParametersOf.html | 40 + ...ush_knex-schema..PolymorphicRowSchema.html | 42 + ...cleverbrush_knex-schema..PrimaryKeyOf.html | 53 + ...rbrush_knex-schema..PrimaryKeyValueOf.html | 49 + ...everbrush_knex-schema..QueryArguments.html | 42 + ...verbrush_knex-schema..QueryDefinition.html | 92 + .../_cleverbrush_knex-schema..QueryView.html | 43 + ...verbrush_knex-schema..ReadAliasTables.html | 42 + ..._cleverbrush_knex-schema..ReadColumns.html | 43 + ...everbrush_knex-schema..ReadMembership.html | 38 + .../_cleverbrush_knex-schema..ReadObject.html | 38 + ...brush_knex-schema..ReadPredicateGroup.html | 55 + ...ush_knex-schema..ReadPredicateMethods.html | 44 + ...sh_knex-schema..ReadPredicateSelector.html | 42 + ...everbrush_knex-schema..ReadProjection.html | 42 + ...leverbrush_knex-schema..ReadRelations.html | 42 + .../_cleverbrush_knex-schema..ReadSchema.html | 38 + .../_cleverbrush_knex-schema..ReadValue.html | 42 + ...rush_knex-schema..ReadVariantMetadata.html | 42 + ...brush_knex-schema..RowVersionStrategy.html | 43 + ...erbrush_knex-schema..SchemaAwareQuery.html | 43 + ...everbrush_knex-schema..SchemaForValue.html | 42 + .../_cleverbrush_knex-schema..SchemaKeys.html | 42 + ..._cleverbrush_knex-schema..SchemaProps.html | 43 + ...erbrush_knex-schema..SelectProjection.html | 45 + ...everbrush_knex-schema..SelectSelector.html | 56 + ...verbrush_knex-schema..UnwrapNavSchema.html | 43 + ...leverbrush_knex-schema..ValidatedSpec.html | 38 + ...leverbrush_knex-schema..VariantBranch.html | 45 + ...rbrush_knex-schema..VariantReadSchema.html | 43 + ...brush_knex-schema..VariantReadSchemas.html | 42 + ...brush_knex-schema..VariantStorageType.html | 38 + ...everbrush_knex-schema..WithJoinedMany.html | 44 + ...leverbrush_knex-schema..WithJoinedOne.html | 45 + ...verbrush_knex-schema..WithReadVariant.html | 73 + ...cleverbrush_knex-schema..WithRelation.html | 49 + ...nex-schema.extension.PrimaryKeyColumn.html | 42 + .../types/_cleverbrush_log..Enricher.html | 52 + .../types/_cleverbrush_log..LogFilter.html | 51 + .../types/_cleverbrush_log..LogLevel.html | 47 + .../types/_cleverbrush_log..LogLevelName.html | 38 + .../_cleverbrush_log..SamplingRates.html | 39 + ...ush_mapper.SchemaToSchemaMapperResult.html | 54 + ...mapper.SyncSchemaToSchemaMapperResult.html | 54 + .../_cleverbrush_orm.AggregateResult.html | 42 + .../types/_cleverbrush_orm.AliasTables.html | 43 + .../_cleverbrush_orm.AttachParameters.html | 43 + .../_cleverbrush_orm.CheckParameterState.html | 41 + .../_cleverbrush_orm.ColumnReadSchema.html | 41 + .../types/_cleverbrush_orm.ColumnRef.html | 41 + .../types/_cleverbrush_orm.DbContext.html | 86 + .../v5.1.0/types/_cleverbrush_orm.DbSet.html | 49 + .../types/_cleverbrush_orm.EntityMap.html | 37 + .../_cleverbrush_orm.EntityPropSelector.html | 58 + .../types/_cleverbrush_orm.EntityQuery.html | 49 + .../_cleverbrush_orm.EntityReadSchema.html | 43 + .../_cleverbrush_orm.EntityRelationKeys.html | 43 + .../_cleverbrush_orm.EntityRelations.html | 41 + .../types/_cleverbrush_orm.EntityResult.html | 47 + ...cleverbrush_orm.EntityResultByVariant.html | 42 + .../types/_cleverbrush_orm.EntitySchema.html | 41 + ...brush_orm.EntitySchemaValidationIssue.html | 37 + .../_cleverbrush_orm.EntityVariantUnion.html | 42 + .../types/_cleverbrush_orm.EntryState.html | 37 + .../types/_cleverbrush_orm.ExtractBranch.html | 48 + .../types/_cleverbrush_orm.HasVariants.html | 42 + .../_cleverbrush_orm.InferDatabaseRow.html | 44 + .../_cleverbrush_orm.InferDatabaseValue.html | 44 + .../types/_cleverbrush_orm.InsertType.html | 41 + .../_cleverbrush_orm.JoinedProjection.html | 41 + .../_cleverbrush_orm.MergeParameters.html | 40 + .../_cleverbrush_orm.ObjectReadSchema.html | 42 + .../_cleverbrush_orm.ParameterState.html | 37 + .../_cleverbrush_orm.ParameterizedQuery.html | 86 + .../types/_cleverbrush_orm.ParametersOf.html | 39 + ..._cleverbrush_orm.PolymorphicRowSchema.html | 41 + .../_cleverbrush_orm.PrimaryKeyColumn.html | 41 + .../types/_cleverbrush_orm.PrimaryKeyOf.html | 52 + .../_cleverbrush_orm.PrimaryKeyValueOf.html | 48 + .../_cleverbrush_orm.QueryArguments.html | 41 + .../_cleverbrush_orm.QueryDefinition.html | 91 + .../types/_cleverbrush_orm.QueryView.html | 42 + .../_cleverbrush_orm.ReadAliasTables.html | 41 + .../types/_cleverbrush_orm.ReadColumns.html | 42 + .../_cleverbrush_orm.ReadMembership.html | 37 + .../types/_cleverbrush_orm.ReadObject.html | 37 + .../_cleverbrush_orm.ReadPredicateGroup.html | 54 + ..._cleverbrush_orm.ReadPredicateMethods.html | 43 + ...cleverbrush_orm.ReadPredicateSelector.html | 41 + .../_cleverbrush_orm.ReadProjection.html | 41 + .../types/_cleverbrush_orm.ReadRelations.html | 41 + .../types/_cleverbrush_orm.ReadSchema.html | 37 + .../types/_cleverbrush_orm.ReadValue.html | 41 + .../_cleverbrush_orm.ReadVariantMetadata.html | 41 + .../types/_cleverbrush_orm.RelKeyTree.html | 43 + .../types/_cleverbrush_orm.RelatedSchema.html | 42 + .../types/_cleverbrush_orm.ResolvedRel.html | 42 + .../_cleverbrush_orm.RowVersionStrategy.html | 42 + .../types/_cleverbrush_orm.SaveGraph.html | 49 + .../_cleverbrush_orm.SavingChangesHook.html | 50 + .../_cleverbrush_orm.SchemaAwareQuery.html | 42 + .../_cleverbrush_orm.SchemaForValue.html | 41 + .../types/_cleverbrush_orm.SchemaKeys.html | 41 + .../types/_cleverbrush_orm.SchemaProps.html | 42 + .../_cleverbrush_orm.SelectProjection.html | 44 + .../_cleverbrush_orm.SelectSelector.html | 55 + .../_cleverbrush_orm.TrackedDbContext.html | 192 ++ .../_cleverbrush_orm.UnwrapNavSchema.html | 42 + .../types/_cleverbrush_orm.ValidatedSpec.html | 37 + .../types/_cleverbrush_orm.VariantBranch.html | 44 + ..._cleverbrush_orm.VariantInsertPayload.html | 51 + .../_cleverbrush_orm.VariantReadSchema.html | 42 + .../_cleverbrush_orm.VariantReadSchemas.html | 41 + .../types/_cleverbrush_orm.VariantResult.html | 51 + .../_cleverbrush_orm.VariantStorageType.html | 37 + ..._cleverbrush_orm.VariantUpdatePayload.html | 44 + .../types/_cleverbrush_orm.WithIncluded.html | 43 + .../_cleverbrush_orm.WithJoinedMany.html | 43 + .../types/_cleverbrush_orm.WithJoinedOne.html | 44 + .../_cleverbrush_orm.WithReadVariant.html | 72 + .../types/_cleverbrush_orm.WithRelation.html | 48 + .../_cleverbrush_orm.WithVariantIncluded.html | 46 + ...verbrush_otel.client.ClientMiddleware.html | 50 + .../_cleverbrush_otel.client.FetchLike.html | 53 + .../_cleverbrush_react-form.FieldProps.html | 109 + ...everbrush_react-form.FieldRenderProps.html | 184 ++ ..._cleverbrush_react-form.FieldRenderer.html | 54 + .../_cleverbrush_react-form.FieldState.html | 90 + .../_cleverbrush_react-form.FormIssue.html | 68 + ...verbrush_react-form.FormProviderProps.html | 67 + ...rbrush_react-form.FormSubmissionState.html | 66 + ...verbrush_react-form.FormSubmitHandler.html | 49 + ...verbrush_react-form.FormSubmitOptions.html | 81 + ...everbrush_react-form.FormSubmitResult.html | 41 + ...everbrush_react-form.FormSystemConfig.html | 60 + ...sh_react-form.FormSystemProviderProps.html | 75 + ...erbrush_react-form.SchemaFormInstance.html | 77 + ...rbrush_react-form.TypedFieldComponent.html | 58 + ...leverbrush_react-form.TypedFieldProps.html | 43 + ...erbrush_react-form.TypedFieldRenderer.html | 42 + ...leverbrush_react-form.TypedFormSystem.html | 76 + ...rush_react-form.TypedRendererRegistry.html | 35 + ...cleverbrush_react-form.UseFieldResult.html | 119 + ...brush_react-form.UseSchemaFormOptions.html | 127 ++ ...duler-postgres.PostgresStorageOptions.html | 60 + .../_cleverbrush_scheduler.JobAttempt.html | 90 + .../_cleverbrush_scheduler.JobBinding.html | 72 + .../_cleverbrush_scheduler.JobContext.html | 100 + .../_cleverbrush_scheduler.JobError.html | 66 + .../_cleverbrush_scheduler.JobEvent.html | 41 + .../_cleverbrush_scheduler.JobHandler.html | 54 + .../_cleverbrush_scheduler.JobOptions.html | 37 + ...erbrush_scheduler.JobRepositoryHealth.html | 72 + .../types/_cleverbrush_scheduler.JobRun.html | 142 ++ ...erbrush_scheduler.JobSchedulerOptions.html | 80 + .../_cleverbrush_scheduler.JobSchema.html | 37 + .../_cleverbrush_scheduler.JobSubmission.html | 37 + ...leverbrush_scheduler.JobWorkerOptions.html | 90 + .../_cleverbrush_scheduler.JsonValue.html | 37 + .../_cleverbrush_scheduler.RetryPolicy.html | 72 + .../_cleverbrush_scheduler.RunPolicy.html | 90 + .../_cleverbrush_scheduler.RunRecord.html | 37 + .../_cleverbrush_scheduler.RunStatus.html | 37 + .../_cleverbrush_scheduler.Schedule.html | 37 + ..._cleverbrush_scheduler.ScheduleRecord.html | 144 ++ ...verbrush_scheduler.ScheduleSubmission.html | 37 + ...erbrush_scheduler.SchedulerDiagnostic.html | 78 + ..._cleverbrush_scheduler.StoredSchedule.html | 37 + .../_cleverbrush_scheduler.SupportedJob.html | 66 + .../_cleverbrush_scheduler.TaskSchedule.html | 37 + ...brush_schema-json.InferFromJsonSchema.html | 50 + ...leverbrush_schema-json.JsonSchemaNode.html | 39 + ...h_schema-json.JsonSchemaNodeToBuilder.html | 64 + ...-json.StandardJSONSchemaV1.InferInput.html | 42 + ...json.StandardJSONSchemaV1.InferOutput.html | 42 + ...hema-json.StandardJSONSchemaV1.Target.html | 40 + ...chema-json.StandardTypedV1.InferInput.html | 42 + ...hema-json.StandardTypedV1.InferOutput.html | 42 + ...brush_schema-json.ToJsonSchemaOptions.html | 115 + ...sh_schema.ArraySchemaValidationResult.html | 62 + .../types/_cleverbrush_schema.BRAND-1.html | 37 + .../types/_cleverbrush_schema.Brand.html | 49 + .../_cleverbrush_schema.CleanExtended.html | 45 + ...rbrush_schema.ElementValidationResult.html | 44 + .../_cleverbrush_schema.ExtendedAny.html | 37 + .../_cleverbrush_schema.ExtendedArray.html | 41 + .../_cleverbrush_schema.ExtendedBoolean.html | 37 + .../_cleverbrush_schema.ExtendedDate.html | 37 + .../_cleverbrush_schema.ExtendedFunc.html | 37 + .../_cleverbrush_schema.ExtendedNumber.html | 41 + .../_cleverbrush_schema.ExtendedObject.html | 41 + .../_cleverbrush_schema.ExtendedPromise.html | 41 + .../_cleverbrush_schema.ExtendedRecord.html | 42 + .../_cleverbrush_schema.ExtendedString.html | 41 + .../_cleverbrush_schema.ExtendedTuple.html | 41 + .../_cleverbrush_schema.ExtendedUnion.html | 41 + .../_cleverbrush_schema.ExtensionConfig.html | 61 + ...leverbrush_schema.ExtensionDescriptor.html | 91 + .../_cleverbrush_schema.ExtraProperties.html | 42 + ...everbrush_schema.ExtraTypeBrandSymbol.html | 35 + .../_cleverbrush_schema.FixedMethods.html | 63 + ...erbrush_schema.HiddenExtensionMethods.html | 73 + ...rush_schema.IndexedPropertyDescriptor.html | 52 + ...erbrush_schema.InferExtensionMetadata.html | 41 + .../types/_cleverbrush_schema.InferType.html | 48 + ...ma.IntersectionSchemaValidationResult.html | 39 + .../_cleverbrush_schema.MakeOptional.html | 42 + .../_cleverbrush_schema.MetadataExtended.html | 44 + .../_cleverbrush_schema.MetadataMethod.html | 44 + .../_cleverbrush_schema.MetadataMethods.html | 41 + .../_cleverbrush_schema.MetadataState.html | 43 + ...brush_schema.MethodLiteralBrandSymbol.html | 35 + ...erbrush_schema.NestedValidationResult.html | 104 + ...everbrush_schema.NumberOneOfExtension.html | 38 + ...h_schema.ObjectSchemaValidationResult.html | 94 + ...rbrush_schema.OptionValidationResults.html | 45 + ...erbrush_schema.ParseStringTemplateTag.html | 59 + ...cleverbrush_schema.PropertyDescriptor.html | 69 + ...rbrush_schema.PropertyDescriptorInner.html | 173 ++ ...erbrush_schema.PropertyDescriptorTree.html | 45 + ...verbrush_schema.PropertySetterOptions.html | 86 + ...h_schema.RecordSchemaValidationResult.html | 120 + ...erbrush_schema.SchemaPropertySelector.html | 59 + .../_cleverbrush_schema.SchemaTypeBrand.html | 35 + ...sh_schema.StandardSchemaV1.InferInput.html | 42 + ...h_schema.StandardSchemaV1.InferOutput.html | 42 + ...rbrush_schema.StandardSchemaV1.Result.html | 42 + ...ush_schema.StandardTypedV1.InferInput.html | 42 + ...sh_schema.StandardTypedV1.InferOutput.html | 42 + ...everbrush_schema.StringOneOfExtension.html | 38 + ..._schema.TupleElementValidationResults.html | 45 + ...sh_schema.TupleSchemaValidationResult.html | 62 + ...sh_schema.UnionSchemaValidationResult.html | 64 + .../_cleverbrush_schema.ValidationError.html | 77 + ...schema.ValidationErrorMessageProvider.html | 44 + .../_cleverbrush_schema.ValidationResult.html | 78 + ...brush_server-openapi.AsyncApiDocument.html | 38 + ...rbrush_server-openapi.OpenApiDocument.html | 38 + .../_cleverbrush_server..ActionContext.html | 44 + ...erbrush_server..AllowedResponseReturn.html | 50 + ...h_server..EndpointMetadataDescriptors.html | 85 + .../_cleverbrush_server..EndpointOptions.html | 85 + .../_cleverbrush_server..EndpointParams.html | 42 + .../_cleverbrush_server..ErrorResponse.html | 38 + ..._cleverbrush_server..ErrorResponsesOf.html | 42 + .../types/_cleverbrush_server..Handler.html | 40 + .../_cleverbrush_server..HandlerEntry.html | 44 + .../_cleverbrush_server..HandlerMap.html | 50 + ..._cleverbrush_server..IdempotencyScope.html | 38 + ...sh_server..ImplementationHandlerEntry.html | 42 + ...rbrush_server..ImplementationHandlers.html | 42 + .../_cleverbrush_server..Middleware.html | 59 + .../_cleverbrush_server..PropertyRefTree.html | 47 + ..._cleverbrush_server..RawResultHandler.html | 53 + .../_cleverbrush_server..ResponsesOf.html | 43 + ...erbrush_server..ScopedEndpointFactory.html | 89 + ...everbrush_server..SubscriptionContext.html | 45 + ...everbrush_server..SubscriptionHandler.html | 50 + ...rush_server..SubscriptionHandlerEntry.html | 44 + .../_cleverbrush_server..UploadContract.html | 38 + .../_cleverbrush_server..UploadFiles.html | 42 + .../_cleverbrush_server..UploadSchema.html | 38 + ...everbrush_server.contract.ApiContract.html | 46 + ..._cleverbrush_server.contract.ApiGroup.html | 39 + ...brush_server.contract.MergedContracts.html | 50 + .../_cleverbrush_storage.StorageBody.html | 37 + ..._cleverbrush_storage.StorageErrorCode.html | 37 + ..._cleverbrush_client..PER_CALL_OPTIONS.html | 45 + ...imistic-update.OPTIMISTIC_MUTATION_ID.html | 36 + ...erbrush_client.react.QUERY_KEY_PREFIX.html | 40 + .../_cleverbrush_deep.deepExtend.html | 68 + ...verbrush_knex-schema..COMPILED_READER.html | 38 + ...erbrush_knex-schema..EXTRA_TYPE_BRAND.html | 57 + .../_cleverbrush_knex-schema..MAPPERS.html | 45 + ...ush_knex-schema..METHOD_LITERAL_BRAND.html | 45 + ...erbrush_knex-schema..PARAMETER_READER.html | 38 + ...verbrush_knex-schema..PARAMETER_STATE.html | 36 + ..._cleverbrush_knex-schema..READ_ENTITY.html | 38 + .../_cleverbrush_knex-schema..aggregate.html | 183 ++ ...extension.COMPOSITE_PRIMARY_KEY_BRAND.html | 39 + ...hema.extension.POLYMORPHIC_TYPE_BRAND.html | 41 + ...ex-schema.extension.PRIMARY_KEY_BRAND.html | 40 + ...cleverbrush_knex-schema.extension.any.html | 38 + ...everbrush_knex-schema.extension.array.html | 38 + ...erbrush_knex-schema.extension.boolean.html | 38 + ...leverbrush_knex-schema.extension.date.html | 38 + ...ush_knex-schema.extension.dbExtension.html | 47 + ...sh_knex-schema.extension.ddlExtension.html | 46 + ...leverbrush_knex-schema.extension.func.html | 38 + ...verbrush_knex-schema.extension.number.html | 38 + ...verbrush_knex-schema.extension.object.html | 38 + ...verbrush_knex-schema.extension.string.html | 38 + ...everbrush_knex-schema.extension.union.html | 38 + .../variables/_cleverbrush_log..ILogger.html | 45 + .../_cleverbrush_log..LogContext.html | 147 ++ .../variables/_cleverbrush_log..LogLevel.html | 62 + .../variables/_cleverbrush_log..SelfLog.html | 112 + .../_cleverbrush_orm.COMPILED_READER.html | 37 + ...brush_orm.COMPOSITE_PRIMARY_KEY_BRAND.html | 38 + .../_cleverbrush_orm.EXTRA_TYPE_BRAND.html | 56 + .../variables/_cleverbrush_orm.MAPPERS.html | 44 + ..._cleverbrush_orm.METHOD_LITERAL_BRAND.html | 44 + .../_cleverbrush_orm.PARAMETER_READER.html | 37 + .../_cleverbrush_orm.PARAMETER_STATE.html | 35 + ...leverbrush_orm.POLYMORPHIC_TYPE_BRAND.html | 40 + .../_cleverbrush_orm.PRIMARY_KEY_BRAND.html | 39 + .../_cleverbrush_orm.READ_ENTITY.html | 37 + .../variables/_cleverbrush_orm.aggregate.html | 182 ++ .../variables/_cleverbrush_orm.any.html | 45 + .../variables/_cleverbrush_orm.array.html | 53 + .../variables/_cleverbrush_orm.boolean.html | 45 + .../variables/_cleverbrush_orm.date.html | 45 + .../_cleverbrush_orm.dbExtension.html | 46 + .../_cleverbrush_orm.ddlExtension.html | 45 + .../variables/_cleverbrush_orm.func.html | 45 + .../variables/_cleverbrush_orm.number.html | 56 + .../variables/_cleverbrush_orm.object.html | 53 + .../variables/_cleverbrush_orm.string.html | 56 + .../variables/_cleverbrush_orm.union.html | 53 + .../variables/_cleverbrush_otel..IMeter.html | 45 + .../variables/_cleverbrush_otel..ITracer.html | 46 + ..._cleverbrush_otel..OTEL_SPAN_ITEM_KEY.html | 42 + ...everbrush_scheduler.ScheduleDaySchema.html | 37 + ...rbrush_scheduler.ScheduleMinuteSchema.html | 37 + ...erbrush_scheduler.ScheduleMonthSchema.html | 37 + ..._cleverbrush_scheduler.ScheduleSchema.html | 37 + ...verbrush_scheduler.ScheduleSchemaBase.html | 37 + ...verbrush_scheduler.ScheduleWeekSchema.html | 37 + ...verbrush_scheduler.ScheduleYearSchema.html | 37 + .../_cleverbrush_scheduler.Schemas.html | 68 + .../_cleverbrush_schema.EXTRA_TYPE_BRAND.html | 56 + ...everbrush_schema.METHOD_LITERAL_BRAND.html | 44 + ...verbrush_schema.SYMBOL_HAS_PROPERTIES.html | 44 + ...ema.SYMBOL_SCHEMA_PROPERTY_DESCRIPTOR.html | 40 + .../variables/_cleverbrush_schema.any.html | 43 + .../variables/_cleverbrush_schema.array.html | 51 + .../_cleverbrush_schema.arrayExtensions.html | 45 + .../_cleverbrush_schema.boolean.html | 43 + .../variables/_cleverbrush_schema.date.html | 43 + .../variables/_cleverbrush_schema.func.html | 43 + .../variables/_cleverbrush_schema.number.html | 54 + .../_cleverbrush_schema.numberExtensions.html | 45 + .../variables/_cleverbrush_schema.object.html | 65 + .../_cleverbrush_schema.promise.html | 51 + .../variables/_cleverbrush_schema.record.html | 53 + .../variables/_cleverbrush_schema.string.html | 54 + .../_cleverbrush_schema.stringExtensions.html | 45 + .../variables/_cleverbrush_schema.tuple.html | 51 + .../variables/_cleverbrush_schema.union.html | 51 + ...erbrush_server..DEFAULT_MAX_BODY_SIZE.html | 38 + .../_cleverbrush_server..IRequestContext.html | 39 + .../_cleverbrush_server..endpoint.html | 46 + ...ver..formUrlEncodedContentTypeHandler.html | 40 + ...rbrush_server..jsonContentTypeHandler.html | 38 + websites/docs/public/api-docs/versions.json | 1 + 1126 files changed, 134596 insertions(+), 354 deletions(-) delete mode 100644 .changeset/deep-sort-sparse.md delete mode 100644 .changeset/deep-traversal-sort.md delete mode 100644 .changeset/react-form-blur-lifecycle.md delete mode 100644 .changeset/request-cancellation.md delete mode 100644 .changeset/typed-paths-and-transaction-locks.md create mode 100644 scripts/docs.mjs create mode 100644 scripts/docs.test.mjs create mode 100644 websites/docs/public/api-docs/v5.1.0/.nojekyll create mode 100644 websites/docs/public/api-docs/v5.1.0/LICENSE create mode 100644 websites/docs/public/api-docs/v5.1.0/assets/hierarchy.js create mode 100644 websites/docs/public/api-docs/v5.1.0/assets/highlight.css create mode 100644 websites/docs/public/api-docs/v5.1.0/assets/icons.js create mode 100644 websites/docs/public/api-docs/v5.1.0/assets/icons.svg create mode 100644 websites/docs/public/api-docs/v5.1.0/assets/main.js create mode 100644 websites/docs/public/api-docs/v5.1.0/assets/navigation.js create mode 100644 websites/docs/public/api-docs/v5.1.0/assets/search.js create mode 100644 websites/docs/public/api-docs/v5.1.0/assets/style.css create mode 100644 websites/docs/public/api-docs/v5.1.0/classes/_cleverbrush_async.Collector.html create mode 100644 websites/docs/public/api-docs/v5.1.0/classes/_cleverbrush_async.TimeoutError.html create mode 100644 websites/docs/public/api-docs/v5.1.0/classes/_cleverbrush_auth.AuthorizationService.html create mode 100644 websites/docs/public/api-docs/v5.1.0/classes/_cleverbrush_auth.PolicyBuilder.html create mode 100644 websites/docs/public/api-docs/v5.1.0/classes/_cleverbrush_auth.Principal.html create mode 100644 websites/docs/public/api-docs/v5.1.0/classes/_cleverbrush_client..ApiError.html create mode 100644 websites/docs/public/api-docs/v5.1.0/classes/_cleverbrush_client..NetworkError.html create mode 100644 websites/docs/public/api-docs/v5.1.0/classes/_cleverbrush_client..OfflineError.html create mode 100644 websites/docs/public/api-docs/v5.1.0/classes/_cleverbrush_client..TimeoutError.html create mode 100644 websites/docs/public/api-docs/v5.1.0/classes/_cleverbrush_client..WebError.html create mode 100644 websites/docs/public/api-docs/v5.1.0/classes/_cleverbrush_di.ScopedServiceProvider.html create mode 100644 websites/docs/public/api-docs/v5.1.0/classes/_cleverbrush_di.ServiceCollection.html create mode 100644 websites/docs/public/api-docs/v5.1.0/classes/_cleverbrush_di.ServiceProvider.html create mode 100644 websites/docs/public/api-docs/v5.1.0/classes/_cleverbrush_di.ServiceScope.html create mode 100644 websites/docs/public/api-docs/v5.1.0/classes/_cleverbrush_env.EnvValidationError.html create mode 100644 websites/docs/public/api-docs/v5.1.0/classes/_cleverbrush_knex-clickhouse.ClickhouseKnexClient.html create mode 100644 websites/docs/public/api-docs/v5.1.0/classes/_cleverbrush_knex-schema..AliasedQueryBuilder.html create mode 100644 websites/docs/public/api-docs/v5.1.0/classes/_cleverbrush_knex-schema..Entity.html create mode 100644 websites/docs/public/api-docs/v5.1.0/classes/_cleverbrush_knex-schema..OpaqueQuery.html create mode 100644 websites/docs/public/api-docs/v5.1.0/classes/_cleverbrush_knex-schema..PolymorphicQueryBuilder.html create mode 100644 websites/docs/public/api-docs/v5.1.0/classes/_cleverbrush_knex-schema..ReadSchemaError.html create mode 100644 websites/docs/public/api-docs/v5.1.0/classes/_cleverbrush_knex-schema..SchemaQueryBuilder.html create mode 100644 websites/docs/public/api-docs/v5.1.0/classes/_cleverbrush_log..BatchingSink.html create mode 100644 websites/docs/public/api-docs/v5.1.0/classes/_cleverbrush_log..Logger.html create mode 100644 websites/docs/public/api-docs/v5.1.0/classes/_cleverbrush_mapper.Mapper.html create mode 100644 websites/docs/public/api-docs/v5.1.0/classes/_cleverbrush_mapper.MapperConfigurationError.html create mode 100644 websites/docs/public/api-docs/v5.1.0/classes/_cleverbrush_mapper.MappingRegistry.html create mode 100644 websites/docs/public/api-docs/v5.1.0/classes/_cleverbrush_mapper.PropertyMappingBuilder.html create mode 100644 websites/docs/public/api-docs/v5.1.0/classes/_cleverbrush_orm.AliasedQueryBuilder.html create mode 100644 websites/docs/public/api-docs/v5.1.0/classes/_cleverbrush_orm.ConcurrencyError.html create mode 100644 websites/docs/public/api-docs/v5.1.0/classes/_cleverbrush_orm.Entity.html create mode 100644 websites/docs/public/api-docs/v5.1.0/classes/_cleverbrush_orm.EntityNotFoundError.html create mode 100644 websites/docs/public/api-docs/v5.1.0/classes/_cleverbrush_orm.InvariantViolationError.html create mode 100644 websites/docs/public/api-docs/v5.1.0/classes/_cleverbrush_orm.OpaqueQuery.html create mode 100644 websites/docs/public/api-docs/v5.1.0/classes/_cleverbrush_orm.PendingChangesError.html create mode 100644 websites/docs/public/api-docs/v5.1.0/classes/_cleverbrush_orm.PolymorphicQueryBuilder.html create mode 100644 websites/docs/public/api-docs/v5.1.0/classes/_cleverbrush_orm.ReadSchemaError.html create mode 100644 websites/docs/public/api-docs/v5.1.0/classes/_cleverbrush_orm.SchemaQueryBuilder.html create mode 100644 websites/docs/public/api-docs/v5.1.0/classes/_cleverbrush_scheduler-postgres.PostgresJobRepository.html create mode 100644 websites/docs/public/api-docs/v5.1.0/classes/_cleverbrush_scheduler-postgres.PostgresJobStorage.html create mode 100644 websites/docs/public/api-docs/v5.1.0/classes/_cleverbrush_scheduler.InMemoryJobRepository.html create mode 100644 websites/docs/public/api-docs/v5.1.0/classes/_cleverbrush_scheduler.InMemoryJobStorage.html create mode 100644 websites/docs/public/api-docs/v5.1.0/classes/_cleverbrush_scheduler.JobRepository.html create mode 100644 websites/docs/public/api-docs/v5.1.0/classes/_cleverbrush_scheduler.JobScheduler.html create mode 100644 websites/docs/public/api-docs/v5.1.0/classes/_cleverbrush_scheduler.JobWorker.html create mode 100644 websites/docs/public/api-docs/v5.1.0/classes/_cleverbrush_scheduler.LeaseLostError.html create mode 100644 websites/docs/public/api-docs/v5.1.0/classes/_cleverbrush_scheduler.NonRetryableJobError.html create mode 100644 websites/docs/public/api-docs/v5.1.0/classes/_cleverbrush_scheduler.ScheduleCalculator.html create mode 100644 websites/docs/public/api-docs/v5.1.0/classes/_cleverbrush_scheduler.SubmissionConflictError.html create mode 100644 websites/docs/public/api-docs/v5.1.0/classes/_cleverbrush_schema.AnySchemaBuilder.html create mode 100644 websites/docs/public/api-docs/v5.1.0/classes/_cleverbrush_schema.ArraySchemaBuilder.html create mode 100644 websites/docs/public/api-docs/v5.1.0/classes/_cleverbrush_schema.BooleanSchemaBuilder.html create mode 100644 websites/docs/public/api-docs/v5.1.0/classes/_cleverbrush_schema.DateSchemaBuilder.html create mode 100644 websites/docs/public/api-docs/v5.1.0/classes/_cleverbrush_schema.ExternSchemaBuilder.html create mode 100644 websites/docs/public/api-docs/v5.1.0/classes/_cleverbrush_schema.FunctionSchemaBuilder.html create mode 100644 websites/docs/public/api-docs/v5.1.0/classes/_cleverbrush_schema.GenericSchemaBuilder.html create mode 100644 websites/docs/public/api-docs/v5.1.0/classes/_cleverbrush_schema.IntersectionSchemaBuilder.html create mode 100644 websites/docs/public/api-docs/v5.1.0/classes/_cleverbrush_schema.LazySchemaBuilder.html create mode 100644 websites/docs/public/api-docs/v5.1.0/classes/_cleverbrush_schema.NullSchemaBuilder.html create mode 100644 websites/docs/public/api-docs/v5.1.0/classes/_cleverbrush_schema.NumberSchemaBuilder.html create mode 100644 websites/docs/public/api-docs/v5.1.0/classes/_cleverbrush_schema.ObjectSchemaBuilder.html create mode 100644 websites/docs/public/api-docs/v5.1.0/classes/_cleverbrush_schema.ParseStringSchemaBuilder.html create mode 100644 websites/docs/public/api-docs/v5.1.0/classes/_cleverbrush_schema.PromiseSchemaBuilder.html create mode 100644 websites/docs/public/api-docs/v5.1.0/classes/_cleverbrush_schema.RecordSchemaBuilder.html create mode 100644 websites/docs/public/api-docs/v5.1.0/classes/_cleverbrush_schema.SchemaBuilder.html create mode 100644 websites/docs/public/api-docs/v5.1.0/classes/_cleverbrush_schema.SchemaValidationError.html create mode 100644 websites/docs/public/api-docs/v5.1.0/classes/_cleverbrush_schema.StringSchemaBuilder.html create mode 100644 websites/docs/public/api-docs/v5.1.0/classes/_cleverbrush_schema.TupleSchemaBuilder.html create mode 100644 websites/docs/public/api-docs/v5.1.0/classes/_cleverbrush_schema.UnionSchemaBuilder.html create mode 100644 websites/docs/public/api-docs/v5.1.0/classes/_cleverbrush_server-openapi.SchemaRegistry.html create mode 100644 websites/docs/public/api-docs/v5.1.0/classes/_cleverbrush_server..ActionResult.html create mode 100644 websites/docs/public/api-docs/v5.1.0/classes/_cleverbrush_server..ApiImplementation.html create mode 100644 websites/docs/public/api-docs/v5.1.0/classes/_cleverbrush_server..BadRequestError.html create mode 100644 websites/docs/public/api-docs/v5.1.0/classes/_cleverbrush_server..ConflictError.html create mode 100644 websites/docs/public/api-docs/v5.1.0/classes/_cleverbrush_server..ContentNegotiator.html create mode 100644 websites/docs/public/api-docs/v5.1.0/classes/_cleverbrush_server..ContentResult.html create mode 100644 websites/docs/public/api-docs/v5.1.0/classes/_cleverbrush_server..EndpointBuilder.html create mode 100644 websites/docs/public/api-docs/v5.1.0/classes/_cleverbrush_server..ErrorMap.html create mode 100644 websites/docs/public/api-docs/v5.1.0/classes/_cleverbrush_server..FileResult.html create mode 100644 websites/docs/public/api-docs/v5.1.0/classes/_cleverbrush_server..ForbiddenError.html create mode 100644 websites/docs/public/api-docs/v5.1.0/classes/_cleverbrush_server..HttpError.html create mode 100644 websites/docs/public/api-docs/v5.1.0/classes/_cleverbrush_server..ImplementationModule.html create mode 100644 websites/docs/public/api-docs/v5.1.0/classes/_cleverbrush_server..ImplementationScope.html create mode 100644 websites/docs/public/api-docs/v5.1.0/classes/_cleverbrush_server..JsonResult.html create mode 100644 websites/docs/public/api-docs/v5.1.0/classes/_cleverbrush_server..NoContentResult.html create mode 100644 websites/docs/public/api-docs/v5.1.0/classes/_cleverbrush_server..NotFoundError.html create mode 100644 websites/docs/public/api-docs/v5.1.0/classes/_cleverbrush_server..RawResult.html create mode 100644 websites/docs/public/api-docs/v5.1.0/classes/_cleverbrush_server..RedirectResult.html create mode 100644 websites/docs/public/api-docs/v5.1.0/classes/_cleverbrush_server..RequestContext.html create mode 100644 websites/docs/public/api-docs/v5.1.0/classes/_cleverbrush_server..Server.html create mode 100644 websites/docs/public/api-docs/v5.1.0/classes/_cleverbrush_server..ServerBuilder.html create mode 100644 websites/docs/public/api-docs/v5.1.0/classes/_cleverbrush_server..StatusCodeResult.html create mode 100644 websites/docs/public/api-docs/v5.1.0/classes/_cleverbrush_server..StreamResult.html create mode 100644 websites/docs/public/api-docs/v5.1.0/classes/_cleverbrush_server..SubscriptionBuilder.html create mode 100644 websites/docs/public/api-docs/v5.1.0/classes/_cleverbrush_server..UnauthorizedError.html create mode 100644 websites/docs/public/api-docs/v5.1.0/classes/_cleverbrush_storage-s3.S3Storage.html create mode 100644 websites/docs/public/api-docs/v5.1.0/classes/_cleverbrush_storage.StorageError.html create mode 100644 websites/docs/public/api-docs/v5.1.0/enums/_cleverbrush_di.ServiceLifetime.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_async.debounce.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_async.dedupe.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_async.retry.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_async.throttle.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_async.withTimeout.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_auth.authorizationCodeScheme.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_auth.clientCredentialsScheme.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_auth.cookieScheme.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_auth.defineRoles.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_auth.jwtScheme.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_auth.oidcScheme.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_auth.parseCookies.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_auth.requireRole.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_auth.serializeCookie.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_auth.signJwt.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_client..composeMiddleware.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_client..createClient.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_client..decodeValidationIssues.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_client..getPerCallOptions.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_client..isApiError.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_client..isNetworkError.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_client..isOfflineError.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_client..isTimeoutError.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_client..isWebError.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_client.batching.batching.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_client.cache.cacheTags.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_client.cache.computeCacheTagKey.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_client.cache.createCacheTagRoot.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_client.cache.externalCacheTags.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_client.cache.isMutatingMethod.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_client.cache.throttlingCache.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_client.dedupe.dedupe.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_client.idempotency.idempotency.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_client.offline-queue.offlineQueue.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_client.optimistic-update.optimisticUpdate.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_client.react.buildGroupQueryKey.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_client.react.buildQueryKey.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_client.react.createClient.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_client.react.useOptimisticMutation.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_client.react.useSubscription.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_client.retry.retry.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_client.timeout.timeout.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_deep.deepClone.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_deep.deepEqual.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_deep.deepFlatten.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_deep.deepForEachAsync.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_deep.deepSort.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_di.isAsyncDisposable.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_di.isDisposable.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_env.env.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_env.envBoolean.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_env.parseEnv.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_env.parseEnvFlat.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_env.splitBy.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_knex-clickhouse.getClickhouseConnection.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_knex-schema..alias.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_knex-schema..and.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_knex-schema..applyDiff.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_knex-schema..assertParametersBound.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_knex-schema..buildColumnMap.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_knex-schema..clearRow.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_knex-schema..createQuery.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_knex-schema..defineEntity.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_knex-schema..diffSchema.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_knex-schema..encodeJsonColumn.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_knex-schema..entitiesToSnapshot.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_knex-schema..entitySchemaToTableState.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_knex-schema..eq.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_knex-schema..generateCreatePolymorphicTables.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_knex-schema..generateCreateTable.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_knex-schema..generateCreateTableSource.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_knex-schema..generateMigration.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_knex-schema..generateMigrationsForContext.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_knex-schema..getPrimaryKeyColumns.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_knex-schema..getRowVersionColumn.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_knex-schema..introspectDatabase.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_knex-schema..isDiffEmpty.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_knex-schema..isJsonColumn.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_knex-schema..isParameterizedQuery.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_knex-schema..isSqlIdentifier.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_knex-schema..loadSnapshot.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_knex-schema..mapObject.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_knex-schema..mapValue.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_knex-schema..or.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_knex-schema..parameter.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_knex-schema..query.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_knex-schema..rawQuery.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_knex-schema..resolveColumnRef.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_knex-schema..resolvePropertyKey.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_knex-schema..tableExistsInDb.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_knex-schema..validateEntitiesAgainstDatabase.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_knex-schema..writeSnapshot.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_knex-schema.extension.applyVariantsToSchema.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_knex-schema.extension.getColumnName.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_knex-schema.extension.getPolymorphicVariantSchemas.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_knex-schema.extension.getProjections.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_knex-schema.extension.getTableName.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_knex-schema.extension.getVariants.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_log..applicationEnricher.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_log..callerEnricher.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_log..captureProperties.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_log..computeEventId.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_log..configureLogging.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_log..consoleSink.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_log..correlationIdEnricher.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_log..correlationIdMiddleware.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_log..createLogEvent.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_log..createLogger.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_log..createSink.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_log..environmentEnricher.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_log..extractCorrelationId.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_log..fileSink.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_log..formatClef.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_log..formatClefBatch.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_log..generateCorrelationId.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_log..hostnameEnricher.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_log..levelToShortString.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_log..levelToString.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_log..parseLogLevel.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_log..parseTemplate.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_log..processIdEnricher.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_log..renderTemplate.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_log..requestLoggingMiddleware.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_log..safeSerialize.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_log..samplingFilter.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_log..seqSink.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_log..useLogging.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_log.clickhouse.clickHouseSink.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_log.clickhouse.createLogsTable.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_mapper.mapper.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_orm-cli.defineConfig.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_orm.alias.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_orm.and.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_orm.applyDiff.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_orm.assertParametersBound.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_orm.buildColumnMap.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_orm.clearRow.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_orm.createDb.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_orm.createQuery.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_orm.defineEntity.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_orm.diffSchema.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_orm.encodeJsonColumn.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_orm.entitiesToSnapshot.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_orm.entitySchemaToTableState.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_orm.eq.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_orm.generateCreatePolymorphicTables.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_orm.generateCreateTable.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_orm.generateCreateTableSource.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_orm.generateMigration.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_orm.generateMigrationsForContext.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_orm.getColumnName.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_orm.getPolymorphicVariantSchemas.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_orm.getPrimaryKeyColumns.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_orm.getProjections.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_orm.getRowVersionColumn.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_orm.getTableName.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_orm.getVariants.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_orm.introspectDatabase.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_orm.isDiffEmpty.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_orm.isJsonColumn.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_orm.isParameterizedQuery.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_orm.isSqlIdentifier.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_orm.loadSnapshot.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_orm.mapObject.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_orm.mapValue.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_orm.or.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_orm.parameter.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_orm.query.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_orm.rawQuery.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_orm.resolveColumnRef.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_orm.resolvePropertyKey.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_orm.tableExistsInDb.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_orm.validateEntitiesAgainstDatabase.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_orm.writeSnapshot.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_otel..configureOtel.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_otel..instrumentKnex.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_otel..otelLogSink.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_otel..setupOtel.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_otel..traceEnricher.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_otel..tracingMiddleware.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_otel..withSpan.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_otel.client.clientTracingMiddleware.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_otel.instrumentations.outboundHttpInstrumentations.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_otel.instrumentations.runtimeMetrics.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_react-form.Field.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_react-form.FormProvider.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_react-form.FormSystemProvider.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_react-form.createFormSystem.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_react-form.defineFieldRenderer.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_react-form.useField.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_react-form.useFormSystem.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_react-form.useSchemaForm.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_scheduler-postgres.createSchedulerTables.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_scheduler-postgres.dropSchedulerTables.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_scheduler.defineJob.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_schema-json.fromJsonSchema.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_schema-json.toJsonSchema.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_schema-json.withStandardJsonSchema.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_schema.defineExtension.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_schema.defineMetadataMethod.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_schema.enumOf.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_schema.extern.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_schema.generic.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_schema.intersection.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_schema.lazy.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_schema.nul.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_schema.parseString.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_schema.withExtensions.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_server-openapi.convertSchema.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_server-openapi.createOpenApiEndpoint.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_server-openapi.generateAsyncApiSpec.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_server-openapi.generateOpenApiSpec.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_server-openapi.mapOperationSecurity.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_server-openapi.mapSecuritySchemes.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_server-openapi.resolvePath.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_server-openapi.serveAsyncApi.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_server-openapi.serveOpenApi.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_server-openapi.walkSchemas.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_server-openapi.writeOpenApiSpec.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_server..cacheResponse.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_server..computeCacheKey.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_server..createCacheTagTree.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_server..createEndpoints.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_server..createProblemDetails.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_server..createServer.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_server..createValidationProblemDetails.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_server..defineWebhook.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_server..endpointPath.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_server..errorMap.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_server..file.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_server..idempotency.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_server..implement.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_server..mapHandlers.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_server..matchEndpointPath.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_server..route.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_server..serializeTag.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_server..tracked.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_server..withErrors.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_server..withRequestSignal.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_server.contract.defineApi.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_server.contract.mergeContracts.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_server.contract.omitGroups.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_server.contract.pickGroups.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_storage.prefixedObjectKey.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_storage.publicObjectUrl.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_storage.validateObjectKey.html create mode 100644 websites/docs/public/api-docs/v5.1.0/functions/_cleverbrush_storage.validatePublicBaseUrl.html create mode 100644 websites/docs/public/api-docs/v5.1.0/hierarchy.html create mode 100644 websites/docs/public/api-docs/v5.1.0/index.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_auth.AuthenticationContext.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_auth.AuthenticationScheme.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_auth.AuthorizationCodeSchemeOptions.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_auth.AuthorizationPolicy.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_auth.ClientCredentialsSchemeOptions.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_auth.CookieOptions.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_auth.CookieSchemeOptions.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_auth.JwtPayload.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_auth.JwtSchemeOptions.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_auth.OAuthFlow.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_auth.OAuthFlows.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_auth.OidcSchemeOptions.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_client..ClientHooks.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_client..ClientOptions.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_client..EndpointMeta.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_client..FilePart.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_client..PerCallOverrides.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_client..Subscription.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_client.batching.BatchingOptions.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_client.cache.CacheOptions.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_client.cache.CacheTagMiddlewareOptions.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_client.cache.CacheTagRoot.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_client.cache.ExternalCacheTagsOptions.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_client.cache.SerializedCacheTag.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_client.dedupe.DedupeOptions.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_client.idempotency.IdempotencyOptions.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_client.offline-queue.OfflineQueueOptions.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_client.offline-queue.OfflineQueueStore.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_client.offline-queue.QueuedRequest.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_client.optimistic-update.OptimisticFailure.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_client.optimistic-update.OptimisticUpdateOptions.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_client.optimistic-update.OptimisticUpdateStore.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_client.react.OptimisticMutationConfig.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_client.react.UseSubscriptionOptions.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_client.react.UseSubscriptionState.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_client.retry.RetryOptions.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_client.timeout.TimeoutOptions.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_deep.DeepForEachAsyncOptions.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_di.IServiceProvider.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_di.ServiceDescriptor.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_di.ServiceProviderOptions.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_di.ServiceRegistrationOptions.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_env.EnvBooleanOptions.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_env.InvalidEnvVar.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_env.MissingEnvVar.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_knex-clickhouse.ClickHouseClient.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_knex-schema..AddColumnDiff.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_knex-schema..AddForeignKeyDiff.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_knex-schema..AddIndexDiff.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_knex-schema..AggregateExpression.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_knex-schema..AggregateOptions.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_knex-schema..AliasedColumn.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_knex-schema..AlterColumnDiff.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_knex-schema..BoundQuery.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_knex-schema..BoundQuerySql.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_knex-schema..CompositeCursorOptions.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_knex-schema..CursorPaginationResult.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_knex-schema..DatabaseCheckInfo.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_knex-schema..DatabaseColumnInfo.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_knex-schema..DatabaseForeignKeyInfo.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_knex-schema..DatabaseIndexInfo.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_knex-schema..DatabaseTableState.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_knex-schema..EntitySchemaValidationResult.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_knex-schema..JoinManySpec.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_knex-schema..JoinOneSpec.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_knex-schema..JoinPredicate.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_knex-schema..MigrationDiff.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_knex-schema..OutputSchema.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_knex-schema..PaginationResult.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_knex-schema..ParameterReader.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_knex-schema..PrimaryKeyColumns.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_knex-schema..QueryOutput.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_knex-schema..QueryParameter.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_knex-schema..QueryScope.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_knex-schema..ReadColumn.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_knex-schema..ReadPredicateBuilder.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_knex-schema..ReadQueryShape.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_knex-schema..ReadVariant.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_knex-schema..ReadVariants.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_knex-schema..RelationInfo.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_knex-schema..RelationSpec.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_knex-schema..ResolvedVariantConfig.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_knex-schema..ResolvedVariantSpec.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_knex-schema..RowVersionColumn.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_knex-schema..SchemaSnapshot.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_knex-schema..TableAlias.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_knex-schema..ValidatedJoinManySpec.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_knex-schema..ValidatedJoinOneSpec.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_knex-schema.extension.VariantInputForResolver.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_log..BatchingSinkOptions.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_log..ConsoleSinkOptions.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_log..CorrelationIdMiddlewareOptions.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_log..CreateSinkOptions.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_log..FileSinkOptions.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_log..LogContextStore.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_log..LogEvent.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_log..LogSink.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_log..LoggerConfig.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_log..RequestLoggingOptions.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_log..RotationOptions.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_log..SeqSinkOptions.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_log..SerializationOptions.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_log..TypedTemplate.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_log.clickhouse.ClickHouseColumnMapping.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_log.clickhouse.ClickHouseSinkOptions.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_log.clickhouse.CreateLogsTableOptions.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_orm-cli.MigrationsConfig.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_orm-cli.OrmCliConfig.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_orm.AddColumnDiff.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_orm.AddForeignKeyDiff.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_orm.AddIndexDiff.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_orm.AggregateExpression.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_orm.AggregateOptions.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_orm.AliasedColumn.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_orm.AlterColumnDiff.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_orm.BoundQuery.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_orm.BoundQuerySql.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_orm.CompositeCursorOptions.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_orm.CursorPaginationResult.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_orm.DatabaseCheckInfo.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_orm.DatabaseColumnInfo.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_orm.DatabaseForeignKeyInfo.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_orm.DatabaseIndexInfo.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_orm.DatabaseTableState.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_orm.DbSetOperations.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_orm.EntityEntry.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_orm.EntitySchemaValidationResult.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_orm.JoinManySpec.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_orm.JoinOneSpec.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_orm.JoinPredicate.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_orm.MigrationDiff.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_orm.OutputSchema.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_orm.PaginationResult.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_orm.ParameterReader.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_orm.PolymorphicEntityQuery.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_orm.PrimaryKeyColumns.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_orm.QueryOutput.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_orm.QueryParameter.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_orm.QueryScope.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_orm.ReadColumn.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_orm.ReadPredicateBuilder.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_orm.ReadQueryShape.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_orm.ReadVariant.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_orm.ReadVariants.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_orm.RelationInfo.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_orm.RelationSpec.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_orm.ResolvedVariantConfig.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_orm.ResolvedVariantSpec.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_orm.RowVersionColumn.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_orm.SchemaSnapshot.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_orm.TableAlias.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_orm.TableEntityQuery.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_orm.TransactionOptions.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_orm.ValidatedJoinManySpec.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_orm.ValidatedJoinOneSpec.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_orm.VariantDbSet.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_otel..ConfigureOtelOptions.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_otel..InstrumentKnexOptions.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_otel..OtelConfig.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_otel..OtelHandle.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_otel..OtelLogSinkOptions.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_otel..SpanHandle.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_otel..TracingMiddlewareOptions.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_otel..WithSpanOptions.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_otel.client.ClientTracingEndpointMeta.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_otel.client.ClientTracingInfo.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_otel.client.ClientTracingMiddlewareOptions.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_scheduler.JobDefinition.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_scheduler.JobStorage.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_scheduler.JobStorageTransaction.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_schema-json.StandardJSONSchemaV1.Converter.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_schema-json.StandardJSONSchemaV1.Options.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_schema-json.StandardJSONSchemaV1.Props.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_schema-json.StandardJSONSchemaV1.Types.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_schema-json.StandardJSONSchemaV1.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_schema-json.StandardTypedV1.Props.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_schema-json.StandardTypedV1.Types.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_schema-json.StandardTypedV1.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_schema.ArrayBuiltinExtensions.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_schema.MetadataMethodBuilder.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_schema.NumberBuiltinExtensions.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_schema.StandardSchemaV1.FailureResult.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_schema.StandardSchemaV1.Issue.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_schema.StandardSchemaV1.Options.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_schema.StandardSchemaV1.PathSegment.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_schema.StandardSchemaV1.Props.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_schema.StandardSchemaV1.SuccessResult.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_schema.StandardSchemaV1.Types.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_schema.StandardSchemaV1.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_schema.StandardTypedV1.Props.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_schema.StandardTypedV1.Types.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_schema.StandardTypedV1.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_schema.StringBuiltinExtensions.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_server-openapi.AsyncApiInfo.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_server-openapi.AsyncApiOptions.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_server-openapi.AsyncApiServerEntry.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_server-openapi.AsyncApiServer_ServerLike.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_server-openapi.OpenApiEndpointOptions.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_server-openapi.OpenApiInfo.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_server-openapi.OpenApiOptions.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_server-openapi.OpenApiSecurityScheme.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_server-openapi.OpenApiServer.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_server-openapi.OpenApiServer_ServerLike.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_server-openapi.OpenApiTag.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_server-openapi.PathParameterInfo.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_server-openapi.ResolvedPath.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_server-openapi.ServeAsyncApiOptions.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_server-openapi.ServeOpenApiOptions.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_server..AuthenticationConfig.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_server..AuthorizationConfig.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_server..CacheTagDefinition.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_server..CacheTagPropertyAccessor.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_server..CallbackDefinition.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_server..ContentTypeHandler.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_server..EndpointIdempotencyLimits.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_server..EndpointMetadata.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_server..EndpointRegistration.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_server..FilePart.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_server..HandlerMapping.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_server..ImplementationDefaults.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_server..ImplementationGroupOptions.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_server..ImplementationOperationOptions.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_server..LinkDefinition.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_server..ProblemDetails.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_server..RejectedFile.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_server..RequestSignalContext.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_server..RequestSignalOptions.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_server..ServerBatchingOptions.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_server..ServerCacheOptions.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_server..ServerCorsOptions.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_server..ServerIdempotencyOptions.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_server..ServerOptions.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_server..SubscriptionMetadata.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_server..SubscriptionRegistration.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_server..TrackedEvent.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_server..UploadConfiguration.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_server..UploadOptions.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_server..ValidationErrorItem.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_server..WebhookDefinition.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_storage-s3.S3Credentials.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_storage-s3.S3StorageOptions.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_storage.ObjectHeaders.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_storage.ObjectMetadata.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_storage.ObjectStorage.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_storage.PutOptions.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_storage.StorageOptions.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_storage.StorageReadResult.html create mode 100644 websites/docs/public/api-docs/v5.1.0/interfaces/_cleverbrush_storage.StoredObject.html create mode 100644 websites/docs/public/api-docs/v5.1.0/media/LICENSE create mode 100644 websites/docs/public/api-docs/v5.1.0/media/MIGRATION-v5-1.md create mode 100644 websites/docs/public/api-docs/v5.1.0/media/MIGRATION-v5-2.md create mode 100644 websites/docs/public/api-docs/v5.1.0/media/MIGRATION-v5.md create mode 100644 websites/docs/public/api-docs/v5.1.0/media/README.md create mode 100644 websites/docs/public/api-docs/v5.1.0/media/SECURITY.md create mode 100644 websites/docs/public/api-docs/v5.1.0/media/cache-form-migration.md create mode 100644 websites/docs/public/api-docs/v5.1.0/media/ci.yml create mode 100644 websites/docs/public/api-docs/v5.1.0/modules.html create mode 100644 websites/docs/public/api-docs/v5.1.0/modules/_cleverbrush_async.html create mode 100644 websites/docs/public/api-docs/v5.1.0/modules/_cleverbrush_auth.html create mode 100644 websites/docs/public/api-docs/v5.1.0/modules/_cleverbrush_client..html create mode 100644 websites/docs/public/api-docs/v5.1.0/modules/_cleverbrush_client.batching.html create mode 100644 websites/docs/public/api-docs/v5.1.0/modules/_cleverbrush_client.cache.html create mode 100644 websites/docs/public/api-docs/v5.1.0/modules/_cleverbrush_client.dedupe.html create mode 100644 websites/docs/public/api-docs/v5.1.0/modules/_cleverbrush_client.html create mode 100644 websites/docs/public/api-docs/v5.1.0/modules/_cleverbrush_client.idempotency.html create mode 100644 websites/docs/public/api-docs/v5.1.0/modules/_cleverbrush_client.offline-queue.html create mode 100644 websites/docs/public/api-docs/v5.1.0/modules/_cleverbrush_client.optimistic-update.html create mode 100644 websites/docs/public/api-docs/v5.1.0/modules/_cleverbrush_client.react.html create mode 100644 websites/docs/public/api-docs/v5.1.0/modules/_cleverbrush_client.retry.html create mode 100644 websites/docs/public/api-docs/v5.1.0/modules/_cleverbrush_client.timeout.html create mode 100644 websites/docs/public/api-docs/v5.1.0/modules/_cleverbrush_deep.html create mode 100644 websites/docs/public/api-docs/v5.1.0/modules/_cleverbrush_di.html create mode 100644 websites/docs/public/api-docs/v5.1.0/modules/_cleverbrush_env.html create mode 100644 websites/docs/public/api-docs/v5.1.0/modules/_cleverbrush_knex-clickhouse.html create mode 100644 websites/docs/public/api-docs/v5.1.0/modules/_cleverbrush_knex-schema..html create mode 100644 websites/docs/public/api-docs/v5.1.0/modules/_cleverbrush_knex-schema.extension.html create mode 100644 websites/docs/public/api-docs/v5.1.0/modules/_cleverbrush_knex-schema.html create mode 100644 websites/docs/public/api-docs/v5.1.0/modules/_cleverbrush_log..html create mode 100644 websites/docs/public/api-docs/v5.1.0/modules/_cleverbrush_log.clickhouse.html create mode 100644 websites/docs/public/api-docs/v5.1.0/modules/_cleverbrush_log.html create mode 100644 websites/docs/public/api-docs/v5.1.0/modules/_cleverbrush_mapper.html create mode 100644 websites/docs/public/api-docs/v5.1.0/modules/_cleverbrush_orm-cli.html create mode 100644 websites/docs/public/api-docs/v5.1.0/modules/_cleverbrush_orm.html create mode 100644 websites/docs/public/api-docs/v5.1.0/modules/_cleverbrush_otel..html create mode 100644 websites/docs/public/api-docs/v5.1.0/modules/_cleverbrush_otel.client.html create mode 100644 websites/docs/public/api-docs/v5.1.0/modules/_cleverbrush_otel.html create mode 100644 websites/docs/public/api-docs/v5.1.0/modules/_cleverbrush_otel.instrumentations.html create mode 100644 websites/docs/public/api-docs/v5.1.0/modules/_cleverbrush_react-form.html create mode 100644 websites/docs/public/api-docs/v5.1.0/modules/_cleverbrush_scheduler-postgres.html create mode 100644 websites/docs/public/api-docs/v5.1.0/modules/_cleverbrush_scheduler.html create mode 100644 websites/docs/public/api-docs/v5.1.0/modules/_cleverbrush_schema-json.StandardJSONSchemaV1.html create mode 100644 websites/docs/public/api-docs/v5.1.0/modules/_cleverbrush_schema-json.StandardTypedV1.html create mode 100644 websites/docs/public/api-docs/v5.1.0/modules/_cleverbrush_schema-json.html create mode 100644 websites/docs/public/api-docs/v5.1.0/modules/_cleverbrush_schema.StandardSchemaV1.html create mode 100644 websites/docs/public/api-docs/v5.1.0/modules/_cleverbrush_schema.StandardTypedV1.html create mode 100644 websites/docs/public/api-docs/v5.1.0/modules/_cleverbrush_schema.html create mode 100644 websites/docs/public/api-docs/v5.1.0/modules/_cleverbrush_server-openapi.html create mode 100644 websites/docs/public/api-docs/v5.1.0/modules/_cleverbrush_server..html create mode 100644 websites/docs/public/api-docs/v5.1.0/modules/_cleverbrush_server.contract.html create mode 100644 websites/docs/public/api-docs/v5.1.0/modules/_cleverbrush_server.html create mode 100644 websites/docs/public/api-docs/v5.1.0/modules/_cleverbrush_storage-s3.html create mode 100644 websites/docs/public/api-docs/v5.1.0/modules/_cleverbrush_storage.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_auth.AuthenticationResult.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_auth.AuthorizationRequirement.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_auth.AuthorizationResult.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_client..ApiContract.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_client..EndpointCall.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_client..EndpointCallArgs.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_client..EndpointResponse.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_client..FetchLike.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_client..Middleware.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_client..SubscriptionCall.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_client..SubscriptionCallArgs.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_client..SubscriptionIncoming.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_client..SubscriptionOutgoing.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_client..TypedClient.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_client..ValidationIssueSource.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_client.react.EndpointQueryHooks.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_client.react.InfiniteQueryHookOptions.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_client.react.MutationHookOptions.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_client.react.QueryHookOptions.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_client.react.SuspenseQueryHookOptions.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_client.react.TypedQueryClient.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_client.react.TypedQueryGroup.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_client.react.UnifiedClient.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_client.react.UnifiedEndpointCall.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_client.react.UnifiedGroup.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_deep.Merge.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_deep.MergeTwo.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_di.ServiceFactory.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_env.EnvConfig.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_env.EnvConfigNode.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_env.EnvField.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_env.InferEnvConfig.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_knex-schema..AggregateResult.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_knex-schema..AliasTables.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_knex-schema..AttachParameters.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_knex-schema..CheckParameterState.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_knex-schema..ColumnReadSchema.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_knex-schema..ColumnRef.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_knex-schema..EntityPropSelector.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_knex-schema..EntityReadSchema.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_knex-schema..EntityRelationKeys.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_knex-schema..EntityRelations.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_knex-schema..EntitySchema.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_knex-schema..EntitySchemaValidationIssue.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_knex-schema..EntityVariantUnion.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_knex-schema..InferDatabaseRow.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_knex-schema..InferDatabaseValue.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_knex-schema..InsertType.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_knex-schema..JoinedProjection.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_knex-schema..MergeParameters.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_knex-schema..ObjectReadSchema.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_knex-schema..ParameterState.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_knex-schema..ParameterizedQuery.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_knex-schema..ParametersOf.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_knex-schema..PolymorphicRowSchema.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_knex-schema..PrimaryKeyOf.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_knex-schema..PrimaryKeyValueOf.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_knex-schema..QueryArguments.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_knex-schema..QueryDefinition.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_knex-schema..QueryView.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_knex-schema..ReadAliasTables.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_knex-schema..ReadColumns.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_knex-schema..ReadMembership.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_knex-schema..ReadObject.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_knex-schema..ReadPredicateGroup.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_knex-schema..ReadPredicateMethods.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_knex-schema..ReadPredicateSelector.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_knex-schema..ReadProjection.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_knex-schema..ReadRelations.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_knex-schema..ReadSchema.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_knex-schema..ReadValue.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_knex-schema..ReadVariantMetadata.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_knex-schema..RowVersionStrategy.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_knex-schema..SchemaAwareQuery.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_knex-schema..SchemaForValue.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_knex-schema..SchemaKeys.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_knex-schema..SchemaProps.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_knex-schema..SelectProjection.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_knex-schema..SelectSelector.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_knex-schema..UnwrapNavSchema.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_knex-schema..ValidatedSpec.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_knex-schema..VariantBranch.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_knex-schema..VariantReadSchema.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_knex-schema..VariantReadSchemas.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_knex-schema..VariantStorageType.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_knex-schema..WithJoinedMany.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_knex-schema..WithJoinedOne.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_knex-schema..WithReadVariant.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_knex-schema..WithRelation.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_knex-schema.extension.PrimaryKeyColumn.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_log..Enricher.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_log..LogFilter.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_log..LogLevel.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_log..LogLevelName.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_log..SamplingRates.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_mapper.SchemaToSchemaMapperResult.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_mapper.SyncSchemaToSchemaMapperResult.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_orm.AggregateResult.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_orm.AliasTables.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_orm.AttachParameters.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_orm.CheckParameterState.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_orm.ColumnReadSchema.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_orm.ColumnRef.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_orm.DbContext.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_orm.DbSet.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_orm.EntityMap.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_orm.EntityPropSelector.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_orm.EntityQuery.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_orm.EntityReadSchema.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_orm.EntityRelationKeys.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_orm.EntityRelations.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_orm.EntityResult.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_orm.EntityResultByVariant.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_orm.EntitySchema.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_orm.EntitySchemaValidationIssue.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_orm.EntityVariantUnion.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_orm.EntryState.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_orm.ExtractBranch.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_orm.HasVariants.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_orm.InferDatabaseRow.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_orm.InferDatabaseValue.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_orm.InsertType.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_orm.JoinedProjection.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_orm.MergeParameters.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_orm.ObjectReadSchema.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_orm.ParameterState.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_orm.ParameterizedQuery.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_orm.ParametersOf.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_orm.PolymorphicRowSchema.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_orm.PrimaryKeyColumn.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_orm.PrimaryKeyOf.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_orm.PrimaryKeyValueOf.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_orm.QueryArguments.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_orm.QueryDefinition.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_orm.QueryView.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_orm.ReadAliasTables.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_orm.ReadColumns.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_orm.ReadMembership.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_orm.ReadObject.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_orm.ReadPredicateGroup.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_orm.ReadPredicateMethods.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_orm.ReadPredicateSelector.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_orm.ReadProjection.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_orm.ReadRelations.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_orm.ReadSchema.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_orm.ReadValue.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_orm.ReadVariantMetadata.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_orm.RelKeyTree.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_orm.RelatedSchema.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_orm.ResolvedRel.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_orm.RowVersionStrategy.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_orm.SaveGraph.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_orm.SavingChangesHook.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_orm.SchemaAwareQuery.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_orm.SchemaForValue.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_orm.SchemaKeys.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_orm.SchemaProps.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_orm.SelectProjection.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_orm.SelectSelector.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_orm.TrackedDbContext.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_orm.UnwrapNavSchema.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_orm.ValidatedSpec.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_orm.VariantBranch.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_orm.VariantInsertPayload.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_orm.VariantReadSchema.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_orm.VariantReadSchemas.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_orm.VariantResult.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_orm.VariantStorageType.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_orm.VariantUpdatePayload.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_orm.WithIncluded.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_orm.WithJoinedMany.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_orm.WithJoinedOne.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_orm.WithReadVariant.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_orm.WithRelation.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_orm.WithVariantIncluded.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_otel.client.ClientMiddleware.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_otel.client.FetchLike.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_react-form.FieldProps.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_react-form.FieldRenderProps.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_react-form.FieldRenderer.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_react-form.FieldState.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_react-form.FormIssue.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_react-form.FormProviderProps.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_react-form.FormSubmissionState.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_react-form.FormSubmitHandler.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_react-form.FormSubmitOptions.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_react-form.FormSubmitResult.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_react-form.FormSystemConfig.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_react-form.FormSystemProviderProps.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_react-form.SchemaFormInstance.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_react-form.TypedFieldComponent.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_react-form.TypedFieldProps.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_react-form.TypedFieldRenderer.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_react-form.TypedFormSystem.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_react-form.TypedRendererRegistry.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_react-form.UseFieldResult.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_react-form.UseSchemaFormOptions.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_scheduler-postgres.PostgresStorageOptions.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_scheduler.JobAttempt.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_scheduler.JobBinding.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_scheduler.JobContext.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_scheduler.JobError.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_scheduler.JobEvent.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_scheduler.JobHandler.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_scheduler.JobOptions.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_scheduler.JobRepositoryHealth.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_scheduler.JobRun.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_scheduler.JobSchedulerOptions.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_scheduler.JobSchema.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_scheduler.JobSubmission.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_scheduler.JobWorkerOptions.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_scheduler.JsonValue.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_scheduler.RetryPolicy.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_scheduler.RunPolicy.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_scheduler.RunRecord.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_scheduler.RunStatus.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_scheduler.Schedule.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_scheduler.ScheduleRecord.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_scheduler.ScheduleSubmission.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_scheduler.SchedulerDiagnostic.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_scheduler.StoredSchedule.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_scheduler.SupportedJob.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_scheduler.TaskSchedule.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_schema-json.InferFromJsonSchema.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_schema-json.JsonSchemaNode.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_schema-json.JsonSchemaNodeToBuilder.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_schema-json.StandardJSONSchemaV1.InferInput.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_schema-json.StandardJSONSchemaV1.InferOutput.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_schema-json.StandardJSONSchemaV1.Target.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_schema-json.StandardTypedV1.InferInput.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_schema-json.StandardTypedV1.InferOutput.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_schema-json.ToJsonSchemaOptions.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_schema.ArraySchemaValidationResult.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_schema.BRAND-1.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_schema.Brand.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_schema.CleanExtended.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_schema.ElementValidationResult.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_schema.ExtendedAny.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_schema.ExtendedArray.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_schema.ExtendedBoolean.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_schema.ExtendedDate.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_schema.ExtendedFunc.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_schema.ExtendedNumber.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_schema.ExtendedObject.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_schema.ExtendedPromise.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_schema.ExtendedRecord.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_schema.ExtendedString.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_schema.ExtendedTuple.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_schema.ExtendedUnion.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_schema.ExtensionConfig.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_schema.ExtensionDescriptor.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_schema.ExtraProperties.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_schema.ExtraTypeBrandSymbol.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_schema.FixedMethods.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_schema.HiddenExtensionMethods.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_schema.IndexedPropertyDescriptor.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_schema.InferExtensionMetadata.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_schema.InferType.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_schema.IntersectionSchemaValidationResult.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_schema.MakeOptional.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_schema.MetadataExtended.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_schema.MetadataMethod.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_schema.MetadataMethods.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_schema.MetadataState.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_schema.MethodLiteralBrandSymbol.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_schema.NestedValidationResult.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_schema.NumberOneOfExtension.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_schema.ObjectSchemaValidationResult.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_schema.OptionValidationResults.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_schema.ParseStringTemplateTag.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_schema.PropertyDescriptor.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_schema.PropertyDescriptorInner.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_schema.PropertyDescriptorTree.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_schema.PropertySetterOptions.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_schema.RecordSchemaValidationResult.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_schema.SchemaPropertySelector.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_schema.SchemaTypeBrand.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_schema.StandardSchemaV1.InferInput.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_schema.StandardSchemaV1.InferOutput.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_schema.StandardSchemaV1.Result.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_schema.StandardTypedV1.InferInput.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_schema.StandardTypedV1.InferOutput.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_schema.StringOneOfExtension.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_schema.TupleElementValidationResults.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_schema.TupleSchemaValidationResult.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_schema.UnionSchemaValidationResult.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_schema.ValidationError.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_schema.ValidationErrorMessageProvider.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_schema.ValidationResult.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_server-openapi.AsyncApiDocument.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_server-openapi.OpenApiDocument.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_server..ActionContext.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_server..AllowedResponseReturn.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_server..EndpointMetadataDescriptors.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_server..EndpointOptions.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_server..EndpointParams.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_server..ErrorResponse.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_server..ErrorResponsesOf.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_server..Handler.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_server..HandlerEntry.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_server..HandlerMap.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_server..IdempotencyScope.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_server..ImplementationHandlerEntry.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_server..ImplementationHandlers.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_server..Middleware.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_server..PropertyRefTree.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_server..RawResultHandler.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_server..ResponsesOf.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_server..ScopedEndpointFactory.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_server..SubscriptionContext.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_server..SubscriptionHandler.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_server..SubscriptionHandlerEntry.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_server..UploadContract.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_server..UploadFiles.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_server..UploadSchema.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_server.contract.ApiContract.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_server.contract.ApiGroup.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_server.contract.MergedContracts.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_storage.StorageBody.html create mode 100644 websites/docs/public/api-docs/v5.1.0/types/_cleverbrush_storage.StorageErrorCode.html create mode 100644 websites/docs/public/api-docs/v5.1.0/variables/_cleverbrush_client..PER_CALL_OPTIONS.html create mode 100644 websites/docs/public/api-docs/v5.1.0/variables/_cleverbrush_client.optimistic-update.OPTIMISTIC_MUTATION_ID.html create mode 100644 websites/docs/public/api-docs/v5.1.0/variables/_cleverbrush_client.react.QUERY_KEY_PREFIX.html create mode 100644 websites/docs/public/api-docs/v5.1.0/variables/_cleverbrush_deep.deepExtend.html create mode 100644 websites/docs/public/api-docs/v5.1.0/variables/_cleverbrush_knex-schema..COMPILED_READER.html create mode 100644 websites/docs/public/api-docs/v5.1.0/variables/_cleverbrush_knex-schema..EXTRA_TYPE_BRAND.html create mode 100644 websites/docs/public/api-docs/v5.1.0/variables/_cleverbrush_knex-schema..MAPPERS.html create mode 100644 websites/docs/public/api-docs/v5.1.0/variables/_cleverbrush_knex-schema..METHOD_LITERAL_BRAND.html create mode 100644 websites/docs/public/api-docs/v5.1.0/variables/_cleverbrush_knex-schema..PARAMETER_READER.html create mode 100644 websites/docs/public/api-docs/v5.1.0/variables/_cleverbrush_knex-schema..PARAMETER_STATE.html create mode 100644 websites/docs/public/api-docs/v5.1.0/variables/_cleverbrush_knex-schema..READ_ENTITY.html create mode 100644 websites/docs/public/api-docs/v5.1.0/variables/_cleverbrush_knex-schema..aggregate.html create mode 100644 websites/docs/public/api-docs/v5.1.0/variables/_cleverbrush_knex-schema.extension.COMPOSITE_PRIMARY_KEY_BRAND.html create mode 100644 websites/docs/public/api-docs/v5.1.0/variables/_cleverbrush_knex-schema.extension.POLYMORPHIC_TYPE_BRAND.html create mode 100644 websites/docs/public/api-docs/v5.1.0/variables/_cleverbrush_knex-schema.extension.PRIMARY_KEY_BRAND.html create mode 100644 websites/docs/public/api-docs/v5.1.0/variables/_cleverbrush_knex-schema.extension.any.html create mode 100644 websites/docs/public/api-docs/v5.1.0/variables/_cleverbrush_knex-schema.extension.array.html create mode 100644 websites/docs/public/api-docs/v5.1.0/variables/_cleverbrush_knex-schema.extension.boolean.html create mode 100644 websites/docs/public/api-docs/v5.1.0/variables/_cleverbrush_knex-schema.extension.date.html create mode 100644 websites/docs/public/api-docs/v5.1.0/variables/_cleverbrush_knex-schema.extension.dbExtension.html create mode 100644 websites/docs/public/api-docs/v5.1.0/variables/_cleverbrush_knex-schema.extension.ddlExtension.html create mode 100644 websites/docs/public/api-docs/v5.1.0/variables/_cleverbrush_knex-schema.extension.func.html create mode 100644 websites/docs/public/api-docs/v5.1.0/variables/_cleverbrush_knex-schema.extension.number.html create mode 100644 websites/docs/public/api-docs/v5.1.0/variables/_cleverbrush_knex-schema.extension.object.html create mode 100644 websites/docs/public/api-docs/v5.1.0/variables/_cleverbrush_knex-schema.extension.string.html create mode 100644 websites/docs/public/api-docs/v5.1.0/variables/_cleverbrush_knex-schema.extension.union.html create mode 100644 websites/docs/public/api-docs/v5.1.0/variables/_cleverbrush_log..ILogger.html create mode 100644 websites/docs/public/api-docs/v5.1.0/variables/_cleverbrush_log..LogContext.html create mode 100644 websites/docs/public/api-docs/v5.1.0/variables/_cleverbrush_log..LogLevel.html create mode 100644 websites/docs/public/api-docs/v5.1.0/variables/_cleverbrush_log..SelfLog.html create mode 100644 websites/docs/public/api-docs/v5.1.0/variables/_cleverbrush_orm.COMPILED_READER.html create mode 100644 websites/docs/public/api-docs/v5.1.0/variables/_cleverbrush_orm.COMPOSITE_PRIMARY_KEY_BRAND.html create mode 100644 websites/docs/public/api-docs/v5.1.0/variables/_cleverbrush_orm.EXTRA_TYPE_BRAND.html create mode 100644 websites/docs/public/api-docs/v5.1.0/variables/_cleverbrush_orm.MAPPERS.html create mode 100644 websites/docs/public/api-docs/v5.1.0/variables/_cleverbrush_orm.METHOD_LITERAL_BRAND.html create mode 100644 websites/docs/public/api-docs/v5.1.0/variables/_cleverbrush_orm.PARAMETER_READER.html create mode 100644 websites/docs/public/api-docs/v5.1.0/variables/_cleverbrush_orm.PARAMETER_STATE.html create mode 100644 websites/docs/public/api-docs/v5.1.0/variables/_cleverbrush_orm.POLYMORPHIC_TYPE_BRAND.html create mode 100644 websites/docs/public/api-docs/v5.1.0/variables/_cleverbrush_orm.PRIMARY_KEY_BRAND.html create mode 100644 websites/docs/public/api-docs/v5.1.0/variables/_cleverbrush_orm.READ_ENTITY.html create mode 100644 websites/docs/public/api-docs/v5.1.0/variables/_cleverbrush_orm.aggregate.html create mode 100644 websites/docs/public/api-docs/v5.1.0/variables/_cleverbrush_orm.any.html create mode 100644 websites/docs/public/api-docs/v5.1.0/variables/_cleverbrush_orm.array.html create mode 100644 websites/docs/public/api-docs/v5.1.0/variables/_cleverbrush_orm.boolean.html create mode 100644 websites/docs/public/api-docs/v5.1.0/variables/_cleverbrush_orm.date.html create mode 100644 websites/docs/public/api-docs/v5.1.0/variables/_cleverbrush_orm.dbExtension.html create mode 100644 websites/docs/public/api-docs/v5.1.0/variables/_cleverbrush_orm.ddlExtension.html create mode 100644 websites/docs/public/api-docs/v5.1.0/variables/_cleverbrush_orm.func.html create mode 100644 websites/docs/public/api-docs/v5.1.0/variables/_cleverbrush_orm.number.html create mode 100644 websites/docs/public/api-docs/v5.1.0/variables/_cleverbrush_orm.object.html create mode 100644 websites/docs/public/api-docs/v5.1.0/variables/_cleverbrush_orm.string.html create mode 100644 websites/docs/public/api-docs/v5.1.0/variables/_cleverbrush_orm.union.html create mode 100644 websites/docs/public/api-docs/v5.1.0/variables/_cleverbrush_otel..IMeter.html create mode 100644 websites/docs/public/api-docs/v5.1.0/variables/_cleverbrush_otel..ITracer.html create mode 100644 websites/docs/public/api-docs/v5.1.0/variables/_cleverbrush_otel..OTEL_SPAN_ITEM_KEY.html create mode 100644 websites/docs/public/api-docs/v5.1.0/variables/_cleverbrush_scheduler.ScheduleDaySchema.html create mode 100644 websites/docs/public/api-docs/v5.1.0/variables/_cleverbrush_scheduler.ScheduleMinuteSchema.html create mode 100644 websites/docs/public/api-docs/v5.1.0/variables/_cleverbrush_scheduler.ScheduleMonthSchema.html create mode 100644 websites/docs/public/api-docs/v5.1.0/variables/_cleverbrush_scheduler.ScheduleSchema.html create mode 100644 websites/docs/public/api-docs/v5.1.0/variables/_cleverbrush_scheduler.ScheduleSchemaBase.html create mode 100644 websites/docs/public/api-docs/v5.1.0/variables/_cleverbrush_scheduler.ScheduleWeekSchema.html create mode 100644 websites/docs/public/api-docs/v5.1.0/variables/_cleverbrush_scheduler.ScheduleYearSchema.html create mode 100644 websites/docs/public/api-docs/v5.1.0/variables/_cleverbrush_scheduler.Schemas.html create mode 100644 websites/docs/public/api-docs/v5.1.0/variables/_cleverbrush_schema.EXTRA_TYPE_BRAND.html create mode 100644 websites/docs/public/api-docs/v5.1.0/variables/_cleverbrush_schema.METHOD_LITERAL_BRAND.html create mode 100644 websites/docs/public/api-docs/v5.1.0/variables/_cleverbrush_schema.SYMBOL_HAS_PROPERTIES.html create mode 100644 websites/docs/public/api-docs/v5.1.0/variables/_cleverbrush_schema.SYMBOL_SCHEMA_PROPERTY_DESCRIPTOR.html create mode 100644 websites/docs/public/api-docs/v5.1.0/variables/_cleverbrush_schema.any.html create mode 100644 websites/docs/public/api-docs/v5.1.0/variables/_cleverbrush_schema.array.html create mode 100644 websites/docs/public/api-docs/v5.1.0/variables/_cleverbrush_schema.arrayExtensions.html create mode 100644 websites/docs/public/api-docs/v5.1.0/variables/_cleverbrush_schema.boolean.html create mode 100644 websites/docs/public/api-docs/v5.1.0/variables/_cleverbrush_schema.date.html create mode 100644 websites/docs/public/api-docs/v5.1.0/variables/_cleverbrush_schema.func.html create mode 100644 websites/docs/public/api-docs/v5.1.0/variables/_cleverbrush_schema.number.html create mode 100644 websites/docs/public/api-docs/v5.1.0/variables/_cleverbrush_schema.numberExtensions.html create mode 100644 websites/docs/public/api-docs/v5.1.0/variables/_cleverbrush_schema.object.html create mode 100644 websites/docs/public/api-docs/v5.1.0/variables/_cleverbrush_schema.promise.html create mode 100644 websites/docs/public/api-docs/v5.1.0/variables/_cleverbrush_schema.record.html create mode 100644 websites/docs/public/api-docs/v5.1.0/variables/_cleverbrush_schema.string.html create mode 100644 websites/docs/public/api-docs/v5.1.0/variables/_cleverbrush_schema.stringExtensions.html create mode 100644 websites/docs/public/api-docs/v5.1.0/variables/_cleverbrush_schema.tuple.html create mode 100644 websites/docs/public/api-docs/v5.1.0/variables/_cleverbrush_schema.union.html create mode 100644 websites/docs/public/api-docs/v5.1.0/variables/_cleverbrush_server..DEFAULT_MAX_BODY_SIZE.html create mode 100644 websites/docs/public/api-docs/v5.1.0/variables/_cleverbrush_server..IRequestContext.html create mode 100644 websites/docs/public/api-docs/v5.1.0/variables/_cleverbrush_server..endpoint.html create mode 100644 websites/docs/public/api-docs/v5.1.0/variables/_cleverbrush_server..formUrlEncodedContentTypeHandler.html create mode 100644 websites/docs/public/api-docs/v5.1.0/variables/_cleverbrush_server..jsonContentTypeHandler.html diff --git a/.changeset/deep-sort-sparse.md b/.changeset/deep-sort-sparse.md deleted file mode 100644 index 58f887f7..00000000 --- a/.changeset/deep-sort-sparse.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@cleverbrush/deep": patch ---- - -Reject sparse record arrays before sorting so missing elements cannot duplicate existing records or partially mutate input. diff --git a/.changeset/deep-traversal-sort.md b/.changeset/deep-traversal-sort.md deleted file mode 100644 index 64991ab9..00000000 --- a/.changeset/deep-traversal-sort.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@cleverbrush/deep": minor ---- - -Add sequential deepForEachAsync traversal and stable in-place deepSort with typed options, explicit validation and failure propagation. diff --git a/.changeset/react-form-blur-lifecycle.md b/.changeset/react-form-blur-lifecycle.md deleted file mode 100644 index e0b15f2b..00000000 --- a/.changeset/react-form-blur-lifecycle.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -"@cleverbrush/react-form": minor ---- - -Add opt-in immediate blur validation that touches only the blurred field, and an -awaitable invalid-submission callback with existing duplicate and stale-result -protection. Opt-in validation-rule refresh retains edited values and field state -while adopting current bounds/messages and suppressing stale callbacks. Existing blur and submission defaults remain unchanged. diff --git a/.changeset/request-cancellation.md b/.changeset/request-cancellation.md deleted file mode 100644 index 9376f600..00000000 --- a/.changeset/request-cancellation.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@cleverbrush/server": minor ---- - -Add withRequestSignal for cooperative request-disconnect, caller and deadline cancellation with deterministic lifecycle cleanup. diff --git a/.changeset/typed-paths-and-transaction-locks.md b/.changeset/typed-paths-and-transaction-locks.md deleted file mode 100644 index eea365df..00000000 --- a/.changeset/typed-paths-and-transaction-locks.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -"@cleverbrush/server": minor -"@cleverbrush/client": patch -"@cleverbrush/orm": minor -"@cleverbrush/schema": patch ---- - -Add typed endpoint pathname construction and matching, shared with client URL generation and server routing. Route parameters are validated and encoded as individual components. - -Add optional PostgreSQL advisory locks to ORM transactions, acquired before callbacks and released with their transaction. - -Reject non-object inputs to open object schemas with inspectable validation errors, including nested arrays, instead of throwing descriptor errors. diff --git a/.dockerignore b/.dockerignore index a2182d66..d4d3e132 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,5 +1,8 @@ -node_modules -dist -*.tsbuildinfo +**/node_modules +**/dist +**/*.tsbuildinfo /coverage .git +**/.next +**/.turbo +/websites/docs/public/api-docs/latest diff --git a/README.md b/README.md index 9dd534f9..425401b2 100644 --- a/README.md +++ b/README.md @@ -128,6 +128,21 @@ demo workflow. Each package also has local source, tests, and exports under `libs/`. +Generate the API reference from the current package sources and READMEs: + +```bash +npm run build +npm run docs +npm run docs:snapshot +``` + +Generation writes `websites/docs/public/api-docs/latest/` using the shared +published-package version. The snapshot command archives that output under +`v/` and updates the version picker. It rejects stale output and +existing snapshots. Commit the numbered archive; `latest/` is generated during +the docs container build and remains ignored by Git. To generate and archive an +explicit version, set `VERSION=1.2.3` for both documentation commands. + ## Quality Gates Every change should leave these commands passing: diff --git a/libs/async/CHANGELOG.md b/libs/async/CHANGELOG.md index 0fee2586..539f36e6 100644 --- a/libs/async/CHANGELOG.md +++ b/libs/async/CHANGELOG.md @@ -1,24 +1,27 @@ # @cleverbrush/async +## 5.1.0 + ## 5.0.0 ### Major Changes - d916566: Make Framework query builders immutable and infer row schemas automatically. - + Retain returned query builders, return synchronous builders from scopes and grouped predicates, and supply an explicit Framework object output schema for opaque raw SELECTs. Ordinary, aliased, polymorphic and ORM queries expose their row schemas directly. Projections replace scalar selections, and projected/aggregate/raw queries cannot perform entity writes. Reads and write-returning rows consistently preserve exact decimal/bigint strings, Date objects and SQL nulls. - + All published Framework packages advance together to the next major version. Tracked entity objects remain mutable. - + ### Migrating from v4.x to v5 - + Remove `withRowSchema()` calls and retain each configured query instead of relying on mutation. Replace raw base-query overloads with explicit output contracts. See `libs/knex-schema/MIGRATION-v5.md` for the complete migration guide. + - c5b4dbc: Require Node.js 24+ consistently across all published packages. Correct the root and all published-package license files to BSD-3-Clause, matching package metadata and documentation, and verify license consistency in source and npm tarballs. See docs/MIGRATION-v5.md for migration guidance. - + Harden JWT key/algorithm and claim validation, cookie parsing/serialization, and request-body lifecycle handling. Require explicit authorization scope for bounded server idempotency; coalesce concurrent retries and capture full response bodies. Bound response caching and bypass private, no-store and cookie-setting responses. - + Preserve DI scope validation through factories and propagate registered optional-service failures. Fix batch response status/header capture, timeout abort-listener cleanup, concurrent deduplication response cloning, CLI database cleanup on validation/production-guard failures, and the missing client idempotency JavaScript export. Update security-sensitive dependencies and ensure OpenTelemetry disable flags override SDK defaults. - + Add regression tests, package-consumer smoke checks, package-level unit coverage floors, migration/security documentation and release validation gates. ## 4.5.0 diff --git a/libs/async/package.json b/libs/async/package.json index 05298107..93bbd6e3 100644 --- a/libs/async/package.json +++ b/libs/async/package.json @@ -41,5 +41,5 @@ }, "type": "module", "types": "./dist/index.d.ts", - "version": "5.0.0" + "version": "5.1.0" } diff --git a/libs/auth/CHANGELOG.md b/libs/auth/CHANGELOG.md index 53975ce3..20aa2ab6 100644 --- a/libs/auth/CHANGELOG.md +++ b/libs/auth/CHANGELOG.md @@ -1,24 +1,32 @@ # @cleverbrush/auth +## 5.1.0 + +### Patch Changes + +- Updated dependencies [39c0234] + - @cleverbrush/schema@5.1.0 + ## 5.0.0 ### Major Changes - d916566: Make Framework query builders immutable and infer row schemas automatically. - + Retain returned query builders, return synchronous builders from scopes and grouped predicates, and supply an explicit Framework object output schema for opaque raw SELECTs. Ordinary, aliased, polymorphic and ORM queries expose their row schemas directly. Projections replace scalar selections, and projected/aggregate/raw queries cannot perform entity writes. Reads and write-returning rows consistently preserve exact decimal/bigint strings, Date objects and SQL nulls. - + All published Framework packages advance together to the next major version. Tracked entity objects remain mutable. - + ### Migrating from v4.x to v5 - + Remove `withRowSchema()` calls and retain each configured query instead of relying on mutation. Replace raw base-query overloads with explicit output contracts. See `libs/knex-schema/MIGRATION-v5.md` for the complete migration guide. + - c5b4dbc: Require Node.js 24+ consistently across all published packages. Correct the root and all published-package license files to BSD-3-Clause, matching package metadata and documentation, and verify license consistency in source and npm tarballs. See docs/MIGRATION-v5.md for migration guidance. - + Harden JWT key/algorithm and claim validation, cookie parsing/serialization, and request-body lifecycle handling. Require explicit authorization scope for bounded server idempotency; coalesce concurrent retries and capture full response bodies. Bound response caching and bypass private, no-store and cookie-setting responses. - + Preserve DI scope validation through factories and propagate registered optional-service failures. Fix batch response status/header capture, timeout abort-listener cleanup, concurrent deduplication response cloning, CLI database cleanup on validation/production-guard failures, and the missing client idempotency JavaScript export. Update security-sensitive dependencies and ensure OpenTelemetry disable flags override SDK defaults. - + Add regression tests, package-consumer smoke checks, package-level unit coverage floors, migration/security documentation and release validation gates. ### Patch Changes diff --git a/libs/auth/package.json b/libs/auth/package.json index 2a641cee..853b7d95 100644 --- a/libs/auth/package.json +++ b/libs/auth/package.json @@ -5,7 +5,7 @@ "email": "andrew_zol@cleverbrush.com" }, "dependencies": { - "@cleverbrush/schema": "^5.0.0" + "@cleverbrush/schema": "^5.1.0" }, "description": "Transport-agnostic authentication & authorization — JWT, cookies, role-based policies, schema-typed principals", "files": [ @@ -46,5 +46,5 @@ }, "type": "module", "types": "./dist/index.d.ts", - "version": "5.0.0" + "version": "5.1.0" } diff --git a/libs/client/CHANGELOG.md b/libs/client/CHANGELOG.md index 572690be..78aff414 100644 --- a/libs/client/CHANGELOG.md +++ b/libs/client/CHANGELOG.md @@ -1,24 +1,40 @@ # @cleverbrush/client +## 5.1.0 + +### Patch Changes + +- 39c0234: Add typed endpoint pathname construction and matching, shared with client URL generation and server routing. Route parameters are validated and encoded as individual components. + + Add optional PostgreSQL advisory locks to ORM transactions, acquired before callbacks and released with their transaction. + + Reject non-object inputs to open object schemas with inspectable validation errors, including nested arrays, instead of throwing descriptor errors. + +- Updated dependencies [5d76049] +- Updated dependencies [39c0234] + - @cleverbrush/server@5.1.0 + - @cleverbrush/schema@5.1.0 + ## 5.0.0 ### Major Changes - d916566: Make Framework query builders immutable and infer row schemas automatically. - + Retain returned query builders, return synchronous builders from scopes and grouped predicates, and supply an explicit Framework object output schema for opaque raw SELECTs. Ordinary, aliased, polymorphic and ORM queries expose their row schemas directly. Projections replace scalar selections, and projected/aggregate/raw queries cannot perform entity writes. Reads and write-returning rows consistently preserve exact decimal/bigint strings, Date objects and SQL nulls. - + All published Framework packages advance together to the next major version. Tracked entity objects remain mutable. - + ### Migrating from v4.x to v5 - + Remove `withRowSchema()` calls and retain each configured query instead of relying on mutation. Replace raw base-query overloads with explicit output contracts. See `libs/knex-schema/MIGRATION-v5.md` for the complete migration guide. + - c5b4dbc: Require Node.js 24+ consistently across all published packages. Correct the root and all published-package license files to BSD-3-Clause, matching package metadata and documentation, and verify license consistency in source and npm tarballs. See docs/MIGRATION-v5.md for migration guidance. - + Harden JWT key/algorithm and claim validation, cookie parsing/serialization, and request-body lifecycle handling. Require explicit authorization scope for bounded server idempotency; coalesce concurrent retries and capture full response bodies. Bound response caching and bypass private, no-store and cookie-setting responses. - + Preserve DI scope validation through factories and propagate registered optional-service failures. Fix batch response status/header capture, timeout abort-listener cleanup, concurrent deduplication response cloning, CLI database cleanup on validation/production-guard failures, and the missing client idempotency JavaScript export. Update security-sensitive dependencies and ensure OpenTelemetry disable flags override SDK defaults. - + Add regression tests, package-consumer smoke checks, package-level unit coverage floors, migration/security documentation and release validation gates. ### Minor Changes @@ -36,7 +52,7 @@ and part limits, reject truncated or duplicate singleton uploads, and support file-only endpoints. Existing options-only uploads retain their single-file shape and explicit MIME rejection reporting. - + Add lossless JSONB object reads and writes using native object schemas with `.acceptUnknownProps().jsonb()`. Preserve nested extension data through returning rows and projections, validate JSON extensions in the database layer, align diff --git a/libs/client/package.json b/libs/client/package.json index 1afd73fb..fdfb376c 100644 --- a/libs/client/package.json +++ b/libs/client/package.json @@ -5,8 +5,8 @@ "email": "andrew_zol@cleverbrush.com" }, "dependencies": { - "@cleverbrush/schema": "^5.0.0", - "@cleverbrush/server": "^5.0.0" + "@cleverbrush/schema": "^5.1.0", + "@cleverbrush/server": "^5.1.0" }, "devDependencies": { "@tanstack/react-query": "^5.75.0", @@ -105,5 +105,5 @@ }, "type": "module", "types": "./dist/index.d.ts", - "version": "5.0.0" + "version": "5.1.0" } diff --git a/libs/deep/CHANGELOG.md b/libs/deep/CHANGELOG.md index 9792e0e5..8f7b56c7 100644 --- a/libs/deep/CHANGELOG.md +++ b/libs/deep/CHANGELOG.md @@ -1,24 +1,35 @@ # @cleverbrush/deep +## 5.1.0 + +### Minor Changes + +- ec87c8f: Add sequential deepForEachAsync traversal and stable in-place deepSort with typed options, explicit validation and failure propagation. + +### Patch Changes + +- 9207eff: Reject sparse record arrays before sorting so missing elements cannot duplicate existing records or partially mutate input. + ## 5.0.0 ### Major Changes - d916566: Make Framework query builders immutable and infer row schemas automatically. - + Retain returned query builders, return synchronous builders from scopes and grouped predicates, and supply an explicit Framework object output schema for opaque raw SELECTs. Ordinary, aliased, polymorphic and ORM queries expose their row schemas directly. Projections replace scalar selections, and projected/aggregate/raw queries cannot perform entity writes. Reads and write-returning rows consistently preserve exact decimal/bigint strings, Date objects and SQL nulls. - + All published Framework packages advance together to the next major version. Tracked entity objects remain mutable. - + ### Migrating from v4.x to v5 - + Remove `withRowSchema()` calls and retain each configured query instead of relying on mutation. Replace raw base-query overloads with explicit output contracts. See `libs/knex-schema/MIGRATION-v5.md` for the complete migration guide. + - c5b4dbc: Require Node.js 24+ consistently across all published packages. Correct the root and all published-package license files to BSD-3-Clause, matching package metadata and documentation, and verify license consistency in source and npm tarballs. See docs/MIGRATION-v5.md for migration guidance. - + Harden JWT key/algorithm and claim validation, cookie parsing/serialization, and request-body lifecycle handling. Require explicit authorization scope for bounded server idempotency; coalesce concurrent retries and capture full response bodies. Bound response caching and bypass private, no-store and cookie-setting responses. - + Preserve DI scope validation through factories and propagate registered optional-service failures. Fix batch response status/header capture, timeout abort-listener cleanup, concurrent deduplication response cloning, CLI database cleanup on validation/production-guard failures, and the missing client idempotency JavaScript export. Update security-sensitive dependencies and ensure OpenTelemetry disable flags override SDK defaults. - + Add regression tests, package-consumer smoke checks, package-level unit coverage floors, migration/security documentation and release validation gates. ### Patch Changes diff --git a/libs/deep/package.json b/libs/deep/package.json index 15466ea2..ff2c0196 100644 --- a/libs/deep/package.json +++ b/libs/deep/package.json @@ -40,5 +40,5 @@ }, "type": "module", "types": "./dist/index.d.ts", - "version": "5.0.0" + "version": "5.1.0" } diff --git a/libs/di/CHANGELOG.md b/libs/di/CHANGELOG.md index 77604795..5b2845c4 100644 --- a/libs/di/CHANGELOG.md +++ b/libs/di/CHANGELOG.md @@ -1,24 +1,32 @@ # @cleverbrush/di +## 5.1.0 + +### Patch Changes + +- Updated dependencies [39c0234] + - @cleverbrush/schema@5.1.0 + ## 5.0.0 ### Major Changes - d916566: Make Framework query builders immutable and infer row schemas automatically. - + Retain returned query builders, return synchronous builders from scopes and grouped predicates, and supply an explicit Framework object output schema for opaque raw SELECTs. Ordinary, aliased, polymorphic and ORM queries expose their row schemas directly. Projections replace scalar selections, and projected/aggregate/raw queries cannot perform entity writes. Reads and write-returning rows consistently preserve exact decimal/bigint strings, Date objects and SQL nulls. - + All published Framework packages advance together to the next major version. Tracked entity objects remain mutable. - + ### Migrating from v4.x to v5 - + Remove `withRowSchema()` calls and retain each configured query instead of relying on mutation. Replace raw base-query overloads with explicit output contracts. See `libs/knex-schema/MIGRATION-v5.md` for the complete migration guide. + - c5b4dbc: Require Node.js 24+ consistently across all published packages. Correct the root and all published-package license files to BSD-3-Clause, matching package metadata and documentation, and verify license consistency in source and npm tarballs. See docs/MIGRATION-v5.md for migration guidance. - + Harden JWT key/algorithm and claim validation, cookie parsing/serialization, and request-body lifecycle handling. Require explicit authorization scope for bounded server idempotency; coalesce concurrent retries and capture full response bodies. Bound response caching and bypass private, no-store and cookie-setting responses. - + Preserve DI scope validation through factories and propagate registered optional-service failures. Fix batch response status/header capture, timeout abort-listener cleanup, concurrent deduplication response cloning, CLI database cleanup on validation/production-guard failures, and the missing client idempotency JavaScript export. Update security-sensitive dependencies and ensure OpenTelemetry disable flags override SDK defaults. - + Add regression tests, package-consumer smoke checks, package-level unit coverage floors, migration/security documentation and release validation gates. ### Minor Changes @@ -27,15 +35,15 @@ schemas, precise decimal/bigint decoding, nested relation graphs and explicit STI/CTI branch schemas. Reuse result schemas directly in separately defined application mappings without duplicating projection schemas. - + Add `getSyncMapper()` with synchronous eligibility inferred through the existing `configure()` API, completeness checks, nested mapping propagation and runtime thenable guards. Existing queries and asynchronous mapping behavior are unchanged. - + Add application-agnostic typed metadata extension methods that retain metadata through immutable chains. Use these in database extensions without modifying global schema prototypes. - + Preserve typed function-schema compatibility in dependency injection when a function declares its return schema. diff --git a/libs/di/package.json b/libs/di/package.json index 0ef1b70c..dfd36e0e 100644 --- a/libs/di/package.json +++ b/libs/di/package.json @@ -5,7 +5,7 @@ "email": "andrew_zol@cleverbrush.com" }, "dependencies": { - "@cleverbrush/schema": "^5.0.0" + "@cleverbrush/schema": "^5.1.0" }, "description": ".NET-style dependency injection container for TypeScript — schema-driven service registration, three lifetimes, function injection", "files": [ @@ -46,5 +46,5 @@ }, "type": "module", "types": "./dist/index.d.ts", - "version": "5.0.0" + "version": "5.1.0" } diff --git a/libs/env/CHANGELOG.md b/libs/env/CHANGELOG.md index f39767e4..2c662267 100644 --- a/libs/env/CHANGELOG.md +++ b/libs/env/CHANGELOG.md @@ -1,24 +1,33 @@ # @cleverbrush/env +## 5.1.0 + +### Patch Changes + +- Updated dependencies [9207eff] +- Updated dependencies [ec87c8f] + - @cleverbrush/deep@5.1.0 + ## 5.0.0 ### Major Changes - d916566: Make Framework query builders immutable and infer row schemas automatically. - + Retain returned query builders, return synchronous builders from scopes and grouped predicates, and supply an explicit Framework object output schema for opaque raw SELECTs. Ordinary, aliased, polymorphic and ORM queries expose their row schemas directly. Projections replace scalar selections, and projected/aggregate/raw queries cannot perform entity writes. Reads and write-returning rows consistently preserve exact decimal/bigint strings, Date objects and SQL nulls. - + All published Framework packages advance together to the next major version. Tracked entity objects remain mutable. - + ### Migrating from v4.x to v5 - + Remove `withRowSchema()` calls and retain each configured query instead of relying on mutation. Replace raw base-query overloads with explicit output contracts. See `libs/knex-schema/MIGRATION-v5.md` for the complete migration guide. + - c5b4dbc: Require Node.js 24+ consistently across all published packages. Correct the root and all published-package license files to BSD-3-Clause, matching package metadata and documentation, and verify license consistency in source and npm tarballs. See docs/MIGRATION-v5.md for migration guidance. - + Harden JWT key/algorithm and claim validation, cookie parsing/serialization, and request-body lifecycle handling. Require explicit authorization scope for bounded server idempotency; coalesce concurrent retries and capture full response bodies. Bound response caching and bypass private, no-store and cookie-setting responses. - + Preserve DI scope validation through factories and propagate registered optional-service failures. Fix batch response status/header capture, timeout abort-listener cleanup, concurrent deduplication response cloning, CLI database cleanup on validation/production-guard failures, and the missing client idempotency JavaScript export. Update security-sensitive dependencies and ensure OpenTelemetry disable flags override SDK defaults. - + Add regression tests, package-consumer smoke checks, package-level unit coverage floors, migration/security documentation and release validation gates. ### Patch Changes diff --git a/libs/env/package.json b/libs/env/package.json index 082eb60c..2d9932a8 100644 --- a/libs/env/package.json +++ b/libs/env/package.json @@ -5,7 +5,7 @@ "email": "andrew_zol@cleverbrush.com" }, "dependencies": { - "@cleverbrush/deep": "^5.0.0" + "@cleverbrush/deep": "^5.1.0" }, "peerDependencies": { "@cleverbrush/schema": "^5.0.0" @@ -54,5 +54,5 @@ "@types/node": "^25.4.0" }, "types": "./dist/index.d.ts", - "version": "5.0.0" + "version": "5.1.0" } diff --git a/libs/knex-clickhouse/CHANGELOG.md b/libs/knex-clickhouse/CHANGELOG.md index 8994afc3..12cc7aa5 100644 --- a/libs/knex-clickhouse/CHANGELOG.md +++ b/libs/knex-clickhouse/CHANGELOG.md @@ -1,24 +1,34 @@ # @cleverbrush/knex-clickhouse +## 5.1.0 + +### Patch Changes + +- Updated dependencies [9207eff] +- Updated dependencies [ec87c8f] + - @cleverbrush/deep@5.1.0 + - @cleverbrush/async@5.1.0 + ## 5.0.0 ### Major Changes - d916566: Make Framework query builders immutable and infer row schemas automatically. - + Retain returned query builders, return synchronous builders from scopes and grouped predicates, and supply an explicit Framework object output schema for opaque raw SELECTs. Ordinary, aliased, polymorphic and ORM queries expose their row schemas directly. Projections replace scalar selections, and projected/aggregate/raw queries cannot perform entity writes. Reads and write-returning rows consistently preserve exact decimal/bigint strings, Date objects and SQL nulls. - + All published Framework packages advance together to the next major version. Tracked entity objects remain mutable. - + ### Migrating from v4.x to v5 - + Remove `withRowSchema()` calls and retain each configured query instead of relying on mutation. Replace raw base-query overloads with explicit output contracts. See `libs/knex-schema/MIGRATION-v5.md` for the complete migration guide. + - c5b4dbc: Require Node.js 24+ consistently across all published packages. Correct the root and all published-package license files to BSD-3-Clause, matching package metadata and documentation, and verify license consistency in source and npm tarballs. See docs/MIGRATION-v5.md for migration guidance. - + Harden JWT key/algorithm and claim validation, cookie parsing/serialization, and request-body lifecycle handling. Require explicit authorization scope for bounded server idempotency; coalesce concurrent retries and capture full response bodies. Bound response caching and bypass private, no-store and cookie-setting responses. - + Preserve DI scope validation through factories and propagate registered optional-service failures. Fix batch response status/header capture, timeout abort-listener cleanup, concurrent deduplication response cloning, CLI database cleanup on validation/production-guard failures, and the missing client idempotency JavaScript export. Update security-sensitive dependencies and ensure OpenTelemetry disable flags override SDK defaults. - + Add regression tests, package-consumer smoke checks, package-level unit coverage floors, migration/security documentation and release validation gates. ### Patch Changes diff --git a/libs/knex-clickhouse/package.json b/libs/knex-clickhouse/package.json index d9569d61..fad1fd04 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": "^5.0.0", - "@cleverbrush/deep": "^5.0.0", + "@cleverbrush/async": "^5.1.0", + "@cleverbrush/deep": "^5.1.0", "@clickhouse/client": "^1.18.2" }, "peerDependencies": { @@ -48,5 +48,5 @@ }, "type": "module", "types": "./dist/index.d.ts", - "version": "5.0.0" + "version": "5.1.0" } diff --git a/libs/knex-schema/CHANGELOG.md b/libs/knex-schema/CHANGELOG.md index c2e77012..f6a93a2b 100644 --- a/libs/knex-schema/CHANGELOG.md +++ b/libs/knex-schema/CHANGELOG.md @@ -1,31 +1,40 @@ # @cleverbrush/knex-schema +## 5.1.0 + +### Patch Changes + +- Updated dependencies [39c0234] + - @cleverbrush/schema@5.1.0 + ## 5.0.0 ### Major Changes - d916566: Make Framework query builders immutable and infer row schemas automatically. - + Retain returned query builders, return synchronous builders from scopes and grouped predicates, and supply an explicit Framework object output schema for opaque raw SELECTs. Ordinary, aliased, polymorphic and ORM queries expose their row schemas directly. Projections replace scalar selections, and projected/aggregate/raw queries cannot perform entity writes. Reads and write-returning rows consistently preserve exact decimal/bigint strings, Date objects and SQL nulls. - + All published Framework packages advance together to the next major version. Tracked entity objects remain mutable. - + ### Migrating from v4.x to v5 - + Remove `withRowSchema()` calls and retain each configured query instead of relying on mutation. Replace raw base-query overloads with explicit output contracts. See `libs/knex-schema/MIGRATION-v5.md` for the complete migration guide. + - c5b4dbc: Require Node.js 24+ consistently across all published packages. Correct the root and all published-package license files to BSD-3-Clause, matching package metadata and documentation, and verify license consistency in source and npm tarballs. See docs/MIGRATION-v5.md for migration guidance. - + Harden JWT key/algorithm and claim validation, cookie parsing/serialization, and request-body lifecycle handling. Require explicit authorization scope for bounded server idempotency; coalesce concurrent retries and capture full response bodies. Bound response caching and bypass private, no-store and cookie-setting responses. - + Preserve DI scope validation through factories and propagate registered optional-service failures. Fix batch response status/header capture, timeout abort-listener cleanup, concurrent deduplication response cloning, CLI database cleanup on validation/production-guard failures, and the missing client idempotency JavaScript export. Update security-sensitive dependencies and ensure OpenTelemetry disable flags override SDK defaults. - + Add regression tests, package-consumer smoke checks, package-level unit coverage floors, migration/security documentation and release validation gates. ### Minor Changes - e43b72f: Add `parameter('name')` for callable PostgreSQL SELECT templates with schema-inferred positional arguments. Compile SQL, binding slots and decoding once on first invocation or `.toSQL(...)`; reuse them with independent values on later calls. `.query(...)` returns an ordinary composable bound reader. - + Support repeated names, grouped filters, fixed membership/range slots, alias joins, relation and STI/CTI customizers, and caller-owned transactions. Preserve storage types, null comparison semantics, result schemas, property navigation, and ORM identity tracking. Reject unsupported placeholder positions and unbound terminals or writes before execution. + - 6d3aecf: Add typed flat joined projections, aggregate expressions and scalar helpers with optional output schemas, and composite keyset pagination. Preserve parent ordering during eager loading and infer related-query customization types. @@ -35,27 +44,29 @@ - cb5d622: Add immutable connection-independent query definitions with `query(Schema)`. Define typed reads once and supply a Knex connection or transaction through `definition(knex, ...values)`, `.query(knex, ...values)` or `.toSQL(knex, ...values)`. - + Preserve inferred parameters, projections, relation/variant schemas and existing connection-first APIs. Capture selectors/scopes/customizers once, compile SELECTs lazily per definition and actual Knex instance, and bind ordinary readers before native SQL composition, pagination or supported writes. Include runtime, declaration and PostgreSQL integration coverage and multi-file usage guidance. + - a90a491: Add opt-in immutable, detached PostgreSQL reads with projection-aware runtime schemas, precise decimal/bigint decoding, nested relation graphs and explicit STI/CTI branch schemas. Reuse result schemas directly in separately defined application mappings without duplicating projection schemas. - + Add `getSyncMapper()` with synchronous eligibility inferred through the existing `configure()` API, completeness checks, nested mapping propagation and runtime thenable guards. Existing queries and asynchronous mapping behavior are unchanged. - + Add application-agnostic typed metadata extension methods that retain metadata through immutable chains. Use these in database extensions without modifying global schema prototypes. - + Preserve typed function-schema compatibility in dependency injection when a function declares its return schema. + - 81c2de4: Add shape-preserving grouped AND/OR predicates, captured IN/EXISTS subqueries, bound raw predicates and ordering, and typed SQL column references to ordinary and aliased schema-aware readers. These capabilities also work in ordinary ORM @@ -67,7 +78,7 @@ and part limits, reject truncated or duplicate singleton uploads, and support file-only endpoints. Existing options-only uploads retain their single-file shape and explicit MIME rejection reporting. - + Add lossless JSONB object reads and writes using native object schemas with `.acceptUnknownProps().jsonb()`. Preserve nested extension data through returning rows and projections, validate JSON extensions in the database layer, align @@ -81,16 +92,17 @@ and tracked polymorphic saves, for single-table and class-table inheritance. Add `ofVariant(key).restore()` and `hardDelete()`; CTI soft deletion retains the child row, while permanent deletion removes both rows atomically. - + **Migration:** Variant `delete()` now respects the base schema's `.softDelete()`. Use `hardDelete()` for physical removal, and `withDeleted()` to include hidden rows. Review lifecycle hooks that now run, and remove identity/discriminator/join keys from update patches. This change is part of the coordinated v5 major release. - + Capture mutation targets inside the write transaction, preserve query restrictions and transaction bindings, and use savepoints for caller-owned transactions. Fix base/variant column mapping and visibility of extension-managed deletion columns; retain exact numeric keys and tracked optimistic-concurrency/rollback semantics. + - 6d7e982: Apply and generate column default changes without dropping, retyping or changing the nullability of the existing column. Removing a default executes DROP DEFAULT; setting one executes SET DEFAULT with safely quoted values (including question diff --git a/libs/knex-schema/package.json b/libs/knex-schema/package.json index 2219eb4f..f5642d91 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": "^5.0.0" + "@cleverbrush/schema": "^5.1.0" }, "peerDependencies": { "knex": ">=3.1.0" @@ -55,5 +55,5 @@ }, "type": "module", "types": "./dist/index.d.ts", - "version": "5.0.0" + "version": "5.1.0" } diff --git a/libs/log/CHANGELOG.md b/libs/log/CHANGELOG.md index f6c4c7e7..93533f3e 100644 --- a/libs/log/CHANGELOG.md +++ b/libs/log/CHANGELOG.md @@ -1,24 +1,33 @@ # @cleverbrush/log +## 5.1.0 + +### Patch Changes + +- Updated dependencies [39c0234] + - @cleverbrush/schema@5.1.0 + - @cleverbrush/async@5.1.0 + ## 5.0.0 ### Major Changes - d916566: Make Framework query builders immutable and infer row schemas automatically. - + Retain returned query builders, return synchronous builders from scopes and grouped predicates, and supply an explicit Framework object output schema for opaque raw SELECTs. Ordinary, aliased, polymorphic and ORM queries expose their row schemas directly. Projections replace scalar selections, and projected/aggregate/raw queries cannot perform entity writes. Reads and write-returning rows consistently preserve exact decimal/bigint strings, Date objects and SQL nulls. - + All published Framework packages advance together to the next major version. Tracked entity objects remain mutable. - + ### Migrating from v4.x to v5 - + Remove `withRowSchema()` calls and retain each configured query instead of relying on mutation. Replace raw base-query overloads with explicit output contracts. See `libs/knex-schema/MIGRATION-v5.md` for the complete migration guide. + - c5b4dbc: Require Node.js 24+ consistently across all published packages. Correct the root and all published-package license files to BSD-3-Clause, matching package metadata and documentation, and verify license consistency in source and npm tarballs. See docs/MIGRATION-v5.md for migration guidance. - + Harden JWT key/algorithm and claim validation, cookie parsing/serialization, and request-body lifecycle handling. Require explicit authorization scope for bounded server idempotency; coalesce concurrent retries and capture full response bodies. Bound response caching and bypass private, no-store and cookie-setting responses. - + Preserve DI scope validation through factories and propagate registered optional-service failures. Fix batch response status/header capture, timeout abort-listener cleanup, concurrent deduplication response cloning, CLI database cleanup on validation/production-guard failures, and the missing client idempotency JavaScript export. Update security-sensitive dependencies and ensure OpenTelemetry disable flags override SDK defaults. - + Add regression tests, package-consumer smoke checks, package-level unit coverage floors, migration/security documentation and release validation gates. ### Patch Changes diff --git a/libs/log/package.json b/libs/log/package.json index c2f5f741..23216b05 100644 --- a/libs/log/package.json +++ b/libs/log/package.json @@ -44,8 +44,8 @@ "clean": "rm -rf dist tsconfig.tsbuildinfo" }, "dependencies": { - "@cleverbrush/schema": "^5.0.0", - "@cleverbrush/async": "^5.0.0" + "@cleverbrush/schema": "^5.1.0", + "@cleverbrush/async": "^5.1.0" }, "peerDependencies": { "@cleverbrush/di": "^5.0.0", @@ -71,5 +71,5 @@ }, "type": "module", "types": "./dist/index.d.ts", - "version": "5.0.0" + "version": "5.1.0" } diff --git a/libs/mapper/CHANGELOG.md b/libs/mapper/CHANGELOG.md index 0d7090e1..e399425d 100644 --- a/libs/mapper/CHANGELOG.md +++ b/libs/mapper/CHANGELOG.md @@ -1,24 +1,32 @@ # @cleverbrush/mapper +## 5.1.0 + +### Patch Changes + +- Updated dependencies [39c0234] + - @cleverbrush/schema@5.1.0 + ## 5.0.0 ### Major Changes - d916566: Make Framework query builders immutable and infer row schemas automatically. - + Retain returned query builders, return synchronous builders from scopes and grouped predicates, and supply an explicit Framework object output schema for opaque raw SELECTs. Ordinary, aliased, polymorphic and ORM queries expose their row schemas directly. Projections replace scalar selections, and projected/aggregate/raw queries cannot perform entity writes. Reads and write-returning rows consistently preserve exact decimal/bigint strings, Date objects and SQL nulls. - + All published Framework packages advance together to the next major version. Tracked entity objects remain mutable. - + ### Migrating from v4.x to v5 - + Remove `withRowSchema()` calls and retain each configured query instead of relying on mutation. Replace raw base-query overloads with explicit output contracts. See `libs/knex-schema/MIGRATION-v5.md` for the complete migration guide. + - c5b4dbc: Require Node.js 24+ consistently across all published packages. Correct the root and all published-package license files to BSD-3-Clause, matching package metadata and documentation, and verify license consistency in source and npm tarballs. See docs/MIGRATION-v5.md for migration guidance. - + Harden JWT key/algorithm and claim validation, cookie parsing/serialization, and request-body lifecycle handling. Require explicit authorization scope for bounded server idempotency; coalesce concurrent retries and capture full response bodies. Bound response caching and bypass private, no-store and cookie-setting responses. - + Preserve DI scope validation through factories and propagate registered optional-service failures. Fix batch response status/header capture, timeout abort-listener cleanup, concurrent deduplication response cloning, CLI database cleanup on validation/production-guard failures, and the missing client idempotency JavaScript export. Update security-sensitive dependencies and ensure OpenTelemetry disable flags override SDK defaults. - + Add regression tests, package-consumer smoke checks, package-level unit coverage floors, migration/security documentation and release validation gates. ### Minor Changes @@ -27,15 +35,15 @@ schemas, precise decimal/bigint decoding, nested relation graphs and explicit STI/CTI branch schemas. Reuse result schemas directly in separately defined application mappings without duplicating projection schemas. - + Add `getSyncMapper()` with synchronous eligibility inferred through the existing `configure()` API, completeness checks, nested mapping propagation and runtime thenable guards. Existing queries and asynchronous mapping behavior are unchanged. - + Add application-agnostic typed metadata extension methods that retain metadata through immutable chains. Use these in database extensions without modifying global schema prototypes. - + Preserve typed function-schema compatibility in dependency injection when a function declares its return schema. diff --git a/libs/mapper/package.json b/libs/mapper/package.json index 87705ba7..1c931714 100644 --- a/libs/mapper/package.json +++ b/libs/mapper/package.json @@ -5,7 +5,7 @@ "email": "andrew_zol@cleverbrush.com" }, "dependencies": { - "@cleverbrush/schema": "^5.0.0" + "@cleverbrush/schema": "^5.1.0" }, "description": "Type-safe, schema-driven object mapper for @cleverbrush/schema — compile-time completeness, selector-based field mapping, auto-mapping", "files": [ @@ -45,5 +45,5 @@ }, "type": "module", "types": "./dist/index.d.ts", - "version": "5.0.0" + "version": "5.1.0" } diff --git a/libs/orm-cli/CHANGELOG.md b/libs/orm-cli/CHANGELOG.md index de3264b5..7f0cf5d6 100644 --- a/libs/orm-cli/CHANGELOG.md +++ b/libs/orm-cli/CHANGELOG.md @@ -1,24 +1,31 @@ # @cleverbrush/orm-cli +## 5.1.0 + +### Patch Changes + +- @cleverbrush/knex-schema@5.1.0 + ## 5.0.0 ### Major Changes - d916566: Make Framework query builders immutable and infer row schemas automatically. - + Retain returned query builders, return synchronous builders from scopes and grouped predicates, and supply an explicit Framework object output schema for opaque raw SELECTs. Ordinary, aliased, polymorphic and ORM queries expose their row schemas directly. Projections replace scalar selections, and projected/aggregate/raw queries cannot perform entity writes. Reads and write-returning rows consistently preserve exact decimal/bigint strings, Date objects and SQL nulls. - + All published Framework packages advance together to the next major version. Tracked entity objects remain mutable. - + ### Migrating from v4.x to v5 - + Remove `withRowSchema()` calls and retain each configured query instead of relying on mutation. Replace raw base-query overloads with explicit output contracts. See `libs/knex-schema/MIGRATION-v5.md` for the complete migration guide. + - c5b4dbc: Require Node.js 24+ consistently across all published packages. Correct the root and all published-package license files to BSD-3-Clause, matching package metadata and documentation, and verify license consistency in source and npm tarballs. See docs/MIGRATION-v5.md for migration guidance. - + Harden JWT key/algorithm and claim validation, cookie parsing/serialization, and request-body lifecycle handling. Require explicit authorization scope for bounded server idempotency; coalesce concurrent retries and capture full response bodies. Bound response caching and bypass private, no-store and cookie-setting responses. - + Preserve DI scope validation through factories and propagate registered optional-service failures. Fix batch response status/header capture, timeout abort-listener cleanup, concurrent deduplication response cloning, CLI database cleanup on validation/production-guard failures, and the missing client idempotency JavaScript export. Update security-sensitive dependencies and ensure OpenTelemetry disable flags override SDK defaults. - + Add regression tests, package-consumer smoke checks, package-level unit coverage floors, migration/security documentation and release validation gates. ### Patch Changes diff --git a/libs/orm-cli/package.json b/libs/orm-cli/package.json index aaeb262f..82a8abbc 100644 --- a/libs/orm-cli/package.json +++ b/libs/orm-cli/package.json @@ -51,5 +51,5 @@ }, "type": "module", "types": "./dist/index.d.ts", - "version": "5.0.0" + "version": "5.1.0" } diff --git a/libs/orm/CHANGELOG.md b/libs/orm/CHANGELOG.md index 35ee06e8..aa859f47 100644 --- a/libs/orm/CHANGELOG.md +++ b/libs/orm/CHANGELOG.md @@ -1,45 +1,64 @@ # @cleverbrush/orm +## 5.1.0 + +### Minor Changes + +- 39c0234: Add typed endpoint pathname construction and matching, shared with client URL generation and server routing. Route parameters are validated and encoded as individual components. + + Add optional PostgreSQL advisory locks to ORM transactions, acquired before callbacks and released with their transaction. + + Reject non-object inputs to open object schemas with inspectable validation errors, including nested arrays, instead of throwing descriptor errors. + +### Patch Changes + +- Updated dependencies [39c0234] + - @cleverbrush/schema@5.1.0 + - @cleverbrush/knex-schema@5.1.0 + ## 5.0.0 ### Major Changes - d916566: Make Framework query builders immutable and infer row schemas automatically. - + Retain returned query builders, return synchronous builders from scopes and grouped predicates, and supply an explicit Framework object output schema for opaque raw SELECTs. Ordinary, aliased, polymorphic and ORM queries expose their row schemas directly. Projections replace scalar selections, and projected/aggregate/raw queries cannot perform entity writes. Reads and write-returning rows consistently preserve exact decimal/bigint strings, Date objects and SQL nulls. - + All published Framework packages advance together to the next major version. Tracked entity objects remain mutable. - + ### Migrating from v4.x to v5 - + Remove `withRowSchema()` calls and retain each configured query instead of relying on mutation. Replace raw base-query overloads with explicit output contracts. See `libs/knex-schema/MIGRATION-v5.md` for the complete migration guide. + - d31323a: Honor hooks, timestamps and base-schema soft deletion in explicit variant writes and tracked polymorphic saves, for single-table and class-table inheritance. Add `ofVariant(key).restore()` and `hardDelete()`; CTI soft deletion retains the child row, while permanent deletion removes both rows atomically. - + **Migration:** Variant `delete()` now respects the base schema's `.softDelete()`. Use `hardDelete()` for physical removal, and `withDeleted()` to include hidden rows. Review lifecycle hooks that now run, and remove identity/discriminator/join keys from update patches. This change is part of the coordinated v5 major release. - + Capture mutation targets inside the write transaction, preserve query restrictions and transaction bindings, and use savepoints for caller-owned transactions. Fix base/variant column mapping and visibility of extension-managed deletion columns; retain exact numeric keys and tracked optimistic-concurrency/rollback semantics. + - c5b4dbc: Require Node.js 24+ consistently across all published packages. Correct the root and all published-package license files to BSD-3-Clause, matching package metadata and documentation, and verify license consistency in source and npm tarballs. See docs/MIGRATION-v5.md for migration guidance. - + Harden JWT key/algorithm and claim validation, cookie parsing/serialization, and request-body lifecycle handling. Require explicit authorization scope for bounded server idempotency; coalesce concurrent retries and capture full response bodies. Bound response caching and bypass private, no-store and cookie-setting responses. - + Preserve DI scope validation through factories and propagate registered optional-service failures. Fix batch response status/header capture, timeout abort-listener cleanup, concurrent deduplication response cloning, CLI database cleanup on validation/production-guard failures, and the missing client idempotency JavaScript export. Update security-sensitive dependencies and ensure OpenTelemetry disable flags override SDK defaults. - + Add regression tests, package-consumer smoke checks, package-level unit coverage floors, migration/security documentation and release validation gates. ### Minor Changes - e43b72f: Add `parameter('name')` for callable PostgreSQL SELECT templates with schema-inferred positional arguments. Compile SQL, binding slots and decoding once on first invocation or `.toSQL(...)`; reuse them with independent values on later calls. `.query(...)` returns an ordinary composable bound reader. - + Support repeated names, grouped filters, fixed membership/range slots, alias joins, relation and STI/CTI customizers, and caller-owned transactions. Preserve storage types, null comparison semantics, result schemas, property navigation, and ORM identity tracking. Reject unsupported placeholder positions and unbound terminals or writes before execution. + - 6d3aecf: Add typed flat joined projections, aggregate expressions and scalar helpers with optional output schemas, and composite keyset pagination. Preserve parent ordering during eager loading and infer related-query customization types. @@ -49,33 +68,35 @@ - cb5d622: Add immutable connection-independent query definitions with `query(Schema)`. Define typed reads once and supply a Knex connection or transaction through `definition(knex, ...values)`, `.query(knex, ...values)` or `.toSQL(knex, ...values)`. - + Preserve inferred parameters, projections, relation/variant schemas and existing connection-first APIs. Capture selectors/scopes/customizers once, compile SELECTs lazily per definition and actual Knex instance, and bind ordinary readers before native SQL composition, pagination or supported writes. Include runtime, declaration and PostgreSQL integration coverage and multi-file usage guidance. + - a90a491: Add opt-in immutable, detached PostgreSQL reads with projection-aware runtime schemas, precise decimal/bigint decoding, nested relation graphs and explicit STI/CTI branch schemas. Reuse result schemas directly in separately defined application mappings without duplicating projection schemas. - + Add `getSyncMapper()` with synchronous eligibility inferred through the existing `configure()` API, completeness checks, nested mapping propagation and runtime thenable guards. Existing queries and asynchronous mapping behavior are unchanged. - + Add application-agnostic typed metadata extension methods that retain metadata through immutable chains. Use these in database extensions without modifying global schema prototypes. - + Preserve typed function-schema compatibility in dependency injection when a function declares its return schema. + - e788a0d: Add schema-based single and multiple file upload contracts, typed multipart client serialization, and matching OpenAPI schemas. Enforce multipart body, file, field, and part limits, reject truncated or duplicate singleton uploads, and support file-only endpoints. Existing options-only uploads retain their single-file shape and explicit MIME rejection reporting. - + Add lossless JSONB object reads and writes using native object schemas with `.acceptUnknownProps().jsonb()`. Preserve nested extension data through returning rows and projections, validate JSON extensions in the database layer, align diff --git a/libs/orm/package.json b/libs/orm/package.json index 99c1d53a..08f89ed0 100644 --- a/libs/orm/package.json +++ b/libs/orm/package.json @@ -5,8 +5,8 @@ "email": "andrew_zol@cleverbrush.com" }, "dependencies": { - "@cleverbrush/schema": "^5.0.0", - "@cleverbrush/knex-schema": "^5.0.0" + "@cleverbrush/schema": "^5.1.0", + "@cleverbrush/knex-schema": "^5.1.0" }, "peerDependencies": { "knex": ">=3.1.0" @@ -56,5 +56,5 @@ }, "type": "module", "types": "./dist/index.d.ts", - "version": "5.0.0" + "version": "5.1.0" } diff --git a/libs/otel/CHANGELOG.md b/libs/otel/CHANGELOG.md index e3c3b997..28be94f8 100644 --- a/libs/otel/CHANGELOG.md +++ b/libs/otel/CHANGELOG.md @@ -1,24 +1,27 @@ # @cleverbrush/otel +## 5.1.0 + ## 5.0.0 ### Major Changes - d916566: Make Framework query builders immutable and infer row schemas automatically. - + Retain returned query builders, return synchronous builders from scopes and grouped predicates, and supply an explicit Framework object output schema for opaque raw SELECTs. Ordinary, aliased, polymorphic and ORM queries expose their row schemas directly. Projections replace scalar selections, and projected/aggregate/raw queries cannot perform entity writes. Reads and write-returning rows consistently preserve exact decimal/bigint strings, Date objects and SQL nulls. - + All published Framework packages advance together to the next major version. Tracked entity objects remain mutable. - + ### Migrating from v4.x to v5 - + Remove `withRowSchema()` calls and retain each configured query instead of relying on mutation. Replace raw base-query overloads with explicit output contracts. See `libs/knex-schema/MIGRATION-v5.md` for the complete migration guide. + - c5b4dbc: Require Node.js 24+ consistently across all published packages. Correct the root and all published-package license files to BSD-3-Clause, matching package metadata and documentation, and verify license consistency in source and npm tarballs. See docs/MIGRATION-v5.md for migration guidance. - + Harden JWT key/algorithm and claim validation, cookie parsing/serialization, and request-body lifecycle handling. Require explicit authorization scope for bounded server idempotency; coalesce concurrent retries and capture full response bodies. Bound response caching and bypass private, no-store and cookie-setting responses. - + Preserve DI scope validation through factories and propagate registered optional-service failures. Fix batch response status/header capture, timeout abort-listener cleanup, concurrent deduplication response cloning, CLI database cleanup on validation/production-guard failures, and the missing client idempotency JavaScript export. Update security-sensitive dependencies and ensure OpenTelemetry disable flags override SDK defaults. - + Add regression tests, package-consumer smoke checks, package-level unit coverage floors, migration/security documentation and release validation gates. ### Patch Changes diff --git a/libs/otel/package.json b/libs/otel/package.json index 0f7dd83b..b21ca411 100644 --- a/libs/otel/package.json +++ b/libs/otel/package.json @@ -110,5 +110,5 @@ }, "type": "module", "types": "./dist/index.d.ts", - "version": "5.0.0" + "version": "5.1.0" } diff --git a/libs/react-form/CHANGELOG.md b/libs/react-form/CHANGELOG.md index 3355b1c9..603abaf3 100644 --- a/libs/react-form/CHANGELOG.md +++ b/libs/react-form/CHANGELOG.md @@ -1,24 +1,42 @@ # @cleverbrush/react-form +## 5.1.0 + +### Minor Changes + +- 0f9d63e: Add opt-in immediate blur validation that touches only the blurred field, and an + awaitable invalid-submission callback with existing duplicate and stale-result + protection. Opt-in validation-rule refresh retains edited values and field state + while adopting current bounds/messages and suppressing stale callbacks. Existing blur and submission defaults remain unchanged. + +### Patch Changes + +- Updated dependencies [9207eff] +- Updated dependencies [ec87c8f] +- Updated dependencies [39c0234] + - @cleverbrush/deep@5.1.0 + - @cleverbrush/schema@5.1.0 + ## 5.0.0 ### Major Changes - d916566: Make Framework query builders immutable and infer row schemas automatically. - + Retain returned query builders, return synchronous builders from scopes and grouped predicates, and supply an explicit Framework object output schema for opaque raw SELECTs. Ordinary, aliased, polymorphic and ORM queries expose their row schemas directly. Projections replace scalar selections, and projected/aggregate/raw queries cannot perform entity writes. Reads and write-returning rows consistently preserve exact decimal/bigint strings, Date objects and SQL nulls. - + All published Framework packages advance together to the next major version. Tracked entity objects remain mutable. - + ### Migrating from v4.x to v5 - + Remove `withRowSchema()` calls and retain each configured query instead of relying on mutation. Replace raw base-query overloads with explicit output contracts. See `libs/knex-schema/MIGRATION-v5.md` for the complete migration guide. + - c5b4dbc: Require Node.js 24+ consistently across all published packages. Correct the root and all published-package license files to BSD-3-Clause, matching package metadata and documentation, and verify license consistency in source and npm tarballs. See docs/MIGRATION-v5.md for migration guidance. - + Harden JWT key/algorithm and claim validation, cookie parsing/serialization, and request-body lifecycle handling. Require explicit authorization scope for bounded server idempotency; coalesce concurrent retries and capture full response bodies. Bound response caching and bypass private, no-store and cookie-setting responses. - + Preserve DI scope validation through factories and propagate registered optional-service failures. Fix batch response status/header capture, timeout abort-listener cleanup, concurrent deduplication response cloning, CLI database cleanup on validation/production-guard failures, and the missing client idempotency JavaScript export. Update security-sensitive dependencies and ensure OpenTelemetry disable flags override SDK defaults. - + Add regression tests, package-consumer smoke checks, package-level unit coverage floors, migration/security documentation and release validation gates. ### Minor Changes diff --git a/libs/react-form/package.json b/libs/react-form/package.json index 363c7279..76bc893d 100644 --- a/libs/react-form/package.json +++ b/libs/react-form/package.json @@ -5,8 +5,8 @@ "email": "andrew_zol@cleverbrush.com" }, "dependencies": { - "@cleverbrush/deep": "^5.0.0", - "@cleverbrush/schema": "^5.0.0" + "@cleverbrush/deep": "^5.1.0", + "@cleverbrush/schema": "^5.1.0" }, "devDependencies": { "@types/react": "^19.0.0", @@ -51,5 +51,5 @@ }, "type": "module", "types": "./dist/index.d.ts", - "version": "5.0.0" + "version": "5.1.0" } diff --git a/libs/scheduler-postgres/CHANGELOG.md b/libs/scheduler-postgres/CHANGELOG.md index f91b5f97..b84eeb4a 100644 --- a/libs/scheduler-postgres/CHANGELOG.md +++ b/libs/scheduler-postgres/CHANGELOG.md @@ -1,5 +1,15 @@ # @cleverbrush/scheduler-postgres +## 5.1.0 + +### Patch Changes + +- Updated dependencies [39c0234] + - @cleverbrush/orm@5.1.0 + - @cleverbrush/schema@5.1.0 + - @cleverbrush/scheduler@5.1.0 + - @cleverbrush/knex-schema@5.1.0 + ## 5.0.0 ### Major Changes @@ -8,12 +18,12 @@ typed separate handlers, durable ordered progress and fenced worker leases. Add an independently installed PostgreSQL adapter using Framework ORM and knex-schema, explicit migrations, transactional enqueue and restart recovery. - + Retries are opt-in and rerun whole handlers. Calendar triggers use explicit UTC or IANA zones with persisted cursors and missed/overlap policies. See the scheduler v4.x-to-v5 migration guide for the breaking API and rollout steps. The adapter joins the fixed Framework release group. - + Retain schema-driven minute/day/week/month/year definitions and their discriminated Schedule type, exposing individual schemas and the Schemas facade. Normalize recurrence defaults, dates and weekday order before fingerprinting; @@ -22,17 +32,18 @@ while rejecting ambiguous dual spelling. Name the explicit persistence option storageRepository. Derive PostgreSQL row and entity types from schema definitions without parallel hand-written row types. - + Use native Date/Intl calendar calculations without an additional date-time runtime dependency. Preserve DST-gap skipping and earlier-fold selection, including non-hour transitions and skipped calendar dates, independently of the host time zone. Bound minute schedules to the representable Date range. + - c5b4dbc: Require Node.js 24+ consistently across all published packages. Correct the root and all published-package license files to BSD-3-Clause, matching package metadata and documentation, and verify license consistency in source and npm tarballs. See docs/MIGRATION-v5.md for migration guidance. - + Harden JWT key/algorithm and claim validation, cookie parsing/serialization, and request-body lifecycle handling. Require explicit authorization scope for bounded server idempotency; coalesce concurrent retries and capture full response bodies. Bound response caching and bypass private, no-store and cookie-setting responses. - + Preserve DI scope validation through factories and propagate registered optional-service failures. Fix batch response status/header capture, timeout abort-listener cleanup, concurrent deduplication response cloning, CLI database cleanup on validation/production-guard failures, and the missing client idempotency JavaScript export. Update security-sensitive dependencies and ensure OpenTelemetry disable flags override SDK defaults. - + Add regression tests, package-consumer smoke checks, package-level unit coverage floors, migration/security documentation and release validation gates. ### Patch Changes diff --git a/libs/scheduler-postgres/package.json b/libs/scheduler-postgres/package.json index 9365d854..4d4cca7f 100644 --- a/libs/scheduler-postgres/package.json +++ b/libs/scheduler-postgres/package.json @@ -3,7 +3,7 @@ "engines": { "node": ">=24" }, - "version": "5.0.0", + "version": "5.1.0", "description": "Transactional PostgreSQL repository for the Cleverbrush durable scheduler", "type": "module", "sideEffects": false, @@ -20,10 +20,10 @@ } }, "dependencies": { - "@cleverbrush/scheduler": "^5.0.0", - "@cleverbrush/schema": "^5.0.0", - "@cleverbrush/orm": "^5.0.0", - "@cleverbrush/knex-schema": "^5.0.0" + "@cleverbrush/scheduler": "^5.1.0", + "@cleverbrush/schema": "^5.1.0", + "@cleverbrush/orm": "^5.1.0", + "@cleverbrush/knex-schema": "^5.1.0" }, "peerDependencies": { "knex": ">=3.1.0", diff --git a/libs/scheduler/CHANGELOG.md b/libs/scheduler/CHANGELOG.md index 5d309ee8..abb563fa 100644 --- a/libs/scheduler/CHANGELOG.md +++ b/libs/scheduler/CHANGELOG.md @@ -1,5 +1,12 @@ # @cleverbrush/scheduler +## 5.1.0 + +### Patch Changes + +- Updated dependencies [39c0234] + - @cleverbrush/schema@5.1.0 + ## 5.0.0 ### Major Changes @@ -8,12 +15,12 @@ typed separate handlers, durable ordered progress and fenced worker leases. Add an independently installed PostgreSQL adapter using Framework ORM and knex-schema, explicit migrations, transactional enqueue and restart recovery. - + Retries are opt-in and rerun whole handlers. Calendar triggers use explicit UTC or IANA zones with persisted cursors and missed/overlap policies. See the scheduler v4.x-to-v5 migration guide for the breaking API and rollout steps. The adapter joins the fixed Framework release group. - + Retain schema-driven minute/day/week/month/year definitions and their discriminated Schedule type, exposing individual schemas and the Schemas facade. Normalize recurrence defaults, dates and weekday order before fingerprinting; @@ -22,26 +29,28 @@ while rejecting ambiguous dual spelling. Name the explicit persistence option storageRepository. Derive PostgreSQL row and entity types from schema definitions without parallel hand-written row types. - + Use native Date/Intl calendar calculations without an additional date-time runtime dependency. Preserve DST-gap skipping and earlier-fold selection, including non-hour transitions and skipped calendar dates, independently of the host time zone. Bound minute schedules to the representable Date range. + - d916566: Make Framework query builders immutable and infer row schemas automatically. - + Retain returned query builders, return synchronous builders from scopes and grouped predicates, and supply an explicit Framework object output schema for opaque raw SELECTs. Ordinary, aliased, polymorphic and ORM queries expose their row schemas directly. Projections replace scalar selections, and projected/aggregate/raw queries cannot perform entity writes. Reads and write-returning rows consistently preserve exact decimal/bigint strings, Date objects and SQL nulls. - + All published Framework packages advance together to the next major version. Tracked entity objects remain mutable. - + ### Migrating from v4.x to v5 - + Remove `withRowSchema()` calls and retain each configured query instead of relying on mutation. Replace raw base-query overloads with explicit output contracts. See `libs/knex-schema/MIGRATION-v5.md` for the complete migration guide. + - c5b4dbc: Require Node.js 24+ consistently across all published packages. Correct the root and all published-package license files to BSD-3-Clause, matching package metadata and documentation, and verify license consistency in source and npm tarballs. See docs/MIGRATION-v5.md for migration guidance. - + Harden JWT key/algorithm and claim validation, cookie parsing/serialization, and request-body lifecycle handling. Require explicit authorization scope for bounded server idempotency; coalesce concurrent retries and capture full response bodies. Bound response caching and bypass private, no-store and cookie-setting responses. - + Preserve DI scope validation through factories and propagate registered optional-service failures. Fix batch response status/header capture, timeout abort-listener cleanup, concurrent deduplication response cloning, CLI database cleanup on validation/production-guard failures, and the missing client idempotency JavaScript export. Update security-sensitive dependencies and ensure OpenTelemetry disable flags override SDK defaults. - + Add regression tests, package-consumer smoke checks, package-level unit coverage floors, migration/security documentation and release validation gates. ### Patch Changes diff --git a/libs/scheduler/package.json b/libs/scheduler/package.json index 13d80659..28d63c2c 100644 --- a/libs/scheduler/package.json +++ b/libs/scheduler/package.json @@ -5,7 +5,7 @@ "email": "andrew_zol@cleverbrush.com" }, "dependencies": { - "@cleverbrush/schema": "^5.0.0" + "@cleverbrush/schema": "^5.1.0" }, "devDependencies": { "@types/node": "^25.4.0" @@ -46,5 +46,5 @@ }, "type": "module", "types": "./dist/index.d.ts", - "version": "5.0.0" + "version": "5.1.0" } diff --git a/libs/schema-json/CHANGELOG.md b/libs/schema-json/CHANGELOG.md index 67335c89..cc190ffd 100644 --- a/libs/schema-json/CHANGELOG.md +++ b/libs/schema-json/CHANGELOG.md @@ -1,24 +1,27 @@ # @cleverbrush/schema-json +## 5.1.0 + ## 5.0.0 ### Major Changes - d916566: Make Framework query builders immutable and infer row schemas automatically. - + Retain returned query builders, return synchronous builders from scopes and grouped predicates, and supply an explicit Framework object output schema for opaque raw SELECTs. Ordinary, aliased, polymorphic and ORM queries expose their row schemas directly. Projections replace scalar selections, and projected/aggregate/raw queries cannot perform entity writes. Reads and write-returning rows consistently preserve exact decimal/bigint strings, Date objects and SQL nulls. - + All published Framework packages advance together to the next major version. Tracked entity objects remain mutable. - + ### Migrating from v4.x to v5 - + Remove `withRowSchema()` calls and retain each configured query instead of relying on mutation. Replace raw base-query overloads with explicit output contracts. See `libs/knex-schema/MIGRATION-v5.md` for the complete migration guide. + - c5b4dbc: Require Node.js 24+ consistently across all published packages. Correct the root and all published-package license files to BSD-3-Clause, matching package metadata and documentation, and verify license consistency in source and npm tarballs. See docs/MIGRATION-v5.md for migration guidance. - + Harden JWT key/algorithm and claim validation, cookie parsing/serialization, and request-body lifecycle handling. Require explicit authorization scope for bounded server idempotency; coalesce concurrent retries and capture full response bodies. Bound response caching and bypass private, no-store and cookie-setting responses. - + Preserve DI scope validation through factories and propagate registered optional-service failures. Fix batch response status/header capture, timeout abort-listener cleanup, concurrent deduplication response cloning, CLI database cleanup on validation/production-guard failures, and the missing client idempotency JavaScript export. Update security-sensitive dependencies and ensure OpenTelemetry disable flags override SDK defaults. - + Add regression tests, package-consumer smoke checks, package-level unit coverage floors, migration/security documentation and release validation gates. ### Minor Changes diff --git a/libs/schema-json/package.json b/libs/schema-json/package.json index 7df8a73a..8131241e 100644 --- a/libs/schema-json/package.json +++ b/libs/schema-json/package.json @@ -47,5 +47,5 @@ }, "type": "module", "types": "./dist/index.d.ts", - "version": "5.0.0" + "version": "5.1.0" } diff --git a/libs/schema/CHANGELOG.md b/libs/schema/CHANGELOG.md index cfe2ce68..7d88e665 100644 --- a/libs/schema/CHANGELOG.md +++ b/libs/schema/CHANGELOG.md @@ -1,24 +1,35 @@ # @cleverbrush/schema +## 5.1.0 + +### Patch Changes + +- 39c0234: Add typed endpoint pathname construction and matching, shared with client URL generation and server routing. Route parameters are validated and encoded as individual components. + + Add optional PostgreSQL advisory locks to ORM transactions, acquired before callbacks and released with their transaction. + + Reject non-object inputs to open object schemas with inspectable validation errors, including nested arrays, instead of throwing descriptor errors. + ## 5.0.0 ### Major Changes - d916566: Make Framework query builders immutable and infer row schemas automatically. - + Retain returned query builders, return synchronous builders from scopes and grouped predicates, and supply an explicit Framework object output schema for opaque raw SELECTs. Ordinary, aliased, polymorphic and ORM queries expose their row schemas directly. Projections replace scalar selections, and projected/aggregate/raw queries cannot perform entity writes. Reads and write-returning rows consistently preserve exact decimal/bigint strings, Date objects and SQL nulls. - + All published Framework packages advance together to the next major version. Tracked entity objects remain mutable. - + ### Migrating from v4.x to v5 - + Remove `withRowSchema()` calls and retain each configured query instead of relying on mutation. Replace raw base-query overloads with explicit output contracts. See `libs/knex-schema/MIGRATION-v5.md` for the complete migration guide. + - c5b4dbc: Require Node.js 24+ consistently across all published packages. Correct the root and all published-package license files to BSD-3-Clause, matching package metadata and documentation, and verify license consistency in source and npm tarballs. See docs/MIGRATION-v5.md for migration guidance. - + Harden JWT key/algorithm and claim validation, cookie parsing/serialization, and request-body lifecycle handling. Require explicit authorization scope for bounded server idempotency; coalesce concurrent retries and capture full response bodies. Bound response caching and bypass private, no-store and cookie-setting responses. - + Preserve DI scope validation through factories and propagate registered optional-service failures. Fix batch response status/header capture, timeout abort-listener cleanup, concurrent deduplication response cloning, CLI database cleanup on validation/production-guard failures, and the missing client idempotency JavaScript export. Update security-sensitive dependencies and ensure OpenTelemetry disable flags override SDK defaults. - + Add regression tests, package-consumer smoke checks, package-level unit coverage floors, migration/security documentation and release validation gates. ### Minor Changes @@ -27,17 +38,18 @@ schemas, precise decimal/bigint decoding, nested relation graphs and explicit STI/CTI branch schemas. Reuse result schemas directly in separately defined application mappings without duplicating projection schemas. - + Add `getSyncMapper()` with synchronous eligibility inferred through the existing `configure()` API, completeness checks, nested mapping propagation and runtime thenable guards. Existing queries and asynchronous mapping behavior are unchanged. - + Add application-agnostic typed metadata extension methods that retain metadata through immutable chains. Use these in database extensions without modifying global schema prototypes. - + Preserve typed function-schema compatibility in dependency injection when a function declares its return schema. + - f9b1f56: Add optional-aware fallbacks and preprocessing, and automatic named schema references through ordinary immutable use-site modifiers, without a wrapper API. Shape, validation-rule, default, fallback and extension changes clear inherited diff --git a/libs/schema/package.json b/libs/schema/package.json index ffb895a2..913d3b6f 100644 --- a/libs/schema/package.json +++ b/libs/schema/package.json @@ -109,9 +109,9 @@ }, "type": "module", "types": "./dist/index.d.ts", - "version": "5.0.0", + "version": "5.1.0", "devDependencies": { - "@cleverbrush/deep": "^5.0.0" + "@cleverbrush/deep": "^5.1.0" }, "peerDependencies": { "@standard-schema/spec": "^1.1.0" diff --git a/libs/server-openapi/CHANGELOG.md b/libs/server-openapi/CHANGELOG.md index 393ea5b4..f3018cb5 100644 --- a/libs/server-openapi/CHANGELOG.md +++ b/libs/server-openapi/CHANGELOG.md @@ -1,24 +1,27 @@ # @cleverbrush/server-openapi +## 5.1.0 + ## 5.0.0 ### Major Changes - d916566: Make Framework query builders immutable and infer row schemas automatically. - + Retain returned query builders, return synchronous builders from scopes and grouped predicates, and supply an explicit Framework object output schema for opaque raw SELECTs. Ordinary, aliased, polymorphic and ORM queries expose their row schemas directly. Projections replace scalar selections, and projected/aggregate/raw queries cannot perform entity writes. Reads and write-returning rows consistently preserve exact decimal/bigint strings, Date objects and SQL nulls. - + All published Framework packages advance together to the next major version. Tracked entity objects remain mutable. - + ### Migrating from v4.x to v5 - + Remove `withRowSchema()` calls and retain each configured query instead of relying on mutation. Replace raw base-query overloads with explicit output contracts. See `libs/knex-schema/MIGRATION-v5.md` for the complete migration guide. + - c5b4dbc: Require Node.js 24+ consistently across all published packages. Correct the root and all published-package license files to BSD-3-Clause, matching package metadata and documentation, and verify license consistency in source and npm tarballs. See docs/MIGRATION-v5.md for migration guidance. - + Harden JWT key/algorithm and claim validation, cookie parsing/serialization, and request-body lifecycle handling. Require explicit authorization scope for bounded server idempotency; coalesce concurrent retries and capture full response bodies. Bound response caching and bypass private, no-store and cookie-setting responses. - + Preserve DI scope validation through factories and propagate registered optional-service failures. Fix batch response status/header capture, timeout abort-listener cleanup, concurrent deduplication response cloning, CLI database cleanup on validation/production-guard failures, and the missing client idempotency JavaScript export. Update security-sensitive dependencies and ensure OpenTelemetry disable flags override SDK defaults. - + Add regression tests, package-consumer smoke checks, package-level unit coverage floors, migration/security documentation and release validation gates. ### Minor Changes @@ -40,7 +43,7 @@ and part limits, reject truncated or duplicate singleton uploads, and support file-only endpoints. Existing options-only uploads retain their single-file shape and explicit MIME rejection reporting. - + Add lossless JSONB object reads and writes using native object schemas with `.acceptUnknownProps().jsonb()`. Preserve nested extension data through returning rows and projections, validate JSON extensions in the database layer, align diff --git a/libs/server-openapi/package.json b/libs/server-openapi/package.json index f9ca5242..4baefaf5 100644 --- a/libs/server-openapi/package.json +++ b/libs/server-openapi/package.json @@ -54,5 +54,5 @@ }, "type": "module", "types": "./dist/index.d.ts", - "version": "5.0.0" + "version": "5.1.0" } diff --git a/libs/server/CHANGELOG.md b/libs/server/CHANGELOG.md index a03086c3..3d9b6b7c 100644 --- a/libs/server/CHANGELOG.md +++ b/libs/server/CHANGELOG.md @@ -1,24 +1,43 @@ # @cleverbrush/server +## 5.1.0 + +### Minor Changes + +- 5d76049: Add withRequestSignal for cooperative request-disconnect, caller and deadline cancellation with deterministic lifecycle cleanup. +- 39c0234: Add typed endpoint pathname construction and matching, shared with client URL generation and server routing. Route parameters are validated and encoded as individual components. + + Add optional PostgreSQL advisory locks to ORM transactions, acquired before callbacks and released with their transaction. + + Reject non-object inputs to open object schemas with inspectable validation errors, including nested arrays, instead of throwing descriptor errors. + +### Patch Changes + +- Updated dependencies [39c0234] + - @cleverbrush/schema@5.1.0 + - @cleverbrush/auth@5.1.0 + - @cleverbrush/di@5.1.0 + ## 5.0.0 ### Major Changes - d916566: Make Framework query builders immutable and infer row schemas automatically. - + Retain returned query builders, return synchronous builders from scopes and grouped predicates, and supply an explicit Framework object output schema for opaque raw SELECTs. Ordinary, aliased, polymorphic and ORM queries expose their row schemas directly. Projections replace scalar selections, and projected/aggregate/raw queries cannot perform entity writes. Reads and write-returning rows consistently preserve exact decimal/bigint strings, Date objects and SQL nulls. - + All published Framework packages advance together to the next major version. Tracked entity objects remain mutable. - + ### Migrating from v4.x to v5 - + Remove `withRowSchema()` calls and retain each configured query instead of relying on mutation. Replace raw base-query overloads with explicit output contracts. See `libs/knex-schema/MIGRATION-v5.md` for the complete migration guide. + - c5b4dbc: Require Node.js 24+ consistently across all published packages. Correct the root and all published-package license files to BSD-3-Clause, matching package metadata and documentation, and verify license consistency in source and npm tarballs. See docs/MIGRATION-v5.md for migration guidance. - + Harden JWT key/algorithm and claim validation, cookie parsing/serialization, and request-body lifecycle handling. Require explicit authorization scope for bounded server idempotency; coalesce concurrent retries and capture full response bodies. Bound response caching and bypass private, no-store and cookie-setting responses. - + Preserve DI scope validation through factories and propagate registered optional-service failures. Fix batch response status/header capture, timeout abort-listener cleanup, concurrent deduplication response cloning, CLI database cleanup on validation/production-guard failures, and the missing client idempotency JavaScript export. Update security-sensitive dependencies and ensure OpenTelemetry disable flags override SDK defaults. - + Add regression tests, package-consumer smoke checks, package-level unit coverage floors, migration/security documentation and release validation gates. ### Minor Changes @@ -47,7 +66,7 @@ and part limits, reject truncated or duplicate singleton uploads, and support file-only endpoints. Existing options-only uploads retain their single-file shape and explicit MIME rejection reporting. - + Add lossless JSONB object reads and writes using native object schemas with `.acceptUnknownProps().jsonb()`. Preserve nested extension data through returning rows and projections, validate JSON extensions in the database layer, align diff --git a/libs/server/package.json b/libs/server/package.json index 8de24c23..1bc49a2b 100644 --- a/libs/server/package.json +++ b/libs/server/package.json @@ -5,9 +5,9 @@ "email": "andrew_zol@cleverbrush.com" }, "dependencies": { - "@cleverbrush/auth": "^5.0.0", - "@cleverbrush/di": "^5.0.0", - "@cleverbrush/schema": "^5.0.0", + "@cleverbrush/auth": "^5.1.0", + "@cleverbrush/di": "^5.1.0", + "@cleverbrush/schema": "^5.1.0", "@fastify/busboy": "^3.2.2", "ws": "^8.22.0" }, @@ -58,5 +58,5 @@ }, "type": "module", "types": "./dist/index.d.ts", - "version": "5.0.0" + "version": "5.1.0" } diff --git a/libs/storage-s3/CHANGELOG.md b/libs/storage-s3/CHANGELOG.md index c1995215..c58aa090 100644 --- a/libs/storage-s3/CHANGELOG.md +++ b/libs/storage-s3/CHANGELOG.md @@ -1,15 +1,21 @@ # @cleverbrush/storage-s3 +## 5.1.0 + +### Patch Changes + +- @cleverbrush/storage@5.1.0 + ## 5.0.0 ### Major Changes - c5b4dbc: Require Node.js 24+ consistently across all published packages. Correct the root and all published-package license files to BSD-3-Clause, matching package metadata and documentation, and verify license consistency in source and npm tarballs. See docs/MIGRATION-v5.md for migration guidance. - + Harden JWT key/algorithm and claim validation, cookie parsing/serialization, and request-body lifecycle handling. Require explicit authorization scope for bounded server idempotency; coalesce concurrent retries and capture full response bodies. Bound response caching and bypass private, no-store and cookie-setting responses. - + Preserve DI scope validation through factories and propagate registered optional-service failures. Fix batch response status/header capture, timeout abort-listener cleanup, concurrent deduplication response cloning, CLI database cleanup on validation/production-guard failures, and the missing client idempotency JavaScript export. Update security-sensitive dependencies and ensure OpenTelemetry disable flags override SDK defaults. - + Add regression tests, package-consumer smoke checks, package-level unit coverage floors, migration/security documentation and release validation gates. ### Minor Changes diff --git a/libs/storage-s3/package.json b/libs/storage-s3/package.json index 4c011eaf..c47f4632 100644 --- a/libs/storage-s3/package.json +++ b/libs/storage-s3/package.json @@ -1,6 +1,6 @@ { "name": "@cleverbrush/storage-s3", - "version": "5.0.0", + "version": "5.1.0", "description": "S3-compatible object storage for self-hosted and hosted providers", "type": "module", "sideEffects": false, @@ -27,7 +27,7 @@ "clean": "rm -rf dist tsconfig.tsbuildinfo" }, "dependencies": { - "@cleverbrush/storage": "^5.0.0", + "@cleverbrush/storage": "^5.1.0", "@aws-sdk/client-s3": "^3.1145.0", "@aws-sdk/lib-storage": "^3.1145.0" } diff --git a/libs/storage/CHANGELOG.md b/libs/storage/CHANGELOG.md index 6b80f5a4..4ff7e1ee 100644 --- a/libs/storage/CHANGELOG.md +++ b/libs/storage/CHANGELOG.md @@ -1,15 +1,17 @@ # @cleverbrush/storage +## 5.1.0 + ## 5.0.0 ### Major Changes - c5b4dbc: Require Node.js 24+ consistently across all published packages. Correct the root and all published-package license files to BSD-3-Clause, matching package metadata and documentation, and verify license consistency in source and npm tarballs. See docs/MIGRATION-v5.md for migration guidance. - + Harden JWT key/algorithm and claim validation, cookie parsing/serialization, and request-body lifecycle handling. Require explicit authorization scope for bounded server idempotency; coalesce concurrent retries and capture full response bodies. Bound response caching and bypass private, no-store and cookie-setting responses. - + Preserve DI scope validation through factories and propagate registered optional-service failures. Fix batch response status/header capture, timeout abort-listener cleanup, concurrent deduplication response cloning, CLI database cleanup on validation/production-guard failures, and the missing client idempotency JavaScript export. Update security-sensitive dependencies and ensure OpenTelemetry disable flags override SDK defaults. - + Add regression tests, package-consumer smoke checks, package-level unit coverage floors, migration/security documentation and release validation gates. ### Minor Changes diff --git a/libs/storage/package.json b/libs/storage/package.json index fa3468a9..742148b0 100644 --- a/libs/storage/package.json +++ b/libs/storage/package.json @@ -1,6 +1,6 @@ { "name": "@cleverbrush/storage", - "version": "5.0.0", + "version": "5.1.0", "description": "Provider-neutral object storage contracts for Node.js", "type": "module", "sideEffects": false, diff --git a/package-lock.json b/package-lock.json index c331d06d..dccb01b5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -136,7 +136,7 @@ }, "libs/async": { "name": "@cleverbrush/async", - "version": "4.5.0", + "version": "5.1.0", "license": "BSD-3-Clause", "devDependencies": { "@types/node": "^25.4.0" @@ -157,10 +157,10 @@ }, "libs/auth": { "name": "@cleverbrush/auth", - "version": "4.5.0", + "version": "5.1.0", "license": "BSD-3-Clause", "dependencies": { - "@cleverbrush/schema": "^4.5.0" + "@cleverbrush/schema": "^5.1.0" }, "engines": { "node": ">=24" @@ -170,7 +170,7 @@ "name": "@cleverbrush/benchmarks", "version": "2.0.2", "dependencies": { - "@cleverbrush/schema": "^4.0.0", + "@cleverbrush/schema": "^5.0.0", "joi": "^17.13.7", "yup": "^1.6.1", "zod": "^3.24.4" @@ -178,11 +178,11 @@ }, "libs/client": { "name": "@cleverbrush/client", - "version": "4.5.0", + "version": "5.1.0", "license": "BSD-3-Clause", "dependencies": { - "@cleverbrush/schema": "^4.5.0", - "@cleverbrush/server": "^4.5.0" + "@cleverbrush/schema": "^5.1.0", + "@cleverbrush/server": "^5.1.0" }, "devDependencies": { "@tanstack/react-query": "^5.75.0", @@ -209,7 +209,7 @@ }, "libs/deep": { "name": "@cleverbrush/deep", - "version": "4.5.0", + "version": "5.1.0", "license": "BSD-3-Clause", "engines": { "node": ">=24" @@ -217,10 +217,10 @@ }, "libs/di": { "name": "@cleverbrush/di", - "version": "4.5.0", + "version": "5.1.0", "license": "BSD-3-Clause", "dependencies": { - "@cleverbrush/schema": "^4.5.0" + "@cleverbrush/schema": "^5.1.0" }, "engines": { "node": ">=24" @@ -228,10 +228,10 @@ }, "libs/env": { "name": "@cleverbrush/env", - "version": "4.5.0", + "version": "5.1.0", "license": "BSD-3-Clause", "dependencies": { - "@cleverbrush/deep": "^4.5.0" + "@cleverbrush/deep": "^5.1.0" }, "devDependencies": { "@cleverbrush/schema": "*", @@ -241,7 +241,7 @@ "node": ">=24" }, "peerDependencies": { - "@cleverbrush/schema": "^4.0.0" + "@cleverbrush/schema": "^5.0.0" } }, "libs/env/node_modules/@types/node": { @@ -256,11 +256,11 @@ }, "libs/knex-clickhouse": { "name": "@cleverbrush/knex-clickhouse", - "version": "4.5.0", + "version": "5.1.0", "license": "BSD-3-Clause", "dependencies": { - "@cleverbrush/async": "^4.5.0", - "@cleverbrush/deep": "^4.5.0", + "@cleverbrush/async": "^5.1.0", + "@cleverbrush/deep": "^5.1.0", "@clickhouse/client": "^1.18.2" }, "engines": { @@ -272,10 +272,10 @@ }, "libs/knex-schema": { "name": "@cleverbrush/knex-schema", - "version": "4.5.0", + "version": "5.1.0", "license": "BSD-3-Clause", "dependencies": { - "@cleverbrush/schema": "^4.5.0" + "@cleverbrush/schema": "^5.1.0" }, "engines": { "node": ">=24" @@ -286,11 +286,11 @@ }, "libs/log": { "name": "@cleverbrush/log", - "version": "4.5.0", + "version": "5.1.0", "license": "BSD-3-Clause", "dependencies": { - "@cleverbrush/async": "^4.5.0", - "@cleverbrush/schema": "^4.5.0" + "@cleverbrush/async": "^5.1.0", + "@cleverbrush/schema": "^5.1.0" }, "devDependencies": { "@cleverbrush/di": "*", @@ -302,9 +302,9 @@ "node": ">=24" }, "peerDependencies": { - "@cleverbrush/di": "^4.0.0", - "@cleverbrush/knex-clickhouse": "^4.0.0", - "@cleverbrush/server": "^4.0.0" + "@cleverbrush/di": "^5.0.0", + "@cleverbrush/knex-clickhouse": "^5.0.0", + "@cleverbrush/server": "^5.0.0" }, "peerDependenciesMeta": { "@cleverbrush/di": { @@ -330,10 +330,10 @@ }, "libs/mapper": { "name": "@cleverbrush/mapper", - "version": "4.5.0", + "version": "5.1.0", "license": "BSD-3-Clause", "dependencies": { - "@cleverbrush/schema": "^4.5.0" + "@cleverbrush/schema": "^5.1.0" }, "engines": { "node": ">=24" @@ -341,11 +341,11 @@ }, "libs/orm": { "name": "@cleverbrush/orm", - "version": "4.5.0", + "version": "5.1.0", "license": "BSD-3-Clause", "dependencies": { - "@cleverbrush/knex-schema": "^4.5.0", - "@cleverbrush/schema": "^4.5.0" + "@cleverbrush/knex-schema": "^5.1.0", + "@cleverbrush/schema": "^5.1.0" }, "engines": { "node": ">=24" @@ -356,7 +356,7 @@ }, "libs/orm-cli": { "name": "@cleverbrush/orm-cli", - "version": "4.5.0", + "version": "5.1.0", "license": "BSD-3-Clause", "dependencies": { "@cleverbrush/knex-schema": "*", @@ -374,7 +374,7 @@ }, "libs/otel": { "name": "@cleverbrush/otel", - "version": "4.5.0", + "version": "5.1.0", "license": "BSD-3-Clause", "dependencies": { "@opentelemetry/api": "^1.9.0", @@ -405,9 +405,9 @@ "node": ">=24" }, "peerDependencies": { - "@cleverbrush/di": "^4.0.0", - "@cleverbrush/log": "^4.0.0", - "@cleverbrush/server": "^4.0.0", + "@cleverbrush/di": "^5.0.0", + "@cleverbrush/log": "^5.0.0", + "@cleverbrush/server": "^5.0.0", "@opentelemetry/instrumentation-http": "^0.222.0", "@opentelemetry/instrumentation-runtime-node": "^0.28.0", "@opentelemetry/instrumentation-undici": "^0.25.0", @@ -449,11 +449,11 @@ }, "libs/react-form": { "name": "@cleverbrush/react-form", - "version": "4.5.0", + "version": "5.1.0", "license": "BSD-3-Clause", "dependencies": { - "@cleverbrush/deep": "^4.5.0", - "@cleverbrush/schema": "^4.5.0" + "@cleverbrush/deep": "^5.1.0", + "@cleverbrush/schema": "^5.1.0" }, "devDependencies": { "@types/react": "^19.0.0", @@ -468,10 +468,10 @@ }, "libs/scheduler": { "name": "@cleverbrush/scheduler", - "version": "4.5.0", + "version": "5.1.0", "license": "BSD-3-Clause", "dependencies": { - "@cleverbrush/schema": "^4.5.0" + "@cleverbrush/schema": "^5.1.0" }, "devDependencies": { "@types/node": "^25.4.0" @@ -482,13 +482,13 @@ }, "libs/scheduler-postgres": { "name": "@cleverbrush/scheduler-postgres", - "version": "4.4.3", + "version": "5.1.0", "license": "BSD-3-Clause", "dependencies": { - "@cleverbrush/knex-schema": "^4.4.3", - "@cleverbrush/orm": "^4.4.3", - "@cleverbrush/scheduler": "^4.4.3", - "@cleverbrush/schema": "^4.4.3" + "@cleverbrush/knex-schema": "^5.1.0", + "@cleverbrush/orm": "^5.1.0", + "@cleverbrush/scheduler": "^5.1.0", + "@cleverbrush/schema": "^5.1.0" }, "devDependencies": { "@types/node": "^25.4.0" @@ -523,10 +523,10 @@ }, "libs/schema": { "name": "@cleverbrush/schema", - "version": "4.5.0", + "version": "5.1.0", "license": "BSD-3-Clause", "devDependencies": { - "@cleverbrush/deep": "^4.5.0" + "@cleverbrush/deep": "^5.1.0" }, "engines": { "node": ">=24" @@ -537,7 +537,7 @@ }, "libs/schema-json": { "name": "@cleverbrush/schema-json", - "version": "4.5.0", + "version": "5.1.0", "license": "BSD-3-Clause", "devDependencies": { "@cleverbrush/schema": "*" @@ -546,18 +546,18 @@ "node": ">=24" }, "peerDependencies": { - "@cleverbrush/schema": "^4.0.0", + "@cleverbrush/schema": "^5.0.0", "@standard-schema/spec": "^1.1.0" } }, "libs/server": { "name": "@cleverbrush/server", - "version": "4.5.0", + "version": "5.1.0", "license": "BSD-3-Clause", "dependencies": { - "@cleverbrush/auth": "^4.5.0", - "@cleverbrush/di": "^4.5.0", - "@cleverbrush/schema": "^4.5.0", + "@cleverbrush/auth": "^5.1.0", + "@cleverbrush/di": "^5.1.0", + "@cleverbrush/schema": "^5.1.0", "@fastify/busboy": "^3.2.2", "ws": "^8.22.0" }, @@ -573,15 +573,15 @@ "name": "@cleverbrush/server-integration-tests", "version": "2.0.2", "dependencies": { - "@cleverbrush/auth": "^4.0.0", - "@cleverbrush/di": "^4.0.0", - "@cleverbrush/schema": "^4.0.0", - "@cleverbrush/server": "^4.0.0" + "@cleverbrush/auth": "^5.0.0", + "@cleverbrush/di": "^5.0.0", + "@cleverbrush/schema": "^5.0.0", + "@cleverbrush/server": "^5.0.0" } }, "libs/server-openapi": { "name": "@cleverbrush/server-openapi", - "version": "4.5.0", + "version": "5.1.0", "license": "BSD-3-Clause", "devDependencies": { "@cleverbrush/auth": "*", @@ -593,15 +593,15 @@ "node": ">=24" }, "peerDependencies": { - "@cleverbrush/auth": "^4.0.0", - "@cleverbrush/schema": "^4.0.0", - "@cleverbrush/schema-json": "^4.0.0", - "@cleverbrush/server": "^4.0.0" + "@cleverbrush/auth": "^5.0.0", + "@cleverbrush/schema": "^5.0.0", + "@cleverbrush/schema-json": "^5.0.0", + "@cleverbrush/server": "^5.0.0" } }, "libs/storage": { "name": "@cleverbrush/storage", - "version": "4.4.3", + "version": "5.1.0", "license": "BSD-3-Clause", "devDependencies": { "@types/node": "^25.4.0" @@ -612,12 +612,12 @@ }, "libs/storage-s3": { "name": "@cleverbrush/storage-s3", - "version": "4.4.3", + "version": "5.1.0", "license": "BSD-3-Clause", "dependencies": { "@aws-sdk/client-s3": "^3.1145.0", "@aws-sdk/lib-storage": "^3.1145.0", - "@cleverbrush/storage": "^4.4.3" + "@cleverbrush/storage": "^5.1.0" }, "devDependencies": { "@types/node": "^25.4.0" diff --git a/package.json b/package.json index ac7d08b2..06ba68d9 100644 --- a/package.json +++ b/package.json @@ -15,7 +15,7 @@ "build:docs-site": "cd websites/docs && npm run build && cd ../..", "clean": "turbo run clean", "watch": "tsc --build --watch tsconfig.build.json", - "docs": "typedoc && ./scripts/inject-gtm.sh websites/docs/public/api-docs/latest", + "docs": "node scripts/docs.mjs", "docs:snapshot": "./scripts/snapshot-docs.sh", "lint": "biome check ./libs ./websites/schema ./websites/docs", "typecheck:schema-site": "tsc --noEmit -p websites/schema/tsconfig.json", diff --git a/scripts/docs.mjs b/scripts/docs.mjs new file mode 100644 index 00000000..50595d21 --- /dev/null +++ b/scripts/docs.mjs @@ -0,0 +1,117 @@ +import { spawnSync } from 'node:child_process'; +import { + copyFileSync, + existsSync, + readFileSync, + readdirSync, + writeFileSync +} from 'node:fs'; +import { dirname, join, relative, sep } from 'node:path'; +import { fileURLToPath } from 'node:url'; + +const ROOT_DIR = fileURLToPath(new URL('../', import.meta.url)); +const numeric = '(?:0|[1-9]\\d*)'; +const prerelease = `(?:${numeric}|\\d*[A-Za-z-][0-9A-Za-z-]*)`; +const versionPattern = new RegExp( + `^${numeric}\\.${numeric}\\.${numeric}` + + `(?:-${prerelease}(?:\\.${prerelease})*)?` + + '(?:\\+[0-9A-Za-z-]+(?:\\.[0-9A-Za-z-]+)*)?$' +); + +function readJson(path) { + return JSON.parse(readFileSync(path, 'utf8')); +} + +export function getDocsVersion(rootDir = ROOT_DIR, override) { + const packageNames = readJson( + join(rootDir, '.changeset/config.json') + ).fixed.flat(); + if (packageNames.length === 0) { + throw new Error('No fixed release packages configured.'); + } + + const packages = new Map( + readdirSync(join(rootDir, 'libs'), { withFileTypes: true }) + .filter( + entry => + entry.isDirectory() && + existsSync( + join(rootDir, 'libs', entry.name, 'package.json') + ) + ) + .map(entry => { + const pkg = readJson( + join(rootDir, 'libs', entry.name, 'package.json') + ); + return [pkg.name, pkg]; + }) + ); + const versions = new Set( + packageNames.map(name => { + const pkg = packages.get(name); + if (!pkg || !versionPattern.test(pkg.version)) { + throw new Error(`Missing package or invalid version: ${name}`); + } + return pkg.version; + }) + ); + if (versions.size !== 1) { + throw new Error('Published package versions do not match.'); + } + + const version = override ?? versions.values().next().value; + if (!versionPattern.test(version)) { + throw new Error(`Invalid documentation version: ${version}`); + } + return version; +} + +export function prepareDocs(directory, rootDir = ROOT_DIR) { + const license = join(directory, 'LICENSE'); + copyFileSync(join(rootDir, 'LICENSE'), license); + + function visit(path) { + for (const entry of readdirSync(path, { withFileTypes: true })) { + const file = join(path, entry.name); + if (entry.isDirectory()) { + visit(file); + } else if (entry.name.endsWith('.html')) { + const html = readFileSync(file, 'utf8'); + const licensePath = relative(dirname(file), license) + .split(sep) + .join('/'); + const updated = html.replace( + /href="(?:\.\.?\/)*LICENSE"/g, + `href="${licensePath}"` + ); + if (updated !== html) writeFileSync(file, updated); + } + } + } + visit(directory); +} + +function run(command, args) { + const result = spawnSync(command, args, { + cwd: ROOT_DIR, + stdio: 'inherit' + }); + if (result.error) throw result.error; + if (result.status !== 0) process.exit(result.status ?? 1); +} + +if (import.meta.main) { + const version = getDocsVersion(ROOT_DIR, process.env.VERSION); + if (process.argv[2] === '--version') { + process.stdout.write(`${version}\n`); + } else { + const output = join(ROOT_DIR, 'websites/docs/public/api-docs/latest'); + run(process.execPath, [ + join(ROOT_DIR, 'node_modules/typedoc/bin/typedoc'), + '--name', + `Libraries v${version}` + ]); + prepareDocs(output); + run('bash', [join(ROOT_DIR, 'scripts/inject-gtm.sh'), output]); + } +} diff --git a/scripts/docs.test.mjs b/scripts/docs.test.mjs new file mode 100644 index 00000000..72d07b8c --- /dev/null +++ b/scripts/docs.test.mjs @@ -0,0 +1,199 @@ +import { spawnSync } from 'node:child_process'; +import { + copyFileSync, + existsSync, + mkdirSync, + mkdtempSync, + readFileSync, + rmSync, + writeFileSync +} from 'node:fs'; +import { tmpdir } from 'node:os'; +import { join } from 'node:path'; +import { afterEach, beforeEach, describe, expect, it } from 'vitest'; +import { getDocsVersion, prepareDocs } from './docs.mjs'; + +let rootDir; + +function writeJson(path, value) { + writeFileSync(path, JSON.stringify(value)); +} + +function writePackage(name, version = '5.1.0') { + const directory = join(rootDir, 'libs', name); + mkdirSync(directory, { recursive: true }); + writeJson(join(directory, 'package.json'), { + name: `@cleverbrush/${name}`, + version + }); +} + +beforeEach(() => { + rootDir = mkdtempSync(join(tmpdir(), 'framework-docs-test-')); + mkdirSync(join(rootDir, '.changeset')); + mkdirSync(join(rootDir, 'scripts')); + writeJson(join(rootDir, 'package.json'), { + private: true, + version: '4.2.0' + }); + writeJson(join(rootDir, '.changeset/config.json'), { + fixed: [['@cleverbrush/schema', '@cleverbrush/deep']] + }); + writePackage('schema'); + writePackage('deep'); + writeFileSync(join(rootDir, 'LICENSE'), 'Fixture license'); + for (const name of ['docs.mjs', 'snapshot-docs.sh']) { + copyFileSync( + new URL(name, import.meta.url), + join(rootDir, 'scripts', name) + ); + } +}); + +afterEach(() => { + rmSync(rootDir, { recursive: true, force: true }); +}); + +describe('documentation versions', () => { + it('uses release packages rather than the stale private root version', () => { + mkdirSync(join(rootDir, 'libs/unrelated-directory')); + expect(getDocsVersion(rootDir)).toBe('5.1.0'); + }); + + it('preserves explicit prerelease version overrides', () => { + expect(getDocsVersion(rootDir, '5.2.0-beta.1+build.2')).toBe( + '5.2.0-beta.1+build.2' + ); + }); + + it('rejects mixed package versions even with an override', () => { + writePackage('deep', '5.0.0'); + expect(() => getDocsVersion(rootDir)).toThrow('do not match'); + expect(() => getDocsVersion(rootDir, '5.1.0')).toThrow('do not match'); + }); + + it('rejects missing fixed release packages', () => { + rmSync(join(rootDir, 'libs/deep'), { recursive: true }); + expect(() => getDocsVersion(rootDir)).toThrow('@cleverbrush/deep'); + }); + + it.each(['../5.1.0', 'v5.1.0', '05.1.0', '5.1.0-beta.01', ''])( + 'rejects an invalid override: %s', + version => { + expect(() => getDocsVersion(rootDir, version)).toThrow( + 'Invalid documentation version' + ); + } + ); +}); + +function latestDocs(version = '5.1.0') { + const directory = join(rootDir, 'websites/docs/public/api-docs/latest'); + mkdirSync(directory, { recursive: true }); + writeFileSync( + join(directory, 'index.html'), + `Libraries v${version}License` + ); + return directory; +} + +it('keeps license links local at every documentation depth', () => { + const directory = latestDocs(); + mkdirSync(join(directory, 'modules/nested'), { recursive: true }); + const module = join(directory, 'modules/package.html'); + const nested = join(directory, 'modules/nested/example.html'); + writeFileSync(module, 'License'); + writeFileSync( + nested, + 'License' + + 'External' + ); + + prepareDocs(directory, rootDir); + + expect(readFileSync(join(directory, 'LICENSE'), 'utf8')).toBe( + 'Fixture license' + ); + expect(readFileSync(join(directory, 'index.html'), 'utf8')).toContain( + 'href="LICENSE"' + ); + expect(readFileSync(module, 'utf8')).toContain('href="../LICENSE"'); + expect(readFileSync(nested, 'utf8')).toContain('href="../../LICENSE"'); + expect(readFileSync(nested, 'utf8')).toContain( + 'href="https://example.com/LICENSE"' + ); +}); + +function snapshot(version) { + const env = { ...process.env }; + delete env.VERSION; + if (version !== undefined) env.VERSION = version; + return spawnSync('bash', [join(rootDir, 'scripts/snapshot-docs.sh')], { + cwd: rootDir, + encoding: 'utf8', + env + }); +} + +describe('documentation snapshots', () => { + it('archives matching latest docs and updates the sorted version picker', () => { + const latest = latestDocs(); + prepareDocs(latest, rootDir); + const docs = join(latest, '..'); + mkdirSync(join(docs, 'v5.0.0')); + writeFileSync(join(docs, 'v5.0.0/index.html'), 'Archived release'); + + const result = snapshot(); + + expect(result.status, result.stderr).toBe(0); + expect(readFileSync(join(docs, 'v5.1.0/index.html'), 'utf8')).toBe( + readFileSync(join(latest, 'index.html'), 'utf8') + ); + expect(readFileSync(join(docs, 'v5.1.0/LICENSE'), 'utf8')).toBe( + 'Fixture license' + ); + expect( + JSON.parse(readFileSync(join(docs, 'versions.json'), 'utf8')) + ).toEqual([ + { version: 'v5.1.0', path: 'v5.1.0/index.html' }, + { version: 'v5.0.0', path: 'v5.0.0/index.html' } + ]); + expect(readFileSync(join(docs, 'index.html'), 'utf8')).toContain( + './v5.1.0/index.html' + ); + expect(readFileSync(join(docs, 'v5.0.0/index.html'), 'utf8')).toBe( + 'Archived release' + ); + + writeFileSync(join(latest, 'index.html'), 'Changed latest docs'); + const repeated = snapshot(); + expect(repeated.status).toBe(1); + expect(repeated.stdout).toContain('already exists'); + expect(readFileSync(join(docs, 'v5.1.0/index.html'), 'utf8')).toContain( + 'Libraries v5.1.0' + ); + }); + + it('rejects stale latest docs instead of mislabeling the archive', () => { + const latest = latestDocs('5.0.0'); + const result = snapshot(); + expect(result.status).toBe(1); + expect(result.stdout).toContain('do not match v5.1.0'); + expect(existsSync(join(latest, '../v5.1.0'))).toBe(false); + }); + + it('preserves matching explicit version overrides', () => { + const latest = latestDocs('5.2.0-beta.1'); + const result = snapshot('5.2.0-beta.1'); + expect(result.status, result.stderr).toBe(0); + expect(existsSync(join(latest, '../v5.2.0-beta.1/index.html'))).toBe( + true + ); + }); + + it('requires latest docs to have been generated', () => { + const result = snapshot(); + expect(result.status).toBe(1); + expect(result.stdout).toContain("Run 'npm run docs' first"); + }); +}); diff --git a/scripts/snapshot-docs.sh b/scripts/snapshot-docs.sh index 6b1cdc39..c1b370e4 100755 --- a/scripts/snapshot-docs.sh +++ b/scripts/snapshot-docs.sh @@ -4,7 +4,7 @@ set -euo pipefail # snapshot-docs.sh — Snapshot generated API docs for the current version. # # Usage: -# npm run docs:snapshot # uses version from root package.json +# npm run docs:snapshot # uses the fixed release packages' version # ./scripts/snapshot-docs.sh # same # VERSION=1.2.3 ./scripts/snapshot-docs.sh # override version @@ -13,10 +13,8 @@ ROOT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)" DOCS_DIR="$ROOT_DIR/websites/docs/public/api-docs" LATEST_DIR="$DOCS_DIR/latest" -# Determine version -if [[ -z "${VERSION:-}" ]]; then - VERSION=$(node -p "require('$ROOT_DIR/package.json').version") -fi +# Use the same version resolver as documentation generation (including VERSION). +VERSION=$(node "$SCRIPT_DIR/docs.mjs" --version) TARGET_DIR="$DOCS_DIR/v$VERSION" @@ -32,6 +30,12 @@ if [[ -d "$TARGET_DIR" ]]; then exit 1 fi +# Do not archive stale docs under a newer package version. +if [[ ! -f "$LATEST_DIR/index.html" ]] || ! grep -Fq "Libraries v$VERSION" "$LATEST_DIR/index.html"; then + echo "Error: latest docs do not match v$VERSION. Run 'npm run docs' first." + exit 1 +fi + # Copy latest → versioned snapshot echo "Snapshotting docs v$VERSION..." cp -r "$LATEST_DIR" "$TARGET_DIR" diff --git a/websites/docs/Dockerfile b/websites/docs/Dockerfile index c9b8f86e..63d7ccc2 100644 --- a/websites/docs/Dockerfile +++ b/websites/docs/Dockerfile @@ -1,37 +1,27 @@ # Build stage — builds the framework libs, API docs, and the Next.js website -FROM node:22-alpine AS build +FROM node:24-alpine AS build WORKDIR /app # Copy root workspace config and lockfile COPY package.json package-lock.json ./ -COPY typedoc.json ./ +COPY typedoc.json tsconfig.json tsconfig.build.json turbo.json ./ +COPY README.md LICENSE SECURITY.md ./ +COPY docs/ docs/ +COPY .changeset/config.json .changeset/config.json COPY scripts/ scripts/ -# Copy the libraries needed for API docs generation -COPY libs/schema/ libs/schema/ -COPY libs/mapper/ libs/mapper/ -COPY libs/react-form/ libs/react-form/ -COPY libs/async/ libs/async/ -COPY libs/deep/ libs/deep/ -COPY libs/scheduler/ libs/scheduler/ -COPY libs/scheduler-postgres/ libs/scheduler-postgres/ -COPY libs/knex-schema/ libs/knex-schema/ -COPY libs/orm/ libs/orm/ -COPY libs/schema-json/ libs/schema-json/ - -# Copy the shared package and the docs website -COPY websites/shared/ websites/shared/ -COPY websites/docs/ websites/docs/ +# Include every workspace so npm ci and TypeDoc see the complete monorepo. +COPY libs/ libs/ +COPY demos/ demos/ +COPY websites/ websites/ # Install root workspace dependencies RUN apk add --no-cache perl bash RUN npm ci --ignore-scripts -# Build libs required for API docs -RUN cd libs/schema && npm run build -RUN cd libs/mapper && npm run build -RUN cd libs/react-form && npm run build +# Build all published libraries in dependency order, excluding demo apps. +RUN npx turbo run build --filter='./libs/*' # Generate API reference docs into websites/docs/public/api-docs/latest/ RUN npm run docs @@ -41,7 +31,7 @@ WORKDIR /app/websites/docs RUN npm run build # Production stage — lightweight Node.js server with Next.js standalone output -FROM node:22-alpine +FROM node:24-alpine WORKDIR /app diff --git a/websites/docs/next.config.ts b/websites/docs/next.config.ts index 3699712a..ba018880 100644 --- a/websites/docs/next.config.ts +++ b/websites/docs/next.config.ts @@ -1,12 +1,14 @@ +import { fileURLToPath } from 'node:url'; import type { NextConfig } from 'next'; const isDev = process.env.NODE_ENV === 'development'; +const workspaceRoot = fileURLToPath(new URL('../..', import.meta.url)); const cspHeader = [ "default-src 'self'", `script-src 'self' 'unsafe-inline'${isDev ? " 'unsafe-eval'" : ''} https://www.googletagmanager.com https://www.google-analytics.com`, "style-src 'self' 'unsafe-inline' https://fonts.googleapis.com", - "img-src 'self' data: blob:", + "img-src 'self' data: blob: https://github.com https://img.shields.io", "font-src 'self' https://fonts.gstatic.com data:", "connect-src 'self' https://www.google-analytics.com", 'frame-src https://www.googletagmanager.com', @@ -50,6 +52,10 @@ const securityHeaders = [ const nextConfig: NextConfig = { output: 'standalone', + outputFileTracingRoot: workspaceRoot, + turbopack: { + root: workspaceRoot + }, transpilePackages: [ '@t3-oss/env-nextjs', '@t3-oss/env-core', diff --git a/websites/docs/public/api-docs/index.html b/websites/docs/public/api-docs/index.html index a5f5309b..35c841dd 100644 --- a/websites/docs/public/api-docs/index.html +++ b/websites/docs/public/api-docs/index.html @@ -40,6 +40,8 @@

Previous Versions

+ + @@ -71,6 +73,7 @@

Previous Versions