@antelopejs/interface-database-decorators 0.1.11 → 0.2.0
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 +17 -13
- package/dist/antelope.test.js +1 -1
- package/dist/common.d.ts +48 -2
- package/dist/common.js +51 -5
- package/dist/common.js.map +1 -1
- package/dist/database.js +18 -3
- package/dist/database.js.map +1 -1
- package/dist/internal/bound-schema.d.ts +8 -0
- package/dist/internal/bound-schema.js +14 -0
- package/dist/internal/bound-schema.js.map +1 -0
- package/dist/model.d.ts +21 -8
- package/dist/model.js +34 -15
- package/dist/model.js.map +1 -1
- package/dist/modifiers/autodate.d.ts +2 -2
- package/dist/modifiers/autodate.js.map +1 -1
- package/dist/modifiers/common.d.ts +37 -20
- package/dist/modifiers/common.js +81 -68
- package/dist/modifiers/common.js.map +1 -1
- package/dist/modifiers/encryption.js +26 -14
- package/dist/modifiers/encryption.js.map +1 -1
- package/dist/modifiers/hash.d.ts +46 -4
- package/dist/modifiers/hash.js +175 -14
- package/dist/modifiers/hash.js.map +1 -1
- package/dist/modifiers/internal/kinds.d.ts +15 -1
- package/dist/modifiers/internal/kinds.js +35 -0
- package/dist/modifiers/internal/kinds.js.map +1 -1
- package/dist/modifiers/internal/records.d.ts +40 -5
- package/dist/modifiers/internal/records.js +70 -1
- package/dist/modifiers/internal/records.js.map +1 -1
- package/dist/modifiers/localization.js +12 -7
- package/dist/modifiers/localization.js.map +1 -1
- package/dist/relation.d.ts +5 -0
- package/dist/relation.js +11 -0
- package/dist/relation.js.map +1 -1
- package/dist/schema.js +5 -6
- package/dist/schema.js.map +1 -1
- package/dist/table.d.ts +3 -2
- package/dist/table.js +29 -13
- package/dist/table.js.map +1 -1
- package/dist/tests/cross_instance.test.js +5 -2
- package/dist/tests/cross_instance.test.js.map +1 -1
- package/dist/tests/database.test.js +42 -2
- package/dist/tests/database.test.js.map +1 -1
- package/dist/tests/hash_upgrade.test.d.ts +1 -0
- package/dist/tests/hash_upgrade.test.js +132 -0
- package/dist/tests/hash_upgrade.test.js.map +1 -0
- package/dist/tests/helpers/hash-rows.d.ts +40 -0
- package/dist/tests/helpers/hash-rows.js +41 -0
- package/dist/tests/helpers/hash-rows.js.map +1 -0
- package/dist/tests/helpers/other-instance.js.map +1 -1
- package/dist/tests/integration.test.js +15 -4
- package/dist/tests/integration.test.js.map +1 -1
- package/dist/tests/metadata_inheritance.test.d.ts +1 -0
- package/dist/tests/metadata_inheritance.test.js +212 -0
- package/dist/tests/metadata_inheritance.test.js.map +1 -0
- package/dist/tests/modifiers/encryption_date_marker.test.d.ts +1 -0
- package/dist/tests/modifiers/encryption_date_marker.test.js +78 -0
- package/dist/tests/modifiers/encryption_date_marker.test.js.map +1 -0
- package/dist/tests/modifiers/hash.test.js +295 -0
- package/dist/tests/modifiers/hash.test.js.map +1 -1
- package/dist/tests/modifiers/inherited_names.test.d.ts +1 -0
- package/dist/tests/modifiers/inherited_names.test.js +96 -0
- package/dist/tests/modifiers/inherited_names.test.js.map +1 -0
- package/dist/tests/own_key_lookups.test.d.ts +1 -0
- package/dist/tests/own_key_lookups.test.js +49 -0
- package/dist/tests/own_key_lookups.test.js.map +1 -0
- package/dist/tests/partial_update.test.d.ts +1 -0
- package/dist/tests/partial_update.test.js +55 -0
- package/dist/tests/partial_update.test.js.map +1 -0
- package/dist/tests/row_forms.test.d.ts +1 -0
- package/dist/tests/row_forms.test.js +59 -0
- package/dist/tests/row_forms.test.js.map +1 -0
- package/dist/tests/stored_metadata.test.d.ts +1 -0
- package/dist/tests/stored_metadata.test.js +91 -0
- package/dist/tests/stored_metadata.test.js.map +1 -0
- package/dist/tests/subclass_schema_binding.test.d.ts +1 -0
- package/dist/tests/subclass_schema_binding.test.js +115 -0
- package/dist/tests/subclass_schema_binding.test.js.map +1 -0
- package/dist/tests/table.test.js +16 -0
- package/dist/tests/table.test.js.map +1 -1
- package/docs/1.introduction.md +24 -20
- package/docs/2.table-definitions.md +63 -41
- package/docs/3.table-modifiers.md +128 -98
- package/docs/4.data-models.md +63 -52
- package/docs/5.parameter-decoration.md +28 -24
- package/docs/tsconfig.json +3 -0
- package/package.json +10 -9
- package/skills/database-decorators-interface/SKILL.md +6 -3
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
const chai_1 = require("chai");
|
|
13
|
+
const model_1 = require("../model");
|
|
14
|
+
const localization_1 = require("../modifiers/localization");
|
|
15
|
+
const common_1 = require("../modifiers/common");
|
|
16
|
+
const table_1 = require("../table");
|
|
17
|
+
class Article extends table_1.Table.with(localization_1.LocalizationModifier) {
|
|
18
|
+
}
|
|
19
|
+
__decorate([
|
|
20
|
+
(0, localization_1.Localized)({ fallbackLocale: "en" }),
|
|
21
|
+
__metadata("design:type", String)
|
|
22
|
+
], Article.prototype, "title", void 0);
|
|
23
|
+
__decorate([
|
|
24
|
+
(0, table_1.Field)("number"),
|
|
25
|
+
__metadata("design:type", Number)
|
|
26
|
+
], Article.prototype, "views", void 0);
|
|
27
|
+
const ArticleModel = (0, model_1.BasicDataModel)(Article, "articles");
|
|
28
|
+
describe("Row forms", () => {
|
|
29
|
+
it("reads a localized field given per locale", () => {
|
|
30
|
+
const article = ArticleModel.fromPlainData({
|
|
31
|
+
title: { en: "Hello", fr: "Salut" },
|
|
32
|
+
}).localize("*");
|
|
33
|
+
(0, chai_1.expect)(article.localize("fr").title).to.equal("Salut");
|
|
34
|
+
(0, chai_1.expect)(article.localize("en").title).to.equal("Hello");
|
|
35
|
+
});
|
|
36
|
+
it("locks a value given in the plain form once its locale is known", () => {
|
|
37
|
+
const article = ArticleModel.fromPlainData({
|
|
38
|
+
title: "Bonjour",
|
|
39
|
+
views: 2,
|
|
40
|
+
}).localize("fr");
|
|
41
|
+
(0, chai_1.expect)(ArticleModel.toDatabase(article)._internal?.data.title).to.deep.equal({ fr: "Bonjour" });
|
|
42
|
+
});
|
|
43
|
+
it("leaves the locked fields out of the plain form", () => {
|
|
44
|
+
const article = ArticleModel.fromPlainData({ title: "Hi" }).localize("en");
|
|
45
|
+
const plain = (0, common_1.toPlainData)(article);
|
|
46
|
+
(0, chai_1.expect)(plain).to.deep.equal({ title: "Hi" });
|
|
47
|
+
});
|
|
48
|
+
it("gives back a stored row as an instance of its table", () => {
|
|
49
|
+
const written = ArticleModel.fromPlainData({
|
|
50
|
+
title: "Hi",
|
|
51
|
+
views: 3,
|
|
52
|
+
}).localize("en");
|
|
53
|
+
const read = (0, common_1.fromDatabase)((0, common_1.toDatabase)(written), Article);
|
|
54
|
+
(0, chai_1.expect)(read).to.be.instanceOf(Article);
|
|
55
|
+
(0, chai_1.expect)(read.views).to.equal(3);
|
|
56
|
+
(0, chai_1.expect)(read.localize("en").title).to.equal("Hi");
|
|
57
|
+
});
|
|
58
|
+
});
|
|
59
|
+
//# sourceMappingURL=row_forms.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"row_forms.test.js","sourceRoot":"","sources":["../../src/tests/row_forms.test.ts"],"names":[],"mappings":";;;;;;;;;;;AAAA,+BAA8B;AAE9B,oCAA0C;AAC1C,4DAA4E;AAC5E,gDAA4E;AAC5E,oCAAwC;AAExC,MAAM,OAAQ,SAAQ,aAAK,CAAC,IAAI,CAAC,mCAAoB,CAAC;CAMrD;AAJS;IADP,IAAA,wBAAS,EAAC,EAAE,cAAc,EAAE,IAAI,EAAE,CAAC;;sCACd;AAGd;IADP,IAAA,aAAK,EAAC,QAAQ,CAAC;;sCACM;AAGxB,MAAM,YAAY,GAAG,IAAA,sBAAc,EAAC,OAAO,EAAE,UAAU,CAAC,CAAC;AAEzD,QAAQ,CAAC,WAAW,EAAE,GAAG,EAAE;IACzB,EAAE,CAAC,0CAA0C,EAAE,GAAG,EAAE;QAClD,MAAM,OAAO,GAAG,YAAY,CAAC,aAAa,CAAC;YACzC,KAAK,EAAE,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,OAAO,EAAE;SACpC,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;QAEjB,IAAA,aAAM,EAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QACvD,IAAA,aAAM,EAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IACzD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,gEAAgE,EAAE,GAAG,EAAE;QACxE,MAAM,OAAO,GAAG,YAAY,CAAC,aAAa,CAAC;YACzC,KAAK,EAAE,SAAS;YAChB,KAAK,EAAE,CAAC;SACT,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QAElB,IAAA,aAAM,EACJ,YAAY,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,SAAS,EAAE,IAAI,CAAC,KAAK,CACvD,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,SAAS,EAAE,CAAC,CAAC;IACrC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,gDAAgD,EAAE,GAAG,EAAE;QACxD,MAAM,OAAO,GAAG,YAAY,CAAC,aAAa,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QAE3E,MAAM,KAAK,GAAG,IAAA,oBAAW,EAAC,OAAO,CAAC,CAAC;QAEnC,IAAA,aAAM,EAAC,KAAK,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IAC/C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qDAAqD,EAAE,GAAG,EAAE;QAC7D,MAAM,OAAO,GAAG,YAAY,CAAC,aAAa,CAAC;YACzC,KAAK,EAAE,IAAI;YACX,KAAK,EAAE,CAAC;SACT,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QAElB,MAAM,IAAI,GAAG,IAAA,qBAAY,EAAC,IAAA,mBAAU,EAAC,OAAO,CAAC,EAAE,OAAO,CAAC,CAAC;QAExD,IAAA,aAAM,EAAC,IAAI,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;QACvC,IAAA,aAAM,EAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QAC/B,IAAA,aAAM,EAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IACnD,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const chai_1 = require("chai");
|
|
4
|
+
const table_1 = require("../table");
|
|
5
|
+
const common_1 = require("../common");
|
|
6
|
+
/**
|
|
7
|
+
* The table metadata as copies 0.1.8 and 0.1.9 of the package store it under
|
|
8
|
+
* the shared metadata key, before `uniqueIndexes` was added to its shape.
|
|
9
|
+
*/
|
|
10
|
+
class LegacyDatumStaticMetadata {
|
|
11
|
+
tableName;
|
|
12
|
+
schemaName;
|
|
13
|
+
indexes = {};
|
|
14
|
+
crossInstanceIndexes = new Set();
|
|
15
|
+
fields = {};
|
|
16
|
+
primary = "_id";
|
|
17
|
+
generator;
|
|
18
|
+
schema;
|
|
19
|
+
addIndex(key, group, isCrossInstance = false) {
|
|
20
|
+
if (!Object.hasOwn(this.indexes, group)) {
|
|
21
|
+
this.indexes[group] = [];
|
|
22
|
+
}
|
|
23
|
+
this.indexes[group].push(key);
|
|
24
|
+
if (isCrossInstance) {
|
|
25
|
+
this.crossInstanceIndexes.add(group);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
function declaredByLegacyCopy(tableClass) {
|
|
30
|
+
const legacy = new LegacyDatumStaticMetadata();
|
|
31
|
+
legacy.tableName = "legacy_rows";
|
|
32
|
+
legacy.schemaName = "legacy-schema";
|
|
33
|
+
legacy.primary = "code";
|
|
34
|
+
legacy.addIndex("email", "email");
|
|
35
|
+
legacy.addIndex("name", "search", true);
|
|
36
|
+
legacy.addIndex("city", "search");
|
|
37
|
+
Reflect.defineMetadata(common_1.DatumStaticMetadata.key, legacy, tableClass);
|
|
38
|
+
return legacy;
|
|
39
|
+
}
|
|
40
|
+
describe("Metadata - stored by an older copy of the package", () => {
|
|
41
|
+
it("reads the metadata as the current shape", async () => {
|
|
42
|
+
class Row extends table_1.Table {
|
|
43
|
+
}
|
|
44
|
+
declaredByLegacyCopy(Row);
|
|
45
|
+
const metadata = (0, common_1.getMetadata)(Row, common_1.DatumStaticMetadata);
|
|
46
|
+
(0, chai_1.expect)(metadata).to.be.instanceOf(common_1.DatumStaticMetadata);
|
|
47
|
+
(0, chai_1.expect)([...metadata.uniqueIndexes]).to.deep.equal([]);
|
|
48
|
+
(0, chai_1.expect)(metadata.uniqueIndexes.has("email")).to.equal(false);
|
|
49
|
+
});
|
|
50
|
+
it("keeps what the older copy stored", async () => {
|
|
51
|
+
class Row extends table_1.Table {
|
|
52
|
+
}
|
|
53
|
+
declaredByLegacyCopy(Row);
|
|
54
|
+
const metadata = (0, common_1.getMetadata)(Row, common_1.DatumStaticMetadata);
|
|
55
|
+
(0, chai_1.expect)(metadata.tableName).to.equal("legacy_rows");
|
|
56
|
+
(0, chai_1.expect)(metadata.schemaName).to.equal("legacy-schema");
|
|
57
|
+
(0, chai_1.expect)(metadata.primary).to.equal("code");
|
|
58
|
+
(0, chai_1.expect)(metadata.indexes).to.deep.equal({
|
|
59
|
+
email: ["email"],
|
|
60
|
+
search: ["name", "city"],
|
|
61
|
+
});
|
|
62
|
+
(0, chai_1.expect)([...metadata.crossInstanceIndexes]).to.deep.equal(["search"]);
|
|
63
|
+
});
|
|
64
|
+
it("answers the same metadata on every read", async () => {
|
|
65
|
+
class Row extends table_1.Table {
|
|
66
|
+
}
|
|
67
|
+
declaredByLegacyCopy(Row);
|
|
68
|
+
(0, chai_1.expect)((0, common_1.getMetadata)(Row, common_1.DatumStaticMetadata)).to.equal((0, common_1.getMetadata)(Row, common_1.DatumStaticMetadata));
|
|
69
|
+
});
|
|
70
|
+
it("records a unique index declared after the older copy", async () => {
|
|
71
|
+
class Row extends table_1.Table {
|
|
72
|
+
}
|
|
73
|
+
declaredByLegacyCopy(Row);
|
|
74
|
+
(0, table_1.Index)({ unique: true })(Row.prototype, "code");
|
|
75
|
+
const metadata = (0, common_1.getMetadata)(Row, common_1.DatumStaticMetadata);
|
|
76
|
+
(0, chai_1.expect)([...metadata.uniqueIndexes]).to.deep.equal(["code"]);
|
|
77
|
+
(0, chai_1.expect)(metadata.indexes.code).to.deep.equal(["code"]);
|
|
78
|
+
});
|
|
79
|
+
it("starts a subclass from the metadata the older copy stored", async () => {
|
|
80
|
+
class Base extends table_1.Table {
|
|
81
|
+
}
|
|
82
|
+
declaredByLegacyCopy(Base);
|
|
83
|
+
class Child extends Base {
|
|
84
|
+
}
|
|
85
|
+
const metadata = (0, common_1.getMetadata)(Child, common_1.DatumStaticMetadata);
|
|
86
|
+
(0, chai_1.expect)(metadata).to.be.instanceOf(common_1.DatumStaticMetadata);
|
|
87
|
+
(0, chai_1.expect)(metadata.uniqueIndexes.has("email")).to.equal(false);
|
|
88
|
+
(0, chai_1.expect)(metadata.indexes).to.have.property("email");
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
//# sourceMappingURL=stored_metadata.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stored_metadata.test.js","sourceRoot":"","sources":["../../src/tests/stored_metadata.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
const chai_1 = require("chai");
|
|
13
|
+
const interface_database_1 = require("@antelopejs/interface-database");
|
|
14
|
+
const common_1 = require("../common");
|
|
15
|
+
const bound_schema_1 = require("../internal/bound-schema");
|
|
16
|
+
const schema_1 = require("../schema");
|
|
17
|
+
const database_1 = require("../database");
|
|
18
|
+
const model_1 = require("../model");
|
|
19
|
+
const table_1 = require("../table");
|
|
20
|
+
describe("Schema binding - subclasses of a table", () => {
|
|
21
|
+
it("binds a subclass whose model is built before RegisterSchema ran", async () => {
|
|
22
|
+
let Users = class Users extends table_1.Table {
|
|
23
|
+
};
|
|
24
|
+
__decorate([
|
|
25
|
+
(0, table_1.Field)("string"),
|
|
26
|
+
__metadata("design:type", String)
|
|
27
|
+
], Users.prototype, "name", void 0);
|
|
28
|
+
Users = __decorate([
|
|
29
|
+
(0, schema_1.RegisterTable)("binding_users", "binding-before-schema")
|
|
30
|
+
], Users);
|
|
31
|
+
class Admin extends Users {
|
|
32
|
+
}
|
|
33
|
+
const AdminModel = (0, model_1.BasicDataModel)(Admin);
|
|
34
|
+
await (0, database_1.RegisterSchema)("binding-before-schema");
|
|
35
|
+
const model = (0, model_1.GetModel)(AdminModel, "binding-instance");
|
|
36
|
+
(0, chai_1.expect)(model.database.build()[0]).to.deep.include({
|
|
37
|
+
stage: "schema",
|
|
38
|
+
options: { id: "binding-before-schema" },
|
|
39
|
+
});
|
|
40
|
+
(0, chai_1.expect)(Admin.table().build()[0]).to.deep.include({
|
|
41
|
+
stage: "schema",
|
|
42
|
+
options: { id: "binding-before-schema" },
|
|
43
|
+
});
|
|
44
|
+
});
|
|
45
|
+
it("binds a subclass declared after RegisterSchema ran", async () => {
|
|
46
|
+
let Users = class Users extends table_1.Table {
|
|
47
|
+
};
|
|
48
|
+
__decorate([
|
|
49
|
+
(0, table_1.Field)("string"),
|
|
50
|
+
__metadata("design:type", String)
|
|
51
|
+
], Users.prototype, "name", void 0);
|
|
52
|
+
Users = __decorate([
|
|
53
|
+
(0, schema_1.RegisterTable)("binding_late_users", "binding-after-schema")
|
|
54
|
+
], Users);
|
|
55
|
+
await (0, database_1.RegisterSchema)("binding-after-schema");
|
|
56
|
+
class Admin extends Users {
|
|
57
|
+
}
|
|
58
|
+
const model = (0, model_1.GetModel)((0, model_1.BasicDataModel)(Admin), "binding-instance");
|
|
59
|
+
(0, chai_1.expect)(model.database.build()[0]).to.deep.include({
|
|
60
|
+
stage: "schema",
|
|
61
|
+
options: { id: "binding-after-schema" },
|
|
62
|
+
});
|
|
63
|
+
(0, chai_1.expect)(Admin.table().build()[0]).to.deep.include({
|
|
64
|
+
stage: "schema",
|
|
65
|
+
options: { id: "binding-after-schema" },
|
|
66
|
+
});
|
|
67
|
+
});
|
|
68
|
+
it("binds a subclass that registers its own table to its own schema", async () => {
|
|
69
|
+
let Parent = class Parent extends table_1.Table {
|
|
70
|
+
};
|
|
71
|
+
__decorate([
|
|
72
|
+
(0, table_1.Field)("string"),
|
|
73
|
+
__metadata("design:type", String)
|
|
74
|
+
], Parent.prototype, "name", void 0);
|
|
75
|
+
Parent = __decorate([
|
|
76
|
+
(0, schema_1.RegisterTable)("binding_parents", "binding-parent-schema")
|
|
77
|
+
], Parent);
|
|
78
|
+
let Child = class Child extends Parent {
|
|
79
|
+
};
|
|
80
|
+
Child = __decorate([
|
|
81
|
+
(0, schema_1.RegisterTable)("binding_children", "binding-child-schema")
|
|
82
|
+
], Child);
|
|
83
|
+
await (0, database_1.RegisterSchema)("binding-parent-schema");
|
|
84
|
+
await (0, database_1.RegisterSchema)("binding-child-schema");
|
|
85
|
+
(0, chai_1.expect)(Parent.table().build()[0]).to.deep.include({
|
|
86
|
+
stage: "schema",
|
|
87
|
+
options: { id: "binding-parent-schema" },
|
|
88
|
+
});
|
|
89
|
+
(0, chai_1.expect)(Child.table().build()[0]).to.deep.include({
|
|
90
|
+
stage: "schema",
|
|
91
|
+
options: { id: "binding-child-schema" },
|
|
92
|
+
});
|
|
93
|
+
});
|
|
94
|
+
it("follows the schema its parent is bound to when RegisterSchema runs again", async () => {
|
|
95
|
+
let Users = class Users extends table_1.Table {
|
|
96
|
+
};
|
|
97
|
+
__decorate([
|
|
98
|
+
(0, table_1.Field)("string"),
|
|
99
|
+
__metadata("design:type", String)
|
|
100
|
+
], Users.prototype, "name", void 0);
|
|
101
|
+
Users = __decorate([
|
|
102
|
+
(0, schema_1.RegisterTable)("binding_rebound", "binding-rebound-schema")
|
|
103
|
+
], Users);
|
|
104
|
+
await (0, database_1.RegisterSchema)("binding-rebound-schema");
|
|
105
|
+
class Admin extends Users {
|
|
106
|
+
}
|
|
107
|
+
const adminMetadata = (0, common_1.getMetadata)(Admin, common_1.DatumStaticMetadata);
|
|
108
|
+
const first = (0, bound_schema_1.boundSchema)(adminMetadata);
|
|
109
|
+
await (0, database_1.RegisterSchema)("binding-rebound-schema");
|
|
110
|
+
const second = interface_database_1.Schema.get("binding-rebound-schema");
|
|
111
|
+
(0, chai_1.expect)(second).to.not.equal(first);
|
|
112
|
+
(0, chai_1.expect)((0, bound_schema_1.boundSchema)(adminMetadata)).to.equal(second);
|
|
113
|
+
});
|
|
114
|
+
});
|
|
115
|
+
//# sourceMappingURL=subclass_schema_binding.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"subclass_schema_binding.test.js","sourceRoot":"","sources":["../../src/tests/subclass_schema_binding.test.ts"],"names":[],"mappings":"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"}
|
package/dist/tests/table.test.js
CHANGED
|
@@ -9,6 +9,7 @@ var __metadata = (this && this.__metadata) || function (k, v) {
|
|
|
9
9
|
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
10
|
};
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
const node_assert_1 = require("node:assert");
|
|
12
13
|
const chai_1 = require("chai");
|
|
13
14
|
const common_1 = require("../modifiers/common");
|
|
14
15
|
const table_1 = require("../table");
|
|
@@ -68,6 +69,21 @@ describe("Table - decorators", () => {
|
|
|
68
69
|
(0, chai_1.expect)(metadata.indexes.user_search).to.deep.equal(["name", "email"]);
|
|
69
70
|
(0, chai_1.expect)(metadata.indexes.age_range).to.deep.equal(["age"]);
|
|
70
71
|
});
|
|
72
|
+
it("refuses an index on a symbol-keyed field", () => {
|
|
73
|
+
const secret = Symbol("secret");
|
|
74
|
+
const declare = () => {
|
|
75
|
+
var _a;
|
|
76
|
+
class TestTable extends table_1.Table {
|
|
77
|
+
[_a = secret];
|
|
78
|
+
}
|
|
79
|
+
__decorate([
|
|
80
|
+
(0, table_1.Index)(),
|
|
81
|
+
__metadata("design:type", String)
|
|
82
|
+
], TestTable.prototype, _a, void 0);
|
|
83
|
+
return TestTable;
|
|
84
|
+
};
|
|
85
|
+
(0, chai_1.expect)(declare).to.throw(node_assert_1.AssertionError);
|
|
86
|
+
});
|
|
71
87
|
it("creates table with fixture data", async () => {
|
|
72
88
|
const testData = [
|
|
73
89
|
{ id: "1", name: "Test User 1" },
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"table.test.js","sourceRoot":"","sources":["../../src/tests/table.test.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"table.test.js","sourceRoot":"","sources":["../../src/tests/table.test.ts"],"names":[],"mappings":"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"}
|
package/docs/1.introduction.md
CHANGED
|
@@ -1,21 +1,25 @@
|
|
|
1
|
-
|
|
1
|
+
---
|
|
2
|
+
title: Define tables and work with models
|
|
3
|
+
description: Describe a table as a TypeScript class, register its schema, and save and read a first row through a typed model.
|
|
4
|
+
mode: how-to
|
|
5
|
+
---
|
|
2
6
|
|
|
3
7
|
## Overview
|
|
4
8
|
|
|
5
|
-
|
|
9
|
+
`@antelopejs/interface-database-decorators` describes tables as TypeScript classes and reads and writes converted rows through models. It builds on AQL (`@antelopejs/interface-database`) and adds field modifiers and model injection into API controllers.
|
|
6
10
|
|
|
7
11
|
## From a table class to a stored record
|
|
8
12
|
|
|
9
13
|
1. **Describe the table.** Extend `Table`, declare fields and indexes, and register the class with `@RegisterTable("users", "myapp")`. See [table definitions](./2.table-definitions.md).
|
|
10
|
-
2. **Bind the schema.** Import the table declarations, then call `await RegisterSchema("myapp")` from their declaring module.
|
|
11
|
-
3. **Create the model.** Use `BasicDataModel(User)`
|
|
12
|
-
4. **Write and read through the model.** Model operations apply
|
|
14
|
+
2. **Bind the schema.** Import the table declarations, then call `await RegisterSchema("myapp")` from their declaring module. The call needs a configured database module. It provisions the tables and inserts fixtures, so it writes to the database.
|
|
15
|
+
3. **Create the model.** Use `BasicDataModel(User)` with a `SchemaInstance`, or call `GetModel` once the table is bound. See [data models](./4.data-models.md).
|
|
16
|
+
4. **Write and read through the model.** Model operations apply the conversions and the modifier events. To compose an AQL query yourself, use `model.table`.
|
|
13
17
|
|
|
14
|
-
Keep schema IDs and instance IDs
|
|
18
|
+
Keep schema IDs and instance IDs apart. `myapp` names the table definitions, and an instance ID selects the database instance a model uses. `GetModel` throws for a table class that `RegisterSchema` has not bound, unless a schema of the class's schema name already exists.
|
|
15
19
|
|
|
16
20
|
### Save and retrieve a note
|
|
17
21
|
|
|
18
|
-
In a module with a configured database
|
|
22
|
+
In a module with a configured database module, import this declaration, then call `tryNote()` during initialization. Use a disposable development database, because `RegisterSchema` provisions the schema and `insert` writes a row.
|
|
19
23
|
|
|
20
24
|
```ts docs-check
|
|
21
25
|
import {
|
|
@@ -45,7 +49,7 @@ export async function tryNote() {
|
|
|
45
49
|
}
|
|
46
50
|
```
|
|
47
51
|
|
|
48
|
-
The model uses the default instance of the schema bound to `Note`.
|
|
52
|
+
The model uses the default instance of the schema bound to `Note`. Each run inserts a new note, so keep the inserted ID if you extend this exercise with `update` or `delete`. In an application, register the schema once during initialization, not on each request.
|
|
49
53
|
|
|
50
54
|
## Choose the layer for your task
|
|
51
55
|
|
|
@@ -54,23 +58,23 @@ The model uses the default instance of the schema bound to `Note`. Keep the inse
|
|
|
54
58
|
| Describe storage fields and indexes | [Table definitions](./2.table-definitions.md) | Declaring a class is separate from registering its schema. |
|
|
55
59
|
| Encrypt, hash, or localize fields | [Table modifiers](./3.table-modifiers.md) | Conversion events determine when transformations run. |
|
|
56
60
|
| Read or write converted records | [Data models](./4.data-models.md) | Reads return converted records, not chainable queries. |
|
|
57
|
-
| Select a model in an HTTP request | [Parameter decoration](./5.parameter-decoration.md) | The instance ID selects a binding
|
|
61
|
+
| Select a model in an HTTP request | [Parameter decoration](./5.parameter-decoration.md) | The instance ID selects a binding. It does not authorize access. |
|
|
58
62
|
|
|
59
|
-
Start without modifiers until the schema and model work together.
|
|
63
|
+
Start without modifiers until the schema and the model work together. Validation is opt-in. A string-token `@Field` describes storage only, and codec validation needs io-ts codecs and the model's `validate` option.
|
|
60
64
|
|
|
61
65
|
## Dependencies
|
|
62
66
|
|
|
63
|
-
|
|
67
|
+
The package depends on these packages:
|
|
64
68
|
|
|
65
|
-
- [
|
|
66
|
-
- [
|
|
67
|
-
- [
|
|
68
|
-
- [
|
|
69
|
-
- [
|
|
69
|
+
- [`@antelopejs/interface-database`](https://github.com/AntelopeJS/interface-database) is the database query interface (AQL).
|
|
70
|
+
- [`@antelopejs/interface-api`](https://github.com/AntelopeJS/interface-api) provides the API controllers that `@Model` injects into.
|
|
71
|
+
- [`@antelopejs/interface-core`](https://github.com/AntelopeJS/interface-core) provides the decorator factories.
|
|
72
|
+
- [`reflect-metadata`](https://www.npmjs.com/package/reflect-metadata) stores the decorator metadata.
|
|
73
|
+
- [`randomstring`](https://www.npmjs.com/package/randomstring) generates the salt of a `@Hashed` field that sets an `algorithm`.
|
|
70
74
|
|
|
71
75
|
## Documentation
|
|
72
76
|
|
|
73
|
-
- [Table
|
|
74
|
-
- [Table
|
|
75
|
-
- [Data
|
|
76
|
-
- [Parameter
|
|
77
|
+
- [Table definitions](./2.table-definitions.md) covers the `Table` class and the `Field`, `Index`, `Relation`, `RegisterTable`, and `Fixture` decorators.
|
|
78
|
+
- [Table modifiers](./3.table-modifiers.md) covers encryption, hashing, and localization of fields, and custom modifiers.
|
|
79
|
+
- [Data models](./4.data-models.md) covers `BasicDataModel`, its CRUD methods, and the data conversions.
|
|
80
|
+
- [Parameter decoration](./5.parameter-decoration.md) covers the `Model` decorator, which injects a model into API controller methods.
|