rads-db 3.2.28 → 3.2.32

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/config.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { g as RadsConfig, T as TypeDefinition } from './types-4fe0833c.js';
1
+ import { g as RadsConfig, T as TypeDefinition } from './types-754c7eba.js';
2
2
  import 'mssql';
3
3
  import '_rads-db';
4
4
 
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { E as EntityDecoratorArgs, U as UiDecoratorArgs, a as UiFieldDecoratorArgs, V as ValidateEntityDecoratorArgs, b as ValidateFieldDecoratorArgs, F as FieldDecoratorArgs, C as ComputedDecoratorArgs, S as Schema, D as DriverConstructor, c as Driver, d as ComputedContext, R as RadsRequestContext, e as CreateRadsDbArgs, f as CreateRadsDbClientArgs } from './types-4fe0833c.js';
2
- export { O as Change, x as ComputedContextGlobal, k as CreateRadsArgsDrivers, m as CreateRadsDbArgsNormalized, ak as DeepKeys, af as DeepPartial, ad as DeepPartialWithNulls, ae as DeepPartialWithNullsItem, al as EntityMethods, w as EnumDefinition, v as FieldDefinition, J as FileSystemNode, u as FileUploadArgs, q as FileUploadDriver, p as FileUploadResult, H as GenerateClientNormalizedOptions, B as GenerateClientOptions, a9 as Get, $ as GetAggArgs, a0 as GetAggArgsAgg, a3 as GetAggArgsAny, a6 as GetAggResponse, _ as GetArgs, a2 as GetArgsAny, a5 as GetArgsInclude, Q as GetManyArgs, a1 as GetManyArgsAny, a7 as GetManyResponse, a8 as GetResponse, aa as GetResponseInclude, ab as GetResponseIncludeSelect, ac as GetResponseNoInclude, s as GetRestRoutesArgs, G as GetRestRoutesOptions, t as GetRestRoutesResponse, ah as InverseRelation, aj as JsonPutOperations, M as MinimalDriver, ai as Put, P as PutEffect, g as RadsConfig, h as RadsConfigDataSource, r as RadsDbInstance, N as RadsFeature, y as RadsHookDoc, L as RadsUiSlotDefinition, K as RadsUiSlotName, I as RadsVitePluginOptions, ag as Relation, i as RequiredFields, l as RestDriverOptions, A as RestFileUploadDriverOptions, n as SchemaLoadResult, o as SchemaValidators, z as SqlDriverOptions, T as TypeDefinition, j as ValidateStringDecoratorArgs, X as VerifyManyArgs, a4 as VerifyManyArgsAny, Y as VerifyManyResponse, Z as Where, W as WhereJsonContains } from './types-4fe0833c.js';
1
+ import { E as EntityDecoratorArgs, U as UiDecoratorArgs, a as UiFieldDecoratorArgs, V as ValidateEntityDecoratorArgs, b as ValidateFieldDecoratorArgs, F as FieldDecoratorArgs, C as ComputedDecoratorArgs, S as Schema, D as DriverConstructor, c as Driver, d as ComputedContext, R as RadsRequestContext, e as CreateRadsDbArgs, f as CreateRadsDbClientArgs } from './types-754c7eba.js';
2
+ export { O as Change, x as ComputedContextGlobal, k as CreateRadsArgsDrivers, m as CreateRadsDbArgsNormalized, an as DeepKeys, ai as DeepPartial, af as DeepPartialArrayItem, ad as DeepPartialWithNulls, ae as DeepPartialWithNullsItem, ag as DeepPartialWithoutNulls, ah as DeepPartialWithoutNullsItem, ao as EntityMethods, w as EnumDefinition, v as FieldDefinition, J as FileSystemNode, u as FileUploadArgs, q as FileUploadDriver, p as FileUploadResult, H as GenerateClientNormalizedOptions, B as GenerateClientOptions, a9 as Get, $ as GetAggArgs, a0 as GetAggArgsAgg, a3 as GetAggArgsAny, a6 as GetAggResponse, _ as GetArgs, a2 as GetArgsAny, a5 as GetArgsInclude, Q as GetManyArgs, a1 as GetManyArgsAny, a7 as GetManyResponse, a8 as GetResponse, aa as GetResponseInclude, ab as GetResponseIncludeSelect, ac as GetResponseNoInclude, s as GetRestRoutesArgs, G as GetRestRoutesOptions, t as GetRestRoutesResponse, ak as InverseRelation, am as JsonPutOperations, M as MinimalDriver, al as Put, P as PutEffect, g as RadsConfig, h as RadsConfigDataSource, r as RadsDbInstance, N as RadsFeature, y as RadsHookDoc, L as RadsUiSlotDefinition, K as RadsUiSlotName, I as RadsVitePluginOptions, aj as Relation, i as RequiredFields, l as RestDriverOptions, A as RestFileUploadDriverOptions, n as SchemaLoadResult, o as SchemaValidators, z as SqlDriverOptions, T as TypeDefinition, j as ValidateStringDecoratorArgs, X as VerifyManyArgs, a4 as VerifyManyArgsAny, Y as VerifyManyResponse, Z as Where, W as WhereJsonContains } from './types-754c7eba.js';
3
3
  import { RadsDb } from '_rads-db';
4
4
  export { RadsDb } from '_rads-db';
5
5
  import 'mssql';
@@ -45,18 +45,18 @@ type VerifyManyArgsAny = VerifyManyArgs<any>;
45
45
  type RelationsAndNestedObjects<EN extends keyof EntityMeta> = EntityMeta[EN]['relations'] & EntityMeta[EN]['nestedObjects'];
