@idb-orm/core 1.0.11 → 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 +181 -22
- package/dist/client/compiled-query.d.ts +2 -2
- package/dist/client/dump.d.ts +27 -0
- package/dist/client/helpers.d.ts +2 -2
- package/dist/client/index.d.ts +4 -4
- package/dist/client/restore.d.ts +14 -0
- package/dist/client/types/find.d.ts +32 -16
- package/dist/client/types/index.d.ts +7 -7
- package/dist/client/types/mutation.d.ts +25 -24
- package/dist/core.d.ts +1 -5
- package/dist/error.d.ts +46 -1
- package/dist/field/field-types.d.ts +5 -5
- package/dist/field/index.d.ts +1 -1
- package/dist/field/primary-key.d.ts +8 -1
- package/dist/field/property.d.ts +12 -27
- 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-types.d.ts +7 -4
- package/dist/model/model.d.ts +6 -5
- package/dist/object-store.d.ts +5 -2
- package/dist/typing/index.d.ts +3 -0
- package/dist/typing/tag.d.ts +104 -0
- package/dist/typing/type.d.ts +42 -0
- package/dist/typing/utils.d.ts +30 -0
- package/dist/util-types.d.ts +10 -0
- package/dist/utils.d.ts +5 -0
- package/package.json +1 -1
- package/dist/dump/class.d.ts +0 -22
- package/dist/dump/json.d.ts +0 -9
- package/dist/field/type-wrapper.d.ts +0 -108
- package/dist/field/validators.d.ts +0 -13
|
@@ -13,11 +13,18 @@ export default class PrimaryKey<AutoGenerate extends boolean, KeyType extends Va
|
|
|
13
13
|
uuid(): PrimaryKey<true, string>;
|
|
14
14
|
date(): PrimaryKey<true, Date>;
|
|
15
15
|
genKey(): KeyType;
|
|
16
|
-
getSchema(): import('./property.js').ParseFn<string> | import('./property.js').ParseFn<number> | import('./property.js').ParseFn<Date>;
|
|
17
16
|
/**
|
|
18
17
|
* If the internal objectStore "autoIncrement" utility is being used
|
|
19
18
|
* @returns
|
|
20
19
|
*/
|
|
21
20
|
isAutoIncremented(): boolean;
|
|
22
21
|
static is(value: object): value is PrimaryKey<any, any>;
|
|
22
|
+
/**
|
|
23
|
+
* Compares primary key values to see if they are the same
|
|
24
|
+
* @param key1 First key
|
|
25
|
+
* @param key2 Second key
|
|
26
|
+
* @returns true if the keys share the same value AND type, false otherwise
|
|
27
|
+
*/
|
|
28
|
+
static compareKeyValue(key1: ValidKey, key2: ValidKey): boolean;
|
|
29
|
+
static readonly validKeyTag: import('./index.js').UnionTag<[import('./index.js').StringTag, import('./index.js').NumberTag, import('./index.js').DateTag]>;
|
|
23
30
|
}
|
package/dist/field/property.d.ts
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
import { Literable, NoUndefined, Promisable } from '../util-types.js';
|
|
2
2
|
import { FunctionMatch, PropertyUnion, ReferenceActions, RelationOptions, StringValidKeyType } from './field-types.js';
|
|
3
|
-
import { default as PrimaryKey } from './primary-key
|
|
4
|
-
import { Relation } from './relation
|
|
5
|
-
import { TypeTag } from '
|
|
3
|
+
import { default as PrimaryKey } from './primary-key';
|
|
4
|
+
import { Relation } from './relation';
|
|
5
|
+
import { TypeTag } from '../typing';
|
|
6
6
|
export interface PropertyOptions {
|
|
7
7
|
unique: boolean;
|
|
8
8
|
}
|
|
9
9
|
export type PropertyInputOptions = Partial<PropertyOptions>;
|
|
10
10
|
export interface CustomPropertyOptions<T> extends PropertyInputOptions {
|
|
11
|
-
isType: (test: unknown) => boolean;
|
|
12
11
|
serialize?: (value: T) => Promisable<unknown>;
|
|
13
12
|
deserialize?: (value: unknown) => Promisable<T>;
|
|
14
13
|
}
|
|
@@ -25,28 +24,15 @@ export type ParseResult<T> = {
|
|
|
25
24
|
* A function to parse and validate an unknown value. It should also handle applying defaults
|
|
26
25
|
*/
|
|
27
26
|
export type ParseFn<T> = (value: unknown) => ParseResult<T>;
|
|
28
|
-
export declare
|
|
29
|
-
|
|
30
|
-
protected type: TypeTag;
|
|
27
|
+
export declare class Property<Value, HasDefault extends boolean> {
|
|
28
|
+
type: TypeTag;
|
|
31
29
|
readonly symbol: symbol;
|
|
32
30
|
protected hasDefault: HasDefault;
|
|
33
31
|
protected options: PropertyOptions;
|
|
34
|
-
constructor(
|
|
35
|
-
get parse(): (value: unknown) => ParseResult<Value>;
|
|
36
|
-
getType(): TypeTag;
|
|
37
|
-
abstract array(...args: unknown[]): AbstractProperty<Value[], false>;
|
|
38
|
-
abstract default(defaultValue: NoUndefined<Value> | (() => NoUndefined<Value>)): AbstractProperty<NoUndefined<Value>, true>;
|
|
39
|
-
abstract optional(...args: unknown[]): AbstractProperty<Value | undefined, false>;
|
|
40
|
-
static array<T>(..._args: unknown[]): AbstractProperty<T[], false>;
|
|
41
|
-
static boolean(..._: unknown[]): AbstractProperty<boolean, false>;
|
|
42
|
-
static custom<T>(..._: unknown[]): AbstractProperty<T, false>;
|
|
43
|
-
static date(..._: unknown[]): AbstractProperty<Date, false>;
|
|
44
|
-
static literal<const V extends Literable>(_item: V, ..._: unknown[]): AbstractProperty<V, false>;
|
|
45
|
-
static number(..._: unknown[]): AbstractProperty<number, false>;
|
|
46
|
-
static union<const _T extends readonly AbstractProperty<any, boolean>[]>(..._: unknown[]): AbstractProperty<unknown, false>;
|
|
47
|
-
static set<T>(..._: unknown[]): AbstractProperty<Set<T>, false>;
|
|
48
|
-
static string(..._: unknown[]): AbstractProperty<string, false>;
|
|
32
|
+
constructor(type: TypeTag, options?: PropertyInputOptions);
|
|
49
33
|
/**
|
|
34
|
+
* @deprecated This functionality does not work yet
|
|
35
|
+
*
|
|
50
36
|
* Indicates that a field must be unique across all documents
|
|
51
37
|
*
|
|
52
38
|
* **NOTE**: The field type must be a primitive. If this is applied to a non-primitive, it returns `null`
|
|
@@ -56,20 +42,19 @@ export declare abstract class AbstractProperty<Value, HasDefault extends boolean
|
|
|
56
42
|
static relation<To extends string, const Name extends string = never>(to: To, options?: RelationOptions<Name, ReferenceActions>): Relation<To, Name>;
|
|
57
43
|
static primaryKey<V extends StringValidKeyType = "number">(type?: V): PrimaryKey<false, FunctionMatch<V>>;
|
|
58
44
|
static nameToType(typeName: string): TypeTag;
|
|
59
|
-
static is(value: any): value is
|
|
60
|
-
}
|
|
61
|
-
export declare class Property<Value, HasDefault extends boolean> extends AbstractProperty<Value, HasDefault> {
|
|
45
|
+
static is(value: any): value is Property<any, any>;
|
|
62
46
|
array(): Property<Value[], false>;
|
|
63
47
|
default(defaultValue: NoUndefined<Value> | (() => NoUndefined<Value>)): Property<NoUndefined<Value>, true>;
|
|
64
48
|
optional(): Property<Value | undefined, false>;
|
|
65
49
|
static array<T>(item: Property<T, boolean>, options?: PropertyInputOptions): Property<T[], false>;
|
|
66
50
|
static boolean(options?: PropertyInputOptions): Property<boolean, false>;
|
|
67
|
-
static custom<T>(fn: ParseFn<T>, options?:
|
|
51
|
+
static custom<T>(fn: ParseFn<T>, options?: CustomPropertyOptions<T>): Property<T, false>;
|
|
68
52
|
static date(options?: PropertyInputOptions): Property<Date, false>;
|
|
53
|
+
static file(options?: PropertyInputOptions): Property<File, false>;
|
|
69
54
|
static literal<const V extends Literable>(value: V, options?: PropertyInputOptions): Property<V, false>;
|
|
70
55
|
static number(options?: PropertyInputOptions): Property<number, false>;
|
|
71
56
|
static string(options?: PropertyInputOptions): Property<string, false>;
|
|
72
57
|
static set<T>(item: Property<T, boolean>, options?: PropertyInputOptions): Property<Set<T>, false>;
|
|
73
|
-
static union<const T extends readonly
|
|
58
|
+
static union<const T extends readonly Property<any, boolean>[]>(items: T, options?: PropertyInputOptions): Property<PropertyUnion<T>, false>;
|
|
74
59
|
private static generateArrayValidator;
|
|
75
60
|
}
|
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,r){return class extends e{static code;constructor(e=r){super(t,e)}static of(e){new this(e)}}}const r=t("INVALID_CONFIG","Configuration is invalid"),n=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"),l=t("NOT_FOUND","Document Not Found"),u=t("UPDATE_FAILED","Item could not be updated"),d=t("ADD_FAILED","Item could not be added"),h=t("OPEN_CURSOR","Cursor could not be opened"),y=t("GET_FAILED","Item could not be retrieved"),f=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 $(e,t){for(const r of t.keys())e.add(r);return e}class k{static String={tag:0};static Number={tag:1};static Boolean={tag:2};static BigInt={tag:6};static Symbol={tag:5};static File={tag:11};static Date={tag:4};static Unknown={tag:12};static Literal(e){return{tag:3,value:e}}static Array(e){return{tag:7,of:e}}static Set(e){return{tag:8,of:e}}static Union(e){return{tag:9,options:e}}static Optional(e){return{tag:10,of:e}}static Object(e){return{tag:14,props:e}}static Custom({isType:e,serialize:t,deserialize:r}){return{tag:15,isType:e,serialize:t,deserialize:r}}static async serialize(e,t){switch(e.tag){case 3:case 2:case 1:case 6:case 0:return t;case 5:return t.description;case 12:return JSON.stringify(t);case 4:return t.getTime();case 7:{const r=[];for(const n of t)r.push(await k.serialize(e.of,n));return r}case 8:{const r=new Set;for(const n of t)r.add(await k.serialize(e.of,n));return r}case 10:return void 0===t?null:await k.serialize(e.of,t);case 9:for(const r of e.options)if(k.is(r,t))return await k.serialize(r,t);throw new Error("Value union could not be serialized");case 11:if(!(t instanceof File))throw new Error("Value is not a valid file");return{data:new Promise((e,r)=>{const n=new FileReader;n.onload=()=>e(n.result),n.onerror=r,n.readAsDataURL(t)}),name:t.name};case 14:{if(!t||"object"!=typeof t)throw new Error("Value is not an object");const r={};for(const n in e.props){const s=e.props[n];if(!(n in t)&&10!==s.tag)throw new Error(`Required property '${n}' not found`);r[n]=await this.serialize(s,t[n])}return r}case 13:return this.serialize(e.of,t);case 15:return e.serialize?await e.serialize(t):JSON.stringify(t)}}static async deserialize(e,t){switch(e.tag){case 3:if(typeof t!=typeof e.value)throw new Error(`'${t}' is not equal to literal '${t}'`);return t;case 2:if("boolean"!=typeof t)throw new Error(`'${t}' is not a boolean`);return t;case 1:if("number"!=typeof t)throw new Error(`'${t}' is not a number`);return t;case 6:if("number"!=typeof t)throw new Error(`'${t}' is not a bigint`);return BigInt(t);case 0:if("string"!=typeof t)throw new Error(`'${t}' is not a string`);return t;case 5:if("string"!=typeof t)throw new Error(`'${t}' is not a symbol`);return Symbol.for(t);case 4:if(!(t instanceof Date))throw new Error(`'${t}' is not a date`);return t;case 7:if(!Array.isArray(t))throw new Error(`'${t}' is not an array`);return t;case 8:if(!Array.isArray(t))throw new Error(`'${t}' is not an array`);return new Set(t);case 10:return k.deserialize(e.of,t);case 12:return JSON.parse(t);case 9:{let r,n=!1;for(const s of e.options){try{r=k.deserialize(s,t),n=!0}catch{n=!1}if(n)break}if(!n)throw new Error("Value did not match the union");return r}case 11:{if(!t||"object"!=typeof t||!("data"in t)||!("name"in t)||"string"!=typeof t.data||"string"!=typeof t.name)throw new Error("Value is not a valid file schema");const e=await fetch(t.data);return new File([await e.blob()],t.name)}case 13:return this.deserialize(e.of,t);case 15:if(e.isType(t))return e.deserialize?await e.deserialize(t):JSON.parse(String(t));throw new Error("Value is not valid");case 14:{if(!t||"object"!=typeof t)throw new Error("Value is not an object");const r={};for(const n in e.props){const s=e.props[n];if(!(n in t)&&10!==s.tag)throw new Error(`Required property '${n}' not found`);r[n]=await this.deserialize(s,t[n])}return r}}}static is(e,t){switch(e.tag){case 3:return t===e.value;case 2:return"boolean"==typeof t;case 1:return"number"==typeof t;case 6:return"bigint"==typeof t;case 0:return"string"==typeof t;case 5:return"symbol"==typeof t;case 12:return!0;case 4:return t instanceof Date;case 7:return Array.isArray(t)&&t.every(t=>k.is(e.of,t));case 8:return t instanceof Set&&Array.from(t).every(t=>k.is(e.of,t));case 10:return void 0===t||this.is(e.of,t);case 9:return e.options.some(e=>k.is(e,t));case 11:return t instanceof File;case 14:return!(!t||"object"!=typeof t)&&Object.keys(e.props).every(r=>k.is(e.props[r],t[r]));case 13:return this.is(e.of,t);case 15:return e.isType(t)}}}const R=Object.freeze(Object.defineProperty({__proto__:null,Type:k},Symbol.toStringTag,{value:"Module"}));function v(e){return t=>typeof t===e?{success:!0,data:t}:{success:!1,error:"Value is not a string"}}const O={[k.String.tag]:v("string"),[k.Number.tag]:v("number"),[k.BigInt.tag]:v("bigint"),[k.Boolean.tag]:v("boolean"),[k.Symbol.tag]:v("symbol"),[k.Unknown.tag]:e=>({success:!0,data:e}),[k.Date.tag]:e=>e instanceof Date?isNaN(e.getTime())?{success:!1,error:"Value is not a valid date"}:{success:!0,data:e}:{success:!1,error:"Value is not a date"}},K=Symbol.for("primaryKey");class N{symbol=K;genFn;autoGenerate;type;constructor(e,t){if(e){if(e>k.Date)throw new r("Invalid Primary Key Type");this.type=e,t?(this.autoGenerate=!0,this.genFn=t):this.autoGenerate=!1}else this.autoGenerate=!1,this.type=k.Number}getType(){return this.type}generator(e){return this.genFn=e,this.autoGenerate=!0,this}autoIncrement(){if(this.type===k.Number)return this.genFn=void 0,this.autoGenerate=!0,this;throw new r("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 N(k.String,b)}date(){return new N(k.Date,S)}genKey(){if(this.genFn)return this.genFn();throw new Error("Generator function not defined")}getSchema(){return O[this.type.tag]}isAutoIncremented(){return this.autoGenerate&&!this.genFn}static is(e){return e?.symbol===K}}class M{constructor(e,t="",r=!1,n=!1,s){this.to=e,this.name=t,this.isOptional=r,this.isArray=n,this.relatedKey="",this.actions={onDelete:s||"Restrict"}}static SYMBOL=Symbol.for("baseRelation");BASE_SYMBOL=M.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()===M.SYMBOL}}class D extends M{static R_SYMBOL=Symbol.for("relation");symbol=D.R_SYMBOL;constructor(e,t={}){super(e,t.name,!1,!1,t.onDelete)}array({onDelete:e}={}){return new I(this.to,this.name,e)}optional({onDelete:e}={}){return new j(this.to,this.name,e)}onDelete(e){return this.actions.onDelete=e,this}static is(e){return e?.symbol===this.R_SYMBOL}}class I extends M{static A_SYMBOL=Symbol.for("arrayRelation");symbol=I.A_SYMBOL;constructor(e,t,r="None"){super(e,t,!1,!0,r)}static is(e){return e?.symbol===this.A_SYMBOL}}class j extends M{static O_SYMBOL=Symbol.for("optionalRelation");symbol=j.O_SYMBOL;constructor(e,t,r="None"){super(e,t,!0,!1,r)}static is(e){return e?.symbol===this.O_SYMBOL}}var E=(e=>(e[e.Property=0]="Property",e[e.Relation=1]="Relation",e[e.PrimaryKey=2]="PrimaryKey",e[e.Invalid=3]="Invalid",e))(E||{});const x=Symbol.for("property");class T{constructor(e,t,r){this.parseFn=e,this.type=t,this.options={unique:r?.unique??!1}}symbol=x;hasDefault=!1;options;get parse(){return this.parseFn}getType(){return this.type}static array(...e){throw new Error("Method Not Implemented")}static boolean(...e){throw new Error("Method Not Implemented")}static custom(...e){throw new Error("Method Not Implemented")}static date(...e){throw new Error("Method Not Implemented")}static literal(e,...t){throw new Error("Method Not Implemented")}static number(...e){throw new Error("Method Not Implemented")}static union(...e){throw new Error("Method Not Implemented")}static set(...e){throw new Error("Method Not Implemented")}static string(...e){throw new Error("Method Not Implemented")}unique(){switch(this.type){case k.Boolean:case k.String:case k.Number:case k.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 D(e,t)}static primaryKey(e="number"){return new N(this.nameToType(e))}static nameToType(e){switch(e){case"boolean":return k.Boolean;case"bigint":return k.BigInt;case"number":case"string":return k.Number;case"symbol":return k.Symbol;default:return k.Unknown}}static is(e){return"object"==typeof e&&e?.symbol===x}}class F extends T{array(){return new F(F.generateArrayValidator(this.parseFn),k.Array(this.type),this.options)}default(e){return this.hasDefault=!0,new F(t=>null==t?{success:!0,data:"function"==typeof e?e():e}:this.parseFn(t),this.type,this.options)}optional(){return new F(e=>null==e?{success:!0,data:void 0}:this.parseFn(e),this.type,this.options)}static array(e,t){return new F(F.generateArrayValidator(e.parseFn),k.Array(e.type),t)}static boolean(e){return new F(e=>"boolean"==typeof e?{success:!0,data:e}:{success:!1,error:"Value is not a string"},k.Boolean,e)}static custom(e,t){return new F(e,k.Unknown,t)}static date(e){return new F(O[k.Date.tag],k.Date,e)}static literal(e,t){return new F(t=>t===e?{success:!0,data:e}:{success:!1,error:`${t} !== ${e}`},k.Literal(e),t)}static number(e){return new F(O[k.Number.tag],k.Number,e)}static string(e){return new F(O[k.String.tag],k.String,e)}static set(e,t){return new F(t=>{if(t instanceof Set){const r=new Set;for(const n of t){const t=e.parseFn(n);if(!t.success)return t;r.add(t.data)}return{success:!0,data:r}}return{success:!1,error:"Value is not an array"}},k.Set(e.type),t)}static union(e,t){const r=e.map(e=>e.parse);return new F(e=>{for(const t of r){const r=t(e);if(r.success)return r}return{success:!1,error:"Value did not match any of the items"}},k.Union(e.map(e=>e.getType())),t)}static generateArrayValidator(e){return t=>{if(Array.isArray(t)){const r=[];for(const n of t){const t=e(n);if(!t.success)return t;r.push(t.data)}return{success:!0,data:r}}return{success:!1,error:"Value is not an array"}}}}const P=Symbol.for("model");class _{constructor(t,r){this.name=t,this.fields=r,this.fieldKeys=m(r);for(const e of this.fieldKeys){const t=this.fields[e];M.is(t)&&t.to!==this.name&&this.relationLinks.add(t.to)}const n=this.fieldKeys.find(e=>N.is(this.fields[e]));if(!n)throw new e("INVALID_CONFIG",`Model ${this.name} has no primary key`);this.primaryKey=n}symbol=P;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&&M.is(t))return t}keyType(e){const t=this.fields[e];return t?T.is(t)?E.Property:M.is(t)?E.Relation:N.is(t)?E.PrimaryKey:E.Invalid:E.Invalid}links(){return this.relationLinks.keys()}*relations(){for(const e of this.fieldKeys)M.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 T.is(this.fields[e])?this.fields[e].parse(t):null}getDeletedStores(e){if(this.cache.delete)return this.cache.delete;const t=new Set,r=[this.name];let n;for(;r.length>0;){const s=r.shift();if(t.has(s))continue;n=e.getModel(s);const a=n.cache.delete;if(a)$(t,a);else{t.add(s);for(const e of n.links())t.has(e)||r.push(e)}}return this.cache.delete=t,t}static is(e){return e?.symbol===P}}class L{constructor(e,t){this.tx=e,this.store=t}add(e){return this.handleRequest(this.store.add(e),()=>new d)}get(e){return this.handleRequest(this.store.get(e),()=>new y)}async assertGet(e){const t=await this.handleRequest(this.store.get(e),()=>new y);if(!t)throw this.tx.abort(new l);return t}put(e){return this.handleRequest(this.store.put(e),()=>new u)}delete(e){return this.handleRequest(this.store.delete(e),()=>new i)}async openCursor(t,r={}){const n=r.onError||(()=>new h),s=this.store.openCursor(r.query,r.direction);await new Promise((r,a)=>{s.onsuccess=async s=>{try{s.target||a(this.tx.abort(n()));const e=s.target.result;e&&await t(e,this.tx)||r()}catch(i){a(this.tx.abort(i instanceof e?i:new o(String(i))))}},s.onerror=()=>{a(this.tx.abort(n()))}})}handleRequest(e,t){return new Promise(r=>{e.onsuccess=()=>{r(e.result)},e.onerror=()=>{throw this.tx.abort(t())}})}}class B{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,r,n={}){e instanceof B?(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,r),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,n.onAbort),this.internal.onerror=this.registerHandler(3,n.onError),this.internal.oncomplete=this.registerHandler(2,n.onComplete))}static create(e,t,r,n){return n||new B(e,t,r)}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 n(`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 L(this,this.internal.objectStore(e))}catch{throw this.abort(new c(`No ObjectStore with the name '${e}' found`))}}registerHandler(e,t=()=>{}){return r=>{this.status=e,t(this,r)}}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(r){throw this.inWrap=!1,r instanceof e?this.abort(r):this.abort(new o(JSON.stringify(r)))}}}function V(e){if(!e)return[];const t=[];for(const r in e)if(Object.hasOwn(e,r))switch(typeof e[r]){case"function":t.push([r,!0,e[r]]);break;case"object":if(e[r]instanceof Date){const n=e[r];t.push([r,!0,e=>e instanceof Date&&e.getTime()===n.getTime()])}break;default:t.push([r,!1,e[r]])}return t}function C(e,t){if(!t||"object"!=typeof t)return!1;for(const r of e)if(r[1]){if(!r[2](t[r[0]]))return!1}else if(r[2]!==t[r[0]])return!1;return!0}function z(e,t,r={},n){const a=t.getModel(e);if(r.include&&r.select)throw new s("include and select cannot both be defined");const o=V(r.where),i=r.select?"select":r.include?"include":"";if(i){const e=r[i],n=!!r.select,s=[];for(const r in e)if(Object.hasOwn(e,r)&&e[r])switch(a.keyType(r)){case E.Relation:{const n=a.getRelation(r),o="object"==typeof e[r]?z(n.to,t,e[r]):A,i=n.getRelatedKey();if(n.isArray){const e=async(e,t)=>{const r=[],s=t.getStore(n.to);for(const n of e){const e=await o(await s.assertGet(n),t);e&&(delete e[i],r.push(e))}return r};s.push({key:r,getValue:e})}else{const e=async(e,t)=>await o(await t.getStore(n.to).assertGet(e),t);s.push({key:r,getValue:e})}break}case E.Property:case E.PrimaryKey:n&&s.push({key:r})}return n?async(e,t)=>{if(!C(o,e))return;const r={};for(const{key:n,getValue:a}of s)r[n]=a?await a(e[n],t):e[n];return r}:async(e,t)=>{if(C(o,e)){for(const{key:r,getValue:n}of s)e[r]=await n(e[r],t);return e}}}return e=>C(o,e)?e:void 0}function U(e,t,r,n){const s=new Set([e]);if(r){const a=m(t),o=n.getModel(e);for(const e of a){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":$(s,o.getDeletedStores(n));break;case"$create":$(s,U(a.to,e[t],r,n));break;case"$createMany":e[t].forEach(e=>$(s,U(a.to,e,r,n)));break;case"$update":$(s,U(a.to,e[t].data,r,n));break;case"$updateMany":e[t].forEach(e=>$(s,U(a.to,e.data,r,n)))}}}else{const r=n.getModel(e);for(const e of m(t)){const a=r.getRelation(e);if(a)switch(typeof t[e]){case"object":$(s,U(a.to,q(t[e]),!1,n));break;case"boolean":s.add(a.to)}}}return s}function q(e){return e.select?e.select:e.include?e.include:{}}class G{constructor(e,t,r){this.client=e,this.name=t,this.accessedStores=Array.from(U(t,q(r),!1,this.client)),this.selectClause=z(t,this.client,r)}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 r=[],n=t.getStore(this.name);return await n.openCursor(async n=>{const s=await this.selectClause(n.value,t);return s&&r.push(s),(!e||!r.length)&&(n.continue(),!0)}),r})}}function Y(e,t,n){return async s=>{if(!s)return!1;const a=s[e.primaryKey];for(const[o,c]of e.relations()){const{onDelete:l}=c.getActions(),u=s[o],d=t.getModel(c.to);switch(l){case"Cascade":if(c.isArray){n.assertIsArray(u);const e=new Set(u),r=Y(d,t,n),s=n.getStore(c.to);await s.openCursor(async t=>(e.has(t.value[d.primaryKey])&&await r(t.value),t.continue(),!0)).catch(n.onRejection)}else u&&await J(c.to,t,void 0,void 0,{tx:n,singleton:{id:u}});break;case"SetNull":{if(!u)break;const e=g(u),t=n.getStore(c.to),s=c.getRelatedKey(),o=d.getRelation(s);if(!o)throw new r(`Relation '${c.name}' has an invalid relation key '${c.getRelatedKey()}'`);if(!o.isNullable())throw new r(`Key '${s}' on model '${s}': Non-optional relation cannot have the 'SetNull' action`);for(const r of e){const e=await t.get(r);if(!e)continue;const i=e[s];if(o.isArray){n.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(u)&&u.length>0||u)throw new i(`Key '${o}' on model '${e.name}' deletion is restricted while there is an active relation`)}}return!0}}async function J(e,t,r,n=!1,s={}){const{singleton:a,finalStep:o=!0}=s,i=t.getModel(e),c=s.tx?s.tx.storeNames:Array.from(i.getDeletedStores(t)),l=B.create(t.getDb(),c,"readwrite",s.tx);return await l.wrap(async s=>{const c=s.getStore(e);let l=0;const u=Y(i,t,s);if(a)await u(await c.assertGet(a.id))&&(await c.delete(a.id),l++);else{const e=V(r);let t;await c.openCursor(async r=>{const a=r.value;return C(e,a)&&await u(a)&&(t=p(r.delete()).catch(s.onRejection)),!(n&&l>0)&&(r.continue(),!0)}),t&&o&&await t}return l})}class W{constructor(e,t,r){this.name=e,this.content=t,this.extension=r}download(e=`${this.name}_dump.${this.extension}`,t){const r=URL.createObjectURL(this.toFile(e,t)),n=document.createElement("a");n.href=r,n.download=e,document.body.appendChild(n),n.click(),document.body.removeChild(n),URL.revokeObjectURL(r)}}class H extends W{constructor(e,t){super(e,t,"json")}getValue(){return this.content}toFile(e=`${this.name}_dump.json`,t={}){return new File([JSON.stringify(this.content,void 0,4)],e,t)}}class Q extends W{constructor(e,t){super(e,t,"csv")}getValue(){return this.content}toFile(e=`${this.name}_dump.csv`,t){return new File([this.content],e,t)}}function X(e){return"string"!=typeof e?`${e}`:e.replaceAll(/~/g,"~0").replaceAll(/\//g,"~1")}async function Z(e,t,r,n){n=B.create(e.getDb(),[t],"readonly",n);const s=V(r),o=e.getModel(t);return new H(t,await n.wrap(async e=>{const r={};return await e.getStore(t).openCursor(async e=>{if(C(s,e.value)){for(const[t,r]of o.entries())if(M.is(r))if(r.isArray){if(!Array.isArray(e.value[t]))throw new a("Expected array type");const n=[];for(const s of e.value[t])n.push(`/${r.to}/${X(s)}`);e.value[t]=n}else(r.isOptional&&e.value[t]||!r.isNullable())&&(e.value[t]=`/${r.to}/${X(e.value[t])}`);else{if(!F.is(r)&&!N.is(r))throw new w(`Unrecognized model field on key '${t}'`);e.value[t]=await k.serialize(r.getType(),e.value[t])}if(r[e.value[o.primaryKey]])throw new w("Duplicate primary key detected "+JSON.stringify(r));r[e.value[o.primaryKey]]=e.value}return e.continue(),!0}),r}))}class ee{constructor(e,t){this.db=e,this.models=t,this.name=this.db.name,this.version=this.db.version,this.stores={};for(const r of this.models.keys())this.stores[r]=this.createInterface(r)}name;version;stores;getDb(){return this.db}getStore(e){return this.stores[e]}getStoreNames(){return this.models.keys()}createTransaction(e,t,r){return new B(this.db,t,e,r)}async deleteDb(){await p(window.indexedDB.deleteDatabase(this.name))}async dump(e,t){return"json"===e?await async function(e,t){const r={};t=t||e.getStoreNames();const n=e.createTransaction("readonly",t);for(const s of t)r[s]=(await Z(e,s,void 0,n)).getValue();return new H(e.name,r)}(this,t):new Q("d","")}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){return this.models.getModel(e)}getAccessedStores(e,t,r,n){return n?n.storeNames:Array.from(U(e,t,r,this))}createInterface(e){return{add:async(t,r)=>await this.add(e,t,{tx:r}),addMany:async(t,r)=>{if(!r){const n=new Set;for(const r of t)$(n,U(e,r,!0,this));r=this.createTransaction("readwrite",Array.from(n))}const n=[];for(const s of t)n.push(await this.add(e,s,{tx:r}));return n},findFirst:async(t,r)=>(await this.find(e,t,!0,{tx:r}))[0],find:async(t,r)=>await this.find(e,t,!1,{tx:r}),get:async t=>{const r=this.createTransaction("readonly",e);return await r.getStore(e).get(t)},update:async(t,r)=>(await this.update(e,{data:r},!0,{singleton:{id:t}}))[0],updateFirst:async(t,r)=>(await this.update(e,t,!0,{tx:r}))[0],updateMany:async(t,r)=>await this.update(e,t,!1,{tx:r}),compileQuery:t=>new G(this,e,t),delete:async t=>await J(e,this,void 0,void 0,{singleton:{id:t}})>0,deleteFirst:async t=>await J(e,this,t,!0)>0,deleteMany:async t=>await J(e,this,t,!1),dump:async(t,r)=>"json"===t?await Z(this,e,r):new Q("","")}}async add(e,t,r={}){let{tx:n}=r;const{relation:a}=r,i=this.getAccessedStores(e,t,!0,n);return n=B.create(this.db,i,"readwrite",n),await n.wrap(async r=>{const n=r.getStore(e),i=this.getModel(e),c=i.getPrimaryKey(),l=a?{[a.key]:i.getRelation(a.key)?.isArray?[a.id]:a.id}:{},u=c.isAutoIncremented()?{...l}:{...l,[i.primaryKey]:t[i.primaryKey]??c.genKey()},d=await n.add(u),h={},y=new Set;for(const a of m(t)){y.add(a);const n=t[a];switch(i.keyType(a)){case E.Invalid:throw new s(`Key '${a}' does ont exist on model '${e}'`);case E.Property:{const e=i.parseField(a,n);if(!e)throw new o;if(!e.success)throw new s(`Key '${a}' has the following validation error: ${e.error}`);h[a]=e.data;break}case E.Relation:{if(!n)continue;const e=g(n),t=i.getRelation(a);if(t.isArray&&(h[a]=[],"$createMany"in n||"$connectMany"in n)){const t=[];for(const e of n.$createMany??[])t.push({$create:e});for(const e of n.$connectMany??[])t.push({$connect:e});e.push(...t)}const o=this.getModel(t.to).getRelation(t.getRelatedKey()),c=new Set;for(const n of e){const e=m(n)[0];if(!e)throw new s(`Key '${a}' cannot be an empty connection object`);switch(e){case"$connect":{const i=n[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,d,i,r),t.isArray?h[a].push(i):h[a]=i;break}case"$create":{const s=await this.add(t.to,n[e],{tx:r,relation:{id:d,key:t.getRelatedKey()}});t.isArray?h[a].push(s):h[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 E.PrimaryKey:}}const f=Array.from(new Set(i.keys()).difference(y));for(const e of f)switch(i.keyType(e)){case E.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`);h[e]=t.data;break}case E.Relation:{const t=i.getRelation(e),r=l[e];if(t.isArray)h[e]=r??[];else if(t.isOptional)h[e]=r??null;else{if(!r)throw new s(`Required relation '${e}' is not defined`);h[e]=r}break}case E.Invalid:case E.PrimaryKey:}return await n.put({[i.primaryKey]:d,...h})})}async clear(e,t){await J(e,this,void 0,!1,t)}async find(e,t,r,n={}){let{tx:s}=n;const a=this.getAccessedStores(e,q(t),!1,s);s=B.create(this.db,a,"readonly",s);const o=[];return await s.wrap(async n=>{const s=n.getStore(e),a=z(e,this,t);return await s.openCursor(async e=>{const t=await a(e.value,n);return t&&o.push(t),(!r||!o.length)&&(e.continue(),!0)}),o})}async update(e,t,r,n={}){const{singleton:a}=n,i=n.singleton?t:t.data,c=this.getAccessedStores(e,i,!0,n.tx),d=B.create(this.db,c,"readwrite",n.tx);return await d.wrap(async n=>{const c=n.getStore(e),d=this.getModel(e),h=[];for(const e of m(i))switch(d.keyType(e)){case E.Property:h.push({key:e,isRelation:!1,updateFn:"function"==typeof i[e]?i[e]:()=>i[e]});break;case E.Relation:{const t=g(i[e]);if(!t)continue;const r=[];for(const e of t)for(const t in e){switch(t){case"$createMany":case"$connectMany":case"$updateMany":case"$deleteMany":case"$disconnectMany":{const n=t.substring(0,t.length-4);for(const s of e[t])r.push([n,s]);break}default:r.push([t,e[t]])}break}h.push({actions:r,key:e,isRelation:!0,relation:d.getRelation(e)});break}case E.PrimaryKey:throw new u("Primary key field cannot be updated");case E.Invalid:default:throw new o(`Unknown key '${e}'`)}const y=[],f=async e=>{const t=e[d.primaryKey];for(const{key:r,...a}of h){const o=a.relation;if(a.isRelation)for(const[i,c]of a.actions)switch(i){case"$connect":e[r]&&!o.isArray&&await this.disconnectDocument(o,t,e[r],n).catch(n.onRejection),await this.connectDocument(o,t,c,n).catch(n.onRejection),o.isArray?e[r].push(c):e[r]=c;break;case"$create":{const s=await this.add(o.to,c,{tx:n,relation:{id:t,key:o.getRelatedKey()}});o.isArray?e[r].push(s):e[r]=s;break}case"$delete":if(!o.isNullable())throw new s("Item cannot be deleted, relation is required");e[r]=o.isArray&&Array.isArray(e[r])?e[r].filter(e=>e!==c):null,await J(o.to,this,{},!0,{tx:n,singleton:{id:c}});break;case"$disconnect":{if(!o.isNullable())throw new s("Item cannot be disconnected, relation is required");if(!e[r]||0===e[r]?.lenth)break;const a=this.getModel(o.to).getRelation(o.getRelatedKey());await this.disconnectDocument(o,t,a.isArray?c:e[r],n).catch(n.onRejection),e[r]=o.isArray&&Array.isArray(e[r])?e[r].filter(e=>e!==c):null;break}case"$update":o.isArray?await this.update(o.to,c,!1,{tx:n}):null!=e[r]&&await this.update(o.to,c,!1,{tx:n,singleton:{id:t}});break;case"$deleteAll":if(c&&o.isArray&&Array.isArray(e[r])){const t=this.getModel(o.to),s=new Set(e[r]);await J(o.to,this,{[t.primaryKey]:e=>s.has(e)},!1,{tx:n}),e[r]=[]}break;case"$disconnectAll":if(c&&o.isArray&&Array.isArray(e[r])){for(const s of e[r])await this.disconnectDocument(o,t,s,n);e[r]=[]}}else e[r]=a.updateFn(e[r])}return e};if(a){const e=await c.get(a.id);if(!e)throw new l(`${d.name} with priamry key '${a.id}' not found`);const t=await f(e).catch(n.onRejection);return await c.put(t),[t]}{const e=V(t.where);return await c.openCursor(async t=>{const s=t.value;if(C(e,s)){const e=await f(s).catch(n.onRejection);if(await p(t.update(e)).then(()=>y.push(e)).catch(n.onRejection),r)return!1}return t.continue(),!0}),y}})}async connectDocument(e,t,r,n){const s=n.getStore(e.to),a=await s.get(r);if(!a)throw new l(`Document with Primary Key '${r}' 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 f;a[o]=t}return await s.put(a).catch(n.onRejection),r}async disconnectDocument(e,t,r,n){const s=n.getStore(e.to),a=await s.get(r);if(!a)throw new l(`Document with Primary Key '${r}' 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 f;a[e.getRelatedKey()]=null}return await s.put(a).catch(n.onRejection),r}}class te{constructor(e,t){this.name=e,this.models=t,this.modelKeys=m(this.models),this.schemas={};for(const n of this.modelKeys){const e=this.models[n],t={};for(const s of e.keys()){const a=e.get(s);if(T.is(a))t[s]=a.parse;else if(M.is(a)){const{onDelete:o}=a.getActions(),i=this.models[a.to],c=i.getPrimaryKey();t[s]=O[c.type.tag],a.isOptional?t[s]=new F(t[s],c.type).optional().parse:a.isArray&&(t[s]=t[s]=new F(t[s],c.type).array().parse);let l=!!a.getRelatedKey();if(!l)for(const[t,n]of i.relations())if(s!==t&&n.to===e.name&&n.name===a.name){if(l=!0,a.setRelatedKey(t),n.setRelatedKey(s),"SetNull"===o&&!n.isNullable())throw new r(`Key '${t}' on model '${i.name}': Non-optional relation cannot have the 'SetNull' action`);break}if(!l)throw new r(`Relation '${a.name}' of model ${n} does not have an equivalent relation on model '${a.to}'`)}else{if(!N.is(a))throw new r(`Unknown field value detected: ${JSON.stringify(a)}`);t[s]=O[a.type.tag]}}this.schemas[n]=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 r of this.modelKeys){const e=this.models[r];t.objectStoreNames.contains(e.name)||t.createObjectStore(e.name,{autoIncrement:e.getPrimaryKey().isAutoIncremented(),keyPath:e.primaryKey})}};const r=await p(t);return new ee(r,this)}keys(){return[...this.modelKeys]}}const re=Object.freeze(Object.defineProperty({__proto__:null,AbstractProperty:T,ArrayRelation:I,BaseRelation:M,DbClient:ee,FieldTypes:E,Model:_,OptionalRelation:j,PrimaryKey:N,Property:F,Relation:D,Type:k,Typing:R,VALIDATORS:O},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&&_.is(e))return this.models[e.name]=e,e;{if(!t)throw new Error("Model Fields must be defined");const r=new _(e,t);return this.models[e]=r,r}}compile(e){return new te(this.name,e)}},exports.CompiledQuery=G,exports.Model=_,exports.Property=F,exports.StoreError=e,exports.core=re;
|
|
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,
|
|
2
|
-
return new Date}function A(e){return e}function $(e,t){for(const r of t.keys())e.add(r);return e}class k{static String={tag:0};static Number={tag:1};static Boolean={tag:2};static BigInt={tag:6};static Symbol={tag:5};static File={tag:11};static Date={tag:4};static Unknown={tag:12};static Literal(e){return{tag:3,value:e}}static Array(e){return{tag:7,of:e}}static Set(e){return{tag:8,of:e}}static Union(e){return{tag:9,options:e}}static Optional(e){return{tag:10,of:e}}static Object(e){return{tag:14,props:e}}static Custom({isType:e,serialize:t,deserialize:r}){return{tag:15,isType:e,serialize:t,deserialize:r}}static async serialize(e,t){switch(e.tag){case 3:case 2:case 1:case 6:case 0:return t;case 5:return t.description;case 12:return JSON.stringify(t);case 4:return t.getTime();case 7:{const r=[];for(const n of t)r.push(await k.serialize(e.of,n));return r}case 8:{const r=/* @__PURE__ */new Set;for(const n of t)r.add(await k.serialize(e.of,n));return r}case 10:return void 0===t?null:await k.serialize(e.of,t);case 9:for(const r of e.options)if(k.is(r,t))return await k.serialize(r,t);throw new Error("Value union could not be serialized");case 11:if(!(t instanceof File))throw new Error("Value is not a valid file");return{data:new Promise((e,r)=>{const n=new FileReader;n.onload=()=>e(n.result),n.onerror=r,n.readAsDataURL(t)}),name:t.name};case 14:{if(!t||"object"!=typeof t)throw new Error("Value is not an object");const r={};for(const n in e.props){const s=e.props[n];if(!(n in t)&&10!==s.tag)throw new Error(`Required property '${n}' not found`);r[n]=await this.serialize(s,t[n])}return r}case 13:return this.serialize(e.of,t);case 15:return e.serialize?await e.serialize(t):JSON.stringify(t)}}static async deserialize(e,t){switch(e.tag){case 3:if(typeof t!=typeof e.value)throw new Error(`'${t}' is not equal to literal '${t}'`);return t;case 2:if("boolean"!=typeof t)throw new Error(`'${t}' is not a boolean`);return t;case 1:if("number"!=typeof t)throw new Error(`'${t}' is not a number`);return t;case 6:if("number"!=typeof t)throw new Error(`'${t}' is not a bigint`);return BigInt(t);case 0:if("string"!=typeof t)throw new Error(`'${t}' is not a string`);return t;case 5:if("string"!=typeof t)throw new Error(`'${t}' is not a symbol`);return Symbol.for(t);case 4:if(!(t instanceof Date))throw new Error(`'${t}' is not a date`);return t;case 7:if(!Array.isArray(t))throw new Error(`'${t}' is not an array`);return t;case 8:if(!Array.isArray(t))throw new Error(`'${t}' is not an array`);return new Set(t);case 10:return k.deserialize(e.of,t);case 12:return JSON.parse(t);case 9:{let r,n=!1;for(const s of e.options){try{r=k.deserialize(s,t),n=!0}catch{n=!1}if(n)break}if(!n)throw new Error("Value did not match the union");return r}case 11:{if(!t||"object"!=typeof t||!("data"in t)||!("name"in t)||"string"!=typeof t.data||"string"!=typeof t.name)throw new Error("Value is not a valid file schema");const e=await fetch(t.data);return new File([await e.blob()],t.name)}case 13:return this.deserialize(e.of,t);case 15:if(e.isType(t))return e.deserialize?await e.deserialize(t):JSON.parse(String(t));throw new Error("Value is not valid");case 14:{if(!t||"object"!=typeof t)throw new Error("Value is not an object");const r={};for(const n in e.props){const s=e.props[n];if(!(n in t)&&10!==s.tag)throw new Error(`Required property '${n}' not found`);r[n]=await this.deserialize(s,t[n])}return r}}}static is(e,t){switch(e.tag){case 3:return t===e.value;case 2:return"boolean"==typeof t;case 1:return"number"==typeof t;case 6:return"bigint"==typeof t;case 0:return"string"==typeof t;case 5:return"symbol"==typeof t;case 12:return!0;case 4:return t instanceof Date;case 7:return Array.isArray(t)&&t.every(t=>k.is(e.of,t));case 8:return t instanceof Set&&Array.from(t).every(t=>k.is(e.of,t));case 10:return void 0===t||this.is(e.of,t);case 9:return e.options.some(e=>k.is(e,t));case 11:return t instanceof File;case 14:return!(!t||"object"!=typeof t)&&Object.keys(e.props).every(r=>k.is(e.props[r],t[r]));case 13:return this.is(e.of,t);case 15:return e.isType(t)}}}const R=/* @__PURE__ */Object.freeze(/* @__PURE__ */Object.defineProperty({__proto__:null,Type:k},Symbol.toStringTag,{value:"Module"}));function v(e){return t=>typeof t===e?{success:!0,data:t}:{success:!1,error:"Value is not a string"}}const K={[k.String.tag]:v("string"),[k.Number.tag]:v("number"),[k.BigInt.tag]:v("bigint"),[k.Boolean.tag]:v("boolean"),[k.Symbol.tag]:v("symbol"),[k.Unknown.tag]:e=>({success:!0,data:e}),[k.Date.tag]:e=>e instanceof Date?isNaN(e.getTime())?{success:!1,error:"Value is not a valid date"}:{success:!0,data:e}:{success:!1,error:"Value is not a date"}},O=Symbol.for("primaryKey");class N{symbol=O;genFn;autoGenerate;type;constructor(e,t){if(e){if(e>k.Date)throw new r("Invalid Primary Key Type");this.type=e,t?(this.autoGenerate=!0,this.genFn=t):this.autoGenerate=!1}else this.autoGenerate=!1,this.type=k.Number}getType(){return this.type}generator(e){return this.genFn=e,this.autoGenerate=!0,this}autoIncrement(){if(this.type===k.Number)return this.genFn=void 0,this.autoGenerate=!0,this;throw new r("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 N(k.String,b)}date(){return new N(k.Date,S)}genKey(){if(this.genFn)return this.genFn();throw new Error("Generator function not defined")}getSchema(){return K[this.type.tag]}isAutoIncremented(){return this.autoGenerate&&!this.genFn}static is(e){return e?.symbol===O}}class M{constructor(e,t="",r=!1,n=!1,s){this.to=e,this.name=t,this.isOptional=r,this.isArray=n,this.relatedKey="",this.actions={onDelete:s||"Restrict"}}static SYMBOL=Symbol.for("baseRelation");BASE_SYMBOL=M.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()===M.SYMBOL}}class D extends M{static R_SYMBOL=Symbol.for("relation");symbol=D.R_SYMBOL;constructor(e,t={}){super(e,t.name,!1,!1,t.onDelete)}array({onDelete:e}={}){return new I(this.to,this.name,e)}optional({onDelete:e}={}){return new j(this.to,this.name,e)}onDelete(e){return this.actions.onDelete=e,this}static is(e){return e?.symbol===this.R_SYMBOL}}class I extends M{static A_SYMBOL=Symbol.for("arrayRelation");symbol=I.A_SYMBOL;constructor(e,t,r="None"){super(e,t,!1,!0,r)}static is(e){return e?.symbol===this.A_SYMBOL}}class j extends M{static O_SYMBOL=Symbol.for("optionalRelation");symbol=j.O_SYMBOL;constructor(e,t,r="None"){super(e,t,!0,!1,r)}static is(e){return e?.symbol===this.O_SYMBOL}}var E=/* @__PURE__ */(e=>(e[e.Property=0]="Property",e[e.Relation=1]="Relation",e[e.PrimaryKey=2]="PrimaryKey",e[e.Invalid=3]="Invalid",e))(E||{});const x=Symbol.for("property");class F{constructor(e,t,r){this.parseFn=e,this.type=t,this.options={unique:r?.unique??!1}}symbol=x;hasDefault=!1;options;get parse(){return this.parseFn}getType(){return this.type}static array(...e){throw new Error("Method Not Implemented")}static boolean(...e){throw new Error("Method Not Implemented")}static custom(...e){throw new Error("Method Not Implemented")}static date(...e){throw new Error("Method Not Implemented")}static literal(e,...t){throw new Error("Method Not Implemented")}static number(...e){throw new Error("Method Not Implemented")}static union(...e){throw new Error("Method Not Implemented")}static set(...e){throw new Error("Method Not Implemented")}static string(...e){throw new Error("Method Not Implemented")}unique(){switch(this.type){case k.Boolean:case k.String:case k.Number:case k.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 D(e,t)}static primaryKey(e="number"){return new N(this.nameToType(e))}static nameToType(e){switch(e){case"boolean":return k.Boolean;case"bigint":return k.BigInt;case"number":case"string":return k.Number;case"symbol":return k.Symbol;default:return k.Unknown}}static is(e){return"object"==typeof e&&e?.symbol===x}}class T extends F{array(){return new T(T.generateArrayValidator(this.parseFn),k.Array(this.type),this.options)}default(e){return this.hasDefault=!0,new T(t=>null==t?{success:!0,data:"function"==typeof e?e():e}:this.parseFn(t),this.type,this.options)}optional(){return new T(e=>null==e?{success:!0,data:void 0}:this.parseFn(e),this.type,this.options)}static array(e,t){return new T(T.generateArrayValidator(e.parseFn),k.Array(e.type),t)}static boolean(e){return new T(e=>"boolean"==typeof e?{success:!0,data:e}:{success:!1,error:"Value is not a string"},k.Boolean,e)}static custom(e,t){return new T(e,k.Unknown,t)}static date(e){return new T(K[k.Date.tag],k.Date,e)}static literal(e,t){return new T(t=>t===e?{success:!0,data:e}:{success:!1,error:`${t} !== ${e}`},k.Literal(e),t)}static number(e){return new T(K[k.Number.tag],k.Number,e)}static string(e){return new T(K[k.String.tag],k.String,e)}static set(e,t){return new T(t=>{if(t instanceof Set){const r=/* @__PURE__ */new Set;for(const n of t){const t=e.parseFn(n);if(!t.success)return t;r.add(t.data)}return{success:!0,data:r}}return{success:!1,error:"Value is not an array"}},k.Set(e.type),t)}static union(e,t){const r=e.map(e=>e.parse);return new T(e=>{for(const t of r){const r=t(e);if(r.success)return r}return{success:!1,error:"Value did not match any of the items"}},k.Union(e.map(e=>e.getType())),t)}static generateArrayValidator(e){return t=>{if(Array.isArray(t)){const r=[];for(const n of t){const t=e(n);if(!t.success)return t;r.push(t.data)}return{success:!0,data:r}}return{success:!1,error:"Value is not an array"}}}}const _=Symbol.for("model");class P{constructor(t,r){this.name=t,this.fields=r,this.fieldKeys=m(r);for(const e of this.fieldKeys){const t=this.fields[e];M.is(t)&&t.to!==this.name&&this.relationLinks.add(t.to)}const n=this.fieldKeys.find(e=>N.is(this.fields[e]));if(!n)throw new e("INVALID_CONFIG",`Model ${this.name} has no primary key`);this.primaryKey=n}symbol=_;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&&M.is(t))return t}keyType(e){const t=this.fields[e];return t?F.is(t)?E.Property:M.is(t)?E.Relation:N.is(t)?E.PrimaryKey:E.Invalid:E.Invalid}links(){return this.relationLinks.keys()}*relations(){for(const e of this.fieldKeys)M.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 F.is(this.fields[e])?this.fields[e].parse(t):null}getDeletedStores(e){if(this.cache.delete)return this.cache.delete;const t=/* @__PURE__ */new Set,r=[this.name];let n;for(;r.length>0;){const s=r.shift();if(t.has(s))continue;n=e.getModel(s);const a=n.cache.delete;if(a)$(t,a);else{t.add(s);for(const e of n.links())t.has(e)||r.push(e)}}return this.cache.delete=t,t}static is(e){return e?.symbol===_}}class L{constructor(e,t){this.tx=e,this.store=t}add(e){return this.handleRequest(this.store.add(e),()=>new d)}get(e){return this.handleRequest(this.store.get(e),()=>new y)}async assertGet(e){const t=await this.handleRequest(this.store.get(e),()=>new y);if(!t)throw this.tx.abort(new l);return t}put(e){return this.handleRequest(this.store.put(e),()=>new u)}delete(e){return this.handleRequest(this.store.delete(e),()=>new i)}async openCursor(t,r={}){const n=r.onError||(()=>new h),s=this.store.openCursor(r.query,r.direction);await new Promise((r,a)=>{s.onsuccess=async s=>{try{s.target||a(this.tx.abort(n()));const e=s.target.result;e&&await t(e,this.tx)||r()}catch(i){a(this.tx.abort(i instanceof e?i:new o(String(i))))}},s.onerror=()=>{a(this.tx.abort(n()))}})}handleRequest(e,t){return new Promise(r=>{e.onsuccess=()=>{r(e.result)},e.onerror=()=>{throw this.tx.abort(t())}})}}class V{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,r,n={}){e instanceof V?(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,r),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,n.onAbort),this.internal.onerror=this.registerHandler(3,n.onError),this.internal.oncomplete=this.registerHandler(2,n.onComplete))}static create(e,t,r,n){return n||new V(e,t,r)}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 n(`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 L(this,this.internal.objectStore(e))}catch{throw this.abort(new c(`No ObjectStore with the name '${e}' found`))}}registerHandler(e,t=()=>{}){return r=>{this.status=e,t(this,r)}}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(r){throw this.inWrap=!1,r instanceof e?this.abort(r):this.abort(new o(JSON.stringify(r)))}}}function B(e){if(!e)return[];const t=[];for(const r in e)if(Object.hasOwn(e,r))switch(typeof e[r]){case"function":t.push([r,!0,e[r]]);break;case"object":if(e[r]instanceof Date){const n=e[r];t.push([r,!0,e=>e instanceof Date&&e.getTime()===n.getTime()])}break;default:t.push([r,!1,e[r]])}return t}function C(e,t){if(!t||"object"!=typeof t)return!1;for(const r of e)if(r[1]){if(!r[2](t[r[0]]))return!1}else if(r[2]!==t[r[0]])return!1;return!0}function z(e,t,r={},n){const a=t.getModel(e);if(r.include&&r.select)throw new s("include and select cannot both be defined");const o=B(r.where),i=r.select?"select":r.include?"include":"";if(i){const e=r[i],n=!!r.select,s=[];for(const r in e)if(Object.hasOwn(e,r)&&e[r])switch(a.keyType(r)){case E.Relation:{const n=a.getRelation(r),o="object"==typeof e[r]?z(n.to,t,e[r]):A,i=n.getRelatedKey();if(n.isArray){const e=async(e,t)=>{const r=[],s=t.getStore(n.to);for(const n of e){const e=await o(await s.assertGet(n),t);e&&(delete e[i],r.push(e))}return r};s.push({key:r,getValue:e})}else{const e=async(e,t)=>await o(await t.getStore(n.to).assertGet(e),t);s.push({key:r,getValue:e})}break}case E.Property:case E.PrimaryKey:n&&s.push({key:r})}return n?async(e,t)=>{if(!C(o,e))return;const r={};for(const{key:n,getValue:a}of s)r[n]=a?await a(e[n],t):e[n];return r}:async(e,t)=>{if(C(o,e)){for(const{key:r,getValue:n}of s)e[r]=await n(e[r],t);return e}}}return e=>C(o,e)?e:void 0}function U(e,t,r,n){const s=/* @__PURE__ */new Set([e]);if(r){const a=m(t),o=n.getModel(e);for(const e of a){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":$(s,o.getDeletedStores(n));break;case"$create":$(s,U(a.to,e[t],r,n));break;case"$createMany":e[t].forEach(e=>$(s,U(a.to,e,r,n)));break;case"$update":$(s,U(a.to,e[t].data,r,n));break;case"$updateMany":e[t].forEach(e=>$(s,U(a.to,e.data,r,n)))}}}else{const r=n.getModel(e);for(const e of m(t)){const a=r.getRelation(e);if(a)switch(typeof t[e]){case"object":$(s,U(a.to,q(t[e]),!1,n));break;case"boolean":s.add(a.to)}}}return s}function q(e){return e.select?e.select:e.include?e.include:{}}class G{constructor(e,t,r){this.client=e,this.name=t,this.accessedStores=Array.from(U(t,q(r),!1,this.client)),this.selectClause=z(t,this.client,r)}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 r=[],n=t.getStore(this.name);return await n.openCursor(async n=>{const s=await this.selectClause(n.value,t);return s&&r.push(s),(!e||!r.length)&&(n.continue(),!0)}),r})}}function Y(e,t,n){return async s=>{if(!s)return!1;const a=s[e.primaryKey];for(const[o,c]of e.relations()){const{onDelete:l}=c.getActions(),u=s[o],d=t.getModel(c.to);switch(l){case"Cascade":if(c.isArray){n.assertIsArray(u);const e=new Set(u),r=Y(d,t,n),s=n.getStore(c.to);await s.openCursor(async t=>(e.has(t.value[d.primaryKey])&&await r(t.value),t.continue(),!0)).catch(n.onRejection)}else u&&await J(c.to,t,void 0,void 0,{tx:n,singleton:{id:u}});break;case"SetNull":{if(!u)break;const e=g(u),t=n.getStore(c.to),s=c.getRelatedKey(),o=d.getRelation(s);if(!o)throw new r(`Relation '${c.name}' has an invalid relation key '${c.getRelatedKey()}'`);if(!o.isNullable())throw new r(`Key '${s}' on model '${s}': Non-optional relation cannot have the 'SetNull' action`);for(const r of e){const e=await t.get(r);if(!e)continue;const i=e[s];if(o.isArray){n.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(u)&&u.length>0||u)throw new i(`Key '${o}' on model '${e.name}' deletion is restricted while there is an active relation`)}}return!0}}async function J(e,t,r,n=!1,s={}){const{singleton:a,finalStep:o=!0}=s,i=t.getModel(e),c=s.tx?s.tx.storeNames:Array.from(i.getDeletedStores(t)),l=V.create(t.getDb(),c,"readwrite",s.tx);return await l.wrap(async s=>{const c=s.getStore(e);let l=0;const u=Y(i,t,s);if(a)await u(await c.assertGet(a.id))&&(await c.delete(a.id),l++);else{const e=B(r);let t;await c.openCursor(async r=>{const a=r.value;return C(e,a)&&await u(a)&&(t=p(r.delete()).catch(s.onRejection)),!(n&&l>0)&&(r.continue(),!0)}),t&&o&&await t}return l})}class W{constructor(e,t,r){this.name=e,this.content=t,this.extension=r}download(e=`${this.name}_dump.${this.extension}`,t){const r=URL.createObjectURL(this.toFile(e,t)),n=document.createElement("a");n.href=r,n.download=e,document.body.appendChild(n),n.click(),document.body.removeChild(n),URL.revokeObjectURL(r)}}class H extends W{constructor(e,t){super(e,t,"json")}getValue(){return this.content}toFile(e=`${this.name}_dump.json`,t={}){return new File([JSON.stringify(this.content,void 0,4)],e,t)}}class X extends W{constructor(e,t){super(e,t,"csv")}getValue(){return this.content}toFile(e=`${this.name}_dump.csv`,t){return new File([this.content],e,t)}}function Q(e){return"string"!=typeof e?`${e}`:e.replaceAll(/~/g,"~0").replaceAll(/\//g,"~1")}async function Z(e,t,r,n){n=V.create(e.getDb(),[t],"readonly",n);const s=B(r),o=e.getModel(t);return new H(t,await n.wrap(async e=>{const r={};return await e.getStore(t).openCursor(async e=>{if(C(s,e.value)){for(const[t,r]of o.entries())if(M.is(r))if(r.isArray){if(!Array.isArray(e.value[t]))throw new a("Expected array type");const n=[];for(const s of e.value[t])n.push(`/${r.to}/${Q(s)}`);e.value[t]=n}else(r.isOptional&&e.value[t]||!r.isNullable())&&(e.value[t]=`/${r.to}/${Q(e.value[t])}`);else{if(!T.is(r)&&!N.is(r))throw new w(`Unrecognized model field on key '${t}'`);e.value[t]=await k.serialize(r.getType(),e.value[t])}if(r[e.value[o.primaryKey]])throw new w("Duplicate primary key detected "+JSON.stringify(r));r[e.value[o.primaryKey]]=e.value}return e.continue(),!0}),r}))}class ee{constructor(e,t){this.db=e,this.models=t,this.name=this.db.name,this.version=this.db.version,this.stores={};for(const r of this.models.keys())this.stores[r]=this.createInterface(r)}name;version;stores;getDb(){return this.db}getStore(e){return this.stores[e]}getStoreNames(){return this.models.keys()}createTransaction(e,t,r){return new V(this.db,t,e,r)}async deleteDb(){await p(window.indexedDB.deleteDatabase(this.name))}async dump(e,t){return"json"===e?await async function(e,t){const r={};t=t||e.getStoreNames();const n=e.createTransaction("readonly",t);for(const s of t)r[s]=(await Z(e,s,void 0,n)).getValue();return new H(e.name,r)}(this,t):new X("d","")}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){return this.models.getModel(e)}getAccessedStores(e,t,r,n){return n?n.storeNames:Array.from(U(e,t,r,this))}createInterface(e){return{add:async(t,r)=>await this.add(e,t,{tx:r}),addMany:async(t,r)=>{if(!r){const n=/* @__PURE__ */new Set;for(const r of t)$(n,U(e,r,!0,this));r=this.createTransaction("readwrite",Array.from(n))}const n=[];for(const s of t)n.push(await this.add(e,s,{tx:r}));return n},findFirst:async(t,r)=>(await this.find(e,t,!0,{tx:r}))[0],find:async(t,r)=>await this.find(e,t,!1,{tx:r}),get:async t=>{const r=this.createTransaction("readonly",e);return await r.getStore(e).get(t)},update:async(t,r)=>(await this.update(e,{data:r},!0,{singleton:{id:t}}))[0],updateFirst:async(t,r)=>(await this.update(e,t,!0,{tx:r}))[0],updateMany:async(t,r)=>await this.update(e,t,!1,{tx:r}),compileQuery:t=>new G(this,e,t),delete:async t=>await J(e,this,void 0,void 0,{singleton:{id:t}})>0,deleteFirst:async t=>await J(e,this,t,!0)>0,deleteMany:async t=>await J(e,this,t,!1),dump:async(t,r)=>"json"===t?await Z(this,e,r):new X("","")}}async add(e,t,r={}){let{tx:n}=r;const{relation:a}=r,i=this.getAccessedStores(e,t,!0,n);return n=V.create(this.db,i,"readwrite",n),await n.wrap(async r=>{const n=r.getStore(e),i=this.getModel(e),c=i.getPrimaryKey(),l=a?{[a.key]:i.getRelation(a.key)?.isArray?[a.id]:a.id}:{},u=c.isAutoIncremented()?{...l}:{...l,[i.primaryKey]:t[i.primaryKey]??c.genKey()},d=await n.add(u),h={},y=/* @__PURE__ */new Set;for(const a of m(t)){y.add(a);const n=t[a];switch(i.keyType(a)){case E.Invalid:throw new s(`Key '${a}' does ont exist on model '${e}'`);case E.Property:{const e=i.parseField(a,n);if(!e)throw new o;if(!e.success)throw new s(`Key '${a}' has the following validation error: ${e.error}`);h[a]=e.data;break}case E.Relation:{if(!n)continue;const e=g(n),t=i.getRelation(a);if(t.isArray&&(h[a]=[],"$createMany"in n||"$connectMany"in n)){const t=[];for(const e of n.$createMany??[])t.push({$create:e});for(const e of n.$connectMany??[])t.push({$connect:e});e.push(...t)}const o=this.getModel(t.to).getRelation(t.getRelatedKey()),c=/* @__PURE__ */new Set;for(const n of e){const e=m(n)[0];if(!e)throw new s(`Key '${a}' cannot be an empty connection object`);switch(e){case"$connect":{const i=n[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,d,i,r),t.isArray?h[a].push(i):h[a]=i;break}case"$create":{const s=await this.add(t.to,n[e],{tx:r,relation:{id:d,key:t.getRelatedKey()}});t.isArray?h[a].push(s):h[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 E.PrimaryKey:}}const f=Array.from(new Set(i.keys()).difference(y));for(const e of f)switch(i.keyType(e)){case E.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`);h[e]=t.data;break}case E.Relation:{const t=i.getRelation(e),r=l[e];if(t.isArray)h[e]=r??[];else if(t.isOptional)h[e]=r??null;else{if(!r)throw new s(`Required relation '${e}' is not defined`);h[e]=r}break}case E.Invalid:case E.PrimaryKey:}return await n.put({[i.primaryKey]:d,...h})})}async clear(e,t){await J(e,this,void 0,!1,t)}async find(e,t,r,n={}){let{tx:s}=n;const a=this.getAccessedStores(e,q(t),!1,s);s=V.create(this.db,a,"readonly",s);const o=[];return await s.wrap(async n=>{const s=n.getStore(e),a=z(e,this,t);return await s.openCursor(async e=>{const t=await a(e.value,n);return t&&o.push(t),(!r||!o.length)&&(e.continue(),!0)}),o})}async update(e,t,r,n={}){const{singleton:a}=n,i=n.singleton?t:t.data,c=this.getAccessedStores(e,i,!0,n.tx),d=V.create(this.db,c,"readwrite",n.tx);return await d.wrap(async n=>{const c=n.getStore(e),d=this.getModel(e),h=[];for(const e of m(i))switch(d.keyType(e)){case E.Property:h.push({key:e,isRelation:!1,updateFn:"function"==typeof i[e]?i[e]:()=>i[e]});break;case E.Relation:{const t=g(i[e]);if(!t)continue;const r=[];for(const e of t)for(const t in e){switch(t){case"$createMany":case"$connectMany":case"$updateMany":case"$deleteMany":case"$disconnectMany":{const n=t.substring(0,t.length-4);for(const s of e[t])r.push([n,s]);break}default:r.push([t,e[t]])}break}h.push({actions:r,key:e,isRelation:!0,relation:d.getRelation(e)});break}case E.PrimaryKey:throw new u("Primary key field cannot be updated");case E.Invalid:default:throw new o(`Unknown key '${e}'`)}const y=[],f=async e=>{const t=e[d.primaryKey];for(const{key:r,...a}of h){const o=a.relation;if(a.isRelation)for(const[i,c]of a.actions)switch(i){case"$connect":e[r]&&!o.isArray&&await this.disconnectDocument(o,t,e[r],n).catch(n.onRejection),await this.connectDocument(o,t,c,n).catch(n.onRejection),o.isArray?e[r].push(c):e[r]=c;break;case"$create":{const s=await this.add(o.to,c,{tx:n,relation:{id:t,key:o.getRelatedKey()}});o.isArray?e[r].push(s):e[r]=s;break}case"$delete":if(!o.isNullable())throw new s("Item cannot be deleted, relation is required");e[r]=o.isArray&&Array.isArray(e[r])?e[r].filter(e=>e!==c):null,await J(o.to,this,{},!0,{tx:n,singleton:{id:c}});break;case"$disconnect":{if(!o.isNullable())throw new s("Item cannot be disconnected, relation is required");if(!e[r]||0===e[r]?.lenth)break;const a=this.getModel(o.to).getRelation(o.getRelatedKey());await this.disconnectDocument(o,t,a.isArray?c:e[r],n).catch(n.onRejection),e[r]=o.isArray&&Array.isArray(e[r])?e[r].filter(e=>e!==c):null;break}case"$update":o.isArray?await this.update(o.to,c,!1,{tx:n}):null!=e[r]&&await this.update(o.to,c,!1,{tx:n,singleton:{id:t}});break;case"$deleteAll":if(c&&o.isArray&&Array.isArray(e[r])){const t=this.getModel(o.to),s=new Set(e[r]);await J(o.to,this,{[t.primaryKey]:e=>s.has(e)},!1,{tx:n}),e[r]=[]}break;case"$disconnectAll":if(c&&o.isArray&&Array.isArray(e[r])){for(const s of e[r])await this.disconnectDocument(o,t,s,n);e[r]=[]}}else e[r]=a.updateFn(e[r])}return e};if(a){const e=await c.get(a.id);if(!e)throw new l(`${d.name} with priamry key '${a.id}' not found`);const t=await f(e).catch(n.onRejection);return await c.put(t),[t]}{const e=B(t.where);return await c.openCursor(async t=>{const s=t.value;if(C(e,s)){const e=await f(s).catch(n.onRejection);if(await p(t.update(e)).then(()=>y.push(e)).catch(n.onRejection),r)return!1}return t.continue(),!0}),y}})}async connectDocument(e,t,r,n){const s=n.getStore(e.to),a=await s.get(r);if(!a)throw new l(`Document with Primary Key '${r}' 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 f;a[o]=t}return await s.put(a).catch(n.onRejection),r}async disconnectDocument(e,t,r,n){const s=n.getStore(e.to),a=await s.get(r);if(!a)throw new l(`Document with Primary Key '${r}' 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 f;a[e.getRelatedKey()]=null}return await s.put(a).catch(n.onRejection),r}}class te{constructor(e,t){this.name=e,this.names=t,this.models={}}models;defineModel(e,t){if("object"==typeof e&&P.is(e))return this.models[e.name]=e,e;{if(!t)throw new Error("Model Fields must be defined");const r=new P(e,t);return this.models[e]=r,r}}compile(e){return new re(this.name,e)}}class re{constructor(e,t){this.name=e,this.models=t,this.modelKeys=m(this.models),this.schemas={};for(const n of this.modelKeys){const e=this.models[n],t={};for(const s of e.keys()){const a=e.get(s);if(F.is(a))t[s]=a.parse;else if(M.is(a)){const{onDelete:o}=a.getActions(),i=this.models[a.to],c=i.getPrimaryKey();t[s]=K[c.type.tag],a.isOptional?t[s]=new T(t[s],c.type).optional().parse:a.isArray&&(t[s]=t[s]=new T(t[s],c.type).array().parse);let l=!!a.getRelatedKey();if(!l)for(const[t,n]of i.relations())if(s!==t&&n.to===e.name&&n.name===a.name){if(l=!0,a.setRelatedKey(t),n.setRelatedKey(s),"SetNull"===o&&!n.isNullable())throw new r(`Key '${t}' on model '${i.name}': Non-optional relation cannot have the 'SetNull' action`);break}if(!l)throw new r(`Relation '${a.name}' of model ${n} does not have an equivalent relation on model '${a.to}'`)}else{if(!N.is(a))throw new r(`Unknown field value detected: ${JSON.stringify(a)}`);t[s]=K[a.type.tag]}}this.schemas[n]=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 r of this.modelKeys){const e=this.models[r];t.objectStoreNames.contains(e.name)||t.createObjectStore(e.name,{autoIncrement:e.getPrimaryKey().isAutoIncremented(),keyPath:e.primaryKey})}};const r=await p(t);return new ee(r,this)}keys(){return[...this.modelKeys]}}const ne=/* @__PURE__ */Object.freeze(/* @__PURE__ */Object.defineProperty({__proto__:null,AbstractProperty:F,ArrayRelation:I,BaseRelation:M,DbClient:ee,FieldTypes:E,Model:P,OptionalRelation:j,PrimaryKey:N,Property:T,Relation:D,Type:k,Typing:R,VALIDATORS:K},Symbol.toStringTag,{value:"Module"}));export{te as Builder,G as CompiledQuery,P as Model,T as Property,e as StoreError,ne 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};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { CompiledDb } from '../builder.js';
|
|
2
|
-
import { ValidValue, BaseRelation, OptionalRelation, ArrayRelation, RelationOutput, Relation,
|
|
2
|
+
import { ValidValue, BaseRelation, OptionalRelation, ArrayRelation, RelationOutput, Relation, Property, PrimaryKey, TypeTag } from '../field';
|
|
3
3
|
import { Dict, Keyof } from '../util-types.js';
|
|
4
4
|
import { default as Model } from './model.js';
|
|
5
5
|
export type FindPrimaryKey<F extends Record<string, ValidValue>> = Extract<{
|
|
@@ -20,7 +20,7 @@ export type RelationValue<Name extends string, C> = Name extends keyof C ? C[Nam
|
|
|
20
20
|
*/
|
|
21
21
|
export type GetRelationField<F, C> = F extends Relation<infer To, any> ? RelationValue<To, C> : F extends OptionalRelation<infer To, any> ? RelationValue<To, C> | null : F extends ArrayRelation<infer To, any> ? RelationValue<To, C>[] : never;
|
|
22
22
|
export type ModelStructure<F extends Dict<ValidValue>, C> = {
|
|
23
|
-
[K in keyof F]: F[K] extends
|
|
23
|
+
[K in keyof F]: F[K] extends Property<infer Output, any> ? Output : F[K] extends PrimaryKey<any, infer Type> ? Type : GetRelationField<F[K], C>;
|
|
24
24
|
};
|
|
25
25
|
export type ModelType<M extends Model<any, any, any>, C extends CompiledDb<any, any, any>> = M extends Model<any, infer Fields, any> ? C extends CompiledDb<any, any, infer Collection> ? ModelStructure<Fields, Collection> : never : never;
|
|
26
26
|
export type ExtractFields<M extends Model<any, any, any>> = M extends Model<any, infer Fields, any> ? Fields : never;
|
|
@@ -28,10 +28,13 @@ export type AllRelationKeys<M extends Model<any, any, any>> = M extends Model<an
|
|
|
28
28
|
[K in Keyof<Fields>]: Fields[K] extends BaseRelation<any, any> ? K : never;
|
|
29
29
|
}[Keyof<Fields>] : never;
|
|
30
30
|
export type RelationlessModelStructure<M extends Model<any, any, any>> = M extends Model<any, infer Fields, any> ? Omit<{
|
|
31
|
-
[K in Keyof<Fields>]: Fields[K] extends BaseRelation<any, any> ? unknown : Fields[K] extends
|
|
31
|
+
[K in Keyof<Fields>]: Fields[K] extends BaseRelation<any, any> ? unknown : Fields[K] extends Property<infer Type, any> ? Type : Fields[K] extends PrimaryKey<any, infer Type> ? Type : never;
|
|
32
32
|
}, AllRelationKeys<M>> : never;
|
|
33
|
+
export type TypeTagWrap<T extends Dict> = {
|
|
34
|
+
[K in keyof T]: TypeTag;
|
|
35
|
+
};
|
|
33
36
|
export type CollectionSchema<C> = C extends Record<infer Keys, Model<any, any, any>> ? {
|
|
34
|
-
[K in Keys]: C[K] extends Model<any, infer Fields, any> ?
|
|
37
|
+
[K in Keys]: C[K] extends Model<any, infer Fields, any> ? TypeTagWrap<ModelStructure<Fields, C>> : never;
|
|
35
38
|
} : never;
|
|
36
39
|
export type FindRelationKey<From extends string, RelationName extends string, M extends Model<any, any, any>> = M extends Model<any, infer Fields, any> ? {
|
|
37
40
|
[K in Keyof<Fields>]: Fields[K] extends BaseRelation<From, infer CurName> ? CurName extends RelationName ? K : never : never;
|
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>;
|
|
@@ -33,7 +34,7 @@ export default class Model<Name extends string, F extends Record<string, ValidVa
|
|
|
33
34
|
* Generator for all of the entries present on the model
|
|
34
35
|
*/
|
|
35
36
|
entries(): Generator<[key: string, value: ValidValue]>;
|
|
36
|
-
keys(): Keyof<F>[];
|
|
37
|
+
keys(): readonly Keyof<F>[];
|
|
37
38
|
parseField<K extends Keyof<F>>(field: K, value: unknown): ParseResult<any>;
|
|
38
39
|
getDeletedStores<ModelNames extends string, Models extends CollectionObject<ModelNames>>(client: DbClient<string, ModelNames, Models>): Set<ModelNames>;
|
|
39
40
|
static is<Name extends string, Fields extends Dict<ValidValue>, Primary extends FindPrimaryKey<Fields> = FindPrimaryKey<Fields>>(value: object): value is Model<Name, Fields, Primary>;
|
package/dist/object-store.d.ts
CHANGED
|
@@ -2,10 +2,13 @@ import { StoreError } from './error.js';
|
|
|
2
2
|
import { ValidKey } from './field';
|
|
3
3
|
import { Transaction } from './transaction.js';
|
|
4
4
|
import { Dict, Promisable } from './util-types.js';
|
|
5
|
+
/**
|
|
6
|
+
* A paper thin wrapper around IDBObjectStore
|
|
7
|
+
*/
|
|
5
8
|
export declare class ObjectStore<T = Dict> {
|
|
6
9
|
private readonly tx;
|
|
7
|
-
readonly
|
|
8
|
-
constructor(tx: Transaction<IDBTransactionMode, string>,
|
|
10
|
+
readonly internal: IDBObjectStore;
|
|
11
|
+
constructor(tx: Transaction<IDBTransactionMode, string>, internal: IDBObjectStore);
|
|
9
12
|
add(item: T): Promise<ValidKey>;
|
|
10
13
|
/**
|
|
11
14
|
* Attempts to retrieve the value from the object store.
|