@idb-orm/core 1.0.12 → 1.0.13
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/README.md +3 -20
- package/dist/client/compiled-query.d.ts +2 -2
- package/dist/client/helpers.d.ts +2 -2
- package/dist/client/types/find.d.ts +30 -14
- package/dist/client/types/index.d.ts +4 -4
- package/dist/client/types/mutation.d.ts +23 -22
- package/dist/core.d.ts +1 -1
- package/dist/error.d.ts +31 -1
- package/dist/field/field-types.d.ts +1 -1
- package/dist/index.cjs.js +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.es.js +2 -2
- package/dist/model/model.d.ts +5 -4
- package/dist/typing/tag.d.ts +27 -12
- package/dist/typing/type.d.ts +6 -1
- package/dist/typing/utils.d.ts +6 -0
- package/dist/util-types.d.ts +6 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -180,33 +180,16 @@ const client = await compiledDb.createClient();
|
|
|
180
180
|
_To be continued..._
|
|
181
181
|
|
|
182
182
|
## Roadmap
|
|
183
|
-
|
|
184
|
-
- [
|
|
185
|
-
- [
|
|
186
|
-
- [x] modify the query object so that on relations it is recursive
|
|
187
|
-
- [x] Make sure non-optional and non-array relations do not have the `SetNull` onDelete action on model compilation
|
|
188
|
-
- [x] Complete update action
|
|
189
|
-
- [x] Redo Mutation type. It should provide structurally no change:
|
|
190
|
-
- [x] Split `add` and `update` mutation until completely separate interfaces?
|
|
191
|
-
- [x] -Many or -All are only present on `ArrayRelation`'s,
|
|
192
|
-
- [x] Cannot use `delete` or `disconnect` on non-nullable (1-1) relations
|
|
193
|
-
- [x] Add additional functions to the storeInterface
|
|
194
|
-
- [x] get([primaryKey], [include/select])
|
|
195
|
-
- [x] update([primaryKey], [updateMutation without where])
|
|
196
|
-
- [x] Error Handling: Instead of needing to type `tx.abort(...)` just use the `throw new ...` syntax and catch the error and automatically abort the transaction. This will require actions to be wrapped in some kind of try-catch block.
|
|
197
|
-
- [x] Dump database to different formats:
|
|
198
|
-
- [x] JSON
|
|
199
|
-
- [x] CSV
|
|
200
|
-
- [x] Make package to wrap Tanstack query for react application
|
|
183
|
+
- [ ] Restore database to different formats
|
|
184
|
+
- [ ] JSON
|
|
185
|
+
- [ ] CSV
|
|
201
186
|
- [ ] Add extra object syntax to "where" clause (i.e. `in`/`ne`/`gt`/...)
|
|
202
187
|
- [ ] Allow object types in where clauses
|
|
203
|
-
- [x] Convert internal string unions to enums
|
|
204
188
|
- [ ] Make subpackages for adapters for different validation languages
|
|
205
189
|
- [x] Zod
|
|
206
190
|
- [ ] Yup
|
|
207
191
|
- [ ] Joi
|
|
208
192
|
- [ ] schema.js
|
|
209
|
-
- [x] Migrate to vite instead of rollup
|
|
210
193
|
|
|
211
194
|
### Roadmap - Maybe
|
|
212
195
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { CollectionObject } from '../model';
|
|
2
2
|
import { DbClient } from './index.ts';
|
|
3
|
-
import { FindInput, FindOutput } from './types/find
|
|
4
|
-
export declare class CompiledQuery<Stores extends string, Models extends CollectionObject<string>, Db extends DbClient<string, Stores, Models>, Input extends FindInput<Stores,
|
|
3
|
+
import { FindInput, FindOutput } from './types/find';
|
|
4
|
+
export declare class CompiledQuery<Stores extends string, Models extends CollectionObject<string>, Db extends DbClient<string, Stores, Models>, Input extends FindInput<Stores, Stores, Models> = FindInput<Stores, Stores, Models>, Output = FindOutput<Stores, Stores, Models, Input>> {
|
|
5
5
|
private readonly client;
|
|
6
6
|
private readonly name;
|
|
7
7
|
private readonly accessedStores;
|
package/dist/client/helpers.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Dict, Promisable } from '../util-types.js';
|
|
2
2
|
import { DbClient } from './index.ts';
|
|
3
|
-
import { QueryInput } from './types/find
|
|
3
|
+
import { QueryInput } from './types/find';
|
|
4
4
|
import { Transaction } from '../transaction.js';
|
|
5
5
|
import { CollectionObject } from '../model';
|
|
6
6
|
type WhereClauseElement = [key: string, isFun: true, fn: (value: unknown) => boolean] | [key: string, isFun: false, value: unknown];
|
|
@@ -14,5 +14,5 @@ export declare function generateWhereClause(where?: Dict): WhereClauseElement[];
|
|
|
14
14
|
export declare function parseWhere(whereArray: WhereClauseElement[], obj: unknown): boolean;
|
|
15
15
|
export declare function generateSelector<ModelNames extends string, Models extends CollectionObject<ModelNames>, Db extends DbClient<string, ModelNames, Models>, Q extends QueryInput<ModelNames, any, Models> = QueryInput<ModelNames, any, Models>>(name: ModelNames, client: Db, query?: Q, initTx?: Transaction<IDBTransactionMode, ModelNames>): (item: Dict, tx: Transaction<IDBTransactionMode, ModelNames>) => Promisable<Dict | undefined>;
|
|
16
16
|
export declare function getAccessedStores<ModelNames extends string, Models extends CollectionObject<ModelNames>>(name: ModelNames, query: Dict, isMutation: boolean, client: DbClient<string, ModelNames, Models>): Set<ModelNames>;
|
|
17
|
-
export declare function getSearchableQuery(q: QueryInput<
|
|
17
|
+
export declare function getSearchableQuery(q: QueryInput<string, any, any>): import('./types/find').SelectObject<string, any, any, 10>;
|
|
18
18
|
export {};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { Dec, Dict, Keyof, MakeRequired, NoUndefined, RecursionLimit, RemoveNeverValues, Simplify } from '../../util-types';
|
|
2
|
+
import { ModelStructure, RelationlessModelStructure, RelationValue } from '../../model/model-types';
|
|
3
3
|
import { Model, CollectionObject } from '../../model';
|
|
4
4
|
import { BaseRelation, PrimaryKey, RelationOutputStructure, ValidValue, Relation, Property } from '../../field';
|
|
5
5
|
export type FilterFn<Input> = (item: Input) => boolean;
|
|
@@ -7,23 +7,39 @@ export type FilterFn<Input> = (item: Input) => boolean;
|
|
|
7
7
|
* If an property is an object type (dictionary, array, map, set, etc...) return never. If it's a union it strips out any object types
|
|
8
8
|
*/
|
|
9
9
|
export type ProhibitObjects<T> = T extends Date ? Date : T extends object ? never : T;
|
|
10
|
+
type ModelFields<C, K extends keyof C> = C[K] extends Model<any, infer Fields, any> ? Fields : never;
|
|
10
11
|
export type WhereObject<Fields extends Dict<ValidValue>> = Partial<RemoveNeverValues<{
|
|
11
12
|
[K in keyof Fields]: Fields[K] extends Property<infer Output, any> ? ProhibitObjects<Output> | FilterFn<Output> : Fields[K] extends PrimaryKey<any, infer Type> ? ProhibitObjects<Type> | FilterFn<Type> : never;
|
|
12
13
|
}>>;
|
|
13
|
-
export type SelectObject<All extends string, Fields extends Dict<ValidValue>, C extends CollectionObject<All
|
|
14
|
-
[K in keyof Fields]?: Fields[K] extends Property<any, any> ? true : Fields[K] extends PrimaryKey<any, any> ? true : Fields[K] extends BaseRelation<infer To, any> ? true | (To extends Keyof<C> ? C[To] extends Model<any, infer SubFields, any> ? QueryInput<All, SubFields, C> : never : never) : never;
|
|
14
|
+
export type SelectObject<All extends string, Fields extends Dict<ValidValue>, C extends CollectionObject<All>, Depth extends number> = {
|
|
15
|
+
[K in keyof Fields]?: Fields[K] extends Property<any, any> ? true : Fields[K] extends PrimaryKey<any, any> ? true : Fields[K] extends BaseRelation<infer To, any> ? true | (To extends Keyof<C> ? C[To] extends Model<any, infer SubFields, any> ? QueryInput<All, SubFields, C, Depth> : never : never) : never;
|
|
15
16
|
};
|
|
16
|
-
export interface QueryInput<All extends string, Fields extends Dict<ValidValue>, C extends CollectionObject<All
|
|
17
|
+
export interface QueryInput<All extends string, Fields extends Dict<ValidValue>, C extends CollectionObject<All>, Depth extends number = RecursionLimit> {
|
|
17
18
|
where?: WhereObject<Fields>;
|
|
18
|
-
select?: SelectObject<All, Fields, C>;
|
|
19
|
-
include?: SelectObject<All, Fields, C>;
|
|
19
|
+
select?: SelectObject<All, Fields, C, Depth>;
|
|
20
|
+
include?: SelectObject<All, Fields, C, Depth>;
|
|
20
21
|
}
|
|
21
|
-
export type FindInput<All extends string,
|
|
22
|
-
type
|
|
23
|
-
|
|
22
|
+
export type FindInput<All extends string, To extends keyof C, C extends CollectionObject<All>, Depth extends number = RecursionLimit> = Depth extends 0 ? never : QueryInput<All, ModelFields<C, To>, C, Dec<Depth>>;
|
|
23
|
+
type NormalizeQuery<F> = F extends {
|
|
24
|
+
select: infer S;
|
|
25
|
+
} ? {
|
|
26
|
+
mode: "select";
|
|
27
|
+
value: S;
|
|
28
|
+
} : F extends {
|
|
29
|
+
include: infer I;
|
|
30
|
+
} ? {
|
|
31
|
+
mode: "include";
|
|
32
|
+
value: I;
|
|
33
|
+
} : {
|
|
34
|
+
mode: "none";
|
|
35
|
+
value: any;
|
|
24
36
|
};
|
|
25
|
-
type
|
|
26
|
-
[K in Keyof<
|
|
27
|
-
}
|
|
28
|
-
|
|
37
|
+
type _SelectOutput<All extends string, Select extends Dict<Dict | true>, Fields extends Dict<ValidValue>, C extends CollectionObject<All>, Depth extends number> = {
|
|
38
|
+
[K in Keyof<Select>]: Fields[K] extends BaseRelation<infer To, any> ? To extends keyof C ? Select[K] extends true ? RelationOutputStructure<Fields[K], RelationlessModelStructure<C[To]>> : Select[K] extends FindInput<All, To, C, Depth> ? RelationOutputStructure<Fields[K], FindOutput<All, To, C, Select[K]>> : never : never : Fields[K] extends PrimaryKey<any, infer Type> ? Type : Fields[K] extends Property<infer Type, any> ? Type : never;
|
|
39
|
+
};
|
|
40
|
+
type _IncludeOutput<All extends string, Include extends Record<Keys, Dict | true>, Fields extends Dict<ValidValue>, C extends CollectionObject<All>, Depth extends number, Keys extends Keyof<Fields> = Keyof<Fields>> = {
|
|
41
|
+
[K in Keys]: Fields[K] extends BaseRelation<infer To, any> ? To extends keyof C ? Include[K] extends true ? RelationOutputStructure<Fields[K], RelationlessModelStructure<C[To]>> : Include[K] extends FindInput<All, To, C, Depth> ? MakeRequired<Fields[K] extends Relation<any, any> ? true : false, NoUndefined<RelationOutputStructure<Fields[K], NoUndefined<FindOutput<All, To, C, Include[K]>>>>> : unknown : RelationOutputStructure<Fields[K], RelationValue<To, C>> : Fields[K] extends PrimaryKey<any, infer Type> ? Type : Fields[K] extends Property<infer Type, any> ? Type : never;
|
|
42
|
+
};
|
|
43
|
+
type _OutputFromQuery<Q extends NormalizeQuery<any>, Fields extends Dict<ValidValue>, All extends string, C extends CollectionObject<All>, Depth extends number> = Q["mode"] extends "none" ? ModelStructure<Fields, C> : Q["mode"] extends "select" ? _SelectOutput<All, Q["value"], Fields, C, Depth> : Q["mode"] extends "include" ? _IncludeOutput<All, Q["value"], Fields, C, Depth> : never;
|
|
44
|
+
export type FindOutput<All extends string, Name extends keyof C, C extends CollectionObject<All>, FIn extends FindInput<All, Name, C>, Depth extends number = RecursionLimit> = Depth extends 0 ? unknown : C[Name] extends Model<any, infer Fields, any> ? Simplify<_OutputFromQuery<NormalizeQuery<FIn>, Fields, All, C, Dec<Depth>>> | undefined : never;
|
|
29
45
|
export {};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Dict, Simplify } from '../../util-types.js';
|
|
2
2
|
import { ExtractFields, Model, ModelStructure, PrimaryKeyType, CollectionObject } from '../../model';
|
|
3
3
|
import { AddMutation, MutationAction, UpdateMutation } from './mutation.ts';
|
|
4
|
-
import { FindInput, FindOutput, WhereObject } from './find.
|
|
4
|
+
import { FindInput, FindOutput, WhereObject } from './find.js';
|
|
5
5
|
import { CompiledQuery } from '../compiled-query.ts';
|
|
6
6
|
import { DbClient } from '../index.ts';
|
|
7
7
|
import { Transaction } from '../../transaction.js';
|
|
@@ -12,15 +12,15 @@ export type ExportFormat = "json" | "csv";
|
|
|
12
12
|
export interface StoreInterface<Name extends Names, Names extends string, C extends CollectionObject<Names>, KeyType = PrimaryKeyType<C[Name]>, Add = AddMutation<Name, Names, C[Name], C>, Update extends UpdateMutation<Name, Names, C[Name], C> = UpdateMutation<Name, Names, C[Name], C>> {
|
|
13
13
|
add(mutation: Add, transaction?: Transaction<"readwrite", Names>): Promise<KeyType>;
|
|
14
14
|
addMany(mutations: Add[], transaction?: Transaction<"readwrite", Names>): Promise<KeyType[]>;
|
|
15
|
-
find<T extends FindInput<Names,
|
|
16
|
-
findFirst<T extends FindInput<Names,
|
|
15
|
+
find<T extends FindInput<Names, Name, C>>(query: T, transaction?: Transaction<IDBTransactionMode, Names>): Promise<NonNullable<FindOutput<Names, Name, C, T>>[]>;
|
|
16
|
+
findFirst<T extends FindInput<Names, Name, C>>(query: T, transaction?: Transaction<IDBTransactionMode, Names>): Promise<FindOutput<Names, Name, C, T>>;
|
|
17
17
|
update(key: KeyType, data: Update["data"]): Promise<GetStructure<Name, C>>;
|
|
18
18
|
updateFirst(item: Update, transaction?: Transaction<"readwrite", Names>): Promise<GetStructure<Name, C> | undefined>;
|
|
19
19
|
updateMany(item: Update, transaction?: Transaction<"readwrite", Names>): Promise<GetStructure<Name, C>[]>;
|
|
20
20
|
delete(key: KeyType): Promise<boolean>;
|
|
21
21
|
deleteFirst(where?: WhereObject<ExtractFields<C[Name]>>): Promise<boolean>;
|
|
22
22
|
deleteMany(where: WhereObject<ExtractFields<C[Name]>>): Promise<number>;
|
|
23
|
-
compileQuery<T extends FindInput<Names,
|
|
23
|
+
compileQuery<T extends FindInput<Names, Name, C>>(query: T): CompiledQuery<Names, C, DbClient<string, Names, C>, T>;
|
|
24
24
|
get(key: KeyType): Promise<GetStructure<Name, C> | undefined>;
|
|
25
25
|
dump<Format extends ExportFormat>(format: Format, where?: WhereObject<C[Name] extends Model<any, infer Fields, any> ? Fields : never>): Promise<Dump<Format>>;
|
|
26
26
|
}
|
|
@@ -1,31 +1,31 @@
|
|
|
1
|
-
import { MakeArrayable, MakeOptional, RemoveNeverValues, PartialOnUndefined, Extends, If, Or, Keyof } from '../../util-types
|
|
1
|
+
import { MakeArrayable, MakeOptional, RemoveNeverValues, PartialOnUndefined, Extends, If, Or, Keyof } from '../../util-types';
|
|
2
2
|
import { BaseRelation, Property, OptionalRelation, PrimaryKey, ArrayRelation } from '../../field';
|
|
3
|
-
import { WhereObject } from './find
|
|
3
|
+
import { WhereObject } from './find';
|
|
4
4
|
import { Model, FindRelationKey, RelationValue, CollectionObject } from '../../model';
|
|
5
5
|
export type MutationAction = "$connect" | "$connectMany" | "$create" | "$createMany" | "$update" | "$updateMany" | "$delete" | "$deleteMany" | "$deleteAll" | "$disconnect" | "$disconnectMany" | "$disconnectAll";
|
|
6
6
|
type WhereSelection<Struct extends object> = Struct extends Model<any, infer Fields, any> ? WhereObject<Fields> : never;
|
|
7
|
-
type _UpdateRelationMutation<This extends All, All extends string, C extends CollectionObject<All>, To extends All, Name extends string, Relation extends BaseRelation<To, Name>, ThisKey extends string, OmitKeys extends string, IsOptional extends boolean = Extends<Relation, OptionalRelation<any, any>>, IsArray extends boolean = Extends<Relation, ArrayRelation<any, any>>, IsNullable extends boolean = Or<IsOptional, IsArray
|
|
8
|
-
$connect:
|
|
7
|
+
type _UpdateRelationMutation<This extends All, All extends string, C extends CollectionObject<All>, To extends All, Name extends string, Relation extends BaseRelation<To, Name>, ThisKey extends string, OmitKeys extends string, IsOptional extends boolean = Extends<Relation, OptionalRelation<any, any>>, IsArray extends boolean = Extends<Relation, ArrayRelation<any, any>>, IsNullable extends boolean = Or<IsOptional, IsArray>, Value = RelationValue<To, C>, Dest extends C[To] = C[To]> = MakeOptional<IsNullable, MakeArrayable<IsArray, {
|
|
8
|
+
$connect: Value;
|
|
9
9
|
} | {
|
|
10
|
-
$create: Omit<AddMutation<To, All,
|
|
10
|
+
$create: Omit<AddMutation<To, All, Dest, C>, OmitKeys | FindRelationKey<This, Name, Dest>>;
|
|
11
11
|
} | {
|
|
12
|
-
$update: If<IsArray, UpdateMutation<To, All,
|
|
12
|
+
$update: If<IsArray, UpdateMutation<To, All, Dest, C, OmitKeys | ThisKey>, Omit<UpdateMutation<To, All, Dest, C>["data"], OmitKeys>>;
|
|
13
13
|
} | If<IsNullable, {
|
|
14
|
-
$delete: If<IsArray,
|
|
14
|
+
$delete: If<IsArray, Value, true>;
|
|
15
15
|
} | {
|
|
16
|
-
$disconnect: If<IsArray,
|
|
16
|
+
$disconnect: If<IsArray, Value, true>;
|
|
17
17
|
}, never>> | If<IsArray, {
|
|
18
|
-
$connectMany:
|
|
18
|
+
$connectMany: Value[];
|
|
19
19
|
} | {
|
|
20
|
-
$createMany: Omit<AddMutation<To, All,
|
|
20
|
+
$createMany: Omit<AddMutation<To, All, Dest, C>, OmitKeys | FindRelationKey<This, Name, Dest>>[];
|
|
21
21
|
} | {
|
|
22
|
-
$updateMany: UpdateMutation<To, All,
|
|
22
|
+
$updateMany: UpdateMutation<To, All, Dest, C, OmitKeys | ThisKey>[];
|
|
23
23
|
} | {
|
|
24
|
-
$deleteMany:
|
|
24
|
+
$deleteMany: Value[];
|
|
25
25
|
} | {
|
|
26
26
|
$deleteAll: true;
|
|
27
27
|
} | {
|
|
28
|
-
$disconnectMany:
|
|
28
|
+
$disconnectMany: Value[];
|
|
29
29
|
} | {
|
|
30
30
|
$disconnectAll: true;
|
|
31
31
|
}, never>>;
|
|
@@ -35,15 +35,16 @@ export type UpdateMutation<This extends All, All extends string, Struct extends
|
|
|
35
35
|
[K in Exclude<Keyof<Fields>, OmitKeys>]: Fields[K] extends Property<infer Type, any> ? Type | undefined | ((value: Type) => Type) : Fields[K] extends PrimaryKey<any, any> ? never : Fields[K] extends BaseRelation<infer To, infer Name> ? To extends All ? _UpdateRelationMutation<This, All, C, To, Name, Fields[K], K, OmitKeys> | undefined : never : never;
|
|
36
36
|
} : never>>;
|
|
37
37
|
};
|
|
38
|
+
type AddMutationRelation<This extends All, All extends string, C extends CollectionObject<All>, To extends All, RelationName extends string, Relation extends BaseRelation<any, any>, IsArray extends boolean = Extends<Relation, ArrayRelation<any, any>>, Value = RelationValue<To, C>> = MakeOptional<Or<IsArray, Extends<Relation, OptionalRelation<any, any>>>, MakeArrayable<IsArray, {
|
|
39
|
+
$connect: Value;
|
|
40
|
+
} | {
|
|
41
|
+
$create: Omit<AddMutation<To, All, C[To], C>, FindRelationKey<This, RelationName, C[To]>>;
|
|
42
|
+
}> | If<IsArray, {
|
|
43
|
+
$connectMany: Value[];
|
|
44
|
+
} | {
|
|
45
|
+
$createMany: Omit<AddMutation<To, All, C[To], C>, FindRelationKey<This, RelationName, C[To]>>[];
|
|
46
|
+
}, never>>;
|
|
38
47
|
export type AddMutation<This extends All, All extends string, Struct extends object, C extends CollectionObject<All>> = PartialOnUndefined<RemoveNeverValues<Struct extends Model<any, infer Fields, any> ? {
|
|
39
|
-
[K in keyof Fields]: Fields[K] extends Property<infer Type, infer HasDefault> ? HasDefault extends true ? Type | undefined : Type : Fields[K] extends PrimaryKey<infer IsAuto, infer Type> ? IsAuto extends true ? never : Type : Fields[K] extends BaseRelation<infer To, infer Name> ? To extends All ?
|
|
40
|
-
$connect: RelationValue<To, C>;
|
|
41
|
-
} | {
|
|
42
|
-
$create: Omit<AddMutation<To, All, C[To], C>, FindRelationKey<This, Name, C[To]>>;
|
|
43
|
-
}> | (Fields[K] extends ArrayRelation<any, any> ? {
|
|
44
|
-
$connectMany: RelationValue<To, C>[];
|
|
45
|
-
} | {
|
|
46
|
-
$createMany: Omit<AddMutation<To, All, C[To], C>, FindRelationKey<This, Name, C[To]>>[];
|
|
47
|
-
} : never)> : never : never;
|
|
48
|
+
[K in keyof Fields]: Fields[K] extends Property<infer Type, infer HasDefault> ? HasDefault extends true ? Type | undefined : Type : Fields[K] extends PrimaryKey<infer IsAuto, infer Type> ? IsAuto extends true ? never : Type : Fields[K] extends BaseRelation<infer To, infer Name> ? To extends All ? AddMutationRelation<This, All, C, To, Name, Fields[K]> : never : never;
|
|
48
49
|
} : never>>;
|
|
49
50
|
export {};
|
package/dist/core.d.ts
CHANGED
package/dist/error.d.ts
CHANGED
|
@@ -6,7 +6,7 @@ export type ErrorType = "ID_EXISTS" | "INVALID_ITEM" | "ADD_FAILED" | "UPDATE_FA
|
|
|
6
6
|
/**
|
|
7
7
|
* The database is not found
|
|
8
8
|
*/
|
|
9
|
-
| "NO_DB" | "CUSTOM" | "INVALID_CONFIG" | "ASSERTION_FAILED" | "IMPORT_FAILED" | "OPEN_CURSOR" | "UNKNOWN";
|
|
9
|
+
| "NO_DB" | "CUSTOM" | "INVALID_CONFIG" | "ASSERTION_FAILED" | "IMPORT_FAILED" | "OPEN_CURSOR" | "SERIALIZATION_FAILED" | "DESERIALIZATION_FAILED" | "UNKNOWN";
|
|
10
10
|
export declare class StoreError extends Error {
|
|
11
11
|
readonly code: ErrorType;
|
|
12
12
|
constructor(code: ErrorType, message: string);
|
|
@@ -236,3 +236,33 @@ export declare const ImportError: {
|
|
|
236
236
|
prepareStackTrace(err: Error, stackTraces: NodeJS.CallSite[]): any;
|
|
237
237
|
stackTraceLimit: number;
|
|
238
238
|
};
|
|
239
|
+
export declare const SerializationError: {
|
|
240
|
+
new (message?: string): {
|
|
241
|
+
readonly code: ErrorType;
|
|
242
|
+
name: string;
|
|
243
|
+
message: string;
|
|
244
|
+
stack?: string;
|
|
245
|
+
cause?: unknown;
|
|
246
|
+
};
|
|
247
|
+
readonly code: "SERIALIZATION_FAILED";
|
|
248
|
+
of(message: string): void;
|
|
249
|
+
isError(error: unknown): error is Error;
|
|
250
|
+
captureStackTrace(targetObject: object, constructorOpt?: Function): void;
|
|
251
|
+
prepareStackTrace(err: Error, stackTraces: NodeJS.CallSite[]): any;
|
|
252
|
+
stackTraceLimit: number;
|
|
253
|
+
};
|
|
254
|
+
export declare const DeserializationError: {
|
|
255
|
+
new (message?: string): {
|
|
256
|
+
readonly code: ErrorType;
|
|
257
|
+
name: string;
|
|
258
|
+
message: string;
|
|
259
|
+
stack?: string;
|
|
260
|
+
cause?: unknown;
|
|
261
|
+
};
|
|
262
|
+
readonly code: "DESERIALIZATION_FAILED";
|
|
263
|
+
of(message: string): void;
|
|
264
|
+
isError(error: unknown): error is Error;
|
|
265
|
+
captureStackTrace(targetObject: object, constructorOpt?: Function): void;
|
|
266
|
+
prepareStackTrace(err: Error, stackTraces: NodeJS.CallSite[]): any;
|
|
267
|
+
stackTraceLimit: number;
|
|
268
|
+
};
|
|
@@ -21,7 +21,7 @@ export declare const enum FieldTypes {
|
|
|
21
21
|
PrimaryKey = 2,
|
|
22
22
|
Invalid = 3
|
|
23
23
|
}
|
|
24
|
-
export type GenFunction<T extends ValidKey> = () => T;
|
|
24
|
+
export type GenFunction<T extends ValidKey> = (...args: unknown[]) => T;
|
|
25
25
|
export type FunctionMatch<E> = E extends "string" ? string : E extends "number" ? number : E extends "date" ? Date : never;
|
|
26
26
|
export type GetPrimaryKeyType<T> = T extends PrimaryKey<any, infer Type> ? Type : never;
|
|
27
27
|
export interface FieldOptions {
|
package/dist/index.cjs.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});class e extends Error{code;constructor(e,t){super(`(${e}) ${t}`),this.code=e}}function t(t,n){return class extends e{static code;constructor(e=n){super(t,e)}static of(e){new this(e)}}}const n=t("INVALID_CONFIG","Configuration is invalid"),r=t("INVALID_TX","Transaction is invalid"),s=t("INVALID_ITEM","Item is invalid"),o=t("ASSERTION_FAILED","Assertion failed"),a=t("UNKNOWN","An unknown error occurred"),i=t("DELETE_FAILED","Item could not be deleted"),c=t("NOT_FOUND","Object Store Not Found"),u=t("NOT_FOUND","Document Not Found"),l=t("UPDATE_FAILED","Item could not be updated"),d=t("ADD_FAILED","Item could not be added"),y=t("OPEN_CURSOR","Cursor could not be opened"),f=t("GET_FAILED","Item could not be retrieved"),h=t("OVERWRITE_RELATION","Relation cannot be overwritten"),w=t("EXPORT","Export failed");function p(e,t){return new Promise(t=>{e.onsuccess=()=>{t(e.result)},e.onerror=()=>{}})}function m(e){return Object.keys(e)}function g(e){return Array.isArray(e)||(e=[e]),e}function b(){return crypto.randomUUID()}function S(){return new Date}function A(e){return e}function v(e,t){for(const n of t.keys())e.add(n);return e}var $=(e=>(e[e.string=0]="string",e[e.number=1]="number",e[e.date=2]="date",e[e.boolean=3]="boolean",e[e.symbol=4]="symbol",e[e.bigint=5]="bigint",e[e.file=6]="file",e[e.void=7]="void",e[e.unknown=8]="unknown",e[e.literal=9]="literal",e[e.array=10]="array",e[e.set=11]="set",e[e.union=12]="union",e[e.optional=13]="optional",e[e.default=14]="default",e[e.object=15]="object",e[e.custom=16]="custom",e))($||{});const k={};function R(e){const t=k[e];return t||(k[e]={tag:e})}function O(){return R($.string)}function j(){return R($.number)}function K(){return R($.boolean)}function N(){return R($.bigint)}function M(){return R($.symbol)}function D(){return R($.file)}function T(){return R($.date)}function x(){return R($.unknown)}function E(e){return{tag:$.literal,value:e}}function I(e){return{tag:$.array,of:e}}function P(e,t){return{tag:$.default,of:e,value:t}}function _(e){return{tag:$.set,of:e}}function F(e){return{tag:$.union,options:e}}function L(e){return{tag:$.optional,of:e}}function C(e){return{tag:$.custom,...e}}const B=Object.freeze(Object.defineProperty({__proto__:null,Array:I,BigInt:N,Boolean:K,Custom:C,Date:T,Default:P,File:D,Literal:E,Number:j,Object:function(e){return{tag:$.object,props:e}},Optional:L,Set:_,String:O,Symbol:M,Union:F,Unknown:x,Void:function(){return R($.void)},getType:R},Symbol.toStringTag,{value:"Module"}));function V(e){switch(e.tag){case $.void:return"void";case $.literal:return String(e.value);case $.boolean:return"boolean";case $.number:return"number";case $.bigint:return"bigint";case $.string:return"string";case $.symbol:return"symbol";case $.unknown:return"unknown";case $.date:return"Date";case $.array:return`Array<${V(e.of)}>`;case $.set:return`Set<${V(e.of)}>`;case $.default:case $.optional:return`${V(e.of)} | undefined`;case $.union:return`Union<${e.options.map(e=>V(e)).join(", ")}>`;case $.file:return"File";case $.object:return`{${Object.keys(e.props).map(t=>`${t}: ${V(e.props[t])}`).join(",\n")}}`;case $.custom:return"custom"}}async function q(e,t){if(!G(e,t))throw new Error(`Value not of the proper type, expected type '${V(e)}', received '${JSON.stringify(t)}'`);switch(e.tag){case $.literal:case $.boolean:case $.number:case $.string:return t;case $.void:return;case $.bigint:return Number(t);case $.symbol:return t.description;case $.unknown:return JSON.stringify(t);case $.date:return t.getTime();case $.array:{const n=[];for(const r of t)n.push(q(e.of,r));return await Promise.all(n)}case $.set:{const n=[];for(const r of t.keys())n.push(q(e.of,r));return await Promise.all(n)}case $.optional:if(void 0===t)return;return await q(e.of,t);case $.union:for(const n of e.options)try{return await q(n,t)}catch{}throw new Error("Value union could not be serialized");case $.file:if(!(t instanceof File))throw new Error("Value is not a valid file");return{data:new Promise((e,n)=>{const r=new FileReader;r.onload=()=>e(r.result),r.onerror=n,r.readAsDataURL(t)}),name:t.name,type:t.type};case $.object:{const n={};for(const r in e.props){const s=e.props[r];if(!(r in t)&&s.tag!==$.optional&&s.tag!==$.default&&s.tag!==$.void)throw new Error(`Required property '${r}' not found`);n[r]=await q(s,t[r])}return n}case $.default:return await q(e.of,void 0===t?"function"==typeof e.value?e.value():e.value:t);case $.custom:return e.serialize?await e.serialize(t):JSON.stringify(t)}}async function U(e,t){switch(e.tag){case $.void:return;case $.literal:if(t!==e.value)throw new Error(`'${t}' is not equal to literal '${t}'`);return t;case $.boolean:if("boolean"!=typeof t)throw new Error(`'${t}' is not a boolean`);return t;case $.number:if("number"!=typeof t||isNaN(t))throw new Error(`'${t}' is not a number`);return t;case $.bigint:if("number"!=typeof t||isNaN(t))throw new Error(`'${t}' is not a bigint`);return BigInt(t);case $.string:if("string"!=typeof t)throw new Error(`'${t}' is not a string`);return t;case $.symbol:if("string"!=typeof t)throw new Error(`'${t}' is not a symbol`);return Symbol.for(t);case $.date:if("number"!=typeof t||isNaN(t))throw new Error(`'${t}' is not a date timestamp`);return new Date(t);case $.array:{if(!Array.isArray(t))throw new Error(`'${t}' is not an array`);const n=[];for(const r of t)n.push(U(e.of,r));return await Promise.all(n)}case $.set:{if(!Array.isArray(t))throw new Error(`'${t}' is not an array`);const n=[];for(const r of t)n.push(U(e.of,r));return new Set(await Promise.all(n))}case $.optional:if(void 0===t)return;return U(e.of,t);case $.unknown:return"string"!=typeof t?t:JSON.parse(t);case $.union:for(const n of e.options)try{return await U(n,t)}catch{}throw new Error("Value did not match the union");case $.file:{if(!(t&&"object"==typeof t&&"data"in t&&"name"in t&&"type"in t&&"string"==typeof t.data&&"string"==typeof t.name&&"string"==typeof t.type))throw new Error("Value is not a valid file schema");const e=Buffer.from(t.data.replace(/^data:.+;base64,/,""),"base64");return new File([e],t.name,{type:t.type})}case $.default:return void 0===t?e.value:U(e.of,t);case $.custom:if(e.isType(t))return e.deserialize?await e.deserialize(t):JSON.parse(String(t));throw new Error("Value is not valid");case $.object:{if(!t||"object"!=typeof t)throw new Error("Value is not an object");const n={};for(const r in e.props){const s=e.props[r];if(!(r in t)&&s.tag!==$.optional)throw new Error(`Required property '${r}' not found`);n[r]=await U(s,t[r])}return n}}}function z(e,t){switch(e.tag){case $.literal:return t.tag===$.literal&&t.value===e.value;case $.boolean:case $.number:case $.symbol:case $.string:case $.bigint:return t.tag===e.tag||t.tag===$.literal&&typeof t.value===V(e);case $.unknown:return!0;case $.date:case $.file:case $.void:return t.tag===e.tag;case $.optional:case $.default:case $.set:case $.array:return t.tag===e.tag&&z(e.of,t.of);case $.union:if(t.tag===$.union){for(const n of t.options)if(!z(e,n))return!1;return!0}return e.options.some(e=>z(e,t));case $.object:if(t.tag!==$.object)return!1;for(const n in t.props){if(!e.props[n])return!1;if(!z(e.props[n],t.props[n]))return!1}return!0;case $.custom:return e===t}}function G(e,t){switch(e.tag){case $.void:return void 0===t;case $.literal:return t===e.value;case $.boolean:return"boolean"==typeof t;case $.number:return"number"==typeof t;case $.bigint:return"bigint"==typeof t;case $.string:return"string"==typeof t;case $.symbol:return"symbol"==typeof t;case $.unknown:return!0;case $.date:return t instanceof Date&&!isNaN(t.getTime());case $.array:return Array.isArray(t)&&t.every(t=>G(e.of,t));case $.set:return t instanceof Set&&Array.from(t).every(t=>G(e.of,t));case $.optional:case $.default:return void 0===t||G(e.of,t);case $.union:return e.options.some(e=>G(e,t));case $.file:return t instanceof File;case $.object:return!(!t||"object"!=typeof t)&&Object.keys(e.props).every(n=>G(e.props[n],t[n]));case $.custom:return e.isType(t)}}function Y(e,t){if(G(e,t)){switch(e.tag){case $.custom:if(e.parse)try{return{success:!0,data:e.parse(t)}}catch(n){return{success:!1,error:String(n)}}break;case $.default:return void 0===t?{success:!0,data:e.value}:{success:!0,data:t}}return{success:!0,data:t}}return{success:!1,error:`Value is not a valid '${V(e)}'`}}const J=Object.freeze(Object.defineProperty({__proto__:null,Tag:$,Type:B,deserializeType:U,isSubtype:z,isType:G,parseType:Y,serializeType:q,typeToString:V},Symbol.toStringTag,{value:"Module"})),W=Symbol.for("primaryKey");class H{symbol=W;genFn;autoGenerate;type;constructor(e,t){if(e){if(e.tag>$.date)throw new n("Invalid Primary Key Type");this.type=e,t?(this.autoGenerate=!0,this.genFn=t):this.autoGenerate=!1}else this.autoGenerate=!1,this.type=j()}getType(){return this.type}generator(e){return this.genFn=e,this.autoGenerate=!0,this}autoIncrement(){if(this.type.tag===$.number)return this.genFn=void 0,this.autoGenerate=!0,this;throw new n("Primary key must be a number to use autoIncrement()")}uuid(){if(!window.isSecureContext)throw new Error("Window is not in a secure context");return new H(O(),b)}date(){return new H(T(),S)}genKey(){if(this.genFn)return this.genFn();throw new Error("Generator function not defined")}isAutoIncremented(){return this.autoGenerate&&!this.genFn}static is(e){return e?.symbol===W}static compareKeyValue(e,t){if(typeof e!=typeof t)return!1;switch(typeof e){case"string":case"number":return e===t;case"object":return e.getTime()===t.getTime();default:return!1}}static validKeyTag=F([O(),j(),T()])}class Q{constructor(e,t="",n=!1,r=!1,s){this.to=e,this.name=t,this.isOptional=n,this.isArray=r,this.relatedKey="",this.actions={onDelete:s||"Restrict"}}static SYMBOL=Symbol.for("baseRelation");BASE_SYMBOL=Q.SYMBOL;actions;relatedKey;getActions(){return{...this.actions}}isNullable(){return this.isArray||this.isOptional}setRelatedKey(e){this.relatedKey=e}getRelatedKey(){return this.relatedKey}toString(){return`${this.isArray?"Array":this.isOptional?"Optional":"Standard"} relation from this model to model '${this.to}' on key '${this.relatedKey}'`}getBaseSymbol(){return this.BASE_SYMBOL}static is(e){return"getBaseSymbol"in e&&e.getBaseSymbol()===Q.SYMBOL}}class X extends Q{static R_SYMBOL=Symbol.for("relation");symbol=X.R_SYMBOL;constructor(e,t={}){super(e,t.name,!1,!1,t.onDelete)}array({onDelete:e}={}){return new Z(this.to,this.name,e)}optional({onDelete:e}={}){return new ee(this.to,this.name,e)}onDelete(e){return this.actions.onDelete=e,this}static is(e){return e?.symbol===this.R_SYMBOL}}class Z extends Q{static A_SYMBOL=Symbol.for("arrayRelation");symbol=Z.A_SYMBOL;constructor(e,t,n="None"){super(e,t,!1,!0,n)}static is(e){return e?.symbol===this.A_SYMBOL}}class ee extends Q{static O_SYMBOL=Symbol.for("optionalRelation");symbol=ee.O_SYMBOL;constructor(e,t,n="None"){super(e,t,!0,!1,n)}static is(e){return e?.symbol===this.O_SYMBOL}}var te=(e=>(e[e.Property=0]="Property",e[e.Relation=1]="Relation",e[e.PrimaryKey=2]="PrimaryKey",e[e.Invalid=3]="Invalid",e))(te||{});const ne=Symbol.for("property");class re{constructor(e,t){this.type=e,this.options={unique:t?.unique??!1}}symbol=ne;hasDefault=!1;options;unique(){switch(this.type.tag){case $.boolean:case $.string:case $.number:case $.symbol:return this.options.unique=!0,this;default:throw new Error("A non-primitive cannot be a unique value")}}hasDefaultValue(){return this.hasDefault}static relation(e,t){return new X(e,t)}static primaryKey(e="number"){return new H(this.nameToType(e))}static nameToType(e){switch(e){case"boolean":return K();case"bigint":return N();case"number":return j();case"string":return O();case"symbol":return M();default:return x()}}static is(e){return"object"==typeof e&&e?.symbol===ne}array(){return new re(I(this.type),this.options)}default(e){return this.hasDefault=!0,new re(P(this.type,e),this.options)}optional(){return new re(L(this.type),this.options)}static array(e,t){return new re(I(e.type),t)}static boolean(e){return new re(K(),e)}static custom(e,t){return new re(C({isType:t=>e(t).success,serialize:t?.serialize,deserialize:t?.deserialize}),t)}static date(e){return new re(T(),e)}static file(e){return new re(D(),e)}static literal(e,t){return new re(E(e),t)}static number(e){return new re(j(),e)}static string(e){return new re(O(),e)}static set(e,t){return new re(_(e.type),t)}static union(e,t){return new re(F(e.map(e=>e.type)),t)}static generateArrayValidator(e){return t=>{if(Array.isArray(t)){const n=[];for(const r of t){const t=e(r);if(!t.success)return t;n.push(t.data)}return{success:!0,data:n}}return{success:!1,error:"Value is not an array"}}}}const se=Symbol.for("model");class oe{constructor(t,n){this.name=t,this.fields=n,this.fieldKeys=m(n);for(const e of this.fieldKeys){const t=this.fields[e];Q.is(t)&&t.to!==this.name&&this.relationLinks.add(t.to)}const r=this.fieldKeys.find(e=>H.is(this.fields[e]));if(!r)throw new e("INVALID_CONFIG",`Model ${this.name} has no primary key`);this.primaryKey=r}symbol=se;fieldKeys;relationLinks=new Set;cache={};primaryKey;get(e){return this.fields[e]}getPrimaryKey(){return this.fields[this.primaryKey]}getRelation(e){const t=this.fields[e];if(t&&Q.is(t))return t}keyType(e){const t=this.fields[e];return t?re.is(t)?te.Property:Q.is(t)?te.Relation:H.is(t)?te.PrimaryKey:te.Invalid:te.Invalid}links(){return this.relationLinks.keys()}*relations(){for(const e of this.fieldKeys)Q.is(this.fields[e])&&(yield[e,this.fields[e]])}*entries(){for(const e of this.fieldKeys)yield[e,this.fields[e]]}keys(){return this.fieldKeys}parseField(e,t){return re.is(this.fields[e])?Y(this.fields[e].type,t):null}getDeletedStores(e){if(this.cache.delete)return this.cache.delete;const t=new Set,n=[this.name];let r;for(;n.length>0;){const s=n.shift();if(t.has(s))continue;r=e.getModel(s);const o=r.cache.delete;if(o)v(t,o);else{t.add(s);for(const e of r.links())t.has(e)||n.push(e)}}return this.cache.delete=t,t}static is(e){return e?.symbol===se}}class ae{constructor(e,t){this.tx=e,this.internal=t}add(e){return this.handleRequest(this.internal.add(e),()=>new d)}get(e){return this.handleRequest(this.internal.get(e),()=>new f)}async assertGet(e){const t=await this.handleRequest(this.internal.get(e),()=>new f);if(!t)throw this.tx.abort(new u);return t}put(e){return this.handleRequest(this.internal.put(e),()=>new l)}delete(e){return this.handleRequest(this.internal.delete(e),()=>new i)}async openCursor(t,n={}){const r=n.onError||(()=>new y),s=this.internal.openCursor(n.query,n.direction);await new Promise((n,o)=>{s.onsuccess=async s=>{try{s.target||o(this.tx.abort(r()));const e=s.target.result;e&&await t(e,this.tx)||n()}catch(i){o(this.tx.abort(i instanceof e?i:new a(String(i))))}},s.onerror=()=>{o(this.tx.abort(r()))}})}handleRequest(e,t){return new Promise(n=>{e.onsuccess=()=>{n(e.result)},e.onerror=()=>{throw this.tx.abort(t())}})}}class ie{internal;status;error=null;storeNames;inWrap=!1;onRejection=t=>{throw t instanceof e?this.abort(t):this.abort(new a(String(t)))};objectStores;constructor(e,t,n,r={}){e instanceof ie?(this.internal=e.getInternal(),this.storeNames=e.storeNames,this.status=e.status,this.error=e.error,this.objectStores=e.getAllStores()):(this.internal=e.transaction(t,n),this.status=0,this.storeNames=Array.from(this.internal.objectStoreNames),this.objectStores=new Map(this.storeNames.map(e=>[e,this.getObjectstore(e)])),this.internal.onabort=this.registerHandler(1,r.onAbort),this.internal.onerror=this.registerHandler(3,r.onError),this.internal.oncomplete=this.registerHandler(2,r.onComplete))}static create(e,t,n,r){return r||new ie(e,t,n)}abort(e){return 1!==this.status&&this.internal.abort(),this.status=1,this.error=e,this.error}commit(){this.internal.commit()}getInternal(){return this.internal}getStore(e){const t=this.objectStores.get(e);if(!t)throw this.abort(new r(`Store '${e}' is not a part of this transaction`));return t}getAllStores(){return this.objectStores}get mode(){return this.internal.mode}is(e){return this.status===e}contains(e){Array.isArray(e)||(e=[e]);for(const t of e)if(!this.internal.objectStoreNames.contains(t))return!1;return!0}assertIsArray(e,t="Value is not an array"){if(!Array.isArray(e))throw this.abort(new o(t))}getObjectstore(e){try{return new ae(this,this.internal.objectStore(e))}catch{throw this.abort(new c(`No ObjectStore with the name '${e}' found`))}}registerHandler(e,t=()=>{}){return n=>{this.status=e,t(this,n)}}async wrap(t){if(this.inWrap)return await t(this);this.inWrap=!0;try{const e=await t(this);return this.inWrap=!1,e}catch(n){throw this.inWrap=!1,n instanceof e?this.abort(n):this.abort(new a(JSON.stringify(n)))}}}function ce(e){if(!e)return[];const t=[];for(const n in e)if(Object.hasOwn(e,n))switch(typeof e[n]){case"function":t.push([n,!0,e[n]]);break;case"object":if(e[n]instanceof Date){const r=e[n];t.push([n,!0,e=>e instanceof Date&&e.getTime()===r.getTime()])}break;default:t.push([n,!1,e[n]])}return t}function ue(e,t){if(!t||"object"!=typeof t)return!1;for(const n of e)if(n[1]){if(!n[2](t[n[0]]))return!1}else if(n[2]!==t[n[0]])return!1;return!0}function le(e,t,n={},r){const o=t.getModel(e);if(n.include&&n.select)throw new s("include and select cannot both be defined");const a=ce(n.where),i=n.select?"select":n.include?"include":"";if(i){const e=n[i],r=!!n.select,s=[];for(const n in e)if(Object.hasOwn(e,n)&&e[n])switch(o.keyType(n)){case te.Relation:{const r=o.getRelation(n),a="object"==typeof e[n]?le(r.to,t,e[n]):A,i=r.getRelatedKey();if(r.isArray){const e=async(e,t)=>{const n=[],s=t.getStore(r.to);for(const r of e){const e=await a(await s.assertGet(r),t);e&&(delete e[i],n.push(e))}return n};s.push({key:n,getValue:e})}else{const e=async(e,t)=>await a(await t.getStore(r.to).assertGet(e),t);s.push({key:n,getValue:e})}break}case te.Property:case te.PrimaryKey:r&&s.push({key:n})}return r?async(e,t)=>{if(!ue(a,e))return;const n={};for(const{key:r,getValue:o}of s)n[r]=o?await o(e[r],t):e[r];return n}:async(e,t)=>{if(ue(a,e)){for(const{key:n,getValue:r}of s)e[n]=await r(e[n],t);return e}}}return e=>ue(a,e)?e:void 0}function de(e,t,n,r){const s=new Set([e]);if(n){const o=r.getModel(e);for(const e in t){const a=o.getRelation(e),i=g(t[e]);if(a)for(const e of i)if(e&&"object"==typeof e)for(const t in e)if(Object.hasOwn(e,t))switch(t){case"$connect":case"$connectMany":case"$disconnect":case"$disconnectMany":case"$disconnectAll":s.add(a.to);break;case"$delete":case"$deleteMany":case"$deleteAll":v(s,o.getDeletedStores(r));break;case"$create":v(s,de(a.to,e[t],n,r));break;case"$createMany":e[t].forEach(e=>v(s,de(a.to,e,n,r)));break;case"$update":v(s,de(a.to,e[t].data,n,r));break;case"$updateMany":e[t].forEach(e=>v(s,de(a.to,e.data,n,r)))}}}else{const n=r.getModel(e);for(const e in t){const o=n.getRelation(e);if(o)switch(typeof t[e]){case"object":v(s,de(o.to,ye(t[e]),!1,r));break;case"boolean":s.add(o.to)}}}return s}function ye(e){return e.select?e.select:e.include?e.include:{}}class fe{constructor(e,t,n){this.client=e,this.name=t,this.accessedStores=Array.from(de(t,ye(n),!1,this.client)),this.selectClause=le(t,this.client,n)}accessedStores;selectClause;async find(){return await this._find(!1)}async findFirst(){return(await this._find(!0))[0]}async _find(e){const t=this.client.createTransaction("readonly",this.accessedStores);return await t.wrap(async t=>{const n=[],r=t.getStore(this.name);return await r.openCursor(async r=>{const s=await this.selectClause(r.value,t);return s&&n.push(s),(!e||!n.length)&&(r.continue(),!0)}),n})}}function he(e,t,r){return async s=>{if(!s)return!1;const o=s[e.primaryKey];for(const[a,c]of e.relations()){const{onDelete:u}=c.getActions(),l=s[a],d=t.getModel(c.to);switch(u){case"Cascade":if(c.isArray){r.assertIsArray(l);const e=new Set(l),n=he(d,t,r),s=r.getStore(c.to);await s.openCursor(async t=>(e.has(t.value[d.primaryKey])&&await n(t.value),t.continue(),!0)).catch(r.onRejection)}else l&&await we(c.to,t,void 0,void 0,{tx:r,singleton:{id:l}});break;case"SetNull":{if(!l)break;const e=g(l),t=r.getStore(c.to),s=c.getRelatedKey(),a=d.getRelation(s);if(!a)throw new n(`Relation '${c.name}' has an invalid relation key '${c.getRelatedKey()}'`);if(!a.isNullable())throw new n(`Key '${s}' on model '${s}': Non-optional relation cannot have the 'SetNull' action`);for(const n of e){const e=await t.get(n);if(!e)continue;const i=e[s];if(a.isArray){r.assertIsArray(i);const e=i.indexOf(o);if(-1===e)continue;i.splice(e,1)}else e[s]=null;await t.put(e)}break}case"Restrict":if(Array.isArray(l)&&l.length>0||l)throw new i(`Key '${a}' on model '${e.name}' deletion is restricted while there is an active relation`)}}return!0}}async function we(e,t,n,r=!1,s={}){const{singleton:o,finalStep:a=!0}=s,i=t.getModel(e),c=s.tx?s.tx.storeNames:Array.from(i.getDeletedStores(t)),u=ie.create(t.getDb(),c,"readwrite",s.tx);return await u.wrap(async s=>{const c=s.getStore(e);let u=0;const l=he(i,t,s);if(o)await l(await c.assertGet(o.id))&&(await c.delete(o.id),u++);else{const e=ce(n);let t;await c.openCursor(async n=>{const o=n.value;return ue(e,o)&&await l(o)&&(t=p(n.delete()).catch(s.onRejection)),!(r&&u>0)&&(n.continue(),!0)}),t&&a&&await t}return u})}function pe(e){return"string"!=typeof e?String(e):e.replaceAll(/~|\//g,e=>"~"===e?"~0":"~1")}async function me(e,t,n,r){r=ie.create(e.getDb(),[t],"readonly",r);const s=ce(n),a=e.getModel(t);return await r.wrap(async e=>{const n={};return await e.getStore(t).openCursor(async e=>{if(ue(s,e.value)){for(const[t,n]of a.entries())if(Q.is(n))if(n.isArray){if(!Array.isArray(e.value[t]))throw new o("Expected array type");const r=[];for(const s of e.value[t])r.push(`/${n.to}/${pe(s)}`);e.value[t]=r}else(n.isOptional&&e.value[t]||!n.isNullable())&&(e.value[t]=`/${n.to}/${pe(e.value[t])}`);else{if(!re.is(n)&&!H.is(n))throw new w(`Unrecognized model field on key '${t}'`);e.value[t]=await q(n.type,e.value[t])}if(n[e.value[a.primaryKey]])throw new w("Duplicate primary key detected "+JSON.stringify(n));n[e.value[a.primaryKey]]=e.value}return e.continue(),!0}),n})}function ge(e,t){const n=[`## ${e.name}`],r=[];for(const[s,o]of e.entries())H.is(o)?r.unshift(s):r.push(s);n.push(r.join(","));for(const s of Object.values(t)){const e=[];for(const t of r)switch(typeof s[t]){case"object":e.push(JSON.stringify(s[t]));break;case"undefined":e.push("");break;default:e.push(String(s[t]))}n.push(e.join(","))}return n.join("\n")}class be{constructor(e,t,n){this.name=e,this.content=t,this.extension=n}toFile(e=`${this.name}_dump.${this.extension}`,t){return new File([this.content],e,t)}download(e=`${this.name}_dump.${this.extension}`,t){const n=URL.createObjectURL(this.toFile(e,t)),r=document.createElement("a");r.href=n,r.download=e,document.body.appendChild(r),r.click(),document.body.removeChild(r),URL.revokeObjectURL(n)}static toJson(e,t,n){return new this(e,JSON.stringify(t,void 0,n?.pretty??1?4:void 0),"json")}static toCsvStore(e,t){return new this(e.name,ge(e,t),"csv")}static toCsvDb(e,t,n){const r=[`# ${e.name}`];for(const s of t)r.push(ge(e.getModel(s),n[s]));return new this(e.name,r.join("\n"),"csv")}}class Se{constructor(e,t){this.db=e,this.models=t,this.name=this.db.name,this.version=this.db.version,this.stores={};for(const n of this.models.keys())this.stores[n]=this.createInterface(n)}name;version;stores;getDb(){return this.db}getStore(e){return this.stores[e]}getStoreNames(){return this.models.keys()}createTransaction(e,t,n){return new ie(this.db,t,e,n)}async drop(){await p(window.indexedDB.deleteDatabase(this.name))}async dump(e,t,n){const r=await async function(e,t){const n={};t=t||e.getStoreNames();const r=e.createTransaction("readonly",t);for(const s of t)n[s]=await me(e,s,void 0,r);return n}(this,t);switch(e){case"json":return be.toJson(this.name,r,n);case"csv":return be.toCsvDb(this,t||this.getStoreNames(),r)}}deleteAllStores(){for(const e of this.models.keys())this.db.deleteObjectStore(e)}deleteStore(e){Array.isArray(e)||(e=[e]);for(const t of e)this.db.deleteObjectStore(t)}getModel(e){const t=this.models.getModel(e);if(!t)throw new c(`Model with name '${e}' not found`);return t}getAccessedStores(e,t,n,r){return r?r.storeNames:Array.from(de(e,t,n,this))}createInterface(e){return{add:async(t,n)=>await this.add(e,t,{tx:n}),addMany:async(t,n)=>{if(!n){const r=new Set;for(const n of t)v(r,de(e,n,!0,this));n=this.createTransaction("readwrite",Array.from(r))}const r=[];for(const s of t)r.push(await this.add(e,s,{tx:n}));return r},findFirst:async(t,n)=>(await this.find(e,t,!0,{tx:n}))[0],find:async(t,n)=>await this.find(e,t,!1,{tx:n}),get:async t=>{const n=this.createTransaction("readonly",e);return await n.getStore(e).get(t)},update:async(t,n)=>(await this.update(e,{data:n},!0,{singleton:{id:t}}))[0],updateFirst:async(t,n)=>(await this.update(e,t,!0,{tx:n}))[0],updateMany:async(t,n)=>await this.update(e,t,!1,{tx:n}),compileQuery:t=>new fe(this,e,t),delete:async t=>await we(e,this,void 0,void 0,{singleton:{id:t}})>0,deleteFirst:async t=>await we(e,this,t,!0)>0,deleteMany:async t=>await we(e,this,t,!1),dump:async(t,n,r)=>{const s=await me(this,e,n);switch(t){case"json":return be.toJson(e,s,r);case"csv":return be.toCsvStore(this.getModel(e),s)}}}}async add(e,t,n={}){let{tx:r}=n;const{relation:o}=n,i=this.getAccessedStores(e,t,!0,r);return r=ie.create(this.db,i,"readwrite",r),await r.wrap(async n=>{const r=n.getStore(e),i=this.getModel(e),c=i.getPrimaryKey(),u=o?{[o.key]:i.getRelation(o.key)?.isArray?[o.id]:o.id}:{},l=c.isAutoIncremented()?{...u}:{...u,[i.primaryKey]:t[i.primaryKey]??c.genKey()},d=await r.add(l),y={},f=new Set;for(const o in t){f.add(o);const r=t[o];switch(i.keyType(o)){case te.Invalid:throw new s(`Key '${o}' does ont exist on model '${e}'`);case te.Property:{const e=i.parseField(o,r);if(!e)throw new a;if(!e.success)throw new s(`Key '${o}' has the following validation error: ${e.error}`);y[o]=e.data;break}case te.Relation:{if(!r)continue;const e=g(r),t=i.getRelation(o);if(t.isArray&&(y[o]=[],"$createMany"in r||"$connectMany"in r)){const t=[];for(const e of r.$createMany??[])t.push({$create:e});for(const e of r.$connectMany??[])t.push({$connect:e});e.push(...t)}const a=this.getModel(t.to).getRelation(t.getRelatedKey()),c=new Set;for(const r of e){const e=m(r)[0];if(!e)throw new s(`Key '${o}' cannot be an empty connection object`);switch(e){case"$connect":{const i=r[e];if(c.has(i))throw new s(`Primary key '${i}' was already used for a connection`);if(c.add(i),!a)throw new s(`Could not find corresponding relation '${t.name}'`);await this.connectDocument(t,d,i,n),t.isArray?y[o].push(i):y[o]=i;break}case"$create":{const s=await this.add(t.to,r[e],{tx:n,relation:{id:d,key:t.getRelatedKey()}});t.isArray?y[o].push(s):y[o]=s;break}case"$connectMany":case"$createMany":break;default:throw new s(`Connection Object on key '${o}' has an unknown key '${e}'`)}if(!t.isArray)break}break}case te.PrimaryKey:}}const h=Array.from(new Set(i.keys()).difference(f));for(const e of h)switch(i.keyType(e)){case te.Property:{const t=i.parseField(e,void 0);if(!t)throw new a("A parsing error occurred");if(!t.success)throw new s(`Key '${e}' is missing`);y[e]=t.data;break}case te.Relation:{const t=i.getRelation(e),n=u[e];if(t.isArray)y[e]=n??[];else if(t.isOptional)y[e]=n??null;else{if(!n)throw new s(`Required relation '${e}' is not defined`);y[e]=n}break}case te.Invalid:case te.PrimaryKey:}return await r.put({[i.primaryKey]:d,...y})})}async clear(e,t){await we(e,this,void 0,!1,t)}async find(e,t,n,r={}){let{tx:s}=r;const o=this.getAccessedStores(e,ye(t),!1,s);s=ie.create(this.db,o,"readonly",s);const a=[];return await s.wrap(async r=>{const s=r.getStore(e),o=le(e,this,t);return await s.openCursor(async e=>{const t=await o(e.value,r);return t&&a.push(t),(!n||!a.length)&&(e.continue(),!0)}),a})}async update(e,t,n,r={}){const{singleton:o}=r,i=r.singleton?t:t.data,c=this.getAccessedStores(e,i,!0,r.tx),d=ie.create(this.db,c,"readwrite",r.tx);return await d.wrap(async r=>{const c=r.getStore(e),d=this.getModel(e),y=[];for(const e of m(i))switch(d.keyType(e)){case te.Property:y.push({key:e,isRelation:!1,updateFn:"function"==typeof i[e]?i[e]:()=>i[e]});break;case te.Relation:{const t=g(i[e]);if(!t)continue;const n=[];for(const e of t)for(const t in e){switch(t){case"$createMany":case"$connectMany":case"$updateMany":case"$deleteMany":case"$disconnectMany":{const r=t.substring(0,t.length-4);for(const s of e[t])n.push([r,s]);break}default:n.push([t,e[t]])}break}y.push({actions:n,key:e,isRelation:!0,relation:d.getRelation(e)});break}case te.PrimaryKey:throw new l("Primary key field cannot be updated");case te.Invalid:default:throw new a(`Unknown key '${e}'`)}const f=[],h=async e=>{const t=e[d.primaryKey];for(const{key:n,...o}of y){const a=o.relation;if(o.isRelation)for(const[i,c]of o.actions)switch(i){case"$connect":e[n]&&!a.isArray&&await this.disconnectDocument(a,t,e[n],r).catch(r.onRejection),await this.connectDocument(a,t,c,r).catch(r.onRejection),a.isArray?e[n].push(c):e[n]=c;break;case"$create":{const s=await this.add(a.to,c,{tx:r,relation:{id:t,key:a.getRelatedKey()}});a.isArray?e[n].push(s):e[n]=s;break}case"$delete":if(!a.isNullable())throw new s("Item cannot be deleted, relation is required");e[n]=a.isArray&&Array.isArray(e[n])?e[n].filter(e=>e!==c):null,await we(a.to,this,{},!0,{tx:r,singleton:{id:c}});break;case"$disconnect":{if(!a.isNullable())throw new s("Item cannot be disconnected, relation is required");if(!e[n]||0===e[n]?.lenth)break;const o=this.getModel(a.to).getRelation(a.getRelatedKey());await this.disconnectDocument(a,t,o.isArray?c:e[n],r).catch(r.onRejection),e[n]=a.isArray&&Array.isArray(e[n])?e[n].filter(e=>e!==c):null;break}case"$update":a.isArray?await this.update(a.to,c,!1,{tx:r}):null!=e[n]&&await this.update(a.to,c,!1,{tx:r,singleton:{id:t}});break;case"$deleteAll":if(c&&a.isArray&&Array.isArray(e[n])){const t=this.getModel(a.to),s=new Set(e[n]);await we(a.to,this,{[t.primaryKey]:e=>s.has(e)},!1,{tx:r}),e[n]=[]}break;case"$disconnectAll":if(c&&a.isArray&&Array.isArray(e[n])){for(const s of e[n])await this.disconnectDocument(a,t,s,r);e[n]=[]}}else e[n]=o.updateFn(e[n])}return e};if(o){const e=await c.get(o.id);if(!e)throw new u(`${d.name} with priamry key '${o.id}' not found`);const t=await h(e).catch(r.onRejection);return await c.put(t),[t]}{const e=ce(t.where);return await c.openCursor(async t=>{const s=t.value;if(ue(e,s)){const e=await h(s).catch(r.onRejection);if(await p(t.update(e)).then(()=>f.push(e)).catch(r.onRejection),n)return!1}return t.continue(),!0}),f}})}async connectDocument(e,t,n,r){const s=r.getStore(e.to),o=await s.get(n);if(!o)throw new u(`Document with Primary Key '${n}' could not be found in model '${e.to}'`);const a=e.getRelatedKey(),i=this.getModel(e.to).getRelation(a),c=o[a];if(i.isArray&&Array.isArray(c))c.includes(t)||c.push(t);else{if(c)throw new h;o[a]=t}return await s.put(o).catch(r.onRejection),n}async disconnectDocument(e,t,n,r){const s=r.getStore(e.to),o=await s.get(n);if(!o)throw new u(`Document with Primary Key '${n}' could not be found in model '${e.to}'`);const a=this.getModel(e.to).getRelation(e.getRelatedKey());if(a.isArray)o[e.getRelatedKey()].filter(e=>e!==t);else{if(!a.isOptional)throw new h;o[e.getRelatedKey()]=null}return await s.put(o).catch(r.onRejection),n}}class Ae{constructor(e,t){this.name=e,this.models=t,this.modelKeys=m(this.models),this.schemas={};for(const r of this.modelKeys){const e=this.models[r],t={};for(const[s,o]of e.entries())if(re.is(o))t[s]=o.type;else if(Q.is(o)){const{onDelete:a}=o.getActions(),i=this.models[o.to],c=i.getPrimaryKey();t[s]=c.type,o.isOptional?t[s]=L(t[s]):o.isArray&&(t[s]=I(t[s]));let u=!!o.getRelatedKey();if(!u)for(const[t,r]of i.relations())if(s!==t&&r.to===e.name&&r.name===o.name){if(u=!0,o.setRelatedKey(t),r.setRelatedKey(s),"SetNull"===a&&!r.isNullable())throw new n(`Key '${t}' on model '${i.name}': Non-optional relation cannot have the 'SetNull' action`);break}if(!u)throw new n(`Relation '${o.name}' of model ${r} does not have an equivalent relation on model '${o.to}'`)}else{if(!H.is(o))throw new n(`Unknown field value detected: ${JSON.stringify(o)}`);t[s]=o.type}this.schemas[r]=t}}schemas;modelKeys;getModel(e){return this.models[e]}async createClient(e=1){const t=window.indexedDB.open(this.name,e);t.onupgradeneeded=e=>{const t=e.target.result;for(const n of this.modelKeys){const e=this.models[n];t.objectStoreNames.contains(e.name)||t.createObjectStore(e.name,{autoIncrement:e.getPrimaryKey().isAutoIncremented(),keyPath:e.primaryKey})}};const n=await p(t);return new Se(n,this)}keys(){return[...this.modelKeys]}}const ve=Object.freeze(Object.defineProperty({__proto__:null,ArrayRelation:Z,BaseRelation:Q,DbClient:Se,FieldTypes:te,Model:oe,OptionalRelation:ee,PrimaryKey:H,Property:re,Relation:X,Tag:$,Type:B,Typing:J,deserializeType:U,isSubtype:z,isType:G,parseType:Y,serializeType:q,typeToString:V},Symbol.toStringTag,{value:"Module"}));exports.Builder=class{constructor(e,t){this.name=e,this.names=t,this.models={}}models;defineModel(e,t){if("object"==typeof e&&oe.is(e))return this.models[e.name]=e,e;{if(!t)throw new Error("Model Fields must be defined");const n=new oe(e,t);return this.models[e]=n,n}}compile(e){return new Ae(this.name,e)}},exports.CompiledQuery=fe,exports.Model=oe,exports.Property=re,exports.StoreError=e,exports.core=ve;
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});class e extends Error{code;constructor(e,t){super(`(${e}) ${t}`),this.code=e}}function t(t,n){return class extends e{static code;constructor(e=n){super(t,e)}static of(e){new this(e)}}}const n=t("INVALID_CONFIG","Configuration is invalid"),r=t("INVALID_TX","Transaction is invalid"),s=t("INVALID_ITEM","Item is invalid"),o=t("ASSERTION_FAILED","Assertion failed"),a=t("UNKNOWN","An unknown error occurred"),i=t("DELETE_FAILED","Item could not be deleted"),c=t("NOT_FOUND","Object Store Not Found"),u=t("NOT_FOUND","Document Not Found"),l=t("UPDATE_FAILED","Item could not be updated"),f=t("ADD_FAILED","Item could not be added"),y=t("OPEN_CURSOR","Cursor could not be opened"),d=t("GET_FAILED","Item could not be retrieved"),h=t("OVERWRITE_RELATION","Relation cannot be overwritten"),p=t("EXPORT","Export failed"),w=t("SERIALIZATION_FAILED","Seralization failed"),m=t("DESERIALIZATION_FAILED","De-seralization failed");function g(e,t){return new Promise(t=>{e.onsuccess=()=>{t(e.result)},e.onerror=()=>{}})}function b(e){return Object.keys(e)}function S(e){return Array.isArray(e)||(e=[e]),e}function A(){return crypto.randomUUID()}function v(){return new Date}function $(e){return e}function k(e,t){for(const n of t.keys())e.add(n);return e}var R=(e=>(e[e.string=0]="string",e[e.number=1]="number",e[e.date=2]="date",e[e.boolean=3]="boolean",e[e.symbol=4]="symbol",e[e.bigint=5]="bigint",e[e.file=6]="file",e[e.void=7]="void",e[e.float=8]="float",e[e.int=9]="int",e[e.unknown=10]="unknown",e[e.literal=11]="literal",e[e.array=12]="array",e[e.set=13]="set",e[e.union=14]="union",e[e.optional=15]="optional",e[e.default=16]="default",e[e.object=17]="object",e[e.tuple=18]="tuple",e[e.custom=19]="custom",e))(R||{});const O={};function j(e){const t=O[e];return t||(O[e]={tag:e})}function K(){return j(R.string)}function N(){return j(R.number)}function T(){return j(R.boolean)}function D(){return j(R.bigint)}function M(){return j(R.symbol)}function I(){return j(R.file)}function x(){return j(R.date)}function P(){return j(R.unknown)}function _(e){return{tag:R.literal,value:e}}function F(e){return{tag:R.array,of:e}}function E(e,t){return{tag:R.default,of:e,value:t}}function L(e){return{tag:R.set,of:e}}function C(e){return{tag:R.union,options:e}}function B(e){return{tag:R.optional,of:e}}function V(e){return{tag:R.custom,...e}}const q=Object.freeze(Object.defineProperty({__proto__:null,Array:F,BigInt:D,Boolean:T,Custom:V,Date:x,Default:E,File:I,Float:function(){return j(R.float)},Int:function(){return j(R.int)},Literal:_,Number:N,Object:function(e){return{tag:R.object,props:e}},Optional:B,Set:L,String:K,Symbol:M,Tuple:function(e){return{tag:R.tuple,elements:e}},Union:C,Unknown:P,Void:function(){return j(R.void)},getType:j},Symbol.toStringTag,{value:"Module"}));function z(e){switch(e.tag){case R.void:return"void";case R.literal:return String(e.value);case R.boolean:return"boolean";case R.number:return"number";case R.float:return"float";case R.int:return"integer";case R.bigint:return"bigint";case R.string:return"string";case R.symbol:return"symbol";case R.unknown:return"unknown";case R.date:return"Date";case R.tuple:return`Tuple<${e.elements.map(e=>z(e)).join(", ")}>`;case R.array:return`Array<${z(e.of)}>`;case R.set:return`Set<${z(e.of)}>`;case R.default:case R.optional:return`${z(e.of)} | undefined`;case R.union:return`Union<${e.options.map(e=>z(e)).join(", ")}>`;case R.file:return"File";case R.object:return`{${Object.keys(e.props).map(t=>`${t}: ${z(e.props[t])}`).join(",\n")}}`;case R.custom:return"custom"}}async function U(e,t){if(!W(e,t))throw new w(`Value not of the proper type, expected type '${z(e)}', received '${JSON.stringify(t)}'`);switch(e.tag){case R.literal:case R.boolean:case R.number:case R.float:case R.int:case R.string:return t;case R.void:return;case R.bigint:return Number(t);case R.symbol:return t.description;case R.unknown:return JSON.stringify(t);case R.date:return t.getTime();case R.tuple:{const n=[];for(let r=0;r<t.length;r++)n.push(await U(e.elements[r],t[r]));return n}case R.array:{const n=[];for(const r of t)n.push(U(e.of,r));return await Promise.all(n)}case R.set:{const n=[];for(const r of t.keys())n.push(U(e.of,r));return await Promise.all(n)}case R.optional:if(void 0===t)return;return await U(e.of,t);case R.union:for(const n of e.options)try{return await U(n,t)}catch{}throw new w("Value union could not be serialized");case R.file:if(!(t instanceof File))throw new w("Value is not a valid file");return{data:new Promise((e,n)=>{const r=new FileReader;r.onload=()=>e(r.result),r.onerror=n,r.readAsDataURL(t)}),name:t.name,type:t.type};case R.object:{const n={};for(const r in e.props){const s=e.props[r];if(!(r in t)&&s.tag!==R.optional&&s.tag!==R.default&&s.tag!==R.void)throw new w(`Required property '${r}' not found`);n[r]=await U(s,t[r])}return n}case R.default:return await U(e.of,void 0===t?"function"==typeof e.value?e.value():e.value:t);case R.custom:return e.serialize?await e.serialize(t):JSON.stringify(t)}}async function G(e,t){switch(e.tag){case R.void:return;case R.literal:if(t!==e.value)throw new m(`'${t}' is not equal to literal '${t}'`);return t;case R.boolean:if("boolean"!=typeof t)throw new m(`'${t}' is not a boolean`);return t;case R.int:if("number"!=typeof t||!Number.isInteger(t))throw new m(`'${t}' is not an integer`);return t;case R.float:if("number"!=typeof t||isNaN(t))throw new m(`'${t}' is not a float`);return t;case R.number:if("number"!=typeof t||isNaN(t))throw new m(`'${t}' is not a number`);return t;case R.bigint:if("number"!=typeof t||isNaN(t))throw new m(`'${t}' is not a bigint`);return BigInt(t);case R.string:if("string"!=typeof t)throw new m(`'${t}' is not a string`);return t;case R.symbol:if("string"!=typeof t)throw new m(`'${t}' is not a symbol`);return Symbol.for(t);case R.date:if("number"!=typeof t||isNaN(t))throw new m(`'${t}' is not a date timestamp`);return new Date(t);case R.tuple:{if(!Array.isArray(t))throw new m(`'${t}' is not an array`);const n=[];for(let r=0;r<t.length;r++)n.push(await G(e.elements[r],t[r]));return n}case R.array:{if(!Array.isArray(t))throw new m(`'${t}' is not an array`);const n=[];for(const r of t)n.push(G(e.of,r));return await Promise.all(n)}case R.set:{if(!Array.isArray(t))throw new m(`'${t}' is not an array`);const n=[];for(const r of t)n.push(G(e.of,r));return new Set(await Promise.all(n))}case R.optional:if(void 0===t)return;return G(e.of,t);case R.unknown:return"string"!=typeof t?t:JSON.parse(t);case R.union:for(const n of e.options)try{return await G(n,t)}catch{}throw new m("Value did not match the union");case R.file:{if(!(t&&"object"==typeof t&&"data"in t&&"name"in t&&"type"in t&&"string"==typeof t.data&&"string"==typeof t.name&&"string"==typeof t.type))throw new m("Value is not a valid file schema");const e=Buffer.from(t.data.replace(/^data:.+;base64,/,""),"base64");return new File([e],t.name,{type:t.type})}case R.default:return void 0===t?e.value:G(e.of,t);case R.custom:if(e.isType(t))return e.deserialize?await e.deserialize(t):JSON.parse(String(t));throw new m("Value is not valid");case R.object:{if(!t||"object"!=typeof t)throw new m("Value is not an object");const n={};for(const r in e.props){const s=e.props[r];if(!(r in t)&&s.tag!==R.optional)throw new m(`Required property '${r}' not found`);n[r]=await G(s,t[r])}return n}}}function Y(e,t){if(e.tag!==t.tag)return!1;switch(e.tag){case R.literal:return e.value===t.value;case R.optional:case R.default:case R.set:case R.array:return Y(e.of,t.of);case R.union:if(e.options.length!==t.options.length)return!1;for(let n=0;n<e.options.length;n++)if(!Y(e.options[n],t.options[n]))return!1;return!0;case R.tuple:if(e.elements.length!==t.elements.length)return!1;for(let n=0;n<e.elements.length;n++)if(!Y(e.elements[n],t.elements[n]))return!1;return!0;case R.object:if(Object.keys(e.props).length!==Object.keys(t.props).length)return!1;for(const n in e.props){if(!(n in t.props))return!1;if(!Y(e.props[n],t.props[n]))return!1}return!0;case R.custom:return e===t;default:return!0}}function J(e,t){switch(e.tag){case R.literal:return t.tag===R.literal&&t.value===e.value;case R.number:return t.tag===e.tag||t.tag===R.literal&&typeof t.value===z(e)||t.tag===R.float||t.tag===R.int;case R.boolean:case R.symbol:case R.string:case R.bigint:case R.int:case R.float:return t.tag===e.tag||t.tag===R.literal&&typeof t.value===z(e);case R.unknown:return!0;case R.date:case R.file:case R.void:return t.tag===e.tag;case R.optional:case R.default:case R.set:case R.array:return t.tag===e.tag&&J(e.of,t.of);case R.union:if(t.tag===R.union){for(const n of t.options)if(!J(e,n))return!1;return!0}return e.options.some(e=>J(e,t));case R.tuple:if(t.tag!==R.tuple)return!1;for(let n=0;n<e.elements.length;n++)if(!J(e.elements[n],t.elements[n]))return!1;return!0;case R.object:if(t.tag!==R.object)return!1;for(const n in t.props){if(!e.props[n])return!1;if(!J(e.props[n],t.props[n]))return!1}return!0;case R.custom:return e===t}}function W(e,t){switch(e.tag){case R.void:return void 0===t;case R.literal:return t===e.value;case R.boolean:return"boolean"==typeof t;case R.number:return"number"==typeof t;case R.bigint:return"bigint"==typeof t;case R.string:return"string"==typeof t;case R.symbol:return"symbol"==typeof t;case R.unknown:return!0;case R.float:return"number"==typeof t&&!isNaN(t);case R.int:return"number"==typeof t&&Number.isInteger(t);case R.date:return t instanceof Date&&!isNaN(t.getTime());case R.tuple:return Array.isArray(t)&&t.length===e.elements.length&&t.every((t,n)=>W(e.elements[n],t));case R.array:return Array.isArray(t)&&t.every(t=>W(e.of,t));case R.set:return t instanceof Set&&Array.from(t).every(t=>W(e.of,t));case R.optional:case R.default:return void 0===t||W(e.of,t);case R.union:return e.options.some(e=>W(e,t));case R.file:return t instanceof File;case R.object:return!(!t||"object"!=typeof t)&&Object.keys(e.props).every(n=>W(e.props[n],t[n]));case R.custom:return e.isType(t)}}function H(e,t){if(W(e,t)){switch(e.tag){case R.custom:if(e.parse)try{return{success:!0,data:e.parse(t)}}catch(n){return{success:!1,error:String(n)}}break;case R.default:return void 0===t?{success:!0,data:e.value}:{success:!0,data:t}}return{success:!0,data:t}}return{success:!1,error:`Value is not a valid '${z(e)}'`}}const Q=Object.freeze(Object.defineProperty({__proto__:null,Tag:R,Type:q,deserializeType:G,isExactType:Y,isSubtype:J,isType:W,parseType:H,serializeType:U,typeToString:z},Symbol.toStringTag,{value:"Module"})),X=Symbol.for("primaryKey");class Z{symbol=X;genFn;autoGenerate;type;constructor(e,t){if(e){if(e.tag>R.date)throw new n("Invalid Primary Key Type");this.type=e,t?(this.autoGenerate=!0,this.genFn=t):this.autoGenerate=!1}else this.autoGenerate=!1,this.type=N()}getType(){return this.type}generator(e){return this.genFn=e,this.autoGenerate=!0,this}autoIncrement(){if(this.type.tag===R.number)return this.genFn=void 0,this.autoGenerate=!0,this;throw new n("Primary key must be a number to use autoIncrement()")}uuid(){if(!window.isSecureContext)throw new Error("Window is not in a secure context");return new Z(K(),A)}date(){return new Z(x(),v)}genKey(){if(this.genFn)return this.genFn();throw new Error("Generator function not defined")}isAutoIncremented(){return this.autoGenerate&&!this.genFn}static is(e){return e?.symbol===X}static compareKeyValue(e,t){if(typeof e!=typeof t)return!1;switch(typeof e){case"string":case"number":return e===t;case"object":return e.getTime()===t.getTime();default:return!1}}static validKeyTag=C([K(),N(),x()])}class ee{constructor(e,t="",n=!1,r=!1,s){this.to=e,this.name=t,this.isOptional=n,this.isArray=r,this.relatedKey="",this.actions={onDelete:s||"Restrict"}}static SYMBOL=Symbol.for("baseRelation");BASE_SYMBOL=ee.SYMBOL;actions;relatedKey;getActions(){return{...this.actions}}isNullable(){return this.isArray||this.isOptional}setRelatedKey(e){this.relatedKey=e}getRelatedKey(){return this.relatedKey}toString(){return`${this.isArray?"Array":this.isOptional?"Optional":"Standard"} relation from this model to model '${this.to}' on key '${this.relatedKey}'`}getBaseSymbol(){return this.BASE_SYMBOL}static is(e){return"getBaseSymbol"in e&&e.getBaseSymbol()===ee.SYMBOL}}class te extends ee{static R_SYMBOL=Symbol.for("relation");symbol=te.R_SYMBOL;constructor(e,t={}){super(e,t.name,!1,!1,t.onDelete)}array({onDelete:e}={}){return new ne(this.to,this.name,e)}optional({onDelete:e}={}){return new re(this.to,this.name,e)}onDelete(e){return this.actions.onDelete=e,this}static is(e){return e?.symbol===this.R_SYMBOL}}class ne extends ee{static A_SYMBOL=Symbol.for("arrayRelation");symbol=ne.A_SYMBOL;constructor(e,t,n="None"){super(e,t,!1,!0,n)}static is(e){return e?.symbol===this.A_SYMBOL}}class re extends ee{static O_SYMBOL=Symbol.for("optionalRelation");symbol=re.O_SYMBOL;constructor(e,t,n="None"){super(e,t,!0,!1,n)}static is(e){return e?.symbol===this.O_SYMBOL}}var se=(e=>(e[e.Property=0]="Property",e[e.Relation=1]="Relation",e[e.PrimaryKey=2]="PrimaryKey",e[e.Invalid=3]="Invalid",e))(se||{});const oe=Symbol.for("property");class ae{constructor(e,t){this.type=e,this.options={unique:t?.unique??!1}}symbol=oe;hasDefault=!1;options;unique(){switch(this.type.tag){case R.boolean:case R.string:case R.number:case R.symbol:return this.options.unique=!0,this;default:throw new Error("A non-primitive cannot be a unique value")}}hasDefaultValue(){return this.hasDefault}static relation(e,t){return new te(e,t)}static primaryKey(e="number"){return new Z(this.nameToType(e))}static nameToType(e){switch(e){case"boolean":return T();case"bigint":return D();case"number":return N();case"string":return K();case"symbol":return M();default:return P()}}static is(e){return"object"==typeof e&&e?.symbol===oe}array(){return new ae(F(this.type),this.options)}default(e){return this.hasDefault=!0,new ae(E(this.type,e),this.options)}optional(){return new ae(B(this.type),this.options)}static array(e,t){return new ae(F(e.type),t)}static boolean(e){return new ae(T(),e)}static custom(e,t){return new ae(V({isType:t=>e(t).success,serialize:t?.serialize,deserialize:t?.deserialize}),t)}static date(e){return new ae(x(),e)}static file(e){return new ae(I(),e)}static literal(e,t){return new ae(_(e),t)}static number(e){return new ae(N(),e)}static string(e){return new ae(K(),e)}static set(e,t){return new ae(L(e.type),t)}static union(e,t){return new ae(C(e.map(e=>e.type)),t)}static generateArrayValidator(e){return t=>{if(Array.isArray(t)){const n=[];for(const r of t){const t=e(r);if(!t.success)return t;n.push(t.data)}return{success:!0,data:n}}return{success:!1,error:"Value is not an array"}}}}const ie=Symbol.for("model");class ce{constructor(t,n){this.name=t,this.fields=n,this.fieldKeys=b(n);for(const e of this.fieldKeys){const t=this.fields[e];ee.is(t)&&t.to!==this.name&&this.relationLinks.add(t.to)}const r=this.fieldKeys.find(e=>Z.is(this.fields[e]));if(!r)throw new e("INVALID_CONFIG",`Model ${this.name} has no primary key`);this.primaryKey=r}symbol=ie;fieldKeys;relationLinks=new Set;cache={};primaryKey;get(e){return this.fields[e]}getPrimaryKey(){return this.fields[this.primaryKey]}defineKeyGen(e){return this.getPrimaryKey().generator(e),this}getRelation(e){const t=this.fields[e];if(t&&ee.is(t))return t}keyType(e){const t=this.fields[e];return t?ae.is(t)?se.Property:ee.is(t)?se.Relation:Z.is(t)?se.PrimaryKey:se.Invalid:se.Invalid}links(){return this.relationLinks.keys()}*relations(){for(const e of this.fieldKeys)ee.is(this.fields[e])&&(yield[e,this.fields[e]])}*entries(){for(const e of this.fieldKeys)yield[e,this.fields[e]]}keys(){return this.fieldKeys}parseField(e,t){return ae.is(this.fields[e])?H(this.fields[e].type,t):null}getDeletedStores(e){if(this.cache.delete)return this.cache.delete;const t=new Set,n=[this.name];let r;for(;n.length>0;){const s=n.shift();if(t.has(s))continue;r=e.getModel(s);const o=r.cache.delete;if(o)k(t,o);else{t.add(s);for(const e of r.links())t.has(e)||n.push(e)}}return this.cache.delete=t,t}static is(e){return e?.symbol===ie}}class ue{constructor(e,t){this.tx=e,this.internal=t}add(e){return this.handleRequest(this.internal.add(e),()=>new f)}get(e){return this.handleRequest(this.internal.get(e),()=>new d)}async assertGet(e){const t=await this.handleRequest(this.internal.get(e),()=>new d);if(!t)throw this.tx.abort(new u);return t}put(e){return this.handleRequest(this.internal.put(e),()=>new l)}delete(e){return this.handleRequest(this.internal.delete(e),()=>new i)}async openCursor(t,n={}){const r=n.onError||(()=>new y),s=this.internal.openCursor(n.query,n.direction);await new Promise((n,o)=>{s.onsuccess=async s=>{try{s.target||o(this.tx.abort(r()));const e=s.target.result;e&&await t(e,this.tx)||n()}catch(i){o(this.tx.abort(i instanceof e?i:new a(String(i))))}},s.onerror=()=>{o(this.tx.abort(r()))}})}handleRequest(e,t){return new Promise(n=>{e.onsuccess=()=>{n(e.result)},e.onerror=()=>{throw this.tx.abort(t())}})}}class le{internal;status;error=null;storeNames;inWrap=!1;onRejection=t=>{throw t instanceof e?this.abort(t):this.abort(new a(String(t)))};objectStores;constructor(e,t,n,r={}){e instanceof le?(this.internal=e.getInternal(),this.storeNames=e.storeNames,this.status=e.status,this.error=e.error,this.objectStores=e.getAllStores()):(this.internal=e.transaction(t,n),this.status=0,this.storeNames=Array.from(this.internal.objectStoreNames),this.objectStores=new Map(this.storeNames.map(e=>[e,this.getObjectstore(e)])),this.internal.onabort=this.registerHandler(1,r.onAbort),this.internal.onerror=this.registerHandler(3,r.onError),this.internal.oncomplete=this.registerHandler(2,r.onComplete))}static create(e,t,n,r){return r||new le(e,t,n)}abort(e){return 1!==this.status&&this.internal.abort(),this.status=1,this.error=e,this.error}commit(){this.internal.commit()}getInternal(){return this.internal}getStore(e){const t=this.objectStores.get(e);if(!t)throw this.abort(new r(`Store '${e}' is not a part of this transaction`));return t}getAllStores(){return this.objectStores}get mode(){return this.internal.mode}is(e){return this.status===e}contains(e){Array.isArray(e)||(e=[e]);for(const t of e)if(!this.internal.objectStoreNames.contains(t))return!1;return!0}assertIsArray(e,t="Value is not an array"){if(!Array.isArray(e))throw this.abort(new o(t))}getObjectstore(e){try{return new ue(this,this.internal.objectStore(e))}catch{throw this.abort(new c(`No ObjectStore with the name '${e}' found`))}}registerHandler(e,t=()=>{}){return n=>{this.status=e,t(this,n)}}async wrap(t){if(this.inWrap)return await t(this);this.inWrap=!0;try{const e=await t(this);return this.inWrap=!1,e}catch(n){throw this.inWrap=!1,n instanceof e?this.abort(n):this.abort(new a(JSON.stringify(n)))}}}function fe(e){if(!e)return[];const t=[];for(const n in e)if(Object.hasOwn(e,n))switch(typeof e[n]){case"function":t.push([n,!0,e[n]]);break;case"object":if(e[n]instanceof Date){const r=e[n];t.push([n,!0,e=>e instanceof Date&&e.getTime()===r.getTime()])}break;default:t.push([n,!1,e[n]])}return t}function ye(e,t){if(!t||"object"!=typeof t)return!1;for(const n of e)if(n[1]){if(!n[2](t[n[0]]))return!1}else if(n[2]!==t[n[0]])return!1;return!0}function de(e,t,n={},r){const o=t.getModel(e);if(n.include&&n.select)throw new s("include and select cannot both be defined");const a=fe(n.where),i=n.select?"select":n.include?"include":"";if(i){const e=n[i],r=!!n.select,s=[];for(const n in e)if(Object.hasOwn(e,n)&&e[n])switch(o.keyType(n)){case se.Relation:{const r=o.getRelation(n),a="object"==typeof e[n]?de(r.to,t,e[n]):$,i=r.getRelatedKey();if(r.isArray){const e=async(e,t)=>{const n=[],s=t.getStore(r.to);for(const r of e){const e=await a(await s.assertGet(r),t);e&&(delete e[i],n.push(e))}return n};s.push({key:n,getValue:e})}else{const e=async(e,t)=>await a(await t.getStore(r.to).assertGet(e),t);s.push({key:n,getValue:e})}break}case se.Property:case se.PrimaryKey:r&&s.push({key:n})}return r?async(e,t)=>{if(!ye(a,e))return;const n={};for(const{key:r,getValue:o}of s)n[r]=o?await o(e[r],t):e[r];return n}:async(e,t)=>{if(ye(a,e)){for(const{key:n,getValue:r}of s)e[n]=await r(e[n],t);return e}}}return e=>ye(a,e)?e:void 0}function he(e,t,n,r){const s=new Set([e]);if(n){const o=r.getModel(e);for(const e in t){const a=o.getRelation(e),i=S(t[e]);if(a)for(const e of i)if(e&&"object"==typeof e)for(const t in e)if(Object.hasOwn(e,t))switch(t){case"$connect":case"$connectMany":case"$disconnect":case"$disconnectMany":case"$disconnectAll":s.add(a.to);break;case"$delete":case"$deleteMany":case"$deleteAll":k(s,o.getDeletedStores(r));break;case"$create":k(s,he(a.to,e[t],n,r));break;case"$createMany":e[t].forEach(e=>k(s,he(a.to,e,n,r)));break;case"$update":k(s,he(a.to,e[t].data,n,r));break;case"$updateMany":e[t].forEach(e=>k(s,he(a.to,e.data,n,r)))}}}else{const n=r.getModel(e);for(const e in t){const o=n.getRelation(e);if(o)switch(typeof t[e]){case"object":k(s,he(o.to,pe(t[e]),!1,r));break;case"boolean":s.add(o.to)}}}return s}function pe(e){return e.select?e.select:e.include?e.include:{}}class we{constructor(e,t,n){this.client=e,this.name=t,this.accessedStores=Array.from(he(t,pe(n),!1,this.client)),this.selectClause=de(t,this.client,n)}accessedStores;selectClause;async find(){return await this._find(!1)}async findFirst(){return(await this._find(!0))[0]}async _find(e){const t=this.client.createTransaction("readonly",this.accessedStores);return await t.wrap(async t=>{const n=[],r=t.getStore(this.name);return await r.openCursor(async r=>{const s=await this.selectClause(r.value,t);return s&&n.push(s),(!e||!n.length)&&(r.continue(),!0)}),n})}}function me(e,t,r){return async s=>{if(!s)return!1;const o=s[e.primaryKey];for(const[a,c]of e.relations()){const{onDelete:u}=c.getActions(),l=s[a],f=t.getModel(c.to);switch(u){case"Cascade":if(c.isArray){r.assertIsArray(l);const e=new Set(l),n=me(f,t,r),s=r.getStore(c.to);await s.openCursor(async t=>(e.has(t.value[f.primaryKey])&&await n(t.value),t.continue(),!0)).catch(r.onRejection)}else l&&await ge(c.to,t,void 0,void 0,{tx:r,singleton:{id:l}});break;case"SetNull":{if(!l)break;const e=S(l),t=r.getStore(c.to),s=c.getRelatedKey(),a=f.getRelation(s);if(!a)throw new n(`Relation '${c.name}' has an invalid relation key '${c.getRelatedKey()}'`);if(!a.isNullable())throw new n(`Key '${s}' on model '${s}': Non-optional relation cannot have the 'SetNull' action`);for(const n of e){const e=await t.get(n);if(!e)continue;const i=e[s];if(a.isArray){r.assertIsArray(i);const e=i.indexOf(o);if(-1===e)continue;i.splice(e,1)}else e[s]=null;await t.put(e)}break}case"Restrict":if(Array.isArray(l)&&l.length>0||l)throw new i(`Key '${a}' on model '${e.name}' deletion is restricted while there is an active relation`)}}return!0}}async function ge(e,t,n,r=!1,s={}){const{singleton:o,finalStep:a=!0}=s,i=t.getModel(e),c=s.tx?s.tx.storeNames:Array.from(i.getDeletedStores(t)),u=le.create(t.getDb(),c,"readwrite",s.tx);return await u.wrap(async s=>{const c=s.getStore(e);let u=0;const l=me(i,t,s);if(o)await l(await c.assertGet(o.id))&&(await c.delete(o.id),u++);else{const e=fe(n);let t;await c.openCursor(async n=>{const o=n.value;return ye(e,o)&&await l(o)&&(t=g(n.delete()).catch(s.onRejection)),!(r&&u>0)&&(n.continue(),!0)}),t&&a&&await t}return u})}function be(e){return"string"!=typeof e?String(e):e.replaceAll(/~|\//g,e=>"~"===e?"~0":"~1")}async function Se(e,t,n,r){r=le.create(e.getDb(),[t],"readonly",r);const s=fe(n),a=e.getModel(t);return await r.wrap(async e=>{const n={};return await e.getStore(t).openCursor(async e=>{if(ye(s,e.value)){for(const[t,n]of a.entries())if(ee.is(n))if(n.isArray){if(!Array.isArray(e.value[t]))throw new o("Expected array type");const r=[];for(const s of e.value[t])r.push(`/${n.to}/${be(s)}`);e.value[t]=r}else(n.isOptional&&e.value[t]||!n.isNullable())&&(e.value[t]=`/${n.to}/${be(e.value[t])}`);else{if(!ae.is(n)&&!Z.is(n))throw new p(`Unrecognized model field on key '${t}'`);e.value[t]=await U(n.type,e.value[t])}if(n[e.value[a.primaryKey]])throw new p("Duplicate primary key detected "+JSON.stringify(n));n[e.value[a.primaryKey]]=e.value}return e.continue(),!0}),n})}function Ae(e,t){const n=[`## ${e.name}`],r=[];for(const[s,o]of e.entries())Z.is(o)?r.unshift(s):r.push(s);n.push(r.join(","));for(const s of Object.values(t)){const e=[];for(const t of r)switch(typeof s[t]){case"object":e.push(JSON.stringify(s[t]));break;case"undefined":e.push("");break;default:e.push(String(s[t]))}n.push(e.join(","))}return n.join("\n")}class ve{constructor(e,t,n){this.name=e,this.content=t,this.extension=n}toFile(e=`${this.name}_dump.${this.extension}`,t){return new File([this.content],e,t)}download(e=`${this.name}_dump.${this.extension}`,t){const n=URL.createObjectURL(this.toFile(e,t)),r=document.createElement("a");r.href=n,r.download=e,document.body.appendChild(r),r.click(),document.body.removeChild(r),URL.revokeObjectURL(n)}static toJson(e,t,n){return new this(e,JSON.stringify(t,void 0,n?.pretty??1?4:void 0),"json")}static toCsvStore(e,t){return new this(e.name,Ae(e,t),"csv")}static toCsvDb(e,t,n){const r=[`# ${e.name}`];for(const s of t)r.push(Ae(e.getModel(s),n[s]));return new this(e.name,r.join("\n"),"csv")}}class $e{constructor(e,t){this.db=e,this.models=t,this.name=this.db.name,this.version=this.db.version,this.stores={};for(const n of this.models.keys())this.stores[n]=this.createInterface(n)}name;version;stores;getDb(){return this.db}getStore(e){return this.stores[e]}getStoreNames(){return this.models.keys()}createTransaction(e,t,n){return new le(this.db,t,e,n)}async drop(){await g(window.indexedDB.deleteDatabase(this.name))}async dump(e,t,n){const r=await async function(e,t){const n={};t=t||e.getStoreNames();const r=e.createTransaction("readonly",t);for(const s of t)n[s]=await Se(e,s,void 0,r);return n}(this,t);switch(e){case"json":return ve.toJson(this.name,r,n);case"csv":return ve.toCsvDb(this,t||this.getStoreNames(),r)}}deleteAllStores(){for(const e of this.models.keys())this.db.deleteObjectStore(e)}deleteStore(e){Array.isArray(e)||(e=[e]);for(const t of e)this.db.deleteObjectStore(t)}getModel(e){const t=this.models.getModel(e);if(!t)throw new c(`Model with name '${e}' not found`);return t}getAccessedStores(e,t,n,r){return r?r.storeNames:Array.from(he(e,t,n,this))}createInterface(e){return{add:async(t,n)=>await this.add(e,t,{tx:n}),addMany:async(t,n)=>{if(!n){const r=new Set;for(const n of t)k(r,he(e,n,!0,this));n=this.createTransaction("readwrite",Array.from(r))}const r=[];for(const s of t)r.push(await this.add(e,s,{tx:n}));return r},findFirst:async(t,n)=>(await this.find(e,t,!0,{tx:n}))[0],find:async(t,n)=>await this.find(e,t,!1,{tx:n}),get:async t=>{const n=this.createTransaction("readonly",e);return await n.getStore(e).get(t)},update:async(t,n)=>(await this.update(e,{data:n},!0,{singleton:{id:t}}))[0],updateFirst:async(t,n)=>(await this.update(e,t,!0,{tx:n}))[0],updateMany:async(t,n)=>await this.update(e,t,!1,{tx:n}),compileQuery:t=>new we(this,e,t),delete:async t=>await ge(e,this,void 0,void 0,{singleton:{id:t}})>0,deleteFirst:async t=>await ge(e,this,t,!0)>0,deleteMany:async t=>await ge(e,this,t,!1),dump:async(t,n,r)=>{const s=await Se(this,e,n);switch(t){case"json":return ve.toJson(e,s,r);case"csv":return ve.toCsvStore(this.getModel(e),s)}}}}async add(e,t,n={}){let{tx:r}=n;const{relation:o}=n,i=this.getAccessedStores(e,t,!0,r);return r=le.create(this.db,i,"readwrite",r),await r.wrap(async n=>{const r=n.getStore(e),i=this.getModel(e),c=i.getPrimaryKey(),u=o?{[o.key]:i.getRelation(o.key)?.isArray?[o.id]:o.id}:{},l=c.isAutoIncremented()?{...u}:{...u,[i.primaryKey]:t[i.primaryKey]??c.genKey()},f=await r.add(l),y={},d=new Set;for(const o in t){d.add(o);const r=t[o];switch(i.keyType(o)){case se.Invalid:throw new s(`Key '${o}' does ont exist on model '${e}'`);case se.Property:{const e=i.parseField(o,r);if(!e)throw new a;if(!e.success)throw new s(`Key '${o}' has the following validation error: ${e.error}`);y[o]=e.data;break}case se.Relation:{if(!r)continue;const e=S(r),t=i.getRelation(o);if(t.isArray&&(y[o]=[],"$createMany"in r||"$connectMany"in r)){const t=[];for(const e of r.$createMany??[])t.push({$create:e});for(const e of r.$connectMany??[])t.push({$connect:e});e.push(...t)}const a=this.getModel(t.to).getRelation(t.getRelatedKey()),c=new Set;for(const r of e){const e=b(r)[0];if(!e)throw new s(`Key '${o}' cannot be an empty connection object`);switch(e){case"$connect":{const i=r[e];if(c.has(i))throw new s(`Primary key '${i}' was already used for a connection`);if(c.add(i),!a)throw new s(`Could not find corresponding relation '${t.name}'`);await this.connectDocument(t,f,i,n),t.isArray?y[o].push(i):y[o]=i;break}case"$create":{const s=await this.add(t.to,r[e],{tx:n,relation:{id:f,key:t.getRelatedKey()}});t.isArray?y[o].push(s):y[o]=s;break}case"$connectMany":case"$createMany":break;default:throw new s(`Connection Object on key '${o}' has an unknown key '${e}'`)}if(!t.isArray)break}break}case se.PrimaryKey:}}const h=Array.from(new Set(i.keys()).difference(d));for(const e of h)switch(i.keyType(e)){case se.Property:{const t=i.parseField(e,void 0);if(!t)throw new a("A parsing error occurred");if(!t.success)throw new s(`Key '${e}' is missing`);y[e]=t.data;break}case se.Relation:{const t=i.getRelation(e),n=u[e];if(t.isArray)y[e]=n??[];else if(t.isOptional)y[e]=n??null;else{if(!n)throw new s(`Required relation '${e}' is not defined`);y[e]=n}break}case se.Invalid:case se.PrimaryKey:}return await r.put({[i.primaryKey]:f,...y})})}async clear(e,t){await ge(e,this,void 0,!1,t)}async find(e,t,n,r={}){let{tx:s}=r;const o=this.getAccessedStores(e,pe(t),!1,s);s=le.create(this.db,o,"readonly",s);const a=[];return await s.wrap(async r=>{const s=r.getStore(e),o=de(e,this,t);return await s.openCursor(async e=>{const t=await o(e.value,r);return t&&a.push(t),(!n||!a.length)&&(e.continue(),!0)}),a})}async update(e,t,n,r={}){const{singleton:o}=r,i=r.singleton?t:t.data,c=this.getAccessedStores(e,i,!0,r.tx),f=le.create(this.db,c,"readwrite",r.tx);return await f.wrap(async r=>{const c=r.getStore(e),f=this.getModel(e),y=[];for(const e of b(i))switch(f.keyType(e)){case se.Property:y.push({key:e,isRelation:!1,updateFn:"function"==typeof i[e]?i[e]:()=>i[e]});break;case se.Relation:{const t=S(i[e]);if(!t)continue;const n=[];for(const e of t)for(const t in e){switch(t){case"$createMany":case"$connectMany":case"$updateMany":case"$deleteMany":case"$disconnectMany":{const r=t.substring(0,t.length-4);for(const s of e[t])n.push([r,s]);break}default:n.push([t,e[t]])}break}y.push({actions:n,key:e,isRelation:!0,relation:f.getRelation(e)});break}case se.PrimaryKey:throw new l("Primary key field cannot be updated");case se.Invalid:default:throw new a(`Unknown key '${e}'`)}const d=[],h=async e=>{const t=e[f.primaryKey];for(const{key:n,...o}of y){const a=o.relation;if(o.isRelation)for(const[i,c]of o.actions)switch(i){case"$connect":e[n]&&!a.isArray&&await this.disconnectDocument(a,t,e[n],r).catch(r.onRejection),await this.connectDocument(a,t,c,r).catch(r.onRejection),a.isArray?e[n].push(c):e[n]=c;break;case"$create":{const s=await this.add(a.to,c,{tx:r,relation:{id:t,key:a.getRelatedKey()}});a.isArray?e[n].push(s):e[n]=s;break}case"$delete":if(!a.isNullable())throw new s("Item cannot be deleted, relation is required");e[n]=a.isArray&&Array.isArray(e[n])?e[n].filter(e=>e!==c):null,await ge(a.to,this,{},!0,{tx:r,singleton:{id:c}});break;case"$disconnect":{if(!a.isNullable())throw new s("Item cannot be disconnected, relation is required");if(!e[n]||0===e[n]?.lenth)break;const o=this.getModel(a.to).getRelation(a.getRelatedKey());await this.disconnectDocument(a,t,o.isArray?c:e[n],r).catch(r.onRejection),e[n]=a.isArray&&Array.isArray(e[n])?e[n].filter(e=>e!==c):null;break}case"$update":a.isArray?await this.update(a.to,c,!1,{tx:r}):null!=e[n]&&await this.update(a.to,c,!1,{tx:r,singleton:{id:t}});break;case"$deleteAll":if(c&&a.isArray&&Array.isArray(e[n])){const t=this.getModel(a.to),s=new Set(e[n]);await ge(a.to,this,{[t.primaryKey]:e=>s.has(e)},!1,{tx:r}),e[n]=[]}break;case"$disconnectAll":if(c&&a.isArray&&Array.isArray(e[n])){for(const s of e[n])await this.disconnectDocument(a,t,s,r);e[n]=[]}}else e[n]=o.updateFn(e[n])}return e};if(o){const e=await c.get(o.id);if(!e)throw new u(`${f.name} with priamry key '${o.id}' not found`);const t=await h(e).catch(r.onRejection);return await c.put(t),[t]}{const e=fe(t.where);return await c.openCursor(async t=>{const s=t.value;if(ye(e,s)){const e=await h(s).catch(r.onRejection);if(await g(t.update(e)).then(()=>d.push(e)).catch(r.onRejection),n)return!1}return t.continue(),!0}),d}})}async connectDocument(e,t,n,r){const s=r.getStore(e.to),o=await s.get(n);if(!o)throw new u(`Document with Primary Key '${n}' could not be found in model '${e.to}'`);const a=e.getRelatedKey(),i=this.getModel(e.to).getRelation(a),c=o[a];if(i.isArray&&Array.isArray(c))c.includes(t)||c.push(t);else{if(c)throw new h;o[a]=t}return await s.put(o).catch(r.onRejection),n}async disconnectDocument(e,t,n,r){const s=r.getStore(e.to),o=await s.get(n);if(!o)throw new u(`Document with Primary Key '${n}' could not be found in model '${e.to}'`);const a=this.getModel(e.to).getRelation(e.getRelatedKey());if(a.isArray)o[e.getRelatedKey()].filter(e=>e!==t);else{if(!a.isOptional)throw new h;o[e.getRelatedKey()]=null}return await s.put(o).catch(r.onRejection),n}}class ke{constructor(e,t){this.name=e,this.models=t,this.modelKeys=b(this.models),this.schemas={};for(const r of this.modelKeys){const e=this.models[r],t={};for(const[s,o]of e.entries())if(ae.is(o))t[s]=o.type;else if(ee.is(o)){const{onDelete:a}=o.getActions(),i=this.models[o.to],c=i.getPrimaryKey();t[s]=c.type,o.isOptional?t[s]=B(t[s]):o.isArray&&(t[s]=F(t[s]));let u=!!o.getRelatedKey();if(!u)for(const[t,r]of i.relations())if(s!==t&&r.to===e.name&&r.name===o.name){if(u=!0,o.setRelatedKey(t),r.setRelatedKey(s),"SetNull"===a&&!r.isNullable())throw new n(`Key '${t}' on model '${i.name}': Non-optional relation cannot have the 'SetNull' action`);break}if(!u)throw new n(`Relation '${o.name}' of model ${r} does not have an equivalent relation on model '${o.to}'`)}else{if(!Z.is(o))throw new n(`Unknown field value detected: ${JSON.stringify(o)}`);t[s]=o.type}this.schemas[r]=t}}schemas;modelKeys;getModel(e){return this.models[e]}async createClient(e=1){const t=window.indexedDB.open(this.name,e);t.onupgradeneeded=e=>{const t=e.target.result;for(const n of this.modelKeys){const e=this.models[n];t.objectStoreNames.contains(e.name)||t.createObjectStore(e.name,{autoIncrement:e.getPrimaryKey().isAutoIncremented(),keyPath:e.primaryKey})}};const n=await g(t);return new $e(n,this)}keys(){return[...this.modelKeys]}}const Re=Object.freeze(Object.defineProperty({__proto__:null,ArrayRelation:ne,BaseRelation:ee,DbClient:$e,FieldTypes:se,Model:ce,OptionalRelation:re,PrimaryKey:Z,Property:ae,Relation:te,Tag:R,Type:q,deserializeType:G,isExactType:Y,isSubtype:J,isType:W,parseType:H,serializeType:U,typeToString:z},Symbol.toStringTag,{value:"Module"}));exports.Builder=class{constructor(e,t){this.name=e,this.names=t,this.models={}}models;defineModel(e,t){if("object"==typeof e&&ce.is(e))return this.models[e.name]=e,e;{if(!t)throw new Error("Model Fields must be defined");const n=new ce(e,t);return this.models[e]=n,n}}compile(e){return new ke(this.name,e)}},exports.CompiledQuery=we,exports.Model=ce,exports.Property=ae,exports.StoreError=e,exports.Typing=Q,exports.core=Re;
|
package/dist/index.d.ts
CHANGED
package/dist/index.es.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
class e extends Error{code;constructor(e,t){super(`(${e}) ${t}`),this.code=e}}function t(t,n){return class extends e{static code;constructor(e=n){super(t,e)}static of(e){new this(e)}}}const n=t("INVALID_CONFIG","Configuration is invalid"),r=t("INVALID_TX","Transaction is invalid"),s=t("INVALID_ITEM","Item is invalid"),
|
|
2
|
-
return new Date}function A(e){return e}function v(e,t){for(const n of t.keys())e.add(n);return e}var $=/* @__PURE__ */(e=>(e[e.string=0]="string",e[e.number=1]="number",e[e.date=2]="date",e[e.boolean=3]="boolean",e[e.symbol=4]="symbol",e[e.bigint=5]="bigint",e[e.file=6]="file",e[e.void=7]="void",e[e.unknown=8]="unknown",e[e.literal=9]="literal",e[e.array=10]="array",e[e.set=11]="set",e[e.union=12]="union",e[e.optional=13]="optional",e[e.default=14]="default",e[e.object=15]="object",e[e.custom=16]="custom",e))($||{});const k={};function R(e){const t=k[e];return t||(k[e]={tag:e})}function O(){return R($.string)}function j(){return R($.number)}function K(){return R($.boolean)}function N(){return R($.bigint)}function M(){return R($.symbol)}function D(){return R($.file)}function T(){return R($.date)}function I(){return R($.unknown)}function E(e){return{tag:$.literal,value:e}}function x(e){return{tag:$.array,of:e}}function P(e,t){return{tag:$.default,of:e,value:t}}function _(e){return{tag:$.set,of:e}}function F(e){return{tag:$.union,options:e}}function L(e){return{tag:$.optional,of:e}}function C(e){return{tag:$.custom,...e}}const B=/* @__PURE__ */Object.freeze(/* @__PURE__ */Object.defineProperty({__proto__:null,Array:x,BigInt:N,Boolean:K,Custom:C,Date:T,Default:P,File:D,Literal:E,Number:j,Object:function(e){return{tag:$.object,props:e}},Optional:L,Set:_,String:O,Symbol:M,Union:F,Unknown:I,Void:function(){return R($.void)},getType:R},Symbol.toStringTag,{value:"Module"}));function V(e){switch(e.tag){case $.void:return"void";case $.literal:return String(e.value);case $.boolean:return"boolean";case $.number:return"number";case $.bigint:return"bigint";case $.string:return"string";case $.symbol:return"symbol";case $.unknown:return"unknown";case $.date:return"Date";case $.array:return`Array<${V(e.of)}>`;case $.set:return`Set<${V(e.of)}>`;case $.default:case $.optional:return`${V(e.of)} | undefined`;case $.union:return`Union<${e.options.map(e=>V(e)).join(", ")}>`;case $.file:return"File";case $.object:return`{${Object.keys(e.props).map(t=>`${t}: ${V(e.props[t])}`).join(",\n")}}`;case $.custom:return"custom"}}async function q(e,t){if(!G(e,t))throw new Error(`Value not of the proper type, expected type '${V(e)}', received '${JSON.stringify(t)}'`);switch(e.tag){case $.literal:case $.boolean:case $.number:case $.string:return t;case $.void:return;case $.bigint:return Number(t);case $.symbol:return t.description;case $.unknown:return JSON.stringify(t);case $.date:return t.getTime();case $.array:{const n=[];for(const r of t)n.push(q(e.of,r));return await Promise.all(n)}case $.set:{const n=[];for(const r of t.keys())n.push(q(e.of,r));return await Promise.all(n)}case $.optional:if(void 0===t)return;return await q(e.of,t);case $.union:for(const n of e.options)try{return await q(n,t)}catch{}throw new Error("Value union could not be serialized");case $.file:if(!(t instanceof File))throw new Error("Value is not a valid file");return{data:new Promise((e,n)=>{const r=new FileReader;r.onload=()=>e(r.result),r.onerror=n,r.readAsDataURL(t)}),name:t.name,type:t.type};case $.object:{const n={};for(const r in e.props){const s=e.props[r];if(!(r in t)&&s.tag!==$.optional&&s.tag!==$.default&&s.tag!==$.void)throw new Error(`Required property '${r}' not found`);n[r]=await q(s,t[r])}return n}case $.default:return await q(e.of,void 0===t?"function"==typeof e.value?e.value():e.value:t);case $.custom:return e.serialize?await e.serialize(t):JSON.stringify(t)}}async function U(e,t){switch(e.tag){case $.void:return;case $.literal:if(t!==e.value)throw new Error(`'${t}' is not equal to literal '${t}'`);return t;case $.boolean:if("boolean"!=typeof t)throw new Error(`'${t}' is not a boolean`);return t;case $.number:if("number"!=typeof t||isNaN(t))throw new Error(`'${t}' is not a number`);return t;case $.bigint:if("number"!=typeof t||isNaN(t))throw new Error(`'${t}' is not a bigint`);return BigInt(t);case $.string:if("string"!=typeof t)throw new Error(`'${t}' is not a string`);return t;case $.symbol:if("string"!=typeof t)throw new Error(`'${t}' is not a symbol`);return Symbol.for(t);case $.date:if("number"!=typeof t||isNaN(t))throw new Error(`'${t}' is not a date timestamp`);return new Date(t);case $.array:{if(!Array.isArray(t))throw new Error(`'${t}' is not an array`);const n=[];for(const r of t)n.push(U(e.of,r));return await Promise.all(n)}case $.set:{if(!Array.isArray(t))throw new Error(`'${t}' is not an array`);const n=[];for(const r of t)n.push(U(e.of,r));return new Set(await Promise.all(n))}case $.optional:if(void 0===t)return;return U(e.of,t);case $.unknown:return"string"!=typeof t?t:JSON.parse(t);case $.union:for(const n of e.options)try{return await U(n,t)}catch{}throw new Error("Value did not match the union");case $.file:{if(!(t&&"object"==typeof t&&"data"in t&&"name"in t&&"type"in t&&"string"==typeof t.data&&"string"==typeof t.name&&"string"==typeof t.type))throw new Error("Value is not a valid file schema");const e=Buffer.from(t.data.replace(/^data:.+;base64,/,""),"base64");return new File([e],t.name,{type:t.type})}case $.default:return void 0===t?e.value:U(e.of,t);case $.custom:if(e.isType(t))return e.deserialize?await e.deserialize(t):JSON.parse(String(t));throw new Error("Value is not valid");case $.object:{if(!t||"object"!=typeof t)throw new Error("Value is not an object");const n={};for(const r in e.props){const s=e.props[r];if(!(r in t)&&s.tag!==$.optional)throw new Error(`Required property '${r}' not found`);n[r]=await U(s,t[r])}return n}}}function z(e,t){switch(e.tag){case $.literal:return t.tag===$.literal&&t.value===e.value;case $.boolean:case $.number:case $.symbol:case $.string:case $.bigint:return t.tag===e.tag||t.tag===$.literal&&typeof t.value===V(e);case $.unknown:return!0;case $.date:case $.file:case $.void:return t.tag===e.tag;case $.optional:case $.default:case $.set:case $.array:return t.tag===e.tag&&z(e.of,t.of);case $.union:if(t.tag===$.union){for(const n of t.options)if(!z(e,n))return!1;return!0}return e.options.some(e=>z(e,t));case $.object:if(t.tag!==$.object)return!1;for(const n in t.props){if(!e.props[n])return!1;if(!z(e.props[n],t.props[n]))return!1}return!0;case $.custom:return e===t}}function G(e,t){switch(e.tag){case $.void:return void 0===t;case $.literal:return t===e.value;case $.boolean:return"boolean"==typeof t;case $.number:return"number"==typeof t;case $.bigint:return"bigint"==typeof t;case $.string:return"string"==typeof t;case $.symbol:return"symbol"==typeof t;case $.unknown:return!0;case $.date:return t instanceof Date&&!isNaN(t.getTime());case $.array:return Array.isArray(t)&&t.every(t=>G(e.of,t));case $.set:return t instanceof Set&&Array.from(t).every(t=>G(e.of,t));case $.optional:case $.default:return void 0===t||G(e.of,t);case $.union:return e.options.some(e=>G(e,t));case $.file:return t instanceof File;case $.object:return!(!t||"object"!=typeof t)&&Object.keys(e.props).every(n=>G(e.props[n],t[n]));case $.custom:return e.isType(t)}}function Y(e,t){if(G(e,t)){switch(e.tag){case $.custom:if(e.parse)try{return{success:!0,data:e.parse(t)}}catch(n){return{success:!1,error:String(n)}}break;case $.default:return void 0===t?{success:!0,data:e.value}:{success:!0,data:t}}return{success:!0,data:t}}return{success:!1,error:`Value is not a valid '${V(e)}'`}}const J=/* @__PURE__ */Object.freeze(/* @__PURE__ */Object.defineProperty({__proto__:null,Tag:$,Type:B,deserializeType:U,isSubtype:z,isType:G,parseType:Y,serializeType:q,typeToString:V},Symbol.toStringTag,{value:"Module"})),W=Symbol.for("primaryKey");class H{symbol=W;genFn;autoGenerate;type;constructor(e,t){if(e){if(e.tag>$.date)throw new n("Invalid Primary Key Type");this.type=e,t?(this.autoGenerate=!0,this.genFn=t):this.autoGenerate=!1}else this.autoGenerate=!1,this.type=j()}getType(){return this.type}generator(e){return this.genFn=e,this.autoGenerate=!0,this}autoIncrement(){if(this.type.tag===$.number)return this.genFn=void 0,this.autoGenerate=!0,this;throw new n("Primary key must be a number to use autoIncrement()")}uuid(){if(!window.isSecureContext)throw new Error("Window is not in a secure context");return new H(O(),b)}date(){return new H(T(),S)}genKey(){if(this.genFn)return this.genFn();throw new Error("Generator function not defined")}isAutoIncremented(){return this.autoGenerate&&!this.genFn}static is(e){return e?.symbol===W}static compareKeyValue(e,t){if(typeof e!=typeof t)return!1;switch(typeof e){case"string":case"number":return e===t;case"object":return e.getTime()===t.getTime();default:return!1}}static validKeyTag=F([O(),j(),T()])}class X{constructor(e,t="",n=!1,r=!1,s){this.to=e,this.name=t,this.isOptional=n,this.isArray=r,this.relatedKey="",this.actions={onDelete:s||"Restrict"}}static SYMBOL=Symbol.for("baseRelation");BASE_SYMBOL=X.SYMBOL;actions;relatedKey;getActions(){return{...this.actions}}isNullable(){return this.isArray||this.isOptional}setRelatedKey(e){this.relatedKey=e}getRelatedKey(){return this.relatedKey}toString(){return`${this.isArray?"Array":this.isOptional?"Optional":"Standard"} relation from this model to model '${this.to}' on key '${this.relatedKey}'`}getBaseSymbol(){return this.BASE_SYMBOL}static is(e){return"getBaseSymbol"in e&&e.getBaseSymbol()===X.SYMBOL}}class Q extends X{static R_SYMBOL=Symbol.for("relation");symbol=Q.R_SYMBOL;constructor(e,t={}){super(e,t.name,!1,!1,t.onDelete)}array({onDelete:e}={}){return new Z(this.to,this.name,e)}optional({onDelete:e}={}){return new ee(this.to,this.name,e)}onDelete(e){return this.actions.onDelete=e,this}static is(e){return e?.symbol===this.R_SYMBOL}}class Z extends X{static A_SYMBOL=Symbol.for("arrayRelation");symbol=Z.A_SYMBOL;constructor(e,t,n="None"){super(e,t,!1,!0,n)}static is(e){return e?.symbol===this.A_SYMBOL}}class ee extends X{static O_SYMBOL=Symbol.for("optionalRelation");symbol=ee.O_SYMBOL;constructor(e,t,n="None"){super(e,t,!0,!1,n)}static is(e){return e?.symbol===this.O_SYMBOL}}var te=/* @__PURE__ */(e=>(e[e.Property=0]="Property",e[e.Relation=1]="Relation",e[e.PrimaryKey=2]="PrimaryKey",e[e.Invalid=3]="Invalid",e))(te||{});const ne=Symbol.for("property");class re{constructor(e,t){this.type=e,this.options={unique:t?.unique??!1}}symbol=ne;hasDefault=!1;options;unique(){switch(this.type.tag){case $.boolean:case $.string:case $.number:case $.symbol:return this.options.unique=!0,this;default:throw new Error("A non-primitive cannot be a unique value")}}hasDefaultValue(){return this.hasDefault}static relation(e,t){return new Q(e,t)}static primaryKey(e="number"){return new H(this.nameToType(e))}static nameToType(e){switch(e){case"boolean":return K();case"bigint":return N();case"number":return j();case"string":return O();case"symbol":return M();default:return I()}}static is(e){return"object"==typeof e&&e?.symbol===ne}array(){return new re(x(this.type),this.options)}default(e){return this.hasDefault=!0,new re(P(this.type,e),this.options)}optional(){return new re(L(this.type),this.options)}static array(e,t){return new re(x(e.type),t)}static boolean(e){return new re(K(),e)}static custom(e,t){return new re(C({isType:t=>e(t).success,serialize:t?.serialize,deserialize:t?.deserialize}),t)}static date(e){return new re(T(),e)}static file(e){return new re(D(),e)}static literal(e,t){return new re(E(e),t)}static number(e){return new re(j(),e)}static string(e){return new re(O(),e)}static set(e,t){return new re(_(e.type),t)}static union(e,t){return new re(F(e.map(e=>e.type)),t)}static generateArrayValidator(e){return t=>{if(Array.isArray(t)){const n=[];for(const r of t){const t=e(r);if(!t.success)return t;n.push(t.data)}return{success:!0,data:n}}return{success:!1,error:"Value is not an array"}}}}const se=Symbol.for("model");class oe{constructor(t,n){this.name=t,this.fields=n,this.fieldKeys=m(n);for(const e of this.fieldKeys){const t=this.fields[e];X.is(t)&&t.to!==this.name&&this.relationLinks.add(t.to)}const r=this.fieldKeys.find(e=>H.is(this.fields[e]));if(!r)throw new e("INVALID_CONFIG",`Model ${this.name} has no primary key`);this.primaryKey=r}symbol=se;fieldKeys;relationLinks=/* @__PURE__ */new Set;cache={};primaryKey;get(e){return this.fields[e]}getPrimaryKey(){return this.fields[this.primaryKey]}getRelation(e){const t=this.fields[e];if(t&&X.is(t))return t}keyType(e){const t=this.fields[e];return t?re.is(t)?te.Property:X.is(t)?te.Relation:H.is(t)?te.PrimaryKey:te.Invalid:te.Invalid}links(){return this.relationLinks.keys()}*relations(){for(const e of this.fieldKeys)X.is(this.fields[e])&&(yield[e,this.fields[e]])}*entries(){for(const e of this.fieldKeys)yield[e,this.fields[e]]}keys(){return this.fieldKeys}parseField(e,t){return re.is(this.fields[e])?Y(this.fields[e].type,t):null}getDeletedStores(e){if(this.cache.delete)return this.cache.delete;const t=/* @__PURE__ */new Set,n=[this.name];let r;for(;n.length>0;){const s=n.shift();if(t.has(s))continue;r=e.getModel(s);const o=r.cache.delete;if(o)v(t,o);else{t.add(s);for(const e of r.links())t.has(e)||n.push(e)}}return this.cache.delete=t,t}static is(e){return e?.symbol===se}}class ae{constructor(e,t){this.tx=e,this.internal=t}add(e){return this.handleRequest(this.internal.add(e),()=>new d)}get(e){return this.handleRequest(this.internal.get(e),()=>new f)}async assertGet(e){const t=await this.handleRequest(this.internal.get(e),()=>new f);if(!t)throw this.tx.abort(new u);return t}put(e){return this.handleRequest(this.internal.put(e),()=>new l)}delete(e){return this.handleRequest(this.internal.delete(e),()=>new i)}async openCursor(t,n={}){const r=n.onError||(()=>new y),s=this.internal.openCursor(n.query,n.direction);await new Promise((n,o)=>{s.onsuccess=async s=>{try{s.target||o(this.tx.abort(r()));const e=s.target.result;e&&await t(e,this.tx)||n()}catch(i){o(this.tx.abort(i instanceof e?i:new a(String(i))))}},s.onerror=()=>{o(this.tx.abort(r()))}})}handleRequest(e,t){return new Promise(n=>{e.onsuccess=()=>{n(e.result)},e.onerror=()=>{throw this.tx.abort(t())}})}}class ie{internal;status;error=null;storeNames;inWrap=!1;onRejection=t=>{throw t instanceof e?this.abort(t):this.abort(new a(String(t)))};objectStores;constructor(e,t,n,r={}){e instanceof ie?(this.internal=e.getInternal(),this.storeNames=e.storeNames,this.status=e.status,this.error=e.error,this.objectStores=e.getAllStores()):(this.internal=e.transaction(t,n),this.status=0,this.storeNames=Array.from(this.internal.objectStoreNames),this.objectStores=new Map(this.storeNames.map(e=>[e,this.getObjectstore(e)])),this.internal.onabort=this.registerHandler(1,r.onAbort),this.internal.onerror=this.registerHandler(3,r.onError),this.internal.oncomplete=this.registerHandler(2,r.onComplete))}static create(e,t,n,r){return r||new ie(e,t,n)}abort(e){return 1!==this.status&&this.internal.abort(),this.status=1,this.error=e,this.error}commit(){this.internal.commit()}getInternal(){return this.internal}getStore(e){const t=this.objectStores.get(e);if(!t)throw this.abort(new r(`Store '${e}' is not a part of this transaction`));return t}getAllStores(){return this.objectStores}get mode(){return this.internal.mode}is(e){return this.status===e}contains(e){Array.isArray(e)||(e=[e]);for(const t of e)if(!this.internal.objectStoreNames.contains(t))return!1;return!0}assertIsArray(e,t="Value is not an array"){if(!Array.isArray(e))throw this.abort(new o(t))}getObjectstore(e){try{return new ae(this,this.internal.objectStore(e))}catch{throw this.abort(new c(`No ObjectStore with the name '${e}' found`))}}registerHandler(e,t=()=>{}){return n=>{this.status=e,t(this,n)}}async wrap(t){if(this.inWrap)return await t(this);this.inWrap=!0;try{const e=await t(this);return this.inWrap=!1,e}catch(n){throw this.inWrap=!1,n instanceof e?this.abort(n):this.abort(new a(JSON.stringify(n)))}}}function ce(e){if(!e)return[];const t=[];for(const n in e)if(Object.hasOwn(e,n))switch(typeof e[n]){case"function":t.push([n,!0,e[n]]);break;case"object":if(e[n]instanceof Date){const r=e[n];t.push([n,!0,e=>e instanceof Date&&e.getTime()===r.getTime()])}break;default:t.push([n,!1,e[n]])}return t}function ue(e,t){if(!t||"object"!=typeof t)return!1;for(const n of e)if(n[1]){if(!n[2](t[n[0]]))return!1}else if(n[2]!==t[n[0]])return!1;return!0}function le(e,t,n={},r){const o=t.getModel(e);if(n.include&&n.select)throw new s("include and select cannot both be defined");const a=ce(n.where),i=n.select?"select":n.include?"include":"";if(i){const e=n[i],r=!!n.select,s=[];for(const n in e)if(Object.hasOwn(e,n)&&e[n])switch(o.keyType(n)){case te.Relation:{const r=o.getRelation(n),a="object"==typeof e[n]?le(r.to,t,e[n]):A,i=r.getRelatedKey();if(r.isArray){const e=async(e,t)=>{const n=[],s=t.getStore(r.to);for(const r of e){const e=await a(await s.assertGet(r),t);e&&(delete e[i],n.push(e))}return n};s.push({key:n,getValue:e})}else{const e=async(e,t)=>await a(await t.getStore(r.to).assertGet(e),t);s.push({key:n,getValue:e})}break}case te.Property:case te.PrimaryKey:r&&s.push({key:n})}return r?async(e,t)=>{if(!ue(a,e))return;const n={};for(const{key:r,getValue:o}of s)n[r]=o?await o(e[r],t):e[r];return n}:async(e,t)=>{if(ue(a,e)){for(const{key:n,getValue:r}of s)e[n]=await r(e[n],t);return e}}}return e=>ue(a,e)?e:void 0}function de(e,t,n,r){const s=/* @__PURE__ */new Set([e]);if(n){const o=r.getModel(e);for(const e in t){const a=o.getRelation(e),i=g(t[e]);if(a)for(const e of i)if(e&&"object"==typeof e)for(const t in e)if(Object.hasOwn(e,t))switch(t){case"$connect":case"$connectMany":case"$disconnect":case"$disconnectMany":case"$disconnectAll":s.add(a.to);break;case"$delete":case"$deleteMany":case"$deleteAll":v(s,o.getDeletedStores(r));break;case"$create":v(s,de(a.to,e[t],n,r));break;case"$createMany":e[t].forEach(e=>v(s,de(a.to,e,n,r)));break;case"$update":v(s,de(a.to,e[t].data,n,r));break;case"$updateMany":e[t].forEach(e=>v(s,de(a.to,e.data,n,r)))}}}else{const n=r.getModel(e);for(const e in t){const o=n.getRelation(e);if(o)switch(typeof t[e]){case"object":v(s,de(o.to,ye(t[e]),!1,r));break;case"boolean":s.add(o.to)}}}return s}function ye(e){return e.select?e.select:e.include?e.include:{}}class fe{constructor(e,t,n){this.client=e,this.name=t,this.accessedStores=Array.from(de(t,ye(n),!1,this.client)),this.selectClause=le(t,this.client,n)}accessedStores;selectClause;async find(){return await this._find(!1)}async findFirst(){return(await this._find(!0))[0]}async _find(e){const t=this.client.createTransaction("readonly",this.accessedStores);return await t.wrap(async t=>{const n=[],r=t.getStore(this.name);return await r.openCursor(async r=>{const s=await this.selectClause(r.value,t);return s&&n.push(s),(!e||!n.length)&&(r.continue(),!0)}),n})}}function he(e,t,r){return async s=>{if(!s)return!1;const o=s[e.primaryKey];for(const[a,c]of e.relations()){const{onDelete:u}=c.getActions(),l=s[a],d=t.getModel(c.to);switch(u){case"Cascade":if(c.isArray){r.assertIsArray(l);const e=new Set(l),n=he(d,t,r),s=r.getStore(c.to);await s.openCursor(async t=>(e.has(t.value[d.primaryKey])&&await n(t.value),t.continue(),!0)).catch(r.onRejection)}else l&&await we(c.to,t,void 0,void 0,{tx:r,singleton:{id:l}});break;case"SetNull":{if(!l)break;const e=g(l),t=r.getStore(c.to),s=c.getRelatedKey(),a=d.getRelation(s);if(!a)throw new n(`Relation '${c.name}' has an invalid relation key '${c.getRelatedKey()}'`);if(!a.isNullable())throw new n(`Key '${s}' on model '${s}': Non-optional relation cannot have the 'SetNull' action`);for(const n of e){const e=await t.get(n);if(!e)continue;const i=e[s];if(a.isArray){r.assertIsArray(i);const e=i.indexOf(o);if(-1===e)continue;i.splice(e,1)}else e[s]=null;await t.put(e)}break}case"Restrict":if(Array.isArray(l)&&l.length>0||l)throw new i(`Key '${a}' on model '${e.name}' deletion is restricted while there is an active relation`)}}return!0}}async function we(e,t,n,r=!1,s={}){const{singleton:o,finalStep:a=!0}=s,i=t.getModel(e),c=s.tx?s.tx.storeNames:Array.from(i.getDeletedStores(t)),u=ie.create(t.getDb(),c,"readwrite",s.tx);return await u.wrap(async s=>{const c=s.getStore(e);let u=0;const l=he(i,t,s);if(o)await l(await c.assertGet(o.id))&&(await c.delete(o.id),u++);else{const e=ce(n);let t;await c.openCursor(async n=>{const o=n.value;return ue(e,o)&&await l(o)&&(t=p(n.delete()).catch(s.onRejection)),!(r&&u>0)&&(n.continue(),!0)}),t&&a&&await t}return u})}function pe(e){return"string"!=typeof e?String(e):e.replaceAll(/~|\//g,e=>"~"===e?"~0":"~1")}async function me(e,t,n,r){r=ie.create(e.getDb(),[t],"readonly",r);const s=ce(n),a=e.getModel(t);return await r.wrap(async e=>{const n={};return await e.getStore(t).openCursor(async e=>{if(ue(s,e.value)){for(const[t,n]of a.entries())if(X.is(n))if(n.isArray){if(!Array.isArray(e.value[t]))throw new o("Expected array type");const r=[];for(const s of e.value[t])r.push(`/${n.to}/${pe(s)}`);e.value[t]=r}else(n.isOptional&&e.value[t]||!n.isNullable())&&(e.value[t]=`/${n.to}/${pe(e.value[t])}`);else{if(!re.is(n)&&!H.is(n))throw new w(`Unrecognized model field on key '${t}'`);e.value[t]=await q(n.type,e.value[t])}if(n[e.value[a.primaryKey]])throw new w("Duplicate primary key detected "+JSON.stringify(n));n[e.value[a.primaryKey]]=e.value}return e.continue(),!0}),n})}function ge(e,t){const n=[`## ${e.name}`],r=[];for(const[s,o]of e.entries())H.is(o)?r.unshift(s):r.push(s);n.push(r.join(","));for(const s of Object.values(t)){const e=[];for(const t of r)switch(typeof s[t]){case"object":e.push(JSON.stringify(s[t]));break;case"undefined":e.push("");break;default:e.push(String(s[t]))}n.push(e.join(","))}return n.join("\n")}class be{constructor(e,t,n){this.name=e,this.content=t,this.extension=n}toFile(e=`${this.name}_dump.${this.extension}`,t){return new File([this.content],e,t)}download(e=`${this.name}_dump.${this.extension}`,t){const n=URL.createObjectURL(this.toFile(e,t)),r=document.createElement("a");r.href=n,r.download=e,document.body.appendChild(r),r.click(),document.body.removeChild(r),URL.revokeObjectURL(n)}static toJson(e,t,n){return new this(e,JSON.stringify(t,void 0,n?.pretty??1?4:void 0),"json")}static toCsvStore(e,t){return new this(e.name,ge(e,t),"csv")}static toCsvDb(e,t,n){const r=[`# ${e.name}`];for(const s of t)r.push(ge(e.getModel(s),n[s]));return new this(e.name,r.join("\n"),"csv")}}class Se{constructor(e,t){this.db=e,this.models=t,this.name=this.db.name,this.version=this.db.version,this.stores={};for(const n of this.models.keys())this.stores[n]=this.createInterface(n)}name;version;stores;getDb(){return this.db}getStore(e){return this.stores[e]}getStoreNames(){return this.models.keys()}createTransaction(e,t,n){return new ie(this.db,t,e,n)}async drop(){await p(window.indexedDB.deleteDatabase(this.name))}async dump(e,t,n){const r=await async function(e,t){const n={};t=t||e.getStoreNames();const r=e.createTransaction("readonly",t);for(const s of t)n[s]=await me(e,s,void 0,r);return n}(this,t);switch(e){case"json":return be.toJson(this.name,r,n);case"csv":return be.toCsvDb(this,t||this.getStoreNames(),r)}}deleteAllStores(){for(const e of this.models.keys())this.db.deleteObjectStore(e)}deleteStore(e){Array.isArray(e)||(e=[e]);for(const t of e)this.db.deleteObjectStore(t)}getModel(e){const t=this.models.getModel(e);if(!t)throw new c(`Model with name '${e}' not found`);return t}getAccessedStores(e,t,n,r){return r?r.storeNames:Array.from(de(e,t,n,this))}createInterface(e){return{add:async(t,n)=>await this.add(e,t,{tx:n}),addMany:async(t,n)=>{if(!n){const r=/* @__PURE__ */new Set;for(const n of t)v(r,de(e,n,!0,this));n=this.createTransaction("readwrite",Array.from(r))}const r=[];for(const s of t)r.push(await this.add(e,s,{tx:n}));return r},findFirst:async(t,n)=>(await this.find(e,t,!0,{tx:n}))[0],find:async(t,n)=>await this.find(e,t,!1,{tx:n}),get:async t=>{const n=this.createTransaction("readonly",e);return await n.getStore(e).get(t)},update:async(t,n)=>(await this.update(e,{data:n},!0,{singleton:{id:t}}))[0],updateFirst:async(t,n)=>(await this.update(e,t,!0,{tx:n}))[0],updateMany:async(t,n)=>await this.update(e,t,!1,{tx:n}),compileQuery:t=>new fe(this,e,t),delete:async t=>await we(e,this,void 0,void 0,{singleton:{id:t}})>0,deleteFirst:async t=>await we(e,this,t,!0)>0,deleteMany:async t=>await we(e,this,t,!1),dump:async(t,n,r)=>{const s=await me(this,e,n);switch(t){case"json":return be.toJson(e,s,r);case"csv":return be.toCsvStore(this.getModel(e),s)}}}}async add(e,t,n={}){let{tx:r}=n;const{relation:o}=n,i=this.getAccessedStores(e,t,!0,r);return r=ie.create(this.db,i,"readwrite",r),await r.wrap(async n=>{const r=n.getStore(e),i=this.getModel(e),c=i.getPrimaryKey(),u=o?{[o.key]:i.getRelation(o.key)?.isArray?[o.id]:o.id}:{},l=c.isAutoIncremented()?{...u}:{...u,[i.primaryKey]:t[i.primaryKey]??c.genKey()},d=await r.add(l),y={},f=/* @__PURE__ */new Set;for(const o in t){f.add(o);const r=t[o];switch(i.keyType(o)){case te.Invalid:throw new s(`Key '${o}' does ont exist on model '${e}'`);case te.Property:{const e=i.parseField(o,r);if(!e)throw new a;if(!e.success)throw new s(`Key '${o}' has the following validation error: ${e.error}`);y[o]=e.data;break}case te.Relation:{if(!r)continue;const e=g(r),t=i.getRelation(o);if(t.isArray&&(y[o]=[],"$createMany"in r||"$connectMany"in r)){const t=[];for(const e of r.$createMany??[])t.push({$create:e});for(const e of r.$connectMany??[])t.push({$connect:e});e.push(...t)}const a=this.getModel(t.to).getRelation(t.getRelatedKey()),c=/* @__PURE__ */new Set;for(const r of e){const e=m(r)[0];if(!e)throw new s(`Key '${o}' cannot be an empty connection object`);switch(e){case"$connect":{const i=r[e];if(c.has(i))throw new s(`Primary key '${i}' was already used for a connection`);if(c.add(i),!a)throw new s(`Could not find corresponding relation '${t.name}'`);await this.connectDocument(t,d,i,n),t.isArray?y[o].push(i):y[o]=i;break}case"$create":{const s=await this.add(t.to,r[e],{tx:n,relation:{id:d,key:t.getRelatedKey()}});t.isArray?y[o].push(s):y[o]=s;break}case"$connectMany":case"$createMany":break;default:throw new s(`Connection Object on key '${o}' has an unknown key '${e}'`)}if(!t.isArray)break}break}case te.PrimaryKey:}}const h=Array.from(new Set(i.keys()).difference(f));for(const e of h)switch(i.keyType(e)){case te.Property:{const t=i.parseField(e,void 0);if(!t)throw new a("A parsing error occurred");if(!t.success)throw new s(`Key '${e}' is missing`);y[e]=t.data;break}case te.Relation:{const t=i.getRelation(e),n=u[e];if(t.isArray)y[e]=n??[];else if(t.isOptional)y[e]=n??null;else{if(!n)throw new s(`Required relation '${e}' is not defined`);y[e]=n}break}case te.Invalid:case te.PrimaryKey:}return await r.put({[i.primaryKey]:d,...y})})}async clear(e,t){await we(e,this,void 0,!1,t)}async find(e,t,n,r={}){let{tx:s}=r;const o=this.getAccessedStores(e,ye(t),!1,s);s=ie.create(this.db,o,"readonly",s);const a=[];return await s.wrap(async r=>{const s=r.getStore(e),o=le(e,this,t);return await s.openCursor(async e=>{const t=await o(e.value,r);return t&&a.push(t),(!n||!a.length)&&(e.continue(),!0)}),a})}async update(e,t,n,r={}){const{singleton:o}=r,i=r.singleton?t:t.data,c=this.getAccessedStores(e,i,!0,r.tx),d=ie.create(this.db,c,"readwrite",r.tx);return await d.wrap(async r=>{const c=r.getStore(e),d=this.getModel(e),y=[];for(const e of m(i))switch(d.keyType(e)){case te.Property:y.push({key:e,isRelation:!1,updateFn:"function"==typeof i[e]?i[e]:()=>i[e]});break;case te.Relation:{const t=g(i[e]);if(!t)continue;const n=[];for(const e of t)for(const t in e){switch(t){case"$createMany":case"$connectMany":case"$updateMany":case"$deleteMany":case"$disconnectMany":{const r=t.substring(0,t.length-4);for(const s of e[t])n.push([r,s]);break}default:n.push([t,e[t]])}break}y.push({actions:n,key:e,isRelation:!0,relation:d.getRelation(e)});break}case te.PrimaryKey:throw new l("Primary key field cannot be updated");case te.Invalid:default:throw new a(`Unknown key '${e}'`)}const f=[],h=async e=>{const t=e[d.primaryKey];for(const{key:n,...o}of y){const a=o.relation;if(o.isRelation)for(const[i,c]of o.actions)switch(i){case"$connect":e[n]&&!a.isArray&&await this.disconnectDocument(a,t,e[n],r).catch(r.onRejection),await this.connectDocument(a,t,c,r).catch(r.onRejection),a.isArray?e[n].push(c):e[n]=c;break;case"$create":{const s=await this.add(a.to,c,{tx:r,relation:{id:t,key:a.getRelatedKey()}});a.isArray?e[n].push(s):e[n]=s;break}case"$delete":if(!a.isNullable())throw new s("Item cannot be deleted, relation is required");e[n]=a.isArray&&Array.isArray(e[n])?e[n].filter(e=>e!==c):null,await we(a.to,this,{},!0,{tx:r,singleton:{id:c}});break;case"$disconnect":{if(!a.isNullable())throw new s("Item cannot be disconnected, relation is required");if(!e[n]||0===e[n]?.lenth)break;const o=this.getModel(a.to).getRelation(a.getRelatedKey());await this.disconnectDocument(a,t,o.isArray?c:e[n],r).catch(r.onRejection),e[n]=a.isArray&&Array.isArray(e[n])?e[n].filter(e=>e!==c):null;break}case"$update":a.isArray?await this.update(a.to,c,!1,{tx:r}):null!=e[n]&&await this.update(a.to,c,!1,{tx:r,singleton:{id:t}});break;case"$deleteAll":if(c&&a.isArray&&Array.isArray(e[n])){const t=this.getModel(a.to),s=new Set(e[n]);await we(a.to,this,{[t.primaryKey]:e=>s.has(e)},!1,{tx:r}),e[n]=[]}break;case"$disconnectAll":if(c&&a.isArray&&Array.isArray(e[n])){for(const s of e[n])await this.disconnectDocument(a,t,s,r);e[n]=[]}}else e[n]=o.updateFn(e[n])}return e};if(o){const e=await c.get(o.id);if(!e)throw new u(`${d.name} with priamry key '${o.id}' not found`);const t=await h(e).catch(r.onRejection);return await c.put(t),[t]}{const e=ce(t.where);return await c.openCursor(async t=>{const s=t.value;if(ue(e,s)){const e=await h(s).catch(r.onRejection);if(await p(t.update(e)).then(()=>f.push(e)).catch(r.onRejection),n)return!1}return t.continue(),!0}),f}})}async connectDocument(e,t,n,r){const s=r.getStore(e.to),o=await s.get(n);if(!o)throw new u(`Document with Primary Key '${n}' could not be found in model '${e.to}'`);const a=e.getRelatedKey(),i=this.getModel(e.to).getRelation(a),c=o[a];if(i.isArray&&Array.isArray(c))c.includes(t)||c.push(t);else{if(c)throw new h;o[a]=t}return await s.put(o).catch(r.onRejection),n}async disconnectDocument(e,t,n,r){const s=r.getStore(e.to),o=await s.get(n);if(!o)throw new u(`Document with Primary Key '${n}' could not be found in model '${e.to}'`);const a=this.getModel(e.to).getRelation(e.getRelatedKey());if(a.isArray)o[e.getRelatedKey()].filter(e=>e!==t);else{if(!a.isOptional)throw new h;o[e.getRelatedKey()]=null}return await s.put(o).catch(r.onRejection),n}}class Ae{constructor(e,t){this.name=e,this.names=t,this.models={}}models;defineModel(e,t){if("object"==typeof e&&oe.is(e))return this.models[e.name]=e,e;{if(!t)throw new Error("Model Fields must be defined");const n=new oe(e,t);return this.models[e]=n,n}}compile(e){return new ve(this.name,e)}}class ve{constructor(e,t){this.name=e,this.models=t,this.modelKeys=m(this.models),this.schemas={};for(const r of this.modelKeys){const e=this.models[r],t={};for(const[s,o]of e.entries())if(re.is(o))t[s]=o.type;else if(X.is(o)){const{onDelete:a}=o.getActions(),i=this.models[o.to],c=i.getPrimaryKey();t[s]=c.type,o.isOptional?t[s]=L(t[s]):o.isArray&&(t[s]=x(t[s]));let u=!!o.getRelatedKey();if(!u)for(const[t,r]of i.relations())if(s!==t&&r.to===e.name&&r.name===o.name){if(u=!0,o.setRelatedKey(t),r.setRelatedKey(s),"SetNull"===a&&!r.isNullable())throw new n(`Key '${t}' on model '${i.name}': Non-optional relation cannot have the 'SetNull' action`);break}if(!u)throw new n(`Relation '${o.name}' of model ${r} does not have an equivalent relation on model '${o.to}'`)}else{if(!H.is(o))throw new n(`Unknown field value detected: ${JSON.stringify(o)}`);t[s]=o.type}this.schemas[r]=t}}schemas;modelKeys;getModel(e){return this.models[e]}async createClient(e=1){const t=window.indexedDB.open(this.name,e);t.onupgradeneeded=e=>{const t=e.target.result;for(const n of this.modelKeys){const e=this.models[n];t.objectStoreNames.contains(e.name)||t.createObjectStore(e.name,{autoIncrement:e.getPrimaryKey().isAutoIncremented(),keyPath:e.primaryKey})}};const n=await p(t);return new Se(n,this)}keys(){return[...this.modelKeys]}}const $e=/* @__PURE__ */Object.freeze(/* @__PURE__ */Object.defineProperty({__proto__:null,ArrayRelation:Z,BaseRelation:X,DbClient:Se,FieldTypes:te,Model:oe,OptionalRelation:ee,PrimaryKey:H,Property:re,Relation:Q,Tag:$,Type:B,Typing:J,deserializeType:U,isSubtype:z,isType:G,parseType:Y,serializeType:q,typeToString:V},Symbol.toStringTag,{value:"Module"}));export{Ae as Builder,fe as CompiledQuery,oe as Model,re as Property,e as StoreError,$e as core};
|
|
1
|
+
class e extends Error{code;constructor(e,t){super(`(${e}) ${t}`),this.code=e}}function t(t,n){return class extends e{static code;constructor(e=n){super(t,e)}static of(e){new this(e)}}}const n=t("INVALID_CONFIG","Configuration is invalid"),r=t("INVALID_TX","Transaction is invalid"),s=t("INVALID_ITEM","Item is invalid"),a=t("ASSERTION_FAILED","Assertion failed"),o=t("UNKNOWN","An unknown error occurred"),i=t("DELETE_FAILED","Item could not be deleted"),c=t("NOT_FOUND","Object Store Not Found"),u=t("NOT_FOUND","Document Not Found"),l=t("UPDATE_FAILED","Item could not be updated"),f=t("ADD_FAILED","Item could not be added"),y=t("OPEN_CURSOR","Cursor could not be opened"),d=t("GET_FAILED","Item could not be retrieved"),h=t("OVERWRITE_RELATION","Relation cannot be overwritten"),p=t("EXPORT","Export failed"),w=t("SERIALIZATION_FAILED","Seralization failed"),m=t("DESERIALIZATION_FAILED","De-seralization failed");function g(e,t){return new Promise(t=>{e.onsuccess=()=>{t(e.result)},e.onerror=()=>{}})}function b(e){return Object.keys(e)}function S(e){return Array.isArray(e)||(e=[e]),e}function A(){return crypto.randomUUID()}function v(){/* @__PURE__ */
|
|
2
|
+
return new Date}function $(e){return e}function k(e,t){for(const n of t.keys())e.add(n);return e}var R=/* @__PURE__ */(e=>(e[e.string=0]="string",e[e.number=1]="number",e[e.date=2]="date",e[e.boolean=3]="boolean",e[e.symbol=4]="symbol",e[e.bigint=5]="bigint",e[e.file=6]="file",e[e.void=7]="void",e[e.float=8]="float",e[e.int=9]="int",e[e.unknown=10]="unknown",e[e.literal=11]="literal",e[e.array=12]="array",e[e.set=13]="set",e[e.union=14]="union",e[e.optional=15]="optional",e[e.default=16]="default",e[e.object=17]="object",e[e.tuple=18]="tuple",e[e.custom=19]="custom",e))(R||{});const O={};function j(e){const t=O[e];return t||(O[e]={tag:e})}function K(){return j(R.string)}function N(){return j(R.number)}function D(){return j(R.boolean)}function T(){return j(R.bigint)}function M(){return j(R.symbol)}function I(){return j(R.file)}function x(){return j(R.date)}function _(){return j(R.unknown)}function P(e){return{tag:R.literal,value:e}}function F(e){return{tag:R.array,of:e}}function E(e,t){return{tag:R.default,of:e,value:t}}function L(e){return{tag:R.set,of:e}}function C(e){return{tag:R.union,options:e}}function B(e){return{tag:R.optional,of:e}}function V(e){return{tag:R.custom,...e}}const q=/* @__PURE__ */Object.freeze(/* @__PURE__ */Object.defineProperty({__proto__:null,Array:F,BigInt:T,Boolean:D,Custom:V,Date:x,Default:E,File:I,Float:function(){return j(R.float)},Int:function(){return j(R.int)},Literal:P,Number:N,Object:function(e){return{tag:R.object,props:e}},Optional:B,Set:L,String:K,Symbol:M,Tuple:function(e){return{tag:R.tuple,elements:e}},Union:C,Unknown:_,Void:function(){return j(R.void)},getType:j},Symbol.toStringTag,{value:"Module"}));function z(e){switch(e.tag){case R.void:return"void";case R.literal:return String(e.value);case R.boolean:return"boolean";case R.number:return"number";case R.float:return"float";case R.int:return"integer";case R.bigint:return"bigint";case R.string:return"string";case R.symbol:return"symbol";case R.unknown:return"unknown";case R.date:return"Date";case R.tuple:return`Tuple<${e.elements.map(e=>z(e)).join(", ")}>`;case R.array:return`Array<${z(e.of)}>`;case R.set:return`Set<${z(e.of)}>`;case R.default:case R.optional:return`${z(e.of)} | undefined`;case R.union:return`Union<${e.options.map(e=>z(e)).join(", ")}>`;case R.file:return"File";case R.object:return`{${Object.keys(e.props).map(t=>`${t}: ${z(e.props[t])}`).join(",\n")}}`;case R.custom:return"custom"}}async function U(e,t){if(!W(e,t))throw new w(`Value not of the proper type, expected type '${z(e)}', received '${JSON.stringify(t)}'`);switch(e.tag){case R.literal:case R.boolean:case R.number:case R.float:case R.int:case R.string:return t;case R.void:return;case R.bigint:return Number(t);case R.symbol:return t.description;case R.unknown:return JSON.stringify(t);case R.date:return t.getTime();case R.tuple:{const n=[];for(let r=0;r<t.length;r++)n.push(await U(e.elements[r],t[r]));return n}case R.array:{const n=[];for(const r of t)n.push(U(e.of,r));return await Promise.all(n)}case R.set:{const n=[];for(const r of t.keys())n.push(U(e.of,r));return await Promise.all(n)}case R.optional:if(void 0===t)return;return await U(e.of,t);case R.union:for(const n of e.options)try{return await U(n,t)}catch{}throw new w("Value union could not be serialized");case R.file:if(!(t instanceof File))throw new w("Value is not a valid file");return{data:new Promise((e,n)=>{const r=new FileReader;r.onload=()=>e(r.result),r.onerror=n,r.readAsDataURL(t)}),name:t.name,type:t.type};case R.object:{const n={};for(const r in e.props){const s=e.props[r];if(!(r in t)&&s.tag!==R.optional&&s.tag!==R.default&&s.tag!==R.void)throw new w(`Required property '${r}' not found`);n[r]=await U(s,t[r])}return n}case R.default:return await U(e.of,void 0===t?"function"==typeof e.value?e.value():e.value:t);case R.custom:return e.serialize?await e.serialize(t):JSON.stringify(t)}}async function G(e,t){switch(e.tag){case R.void:return;case R.literal:if(t!==e.value)throw new m(`'${t}' is not equal to literal '${t}'`);return t;case R.boolean:if("boolean"!=typeof t)throw new m(`'${t}' is not a boolean`);return t;case R.int:if("number"!=typeof t||!Number.isInteger(t))throw new m(`'${t}' is not an integer`);return t;case R.float:if("number"!=typeof t||isNaN(t))throw new m(`'${t}' is not a float`);return t;case R.number:if("number"!=typeof t||isNaN(t))throw new m(`'${t}' is not a number`);return t;case R.bigint:if("number"!=typeof t||isNaN(t))throw new m(`'${t}' is not a bigint`);return BigInt(t);case R.string:if("string"!=typeof t)throw new m(`'${t}' is not a string`);return t;case R.symbol:if("string"!=typeof t)throw new m(`'${t}' is not a symbol`);return Symbol.for(t);case R.date:if("number"!=typeof t||isNaN(t))throw new m(`'${t}' is not a date timestamp`);return new Date(t);case R.tuple:{if(!Array.isArray(t))throw new m(`'${t}' is not an array`);const n=[];for(let r=0;r<t.length;r++)n.push(await G(e.elements[r],t[r]));return n}case R.array:{if(!Array.isArray(t))throw new m(`'${t}' is not an array`);const n=[];for(const r of t)n.push(G(e.of,r));return await Promise.all(n)}case R.set:{if(!Array.isArray(t))throw new m(`'${t}' is not an array`);const n=[];for(const r of t)n.push(G(e.of,r));return new Set(await Promise.all(n))}case R.optional:if(void 0===t)return;return G(e.of,t);case R.unknown:return"string"!=typeof t?t:JSON.parse(t);case R.union:for(const n of e.options)try{return await G(n,t)}catch{}throw new m("Value did not match the union");case R.file:{if(!(t&&"object"==typeof t&&"data"in t&&"name"in t&&"type"in t&&"string"==typeof t.data&&"string"==typeof t.name&&"string"==typeof t.type))throw new m("Value is not a valid file schema");const e=Buffer.from(t.data.replace(/^data:.+;base64,/,""),"base64");return new File([e],t.name,{type:t.type})}case R.default:return void 0===t?e.value:G(e.of,t);case R.custom:if(e.isType(t))return e.deserialize?await e.deserialize(t):JSON.parse(String(t));throw new m("Value is not valid");case R.object:{if(!t||"object"!=typeof t)throw new m("Value is not an object");const n={};for(const r in e.props){const s=e.props[r];if(!(r in t)&&s.tag!==R.optional)throw new m(`Required property '${r}' not found`);n[r]=await G(s,t[r])}return n}}}function Y(e,t){if(e.tag!==t.tag)return!1;switch(e.tag){case R.literal:return e.value===t.value;case R.optional:case R.default:case R.set:case R.array:return Y(e.of,t.of);case R.union:if(e.options.length!==t.options.length)return!1;for(let n=0;n<e.options.length;n++)if(!Y(e.options[n],t.options[n]))return!1;return!0;case R.tuple:if(e.elements.length!==t.elements.length)return!1;for(let n=0;n<e.elements.length;n++)if(!Y(e.elements[n],t.elements[n]))return!1;return!0;case R.object:if(Object.keys(e.props).length!==Object.keys(t.props).length)return!1;for(const n in e.props){if(!(n in t.props))return!1;if(!Y(e.props[n],t.props[n]))return!1}return!0;case R.custom:return e===t;default:return!0}}function J(e,t){switch(e.tag){case R.literal:return t.tag===R.literal&&t.value===e.value;case R.number:return t.tag===e.tag||t.tag===R.literal&&typeof t.value===z(e)||t.tag===R.float||t.tag===R.int;case R.boolean:case R.symbol:case R.string:case R.bigint:case R.int:case R.float:return t.tag===e.tag||t.tag===R.literal&&typeof t.value===z(e);case R.unknown:return!0;case R.date:case R.file:case R.void:return t.tag===e.tag;case R.optional:case R.default:case R.set:case R.array:return t.tag===e.tag&&J(e.of,t.of);case R.union:if(t.tag===R.union){for(const n of t.options)if(!J(e,n))return!1;return!0}return e.options.some(e=>J(e,t));case R.tuple:if(t.tag!==R.tuple)return!1;for(let n=0;n<e.elements.length;n++)if(!J(e.elements[n],t.elements[n]))return!1;return!0;case R.object:if(t.tag!==R.object)return!1;for(const n in t.props){if(!e.props[n])return!1;if(!J(e.props[n],t.props[n]))return!1}return!0;case R.custom:return e===t}}function W(e,t){switch(e.tag){case R.void:return void 0===t;case R.literal:return t===e.value;case R.boolean:return"boolean"==typeof t;case R.number:return"number"==typeof t;case R.bigint:return"bigint"==typeof t;case R.string:return"string"==typeof t;case R.symbol:return"symbol"==typeof t;case R.unknown:return!0;case R.float:return"number"==typeof t&&!isNaN(t);case R.int:return"number"==typeof t&&Number.isInteger(t);case R.date:return t instanceof Date&&!isNaN(t.getTime());case R.tuple:return Array.isArray(t)&&t.length===e.elements.length&&t.every((t,n)=>W(e.elements[n],t));case R.array:return Array.isArray(t)&&t.every(t=>W(e.of,t));case R.set:return t instanceof Set&&Array.from(t).every(t=>W(e.of,t));case R.optional:case R.default:return void 0===t||W(e.of,t);case R.union:return e.options.some(e=>W(e,t));case R.file:return t instanceof File;case R.object:return!(!t||"object"!=typeof t)&&Object.keys(e.props).every(n=>W(e.props[n],t[n]));case R.custom:return e.isType(t)}}function H(e,t){if(W(e,t)){switch(e.tag){case R.custom:if(e.parse)try{return{success:!0,data:e.parse(t)}}catch(n){return{success:!1,error:String(n)}}break;case R.default:return void 0===t?{success:!0,data:e.value}:{success:!0,data:t}}return{success:!0,data:t}}return{success:!1,error:`Value is not a valid '${z(e)}'`}}const X=/* @__PURE__ */Object.freeze(/* @__PURE__ */Object.defineProperty({__proto__:null,Tag:R,Type:q,deserializeType:G,isExactType:Y,isSubtype:J,isType:W,parseType:H,serializeType:U,typeToString:z},Symbol.toStringTag,{value:"Module"})),Z=Symbol.for("primaryKey");class Q{symbol=Z;genFn;autoGenerate;type;constructor(e,t){if(e){if(e.tag>R.date)throw new n("Invalid Primary Key Type");this.type=e,t?(this.autoGenerate=!0,this.genFn=t):this.autoGenerate=!1}else this.autoGenerate=!1,this.type=N()}getType(){return this.type}generator(e){return this.genFn=e,this.autoGenerate=!0,this}autoIncrement(){if(this.type.tag===R.number)return this.genFn=void 0,this.autoGenerate=!0,this;throw new n("Primary key must be a number to use autoIncrement()")}uuid(){if(!window.isSecureContext)throw new Error("Window is not in a secure context");return new Q(K(),A)}date(){return new Q(x(),v)}genKey(){if(this.genFn)return this.genFn();throw new Error("Generator function not defined")}isAutoIncremented(){return this.autoGenerate&&!this.genFn}static is(e){return e?.symbol===Z}static compareKeyValue(e,t){if(typeof e!=typeof t)return!1;switch(typeof e){case"string":case"number":return e===t;case"object":return e.getTime()===t.getTime();default:return!1}}static validKeyTag=C([K(),N(),x()])}class ee{constructor(e,t="",n=!1,r=!1,s){this.to=e,this.name=t,this.isOptional=n,this.isArray=r,this.relatedKey="",this.actions={onDelete:s||"Restrict"}}static SYMBOL=Symbol.for("baseRelation");BASE_SYMBOL=ee.SYMBOL;actions;relatedKey;getActions(){return{...this.actions}}isNullable(){return this.isArray||this.isOptional}setRelatedKey(e){this.relatedKey=e}getRelatedKey(){return this.relatedKey}toString(){return`${this.isArray?"Array":this.isOptional?"Optional":"Standard"} relation from this model to model '${this.to}' on key '${this.relatedKey}'`}getBaseSymbol(){return this.BASE_SYMBOL}static is(e){return"getBaseSymbol"in e&&e.getBaseSymbol()===ee.SYMBOL}}class te extends ee{static R_SYMBOL=Symbol.for("relation");symbol=te.R_SYMBOL;constructor(e,t={}){super(e,t.name,!1,!1,t.onDelete)}array({onDelete:e}={}){return new ne(this.to,this.name,e)}optional({onDelete:e}={}){return new re(this.to,this.name,e)}onDelete(e){return this.actions.onDelete=e,this}static is(e){return e?.symbol===this.R_SYMBOL}}class ne extends ee{static A_SYMBOL=Symbol.for("arrayRelation");symbol=ne.A_SYMBOL;constructor(e,t,n="None"){super(e,t,!1,!0,n)}static is(e){return e?.symbol===this.A_SYMBOL}}class re extends ee{static O_SYMBOL=Symbol.for("optionalRelation");symbol=re.O_SYMBOL;constructor(e,t,n="None"){super(e,t,!0,!1,n)}static is(e){return e?.symbol===this.O_SYMBOL}}var se=/* @__PURE__ */(e=>(e[e.Property=0]="Property",e[e.Relation=1]="Relation",e[e.PrimaryKey=2]="PrimaryKey",e[e.Invalid=3]="Invalid",e))(se||{});const ae=Symbol.for("property");class oe{constructor(e,t){this.type=e,this.options={unique:t?.unique??!1}}symbol=ae;hasDefault=!1;options;unique(){switch(this.type.tag){case R.boolean:case R.string:case R.number:case R.symbol:return this.options.unique=!0,this;default:throw new Error("A non-primitive cannot be a unique value")}}hasDefaultValue(){return this.hasDefault}static relation(e,t){return new te(e,t)}static primaryKey(e="number"){return new Q(this.nameToType(e))}static nameToType(e){switch(e){case"boolean":return D();case"bigint":return T();case"number":return N();case"string":return K();case"symbol":return M();default:return _()}}static is(e){return"object"==typeof e&&e?.symbol===ae}array(){return new oe(F(this.type),this.options)}default(e){return this.hasDefault=!0,new oe(E(this.type,e),this.options)}optional(){return new oe(B(this.type),this.options)}static array(e,t){return new oe(F(e.type),t)}static boolean(e){return new oe(D(),e)}static custom(e,t){return new oe(V({isType:t=>e(t).success,serialize:t?.serialize,deserialize:t?.deserialize}),t)}static date(e){return new oe(x(),e)}static file(e){return new oe(I(),e)}static literal(e,t){return new oe(P(e),t)}static number(e){return new oe(N(),e)}static string(e){return new oe(K(),e)}static set(e,t){return new oe(L(e.type),t)}static union(e,t){return new oe(C(e.map(e=>e.type)),t)}static generateArrayValidator(e){return t=>{if(Array.isArray(t)){const n=[];for(const r of t){const t=e(r);if(!t.success)return t;n.push(t.data)}return{success:!0,data:n}}return{success:!1,error:"Value is not an array"}}}}const ie=Symbol.for("model");class ce{constructor(t,n){this.name=t,this.fields=n,this.fieldKeys=b(n);for(const e of this.fieldKeys){const t=this.fields[e];ee.is(t)&&t.to!==this.name&&this.relationLinks.add(t.to)}const r=this.fieldKeys.find(e=>Q.is(this.fields[e]));if(!r)throw new e("INVALID_CONFIG",`Model ${this.name} has no primary key`);this.primaryKey=r}symbol=ie;fieldKeys;relationLinks=/* @__PURE__ */new Set;cache={};primaryKey;get(e){return this.fields[e]}getPrimaryKey(){return this.fields[this.primaryKey]}defineKeyGen(e){return this.getPrimaryKey().generator(e),this}getRelation(e){const t=this.fields[e];if(t&&ee.is(t))return t}keyType(e){const t=this.fields[e];return t?oe.is(t)?se.Property:ee.is(t)?se.Relation:Q.is(t)?se.PrimaryKey:se.Invalid:se.Invalid}links(){return this.relationLinks.keys()}*relations(){for(const e of this.fieldKeys)ee.is(this.fields[e])&&(yield[e,this.fields[e]])}*entries(){for(const e of this.fieldKeys)yield[e,this.fields[e]]}keys(){return this.fieldKeys}parseField(e,t){return oe.is(this.fields[e])?H(this.fields[e].type,t):null}getDeletedStores(e){if(this.cache.delete)return this.cache.delete;const t=/* @__PURE__ */new Set,n=[this.name];let r;for(;n.length>0;){const s=n.shift();if(t.has(s))continue;r=e.getModel(s);const a=r.cache.delete;if(a)k(t,a);else{t.add(s);for(const e of r.links())t.has(e)||n.push(e)}}return this.cache.delete=t,t}static is(e){return e?.symbol===ie}}class ue{constructor(e,t){this.tx=e,this.internal=t}add(e){return this.handleRequest(this.internal.add(e),()=>new f)}get(e){return this.handleRequest(this.internal.get(e),()=>new d)}async assertGet(e){const t=await this.handleRequest(this.internal.get(e),()=>new d);if(!t)throw this.tx.abort(new u);return t}put(e){return this.handleRequest(this.internal.put(e),()=>new l)}delete(e){return this.handleRequest(this.internal.delete(e),()=>new i)}async openCursor(t,n={}){const r=n.onError||(()=>new y),s=this.internal.openCursor(n.query,n.direction);await new Promise((n,a)=>{s.onsuccess=async s=>{try{s.target||a(this.tx.abort(r()));const e=s.target.result;e&&await t(e,this.tx)||n()}catch(i){a(this.tx.abort(i instanceof e?i:new o(String(i))))}},s.onerror=()=>{a(this.tx.abort(r()))}})}handleRequest(e,t){return new Promise(n=>{e.onsuccess=()=>{n(e.result)},e.onerror=()=>{throw this.tx.abort(t())}})}}class le{internal;status;error=null;storeNames;inWrap=!1;onRejection=t=>{throw t instanceof e?this.abort(t):this.abort(new o(String(t)))};objectStores;constructor(e,t,n,r={}){e instanceof le?(this.internal=e.getInternal(),this.storeNames=e.storeNames,this.status=e.status,this.error=e.error,this.objectStores=e.getAllStores()):(this.internal=e.transaction(t,n),this.status=0,this.storeNames=Array.from(this.internal.objectStoreNames),this.objectStores=new Map(this.storeNames.map(e=>[e,this.getObjectstore(e)])),this.internal.onabort=this.registerHandler(1,r.onAbort),this.internal.onerror=this.registerHandler(3,r.onError),this.internal.oncomplete=this.registerHandler(2,r.onComplete))}static create(e,t,n,r){return r||new le(e,t,n)}abort(e){return 1!==this.status&&this.internal.abort(),this.status=1,this.error=e,this.error}commit(){this.internal.commit()}getInternal(){return this.internal}getStore(e){const t=this.objectStores.get(e);if(!t)throw this.abort(new r(`Store '${e}' is not a part of this transaction`));return t}getAllStores(){return this.objectStores}get mode(){return this.internal.mode}is(e){return this.status===e}contains(e){Array.isArray(e)||(e=[e]);for(const t of e)if(!this.internal.objectStoreNames.contains(t))return!1;return!0}assertIsArray(e,t="Value is not an array"){if(!Array.isArray(e))throw this.abort(new a(t))}getObjectstore(e){try{return new ue(this,this.internal.objectStore(e))}catch{throw this.abort(new c(`No ObjectStore with the name '${e}' found`))}}registerHandler(e,t=()=>{}){return n=>{this.status=e,t(this,n)}}async wrap(t){if(this.inWrap)return await t(this);this.inWrap=!0;try{const e=await t(this);return this.inWrap=!1,e}catch(n){throw this.inWrap=!1,n instanceof e?this.abort(n):this.abort(new o(JSON.stringify(n)))}}}function fe(e){if(!e)return[];const t=[];for(const n in e)if(Object.hasOwn(e,n))switch(typeof e[n]){case"function":t.push([n,!0,e[n]]);break;case"object":if(e[n]instanceof Date){const r=e[n];t.push([n,!0,e=>e instanceof Date&&e.getTime()===r.getTime()])}break;default:t.push([n,!1,e[n]])}return t}function ye(e,t){if(!t||"object"!=typeof t)return!1;for(const n of e)if(n[1]){if(!n[2](t[n[0]]))return!1}else if(n[2]!==t[n[0]])return!1;return!0}function de(e,t,n={},r){const a=t.getModel(e);if(n.include&&n.select)throw new s("include and select cannot both be defined");const o=fe(n.where),i=n.select?"select":n.include?"include":"";if(i){const e=n[i],r=!!n.select,s=[];for(const n in e)if(Object.hasOwn(e,n)&&e[n])switch(a.keyType(n)){case se.Relation:{const r=a.getRelation(n),o="object"==typeof e[n]?de(r.to,t,e[n]):$,i=r.getRelatedKey();if(r.isArray){const e=async(e,t)=>{const n=[],s=t.getStore(r.to);for(const r of e){const e=await o(await s.assertGet(r),t);e&&(delete e[i],n.push(e))}return n};s.push({key:n,getValue:e})}else{const e=async(e,t)=>await o(await t.getStore(r.to).assertGet(e),t);s.push({key:n,getValue:e})}break}case se.Property:case se.PrimaryKey:r&&s.push({key:n})}return r?async(e,t)=>{if(!ye(o,e))return;const n={};for(const{key:r,getValue:a}of s)n[r]=a?await a(e[r],t):e[r];return n}:async(e,t)=>{if(ye(o,e)){for(const{key:n,getValue:r}of s)e[n]=await r(e[n],t);return e}}}return e=>ye(o,e)?e:void 0}function he(e,t,n,r){const s=/* @__PURE__ */new Set([e]);if(n){const a=r.getModel(e);for(const e in t){const o=a.getRelation(e),i=S(t[e]);if(o)for(const e of i)if(e&&"object"==typeof e)for(const t in e)if(Object.hasOwn(e,t))switch(t){case"$connect":case"$connectMany":case"$disconnect":case"$disconnectMany":case"$disconnectAll":s.add(o.to);break;case"$delete":case"$deleteMany":case"$deleteAll":k(s,a.getDeletedStores(r));break;case"$create":k(s,he(o.to,e[t],n,r));break;case"$createMany":e[t].forEach(e=>k(s,he(o.to,e,n,r)));break;case"$update":k(s,he(o.to,e[t].data,n,r));break;case"$updateMany":e[t].forEach(e=>k(s,he(o.to,e.data,n,r)))}}}else{const n=r.getModel(e);for(const e in t){const a=n.getRelation(e);if(a)switch(typeof t[e]){case"object":k(s,he(a.to,pe(t[e]),!1,r));break;case"boolean":s.add(a.to)}}}return s}function pe(e){return e.select?e.select:e.include?e.include:{}}class we{constructor(e,t,n){this.client=e,this.name=t,this.accessedStores=Array.from(he(t,pe(n),!1,this.client)),this.selectClause=de(t,this.client,n)}accessedStores;selectClause;async find(){return await this._find(!1)}async findFirst(){return(await this._find(!0))[0]}async _find(e){const t=this.client.createTransaction("readonly",this.accessedStores);return await t.wrap(async t=>{const n=[],r=t.getStore(this.name);return await r.openCursor(async r=>{const s=await this.selectClause(r.value,t);return s&&n.push(s),(!e||!n.length)&&(r.continue(),!0)}),n})}}function me(e,t,r){return async s=>{if(!s)return!1;const a=s[e.primaryKey];for(const[o,c]of e.relations()){const{onDelete:u}=c.getActions(),l=s[o],f=t.getModel(c.to);switch(u){case"Cascade":if(c.isArray){r.assertIsArray(l);const e=new Set(l),n=me(f,t,r),s=r.getStore(c.to);await s.openCursor(async t=>(e.has(t.value[f.primaryKey])&&await n(t.value),t.continue(),!0)).catch(r.onRejection)}else l&&await ge(c.to,t,void 0,void 0,{tx:r,singleton:{id:l}});break;case"SetNull":{if(!l)break;const e=S(l),t=r.getStore(c.to),s=c.getRelatedKey(),o=f.getRelation(s);if(!o)throw new n(`Relation '${c.name}' has an invalid relation key '${c.getRelatedKey()}'`);if(!o.isNullable())throw new n(`Key '${s}' on model '${s}': Non-optional relation cannot have the 'SetNull' action`);for(const n of e){const e=await t.get(n);if(!e)continue;const i=e[s];if(o.isArray){r.assertIsArray(i);const e=i.indexOf(a);if(-1===e)continue;i.splice(e,1)}else e[s]=null;await t.put(e)}break}case"Restrict":if(Array.isArray(l)&&l.length>0||l)throw new i(`Key '${o}' on model '${e.name}' deletion is restricted while there is an active relation`)}}return!0}}async function ge(e,t,n,r=!1,s={}){const{singleton:a,finalStep:o=!0}=s,i=t.getModel(e),c=s.tx?s.tx.storeNames:Array.from(i.getDeletedStores(t)),u=le.create(t.getDb(),c,"readwrite",s.tx);return await u.wrap(async s=>{const c=s.getStore(e);let u=0;const l=me(i,t,s);if(a)await l(await c.assertGet(a.id))&&(await c.delete(a.id),u++);else{const e=fe(n);let t;await c.openCursor(async n=>{const a=n.value;return ye(e,a)&&await l(a)&&(t=g(n.delete()).catch(s.onRejection)),!(r&&u>0)&&(n.continue(),!0)}),t&&o&&await t}return u})}function be(e){return"string"!=typeof e?String(e):e.replaceAll(/~|\//g,e=>"~"===e?"~0":"~1")}async function Se(e,t,n,r){r=le.create(e.getDb(),[t],"readonly",r);const s=fe(n),o=e.getModel(t);return await r.wrap(async e=>{const n={};return await e.getStore(t).openCursor(async e=>{if(ye(s,e.value)){for(const[t,n]of o.entries())if(ee.is(n))if(n.isArray){if(!Array.isArray(e.value[t]))throw new a("Expected array type");const r=[];for(const s of e.value[t])r.push(`/${n.to}/${be(s)}`);e.value[t]=r}else(n.isOptional&&e.value[t]||!n.isNullable())&&(e.value[t]=`/${n.to}/${be(e.value[t])}`);else{if(!oe.is(n)&&!Q.is(n))throw new p(`Unrecognized model field on key '${t}'`);e.value[t]=await U(n.type,e.value[t])}if(n[e.value[o.primaryKey]])throw new p("Duplicate primary key detected "+JSON.stringify(n));n[e.value[o.primaryKey]]=e.value}return e.continue(),!0}),n})}function Ae(e,t){const n=[`## ${e.name}`],r=[];for(const[s,a]of e.entries())Q.is(a)?r.unshift(s):r.push(s);n.push(r.join(","));for(const s of Object.values(t)){const e=[];for(const t of r)switch(typeof s[t]){case"object":e.push(JSON.stringify(s[t]));break;case"undefined":e.push("");break;default:e.push(String(s[t]))}n.push(e.join(","))}return n.join("\n")}class ve{constructor(e,t,n){this.name=e,this.content=t,this.extension=n}toFile(e=`${this.name}_dump.${this.extension}`,t){return new File([this.content],e,t)}download(e=`${this.name}_dump.${this.extension}`,t){const n=URL.createObjectURL(this.toFile(e,t)),r=document.createElement("a");r.href=n,r.download=e,document.body.appendChild(r),r.click(),document.body.removeChild(r),URL.revokeObjectURL(n)}static toJson(e,t,n){return new this(e,JSON.stringify(t,void 0,n?.pretty??1?4:void 0),"json")}static toCsvStore(e,t){return new this(e.name,Ae(e,t),"csv")}static toCsvDb(e,t,n){const r=[`# ${e.name}`];for(const s of t)r.push(Ae(e.getModel(s),n[s]));return new this(e.name,r.join("\n"),"csv")}}class $e{constructor(e,t){this.db=e,this.models=t,this.name=this.db.name,this.version=this.db.version,this.stores={};for(const n of this.models.keys())this.stores[n]=this.createInterface(n)}name;version;stores;getDb(){return this.db}getStore(e){return this.stores[e]}getStoreNames(){return this.models.keys()}createTransaction(e,t,n){return new le(this.db,t,e,n)}async drop(){await g(window.indexedDB.deleteDatabase(this.name))}async dump(e,t,n){const r=await async function(e,t){const n={};t=t||e.getStoreNames();const r=e.createTransaction("readonly",t);for(const s of t)n[s]=await Se(e,s,void 0,r);return n}(this,t);switch(e){case"json":return ve.toJson(this.name,r,n);case"csv":return ve.toCsvDb(this,t||this.getStoreNames(),r)}}deleteAllStores(){for(const e of this.models.keys())this.db.deleteObjectStore(e)}deleteStore(e){Array.isArray(e)||(e=[e]);for(const t of e)this.db.deleteObjectStore(t)}getModel(e){const t=this.models.getModel(e);if(!t)throw new c(`Model with name '${e}' not found`);return t}getAccessedStores(e,t,n,r){return r?r.storeNames:Array.from(he(e,t,n,this))}createInterface(e){return{add:async(t,n)=>await this.add(e,t,{tx:n}),addMany:async(t,n)=>{if(!n){const r=/* @__PURE__ */new Set;for(const n of t)k(r,he(e,n,!0,this));n=this.createTransaction("readwrite",Array.from(r))}const r=[];for(const s of t)r.push(await this.add(e,s,{tx:n}));return r},findFirst:async(t,n)=>(await this.find(e,t,!0,{tx:n}))[0],find:async(t,n)=>await this.find(e,t,!1,{tx:n}),get:async t=>{const n=this.createTransaction("readonly",e);return await n.getStore(e).get(t)},update:async(t,n)=>(await this.update(e,{data:n},!0,{singleton:{id:t}}))[0],updateFirst:async(t,n)=>(await this.update(e,t,!0,{tx:n}))[0],updateMany:async(t,n)=>await this.update(e,t,!1,{tx:n}),compileQuery:t=>new we(this,e,t),delete:async t=>await ge(e,this,void 0,void 0,{singleton:{id:t}})>0,deleteFirst:async t=>await ge(e,this,t,!0)>0,deleteMany:async t=>await ge(e,this,t,!1),dump:async(t,n,r)=>{const s=await Se(this,e,n);switch(t){case"json":return ve.toJson(e,s,r);case"csv":return ve.toCsvStore(this.getModel(e),s)}}}}async add(e,t,n={}){let{tx:r}=n;const{relation:a}=n,i=this.getAccessedStores(e,t,!0,r);return r=le.create(this.db,i,"readwrite",r),await r.wrap(async n=>{const r=n.getStore(e),i=this.getModel(e),c=i.getPrimaryKey(),u=a?{[a.key]:i.getRelation(a.key)?.isArray?[a.id]:a.id}:{},l=c.isAutoIncremented()?{...u}:{...u,[i.primaryKey]:t[i.primaryKey]??c.genKey()},f=await r.add(l),y={},d=/* @__PURE__ */new Set;for(const a in t){d.add(a);const r=t[a];switch(i.keyType(a)){case se.Invalid:throw new s(`Key '${a}' does ont exist on model '${e}'`);case se.Property:{const e=i.parseField(a,r);if(!e)throw new o;if(!e.success)throw new s(`Key '${a}' has the following validation error: ${e.error}`);y[a]=e.data;break}case se.Relation:{if(!r)continue;const e=S(r),t=i.getRelation(a);if(t.isArray&&(y[a]=[],"$createMany"in r||"$connectMany"in r)){const t=[];for(const e of r.$createMany??[])t.push({$create:e});for(const e of r.$connectMany??[])t.push({$connect:e});e.push(...t)}const o=this.getModel(t.to).getRelation(t.getRelatedKey()),c=/* @__PURE__ */new Set;for(const r of e){const e=b(r)[0];if(!e)throw new s(`Key '${a}' cannot be an empty connection object`);switch(e){case"$connect":{const i=r[e];if(c.has(i))throw new s(`Primary key '${i}' was already used for a connection`);if(c.add(i),!o)throw new s(`Could not find corresponding relation '${t.name}'`);await this.connectDocument(t,f,i,n),t.isArray?y[a].push(i):y[a]=i;break}case"$create":{const s=await this.add(t.to,r[e],{tx:n,relation:{id:f,key:t.getRelatedKey()}});t.isArray?y[a].push(s):y[a]=s;break}case"$connectMany":case"$createMany":break;default:throw new s(`Connection Object on key '${a}' has an unknown key '${e}'`)}if(!t.isArray)break}break}case se.PrimaryKey:}}const h=Array.from(new Set(i.keys()).difference(d));for(const e of h)switch(i.keyType(e)){case se.Property:{const t=i.parseField(e,void 0);if(!t)throw new o("A parsing error occurred");if(!t.success)throw new s(`Key '${e}' is missing`);y[e]=t.data;break}case se.Relation:{const t=i.getRelation(e),n=u[e];if(t.isArray)y[e]=n??[];else if(t.isOptional)y[e]=n??null;else{if(!n)throw new s(`Required relation '${e}' is not defined`);y[e]=n}break}case se.Invalid:case se.PrimaryKey:}return await r.put({[i.primaryKey]:f,...y})})}async clear(e,t){await ge(e,this,void 0,!1,t)}async find(e,t,n,r={}){let{tx:s}=r;const a=this.getAccessedStores(e,pe(t),!1,s);s=le.create(this.db,a,"readonly",s);const o=[];return await s.wrap(async r=>{const s=r.getStore(e),a=de(e,this,t);return await s.openCursor(async e=>{const t=await a(e.value,r);return t&&o.push(t),(!n||!o.length)&&(e.continue(),!0)}),o})}async update(e,t,n,r={}){const{singleton:a}=r,i=r.singleton?t:t.data,c=this.getAccessedStores(e,i,!0,r.tx),f=le.create(this.db,c,"readwrite",r.tx);return await f.wrap(async r=>{const c=r.getStore(e),f=this.getModel(e),y=[];for(const e of b(i))switch(f.keyType(e)){case se.Property:y.push({key:e,isRelation:!1,updateFn:"function"==typeof i[e]?i[e]:()=>i[e]});break;case se.Relation:{const t=S(i[e]);if(!t)continue;const n=[];for(const e of t)for(const t in e){switch(t){case"$createMany":case"$connectMany":case"$updateMany":case"$deleteMany":case"$disconnectMany":{const r=t.substring(0,t.length-4);for(const s of e[t])n.push([r,s]);break}default:n.push([t,e[t]])}break}y.push({actions:n,key:e,isRelation:!0,relation:f.getRelation(e)});break}case se.PrimaryKey:throw new l("Primary key field cannot be updated");case se.Invalid:default:throw new o(`Unknown key '${e}'`)}const d=[],h=async e=>{const t=e[f.primaryKey];for(const{key:n,...a}of y){const o=a.relation;if(a.isRelation)for(const[i,c]of a.actions)switch(i){case"$connect":e[n]&&!o.isArray&&await this.disconnectDocument(o,t,e[n],r).catch(r.onRejection),await this.connectDocument(o,t,c,r).catch(r.onRejection),o.isArray?e[n].push(c):e[n]=c;break;case"$create":{const s=await this.add(o.to,c,{tx:r,relation:{id:t,key:o.getRelatedKey()}});o.isArray?e[n].push(s):e[n]=s;break}case"$delete":if(!o.isNullable())throw new s("Item cannot be deleted, relation is required");e[n]=o.isArray&&Array.isArray(e[n])?e[n].filter(e=>e!==c):null,await ge(o.to,this,{},!0,{tx:r,singleton:{id:c}});break;case"$disconnect":{if(!o.isNullable())throw new s("Item cannot be disconnected, relation is required");if(!e[n]||0===e[n]?.lenth)break;const a=this.getModel(o.to).getRelation(o.getRelatedKey());await this.disconnectDocument(o,t,a.isArray?c:e[n],r).catch(r.onRejection),e[n]=o.isArray&&Array.isArray(e[n])?e[n].filter(e=>e!==c):null;break}case"$update":o.isArray?await this.update(o.to,c,!1,{tx:r}):null!=e[n]&&await this.update(o.to,c,!1,{tx:r,singleton:{id:t}});break;case"$deleteAll":if(c&&o.isArray&&Array.isArray(e[n])){const t=this.getModel(o.to),s=new Set(e[n]);await ge(o.to,this,{[t.primaryKey]:e=>s.has(e)},!1,{tx:r}),e[n]=[]}break;case"$disconnectAll":if(c&&o.isArray&&Array.isArray(e[n])){for(const s of e[n])await this.disconnectDocument(o,t,s,r);e[n]=[]}}else e[n]=a.updateFn(e[n])}return e};if(a){const e=await c.get(a.id);if(!e)throw new u(`${f.name} with priamry key '${a.id}' not found`);const t=await h(e).catch(r.onRejection);return await c.put(t),[t]}{const e=fe(t.where);return await c.openCursor(async t=>{const s=t.value;if(ye(e,s)){const e=await h(s).catch(r.onRejection);if(await g(t.update(e)).then(()=>d.push(e)).catch(r.onRejection),n)return!1}return t.continue(),!0}),d}})}async connectDocument(e,t,n,r){const s=r.getStore(e.to),a=await s.get(n);if(!a)throw new u(`Document with Primary Key '${n}' could not be found in model '${e.to}'`);const o=e.getRelatedKey(),i=this.getModel(e.to).getRelation(o),c=a[o];if(i.isArray&&Array.isArray(c))c.includes(t)||c.push(t);else{if(c)throw new h;a[o]=t}return await s.put(a).catch(r.onRejection),n}async disconnectDocument(e,t,n,r){const s=r.getStore(e.to),a=await s.get(n);if(!a)throw new u(`Document with Primary Key '${n}' could not be found in model '${e.to}'`);const o=this.getModel(e.to).getRelation(e.getRelatedKey());if(o.isArray)a[e.getRelatedKey()].filter(e=>e!==t);else{if(!o.isOptional)throw new h;a[e.getRelatedKey()]=null}return await s.put(a).catch(r.onRejection),n}}class ke{constructor(e,t){this.name=e,this.names=t,this.models={}}models;defineModel(e,t){if("object"==typeof e&&ce.is(e))return this.models[e.name]=e,e;{if(!t)throw new Error("Model Fields must be defined");const n=new ce(e,t);return this.models[e]=n,n}}compile(e){return new Re(this.name,e)}}class Re{constructor(e,t){this.name=e,this.models=t,this.modelKeys=b(this.models),this.schemas={};for(const r of this.modelKeys){const e=this.models[r],t={};for(const[s,a]of e.entries())if(oe.is(a))t[s]=a.type;else if(ee.is(a)){const{onDelete:o}=a.getActions(),i=this.models[a.to],c=i.getPrimaryKey();t[s]=c.type,a.isOptional?t[s]=B(t[s]):a.isArray&&(t[s]=F(t[s]));let u=!!a.getRelatedKey();if(!u)for(const[t,r]of i.relations())if(s!==t&&r.to===e.name&&r.name===a.name){if(u=!0,a.setRelatedKey(t),r.setRelatedKey(s),"SetNull"===o&&!r.isNullable())throw new n(`Key '${t}' on model '${i.name}': Non-optional relation cannot have the 'SetNull' action`);break}if(!u)throw new n(`Relation '${a.name}' of model ${r} does not have an equivalent relation on model '${a.to}'`)}else{if(!Q.is(a))throw new n(`Unknown field value detected: ${JSON.stringify(a)}`);t[s]=a.type}this.schemas[r]=t}}schemas;modelKeys;getModel(e){return this.models[e]}async createClient(e=1){const t=window.indexedDB.open(this.name,e);t.onupgradeneeded=e=>{const t=e.target.result;for(const n of this.modelKeys){const e=this.models[n];t.objectStoreNames.contains(e.name)||t.createObjectStore(e.name,{autoIncrement:e.getPrimaryKey().isAutoIncremented(),keyPath:e.primaryKey})}};const n=await g(t);return new $e(n,this)}keys(){return[...this.modelKeys]}}const Oe=/* @__PURE__ */Object.freeze(/* @__PURE__ */Object.defineProperty({__proto__:null,ArrayRelation:ne,BaseRelation:ee,DbClient:$e,FieldTypes:se,Model:ce,OptionalRelation:re,PrimaryKey:Q,Property:oe,Relation:te,Tag:R,Type:q,deserializeType:G,isExactType:Y,isSubtype:J,isType:W,parseType:H,serializeType:U,typeToString:z},Symbol.toStringTag,{value:"Module"}));export{ke as Builder,we as CompiledQuery,ce as Model,oe as Property,e as StoreError,X as Typing,Oe as core};
|
package/dist/model/model.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { DbClient } from '../client
|
|
2
|
-
import { BaseRelation, FieldTypes, PrimaryKey, ValidValue, ParseResult, ValidKey } from '../field';
|
|
3
|
-
import { Dict, Keyof } from '../util-types
|
|
4
|
-
import { FindPrimaryKey, CollectionObject } from './model-types
|
|
1
|
+
import { DbClient } from '../client';
|
|
2
|
+
import { BaseRelation, FieldTypes, PrimaryKey, ValidValue, ParseResult, ValidKey, GetPrimaryKeyType } from '../field';
|
|
3
|
+
import { Dict, Keyof } from '../util-types';
|
|
4
|
+
import { FindPrimaryKey, CollectionObject, RelationlessModelStructure } from './model-types';
|
|
5
5
|
export default class Model<Name extends string, F extends Record<string, ValidValue>, Primary extends FindPrimaryKey<F> = FindPrimaryKey<F>> {
|
|
6
6
|
readonly name: Name;
|
|
7
7
|
private readonly fields;
|
|
@@ -19,6 +19,7 @@ export default class Model<Name extends string, F extends Record<string, ValidVa
|
|
|
19
19
|
constructor(name: Name, fields: F);
|
|
20
20
|
get<K extends Keyof<F>>(key: K): F[K];
|
|
21
21
|
getPrimaryKey(): PrimaryKey<boolean, ValidKey>;
|
|
22
|
+
defineKeyGen(genFn: (model: RelationlessModelStructure<this>) => GetPrimaryKeyType<F[Primary]>): this;
|
|
22
23
|
getRelation<Models extends string>(key: string): BaseRelation<Models, string> | undefined;
|
|
23
24
|
keyType(key: Keyof<F>): FieldTypes;
|
|
24
25
|
links<Names extends string = string>(): SetIterator<Names>;
|
package/dist/typing/tag.d.ts
CHANGED
|
@@ -8,15 +8,18 @@ export declare const enum Tag {
|
|
|
8
8
|
bigint = 5,
|
|
9
9
|
file = 6,
|
|
10
10
|
void = 7,
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
11
|
+
float = 8,
|
|
12
|
+
int = 9,
|
|
13
|
+
unknown = 10,
|
|
14
|
+
literal = 11,
|
|
15
|
+
array = 12,
|
|
16
|
+
set = 13,
|
|
17
|
+
union = 14,
|
|
18
|
+
optional = 15,
|
|
19
|
+
default = 16,
|
|
20
|
+
object = 17,
|
|
21
|
+
tuple = 18,
|
|
22
|
+
custom = 19
|
|
20
23
|
}
|
|
21
24
|
export interface VoidTag {
|
|
22
25
|
tag: Tag.void;
|
|
@@ -27,6 +30,12 @@ export interface StringTag {
|
|
|
27
30
|
export interface NumberTag {
|
|
28
31
|
tag: Tag.number;
|
|
29
32
|
}
|
|
33
|
+
export interface IntTag {
|
|
34
|
+
tag: Tag.int;
|
|
35
|
+
}
|
|
36
|
+
export interface FloatTag {
|
|
37
|
+
tag: Tag.float;
|
|
38
|
+
}
|
|
30
39
|
export interface DateTag {
|
|
31
40
|
tag: Tag.date;
|
|
32
41
|
}
|
|
@@ -65,6 +74,10 @@ export interface UnionTag<V extends TypeTag[] = TypeTag[]> {
|
|
|
65
74
|
tag: Tag.union;
|
|
66
75
|
options: V;
|
|
67
76
|
}
|
|
77
|
+
export interface TupleTag<V extends TypeTag[] = TypeTag[]> {
|
|
78
|
+
tag: Tag.tuple;
|
|
79
|
+
elements: V;
|
|
80
|
+
}
|
|
68
81
|
export interface ObjectTag<P extends Record<string, TypeTag> = Record<string, TypeTag>> {
|
|
69
82
|
tag: Tag.object;
|
|
70
83
|
props: P;
|
|
@@ -81,9 +94,11 @@ export interface CustomTag<V = any, PR = any> {
|
|
|
81
94
|
serialize?: (value: V) => Promisable<unknown>;
|
|
82
95
|
deserialize?: (value: unknown) => Promisable<V>;
|
|
83
96
|
}
|
|
84
|
-
|
|
85
|
-
type
|
|
86
|
-
export type TagToType<T extends TypeTag, Depth extends number = 5> = Depth extends 0 ? any : T extends StringTag ? string : T extends NumberTag ? number : T extends BooleanTag ? boolean : T extends LiteralTag<infer V> ? V : T extends DateTag ? Date : T extends SymbolTag ? symbol : T extends UnknownTag ? unknown : T extends FileTag ? File : T extends BigIntTag ? bigint : T extends
|
|
97
|
+
type Dec = [0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
|
|
98
|
+
export type TypeTag = VoidTag | LiteralTag | StringTag | IntTag | FloatTag | NumberTag | DateTag | BooleanTag | SymbolTag | UnknownTag | FileTag | BigIntTag | SetTag | OptionalTag | UnionTag | ArrayTag | ObjectTag | TupleTag | CustomTag | DefaultTag;
|
|
99
|
+
export type TagToType<T extends TypeTag, Depth extends number = 5> = Depth extends 0 ? any : T extends StringTag ? string : T extends NumberTag ? number : T extends BooleanTag ? boolean : T extends LiteralTag<infer V> ? V : T extends DateTag ? Date : T extends SymbolTag ? symbol : T extends UnknownTag ? unknown : T extends FileTag ? File : T extends BigIntTag ? bigint : T extends TupleTag<infer TEls> ? {
|
|
100
|
+
[K in keyof TEls]: TagToType<TEls[K], Dec[Depth]>;
|
|
101
|
+
} : T extends SetTag<infer T> ? Set<TagToType<T, Dec[Depth]>> : T extends UnionTag<infer TOpts> ? TagToType<TOpts[number], Dec[Depth]> : T extends ArrayTag<infer T> ? TagToType<T, Dec[Depth]>[] : T extends ObjectTag<infer P> ? {
|
|
87
102
|
[K in keyof P]: TagToType<P[K], Dec[Depth]>;
|
|
88
103
|
} : T extends DefaultTag<infer T> | OptionalTag<infer T> ? TagToType<T, Dec[Depth]> | undefined : T extends CustomTag<infer V> ? V : never;
|
|
89
104
|
export {};
|
package/dist/typing/type.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Literable } from '../util-types';
|
|
2
|
-
import { ArrayTag, BigIntTag, BooleanTag, CustomTag, DateTag, DefaultTag, FileTag, LiteralTag, NumberTag, ObjectTag, OptionalTag, SetTag, StringTag, SymbolTag, Tag, TagToType, TypeTag, UnionTag, UnknownTag, VoidTag } from './tag';
|
|
2
|
+
import { ArrayTag, BigIntTag, BooleanTag, CustomTag, DateTag, DefaultTag, FileTag, FloatTag, IntTag, LiteralTag, NumberTag, ObjectTag, OptionalTag, SetTag, StringTag, SymbolTag, Tag, TagToType, TupleTag, TypeTag, UnionTag, UnknownTag, VoidTag } from './tag';
|
|
3
3
|
interface TypeCache {
|
|
4
4
|
[Tag.string]: StringTag;
|
|
5
5
|
[Tag.number]: NumberTag;
|
|
@@ -9,6 +9,8 @@ interface TypeCache {
|
|
|
9
9
|
[Tag.void]: VoidTag;
|
|
10
10
|
[Tag.file]: FileTag;
|
|
11
11
|
[Tag.date]: DateTag;
|
|
12
|
+
[Tag.int]: IntTag;
|
|
13
|
+
[Tag.float]: FloatTag;
|
|
12
14
|
[Tag.unknown]: UnknownTag;
|
|
13
15
|
}
|
|
14
16
|
/**
|
|
@@ -22,6 +24,8 @@ export declare function Number(): NumberTag;
|
|
|
22
24
|
export declare function Boolean(): BooleanTag;
|
|
23
25
|
export declare function BigInt(): BigIntTag;
|
|
24
26
|
export declare function Symbol(): SymbolTag;
|
|
27
|
+
export declare function Int(): IntTag;
|
|
28
|
+
export declare function Float(): FloatTag;
|
|
25
29
|
export declare function Void(): VoidTag;
|
|
26
30
|
export declare function File(): FileTag;
|
|
27
31
|
export declare function Date(): DateTag;
|
|
@@ -33,5 +37,6 @@ export declare function Set<V extends TypeTag>(element: V): SetTag<V>;
|
|
|
33
37
|
export declare function Union<const V extends TypeTag[]>(types: V): UnionTag<V>;
|
|
34
38
|
export declare function Optional<V extends TypeTag>(type: V): OptionalTag<V>;
|
|
35
39
|
export declare function Object<R extends Record<string, TypeTag>>(props: R): ObjectTag<R>;
|
|
40
|
+
export declare function Tuple<const V extends TypeTag[]>(types: V): TupleTag<V>;
|
|
36
41
|
export declare function Custom<V>(opts: Omit<CustomTag<V>, "tag">): CustomTag<V>;
|
|
37
42
|
export {};
|
package/dist/typing/utils.d.ts
CHANGED
|
@@ -14,6 +14,12 @@ export declare function serializeType<T extends TypeTag>(type: T, value: TagToTy
|
|
|
14
14
|
* @returns Type denoted by the type parameter
|
|
15
15
|
*/
|
|
16
16
|
export declare function deserializeType<T extends TypeTag, R = TagToType<T>>(type: T, value: unknown): Promise<R>;
|
|
17
|
+
/**
|
|
18
|
+
* Checks if the given types are exactly equal
|
|
19
|
+
* @param t1 First type to check
|
|
20
|
+
* @param t2 Second type to check
|
|
21
|
+
*/
|
|
22
|
+
export declare function isExactType(t1: TypeTag, t2: TypeTag): boolean;
|
|
17
23
|
/**
|
|
18
24
|
* Checks to see if `test` is a valid subtype of `base`
|
|
19
25
|
* @param base Base type tag
|
package/dist/util-types.d.ts
CHANGED
|
@@ -47,4 +47,10 @@ export type SinglularKey<T extends Record<string, any>> = {
|
|
|
47
47
|
};
|
|
48
48
|
}[keyof T];
|
|
49
49
|
export type Ctor<T> = new (...args: any[]) => T;
|
|
50
|
+
/**
|
|
51
|
+
* If you go over this limit, refactor you application buddy
|
|
52
|
+
*/
|
|
53
|
+
export type RecursionLimit = 10;
|
|
54
|
+
export type PrevDepth = [never, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
|
|
55
|
+
export type Dec<D extends number> = PrevDepth[D] extends number ? PrevDepth[D] : never;
|
|
50
56
|
export {};
|