46
46
  type JsonFieldsInclude<EN extends keyof EntityMeta> = [EntityMeta[EN]['jsonFields']] extends [never] ? unknown : {
47
47
  [K in EntityMeta[EN]['jsonFields'] & string]?: {
48
- _pick?: string[];
48
+ _pick?: readonly string[];
49
49
  };
50
50
  };
51
51
  type GetArgsInclude<EN extends keyof EntityMeta, R extends keyof RelationsAndNestedObjects<EN> = keyof RelationsAndNestedObjects<EN>> = [R] extends [never] ? {
52
- _pick?: (EntityMeta[EN]['primitives'] | EntityMeta[EN]['jsonFields'])[];
52
+ _pick?: readonly (EntityMeta[EN]['primitives'] | EntityMeta[EN]['jsonFields'])[];
53
53
  } & JsonFieldsInclude<EN> : {
54
- _pick?: (EntityMeta[EN]['primitives'] | EntityMeta[EN]['jsonFields'] | R)[];
54
+ _pick?: readonly (EntityMeta[EN]['primitives'] | EntityMeta[EN]['jsonFields'] | R)[];
55
55
  } & {
56
56
  [K in R]?: GetArgsInclude<RelationsAndNestedObjects<EN>[K]['entityName']>;
57
57
  } & JsonFieldsInclude<EN>;
58
58
  type GetAggResponse<EN extends keyof EntityMeta, A extends GetAggArgs<EN>> = {
59
- [K in A['agg'][0]]: K extends '_count' ? number : number | undefined;
59
+ [K in A['agg'][number]]: K extends '_count' ? number : number | undefined;
60
60
  };
