sedentary 0.0.17 → 0.0.21
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/index.d.ts +63 -65
- package/index.js +102 -126
- package/lib/db.d.ts +21 -18
- package/lib/db.js +10 -13
- package/lib/minidb.js +20 -16
- package/lib/transaction.d.ts +2 -0
- package/lib/transaction.js +6 -0
- package/package.json +25 -7
- package/lib/log.d.ts +0 -4
- package/lib/log.js +0 -20
- package/lib/log.ts +0 -22
- package/requirements.txt +0 -2
package/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { DB,
|
|
2
|
-
export {
|
|
1
|
+
import { Attribute, DB, EntryBase, ForeignKeyOptions, Natural, Type } from "./lib/db";
|
|
2
|
+
export { EntryBase, ForeignKeyActions, ForeignKeyOptions, Natural, Type } from "./lib/db";
|
|
3
3
|
export declare type TypeDefinition<N extends Natural, E> = (() => Type<N, E>) | Type<N, E>;
|
|
4
4
|
export interface AttributeOptions<N extends Natural, E> {
|
|
5
5
|
defaultValue?: N;
|
|
@@ -12,17 +12,13 @@ export declare type AttributeDefinition<N extends Natural, E> = TypeDefinition<N
|
|
|
12
12
|
export declare type AttributesDefinition = {
|
|
13
13
|
[key: string]: AttributeDefinition<Natural, unknown>;
|
|
14
14
|
};
|
|
15
|
-
declare type
|
|
16
|
-
declare type
|
|
17
|
-
[
|
|
18
|
-
}[keyof
|
|
19
|
-
declare type Methods<T> = {
|
|
20
|
-
[key: string]: (this: T) => unknown;
|
|
21
|
-
};
|
|
15
|
+
declare type ForeignKeysAttributes<T, k> = T extends AttributeDefinition<Natural, infer E> ? (E extends EntryBase ? k : never) : never;
|
|
16
|
+
declare type ForeignKeys<A extends AttributesDefinition> = {
|
|
17
|
+
[a in keyof A]?: ForeignKeysAttributes<A[a], a>;
|
|
18
|
+
}[keyof A];
|
|
22
19
|
declare type Native__<T> = T extends Type<infer N, unknown> ? N : never;
|
|
23
20
|
declare type Native_<T> = T extends () => Type<infer N, infer E> ? Native__<Type<N, E>> : Native__<T>;
|
|
24
21
|
declare type Native<T> = T extends AttributeOptions<infer N, infer E> ? Native__<Type<N, E>> : Native_<T>;
|
|
25
|
-
declare type Parent<T> = T extends Meta<Natural, infer E> ? E : never;
|
|
26
22
|
export declare type IndexAttributes = string[] | string;
|
|
27
23
|
export interface IndexOptions {
|
|
28
24
|
attributes: IndexAttributes;
|
|
@@ -33,34 +29,59 @@ export declare type IndexDefinition = IndexAttributes | IndexOptions;
|
|
|
33
29
|
export declare type IndexesDefinition = {
|
|
34
30
|
[key: string]: IndexDefinition;
|
|
35
31
|
};
|
|
36
|
-
|
|
32
|
+
interface BaseModelOptions {
|
|
37
33
|
indexes?: IndexesDefinition;
|
|
38
|
-
init?: (this: T) => void;
|
|
39
34
|
sync?: boolean;
|
|
40
35
|
tableName?: string;
|
|
41
|
-
}
|
|
42
|
-
export
|
|
36
|
+
}
|
|
37
|
+
export interface ModelOptions extends BaseModelOptions {
|
|
43
38
|
int8id?: boolean;
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
39
|
+
parent?: Type<Natural, EntryBase>;
|
|
40
|
+
primaryKey?: string;
|
|
41
|
+
}
|
|
42
|
+
declare type ConditionAttribute<N extends Natural> = N | [">" | "<" | ">=" | "<=" | "<>", N] | ["LIKE", string] | ["IN", ...N[]];
|
|
43
|
+
declare type ConditionBase<A extends AttributesDefinition> = string | {
|
|
44
|
+
[a in keyof A]?: ConditionAttribute<Native<A[a]>>;
|
|
47
45
|
};
|
|
48
|
-
declare type
|
|
49
|
-
declare type
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
declare type
|
|
46
|
+
declare type Condition<A extends AttributesDefinition> = ConditionBase<A> | ["NOT", Condition<A>] | ["AND", ...Condition<A>[]] | ["OR", ...Condition<A>[]];
|
|
47
|
+
declare type UnionToIntersection<U> = (U extends unknown ? (k: U) => void : never) extends (k: infer I) => void ? I : never;
|
|
48
|
+
declare type IsUnion<T> = [T] extends [UnionToIntersection<T>] ? false : true;
|
|
49
|
+
declare type BaseKeyType<B extends boolean> = IsUnion<B> extends true ? number : B extends true ? string : number;
|
|
50
|
+
declare type KeyType<B extends boolean, P extends ModelStd> = P extends new () => EntryBase ? (P extends Attribute<infer T, EntryBase> ? T : never) : BaseKeyType<B>;
|
|
51
|
+
declare type ForeignKey<A> = A extends AttributeDefinition<Natural, infer E> ? () => Promise<E> : never;
|
|
52
|
+
declare type EntryBaseAttributes<A extends AttributesDefinition> = {
|
|
55
53
|
[a in keyof A]?: Native<A[a]>;
|
|
56
|
-
} & {
|
|
57
|
-
[a in Keys<A> & string as `${a}Load`]?: ForeignKey<A[a]>;
|
|
58
54
|
};
|
|
59
|
-
declare type
|
|
60
|
-
|
|
55
|
+
declare type EntryMethodsBase<P extends ModelStd> = P extends new () => EntryBase ? P["methods"] : EntryBase;
|
|
56
|
+
declare type EntryMethodsFK<A extends AttributesDefinition> = {
|
|
57
|
+
[a in ForeignKeys<A> & string as `${a}Load`]: ForeignKey<A[a]>;
|
|
58
|
+
};
|
|
59
|
+
declare type EntryMethods<A extends AttributesDefinition, P extends ModelStd> = keyof EntryMethodsFK<A> extends never ? EntryMethodsBase<P> : EntryMethodsBase<P> & EntryMethodsFK<A>;
|
|
60
|
+
declare type ModelAttributesIf<A extends AttributesDefinition, T> = keyof A extends never ? T : T & A;
|
|
61
|
+
declare type ModelAttributes<A extends AttributesDefinition, B extends boolean, K extends string, P extends ModelStd> = K extends keyof A ? A : ModelAttributesIf<A, P extends new () => EntryBase ? P["attributes"] : {
|
|
62
|
+
id: Type<BaseKeyType<B>, unknown>;
|
|
63
|
+
}>;
|
|
64
|
+
declare type ModelBase<N extends Natural, A extends AttributesDefinition, EA extends Record<string, Natural | undefined>, EM extends EntryBase, E extends EntryBase> = (new (from?: EA) => E) & Attribute<N, E> & {
|
|
65
|
+
attributes: A;
|
|
66
|
+
foreignKeys: Record<string, boolean>;
|
|
67
|
+
methods: EM;
|
|
68
|
+
parent?: ModelStd;
|
|
69
|
+
tableName: string;
|
|
70
|
+
load: (where?: Condition<A>) => Promise<E[]>;
|
|
61
71
|
} & {
|
|
62
|
-
|
|
63
|
-
}
|
|
72
|
+
[a in keyof A]: Attribute<Native<A[a]>, E>;
|
|
73
|
+
};
|
|
74
|
+
declare type Model<N extends Natural, A extends AttributesDefinition, EM extends EntryBase> = ModelBase<N, A, EntryBaseAttributes<A>, EM, EntryBaseAttributes<A> & EM>;
|
|
75
|
+
declare type ModelStd = Attribute<Natural, EntryBase> & {
|
|
76
|
+
attributes: AttributesDefinition;
|
|
77
|
+
foreignKeys: Record<string, boolean>;
|
|
78
|
+
methods: EntryBase;
|
|
79
|
+
parent?: ModelStd;
|
|
80
|
+
};
|
|
81
|
+
export declare type Entry<M> = M extends new () => infer E ? E : never;
|
|
82
|
+
export declare type Where<M> = M extends {
|
|
83
|
+
load: (where: infer T) => void;
|
|
84
|
+
} ? Exclude<T, undefined> : never;
|
|
64
85
|
export interface SedentaryOptions {
|
|
65
86
|
log?: ((message: string) => void) | null;
|
|
66
87
|
serverless?: boolean;
|
|
@@ -73,45 +94,22 @@ export declare class Sedentary {
|
|
|
73
94
|
private models;
|
|
74
95
|
constructor(filename: string, options?: SedentaryOptions);
|
|
75
96
|
DATETIME(): Type<Date, unknown>;
|
|
76
|
-
FKEY<N extends Natural, E extends
|
|
97
|
+
FKEY<N extends Natural, E extends EntryBase>(attribute: Attribute<N, E>, options?: ForeignKeyOptions): Type<N, E>;
|
|
77
98
|
INT(size?: number): Type<number, unknown>;
|
|
78
99
|
INT8(): Type<string, unknown>;
|
|
79
100
|
VARCHAR(size?: number): Type<string, unknown>;
|
|
101
|
+
checkSize(size: number, message: string): number;
|
|
80
102
|
connect(): Promise<void>;
|
|
81
103
|
end(): Promise<void>;
|
|
82
|
-
model<A extends AttributesDefinition,
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
primaryKey
|
|
91
|
-
}):
|
|
92
|
-
model<A extends AttributesDefinition, M extends Methods<T>, P extends Meta<Natural, Entry>, N extends P extends Meta<infer N, Entry> ? N : never, T extends Parent<P> & ModelWithMetods<A, M>>(modelName: string, attributes: A, options?: BaseModelOptions<T> & {
|
|
93
|
-
methods: M;
|
|
94
|
-
parent: P;
|
|
95
|
-
}): Ancestor<A, N, T>;
|
|
96
|
-
model<A extends AttributesDefinition, M extends Methods<T>, T extends Entry & {
|
|
97
|
-
id?: number;
|
|
98
|
-
} & ModelWithMetods<A, M>>(modelName: string, attributes: A, options?: BaseModelOptions<T> & {
|
|
99
|
-
methods: M;
|
|
100
|
-
}): Ancestor<A, number, T>;
|
|
101
|
-
model<A extends AttributesDefinition, T extends Entry & {
|
|
102
|
-
id?: string;
|
|
103
|
-
} & Model<A>>(modelName: string, attributes: A, options?: BaseModelOptions<T> & {
|
|
104
|
-
int8id: true;
|
|
105
|
-
}): Ancestor<A, string, T>;
|
|
106
|
-
model<A extends AttributesDefinition, K extends keyof A, N extends K extends keyof A ? Native<A[K]> : never, T extends Entry & Model<A>>(modelName: string, attributes: A, options?: BaseModelOptions<T> & {
|
|
107
|
-
primaryKey: K;
|
|
108
|
-
}): Ancestor<A, N, T>;
|
|
109
|
-
model<A extends AttributesDefinition, P extends Meta<Natural, Entry>, N extends P extends Meta<infer N, Entry> ? N : never, T extends Parent<P> & Model<A>>(modelName: string, attributes: A, options?: BaseModelOptions<T> & {
|
|
110
|
-
parent: P;
|
|
111
|
-
}): Ancestor<A, N, T>;
|
|
112
|
-
model<A extends AttributesDefinition, T extends Entry & {
|
|
113
|
-
id?: number;
|
|
114
|
-
} & Model<A>>(modelName: string, attributes: A, options?: BaseModelOptions<T>): Ancestor<A, number, T>;
|
|
115
|
-
checkSize(size: number, message: string): number;
|
|
104
|
+
model<A extends AttributesDefinition, B extends boolean, K extends string, P extends ModelStd, EM extends EntryMethods<A, P>>(modelName: string, attributes: A, options?: BaseModelOptions & {
|
|
105
|
+
int8id?: B;
|
|
106
|
+
parent?: P;
|
|
107
|
+
primaryKey?: K | keyof A;
|
|
108
|
+
}): Model<K extends keyof A ? Native<A[K]> : KeyType<B, P>, ModelAttributes<A, B, K, P>, EM>;
|
|
109
|
+
model<A extends AttributesDefinition, B extends boolean, K extends string, P extends ModelStd, EA extends EntryBaseAttributes<ModelAttributes<A, B, K, P>>, EM extends EntryMethods<A, P>, M extends Record<string, <S extends M>(this: EA & EM & S, ...args: any[]) => void>>(modelName: string, attributes: A, options: BaseModelOptions & {
|
|
110
|
+
int8id?: B;
|
|
111
|
+
parent?: P;
|
|
112
|
+
primaryKey?: K | keyof A;
|
|
113
|
+
}, methods: M & Record<keyof M, (this: EA & EM & M, ...args: any[]) => void>): Model<K extends keyof A ? Native<A[K]> : KeyType<B, P>, ModelAttributes<A, B, K, P>, EM & M>;
|
|
116
114
|
}
|
|
117
115
|
export declare const Package: typeof Sedentary;
|
package/index.js
CHANGED
|
@@ -1,16 +1,15 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.Package = exports.Sedentary = exports.Type = exports.
|
|
3
|
+
exports.Package = exports.Sedentary = exports.Type = exports.EntryBase = void 0;
|
|
4
4
|
const db_1 = require("./lib/db");
|
|
5
|
-
const log_1 = require("./lib/log");
|
|
6
5
|
const minidb_1 = require("./lib/minidb");
|
|
7
6
|
var db_2 = require("./lib/db");
|
|
8
|
-
Object.defineProperty(exports, "
|
|
7
|
+
Object.defineProperty(exports, "EntryBase", { enumerable: true, get: function () { return db_2.EntryBase; } });
|
|
9
8
|
Object.defineProperty(exports, "Type", { enumerable: true, get: function () { return db_2.Type; } });
|
|
10
|
-
const allowedOption = ["indexes", "
|
|
9
|
+
const allowedOption = ["indexes", "int8id", "parent", "primaryKey", "sync", "tableName"];
|
|
11
10
|
const reservedNames = [
|
|
12
|
-
...["attributeName", "base", "class", "constructor", "defaultValue", "entry", "fieldName", "
|
|
13
|
-
...["
|
|
11
|
+
...["attributeName", "attributes", "base", "class", "construct", "constructor", "defaultValue", "entry", "fieldName", "foreignKeys", "load"],
|
|
12
|
+
...["methods", "name", "postLoad", "postSave", "preLoad", "preSave", "primaryKey", "prototype", "save", "size", "tableName", "type"]
|
|
14
13
|
];
|
|
15
14
|
class Sedentary {
|
|
16
15
|
constructor(filename, options) {
|
|
@@ -30,16 +29,17 @@ class Sedentary {
|
|
|
30
29
|
throw new Error("new Sedentary: 'log' option: Wrong type, expected 'null' or 'Function'");
|
|
31
30
|
if (typeof sync !== "boolean")
|
|
32
31
|
throw new Error("new Sedentary: 'sync' option: Wrong type, expected 'boolean'");
|
|
33
|
-
|
|
32
|
+
// eslint-disable-next-line no-console
|
|
33
|
+
this.log = log ? log : log === null ? () => { } : console.log;
|
|
34
34
|
this.db = new minidb_1.MiniDB(filename, this.log);
|
|
35
35
|
this.sync = sync;
|
|
36
36
|
}
|
|
37
37
|
DATETIME() {
|
|
38
38
|
return new db_1.Type({ base: Date, type: "DATETIME" });
|
|
39
39
|
}
|
|
40
|
-
FKEY(attribute) {
|
|
40
|
+
FKEY(attribute, options) {
|
|
41
41
|
const { attributeName, base, fieldName, size, tableName, type } = attribute;
|
|
42
|
-
return new db_1.Type({ base, foreignKey: { attributeName, fieldName, tableName }, size, type });
|
|
42
|
+
return new db_1.Type({ base, foreignKey: { attributeName, fieldName, options, tableName }, size, type });
|
|
43
43
|
}
|
|
44
44
|
INT(size) {
|
|
45
45
|
const message = "Sedentary.INT: 'size' argument: Wrong value, expected 2 or 4";
|
|
@@ -56,6 +56,13 @@ class Sedentary {
|
|
|
56
56
|
size = size ? this.checkSize(size, message) : undefined;
|
|
57
57
|
return new db_1.Type({ base: String, size, type: "VARCHAR" });
|
|
58
58
|
}
|
|
59
|
+
checkSize(size, message) {
|
|
60
|
+
const str = size.toString();
|
|
61
|
+
const parsed = parseInt(str, 10);
|
|
62
|
+
if (str !== parsed.toString())
|
|
63
|
+
throw new Error(message);
|
|
64
|
+
return parsed;
|
|
65
|
+
}
|
|
59
66
|
async connect() {
|
|
60
67
|
try {
|
|
61
68
|
this.log("Connecting...");
|
|
@@ -65,7 +72,7 @@ class Sedentary {
|
|
|
65
72
|
this.log("Synced");
|
|
66
73
|
}
|
|
67
74
|
catch (e) {
|
|
68
|
-
this.log("Connecting:"
|
|
75
|
+
this.log("Connecting: " + (e instanceof Error ? e.message : JSON.stringify(e)));
|
|
69
76
|
throw e;
|
|
70
77
|
}
|
|
71
78
|
}
|
|
@@ -74,7 +81,8 @@ class Sedentary {
|
|
|
74
81
|
await this.db.end();
|
|
75
82
|
this.log("Connection closed");
|
|
76
83
|
}
|
|
77
|
-
|
|
84
|
+
/* eslint-enable @typescript-eslint/no-explicit-any */
|
|
85
|
+
model(modelName, attributes, options, methods) {
|
|
78
86
|
if (typeof modelName !== "string")
|
|
79
87
|
throw new Error("Sedentary.model: 'name' argument: Wrong type, expected 'string'");
|
|
80
88
|
if (this.models[modelName])
|
|
@@ -98,7 +106,6 @@ class Sedentary {
|
|
|
98
106
|
throw new Error(`Sedentary.model: '${modelName}' model: 'parent' and 'primaryKey' options conflict each other`);
|
|
99
107
|
let autoIncrement = true;
|
|
100
108
|
const { indexes, int8id, parent, primaryKey, sync, tableName } = Object.assign({ sync: this.sync, tableName: modelName }, options);
|
|
101
|
-
let { methods } = options;
|
|
102
109
|
let aarray = int8id
|
|
103
110
|
? [new db_1.Attribute(Object.assign(Object.assign({}, this.INT8()), { attributeName: "id", fieldName: "id", modelName, notNull: true, tableName, unique: true }))]
|
|
104
111
|
: [new db_1.Attribute(Object.assign(Object.assign({}, this.INT(4)), { attributeName: "id", fieldName: "id", modelName, notNull: true, tableName, unique: true }))];
|
|
@@ -107,16 +114,11 @@ class Sedentary {
|
|
|
107
114
|
const pk = aarray[0];
|
|
108
115
|
if (methods && !(methods instanceof Object))
|
|
109
116
|
throw new Error(`Sedentary.model: '${modelName}' model: 'methods' option: Wrong type, expected 'Object'`);
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
throw new Error();
|
|
114
|
-
}
|
|
115
|
-
catch (e) {
|
|
117
|
+
const originalMethods = methods;
|
|
118
|
+
if (parent)
|
|
119
|
+
if (!parent.attributes)
|
|
116
120
|
throw new Error(`Sedentary.model: '${modelName}' model: 'parent' option: Wrong type, expected 'Model'`);
|
|
117
|
-
|
|
118
|
-
methods = (methods ? Object.assign(Object.assign({}, (parent.methods || {})), methods) : parent.methods);
|
|
119
|
-
}
|
|
121
|
+
//methods = (methods ? { ...(parent.methods || {}), ...methods } : parent.methods) as never;
|
|
120
122
|
if (primaryKey && typeof primaryKey !== "string")
|
|
121
123
|
throw new Error(`Sedentary.model: '${modelName}' model: 'primaryKey' option: Wrong type, expected 'string'`);
|
|
122
124
|
if (primaryKey && !Object.keys(attributes).includes(primaryKey))
|
|
@@ -174,6 +176,23 @@ class Sedentary {
|
|
|
174
176
|
}
|
|
175
177
|
return ret;
|
|
176
178
|
})();
|
|
179
|
+
if (foreignKey) {
|
|
180
|
+
const options = foreignKey.options || {};
|
|
181
|
+
if (foreignKey.options !== undefined && !(foreignKey.options instanceof Object))
|
|
182
|
+
throw new Error(`Sedentary.FKEY: '${modelName}' model: '${attributeName}' attribute: Wrong options type, expected 'Object'`);
|
|
183
|
+
for (const k in options)
|
|
184
|
+
if (!["onDelete", "onUpdate"].includes(k))
|
|
185
|
+
throw new Error(`Sedentary.FKEY: '${modelName}' model: '${attributeName}' attribute: Unknown option '${k}'`);
|
|
186
|
+
for (const onChange of ["onDelete", "onUpdate"]) {
|
|
187
|
+
const actions = ["cascade", "no action", "restrict", "set default", "set null"];
|
|
188
|
+
let action = options[onChange];
|
|
189
|
+
if (!action)
|
|
190
|
+
action = options[onChange] = "no action";
|
|
191
|
+
if (action && !actions.includes(action))
|
|
192
|
+
throw new Error(`Sedentary.FKEY: '${modelName}' model: '${attributeName}' attribute: '${onChange}' option: Wrong value, expected ${actions.map(_ => `'${_}'`).join(" | ")}`);
|
|
193
|
+
}
|
|
194
|
+
foreignKey.options = options;
|
|
195
|
+
}
|
|
177
196
|
if (primaryKey === attributeName) {
|
|
178
197
|
notNull = true;
|
|
179
198
|
unique = true;
|
|
@@ -241,120 +260,77 @@ class Sedentary {
|
|
|
241
260
|
}
|
|
242
261
|
this.db.tables.push(new db_1.Table({ autoIncrement, constraints, attributes: aarray, indexes: iarray, parent, sync, tableName }));
|
|
243
262
|
this.models[modelName] = true;
|
|
244
|
-
const
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
263
|
+
const foreignKeys = aarray
|
|
264
|
+
.filter(_ => _.foreignKey)
|
|
265
|
+
.reduce((ret, curr) => {
|
|
266
|
+
ret[curr.attributeName] = true;
|
|
267
|
+
return ret;
|
|
268
|
+
}, {});
|
|
269
|
+
for (const foreignKey in foreignKeys) {
|
|
270
|
+
if (foreignKey + "Load" in attributes)
|
|
271
|
+
throw new Error(`Sedentary.model: '${modelName}' model: '${foreignKey}' attribute: '${foreignKey}Load' inferred methods conflicts with an attribute`);
|
|
272
|
+
if (originalMethods && foreignKey + "Load" in originalMethods)
|
|
273
|
+
throw new Error(`Sedentary.model: '${modelName}' model: '${foreignKey}' attribute: '${foreignKey}Load' inferred methods conflicts with a method`);
|
|
274
|
+
}
|
|
275
|
+
if (originalMethods)
|
|
276
|
+
for (const method in originalMethods)
|
|
277
|
+
if (method in attributes)
|
|
278
|
+
throw new Error(`Sedentary.model: '${modelName}' model: '${method}' method: conflicts with an attribute`);
|
|
279
|
+
const checkParent = (parent) => {
|
|
280
|
+
if (!parent)
|
|
281
|
+
return;
|
|
282
|
+
for (const attribute in attributes) {
|
|
283
|
+
if (attribute in parent.attributes)
|
|
284
|
+
throw new Error(`Sedentary.model: '${modelName}' model: '${attribute}' attribute: conflicts with an attribute of '${parent.modelName}' model`);
|
|
285
|
+
if (attribute in parent.methods)
|
|
286
|
+
throw new Error(`Sedentary.model: '${modelName}' model: '${attribute}' attribute: conflicts with a method of '${parent.modelName}' model`);
|
|
287
|
+
for (const foreignKey in parent.foreignKeys)
|
|
288
|
+
if (attribute === foreignKey + "Load")
|
|
289
|
+
throw new Error(`Sedentary.model: '${modelName}' model: '${attribute}' attribute: conflicts with an inferred methods of '${parent.modelName}' model`);
|
|
259
290
|
}
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
});
|
|
291
|
+
for (const foreignKey in foreignKeys) {
|
|
292
|
+
if (foreignKey + "Load" in parent.attributes)
|
|
293
|
+
throw new Error(`Sedentary.model: '${modelName}' model: '${foreignKey}' attribute: '${foreignKey}Load' inferred methods conflicts with an attribute of '${parent.modelName}' model`);
|
|
294
|
+
if (foreignKey + "Load" in parent.methods)
|
|
295
|
+
throw new Error(`Sedentary.model: '${modelName}' model: '${foreignKey}' attribute: '${foreignKey}Load' inferred methods conflicts with a method of '${parent.modelName}' model`);
|
|
266
296
|
}
|
|
267
|
-
|
|
297
|
+
if (originalMethods) {
|
|
298
|
+
for (const method in originalMethods) {
|
|
299
|
+
if (method in parent.attributes)
|
|
300
|
+
throw new Error(`Sedentary.model: '${modelName}' model: '${method}' method: conflicts with an attribute of '${parent.modelName}' model`);
|
|
301
|
+
for (const foreignKey in parent.foreignKeys)
|
|
302
|
+
if (foreignKey + "Load" === method)
|
|
303
|
+
throw new Error(`Sedentary.model: '${modelName}' model: '${method}' method: conflicts with an inferred methods of '${parent.modelName}' model`);
|
|
304
|
+
if (method in parent.methods)
|
|
305
|
+
throw new Error(`Sedentary.model: '${modelName}' model: '${method}' method: conflicts with a method of '${parent.modelName}' model`);
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
checkParent(parent.parent);
|
|
309
|
+
};
|
|
310
|
+
checkParent(parent);
|
|
311
|
+
const ret = function () { };
|
|
268
312
|
const load = (boh) => new Promise((resolve, reject) => setTimeout(() => {
|
|
269
313
|
if (boh)
|
|
270
|
-
return resolve([new
|
|
314
|
+
return resolve([new ret()]);
|
|
271
315
|
reject(new Error("boh"));
|
|
272
316
|
}, 10));
|
|
273
317
|
Object.defineProperty(load, "name", { value: modelName + ".load" });
|
|
274
|
-
|
|
275
|
-
Object.defineProperty(
|
|
276
|
-
Object.defineProperty(
|
|
277
|
-
Object.defineProperty(
|
|
278
|
-
Object.defineProperty(
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
318
|
+
Object.defineProperty(ret, "name", { value: modelName });
|
|
319
|
+
Object.defineProperty(ret, "load", { value: load });
|
|
320
|
+
Object.defineProperty(ret, "attributes", { value: attributes });
|
|
321
|
+
Object.defineProperty(ret, "foreignKeys", { value: foreignKeys });
|
|
322
|
+
Object.defineProperty(ret, "methods", { value: methods || {} });
|
|
323
|
+
if (methods)
|
|
324
|
+
Object.assign(ret.prototype, methods);
|
|
325
|
+
ret.prototype.save = function () {
|
|
326
|
+
return Promise.resolve(false);
|
|
327
|
+
};
|
|
282
328
|
for (const attribute of aarray)
|
|
283
|
-
Object.defineProperty(
|
|
284
|
-
for (const key of ["attributeName", "base", "fieldName", "modelName", "size", "type", "unique"])
|
|
285
|
-
Object.defineProperty(
|
|
286
|
-
return
|
|
287
|
-
}
|
|
288
|
-
checkSize(size, message) {
|
|
289
|
-
const str = size.toString();
|
|
290
|
-
const parsed = parseInt(str, 10);
|
|
291
|
-
if (str !== parsed.toString())
|
|
292
|
-
throw new Error(message);
|
|
293
|
-
return parsed;
|
|
329
|
+
Object.defineProperty(ret, attribute.attributeName, { value: attribute });
|
|
330
|
+
for (const key of ["attributeName", "base", "fieldName", "modelName", "size", "tableName", "type", "unique"])
|
|
331
|
+
Object.defineProperty(ret, key, { value: pk[key] });
|
|
332
|
+
return ret;
|
|
294
333
|
}
|
|
295
334
|
}
|
|
296
335
|
exports.Sedentary = Sedentary;
|
|
297
336
|
exports.Package = Sedentary;
|
|
298
|
-
const db = new Sedentary("gino");
|
|
299
|
-
const Users = db.model("User", { foo: db.INT(), bar: { type: db.VARCHAR(), unique: true } }, {});
|
|
300
|
-
class Item extends db.model("Item", {
|
|
301
|
-
num: db.FKEY(Users),
|
|
302
|
-
str: db.VARCHAR()
|
|
303
|
-
}, {
|
|
304
|
-
init: function () {
|
|
305
|
-
this.num = 0;
|
|
306
|
-
this.str = "0";
|
|
307
|
-
},
|
|
308
|
-
int8id: true,
|
|
309
|
-
methods: {
|
|
310
|
-
prova: () => "ok"
|
|
311
|
-
}
|
|
312
|
-
}) {
|
|
313
|
-
}
|
|
314
|
-
class Super extends db.model("Super", {
|
|
315
|
-
a: db.INT,
|
|
316
|
-
n: db.FKEY(Item),
|
|
317
|
-
s: db.FKEY(Users.bar)
|
|
318
|
-
}, {
|
|
319
|
-
parent: Item,
|
|
320
|
-
init: async function () {
|
|
321
|
-
this.n = "23";
|
|
322
|
-
this.id = "0";
|
|
323
|
-
this.num = 0;
|
|
324
|
-
const a = this.nLoad ? await this.nLoad() : { prova: () => null };
|
|
325
|
-
a.prova();
|
|
326
|
-
this.prova();
|
|
327
|
-
}
|
|
328
|
-
}) {
|
|
329
|
-
}
|
|
330
|
-
class Next extends db.model("Next", { a: db.INT, b: db.INT }, {
|
|
331
|
-
init: function () {
|
|
332
|
-
this.a = 23;
|
|
333
|
-
},
|
|
334
|
-
primaryKey: "a"
|
|
335
|
-
}) {
|
|
336
|
-
}
|
|
337
|
-
class Current extends db.model("Current", { b: { type: db.FKEY(Next), unique: true } }, {
|
|
338
|
-
init: function () {
|
|
339
|
-
this.b = 24;
|
|
340
|
-
}
|
|
341
|
-
}) {
|
|
342
|
-
}
|
|
343
|
-
class Last extends db.model("Last", { b: db.FKEY(Current.b) }, {
|
|
344
|
-
init: function () {
|
|
345
|
-
this.b = 24;
|
|
346
|
-
},
|
|
347
|
-
parent: Next
|
|
348
|
-
}) {
|
|
349
|
-
}
|
|
350
|
-
(async function () {
|
|
351
|
-
const item = new Super();
|
|
352
|
-
try {
|
|
353
|
-
await item.save();
|
|
354
|
-
}
|
|
355
|
-
catch (e) {
|
|
356
|
-
console.log(Item.load, item.save, await Item.load(true), item, e.message);
|
|
357
|
-
console.log(new Next(), Next.load, await Next.load(true), new Last(), item.prova());
|
|
358
|
-
}
|
|
359
|
-
return true;
|
|
360
|
-
})();
|
package/lib/db.d.ts
CHANGED
|
@@ -1,9 +1,17 @@
|
|
|
1
1
|
export declare type Natural = Date | Record<string, unknown> | boolean | number | string;
|
|
2
|
-
export declare class
|
|
3
|
-
|
|
2
|
+
export declare class EntryBase {
|
|
3
|
+
construct(): void;
|
|
4
|
+
postLoad(): void;
|
|
5
|
+
preLoad(): void;
|
|
6
|
+
preSave(): void;
|
|
4
7
|
save(): Promise<boolean>;
|
|
5
8
|
}
|
|
6
|
-
export declare
|
|
9
|
+
export declare type ForeignKeyActions = "cascade" | "no action" | "restrict" | "set default" | "set null";
|
|
10
|
+
export interface ForeignKeyOptions {
|
|
11
|
+
onDelete?: ForeignKeyActions;
|
|
12
|
+
onUpdate?: ForeignKeyActions;
|
|
13
|
+
}
|
|
14
|
+
export interface Type<N extends Natural, E> {
|
|
7
15
|
base: unknown;
|
|
8
16
|
entry?: E;
|
|
9
17
|
native?: N;
|
|
@@ -12,21 +20,14 @@ export declare class Type<N extends Natural, E> {
|
|
|
12
20
|
foreignKey?: {
|
|
13
21
|
attributeName: string;
|
|
14
22
|
fieldName: string;
|
|
23
|
+
options?: ForeignKeyOptions;
|
|
15
24
|
tableName: string;
|
|
16
25
|
};
|
|
17
|
-
constructor(from: Type<N, E>);
|
|
18
26
|
}
|
|
19
|
-
export declare class
|
|
20
|
-
|
|
21
|
-
isModel?: () => boolean;
|
|
22
|
-
methods: {
|
|
23
|
-
[key: string]: () => unknown;
|
|
24
|
-
};
|
|
25
|
-
primaryKey: string;
|
|
26
|
-
tableName: string;
|
|
27
|
-
constructor(from: Meta<N, E>);
|
|
27
|
+
export declare class Type<N extends Natural, E> {
|
|
28
|
+
constructor(from: Type<N, E>);
|
|
28
29
|
}
|
|
29
|
-
export
|
|
30
|
+
export interface Attribute<N extends Natural, E> extends Type<N, E> {
|
|
30
31
|
attributeName: string;
|
|
31
32
|
defaultValue?: unknown;
|
|
32
33
|
fieldName: string;
|
|
@@ -34,6 +35,8 @@ export declare class Attribute<N extends Natural, E> extends Type<N, E> {
|
|
|
34
35
|
notNull: boolean;
|
|
35
36
|
tableName: string;
|
|
36
37
|
unique?: boolean;
|
|
38
|
+
}
|
|
39
|
+
export declare class Attribute<N extends Natural, E> extends Type<N, E> {
|
|
37
40
|
constructor(from: Attribute<N, E>);
|
|
38
41
|
}
|
|
39
42
|
export interface Constraint {
|
|
@@ -52,11 +55,11 @@ interface ITable {
|
|
|
52
55
|
autoIncrement: boolean;
|
|
53
56
|
constraints: Constraint[];
|
|
54
57
|
indexes: Index[];
|
|
55
|
-
parent:
|
|
58
|
+
parent: any;
|
|
56
59
|
sync: boolean;
|
|
57
60
|
tableName: string;
|
|
58
61
|
}
|
|
59
|
-
declare const Table_base: new (defaults?: ITable) => ITable;
|
|
62
|
+
declare const Table_base: new (defaults?: ITable | undefined) => ITable;
|
|
60
63
|
export declare class Table extends Table_base {
|
|
61
64
|
autoIncrementOwn?: boolean;
|
|
62
65
|
oid?: number;
|
|
@@ -64,7 +67,7 @@ export declare class Table extends Table_base {
|
|
|
64
67
|
}
|
|
65
68
|
export declare abstract class DB {
|
|
66
69
|
tables: Table[];
|
|
67
|
-
protected log: (
|
|
70
|
+
protected log: (message: string) => void;
|
|
68
71
|
protected sync: boolean;
|
|
69
72
|
abstract connect(): Promise<void>;
|
|
70
73
|
abstract end(): Promise<void>;
|
|
@@ -72,7 +75,7 @@ export declare abstract class DB {
|
|
|
72
75
|
findTable(name: string): Table;
|
|
73
76
|
protected indexesEq(a: Index, b: Index): boolean;
|
|
74
77
|
syncDataBase(): Promise<void>;
|
|
75
|
-
protected syncLog(
|
|
78
|
+
protected syncLog(message: string): void;
|
|
76
79
|
abstract dropConstraints(table: Table): Promise<number[]>;
|
|
77
80
|
abstract dropFields(table: Table): Promise<void>;
|
|
78
81
|
abstract dropIndexes(table: Table, constraintIndexes: number[]): Promise<void>;
|
package/lib/db.js
CHANGED
|
@@ -1,25 +1,22 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.DB = exports.Table = exports.Attribute = exports.
|
|
4
|
-
class
|
|
5
|
-
|
|
3
|
+
exports.DB = exports.Table = exports.Attribute = exports.Type = exports.EntryBase = void 0;
|
|
4
|
+
class EntryBase {
|
|
5
|
+
construct() { }
|
|
6
|
+
postLoad() { }
|
|
7
|
+
preLoad() { }
|
|
8
|
+
preSave() { }
|
|
6
9
|
async save() {
|
|
7
10
|
return false;
|
|
8
11
|
}
|
|
9
12
|
}
|
|
10
|
-
exports.
|
|
13
|
+
exports.EntryBase = EntryBase;
|
|
11
14
|
class Type {
|
|
12
15
|
constructor(from) {
|
|
13
16
|
Object.assign(this, from);
|
|
14
17
|
}
|
|
15
18
|
}
|
|
16
19
|
exports.Type = Type;
|
|
17
|
-
class Meta extends Type {
|
|
18
|
-
constructor(from) {
|
|
19
|
-
super(from);
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
exports.Meta = Meta;
|
|
23
20
|
class Attribute extends Type {
|
|
24
21
|
constructor(from) {
|
|
25
22
|
super(from);
|
|
@@ -42,6 +39,7 @@ exports.Table = Table;
|
|
|
42
39
|
class DB {
|
|
43
40
|
constructor(log) {
|
|
44
41
|
this.tables = [];
|
|
42
|
+
this.sync = true;
|
|
45
43
|
this.log = log;
|
|
46
44
|
}
|
|
47
45
|
findTable(name) {
|
|
@@ -72,9 +70,8 @@ class DB {
|
|
|
72
70
|
await this.syncIndexes(table);
|
|
73
71
|
}
|
|
74
72
|
}
|
|
75
|
-
syncLog(
|
|
76
|
-
|
|
77
|
-
this.log(...args);
|
|
73
|
+
syncLog(message) {
|
|
74
|
+
this.log(this.sync ? message : "NOT SYNCING: " + message);
|
|
78
75
|
}
|
|
79
76
|
}
|
|
80
77
|
exports.DB = DB;
|
package/lib/minidb.js
CHANGED
|
@@ -16,14 +16,18 @@ class MiniDB extends db_1.DB {
|
|
|
16
16
|
this.body = JSON.parse((await readFile(this.file)).toString());
|
|
17
17
|
}
|
|
18
18
|
catch (e) {
|
|
19
|
-
|
|
19
|
+
const err = e;
|
|
20
|
+
if (err.code !== "ENOENT")
|
|
20
21
|
throw e;
|
|
21
22
|
}
|
|
22
23
|
}
|
|
23
24
|
async dropConstraints(table) {
|
|
24
25
|
const { constraints } = this.body.tables[table.tableName] || { constraints: { f: {}, u: {} } };
|
|
25
26
|
for (const constraint of Object.keys(constraints.f).sort()) {
|
|
26
|
-
|
|
27
|
+
const arr = table.constraints.filter(({ constraintName, type }) => constraintName === constraint && type === "f");
|
|
28
|
+
const dbOptions = arr.length ? arr[0].attribute.foreignKey.options : { onDelete: "delete", onUpdate: "delete" };
|
|
29
|
+
const inOptions = constraints.f[constraint].options;
|
|
30
|
+
if (dbOptions.onDelete !== inOptions.onDelete || dbOptions.onUpdate !== inOptions.onUpdate) {
|
|
27
31
|
this.syncLog(`'${table.tableName}': Removing foreign key: '${constraint}'`);
|
|
28
32
|
if (this.sync)
|
|
29
33
|
delete constraints.f[constraint];
|
|
@@ -31,7 +35,7 @@ class MiniDB extends db_1.DB {
|
|
|
31
35
|
}
|
|
32
36
|
for (const constraint of Object.keys(constraints.u).sort()) {
|
|
33
37
|
if (!table.constraints.filter(({ constraintName, type }) => constraintName === constraint && type === "u").length) {
|
|
34
|
-
this.syncLog(`'${table.tableName}': Removing unique constraint from field: '${constraints.u[constraint].
|
|
38
|
+
this.syncLog(`'${table.tableName}': Removing unique constraint from field: '${constraints.u[constraint].on}'`);
|
|
35
39
|
if (this.sync)
|
|
36
40
|
delete constraints.u[constraint];
|
|
37
41
|
}
|
|
@@ -70,20 +74,20 @@ class MiniDB extends db_1.DB {
|
|
|
70
74
|
async syncConstraints(table) {
|
|
71
75
|
const { constraints } = this.body.tables[table.tableName] || { constraints: { f: {}, u: {} } };
|
|
72
76
|
for (const constraint of table.constraints) {
|
|
73
|
-
const { constraintName, type } = constraint;
|
|
74
|
-
const { fieldName, foreignKey } = constraint.attribute;
|
|
77
|
+
const { attribute, constraintName, type } = constraint;
|
|
75
78
|
if (!constraints[type][constraintName]) {
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
79
|
+
if (type === "f") {
|
|
80
|
+
const { fieldName, options, tableName } = attribute.foreignKey;
|
|
81
|
+
const onDelete = options.onDelete !== "no action" ? ` on delete ${options.onDelete}` : "";
|
|
82
|
+
const onUpdate = options.onUpdate !== "no action" ? ` on update ${options.onUpdate}` : "";
|
|
83
|
+
this.syncLog(`'${table.tableName}': Adding foreign key '${constraint.constraintName}' on field: '${attribute.fieldName}' references '${tableName}(${fieldName})'${onDelete}${onUpdate}`);
|
|
84
|
+
if (this.sync)
|
|
85
|
+
constraints[type][constraintName] = { on: attribute.fieldName, options, fieldName, tableName };
|
|
86
|
+
}
|
|
87
|
+
else {
|
|
88
|
+
this.syncLog(`'${table.tableName}': Adding unique constraint on field: '${attribute.fieldName}'`);
|
|
89
|
+
if (this.sync)
|
|
90
|
+
constraints[type][constraintName] = { on: attribute.fieldName };
|
|
87
91
|
}
|
|
88
92
|
}
|
|
89
93
|
}
|
package/package.json
CHANGED
|
@@ -5,16 +5,17 @@
|
|
|
5
5
|
"description": "The ORM which never needs to migrate",
|
|
6
6
|
"devDependencies": {
|
|
7
7
|
"@types/mocha": "9.0.0",
|
|
8
|
-
"@types/node": "
|
|
8
|
+
"@types/node": "17.0.5",
|
|
9
9
|
"@types/yamljs": "0.2.31",
|
|
10
|
-
"@typescript-eslint/eslint-plugin": "5.
|
|
11
|
-
"@typescript-eslint/parser": "5.
|
|
12
|
-
"eslint": "8.
|
|
10
|
+
"@typescript-eslint/eslint-plugin": "5.8.1",
|
|
11
|
+
"@typescript-eslint/parser": "5.8.1",
|
|
12
|
+
"eslint": "8.5.0",
|
|
13
13
|
"mocha": "9.1.3",
|
|
14
14
|
"nyc": "15.1.0",
|
|
15
|
-
"prettier": "2.5.
|
|
15
|
+
"prettier": "2.5.1",
|
|
16
16
|
"ts-node": "10.4.0",
|
|
17
|
-
"
|
|
17
|
+
"tsd": "0.19.0",
|
|
18
|
+
"typescript": "4.5.4",
|
|
18
19
|
"yamljs": "0.3.0"
|
|
19
20
|
},
|
|
20
21
|
"engines": {
|
|
@@ -55,6 +56,23 @@
|
|
|
55
56
|
"tsc": "tsc --declaration",
|
|
56
57
|
"version": "node -r ts-node/register utils.ts version"
|
|
57
58
|
},
|
|
59
|
+
"tsd": {
|
|
60
|
+
"compilerOptions": {
|
|
61
|
+
"alwaysStrict": true,
|
|
62
|
+
"declaration": true,
|
|
63
|
+
"esModuleInterop": true,
|
|
64
|
+
"module": "commonjs",
|
|
65
|
+
"noImplicitAny": true,
|
|
66
|
+
"noImplicitReturns": true,
|
|
67
|
+
"noImplicitThis": true,
|
|
68
|
+
"strict": true,
|
|
69
|
+
"strictBindCallApply": true,
|
|
70
|
+
"strictFunctionTypes": true,
|
|
71
|
+
"strictNullChecks": true,
|
|
72
|
+
"strictPropertyInitialization": true,
|
|
73
|
+
"target": "es2017"
|
|
74
|
+
}
|
|
75
|
+
},
|
|
58
76
|
"types": "index.d.ts",
|
|
59
|
-
"version": "0.0.
|
|
77
|
+
"version": "0.0.21"
|
|
60
78
|
}
|
package/lib/log.d.ts
DELETED
package/lib/log.js
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.createLogger = void 0;
|
|
4
|
-
const console_1 = require("console");
|
|
5
|
-
const stream_1 = require("stream");
|
|
6
|
-
class Logger extends stream_1.Writable {
|
|
7
|
-
constructor(log) {
|
|
8
|
-
super();
|
|
9
|
-
this.log = log;
|
|
10
|
-
}
|
|
11
|
-
_write(chunk, encoding, callback) {
|
|
12
|
-
this.log(chunk.toString());
|
|
13
|
-
callback();
|
|
14
|
-
}
|
|
15
|
-
}
|
|
16
|
-
function createLogger(log) {
|
|
17
|
-
// eslint-disable-next-line no-console
|
|
18
|
-
return log ? new console_1.Console(new Logger(log)).log : log === null ? () => { } : console.log;
|
|
19
|
-
}
|
|
20
|
-
exports.createLogger = createLogger;
|
package/lib/log.ts
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import { Console } from "console";
|
|
2
|
-
import { Writable } from "stream";
|
|
3
|
-
|
|
4
|
-
class Logger extends Writable {
|
|
5
|
-
private log: (message: string) => void;
|
|
6
|
-
|
|
7
|
-
constructor(log: (message: string) => void) {
|
|
8
|
-
super();
|
|
9
|
-
|
|
10
|
-
this.log = log;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
_write(chunk: Buffer, encoding: string, callback: () => void) {
|
|
14
|
-
this.log(chunk.toString());
|
|
15
|
-
callback();
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export function createLogger(log: ((message: string) => void) | null | undefined) {
|
|
20
|
-
// eslint-disable-next-line no-console
|
|
21
|
-
return log ? new Console(new Logger(log)).log : log === null ? () => {} : console.log;
|
|
22
|
-
}
|
package/requirements.txt
DELETED