sedentary 0.0.11 → 0.0.15
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/LICENSE +1 -1
- package/README.md +11 -8
- package/index.d.ts +78 -37
- package/index.js +161 -84
- package/lib/db.d.ts +43 -36
- package/lib/db.js +34 -31
- package/lib/log.d.ts +4 -0
- package/lib/log.js +20 -0
- package/lib/log.ts +22 -0
- package/lib/minidb.d.ts +3 -2
- package/lib/minidb.js +83 -31
- package/package.json +15 -12
- package/sedentary-pg/LICENSE +21 -0
- package/sedentary-pg/README.md +34 -0
- package/sedentary-pg/lib/pgdb.ts +340 -0
- package/sedentary-pg/package-lock.json +6768 -0
- package/sedentary-pg/package.json +66 -0
package/LICENSE
CHANGED
package/README.md
CHANGED
|
@@ -1,21 +1,24 @@
|
|
|
1
1
|
# sedentary
|
|
2
2
|
|
|
3
|
-
[![NPM version][npm-badge]][npm-url]
|
|
4
|
-
[![Types][types-badge]][npm-url]
|
|
5
|
-
[![NPM downloads][npm-downloads-badge]][npm-url]
|
|
6
|
-
|
|
7
3
|
[![Build Status][travis-badge]][travis-url]
|
|
8
4
|
[![Code Climate][code-badge]][code-url]
|
|
9
5
|
[![Test Coverage][cover-badge]][code-url]
|
|
10
6
|
|
|
11
|
-
[![
|
|
7
|
+
[![NPM version][npm-badge]][npm-url]
|
|
8
|
+
[![NPM downloads][npm-downloads-badge]][npm-url]
|
|
12
9
|
[![Stars][stars-badge]][github-url]
|
|
10
|
+
|
|
11
|
+
[![Types][types-badge]][npm-url]
|
|
12
|
+
[![Documentation][doc-badge]][doc-url]
|
|
13
|
+
[![Dependents][deps-badge]][npm-url]
|
|
13
14
|
[![Donate][donate-badge]][donate-url]
|
|
14
15
|
|
|
15
16
|
[code-badge]: https://codeclimate.com/github/iccicci/sedentary/badges/gpa.svg
|
|
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
|
|
@@ -24,7 +27,7 @@
|
|
|
24
27
|
[npm-url]: https://www.npmjs.com/package/sedentary
|
|
25
28
|
[stars-badge]: https://badgen.net/github/stars/iccicci/sedentary?icon=github&cache=300
|
|
26
29
|
[travis-badge]: https://badgen.net/travis/iccicci/sedentary?icon=travis&cache=300
|
|
27
|
-
[travis-url]: https://travis-ci.com/iccicci/sedentary
|
|
30
|
+
[travis-url]: https://app.travis-ci.com/github/iccicci/sedentary
|
|
28
31
|
[types-badge]: https://badgen.net/npm/types/sedentary?color=green&icon=typescript&cache=300
|
|
29
32
|
|
|
30
33
|
# under development
|
|
@@ -95,10 +98,10 @@ The full documentation is on [sedentary.readthedocs.io](https://sedentary.readth
|
|
|
95
98
|
|
|
96
99
|
Requires:
|
|
97
100
|
|
|
98
|
-
- Node.js: **
|
|
101
|
+
- Node.js: **v12**
|
|
99
102
|
- TypeScript: **v4.1** (or none if used in a JavaScript project).
|
|
100
103
|
|
|
101
|
-
The package is tested under [all Node.js versions](https://travis-ci.
|
|
104
|
+
The package is tested under [all Node.js versions](https://app.travis-ci.com/github/iccicci/sedentary)
|
|
102
105
|
currently supported accordingly to [Node.js Release](https://github.com/nodejs/Release#readme).
|
|
103
106
|
|
|
104
107
|
To work with the package under Windows, be sure to configure `bash.exe` as your _script-shell_.
|
package/index.d.ts
CHANGED
|
@@ -1,76 +1,117 @@
|
|
|
1
|
-
import { DB, Meta,
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import { DB, Entry, Meta, Natural, Type } from "./lib/db";
|
|
2
|
+
export { Entry, Natural, Type } from "./lib/db";
|
|
3
|
+
export declare type TypeDefinition<N extends Natural, E> = (() => Type<N, E>) | Type<N, E>;
|
|
4
|
+
export interface AttributeOptions<N extends Natural, E> {
|
|
4
5
|
defaultValue?: N;
|
|
5
6
|
fieldName?: string;
|
|
6
7
|
notNull?: boolean;
|
|
7
|
-
type: TypeDefinition<N,
|
|
8
|
+
type: TypeDefinition<N, E>;
|
|
8
9
|
unique?: boolean;
|
|
9
10
|
}
|
|
10
|
-
declare type
|
|
11
|
-
declare type
|
|
12
|
-
[key: string]:
|
|
11
|
+
export declare type AttributeDefinition<N extends Natural, E> = TypeDefinition<N, E> | AttributeOptions<N, E>;
|
|
12
|
+
export declare type AttributesDefinition = {
|
|
13
|
+
[key: string]: AttributeDefinition<Natural, unknown>;
|
|
13
14
|
};
|
|
14
|
-
declare type
|
|
15
|
-
declare type
|
|
16
|
-
|
|
17
|
-
[f in keyof F]?: ForeignKeyFileds<F[f], f>;
|
|
15
|
+
declare type KeysAttributes<T, k> = T extends AttributeDefinition<Natural, infer E> ? (E extends Entry ? k : never) : never;
|
|
16
|
+
declare type Keys<F extends AttributesDefinition> = {
|
|
17
|
+
[f in keyof F]?: KeysAttributes<F[f], f>;
|
|
18
18
|
}[keyof F];
|
|
19
19
|
declare type Methods<T> = {
|
|
20
20
|
[key: string]: (this: T) => unknown;
|
|
21
21
|
};
|
|
22
22
|
declare type Native__<T> = T extends Type<infer N, unknown> ? N : never;
|
|
23
|
-
declare type Native_<T> = T extends () => Type<infer N, infer
|
|
24
|
-
declare type Native<T> = T extends
|
|
25
|
-
declare type Parent<T> = T extends Meta<
|
|
26
|
-
declare type
|
|
23
|
+
declare type Native_<T> = T extends () => Type<infer N, infer E> ? Native__<Type<N, E>> : Native__<T>;
|
|
24
|
+
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
|
+
export declare type IndexAttributes = string[] | string;
|
|
27
|
+
export interface IndexOptions {
|
|
28
|
+
attributes: IndexAttributes;
|
|
29
|
+
type?: "btree" | "hash";
|
|
30
|
+
unique?: boolean;
|
|
31
|
+
}
|
|
32
|
+
export declare type IndexDefinition = IndexAttributes | IndexOptions;
|
|
33
|
+
export declare type IndexesDefinition = {
|
|
34
|
+
[key: string]: IndexDefinition;
|
|
35
|
+
};
|
|
36
|
+
declare type BaseModelOptions<T> = {
|
|
37
|
+
indexes?: IndexesDefinition;
|
|
27
38
|
init?: (this: T) => void;
|
|
28
|
-
methods?: M;
|
|
29
39
|
sync?: boolean;
|
|
30
40
|
tableName?: string;
|
|
31
41
|
};
|
|
32
|
-
declare type
|
|
33
|
-
|
|
42
|
+
export declare type ModelOptions<K extends string, M extends Methods<T>, P extends Meta<Natural, Entry>, T extends Entry> = BaseModelOptions<T> & {
|
|
43
|
+
int8id?: boolean;
|
|
44
|
+
methods?: M;
|
|
45
|
+
parent?: P;
|
|
46
|
+
primaryKey?: K;
|
|
47
|
+
};
|
|
48
|
+
declare type ForeignKey<T> = T extends AttributeDefinition<Natural, infer E> ? () => Promise<E> : never;
|
|
49
|
+
declare type ModelWithMetods<A extends AttributesDefinition, M> = {
|
|
50
|
+
[a in keyof A]?: Native<A[a]>;
|
|
34
51
|
} & {
|
|
35
|
-
[
|
|
52
|
+
[a in Keys<A> & string as `${a}Load`]?: ForeignKey<A[a]>;
|
|
36
53
|
} & M;
|
|
37
|
-
declare type
|
|
38
|
-
[
|
|
54
|
+
declare type Model<A extends AttributesDefinition> = {
|
|
55
|
+
[a in keyof A]?: Native<A[a]>;
|
|
56
|
+
} & {
|
|
57
|
+
[a in Keys<A> & string as `${a}Load`]?: ForeignKey<A[a]>;
|
|
58
|
+
};
|
|
59
|
+
declare type Ancestor<A, N extends Natural, T extends Entry> = (new () => T) & {
|
|
60
|
+
[a in keyof A]?: Meta<Native<A[a]>, T>;
|
|
39
61
|
} & {
|
|
40
62
|
load: (boh: boolean) => Promise<T[]>;
|
|
41
63
|
} & Meta<N, T>;
|
|
42
|
-
export interface
|
|
43
|
-
log?: (message: string) => void;
|
|
64
|
+
export interface SedentaryOptions {
|
|
65
|
+
log?: ((message: string) => void) | null;
|
|
66
|
+
serverless?: boolean;
|
|
44
67
|
sync?: boolean;
|
|
45
68
|
}
|
|
46
69
|
export declare class Sedentary {
|
|
47
70
|
protected db: DB;
|
|
48
|
-
protected log: (
|
|
49
|
-
|
|
71
|
+
protected log: (...data: unknown[]) => void;
|
|
72
|
+
protected sync: boolean;
|
|
50
73
|
private models;
|
|
51
|
-
constructor(filename: string, options?:
|
|
74
|
+
constructor(filename: string, options?: SedentaryOptions);
|
|
52
75
|
DATETIME(): Type<Date, unknown>;
|
|
53
|
-
FKEY<N extends
|
|
76
|
+
FKEY<N extends Natural, E extends Entry>(attribute: Type<N, E>): Type<N, E>;
|
|
54
77
|
INT(size?: number): Type<number, unknown>;
|
|
55
78
|
INT8(): Type<string, unknown>;
|
|
56
79
|
VARCHAR(size?: number): Type<string, unknown>;
|
|
57
80
|
connect(): Promise<void>;
|
|
58
81
|
end(): Promise<void>;
|
|
59
|
-
model<
|
|
82
|
+
model<A extends AttributesDefinition, M extends Methods<T>, T extends Entry & {
|
|
83
|
+
id?: string;
|
|
84
|
+
} & ModelWithMetods<A, M>>(name: string, attributes: A, options?: BaseModelOptions<T> & {
|
|
85
|
+
int8id: true;
|
|
86
|
+
methods: M;
|
|
87
|
+
}): Ancestor<A, string, T>;
|
|
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>>(name: string, attributes: A, options?: BaseModelOptions<T> & {
|
|
89
|
+
methods: M;
|
|
90
|
+
primaryKey: K;
|
|
91
|
+
}): Ancestor<A, N, T>;
|
|
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>>(name: 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>>(name: string, attributes: A, options?: BaseModelOptions<T> & {
|
|
99
|
+
methods: M;
|
|
100
|
+
}): Ancestor<A, number, T>;
|
|
101
|
+
model<A extends AttributesDefinition, T extends Entry & {
|
|
60
102
|
id?: string;
|
|
61
|
-
} & Model<
|
|
103
|
+
} & Model<A>>(name: string, attributes: A, options?: BaseModelOptions<T> & {
|
|
62
104
|
int8id: true;
|
|
63
|
-
}): Ancestor<
|
|
64
|
-
model<
|
|
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>>(name: string, attributes: A, options?: BaseModelOptions<T> & {
|
|
65
107
|
primaryKey: K;
|
|
66
|
-
}): Ancestor<
|
|
67
|
-
model<
|
|
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>>(name: string, attributes: A, options?: BaseModelOptions<T> & {
|
|
68
110
|
parent: P;
|
|
69
|
-
}): Ancestor<
|
|
70
|
-
model<
|
|
111
|
+
}): Ancestor<A, N, T>;
|
|
112
|
+
model<A extends AttributesDefinition, T extends Entry & {
|
|
71
113
|
id?: number;
|
|
72
|
-
} & Model<
|
|
114
|
+
} & Model<A>>(name: string, attributes: A, options?: BaseModelOptions<T>): Ancestor<A, number, T>;
|
|
73
115
|
checkSize(size: number, message: string): number;
|
|
74
116
|
}
|
|
75
117
|
export declare const Package: typeof Sedentary;
|
|
76
|
-
export {};
|
package/index.js
CHANGED
|
@@ -1,32 +1,45 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.Package = exports.Sedentary = void 0;
|
|
3
|
+
exports.Package = exports.Sedentary = exports.Type = exports.Entry = void 0;
|
|
4
4
|
const db_1 = require("./lib/db");
|
|
5
|
+
const log_1 = require("./lib/log");
|
|
5
6
|
const minidb_1 = require("./lib/minidb");
|
|
7
|
+
var db_2 = require("./lib/db");
|
|
8
|
+
Object.defineProperty(exports, "Entry", { enumerable: true, get: function () { return db_2.Entry; } });
|
|
9
|
+
Object.defineProperty(exports, "Type", { enumerable: true, get: function () { return db_2.Type; } });
|
|
10
|
+
const allowedOption = ["indexes", "init", "int8id", "methods", "parent", "primaryKey", "sync", "tableName", "type"];
|
|
11
|
+
const reservedNames = [
|
|
12
|
+
...["attributeName", "base", "class", "constructor", "defaultValue", "entry", "fieldName", "init", "isModel"],
|
|
13
|
+
...["load", "meta", "methods", "name", "primaryKey", "prototype", "save", "size", "tableName", "type"]
|
|
14
|
+
];
|
|
6
15
|
class Sedentary {
|
|
7
16
|
constructor(filename, options) {
|
|
8
17
|
this.sync = true;
|
|
9
18
|
this.models = {};
|
|
10
19
|
if (typeof filename !== "string")
|
|
11
|
-
throw new Error("Sedentary
|
|
20
|
+
throw new Error("new Sedentary: 'filename' argument: Wrong type, expected 'string'");
|
|
12
21
|
if (!options)
|
|
13
22
|
options = {};
|
|
14
23
|
if (!(options instanceof Object))
|
|
15
|
-
throw new Error("Sedentary
|
|
16
|
-
for (const k in options)
|
|
17
|
-
if (["log", "sync"].
|
|
18
|
-
throw new Error(`Sedentary
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
24
|
+
throw new Error("new Sedentary: 'options' argument: Wrong type, expected 'Object'");
|
|
25
|
+
for (const k in options)
|
|
26
|
+
if (!["log", "sync"].includes(k))
|
|
27
|
+
throw new Error(`new Sedentary: 'options' argument: Unknown '${k}' option`);
|
|
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);
|
|
23
34
|
this.db = new minidb_1.MiniDB(filename, this.log);
|
|
35
|
+
this.sync = sync;
|
|
24
36
|
}
|
|
25
37
|
DATETIME() {
|
|
26
38
|
return new db_1.Type({ base: Date, type: "DATETIME" });
|
|
27
39
|
}
|
|
28
|
-
FKEY(
|
|
29
|
-
|
|
40
|
+
FKEY(attribute) {
|
|
41
|
+
const { attributeName, base, fieldName, size, tableName, type } = attribute;
|
|
42
|
+
return new db_1.Type({ base, foreignKey: { attributeName, fieldName, tableName }, size, type });
|
|
30
43
|
}
|
|
31
44
|
INT(size) {
|
|
32
45
|
const message = "Sedentary.INT: 'size' argument: Wrong value, expected 2 or 4";
|
|
@@ -48,11 +61,11 @@ class Sedentary {
|
|
|
48
61
|
this.log("Connecting...");
|
|
49
62
|
await this.db.connect();
|
|
50
63
|
this.log("Connected, syncing...");
|
|
51
|
-
await this.db.
|
|
64
|
+
await this.db.syncDataBase();
|
|
52
65
|
this.log("Synced");
|
|
53
66
|
}
|
|
54
67
|
catch (e) {
|
|
55
|
-
this.log("Connecting:
|
|
68
|
+
this.log("Connecting:", e.message);
|
|
56
69
|
throw e;
|
|
57
70
|
}
|
|
58
71
|
}
|
|
@@ -61,34 +74,40 @@ class Sedentary {
|
|
|
61
74
|
await this.db.end();
|
|
62
75
|
this.log("Connection closed");
|
|
63
76
|
}
|
|
64
|
-
model(name,
|
|
77
|
+
model(name, attributes, options) {
|
|
65
78
|
if (typeof name !== "string")
|
|
66
79
|
throw new Error("Sedentary.model: 'name' argument: Wrong type, expected 'string'");
|
|
67
80
|
if (this.models[name])
|
|
68
81
|
throw new Error(`Sedentary.model: '${name}' model: Model already defined`);
|
|
69
|
-
if (!
|
|
70
|
-
|
|
71
|
-
if (!(
|
|
72
|
-
throw new Error(`Sedentary.model: '${name}' model: '
|
|
82
|
+
if (!attributes)
|
|
83
|
+
attributes = {};
|
|
84
|
+
if (!(attributes instanceof Object))
|
|
85
|
+
throw new Error(`Sedentary.model: '${name}' model: 'attributes' argument: Wrong type, expected 'Object'`);
|
|
73
86
|
if (!options)
|
|
74
87
|
options = {};
|
|
75
88
|
if (!(options instanceof Object))
|
|
76
89
|
throw new Error(`Sedentary.model: '${name}' model: 'options' argument: Wrong type, expected 'Object'`);
|
|
77
90
|
for (const k in options)
|
|
78
|
-
if (
|
|
91
|
+
if (!allowedOption.includes(k))
|
|
79
92
|
throw new Error(`Sedentary.model: '${name}' model: 'options' argument: Unknown '${k}' option`);
|
|
80
|
-
|
|
81
|
-
|
|
93
|
+
if (options.int8id && options.parent)
|
|
94
|
+
throw new Error(`Sedentary.model: '${name}' model: 'int8id' and 'parent' options conflict each other`);
|
|
95
|
+
if (options.int8id && options.primaryKey)
|
|
96
|
+
throw new Error(`Sedentary.model: '${name}' model: 'int8id' and 'primaryKey' options conflict each other`);
|
|
97
|
+
if (options.parent && options.primaryKey)
|
|
98
|
+
throw new Error(`Sedentary.model: '${name}' 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: name }, options);
|
|
82
101
|
let { methods } = options;
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
102
|
+
let aarray = int8id
|
|
103
|
+
? [new db_1.Attribute(Object.assign(Object.assign({}, this.INT8()), { attributeName: "id", fieldName: "id", notNull: true, tableName, unique: true }))]
|
|
104
|
+
: [new db_1.Attribute(Object.assign(Object.assign({}, this.INT(4)), { attributeName: "id", fieldName: "id", notNull: true, tableName, unique: true }))];
|
|
105
|
+
let constraints = [{ attribute: aarray[0], constraintName: `${tableName}_id_unique`, type: "u" }];
|
|
106
|
+
const iarray = [];
|
|
107
|
+
const pk = aarray[0];
|
|
87
108
|
if (methods && !(methods instanceof Object))
|
|
88
109
|
throw new Error(`Sedentary.model: '${name}' model: 'methods' option: Wrong type, expected 'Object'`);
|
|
89
110
|
if (parent) {
|
|
90
|
-
if (primaryKey)
|
|
91
|
-
throw new Error(`Sedentary.model: '${name}' model: Both 'parent' and 'primaryKey' options provided`);
|
|
92
111
|
methods = (methods ? Object.assign(Object.assign({}, (parent.methods || {})), methods) : parent.methods);
|
|
93
112
|
try {
|
|
94
113
|
if (!parent.isModel())
|
|
@@ -100,72 +119,127 @@ class Sedentary {
|
|
|
100
119
|
}
|
|
101
120
|
if (primaryKey && typeof primaryKey !== "string")
|
|
102
121
|
throw new Error(`Sedentary.model: '${name}' model: 'primaryKey' option: Wrong type, expected 'string'`);
|
|
103
|
-
if (primaryKey && Object.keys(
|
|
104
|
-
throw new Error(`Sedentary.model: '${name}' model: 'primaryKey' option:
|
|
105
|
-
if (parent || primaryKey)
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
constraints
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
122
|
+
if (primaryKey && !Object.keys(attributes).includes(primaryKey))
|
|
123
|
+
throw new Error(`Sedentary.model: '${name}' model: 'primaryKey' option: Attribute '${primaryKey}' does not exists`);
|
|
124
|
+
if (parent || primaryKey) {
|
|
125
|
+
autoIncrement = false;
|
|
126
|
+
aarray = [];
|
|
127
|
+
constraints = [];
|
|
128
|
+
}
|
|
129
|
+
for (const attributeName in attributes) {
|
|
130
|
+
if (reservedNames.includes(attributeName))
|
|
131
|
+
throw new Error(`Sedentary.model: '${name}' model: '${attributeName}' attribute: Reserved name`);
|
|
132
|
+
const call = (defaultValue, fieldName, notNull, unique, func, message1, message2) => {
|
|
133
|
+
if (func === this.FKEY)
|
|
134
|
+
throw new Error(`${message1} 'this.FKEY' can't be used directly`);
|
|
135
|
+
if (func !== this.DATETIME && func !== this.INT && func !== this.INT8 && func !== this.VARCHAR)
|
|
136
|
+
throw new Error(`${message1} ${message2}`);
|
|
137
|
+
return new db_1.Attribute(Object.assign({ attributeName, defaultValue, fieldName, notNull, tableName, unique }, func()));
|
|
138
|
+
};
|
|
139
|
+
const attributeDefinition = attributes[attributeName];
|
|
140
|
+
let { base, defaultValue, fieldName, foreignKey, notNull, size, type, unique } = (() => {
|
|
115
141
|
const ret = (() => {
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
};
|
|
123
|
-
|
|
124
|
-
return new db_1.Field(Object.assign({ fieldName: fname }, field));
|
|
125
|
-
if (field instanceof Function)
|
|
126
|
-
return call(undefined, fname, false, field, `Sedentary.model: '${name}' model: '${fname}' field: Wrong type, expected 'Field'`);
|
|
127
|
-
if (!(field instanceof Object))
|
|
128
|
-
throw new Error(`Sedentary.model: '${name}' model: '${fname}' field: Wrong field type, expected 'Field'`);
|
|
129
|
-
({ defaultValue, fieldName, unique, type } = field);
|
|
130
|
-
if (!fieldName)
|
|
131
|
-
fieldName = fname;
|
|
142
|
+
if (attributeDefinition instanceof db_1.Type)
|
|
143
|
+
return new db_1.Attribute(Object.assign({ attributeName, fieldName: attributeName, notNull: false, tableName }, attributeDefinition));
|
|
144
|
+
if (attributeDefinition instanceof Function)
|
|
145
|
+
return call(undefined, attributeName, false, false, attributeDefinition, `Sedentary.model: '${name}' model: '${attributeName}' attribute:`, "Wrong type, expected 'Attribute'");
|
|
146
|
+
if (!(attributeDefinition instanceof Object))
|
|
147
|
+
throw new Error(`Sedentary.model: '${name}' model: '${attributeName}' attribute: Wrong attribute type, expected 'Attribute'`);
|
|
148
|
+
const attributeDefaults = Object.assign({ defaultValue: undefined, fieldName: attributeName, notNull: false, unique: false }, attributeDefinition);
|
|
149
|
+
const { defaultValue, fieldName, notNull, unique, type } = attributeDefaults;
|
|
132
150
|
if (defaultValue === null)
|
|
133
|
-
throw new Error(`Sedentary.model: '${name}' model: '${
|
|
151
|
+
throw new Error(`Sedentary.model: '${name}' model: '${attributeName}' attribute: 'defaultValue' option: Does 'null' default value really makes sense?`);
|
|
134
152
|
if (typeof fieldName !== "string")
|
|
135
|
-
throw new Error(`Sedentary.model: '${name}' model: '${
|
|
136
|
-
if (
|
|
137
|
-
throw new Error(`Sedentary.model: '${name}' model: '${
|
|
153
|
+
throw new Error(`Sedentary.model: '${name}' model: '${attributeName}' attribute: 'fieldName' option: Wrong type, expected 'string'`);
|
|
154
|
+
if (typeof notNull !== "boolean")
|
|
155
|
+
throw new Error(`Sedentary.model: '${name}' model: '${attributeName}' attribute: 'notNull' option: Wrong type, expected 'boolean'`);
|
|
156
|
+
if (typeof unique !== "boolean")
|
|
157
|
+
throw new Error(`Sedentary.model: '${name}' model: '${attributeName}' attribute: 'unique' option: Wrong type, expected 'boolean'`);
|
|
158
|
+
if (type === undefined)
|
|
159
|
+
throw new Error(`Sedentary.model: '${name}' model: '${attributeName}' attribute: Missing 'type' option`);
|
|
138
160
|
if (type instanceof db_1.Type)
|
|
139
|
-
return new db_1.
|
|
161
|
+
return new db_1.Attribute(Object.assign({ attributeName, defaultValue, fieldName, notNull, tableName, unique }, type));
|
|
140
162
|
if (type instanceof Function)
|
|
141
|
-
return call(defaultValue, fieldName, unique, type, `Sedentary.model: '${name}' model: '${
|
|
142
|
-
throw new Error(`Sedentary.model: '${name}' model: '${
|
|
163
|
+
return call(defaultValue, fieldName, notNull, unique, type, `Sedentary.model: '${name}' model: '${attributeName}' attribute: 'type' option:`, "Wrong type, expected 'Type'");
|
|
164
|
+
throw new Error(`Sedentary.model: '${name}' model: '${attributeName}' attribute: 'type' option: Wrong type, expected 'Type'`);
|
|
143
165
|
})();
|
|
144
166
|
const { base, defaultValue } = ret;
|
|
145
167
|
if (defaultValue !== undefined) {
|
|
168
|
+
if (base === Date && !(defaultValue instanceof Date))
|
|
169
|
+
throw new Error(`Sedentary.model: '${name}' model: '${attributeName}' attribute: 'defaultValue' option: Wrong type, expected 'Date'`);
|
|
146
170
|
if (base === Number && typeof defaultValue !== "number")
|
|
147
|
-
throw new Error(`Sedentary.model: '${name}' model: '${
|
|
171
|
+
throw new Error(`Sedentary.model: '${name}' model: '${attributeName}' attribute: 'defaultValue' option: Wrong type, expected 'number'`);
|
|
148
172
|
if (base === String && typeof defaultValue !== "string")
|
|
149
|
-
throw new Error(`Sedentary.model: '${name}' model: '${
|
|
173
|
+
throw new Error(`Sedentary.model: '${name}' model: '${attributeName}' attribute: 'defaultValue' option: Wrong type, expected 'string'`);
|
|
150
174
|
}
|
|
151
175
|
return ret;
|
|
152
176
|
})();
|
|
153
|
-
if (primaryKey ===
|
|
177
|
+
if (primaryKey === attributeName) {
|
|
154
178
|
notNull = true;
|
|
155
179
|
unique = true;
|
|
156
180
|
}
|
|
157
181
|
if (defaultValue)
|
|
158
182
|
notNull = true;
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
183
|
+
const attribute = new db_1.Attribute({ attributeName, base, defaultValue, fieldName, foreignKey, notNull, size, tableName, type, unique });
|
|
184
|
+
aarray.push(attribute);
|
|
185
|
+
if (foreignKey)
|
|
186
|
+
constraints.push({ attribute, constraintName: `fkey_${fieldName}_${foreignKey.tableName}_${foreignKey.fieldName}`, type: "f" });
|
|
187
|
+
if (unique)
|
|
188
|
+
constraints.push({ attribute, constraintName: `${tableName}_${fieldName}_unique`, type: "u" });
|
|
189
|
+
}
|
|
190
|
+
if (indexes) {
|
|
191
|
+
const flds = attributes;
|
|
192
|
+
if (!(indexes instanceof Object))
|
|
193
|
+
throw new Error(`Sedentary.model: '${name}' model: 'indexes' option: Wrong type, expected 'Object'`);
|
|
194
|
+
for (const indexName in indexes) {
|
|
195
|
+
if (aarray.filter(({ fieldName, unique }) => unique && `${tableName}_${fieldName}_unique` === indexName).length !== 0)
|
|
196
|
+
throw new Error(`Sedentary.model: '${name}' model: '${indexName}' index: index name already inferred by the unique constraint on an attribute`);
|
|
197
|
+
const idx = indexes[indexName];
|
|
198
|
+
const checkAttribute = (attribute, l) => {
|
|
199
|
+
if (typeof attribute !== "string")
|
|
200
|
+
throw new Error(`Sedentary.model: '${name}' model: '${indexName}' index: #${l + 1} attribute: Wrong type, expected 'string'`);
|
|
201
|
+
if (!(attribute in flds))
|
|
202
|
+
throw new Error(`Sedentary.model: '${name}' model: '${indexName}' index: #${l + 1} attribute: Unknown attribute '${attribute}'`);
|
|
203
|
+
};
|
|
204
|
+
let attributes;
|
|
205
|
+
let type = "btree";
|
|
206
|
+
let unique = false;
|
|
207
|
+
if (idx instanceof Array) {
|
|
208
|
+
idx.forEach(checkAttribute);
|
|
209
|
+
attributes = idx;
|
|
210
|
+
}
|
|
211
|
+
else if (typeof idx === "string") {
|
|
212
|
+
checkAttribute(idx, 0);
|
|
213
|
+
attributes = [idx];
|
|
214
|
+
}
|
|
215
|
+
else if (idx instanceof Object) {
|
|
216
|
+
for (const k in idx)
|
|
217
|
+
if (!["attributes", "type", "unique"].includes(k))
|
|
218
|
+
throw new Error(`Sedentary.model: '${name}' model: '${indexName}' index: Unknown index option '${k}'`);
|
|
219
|
+
({ attributes, type, unique } = Object.assign({ type: "btree", unique: false }, idx));
|
|
220
|
+
if (!attributes)
|
|
221
|
+
throw new Error(`Sedentary.model: '${name}' model: '${indexName}' index: Missing 'attributes' option`);
|
|
222
|
+
if (attributes instanceof Array)
|
|
223
|
+
attributes.forEach(checkAttribute);
|
|
224
|
+
else if (typeof attributes === "string") {
|
|
225
|
+
checkAttribute(attributes, 0);
|
|
226
|
+
attributes = [attributes];
|
|
227
|
+
}
|
|
228
|
+
else
|
|
229
|
+
throw new Error(`Sedentary.model: '${name}' model: '${indexName}' index: 'attributes' option: Wrong type, expected 'FieldNames'`);
|
|
230
|
+
if (typeof type !== "string")
|
|
231
|
+
throw new Error(`Sedentary.model: '${name}' model: '${indexName}' index: 'type' option: Wrong type, expected 'string'`);
|
|
232
|
+
if (!["btree", "hash"].includes(type))
|
|
233
|
+
throw new Error(`Sedentary.model: '${name}' model: '${indexName}' index: 'type' option: Wrong value, expected 'btree' or 'hash'`);
|
|
234
|
+
if (typeof unique !== "boolean")
|
|
235
|
+
throw new Error(`Sedentary.model: '${name}' model: '${indexName}' index: 'unique' option: Wrong type, expected 'boolean'`);
|
|
236
|
+
}
|
|
237
|
+
else
|
|
238
|
+
throw new Error(`Sedentary.model: '${name}' model: '${indexName}' index: Wrong type, expected 'Object'`);
|
|
239
|
+
iarray.push({ fields: attributes, indexName, type, unique });
|
|
166
240
|
}
|
|
167
241
|
}
|
|
168
|
-
this.db.
|
|
242
|
+
this.db.tables.push(new db_1.Table({ autoIncrement, constraints, attributes: aarray, indexes: iarray, parent, sync, tableName }));
|
|
169
243
|
this.models[name] = true;
|
|
170
244
|
const init = parent
|
|
171
245
|
? options.init
|
|
@@ -176,7 +250,7 @@ class Sedentary {
|
|
|
176
250
|
: parent.init
|
|
177
251
|
: options.init;
|
|
178
252
|
const flds = {};
|
|
179
|
-
for (const key in
|
|
253
|
+
for (const key in attributes)
|
|
180
254
|
flds[key] = null;
|
|
181
255
|
class Class {
|
|
182
256
|
constructor() {
|
|
@@ -196,15 +270,19 @@ class Sedentary {
|
|
|
196
270
|
return resolve([new Class()]);
|
|
197
271
|
reject(new Error("boh"));
|
|
198
272
|
}, 10));
|
|
199
|
-
Object.defineProperty(load, "name", { value: name + "
|
|
200
|
-
const meta = { tableName, primaryKey, init, methods };
|
|
201
|
-
Object.defineProperty(Class, "
|
|
273
|
+
Object.defineProperty(load, "name", { value: name + ".load" });
|
|
274
|
+
const meta = { base: Number, type: "meta", tableName, primaryKey, init, methods };
|
|
275
|
+
Object.defineProperty(Class, "isModel", { value: () => true });
|
|
202
276
|
Object.defineProperty(Class, "load", { value: load });
|
|
203
277
|
Object.defineProperty(Class, "meta", { value: new db_1.Meta(meta) });
|
|
278
|
+
Object.defineProperty(Class, "name", { value: name });
|
|
204
279
|
Object.defineProperty(Class.prototype.save, "name", { value: name + ".save" });
|
|
205
280
|
Object.assign(Class, new db_1.Meta(meta));
|
|
206
|
-
Object.assign(Class, Object.assign(Object.assign({}, fields), { isModel: () => true }));
|
|
207
281
|
Object.assign(Class.prototype, methods);
|
|
282
|
+
for (const attribute of aarray)
|
|
283
|
+
Object.defineProperty(Class, attribute.attributeName, { value: attribute });
|
|
284
|
+
for (const key of ["attributeName", "base", "fieldName", "size", "type", "unique"])
|
|
285
|
+
Object.defineProperty(Class, key, { value: pk[key] });
|
|
208
286
|
return Class;
|
|
209
287
|
}
|
|
210
288
|
checkSize(size, message) {
|
|
@@ -218,12 +296,11 @@ class Sedentary {
|
|
|
218
296
|
exports.Sedentary = Sedentary;
|
|
219
297
|
exports.Package = Sedentary;
|
|
220
298
|
const db = new Sedentary("gino");
|
|
221
|
-
const Users = db.model("User", { foo: db.INT(), bar: db.VARCHAR() }, {});
|
|
222
|
-
|
|
299
|
+
const Users = db.model("User", { foo: db.INT(), bar: { type: db.VARCHAR(), unique: true } }, {});
|
|
300
|
+
class Item extends db.model("Item", {
|
|
223
301
|
num: db.FKEY(Users),
|
|
224
302
|
str: db.VARCHAR()
|
|
225
|
-
}
|
|
226
|
-
class Item extends db.model("Item", fields, {
|
|
303
|
+
}, {
|
|
227
304
|
init: function () {
|
|
228
305
|
this.num = 0;
|
|
229
306
|
this.str = "0";
|
|
@@ -256,7 +333,7 @@ class Next extends db.model("Next", { a: db.INT, b: db.INT }, {
|
|
|
256
333
|
primaryKey: "a"
|
|
257
334
|
}) {
|
|
258
335
|
}
|
|
259
|
-
class Current extends db.model("Current", { b: db.FKEY(Next) }, {
|
|
336
|
+
class Current extends db.model("Current", { b: { type: db.FKEY(Next), unique: true } }, {
|
|
260
337
|
init: function () {
|
|
261
338
|
this.b = 24;
|
|
262
339
|
}
|