61
61
  interface GetManyResponse<EN extends keyof EntityMeta, A extends GetArgs<EN>> {
62
62
  nodes: GetResponse<EN, A>[];
@@ -75,12 +75,12 @@ type Get<EntityName extends keyof EntityMeta, Include extends keyof EntityMeta[E
75
75
  type RelationData<EN extends keyof EntityMeta, K extends keyof EntityMeta[EN]['relations']> = Pick<EntityMeta[EN]['relations'][K]['entity'], EntityMeta[EN]['relations'][K]['denormFields']>;
76
76
  type KeepArray<TMaybeArray, TType> = NonNullable<TMaybeArray> extends any[] ? TType[] : TType;
77
77
  type GetResponseInclude<EN extends keyof EntityMeta, I extends GetArgsInclude<EN>> = I extends {
78
- _pick: string[];
78
+ _pick: readonly string[];
79
79
  } ? GetResponseIncludeSelect<EN, I> : {
80
80
  [K in keyof EntityMeta[EN]['type']]: K extends keyof EntityMeta[EN]['relations'] ? K extends keyof I ? KeepArray<EntityMeta[EN]['type'][K], GetResponseInclude<EntityMeta[EN]['relations'][K]['entityName'], I[K]>> : KeepArray<EntityMeta[EN]['type'][K], RelationData<EN, K>> : EntityMeta[EN]['type'][K];
81
81
  };
82
82
  type GetResponseIncludeSelect<EN extends keyof EntityMeta, I extends GetArgsInclude<EN>> = I extends {
83
- _pick: (infer P)[];
83
+ _pick: readonly (infer P)[];
84
84
  } ? Pick<{
85
85
  [K in keyof EntityMeta[EN]['type']]: K extends keyof EntityMeta[EN]['relations'] ? K extends keyof Omit<I, '_pick'> ? KeepArray<EntityMeta[EN]['type'][K], GetResponseInclude<EntityMeta[EN]['relations'][K]['entityName'], Omit<I, '_pick'>[K]>> : KeepArray<EntityMeta[EN]['type'][K], RelationData<EN, K>> : K extends EntityMeta[EN]['jsonFields'] ? K extends keyof Omit<I, '_pick'> ? Omit<I, '_pick'>[K] extends {
86
86
  _pick: (infer JP)[];
@@ -90,13 +90,26 @@ type GetResponseNoInclude<EN extends keyof EntityMeta> = {
90
90
  [K in keyof EntityMeta[EN]['type']]: K extends keyof EntityMeta[EN]['relations'] ? KeepArray<EntityMeta[EN]['type'][K], RelationData<EN, K>> : EntityMeta[EN]['type'][K];
91
91
  };
92
92
  type DeepPartialWithNulls<T> = {
93
- [K in keyof T]?: NonNullable<T[K]> extends any[] ? DeepPartialWithNullsItem<NonNullable<T[K]>[number]>[] : DeepPartialWithNullsItem<NonNullable<T[K]>>;
93
+ [K in keyof T]?: NonNullable<T[K]> extends any[] ? DeepPartialArrayItem<NonNullable<T[K]>[number]>[] | null : DeepPartialWithNullsItem<NonNullable<T[K]>>;
94
94
  };
95
95
  type DeepPartialWithNullsItem<T> = T extends {
96
96
  id: string;
97
97
  } ? {
98
98
  id: string;
99
99
  } | null : T extends Record<string, any> ? DeepPartialWithNulls<T> | null : T | null;
100
+ type DeepPartialArrayItem<T> = T extends {
101
+ id: string;
102
+ } ? {
103
+ id: string;
104
+ } : T extends Record<string, any> ? DeepPartialWithoutNulls<T> : T;
105
+ type DeepPartialWithoutNulls<T> = {
106
+ [K in keyof T]?: NonNullable<T[K]> extends any[] ? DeepPartialArrayItem<NonNullable<T[K]>[number]>[] : DeepPartialWithoutNullsItem<NonNullable<T[K]>>;
107
+ };
108
+ type DeepPartialWithoutNullsItem<T> = T extends {
109
+ id: string;
110
+ } ? {
111
+ id: string;
112
+ } : T extends Record<string, any> ? DeepPartialWithoutNulls<T> : T;
100
113
  type DeepPartial<T> = {
101
114
  [K in keyof T]?: NonNullable<T[K]> extends any[] ? DeepPartial<NonNullable<T[K]>[number]>[] : NonNullable<T[K]> extends Record<string, any> ? DeepPartial<T[K]> : T[K];
102
115
  };
@@ -111,9 +124,12 @@ type Relation<T extends {
111
124
  * If you need more control, please, use separate request instead.
112
125
  */
113
126
  type InverseRelation<EN extends keyof EntityMeta> = EntityMeta[EN]['type'];
114
- type Put<EN extends keyof EntityMeta> = {
127
+ type PutId<T> = T extends {
128
+ id: string;
129
+ } ? {
115
130
  id: string;
116
- } & JsonPutOperations<EN> & DeepPartialWithNulls<EntityMeta[EN]['type']>;
131
+ } : {};
132
+ type Put<EN extends keyof EntityMeta> = PutId<EntityMeta[EN]['type']> & JsonPutOperations<EN> & DeepPartialWithNulls<EntityMeta[EN]['type']>;
117
133
  type JsonPutOperations<EN extends keyof EntityMeta> = {
118
134
  [K in EntityMeta[EN]['jsonFields'] as `${K & string}_replace`]?: EntityMeta[EN]['type'][K];
119
135
  };
@@ -126,14 +142,14 @@ interface EntityMethods<E, EN extends keyof EntityMeta> {
126
142
  /** Used to access underlying mechanism of storage directly.
127
143
  * Warning: bypasses all rads features - schema won't be validated, default values won't be filled, etc. */
128
144
  driver: Driver;
129
- get<A extends GetArgs<EN>>(args: A, ctx?: RadsRequestContext): MaybePromise$1<GetResponse<EN, A>>;
130
- getMany<A extends GetManyArgs<EN>>(args?: A, ctx?: RadsRequestContext): MaybePromise$1<GetManyResponse<EN, A>>;
131
- getAgg<A extends GetAggArgs<EN>>(args: A, ctx?: RadsRequestContext): MaybePromise$1<GetAggResponse<EN, A>>;
132
- getAll<A extends GetManyArgs<EN>>(args?: A, ctx?: RadsRequestContext): MaybePromise$1<GetManyResponse<EN, A>['nodes']>;
145
+ get<const A extends GetArgs<EN>>(args: A, ctx?: RadsRequestContext): MaybePromise$1<GetResponse<EN, A>>;
146
+ getMany<const A extends GetManyArgs<EN>>(args?: A, ctx?: RadsRequestContext): MaybePromise$1<GetManyResponse<EN, A>>;
147
+ getAgg<const A extends GetAggArgs<EN>>(args: A, ctx?: RadsRequestContext): MaybePromise$1<GetAggResponse<EN, A>>;
148
+ getAll<const A extends GetManyArgs<EN>>(args?: A, ctx?: RadsRequestContext): MaybePromise$1<GetManyResponse<EN, A>['nodes']>;
133
149
  put(data: Put<EN>, ctx?: RadsRequestContext): MaybePromise$1<GetResponseNoInclude<EN>>;
134
150
  putMany(data: Put<EN>[], ctx?: RadsRequestContext): MaybePromise$1<GetResponseNoInclude<EN>[]>;
135
- verifyMany<A extends VerifyManyArgs<EN>>(args?: A, ctx?: RadsRequestContext): MaybePromise$1<VerifyManyResponse>;
136
- verifyAll<A extends VerifyManyArgs<EN>>(args?: A, ctx?: RadsRequestContext): MaybePromise$1<Pick<VerifyManyResponse, 'correctCount' | 'incorrectCount'>>;
151
+ verifyMany<const A extends VerifyManyArgs<EN>>(args?: A, ctx?: RadsRequestContext): MaybePromise$1<VerifyManyResponse>;
152
+ verifyAll<const A extends VerifyManyArgs<EN>>(args?: A, ctx?: RadsRequestContext): MaybePromise$1<Pick<VerifyManyResponse, 'correctCount' | 'incorrectCount'>>;
137
153
  }
138
154
  type Prev = [never, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, ...0[]];
139
155
  type Primitive = string | number | boolean | symbol | null | undefined;
@@ -336,12 +352,13 @@ interface MinimalDriver {
336
352
  deleteAll?: (args: GetManyArgsAny, ctx?: RadsRequestContext) => MaybePromise<Record<string, any>[]>;
337
353
  put?: (data: Record<string, any>, ctx?: RadsRequestContext) => MaybePromise<any>;
338
354
  verifyMany?: (args?: VerifyManyArgsAny, ctx?: RadsRequestContext) => MaybePromise<VerifyManyResponse>;
355
+ ensureClientConnected?: () => MaybePromise<void>;
339
356
  generateMigrationScript?: () => MaybePromise<{
340
357
  createScript: string;
341
358
  dropScript: string;
342
359
  }>;
343
360
  }
344
- type Driver = Required<Omit<MinimalDriver, 'verifyMany' | 'client' | 'generateMigrationScript'>> & Pick<MinimalDriver, 'verifyMany' | 'client' | 'generateMigrationScript'>;
361
+ type Driver = Required<Omit<MinimalDriver, 'verifyMany' | 'client' | 'ensureClientConnected' | 'generateMigrationScript'>> & Pick<MinimalDriver, 'verifyMany' | 'client' | 'ensureClientConnected' | 'generateMigrationScript'>;
345
362
  interface FieldDefinition {
346
363
  name: string;
347
364
  type: string;
@@ -488,4 +505,4 @@ interface RadsFeature {
488
505
  afterUploadFile?: (result: FileUploadResult, args: FileUploadArgs) => MaybePromise<void>;
489
506
  }
490
507
 
491
- export { GetAggArgs as $, RestFileUploadDriverOptions as A, GenerateClientOptions as B, ComputedDecoratorArgs as C, DriverConstructor as D, EntityDecoratorArgs as E, FieldDecoratorArgs as F, GetRestRoutesOptions as G, GenerateClientNormalizedOptions as H, RadsVitePluginOptions as I, FileSystemNode as J, RadsUiSlotName as K, RadsUiSlotDefinition as L, MinimalDriver as M, RadsFeature as N, Change as O, PutEffect as P, GetManyArgs as Q, RadsRequestContext as R, Schema as S, TypeDefinition as T, UiDecoratorArgs as U, ValidateEntityDecoratorArgs as V, WhereJsonContains as W, VerifyManyArgs as X, VerifyManyResponse as Y, Where as Z, GetArgs as _, UiFieldDecoratorArgs as a, GetAggArgsAgg as a0, GetManyArgsAny as a1, GetArgsAny as a2, GetAggArgsAny as a3, VerifyManyArgsAny as a4, GetArgsInclude as a5, GetAggResponse as a6, GetManyResponse as a7, GetResponse as a8, Get as a9, GetResponseInclude as aa, GetResponseIncludeSelect as ab, GetResponseNoInclude as ac, DeepPartialWithNulls as ad, DeepPartialWithNullsItem as ae, DeepPartial as af, Relation as ag, InverseRelation as ah, Put as ai, JsonPutOperations as aj, DeepKeys as ak, EntityMethods as al, ValidateFieldDecoratorArgs as b, Driver as c, ComputedContext as d, CreateRadsDbArgs as e, CreateRadsDbClientArgs as f, RadsConfig as g, RadsConfigDataSource as h, RequiredFields as i, ValidateStringDecoratorArgs as j, CreateRadsArgsDrivers as k, RestDriverOptions as l, CreateRadsDbArgsNormalized as m, SchemaLoadResult as n, SchemaValidators as o, FileUploadResult as p, FileUploadDriver as q, RadsDbInstance as r, GetRestRoutesArgs as s, GetRestRoutesResponse as t, FileUploadArgs as u, FieldDefinition as v, EnumDefinition as w, ComputedContextGlobal as x, RadsHookDoc as y, SqlDriverOptions as z };
508
+ export { GetAggArgs as $, RestFileUploadDriverOptions as A, GenerateClientOptions as B, ComputedDecoratorArgs as C, DriverConstructor as D, EntityDecoratorArgs as E, FieldDecoratorArgs as F, GetRestRoutesOptions as G, GenerateClientNormalizedOptions as H, RadsVitePluginOptions as I, FileSystemNode as J, RadsUiSlotName as K, RadsUiSlotDefinition as L, MinimalDriver as M, RadsFeature as N, Change as O, PutEffect as P, GetManyArgs as Q, RadsRequestContext as R, Schema as S, TypeDefinition as T, UiDecoratorArgs as U, ValidateEntityDecoratorArgs as V, WhereJsonContains as W, VerifyManyArgs as X, VerifyManyResponse as Y, Where as Z, GetArgs as _, UiFieldDecoratorArgs as a, GetAggArgsAgg as a0, GetManyArgsAny as a1, GetArgsAny as a2, GetAggArgsAny as a3, VerifyManyArgsAny as a4, GetArgsInclude as a5, GetAggResponse as a6, GetManyResponse as a7, GetResponse as a8, Get as a9, GetResponseInclude as aa, GetResponseIncludeSelect as ab, GetResponseNoInclude as ac, DeepPartialWithNulls as ad, DeepPartialWithNullsItem as ae, DeepPartialArrayItem as af, DeepPartialWithoutNulls as ag, DeepPartialWithoutNullsItem as ah, DeepPartial as ai, Relation as aj, InverseRelation as ak, Put as al, JsonPutOperations as am, DeepKeys as an, EntityMethods as ao, ValidateFieldDecoratorArgs as b, Driver as c, ComputedContext as d, CreateRadsDbArgs as e, CreateRadsDbClientArgs as f, RadsConfig as g, RadsConfigDataSource as h, RequiredFields as i, ValidateStringDecoratorArgs as j, CreateRadsArgsDrivers as k, RestDriverOptions as l, CreateRadsDbArgsNormalized as m, SchemaLoadResult as n, SchemaValidators as o, FileUploadResult as p, FileUploadDriver as q, RadsDbInstance as r, GetRestRoutesArgs as s, GetRestRoutesResponse as t, FileUploadArgs as u, FieldDefinition as v, EnumDefinition as w, ComputedContextGlobal as x, RadsHookDoc as y, SqlDriverOptions as z };
@@ -1,5 +1,5 @@
1
- import type { Schema } from '@/types';
2
- import type { GetAggArgsAny, GetManyArgsAny } from '@/typesClientEngine';
1
+ import type { MinimalDriver, Schema } from '../types';
2
+ import type { GetAggArgsAny, GetManyArgsAny } from '../typesClientEngine';
3
3
  interface MemoryDriverOptions {
4
4
  }
5
5
  declare const _default: (options?: MemoryDriverOptions) => (schema: Schema, entity: string) => MinimalDriver;
@@ -7,6 +7,6 @@ export default _default;
7
7
  export declare function getAggFromArray(array: any[], args: GetAggArgsAny): Record<string, any>;
8
8
  export declare function queryArray(array: any[], args: GetManyArgsAny): {
9
9
  nodes: any;
10
- cursor: any;
10
+ cursor: string | null;
11
11
  };
12
12
  export declare function getFilter(where: Record<string, any>, namePrefix?: string): ((x: any) => boolean | undefined) | null;
@@ -1,3 +1,3 @@
1
- import type { RestDriverOptions, Schema } from '@/types';
1
+ import type { MinimalDriver, RestDriverOptions, Schema } from '../types';
2
2
  declare const _default: (options?: RestDriverOptions) => (schema: Schema, entity: string) => MinimalDriver;
3
3
  export default _default;
package/drivers/sql.d.ts CHANGED
@@ -1,4 +1,3 @@
1
- import type { SqlDriverOptions } from '@/types';
2
- import type { Schema } from 'rads-db';
3
- declare const _default: (options: SqlDriverOptions) => (schema: Schema, entity: string) => MinimalDriver;
1
+ import type { DriverConstructor, SqlDriverOptions } from '../types';
2
+ declare const _default: (options: SqlDriverOptions) => DriverConstructor;
4
3
  export default _default;
@@ -1,5 +1,14 @@
1
- import type { DriverConstructor } from '@/types';
2
- declare const _default: (options: CacheOptions) => RadsFeature;
1
+ import type { DriverConstructor } from '../types';
2
+ declare const _default: (options: CacheOptions) => {
3
+ name: string;
4
+ init(db: Record<string, any>, context: import("../types").ComputedContextGlobal): void;
5
+ beforeGet(args: import("../typesClientEngine").GetArgsAny, ctx: import("../types").RadsRequestContext, context: import("../types").ComputedContext): Promise<Record<string, any> | Record<string, any>[] | {
6
+ nodes: Record<string, any>[];
7
+ cursor: string | undefined;
8
+ } | undefined>;
9
+ afterGet(items: any[], args: import("../typesClientEngine").GetArgsAny, ctx: import("../types").RadsRequestContext, context: import("../types").ComputedContext): Promise<void>;
10
+ afterPut(items: import("../types").RadsHookDoc[], ctx: import("../types").RadsRequestContext, computedContext: import("../types").ComputedContext): Promise<void>;
11
+ };
3
12
  export default _default;
4
13
  export interface EntityCacheOptions {
5
14
  driver?: DriverConstructor;
@@ -1,4 +1,4 @@
1
- import type { ComputedContext, RadsFeature, RadsRequestContext } from '@/types';
1
+ import type { ComputedContext, RadsFeature, RadsRequestContext } from '../types';
2
2
  export interface EventSourcingFeatureOptions {
3
3
  applyEventIf?: (event: any, context: ComputedContext, ctx: RadsRequestContext) => boolean;
4
4
  freezeEvent?: (event: any, context: ComputedContext, ctx: RadsRequestContext) => boolean;
@@ -1,2 +1,5 @@
1
- declare const _default: () => RadsFeature;
1
+ declare const _default: () => {
2
+ name: string;
3
+ beforeGet(args: import("../typesClientEngine").GetArgsAny, ctx: import("../types").RadsRequestContext, context: import("../types").ComputedContext): void;
4
+ };
2
5
  export default _default;
@@ -1,4 +1,5 @@
1
1
  import type { StoragePipelineOptions } from '@azure/storage-blob';
2
+ import type { FileUploadDriver } from '../types';
2
3
  interface AzureStorageBlobUploadDriverOptions {
3
4
  connectionString: string;
4
5
  defaultContainer?: string;
@@ -1,3 +1,4 @@
1
+ import type { FileUploadDriver } from '../types';
1
2
  interface MemoryFileUploadDriverOptions {
2
3
  }
3
4
  declare const _default: (options?: MemoryFileUploadDriverOptions) => FileUploadDriver;
@@ -1,3 +1,3 @@
1
- import type { RestFileUploadDriverOptions } from '@/types';
1
+ import type { FileUploadDriver, RestFileUploadDriverOptions } from '../types';
2
2
  declare const _default: (options: RestFileUploadDriverOptions) => FileUploadDriver;
3
3
  export default _default;
@@ -1,4 +1,5 @@
1
1
  import type { SupabaseClient } from '@supabase/supabase-js';
2
+ import type { FileUploadDriver } from '../types';
2
3
  declare const _default: (options: SupabaseFileUploadDriverOptions) => FileUploadDriver;
3
4
  export default _default;
4
5
  interface SupabaseFileUploadDriverOptions {
package/llms.txt ADDED
@@ -0,0 +1,409 @@
1
+ # rads-db
2
+
3
+ > TypeScript-first universal data access library. Define entities as decorated classes, get strongly-typed CRUD methods, filtering, pagination, JOINs across any storage backend. Works on both server and browser.
4
+
5
+ ## Setup
6
+
7
+ ```bash
8
+ npm install rads-db
9
+ ```
10
+
11
+ Create `rads.config.ts` at the project root:
12
+
13
+ ```typescript
14
+ import { defineRadsConfig, schemaFromFiles } from 'rads-db/config'
15
+
16
+ export default defineRadsConfig({
17
+ dataSources: {
18
+ db: {
19
+ schema: schemaFromFiles('./entities'), // folder with your entity classes
20
+ },
21
+ },
22
+ })
23
+ ```
24
+
25
+ Run codegen after every schema change (generates TypeScript types and metadata):
26
+
27
+ ```bash
28
+ npx rads
29
+ ```
30
+
31
+ Automate in `package.json`:
32
+
33
+ ```json
34
+ {
35
+ "scripts": {
36
+ "dev": "npx rads && <your-dev-command>",
37
+ "build": "npx rads && <your-build-command>"
38
+ }
39
+ }
40
+ ```
41
+
42
+ ## Defining Entities
43
+
44
+ Each entity is a TypeScript class in the entities folder. Use decorators from `rads-db`:
45
+
46
+ ```typescript
47
+ import { entity, field, ui, validate, computed, precomputed, keepHistory } from 'rads-db'
48
+ import type { Relation, InverseRelation } from 'rads-db'
49
+ import type { TcRole } from './TcRole'
50
+ import type { TcPost } from './TcPost'
51
+
52
+ @entity()
53
+ @ui<typeof TcUser>({ name: 'User', namePlural: 'Users', nameField: 'name', captionFields: ['id', 'name'], group: 'People' })
54
+ export class TcUser {
55
+ id!: string
56
+
57
+ @validate<TcUser, any, string>({ preset: 'email' })
58
+ @ui({ name: 'Email Address', hint: 'Used for login' })
59
+ email!: string
60
+
61
+ name!: string
62
+ age?: number
63
+ isActive?: boolean
64
+ tags: string[] = []
65
+
66
+ // Relation: only { id } is stored; use include: { tcRole: {} } to load full object
67
+ tcRole!: Relation<TcRole>
68
+
69
+ // Relation with denormalized fields stored alongside the id
70
+ tcRoleWithName!: Relation<TcRole, 'name'>
71
+
72
+ // Computed inverse relation — not stored, derived at query time
73
+ tcPosts?: InverseRelation<'TcPost'>
74
+
75
+ @computed()
76
+ fullLabel?: string // computed server-side, not stored
77
+
78
+ @precomputed({ preset: 'eventSourcing' })
79
+ status?: string // precomputed and stored when source events change
80
+
81
+ @keepHistory()
82
+ statusHistory?: string // keeps full history of changes
83
+ }
84
+ ```
85
+
86
+ ### Decorator reference
87
+
88
+ | Decorator | Target | Purpose |
89
+ |-----------|--------|---------|
90
+ | `@entity(args?)` | class | Marks class as a database entity; `args.driver` overrides default driver |
91
+ | `@ui(args)` | class or field | Display hints for rads-ui (name, icon, captionFields, nameField, etc.) |
92
+ | `@validate(args)` | class or field | Validation rules (presets, regex, min/maxLength, etc.) |
93
+ | `@field(args?)` | field | Marks a relation field; `args.relation` points to the related class |
94
+ | `@computed()` | field | Computed at query time, never stored |
95
+ | `@precomputed()` | field | Computed and stored; recalculated when source data changes |
96
+ | `@keepHistory()` | field | Stores full change history |
97
+
98
+ ### Relation types
99
+
100
+ ```typescript
101
+ Relation<T> // stores { id } only
102
+ Relation<T, 'field1'|'field2'> // stores { id, field1, field2 } (denormalized)
103
+ InverseRelation<'EntityName'> // reverse lookup — computed, not stored
104
+ ```
105
+
106
+ ### Field validation presets (string)
107
+
108
+ `text` | `html` | `markdown` | `alpha` | `alphanum` | `number` | `decimalNumber` | `email` | `icon` | `imageUrl` | `fileUrl` | `absoluteUrl` | `relativeUrl` | `phoneNumber` | `datetime` | `date` | `time` | `timeInterval` | `duration` | `hexColor`
109
+
110
+ ## Creating the DB instance
111
+
112
+ ```typescript
113
+ import { createRadsDb } from 'rads-db'
114
+
115
+ const db = createRadsDb('db')
116
+ // db.tcUser, db.tcPost, db.tcRole, … — one property per entity (lowerFirst of class name)
117
+ ```
118
+
119
+ ## CRUD Methods
120
+
121
+ Every entity exposes the same set of methods on `db.<entityHandle>`:
122
+
123
+ ### get — fetch one record
124
+
125
+ ```typescript
126
+ const user = await db.tcUser.get({ where: { id: 'user1' } })
127
+ // returns undefined if not found
128
+ ```
129
+
130
+ ### getAll — fetch all matching records
131
+
132
+ ```typescript
133
+ const users = await db.tcUser.getAll({ where: { isActive: true } })
134
+ // returns T[]
135
+ ```
136
+
137
+ ### getMany — paginated fetch
138
+
139
+ ```typescript
140
+ const page = await db.tcUser.getMany({
141
+ where: { isActive: true },
142
+ maxItemCount: 20,
143
+ cursor: previousPage.cursor, // pass cursor from previous response for next page
144
+ orderByArray: ['name_asc', 'age_desc'],
145
+ })
146
+ // returns { nodes: T[], cursor: string | undefined }
147
+ // cursor === undefined means no more pages
148
+ ```
149
+
150
+ ### getAgg — aggregate queries
151
+
152
+ ```typescript
153
+ const agg = await db.tcUser.getAgg({
154
+ where: { isActive: true },
155
+ agg: ['_count', 'age_min', 'age_max', 'age_sum'],
156
+ })
157
+ // agg._count: number; agg.age_min: number | undefined; etc.
158
+ ```
159
+
160
+ ### put — create or update one record (upsert by id)
161
+
162
+ ```typescript
163
+ const saved = await db.tcUser.put({ id: 'user1', name: 'Alice', tcRole: { id: 'role1' } })
164
+ // returns the full saved record
165
+ // missing optional fields stay unchanged; null erases the value
166
+ ```
167
+
168
+ ### putMany — batch upsert
169
+
170
+ ```typescript
171
+ const saved = await db.tcUser.putMany([
172
+ { id: 'user1', name: 'Alice', tcRole: { id: 'role1' } },
173
+ { id: 'user2', name: 'Bob', tcRole: { id: 'role1' } },
174
+ ])
175
+ ```
176
+
177
+ ### construct — create in-memory object with defaults + a new UUID
178
+
179
+ ```typescript
180
+ const newUser = db.tcUser.construct({ name: 'Draft' })
181
+ // newUser.id is a fresh UUID; defaults from field declarations are applied
182
+ ```
183
+
184
+ ## Where Filters
185
+
186
+ Where clauses are fully typed. Every primitive field supports operators via suffix:
187
+
188
+ ```typescript
189
+ await db.tcUser.getAll({
190
+ where: {
191
+ name: 'Alice', // exact match
192
+ name_startsWith: 'Al',
193
+ name_istartsWith: 'al', // case-insensitive
194
+ name_contains: 'lic',
195
+ name_icontains: 'LIC',
196
+ name_endsWith: 'ice',
197
+ name_in: ['Alice', 'Bob'],
198
+ name_notIn: ['Charlie'],
199
+ age_gt: 18,
200
+ age_gte: 18,
201
+ age_lt: 65,
202
+ age_lte: 65,
203
+ isActive: true,
204
+
205
+ // Logical combinators
206
+ _and: [{ isActive: true }, { age_gte: 18 }],
207
+ _or: [{ name: 'Alice' }, { name: 'Bob' }],
208
+ _not: { isActive: false },
209
+
210
+ // Nested object filter
211
+ tcRole: { id: 'role1' },
212
+ },
213
+ })
214
+ ```
215
+
216
+ ## Include (JOINs)
217
+
218
+ Load related entities inline. Works across different databases/drivers:
219
+
220
+ ```typescript
221
+ const post = await db.tcPost.get({
222
+ where: { id: 'post1' },
223
+ include: {
224
+ tcUser: {}, // load full TcUser object
225
+ tcUser: { tcRole: {} }, // nested: load tcUser and its tcRole
226
+ tcComments: { _pick: ['id', 'text'] }, // load only specific fields of relation
227
+ },
228
+ })
229
+ ```
230
+
231
+ ## Field selection with `_pick`
232
+
233
+ ```typescript
234
+ const users = await db.tcUser.getAll({
235
+ include: { _pick: ['id', 'name'] }, // return only id and name
236
+ })
237
+ ```
238
+
239
+ ## TypeScript utility types
240
+
241
+ ```typescript
242
+ import type { Get, Put } from 'rads-db'
243
+
244
+ // Get — shape returned by read operations (all fields non-nullable)
245
+ type UserView = Get<'TcUser'>
246
+ // With relations and field selection:
247
+ type UserWithRole = Get<'TcUser', { tcRole: {}; _pick: ['id', 'name'] }>
248
+
249
+ // Put — shape accepted by write operations (all fields except id are optional; null erases a value)
250
+ type UserWrite = Put<'TcUser'>
251
+ ```
252
+
253
+ **Form state pattern** — use `Put` for editable state; `Get` is assignable to `Put`:
254
+
255
+ ```typescript
256
+ const data = await db.tcUser.get({ where: { id } })
257
+ const form: Put<'TcUser'> = { ...data } // Get is assignable to Put ✓
258
+ form.age = null // null = erase the field
259
+ await db.tcUser.put(form)
260
+ ```
261
+
262
+ ## Context (second argument to every method)
263
+
264
+ Pass `RadsRequestContext` as the second argument to control behaviour per-request:
265
+
266
+ ```typescript
267
+ import type { RadsRequestContext } from 'rads-db'
268
+
269
+ const ctx: RadsRequestContext = {
270
+ getUser: () => ({ id: 'user1', role: 'admin' }),
271
+ dryRun: true, // no changes written; effects returned as logs
272
+ noCache: true, // bypass caching layer
273
+ excludeFeatures: ['softDelete'], // skip specific features
274
+ }
275
+
276
+ const result = await db.tcUser.put(data, ctx)
277
+ ```
278
+
279
+ ## Features
280
+
281
+ Features hook into the get/put pipeline. Pass them to `createRadsDb`:
282
+
283
+ ```typescript
284
+ import { createRadsDb } from 'rads-db'
285
+ import softDelete from 'rads-db/features/softDelete'
286
+ import eventSourcing from 'rads-db/features/eventSourcing'
287
+ import cache from 'rads-db/features/cache'
288
+
289
+ const db = createRadsDb('db', {
290
+ features: [
291
+ softDelete(),
292
+ eventSourcing(),
293
+ cache(),
294
+ ],
295
+ })
296
+ ```
297
+
298
+ ### Built-in features
299
+
300
+ | Feature | Import | What it does |
301
+ |---------|--------|-------------|
302
+ | `softDelete` | `rads-db/features/softDelete` | Filters out records where `isDeleted: true` automatically |
303
+ | `eventSourcing` | `rads-db/features/eventSourcing` | Rebuilds aggregate from event log; entity needs `@precomputed({ preset: 'eventSourcing' })` |
304
+ | `cache` | `rads-db/features/cache` | Adds a caching layer; bypass with `ctx.noCache = true` |
305
+
306
+ ### Custom feature
307
+
308
+ ```typescript
309
+ import type { RadsFeature } from 'rads-db'
310
+
311
+ const auditLog = (): RadsFeature => ({
312
+ name: 'auditLog',
313
+ afterPut(items, ctx, computedContext) {
314
+ for (const { doc, oldDoc } of items) {
315
+ console.log('changed', computedContext.typeName, doc.id)
316
+ }
317
+ },
318
+ })
319
+ ```
320
+
321
+ ## Drivers
322
+
323
+ Configure per data-source in `rads.config.ts` or pass to `createRadsDb`:
324
+
325
+ | Import | Storage |
326
+ |--------|---------|
327
+ | `rads-db/drivers/memory` | In-memory (default; great for tests) |
328
+ | `rads-db/drivers/sql` | MSSQL / MySQL / PostgreSQL (via mssql / mysql2 / pg) |
329
+ | `rads-db/drivers/azureCosmos` | Azure Cosmos DB |
330
+ | `rads-db/drivers/azureStorageBlob` | Azure Blob Storage |
331
+ | `rads-db/drivers/indexedDb` | Browser IndexedDB |
332
+ | `rads-db/drivers/restApi` | REST API (used by `createRadsDbClient`) |
333
+
334
+ ```typescript
335
+ import sql from 'rads-db/drivers/sql'
336
+
337
+ const db = createRadsDb('db', {
338
+ driver: sql({
339
+ server: 'localhost',
340
+ database: 'mydb',
341
+ authentication: { type: 'default', options: { userName: 'sa', password: 'pass' } },
342
+ }),
343
+ })
344
+ ```
345
+
346
+ ## Client-side usage (browser)
347
+
348
+ ```typescript
349
+ import { createRadsDbClient } from 'rads-db'
350
+
351
+ // Uses fetch to talk to the server REST API; same methods as server-side db
352
+ const db = createRadsDbClient('db', { driver: { baseUrl: '/api' } })
353
+
354
+ const users = await db.tcUser.getAll({ where: { isActive: true } })
355
+ ```
356
+
357
+ ## REST API / Server endpoints
358
+
359
+ Expose all entities over HTTP using `getRestRoutes`:
360
+
361
+ ```typescript
362
+ // h3 / Nitro (Nuxt)
363
+ import { defineEventHandler, getMethod, readBody } from 'h3'
364
+ import { createRadsDb } from 'rads-db'
365
+ import { getRestRoutes } from 'rads-db/integrations/restEndpoints'
366
+
367
+ const db = createRadsDb('db')
368
+ const routes = getRestRoutes({ db, prefix: '/api/' })
369
+
370
+ export default defineEventHandler(async event => {
371
+ const path = event.path.split('?')[0]
372
+ const method = getMethod(event)
373
+ const handler = routes[path]?.[method]
374
+ if (!handler) return
375
+ const body = method !== 'GET' ? await readBody(event) : undefined
376
+ return handler({ body, context: event, headers: {} })
377
+ })
378
+ ```
379
+
380
+ Generated routes per entity (e.g. `TcUser` → handle `tcUser`):
381
+
382
+ | Path | Method | Description |
383
+ |------|--------|-------------|
384
+ | `/api/tcUser` | `POST` | `db.tcUser.get(body)` |
385
+ | `/api/tcUser` | `PUT` | `db.tcUser.put(body.data)` |
386
+ | `/api/tcUser/list` | `POST` | `db.tcUser.getMany(body)` |
387
+ | `/api/tcUser/list` | `PUT` | `db.tcUser.putMany(body.data)` |
388
+ | `/api/tcUser/agg` | `POST` | `db.tcUser.getAgg(body)` |
389
+
390
+ ## OpenAPI / Swagger
391
+
392
+ ```typescript
393
+ import { getOpenApiSpec } from 'rads-db/integrations/getOpenApiSpec'
394
+
395
+ const spec = getOpenApiSpec(
396
+ { db, prefix: '/api/' },
397
+ { title: 'My App API', version: '1.0.0' },
398
+ )
399
+ ```
400
+
401
+ ## Utilities
402
+
403
+ ```typescript
404
+ import { merge, diff, cleanEntity } from 'rads-db'
405
+
406
+ merge(target, source) // deep merge source into target
407
+ diff(oldObj, newObj) // returns changed fields only
408
+ cleanEntity(entity) // strips undefined/null fields
409
+ ```
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rads-db",
3
- "version": "3.2.28",
3
+ "version": "3.2.32",
4
4
  "description": "Say goodbye to boilerplate code and hello to efficient and elegant syntax.",
5
5
  "author": "",
6
6
  "license": "ISC",
@@ -48,7 +48,8 @@
48
48
  "drivers",
49
49
  "fileUploadDrivers",
50
50
  "integrations",
51
- "features"
51
+ "features",
52
+ "llms.txt"
52
53
  ],
53
54
  "peerDependencies": {
54
55
  "@azure/cosmos": ">=3",