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 +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/{types-4fe0833c.d.ts → types-754c7eba.d.ts} +34 -17
- package/drivers/memory.d.ts +3 -3
- package/drivers/restApi.d.ts +1 -1
- package/drivers/sql.d.ts +2 -3
- package/features/cache.d.ts +11 -2
- package/features/eventSourcing.d.ts +1 -1
- package/features/softDelete.d.ts +4 -1
- package/fileUploadDrivers/azureStorageBlob.d.ts +1 -0
- package/fileUploadDrivers/memory.d.ts +1 -0
- package/fileUploadDrivers/restApi.d.ts +1 -1
- package/fileUploadDrivers/supabaseStorage.d.ts +1 -0
- package/llms.txt +409 -0
- package/package.json +3 -2
package/dist/config.d.ts
CHANGED
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-
|
|
2
|
-
export { O as Change, x as ComputedContextGlobal, k as CreateRadsArgsDrivers, m as CreateRadsDbArgsNormalized,
|
|
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'][
|
|
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[] ?
|
|
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
|
|
127
|
+
type PutId<T> = T extends {
|
|
128
|
+
id: string;
|
|
129
|
+
} ? {
|
|
115
130
|
id: string;
|
|
116
|
-
}
|
|
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,
|
|
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 };
|
package/drivers/memory.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { Schema } from '
|
|
2
|
-
import type { GetAggArgsAny, GetManyArgsAny } from '
|
|
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:
|
|
10
|
+
cursor: string | null;
|
|
11
11
|
};
|
|
12
12
|
export declare function getFilter(where: Record<string, any>, namePrefix?: string): ((x: any) => boolean | undefined) | null;
|
package/drivers/restApi.d.ts
CHANGED
package/drivers/sql.d.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import type { SqlDriverOptions } from '
|
|
2
|
-
|
|
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;
|
package/features/cache.d.ts
CHANGED
|
@@ -1,5 +1,14 @@
|
|
|
1
|
-
import type { DriverConstructor } from '
|
|
2
|
-
declare const _default: (options: CacheOptions) =>
|
|
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 '
|
|
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;
|
package/features/softDelete.d.ts
CHANGED
|
@@ -1,2 +1,5 @@
|
|
|
1
|
-
declare const _default: () =>
|
|
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 { 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.
|
|
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",
|