sedentary 0.0.14 → 0.0.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -4
- package/index.d.ts +20 -18
- package/index.js +169 -71
- package/lib/db.d.ts +24 -11
- package/lib/db.js +13 -19
- package/lib/minidb.js +76 -53
- package/package.json +10 -7
- package/requirements.txt +2 -0
- package/sedentary-pg/LICENSE +0 -21
- package/sedentary-pg/README.md +0 -32
- package/sedentary-pg/lib/pgdb.ts +0 -341
- package/sedentary-pg/package-lock.json +0 -6765
- package/sedentary-pg/package.json +0 -63
package/README.md
CHANGED
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
[![Stars][stars-badge]][github-url]
|
|
10
10
|
|
|
11
11
|
[![Types][types-badge]][npm-url]
|
|
12
|
+
[![Documentation][doc-badge]][doc-url]
|
|
12
13
|
[![Dependents][deps-badge]][npm-url]
|
|
13
14
|
[![Donate][donate-badge]][donate-url]
|
|
14
15
|
|
|
@@ -16,6 +17,8 @@
|
|
|
16
17
|
[code-url]: https://codeclimate.com/github/iccicci/sedentary
|
|
17
18
|
[cover-badge]: https://codeclimate.com/github/iccicci/sedentary/badges/coverage.svg
|
|
18
19
|
[deps-badge]: https://badgen.net/npm/dependents/sedentary?icon=npm&cache=300
|
|
20
|
+
[doc-badge]: https://readthedocs.org/projects/sedentary/badge/?version=latest
|
|
21
|
+
[doc-url]: https://sedentary.readthedocs.io/
|
|
19
22
|
[donate-badge]: https://badgen.net/badge/donate/bitcoin?icon=bitcoin&cache=300
|
|
20
23
|
[donate-url]: https://blockchain.info/address/1Md9WFAHrXTb3yPBwQWmUfv2RmzrtbHioB
|
|
21
24
|
[github-url]: https://github.com/iccicci/sedentary
|
|
@@ -115,10 +118,6 @@ To work with the package under Windows, be sure to configure `bash.exe` as your
|
|
|
115
118
|
|
|
116
119
|
Do not hesitate to report any bug or inconsistency [@github](https://github.com/iccicci/sedentary/issues).
|
|
117
120
|
|
|
118
|
-
# ChangeLog
|
|
119
|
-
|
|
120
|
-
[ChangeLog](https://github.com/iccicci/sedentary/blob/master/CHANGELOG.md)
|
|
121
|
-
|
|
122
121
|
# Donating
|
|
123
122
|
|
|
124
123
|
If you find useful this package, please consider the opportunity to donate some satoshis to this bitcoin address:
|
package/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { DB, Entry, Meta, Natural, Type } from "./lib/db";
|
|
2
|
-
export { Entry, Natural, Type } from "./lib/db";
|
|
1
|
+
import { DB, Entry, ForeignKeyOptions, Meta, Natural, Type } from "./lib/db";
|
|
2
|
+
export { Entry, 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;
|
|
@@ -30,10 +30,11 @@ export interface IndexOptions {
|
|
|
30
30
|
unique?: boolean;
|
|
31
31
|
}
|
|
32
32
|
export declare type IndexDefinition = IndexAttributes | IndexOptions;
|
|
33
|
-
export declare type
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
33
|
+
export declare type IndexesDefinition = {
|
|
34
|
+
[key: string]: IndexDefinition;
|
|
35
|
+
};
|
|
36
|
+
declare type BaseModelOptions<T> = {
|
|
37
|
+
indexes?: IndexesDefinition;
|
|
37
38
|
init?: (this: T) => void;
|
|
38
39
|
sync?: boolean;
|
|
39
40
|
tableName?: string;
|
|
@@ -60,18 +61,19 @@ declare type Ancestor<A, N extends Natural, T extends Entry> = (new () => T) & {
|
|
|
60
61
|
} & {
|
|
61
62
|
load: (boh: boolean) => Promise<T[]>;
|
|
62
63
|
} & Meta<N, T>;
|
|
63
|
-
export interface
|
|
64
|
+
export interface SedentaryOptions {
|
|
64
65
|
log?: ((message: string) => void) | null;
|
|
66
|
+
serverless?: boolean;
|
|
65
67
|
sync?: boolean;
|
|
66
68
|
}
|
|
67
69
|
export declare class Sedentary {
|
|
68
70
|
protected db: DB;
|
|
69
71
|
protected log: (...data: unknown[]) => void;
|
|
70
|
-
|
|
72
|
+
protected sync: boolean;
|
|
71
73
|
private models;
|
|
72
|
-
constructor(filename: string, options?:
|
|
74
|
+
constructor(filename: string, options?: SedentaryOptions);
|
|
73
75
|
DATETIME(): Type<Date, unknown>;
|
|
74
|
-
FKEY<N extends Natural, E extends Entry>(attribute: Type<N, E
|
|
76
|
+
FKEY<N extends Natural, E extends Entry>(attribute: Type<N, E>, options?: ForeignKeyOptions): Type<N, E>;
|
|
75
77
|
INT(size?: number): Type<number, unknown>;
|
|
76
78
|
INT8(): Type<string, unknown>;
|
|
77
79
|
VARCHAR(size?: number): Type<string, unknown>;
|
|
@@ -79,37 +81,37 @@ export declare class Sedentary {
|
|
|
79
81
|
end(): Promise<void>;
|
|
80
82
|
model<A extends AttributesDefinition, M extends Methods<T>, T extends Entry & {
|
|
81
83
|
id?: string;
|
|
82
|
-
} & ModelWithMetods<A, M>>(
|
|
84
|
+
} & ModelWithMetods<A, M>>(modelName: string, attributes: A, options?: BaseModelOptions<T> & {
|
|
83
85
|
int8id: true;
|
|
84
86
|
methods: M;
|
|
85
87
|
}): Ancestor<A, string, T>;
|
|
86
|
-
model<A extends AttributesDefinition, K extends keyof A, M extends Methods<T>, N extends K extends keyof A ? Native<A[K]> : never, T extends Entry & ModelWithMetods<A, M>>(
|
|
88
|
+
model<A extends AttributesDefinition, K extends keyof A, M extends Methods<T>, N extends K extends keyof A ? Native<A[K]> : never, T extends Entry & ModelWithMetods<A, M>>(modelName: string, attributes: A, options?: BaseModelOptions<T> & {
|
|
87
89
|
methods: M;
|
|
88
90
|
primaryKey: K;
|
|
89
91
|
}): Ancestor<A, N, T>;
|
|
90
|
-
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>>(
|
|
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> & {
|
|
91
93
|
methods: M;
|
|
92
94
|
parent: P;
|
|
93
95
|
}): Ancestor<A, N, T>;
|
|
94
96
|
model<A extends AttributesDefinition, M extends Methods<T>, T extends Entry & {
|
|
95
97
|
id?: number;
|
|
96
|
-
} & ModelWithMetods<A, M>>(
|
|
98
|
+
} & ModelWithMetods<A, M>>(modelName: string, attributes: A, options?: BaseModelOptions<T> & {
|
|
97
99
|
methods: M;
|
|
98
100
|
}): Ancestor<A, number, T>;
|
|
99
101
|
model<A extends AttributesDefinition, T extends Entry & {
|
|
100
102
|
id?: string;
|
|
101
|
-
} & Model<A>>(
|
|
103
|
+
} & Model<A>>(modelName: string, attributes: A, options?: BaseModelOptions<T> & {
|
|
102
104
|
int8id: true;
|
|
103
105
|
}): Ancestor<A, string, T>;
|
|
104
|
-
model<A extends AttributesDefinition, K extends keyof A, N extends K extends keyof A ? Native<A[K]> : never, T extends Entry & Model<A>>(
|
|
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> & {
|
|
105
107
|
primaryKey: K;
|
|
106
108
|
}): Ancestor<A, N, T>;
|
|
107
|
-
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>>(
|
|
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> & {
|
|
108
110
|
parent: P;
|
|
109
111
|
}): Ancestor<A, N, T>;
|
|
110
112
|
model<A extends AttributesDefinition, T extends Entry & {
|
|
111
113
|
id?: number;
|
|
112
|
-
} & Model<A>>(
|
|
114
|
+
} & Model<A>>(modelName: string, attributes: A, options?: BaseModelOptions<T>): Ancestor<A, number, T>;
|
|
113
115
|
checkSize(size: number, message: string): number;
|
|
114
116
|
}
|
|
115
117
|
export declare const Package: typeof Sedentary;
|
package/index.js
CHANGED
|
@@ -25,19 +25,21 @@ class Sedentary {
|
|
|
25
25
|
for (const k in options)
|
|
26
26
|
if (!["log", "sync"].includes(k))
|
|
27
27
|
throw new Error(`new Sedentary: 'options' argument: Unknown '${k}' option`);
|
|
28
|
-
|
|
29
|
-
if (
|
|
30
|
-
|
|
28
|
+
const { log, sync } = Object.assign({ sync: true }, options);
|
|
29
|
+
if (log !== null && log !== undefined && !(log instanceof Function))
|
|
30
|
+
throw new Error("new Sedentary: 'log' option: Wrong type, expected 'null' or 'Function'");
|
|
31
|
+
if (typeof sync !== "boolean")
|
|
32
|
+
throw new Error("new Sedentary: 'sync' option: Wrong type, expected 'boolean'");
|
|
33
|
+
this.log = (0, log_1.createLogger)(log);
|
|
31
34
|
this.db = new minidb_1.MiniDB(filename, this.log);
|
|
35
|
+
this.sync = sync;
|
|
32
36
|
}
|
|
33
37
|
DATETIME() {
|
|
34
38
|
return new db_1.Type({ base: Date, type: "DATETIME" });
|
|
35
39
|
}
|
|
36
|
-
FKEY(attribute) {
|
|
37
|
-
const { attributeName, base, fieldName, size, tableName, type
|
|
38
|
-
|
|
39
|
-
throw new Error(`Sedentary.FKEY: '${tableName}' table: '${attributeName}' attribute: is not unique: can't be used as FKEY target`);
|
|
40
|
-
return new db_1.Type({ base, foreignKey: { attributeName, fieldName, tableName }, size, type });
|
|
40
|
+
FKEY(attribute, options) {
|
|
41
|
+
const { attributeName, base, fieldName, size, tableName, type } = attribute;
|
|
42
|
+
return new db_1.Type({ base, foreignKey: { attributeName, fieldName, options, tableName }, size, type });
|
|
41
43
|
}
|
|
42
44
|
INT(size) {
|
|
43
45
|
const message = "Sedentary.INT: 'size' argument: Wrong value, expected 2 or 4";
|
|
@@ -59,7 +61,7 @@ class Sedentary {
|
|
|
59
61
|
this.log("Connecting...");
|
|
60
62
|
await this.db.connect();
|
|
61
63
|
this.log("Connected, syncing...");
|
|
62
|
-
await this.db.
|
|
64
|
+
await this.db.syncDataBase();
|
|
63
65
|
this.log("Synced");
|
|
64
66
|
}
|
|
65
67
|
catch (e) {
|
|
@@ -72,111 +74,131 @@ class Sedentary {
|
|
|
72
74
|
await this.db.end();
|
|
73
75
|
this.log("Connection closed");
|
|
74
76
|
}
|
|
75
|
-
model(
|
|
76
|
-
if (typeof
|
|
77
|
+
model(modelName, attributes, options) {
|
|
78
|
+
if (typeof modelName !== "string")
|
|
77
79
|
throw new Error("Sedentary.model: 'name' argument: Wrong type, expected 'string'");
|
|
78
|
-
if (this.models[
|
|
79
|
-
throw new Error(`Sedentary.model: '${
|
|
80
|
+
if (this.models[modelName])
|
|
81
|
+
throw new Error(`Sedentary.model: '${modelName}' model: Model already defined`);
|
|
80
82
|
if (!attributes)
|
|
81
83
|
attributes = {};
|
|
82
84
|
if (!(attributes instanceof Object))
|
|
83
|
-
throw new Error(`Sedentary.model: '${
|
|
85
|
+
throw new Error(`Sedentary.model: '${modelName}' model: 'attributes' argument: Wrong type, expected 'Object'`);
|
|
84
86
|
if (!options)
|
|
85
87
|
options = {};
|
|
86
88
|
if (!(options instanceof Object))
|
|
87
|
-
throw new Error(`Sedentary.model: '${
|
|
89
|
+
throw new Error(`Sedentary.model: '${modelName}' model: 'options' argument: Wrong type, expected 'Object'`);
|
|
88
90
|
for (const k in options)
|
|
89
91
|
if (!allowedOption.includes(k))
|
|
90
|
-
throw new Error(`Sedentary.model: '${
|
|
92
|
+
throw new Error(`Sedentary.model: '${modelName}' model: 'options' argument: Unknown '${k}' option`);
|
|
91
93
|
if (options.int8id && options.parent)
|
|
92
|
-
throw new Error(`Sedentary.model: '${
|
|
94
|
+
throw new Error(`Sedentary.model: '${modelName}' model: 'int8id' and 'parent' options conflict each other`);
|
|
93
95
|
if (options.int8id && options.primaryKey)
|
|
94
|
-
throw new Error(`Sedentary.model: '${
|
|
96
|
+
throw new Error(`Sedentary.model: '${modelName}' model: 'int8id' and 'primaryKey' options conflict each other`);
|
|
95
97
|
if (options.parent && options.primaryKey)
|
|
96
|
-
throw new Error(`Sedentary.model: '${
|
|
97
|
-
|
|
98
|
+
throw new Error(`Sedentary.model: '${modelName}' model: 'parent' and 'primaryKey' options conflict each other`);
|
|
99
|
+
let autoIncrement = true;
|
|
100
|
+
const { indexes, int8id, parent, primaryKey, sync, tableName } = Object.assign({ sync: this.sync, tableName: modelName }, options);
|
|
98
101
|
let { methods } = options;
|
|
99
102
|
let aarray = int8id
|
|
100
|
-
? [new db_1.Attribute(Object.assign(Object.assign({}, this.INT8()), { attributeName: "id", fieldName: "id", notNull: true, tableName, unique: true }))]
|
|
101
|
-
: [new db_1.Attribute(Object.assign(Object.assign({}, this.INT(4)), { attributeName: "id", fieldName: "id", notNull: true, tableName, unique: true }))];
|
|
103
|
+
? [new db_1.Attribute(Object.assign(Object.assign({}, this.INT8()), { attributeName: "id", fieldName: "id", modelName, notNull: true, tableName, unique: true }))]
|
|
104
|
+
: [new db_1.Attribute(Object.assign(Object.assign({}, this.INT(4)), { attributeName: "id", fieldName: "id", modelName, notNull: true, tableName, unique: true }))];
|
|
102
105
|
let constraints = [{ attribute: aarray[0], constraintName: `${tableName}_id_unique`, type: "u" }];
|
|
103
106
|
const iarray = [];
|
|
104
107
|
const pk = aarray[0];
|
|
105
108
|
if (methods && !(methods instanceof Object))
|
|
106
|
-
throw new Error(`Sedentary.model: '${
|
|
109
|
+
throw new Error(`Sedentary.model: '${modelName}' model: 'methods' option: Wrong type, expected 'Object'`);
|
|
110
|
+
const originalMethods = methods;
|
|
107
111
|
if (parent) {
|
|
108
|
-
methods = (methods ? Object.assign(Object.assign({}, (parent.methods || {})), methods) : parent.methods);
|
|
109
112
|
try {
|
|
110
113
|
if (!parent.isModel())
|
|
111
114
|
throw new Error();
|
|
112
115
|
}
|
|
113
116
|
catch (e) {
|
|
114
|
-
throw new Error(`Sedentary.model: '${
|
|
117
|
+
throw new Error(`Sedentary.model: '${modelName}' model: 'parent' option: Wrong type, expected 'Model'`);
|
|
115
118
|
}
|
|
119
|
+
methods = (methods ? Object.assign(Object.assign({}, (parent.methods || {})), methods) : parent.methods);
|
|
116
120
|
}
|
|
117
121
|
if (primaryKey && typeof primaryKey !== "string")
|
|
118
|
-
throw new Error(`Sedentary.model: '${
|
|
122
|
+
throw new Error(`Sedentary.model: '${modelName}' model: 'primaryKey' option: Wrong type, expected 'string'`);
|
|
119
123
|
if (primaryKey && !Object.keys(attributes).includes(primaryKey))
|
|
120
|
-
throw new Error(`Sedentary.model: '${
|
|
124
|
+
throw new Error(`Sedentary.model: '${modelName}' model: 'primaryKey' option: Attribute '${primaryKey}' does not exists`);
|
|
121
125
|
if (parent || primaryKey) {
|
|
126
|
+
autoIncrement = false;
|
|
122
127
|
aarray = [];
|
|
123
128
|
constraints = [];
|
|
124
129
|
}
|
|
125
|
-
for (const attributeName
|
|
130
|
+
for (const attributeName of Object.keys(attributes).sort()) {
|
|
126
131
|
if (reservedNames.includes(attributeName))
|
|
127
|
-
throw new Error(`Sedentary.model: '${
|
|
132
|
+
throw new Error(`Sedentary.model: '${modelName}' model: '${attributeName}' attribute: Reserved name`);
|
|
128
133
|
const call = (defaultValue, fieldName, notNull, unique, func, message1, message2) => {
|
|
129
134
|
if (func === this.FKEY)
|
|
130
135
|
throw new Error(`${message1} 'this.FKEY' can't be used directly`);
|
|
131
136
|
if (func !== this.DATETIME && func !== this.INT && func !== this.INT8 && func !== this.VARCHAR)
|
|
132
137
|
throw new Error(`${message1} ${message2}`);
|
|
133
|
-
return new db_1.Attribute(Object.assign({ attributeName, defaultValue, fieldName, notNull, tableName, unique }, func()));
|
|
138
|
+
return new db_1.Attribute(Object.assign({ attributeName, defaultValue, fieldName, modelName, notNull, tableName, unique }, func()));
|
|
134
139
|
};
|
|
135
140
|
const attributeDefinition = attributes[attributeName];
|
|
136
141
|
let { base, defaultValue, fieldName, foreignKey, notNull, size, type, unique } = (() => {
|
|
137
142
|
const ret = (() => {
|
|
138
143
|
if (attributeDefinition instanceof db_1.Type)
|
|
139
|
-
return new db_1.Attribute(Object.assign({ attributeName, fieldName: attributeName, notNull: false, tableName }, attributeDefinition));
|
|
144
|
+
return new db_1.Attribute(Object.assign({ attributeName, fieldName: attributeName, modelName, notNull: false, tableName }, attributeDefinition));
|
|
140
145
|
if (attributeDefinition instanceof Function)
|
|
141
|
-
return call(undefined, attributeName, false, false, attributeDefinition, `Sedentary.model: '${
|
|
146
|
+
return call(undefined, attributeName, false, false, attributeDefinition, `Sedentary.model: '${modelName}' model: '${attributeName}' attribute:`, "Wrong type, expected 'Attribute'");
|
|
142
147
|
if (!(attributeDefinition instanceof Object))
|
|
143
|
-
throw new Error(`Sedentary.model: '${
|
|
148
|
+
throw new Error(`Sedentary.model: '${modelName}' model: '${attributeName}' attribute: Wrong attribute type, expected 'Attribute'`);
|
|
144
149
|
const attributeDefaults = Object.assign({ defaultValue: undefined, fieldName: attributeName, notNull: false, unique: false }, attributeDefinition);
|
|
145
150
|
const { defaultValue, fieldName, notNull, unique, type } = attributeDefaults;
|
|
146
151
|
if (defaultValue === null)
|
|
147
|
-
throw new Error(`Sedentary.model: '${
|
|
152
|
+
throw new Error(`Sedentary.model: '${modelName}' model: '${attributeName}' attribute: 'defaultValue' option: Does 'null' default value really makes sense?`);
|
|
148
153
|
if (typeof fieldName !== "string")
|
|
149
|
-
throw new Error(`Sedentary.model: '${
|
|
154
|
+
throw new Error(`Sedentary.model: '${modelName}' model: '${attributeName}' attribute: 'fieldName' option: Wrong type, expected 'string'`);
|
|
150
155
|
if (typeof notNull !== "boolean")
|
|
151
|
-
throw new Error(`Sedentary.model: '${
|
|
156
|
+
throw new Error(`Sedentary.model: '${modelName}' model: '${attributeName}' attribute: 'notNull' option: Wrong type, expected 'boolean'`);
|
|
152
157
|
if (typeof unique !== "boolean")
|
|
153
|
-
throw new Error(`Sedentary.model: '${
|
|
158
|
+
throw new Error(`Sedentary.model: '${modelName}' model: '${attributeName}' attribute: 'unique' option: Wrong type, expected 'boolean'`);
|
|
154
159
|
if (type === undefined)
|
|
155
|
-
throw new Error(`Sedentary.model: '${
|
|
160
|
+
throw new Error(`Sedentary.model: '${modelName}' model: '${attributeName}' attribute: Missing 'type' option`);
|
|
156
161
|
if (type instanceof db_1.Type)
|
|
157
|
-
return new db_1.Attribute(Object.assign({ attributeName, defaultValue, fieldName, notNull, tableName, unique }, type));
|
|
162
|
+
return new db_1.Attribute(Object.assign({ attributeName, defaultValue, fieldName, modelName, notNull, tableName, unique }, type));
|
|
158
163
|
if (type instanceof Function)
|
|
159
|
-
return call(defaultValue, fieldName, notNull, unique, type, `Sedentary.model: '${
|
|
160
|
-
throw new Error(`Sedentary.model: '${
|
|
164
|
+
return call(defaultValue, fieldName, notNull, unique, type, `Sedentary.model: '${modelName}' model: '${attributeName}' attribute: 'type' option:`, "Wrong type, expected 'Type'");
|
|
165
|
+
throw new Error(`Sedentary.model: '${modelName}' model: '${attributeName}' attribute: 'type' option: Wrong type, expected 'Type'`);
|
|
161
166
|
})();
|
|
162
167
|
const { base, defaultValue } = ret;
|
|
163
168
|
if (defaultValue !== undefined) {
|
|
164
169
|
if (base === Date && !(defaultValue instanceof Date))
|
|
165
|
-
throw new Error(`Sedentary.model: '${
|
|
170
|
+
throw new Error(`Sedentary.model: '${modelName}' model: '${attributeName}' attribute: 'defaultValue' option: Wrong type, expected 'Date'`);
|
|
166
171
|
if (base === Number && typeof defaultValue !== "number")
|
|
167
|
-
throw new Error(`Sedentary.model: '${
|
|
172
|
+
throw new Error(`Sedentary.model: '${modelName}' model: '${attributeName}' attribute: 'defaultValue' option: Wrong type, expected 'number'`);
|
|
168
173
|
if (base === String && typeof defaultValue !== "string")
|
|
169
|
-
throw new Error(`Sedentary.model: '${
|
|
174
|
+
throw new Error(`Sedentary.model: '${modelName}' model: '${attributeName}' attribute: 'defaultValue' option: Wrong type, expected 'string'`);
|
|
170
175
|
}
|
|
171
176
|
return ret;
|
|
172
177
|
})();
|
|
178
|
+
if (foreignKey) {
|
|
179
|
+
if (!foreignKey.options)
|
|
180
|
+
foreignKey.options = {};
|
|
181
|
+
if (!(foreignKey.options instanceof Object))
|
|
182
|
+
throw new Error(`Sedentary.FKEY: '${modelName}' model: '${attributeName}' attribute: Wrong options type, expected 'Object'`);
|
|
183
|
+
for (const k in foreignKey.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 = foreignKey.options[onChange];
|
|
189
|
+
if (!action)
|
|
190
|
+
action = foreignKey.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
|
+
}
|
|
173
195
|
if (primaryKey === attributeName) {
|
|
174
196
|
notNull = true;
|
|
175
197
|
unique = true;
|
|
176
198
|
}
|
|
177
199
|
if (defaultValue)
|
|
178
200
|
notNull = true;
|
|
179
|
-
const attribute = new db_1.Attribute({ attributeName, base, defaultValue, fieldName, foreignKey, notNull, size, tableName, type, unique });
|
|
201
|
+
const attribute = new db_1.Attribute({ attributeName, base, defaultValue, fieldName, foreignKey, modelName, notNull, size, tableName, type, unique });
|
|
180
202
|
aarray.push(attribute);
|
|
181
203
|
if (foreignKey)
|
|
182
204
|
constraints.push({ attribute, constraintName: `fkey_${fieldName}_${foreignKey.tableName}_${foreignKey.fieldName}`, type: "f" });
|
|
@@ -186,16 +208,16 @@ class Sedentary {
|
|
|
186
208
|
if (indexes) {
|
|
187
209
|
const flds = attributes;
|
|
188
210
|
if (!(indexes instanceof Object))
|
|
189
|
-
throw new Error(`Sedentary.model: '${
|
|
211
|
+
throw new Error(`Sedentary.model: '${modelName}' model: 'indexes' option: Wrong type, expected 'Object'`);
|
|
190
212
|
for (const indexName in indexes) {
|
|
191
213
|
if (aarray.filter(({ fieldName, unique }) => unique && `${tableName}_${fieldName}_unique` === indexName).length !== 0)
|
|
192
|
-
throw new Error(`Sedentary.model: '${
|
|
214
|
+
throw new Error(`Sedentary.model: '${modelName}' model: '${indexName}' index: index name already inferred by the unique constraint on an attribute`);
|
|
193
215
|
const idx = indexes[indexName];
|
|
194
216
|
const checkAttribute = (attribute, l) => {
|
|
195
217
|
if (typeof attribute !== "string")
|
|
196
|
-
throw new Error(`Sedentary.model: '${
|
|
218
|
+
throw new Error(`Sedentary.model: '${modelName}' model: '${indexName}' index: #${l + 1} attribute: Wrong type, expected 'string'`);
|
|
197
219
|
if (!(attribute in flds))
|
|
198
|
-
throw new Error(`Sedentary.model: '${
|
|
220
|
+
throw new Error(`Sedentary.model: '${modelName}' model: '${indexName}' index: #${l + 1} attribute: Unknown attribute '${attribute}'`);
|
|
199
221
|
};
|
|
200
222
|
let attributes;
|
|
201
223
|
let type = "btree";
|
|
@@ -211,10 +233,10 @@ class Sedentary {
|
|
|
211
233
|
else if (idx instanceof Object) {
|
|
212
234
|
for (const k in idx)
|
|
213
235
|
if (!["attributes", "type", "unique"].includes(k))
|
|
214
|
-
throw new Error(`Sedentary.model: '${
|
|
236
|
+
throw new Error(`Sedentary.model: '${modelName}' model: '${indexName}' index: Unknown index option '${k}'`);
|
|
215
237
|
({ attributes, type, unique } = Object.assign({ type: "btree", unique: false }, idx));
|
|
216
238
|
if (!attributes)
|
|
217
|
-
throw new Error(`Sedentary.model: '${
|
|
239
|
+
throw new Error(`Sedentary.model: '${modelName}' model: '${indexName}' index: Missing 'attributes' option`);
|
|
218
240
|
if (attributes instanceof Array)
|
|
219
241
|
attributes.forEach(checkAttribute);
|
|
220
242
|
else if (typeof attributes === "string") {
|
|
@@ -222,21 +244,21 @@ class Sedentary {
|
|
|
222
244
|
attributes = [attributes];
|
|
223
245
|
}
|
|
224
246
|
else
|
|
225
|
-
throw new Error(`Sedentary.model: '${
|
|
247
|
+
throw new Error(`Sedentary.model: '${modelName}' model: '${indexName}' index: 'attributes' option: Wrong type, expected 'FieldNames'`);
|
|
226
248
|
if (typeof type !== "string")
|
|
227
|
-
throw new Error(`Sedentary.model: '${
|
|
249
|
+
throw new Error(`Sedentary.model: '${modelName}' model: '${indexName}' index: 'type' option: Wrong type, expected 'string'`);
|
|
228
250
|
if (!["btree", "hash"].includes(type))
|
|
229
|
-
throw new Error(`Sedentary.model: '${
|
|
251
|
+
throw new Error(`Sedentary.model: '${modelName}' model: '${indexName}' index: 'type' option: Wrong value, expected 'btree' or 'hash'`);
|
|
230
252
|
if (typeof unique !== "boolean")
|
|
231
|
-
throw new Error(`Sedentary.model: '${
|
|
253
|
+
throw new Error(`Sedentary.model: '${modelName}' model: '${indexName}' index: 'unique' option: Wrong type, expected 'boolean'`);
|
|
232
254
|
}
|
|
233
255
|
else
|
|
234
|
-
throw new Error(`Sedentary.model: '${
|
|
256
|
+
throw new Error(`Sedentary.model: '${modelName}' model: '${indexName}' index: Wrong type, expected 'Object'`);
|
|
235
257
|
iarray.push({ fields: attributes, indexName, type, unique });
|
|
236
258
|
}
|
|
237
259
|
}
|
|
238
|
-
this.db.
|
|
239
|
-
this.models[
|
|
260
|
+
this.db.tables.push(new db_1.Table({ autoIncrement, constraints, attributes: aarray, indexes: iarray, parent, sync, tableName }));
|
|
261
|
+
this.models[modelName] = true;
|
|
240
262
|
const init = parent
|
|
241
263
|
? options.init
|
|
242
264
|
? function () {
|
|
@@ -245,9 +267,6 @@ class Sedentary {
|
|
|
245
267
|
}
|
|
246
268
|
: parent.init
|
|
247
269
|
: options.init;
|
|
248
|
-
const flds = {};
|
|
249
|
-
for (const key in attributes)
|
|
250
|
-
flds[key] = null;
|
|
251
270
|
class Class {
|
|
252
271
|
constructor() {
|
|
253
272
|
if (init)
|
|
@@ -256,7 +275,7 @@ class Sedentary {
|
|
|
256
275
|
save() {
|
|
257
276
|
return new Promise((resolve, reject) => {
|
|
258
277
|
const save = () => reject(new Error("eh no"));
|
|
259
|
-
Object.defineProperty(save, "name", { value:
|
|
278
|
+
Object.defineProperty(save, "name", { value: modelName + ".save" });
|
|
260
279
|
setTimeout(save, 10);
|
|
261
280
|
});
|
|
262
281
|
}
|
|
@@ -266,18 +285,70 @@ class Sedentary {
|
|
|
266
285
|
return resolve([new Class()]);
|
|
267
286
|
reject(new Error("boh"));
|
|
268
287
|
}, 10));
|
|
269
|
-
Object.defineProperty(load, "name", { value:
|
|
270
|
-
const
|
|
288
|
+
Object.defineProperty(load, "name", { value: modelName + ".load" });
|
|
289
|
+
const metaAttributes = aarray.reduce((ret, curr) => {
|
|
290
|
+
ret[curr.attributeName] = curr;
|
|
291
|
+
return ret;
|
|
292
|
+
}, {});
|
|
293
|
+
const metaForeignKeys = aarray
|
|
294
|
+
.filter(_ => _.foreignKey)
|
|
295
|
+
.reduce((ret, curr) => {
|
|
296
|
+
ret[curr.attributeName] = curr;
|
|
297
|
+
return ret;
|
|
298
|
+
}, {});
|
|
299
|
+
const meta = new db_1.Meta({ base: Number, attributes: metaAttributes, foreignKeys: metaForeignKeys, modelName, parent: parent, type: "meta", tableName, primaryKey, init, methods });
|
|
300
|
+
for (const foreignKey in metaForeignKeys) {
|
|
301
|
+
if (foreignKey + "Load" in metaAttributes)
|
|
302
|
+
throw new Error(`Sedentary.model: '${modelName}' model: '${foreignKey}' attribute: '${foreignKey}Load' inferred methods conflicts with an attribute`);
|
|
303
|
+
if (originalMethods && foreignKey + "Load" in originalMethods)
|
|
304
|
+
throw new Error(`Sedentary.model: '${modelName}' model: '${foreignKey}' attribute: '${foreignKey}Load' inferred methods conflicts with a method`);
|
|
305
|
+
}
|
|
306
|
+
if (originalMethods)
|
|
307
|
+
for (const method in originalMethods)
|
|
308
|
+
if (method in metaAttributes)
|
|
309
|
+
throw new Error(`Sedentary.model: '${modelName}' model: '${method}' method: conflicts with an attribute`);
|
|
310
|
+
const checkParent = (parent) => {
|
|
311
|
+
if (!parent)
|
|
312
|
+
return;
|
|
313
|
+
for (const attribute in metaAttributes) {
|
|
314
|
+
if (attribute in parent.attributes)
|
|
315
|
+
throw new Error(`Sedentary.model: '${modelName}' model: '${attribute}' attribute: conflicts with an attribute of '${parent.modelName}' model`);
|
|
316
|
+
if (parent.methods && attribute in parent.methods)
|
|
317
|
+
throw new Error(`Sedentary.model: '${modelName}' model: '${attribute}' attribute: conflicts with a method of '${parent.modelName}' model`);
|
|
318
|
+
for (const foreignKey in parent.foreignKeys)
|
|
319
|
+
if (attribute === foreignKey + "Load")
|
|
320
|
+
throw new Error(`Sedentary.model: '${modelName}' model: '${attribute}' attribute: conflicts with an inferred methods of '${parent.modelName}' model`);
|
|
321
|
+
}
|
|
322
|
+
for (const foreignKey in metaForeignKeys) {
|
|
323
|
+
if (foreignKey + "Load" in parent.attributes)
|
|
324
|
+
throw new Error(`Sedentary.model: '${modelName}' model: '${foreignKey}' attribute: '${foreignKey}Load' inferred methods conflicts with an attribute of '${parent.modelName}' model`);
|
|
325
|
+
if (parent.methods && foreignKey + "Load" in parent.methods)
|
|
326
|
+
throw new Error(`Sedentary.model: '${modelName}' model: '${foreignKey}' attribute: '${foreignKey}Load' inferred methods conflicts with a method of '${parent.modelName}' model`);
|
|
327
|
+
}
|
|
328
|
+
if (originalMethods) {
|
|
329
|
+
for (const method in originalMethods) {
|
|
330
|
+
if (method in parent.attributes)
|
|
331
|
+
throw new Error(`Sedentary.model: '${modelName}' model: '${method}' method: conflicts with an attribute of '${parent.modelName}' model`);
|
|
332
|
+
for (const foreignKey in parent.foreignKeys)
|
|
333
|
+
if (foreignKey + "Load" === method)
|
|
334
|
+
throw new Error(`Sedentary.model: '${modelName}' model: '${method}' method: conflicts with an inferred methods of '${parent.modelName}' model`);
|
|
335
|
+
if (parent.methods && method in parent.methods)
|
|
336
|
+
throw new Error(`Sedentary.model: '${modelName}' model: '${method}' method: conflicts with a method of '${parent.modelName}' model`);
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
checkParent(parent.parent);
|
|
340
|
+
};
|
|
341
|
+
checkParent(parent);
|
|
271
342
|
Object.defineProperty(Class, "isModel", { value: () => true });
|
|
272
343
|
Object.defineProperty(Class, "load", { value: load });
|
|
273
|
-
Object.defineProperty(Class, "meta", { value:
|
|
274
|
-
Object.defineProperty(Class, "name", { value:
|
|
275
|
-
Object.defineProperty(Class.prototype.save, "name", { value:
|
|
276
|
-
Object.assign(Class,
|
|
344
|
+
Object.defineProperty(Class, "meta", { value: meta });
|
|
345
|
+
Object.defineProperty(Class, "name", { value: modelName });
|
|
346
|
+
Object.defineProperty(Class.prototype.save, "name", { value: modelName + ".save" });
|
|
347
|
+
Object.assign(Class, meta);
|
|
277
348
|
Object.assign(Class.prototype, methods);
|
|
278
349
|
for (const attribute of aarray)
|
|
279
350
|
Object.defineProperty(Class, attribute.attributeName, { value: attribute });
|
|
280
|
-
for (const key of ["attributeName", "base", "fieldName", "size", "type", "unique"])
|
|
351
|
+
for (const key of ["attributeName", "base", "fieldName", "modelName", "size", "type", "unique"])
|
|
281
352
|
Object.defineProperty(Class, key, { value: pk[key] });
|
|
282
353
|
return Class;
|
|
283
354
|
}
|
|
@@ -319,6 +390,7 @@ class Super extends db.model("Super", {
|
|
|
319
390
|
this.num = 0;
|
|
320
391
|
const a = this.nLoad ? await this.nLoad() : { prova: () => null };
|
|
321
392
|
a.prova();
|
|
393
|
+
this.prova();
|
|
322
394
|
}
|
|
323
395
|
}) {
|
|
324
396
|
}
|
|
@@ -335,9 +407,9 @@ class Current extends db.model("Current", { b: { type: db.FKEY(Next), unique: tr
|
|
|
335
407
|
}
|
|
336
408
|
}) {
|
|
337
409
|
}
|
|
338
|
-
class Last extends db.model("Last", {
|
|
410
|
+
class Last extends db.model("Last", { c: db.FKEY(Current.b) }, {
|
|
339
411
|
init: function () {
|
|
340
|
-
this.
|
|
412
|
+
this.c = 24;
|
|
341
413
|
},
|
|
342
414
|
parent: Next
|
|
343
415
|
}) {
|
|
@@ -353,3 +425,29 @@ class Last extends db.model("Last", { b: db.FKEY(Current.b) }, {
|
|
|
353
425
|
}
|
|
354
426
|
return true;
|
|
355
427
|
})();
|
|
428
|
+
/*
|
|
429
|
+
export let factory = () => {
|
|
430
|
+
class Foo {
|
|
431
|
+
a = 3;
|
|
432
|
+
b = 'bar'
|
|
433
|
+
c?: boolean
|
|
434
|
+
}
|
|
435
|
+
return Foo as (new () => { [key in keyof Foo]: Foo[key] })
|
|
436
|
+
};
|
|
437
|
+
|
|
438
|
+
export const FooConstr = factory()
|
|
439
|
+
export type TypeExtractor<T> = T extends (new() => infer E) ? E : never;
|
|
440
|
+
export type FooType = TypeExtractor<typeof FooConstr>;
|
|
441
|
+
|
|
442
|
+
const foo = new FooConstr()
|
|
443
|
+
|
|
444
|
+
function rino(a:FooType){
|
|
445
|
+
if(a instanceof FooConstr){console.log("sisi")}
|
|
446
|
+
if(a instanceof FooType){console.log("sisi")}
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
rino(foo);
|
|
450
|
+
|
|
451
|
+
|
|
452
|
+
B.prototype instanceof A
|
|
453
|
+
*/
|
package/lib/db.d.ts
CHANGED
|
@@ -3,6 +3,11 @@ export declare class Entry {
|
|
|
3
3
|
init(): void;
|
|
4
4
|
save(): Promise<boolean>;
|
|
5
5
|
}
|
|
6
|
+
export declare type ForeignKeyActions = "cascade" | "no action" | "restrict" | "set default" | "set null";
|
|
7
|
+
export interface ForeignKeyOptions {
|
|
8
|
+
onDelete?: ForeignKeyActions;
|
|
9
|
+
onUpdate?: ForeignKeyActions;
|
|
10
|
+
}
|
|
6
11
|
export declare class Type<N extends Natural, E> {
|
|
7
12
|
base: unknown;
|
|
8
13
|
entry?: E;
|
|
@@ -12,16 +17,25 @@ export declare class Type<N extends Natural, E> {
|
|
|
12
17
|
foreignKey?: {
|
|
13
18
|
attributeName: string;
|
|
14
19
|
fieldName: string;
|
|
20
|
+
options?: ForeignKeyOptions;
|
|
15
21
|
tableName: string;
|
|
16
22
|
};
|
|
17
23
|
constructor(from: Type<N, E>);
|
|
18
24
|
}
|
|
19
25
|
export declare class Meta<N extends Natural, E> extends Type<N, E> {
|
|
26
|
+
attributes: {
|
|
27
|
+
[key: string]: unknown;
|
|
28
|
+
};
|
|
29
|
+
foreignKeys: {
|
|
30
|
+
[key: string]: unknown;
|
|
31
|
+
};
|
|
20
32
|
init: () => void;
|
|
21
33
|
isModel?: () => boolean;
|
|
22
34
|
methods: {
|
|
23
35
|
[key: string]: () => unknown;
|
|
24
36
|
};
|
|
37
|
+
modelName: string;
|
|
38
|
+
parent?: Meta<Natural, E>;
|
|
25
39
|
primaryKey: string;
|
|
26
40
|
tableName: string;
|
|
27
41
|
constructor(from: Meta<N, E>);
|
|
@@ -30,6 +44,7 @@ export declare class Attribute<N extends Natural, E> extends Type<N, E> {
|
|
|
30
44
|
attributeName: string;
|
|
31
45
|
defaultValue?: unknown;
|
|
32
46
|
fieldName: string;
|
|
47
|
+
modelName: string;
|
|
33
48
|
notNull: boolean;
|
|
34
49
|
tableName: string;
|
|
35
50
|
unique?: boolean;
|
|
@@ -48,32 +63,30 @@ export interface Index {
|
|
|
48
63
|
}
|
|
49
64
|
interface ITable {
|
|
50
65
|
attributes: Attribute<Natural, unknown>[];
|
|
66
|
+
autoIncrement: boolean;
|
|
51
67
|
constraints: Constraint[];
|
|
52
68
|
indexes: Index[];
|
|
53
|
-
oid?: number;
|
|
54
69
|
parent: Meta<Natural, unknown>;
|
|
55
|
-
primaryKey: string;
|
|
56
70
|
sync: boolean;
|
|
57
71
|
tableName: string;
|
|
58
72
|
}
|
|
59
73
|
declare const Table_base: new (defaults?: ITable) => ITable;
|
|
60
74
|
export declare class Table extends Table_base {
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
75
|
+
autoIncrementOwn?: boolean;
|
|
76
|
+
oid?: number;
|
|
77
|
+
findField(name: string): Attribute<Natural, unknown>;
|
|
64
78
|
}
|
|
65
79
|
export declare abstract class DB {
|
|
66
|
-
tables:
|
|
67
|
-
[key: string]: Table;
|
|
68
|
-
};
|
|
69
|
-
tablesArr: Table[];
|
|
80
|
+
tables: Table[];
|
|
70
81
|
protected log: (...data: unknown[]) => void;
|
|
82
|
+
protected sync: boolean;
|
|
71
83
|
abstract connect(): Promise<void>;
|
|
72
84
|
abstract end(): Promise<void>;
|
|
73
85
|
constructor(log: (message: string) => void);
|
|
74
|
-
|
|
86
|
+
findTable(name: string): Table;
|
|
75
87
|
protected indexesEq(a: Index, b: Index): boolean;
|
|
76
|
-
|
|
88
|
+
syncDataBase(): Promise<void>;
|
|
89
|
+
protected syncLog(...data: unknown[]): void;
|
|
77
90
|
abstract dropConstraints(table: Table): Promise<number[]>;
|
|
78
91
|
abstract dropFields(table: Table): Promise<void>;
|
|
79
92
|
abstract dropIndexes(table: Table, constraintIndexes: number[]): Promise<void>;
|