@primate/core 0.5.0 → 0.6.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/lib/private/App.d.ts +263 -26
- package/lib/private/App.js +42 -14
- package/lib/private/Flags.d.ts +8 -4
- package/lib/private/Module.d.ts +4 -16
- package/lib/private/Module.js +1 -17
- package/lib/private/app/EnvSchema.d.ts +5 -0
- package/lib/private/app/EnvSchema.js +2 -0
- package/lib/private/app/Facade.browser.d.ts +11 -0
- package/lib/private/app/Facade.browser.js +19 -0
- package/lib/private/app/Facade.d.ts +272 -27
- package/lib/private/app/Facade.js +23 -0
- package/lib/private/build/client/index.js +8 -3
- package/lib/private/build/client/plugin/app-request.d.ts +4 -0
- package/lib/private/build/client/plugin/app-request.js +19 -0
- package/lib/private/build/client/plugin/view.d.ts +4 -0
- package/lib/private/build/client/plugin/view.js +13 -0
- package/lib/private/build/hook.d.ts +1 -2
- package/lib/private/build/hook.js +21 -16
- package/lib/private/build/index.d.ts +2 -1
- package/lib/private/build/index.js +20 -21
- package/lib/private/build/server/index.js +7 -9
- package/lib/private/build/server/plugin/app-request.d.ts +4 -0
- package/lib/private/build/server/plugin/app-request.js +19 -0
- package/lib/private/build/server/plugin/assets.js +1 -1
- package/lib/private/build/server/plugin/live-reload.js +9 -9
- package/lib/private/build/server/plugin/native-addons.js +4 -7
- package/lib/private/build/server/plugin/route.js +2 -2
- package/lib/private/build/server/plugin/store.js +9 -31
- package/lib/private/build/server/plugin/stores.js +11 -7
- package/lib/private/build/server/plugin/view.js +1 -1
- package/lib/private/build/shared/plugin/app-request.d.ts +4 -0
- package/lib/private/build/shared/plugin/app-request.js +19 -0
- package/lib/private/client/Data.d.ts +3 -2
- package/lib/private/{frontend → client}/Render.d.ts +1 -1
- package/lib/private/{frontend → client}/ViewResponse.d.ts +1 -1
- package/lib/private/client/app.js +1 -2
- package/lib/private/client/boot.d.ts +5 -0
- package/lib/private/client/boot.js +64 -0
- package/lib/private/client/create-form.d.ts +1 -0
- package/lib/private/client/create-form.js +19 -20
- package/lib/private/client/extract-issues.js +2 -1
- package/lib/private/client/http.d.ts +13 -0
- package/lib/private/client/http.js +57 -0
- package/lib/private/client/index.d.ts +23 -0
- package/lib/private/client/index.js +16 -0
- package/lib/private/client/navigate.d.ts +13 -0
- package/lib/private/client/navigate.js +67 -0
- package/lib/private/client/root.d.ts +9 -0
- package/lib/private/client/root.js +11 -0
- package/lib/private/client/submit.d.ts +2 -0
- package/lib/private/client/submit.js +41 -0
- package/lib/private/config/index.d.ts +7 -2
- package/lib/private/config/index.js +3 -2
- package/lib/private/config/schema.d.ts +82 -26
- package/lib/private/config/schema.js +17 -4
- package/lib/private/cookie.d.ts +12 -6
- package/lib/private/db/DB.d.ts +21 -5
- package/lib/private/db/DB.js +1 -0
- package/lib/private/db/MemoryDB.d.ts +2 -4
- package/lib/private/db/MemoryDB.js +40 -22
- package/lib/private/db/common.d.ts +7 -0
- package/lib/private/db/common.js +31 -0
- package/lib/private/db/errors.d.ts +104 -0
- package/lib/private/db/errors.js +237 -0
- package/lib/private/db/migrate/apply.d.ts +2 -0
- package/lib/private/db/migrate/apply.js +32 -0
- package/lib/private/db/migrate/bundle.d.ts +3 -0
- package/lib/private/db/migrate/bundle.js +22 -0
- package/lib/private/db/migrate/create.d.ts +2 -0
- package/lib/private/db/migrate/create.js +154 -0
- package/lib/private/db/migrate/index.d.ts +10 -0
- package/lib/private/db/migrate/index.js +6 -0
- package/lib/private/db/migrate/status.d.ts +2 -0
- package/lib/private/db/migrate/status.js +38 -0
- package/lib/private/db/migrate/store.d.ts +5 -0
- package/lib/private/db/migrate/store.js +33 -0
- package/lib/private/db/sql.js +3 -3
- package/lib/private/db/test.js +461 -95
- package/lib/private/errors.d.ts +88 -0
- package/lib/private/errors.js +211 -0
- package/lib/private/frontend.d.ts +72 -0
- package/lib/private/frontend.js +245 -0
- package/lib/private/i18n/Formatter.js +2 -2
- package/lib/private/i18n/errors.d.ts +16 -0
- package/lib/private/i18n/errors.js +27 -0
- package/lib/private/i18n/module.d.ts +3 -0
- package/lib/private/i18n/module.js +115 -0
- package/lib/private/i18n/schema.d.ts +10 -5
- package/lib/private/i18n/validate.js +5 -7
- package/lib/private/index.d.ts +14 -0
- package/lib/private/index.js +2 -0
- package/lib/private/log.js +6 -5
- package/lib/private/module/Setup.d.ts +21 -0
- package/lib/private/module/Setup.js +2 -0
- package/lib/private/module/create.d.ts +16 -0
- package/lib/private/module/create.js +28 -0
- package/lib/private/orm/ExtractSchema.d.ts +9 -0
- package/lib/private/orm/ExtractSchema.js +2 -0
- package/lib/private/orm/ForeignKey.d.ts +5 -2
- package/lib/private/orm/ForeignKey.js +3 -0
- package/lib/private/orm/PrimaryKey.d.ts +5 -3
- package/lib/private/orm/PrimaryKey.js +9 -6
- package/lib/private/orm/StoreInput.d.ts +10 -0
- package/lib/private/orm/StoreInput.js +2 -0
- package/lib/private/orm/key.d.ts +6 -6
- package/lib/private/orm/key.js +7 -3
- package/lib/private/orm/parse.d.ts +5 -4
- package/lib/private/orm/parse.js +2 -2
- package/lib/private/orm/relation.d.ts +2 -2
- package/lib/private/orm/{Store.d.ts → store.d.ts} +33 -17
- package/lib/private/orm/{Store.js → store.js} +91 -67
- package/lib/private/paths.js +3 -3
- package/lib/private/request/RequestBag.d.ts +4 -0
- package/lib/private/request/RequestBag.js +5 -2
- package/lib/private/request/RequestBody.d.ts +6 -9
- package/lib/private/request/RequestBody.js +49 -54
- package/lib/private/request/RequestFacade.d.ts +3 -8
- package/lib/private/request/RequestPublic.d.ts +9 -0
- package/lib/private/request/RequestPublic.js +2 -0
- package/lib/private/request/RequestView.d.ts +11 -0
- package/lib/private/request/RequestView.js +3 -0
- package/lib/private/request/handle.d.ts +4 -0
- package/lib/private/request/handle.js +18 -0
- package/lib/private/request/parse.js +1 -0
- package/lib/private/request/route.js +8 -9
- package/lib/private/request/router.js +21 -49
- package/lib/private/request/storage.d.ts +4 -0
- package/lib/private/request/storage.js +5 -0
- package/lib/private/response/ResponseFunction.d.ts +1 -1
- package/lib/private/response/binary.js +1 -1
- package/lib/private/response/error.d.ts +1 -1
- package/lib/private/response/error.js +1 -1
- package/lib/private/response/json.d.ts +1 -1
- package/lib/private/response/json.js +1 -1
- package/lib/private/response/redirect.d.ts +5 -5
- package/lib/private/response/redirect.js +8 -9
- package/lib/private/response/respond.js +9 -7
- package/lib/private/response/sse.d.ts +1 -1
- package/lib/private/response/sse.js +1 -1
- package/lib/private/response/text.d.ts +1 -1
- package/lib/private/response/text.js +1 -1
- package/lib/private/response/view.d.ts +1 -1
- package/lib/private/response/view.js +6 -13
- package/lib/private/response/ws.d.ts +1 -1
- package/lib/private/route/router.d.ts +3 -3
- package/lib/private/route/router.js +7 -10
- package/lib/private/serve/App.d.ts +6 -7
- package/lib/private/serve/App.js +52 -43
- package/lib/private/serve/Init.d.ts +2 -2
- package/lib/private/serve/dev-module.d.ts +2 -0
- package/lib/private/serve/dev-module.js +34 -0
- package/lib/private/serve/hook.d.ts +1 -2
- package/lib/private/serve/hook.js +2 -3
- package/lib/private/serve/index.d.ts +1 -1
- package/lib/private/serve/index.js +32 -2
- package/lib/private/server/TAG.d.ts +3 -0
- package/lib/private/server/TAG.js +2 -0
- package/lib/private/server/index.d.ts +5 -0
- package/lib/private/server/index.js +6 -0
- package/lib/private/session/SessionHandle.js +2 -1
- package/lib/private/session/index.d.ts +1 -1
- package/lib/private/session/module.d.ts +3 -0
- package/lib/private/session/module.js +114 -0
- package/lib/private/session/schema.d.ts +17 -9
- package/lib/private/session/schema.js +9 -5
- package/lib/private/target/Manager.js +6 -12
- package/lib/public/client.d.ts +2 -13
- package/lib/public/client.js +1 -9
- package/lib/public/db/errors.d.ts +2 -0
- package/lib/public/db/errors.js +2 -0
- package/lib/public/db/migrate.d.ts +2 -0
- package/lib/public/db/migrate.js +2 -0
- package/lib/public/db.d.ts +3 -3
- package/lib/public/frontend.d.ts +3 -0
- package/lib/public/frontend.js +2 -0
- package/lib/public/index.d.ts +2 -0
- package/lib/public/index.js +2 -0
- package/lib/public/orm/store.d.ts +2 -0
- package/lib/public/orm/store.js +2 -0
- package/lib/public/request/server.d.ts +5 -0
- package/lib/public/request/server.js +7 -0
- package/lib/public/response.d.ts +4 -4
- package/lib/public/server.d.ts +3 -0
- package/lib/public/server.js +2 -0
- package/package.json +30 -25
- package/lib/private/AppError.d.ts +0 -4
- package/lib/private/AppError.js +0 -8
- package/lib/private/backend/Module.d.ts +0 -18
- package/lib/private/backend/Module.js +0 -19
- package/lib/private/backend/TAG.d.ts +0 -3
- package/lib/private/backend/TAG.js +0 -2
- package/lib/private/build/server/plugin/db-default.d.ts +0 -4
- package/lib/private/build/server/plugin/db-default.js +0 -45
- package/lib/private/build/server/plugin/store-wrap.d.ts +0 -4
- package/lib/private/build/server/plugin/store-wrap.js +0 -33
- package/lib/private/client/spa/index.d.ts +0 -6
- package/lib/private/client/spa/index.js +0 -200
- package/lib/private/db/error.d.ts +0 -81
- package/lib/private/db/error.js +0 -199
- package/lib/private/db/symbol/wrap.d.ts +0 -3
- package/lib/private/db/symbol/wrap.js +0 -2
- package/lib/private/fail.d.ts +0 -3
- package/lib/private/fail.js +0 -5
- package/lib/private/frontend/Module.d.ts +0 -62
- package/lib/private/frontend/Module.js +0 -255
- package/lib/private/i18n/Module.d.ts +0 -16
- package/lib/private/i18n/Module.js +0 -133
- package/lib/private/module/BuildHook.d.ts +0 -5
- package/lib/private/module/BuildHook.js +0 -2
- package/lib/private/module/NextBuild.d.ts +0 -5
- package/lib/private/module/NextBuild.js +0 -2
- package/lib/private/module/NextServe.d.ts +0 -5
- package/lib/private/module/NextServe.js +0 -2
- package/lib/private/orm/Set.d.ts +0 -11
- package/lib/private/orm/Set.js +0 -2
- package/lib/private/orm/foreign.d.ts +0 -4
- package/lib/private/orm/foreign.js +0 -5
- package/lib/private/orm/primary.d.ts +0 -5
- package/lib/private/orm/primary.js +0 -5
- package/lib/private/orm/types.d.ts +0 -18
- package/lib/private/orm/types.js +0 -2
- package/lib/private/orm/wrap.d.ts +0 -5
- package/lib/private/orm/wrap.js +0 -5
- package/lib/private/reducer.d.ts +0 -24
- package/lib/private/reducer.js +0 -10
- package/lib/private/serve/module/Dev.d.ts +0 -11
- package/lib/private/serve/module/Dev.js +0 -32
- package/lib/private/serve/module/Handle.d.ts +0 -10
- package/lib/private/serve/module/Handle.js +0 -15
- package/lib/private/session/SessionModule.d.ts +0 -14
- package/lib/private/session/SessionModule.js +0 -122
- package/lib/public/App.d.ts +0 -2
- package/lib/public/App.js +0 -2
- package/lib/public/AppError.d.ts +0 -2
- package/lib/public/AppError.js +0 -2
- package/lib/public/BuildApp.d.ts +0 -2
- package/lib/public/BuildApp.js +0 -2
- package/lib/public/BuildHook.d.ts +0 -2
- package/lib/public/BuildHook.js +0 -2
- package/lib/public/Mode.d.ts +0 -2
- package/lib/public/Mode.js +0 -2
- package/lib/public/Module.d.ts +0 -2
- package/lib/public/Module.js +0 -2
- package/lib/public/Next.d.ts +0 -2
- package/lib/public/Next.js +0 -2
- package/lib/public/NextBuild.d.ts +0 -2
- package/lib/public/NextBuild.js +0 -2
- package/lib/public/NextHandle.d.ts +0 -2
- package/lib/public/NextHandle.js +0 -2
- package/lib/public/NextRoute.d.ts +0 -3
- package/lib/public/NextRoute.js +0 -2
- package/lib/public/NextServe.d.ts +0 -2
- package/lib/public/NextServe.js +0 -2
- package/lib/public/ServeApp.d.ts +0 -2
- package/lib/public/ServeApp.js +0 -2
- package/lib/public/Target.d.ts +0 -2
- package/lib/public/Target.js +0 -2
- package/lib/public/backend/Module.d.ts +0 -2
- package/lib/public/backend/Module.js +0 -2
- package/lib/public/backend/TAG.d.ts +0 -2
- package/lib/public/backend/TAG.js +0 -2
- package/lib/public/client/Data.d.ts +0 -2
- package/lib/public/client/Data.js +0 -2
- package/lib/public/client/spa.d.ts +0 -2
- package/lib/public/client/spa.js +0 -2
- package/lib/public/db/error.d.ts +0 -2
- package/lib/public/db/error.js +0 -2
- package/lib/public/fail.d.ts +0 -2
- package/lib/public/fail.js +0 -2
- package/lib/public/frontend/Module.d.ts +0 -2
- package/lib/public/frontend/Module.js +0 -2
- package/lib/public/frontend/Publish.d.ts +0 -2
- package/lib/public/frontend/Publish.js +0 -2
- package/lib/public/frontend/Render.d.ts +0 -2
- package/lib/public/frontend/Render.js +0 -2
- package/lib/public/frontend/ViewResponse.d.ts +0 -2
- package/lib/public/frontend/ViewResponse.js +0 -2
- package/lib/public/orm/Store.d.ts +0 -2
- package/lib/public/orm/Store.js +0 -2
- package/lib/public/orm/wrap.d.ts +0 -2
- package/lib/public/orm/wrap.js +0 -2
- package/lib/public/request.d.ts +0 -4
- package/lib/public/request.js +0 -2
- /package/lib/private/{frontend → client}/Publish.d.ts +0 -0
- /package/lib/private/{frontend → client}/Publish.js +0 -0
- /package/lib/private/{frontend → client}/Render.js +0 -0
- /package/lib/private/{frontend → client}/ServerData.d.ts +0 -0
- /package/lib/private/{frontend → client}/ServerData.js +0 -0
- /package/lib/private/{frontend → client}/ServerView.d.ts +0 -0
- /package/lib/private/{frontend → client}/ServerView.js +0 -0
- /package/lib/private/{frontend → client}/View.d.ts +0 -0
- /package/lib/private/{frontend → client}/View.js +0 -0
- /package/lib/private/{frontend → client}/ViewOptions.d.ts +0 -0
- /package/lib/private/{frontend → client}/ViewOptions.js +0 -0
- /package/lib/private/{frontend → client}/ViewResponse.js +0 -0
- /package/lib/private/client/{spa/storage.d.ts → storage.d.ts} +0 -0
- /package/lib/private/client/{spa/storage.js → storage.js} +0 -0
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import E from "#db/
|
|
2
|
-
import wrap from "#db/symbol/wrap";
|
|
1
|
+
import E from "#db/errors";
|
|
3
2
|
import parse from "#orm/parse";
|
|
4
3
|
import assert from "@rcompat/assert";
|
|
5
4
|
import is from "@rcompat/is";
|
|
@@ -64,35 +63,55 @@ const DATE_OPS = ["$before", "$after", "$ne"];
|
|
|
64
63
|
* document database table/collection. It pairs a Pema schema with a uniform
|
|
65
64
|
* CRUD/query API.
|
|
66
65
|
*/
|
|
67
|
-
export
|
|
66
|
+
export class Store {
|
|
68
67
|
#schema;
|
|
69
68
|
#type;
|
|
70
69
|
#types;
|
|
71
70
|
#nullables;
|
|
72
|
-
#db;
|
|
73
71
|
#name;
|
|
72
|
+
#db;
|
|
74
73
|
#pk;
|
|
75
74
|
#generate_pk;
|
|
76
75
|
#fks;
|
|
77
76
|
#relations;
|
|
78
|
-
|
|
79
|
-
|
|
77
|
+
#migrate;
|
|
78
|
+
constructor(init) {
|
|
79
|
+
const { pk, generate_pk, fks, schema } = parse(init.schema);
|
|
80
|
+
const { name, db, migrate } = init;
|
|
81
|
+
if (name === undefined)
|
|
82
|
+
throw E.store_name_required();
|
|
83
|
+
assert.string(name);
|
|
84
|
+
if (!VALID_IDENTIFIER.test(name))
|
|
85
|
+
throw E.identifier_invalid(name);
|
|
86
|
+
assert.defined(db, E.db_missing);
|
|
87
|
+
assert.dict(schema);
|
|
88
|
+
assert.maybe.boolean(migrate);
|
|
89
|
+
assert.maybe.dict(init.extend);
|
|
80
90
|
this.#schema = schema;
|
|
81
91
|
this.#type = new StoreType(schema, pk);
|
|
82
92
|
this.#types = Object.fromEntries(Object.entries(schema).map(([key, value]) => [key, value.datatype]));
|
|
83
|
-
this.#name =
|
|
84
|
-
this.#db =
|
|
93
|
+
this.#name = name;
|
|
94
|
+
this.#db = db;
|
|
85
95
|
this.#pk = pk;
|
|
86
96
|
this.#generate_pk = generate_pk;
|
|
87
97
|
this.#fks = fks;
|
|
88
|
-
this.#relations =
|
|
98
|
+
this.#relations = init.relations ?? {};
|
|
99
|
+
this.#migrate = migrate ?? true;
|
|
100
|
+
for (const relation of Object.keys(this.#relations)) {
|
|
101
|
+
if (relation in schema)
|
|
102
|
+
throw E.relation_conflicts_with_field(relation);
|
|
103
|
+
}
|
|
89
104
|
this.#nullables = new Set(Object.entries(this.#type.properties)
|
|
90
105
|
.filter(([, v]) => v.nullable)
|
|
91
106
|
.map(([k]) => k));
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
107
|
+
if (init.extend !== undefined) {
|
|
108
|
+
for (const [k, v] of Object.entries(init.extend)) {
|
|
109
|
+
if (k in this)
|
|
110
|
+
throw E.key_duplicate(k);
|
|
111
|
+
this[k] = v;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
registry.set(init.schema, this);
|
|
96
115
|
}
|
|
97
116
|
get #as() {
|
|
98
117
|
return {
|
|
@@ -102,14 +121,15 @@ export default class Store {
|
|
|
102
121
|
types: this.#types,
|
|
103
122
|
};
|
|
104
123
|
}
|
|
105
|
-
get
|
|
124
|
+
get table() {
|
|
106
125
|
const db = this.db;
|
|
107
|
-
const
|
|
108
|
-
|
|
109
|
-
|
|
126
|
+
const pk = {
|
|
127
|
+
name: this.#pk,
|
|
128
|
+
generate: this.#generate_pk,
|
|
129
|
+
};
|
|
110
130
|
return {
|
|
111
|
-
create: () => db.schema.create(
|
|
112
|
-
delete: () => db.schema.delete(name),
|
|
131
|
+
create: () => db.schema.create(this.#name, pk, this.#types),
|
|
132
|
+
delete: () => db.schema.delete(this.#name),
|
|
113
133
|
};
|
|
114
134
|
}
|
|
115
135
|
get infer() {
|
|
@@ -121,26 +141,32 @@ export default class Store {
|
|
|
121
141
|
get type() {
|
|
122
142
|
return this.#type;
|
|
123
143
|
}
|
|
124
|
-
|
|
125
|
-
this.#
|
|
126
|
-
|
|
127
|
-
|
|
144
|
+
get migrate() {
|
|
145
|
+
return this.#migrate;
|
|
146
|
+
}
|
|
147
|
+
get name() {
|
|
148
|
+
return this.#name;
|
|
149
|
+
}
|
|
150
|
+
get pk() {
|
|
151
|
+
return this.#pk;
|
|
128
152
|
}
|
|
129
153
|
get db() {
|
|
130
|
-
if (this.#db === undefined)
|
|
131
|
-
throw E.db_missing();
|
|
132
154
|
return this.#db;
|
|
133
155
|
}
|
|
134
156
|
get types() {
|
|
135
157
|
return this.#types;
|
|
136
158
|
}
|
|
137
|
-
|
|
138
|
-
const
|
|
139
|
-
if (
|
|
140
|
-
throw E.
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
159
|
+
#parse_pk(pkv) {
|
|
160
|
+
const pk = this.#pk;
|
|
161
|
+
if (pk === null)
|
|
162
|
+
throw E.pk_undefined(this.name);
|
|
163
|
+
try {
|
|
164
|
+
this.#schema[pk].parse(pkv);
|
|
165
|
+
}
|
|
166
|
+
catch {
|
|
167
|
+
throw E.pk_invalid(pkv);
|
|
168
|
+
}
|
|
169
|
+
return pk;
|
|
144
170
|
}
|
|
145
171
|
#parse_query(query, types) {
|
|
146
172
|
const { where, select, sort, limit } = query;
|
|
@@ -294,6 +320,12 @@ export default class Store {
|
|
|
294
320
|
if (!is.blob(value))
|
|
295
321
|
throw E.wrong_type("blob", k, value);
|
|
296
322
|
continue;
|
|
323
|
+
case "uuid":
|
|
324
|
+
case "uuid_v4":
|
|
325
|
+
case "uuid_v7":
|
|
326
|
+
if (!is.string(value))
|
|
327
|
+
throw E.wrong_type("string", k, value);
|
|
328
|
+
continue;
|
|
297
329
|
default:
|
|
298
330
|
throw E.where_invalid_value(k, value);
|
|
299
331
|
}
|
|
@@ -360,14 +392,11 @@ export default class Store {
|
|
|
360
392
|
* Check whether a record with the given primary key exists.
|
|
361
393
|
*/
|
|
362
394
|
async has(pkv) {
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
return (await this.count({ where: { [this.#pk]: pkv } })) === 1;
|
|
395
|
+
const pk = this.#parse_pk(pkv);
|
|
396
|
+
return (await this.count({ where: { [pk]: pkv } })) === 1;
|
|
366
397
|
}
|
|
367
398
|
async get(pkv, options) {
|
|
368
|
-
const pk = this.#
|
|
369
|
-
if (pk === null)
|
|
370
|
-
throw E.pk_undefined(this.name);
|
|
399
|
+
const pk = this.#parse_pk(pkv);
|
|
371
400
|
guard_options(options, ["select", "with"]);
|
|
372
401
|
this.#parse_query(options ?? {}, this.#types);
|
|
373
402
|
const $with = this.#with(options?.with);
|
|
@@ -376,8 +405,9 @@ export default class Store {
|
|
|
376
405
|
fields: options?.select ? [...options.select] : undefined,
|
|
377
406
|
with: $with,
|
|
378
407
|
});
|
|
379
|
-
|
|
380
|
-
|
|
408
|
+
const n = records.length;
|
|
409
|
+
assert.true(n <= 1, E.record_number_invalid(n, "get"));
|
|
410
|
+
if (n === 0) {
|
|
381
411
|
const err = E.record_not_found(pk, pkv);
|
|
382
412
|
err.not_found = true;
|
|
383
413
|
throw err;
|
|
@@ -442,29 +472,20 @@ export default class Store {
|
|
|
442
472
|
...this.#type.partial().parse(to_parse),
|
|
443
473
|
...nulls,
|
|
444
474
|
};
|
|
445
|
-
if (by_pk)
|
|
475
|
+
if (by_pk)
|
|
446
476
|
return this.#update_1(arg0, parsed);
|
|
447
|
-
}
|
|
448
477
|
const where = arg0.where;
|
|
449
478
|
if (where !== undefined)
|
|
450
479
|
this.#parse_where(where, this.#types);
|
|
451
480
|
return this.#update_n((where ?? {}), parsed);
|
|
452
481
|
}
|
|
453
482
|
async #update_1(pkv, set) {
|
|
454
|
-
const pk = this.#
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
const n = await this.db.update(this.#as, {
|
|
458
|
-
set: set,
|
|
459
|
-
where: { [pk]: pkv },
|
|
460
|
-
});
|
|
461
|
-
assert.true(n === 1, `${n} records updated instead of 1`);
|
|
483
|
+
const pk = this.#parse_pk(pkv);
|
|
484
|
+
const n = await this.db.update(this.#as, { set, where: { [pk]: pkv } });
|
|
485
|
+
assert.true(n === 1, E.record_number_invalid(n, "update"));
|
|
462
486
|
}
|
|
463
487
|
async #update_n(where, set) {
|
|
464
|
-
return await this.db.update(this.#as, {
|
|
465
|
-
set: set,
|
|
466
|
-
where: where,
|
|
467
|
-
});
|
|
488
|
+
return await this.db.update(this.#as, { set, where });
|
|
468
489
|
}
|
|
469
490
|
async delete(pkv_or_options) {
|
|
470
491
|
if (is.dict(pkv_or_options)) {
|
|
@@ -477,11 +498,9 @@ export default class Store {
|
|
|
477
498
|
return this.#delete_1(pkv_or_options);
|
|
478
499
|
}
|
|
479
500
|
async #delete_1(pkv) {
|
|
480
|
-
const pk = this.#
|
|
481
|
-
if (pk === null)
|
|
482
|
-
throw E.pk_undefined(this.name);
|
|
501
|
+
const pk = this.#parse_pk(pkv);
|
|
483
502
|
const n = await this.db.delete(this.#as, { where: { [pk]: pkv } });
|
|
484
|
-
assert.true(n === 1,
|
|
503
|
+
assert.true(n === 1, E.record_number_invalid(n, "delete"));
|
|
485
504
|
}
|
|
486
505
|
async #delete_n(where) {
|
|
487
506
|
return await this.db.delete(this.#as, { where: where });
|
|
@@ -495,7 +514,7 @@ export default class Store {
|
|
|
495
514
|
this.#parse_query(options ?? {}, this.#types);
|
|
496
515
|
const result = await this.db.read(this.#as, {
|
|
497
516
|
where: options?.where ?? {},
|
|
498
|
-
fields: options?.select ? [...options.select] : undefined,
|
|
517
|
+
fields: options?.select !== undefined ? [...options.select] : undefined,
|
|
499
518
|
limit: options?.limit,
|
|
500
519
|
sort: options?.sort,
|
|
501
520
|
with: this.#with(options?.with),
|
|
@@ -506,13 +525,18 @@ export default class Store {
|
|
|
506
525
|
return this.#type.toJSON();
|
|
507
526
|
}
|
|
508
527
|
extend(extensor) {
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
528
|
+
return new Store({
|
|
529
|
+
name: this.name,
|
|
530
|
+
db: this.db,
|
|
531
|
+
schema: this.#schema,
|
|
532
|
+
relations: this.#relations,
|
|
533
|
+
migrate: false,
|
|
534
|
+
extend: extensor(this),
|
|
535
|
+
});
|
|
516
536
|
}
|
|
517
537
|
}
|
|
518
|
-
|
|
538
|
+
function store(init) {
|
|
539
|
+
return new Store(init);
|
|
540
|
+
}
|
|
541
|
+
export default store;
|
|
542
|
+
//# sourceMappingURL=store.js.map
|
package/lib/private/paths.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import E from "#errors";
|
|
2
2
|
import log from "#log";
|
|
3
3
|
async function resolve(root, config_paths) {
|
|
4
4
|
const tsconfig_path = root.join("tsconfig.json");
|
|
@@ -13,13 +13,13 @@ async function resolve(root, config_paths) {
|
|
|
13
13
|
const config = JSON.parse(text);
|
|
14
14
|
const ts_paths = config.compilerOptions?.paths ?? {};
|
|
15
15
|
if (config_paths !== undefined && Object.keys(ts_paths).length > 0) {
|
|
16
|
-
return
|
|
16
|
+
return E.config_tsconfig_has_paths();
|
|
17
17
|
}
|
|
18
18
|
// merge with defaults (user paths override)
|
|
19
19
|
return { ...ts_paths };
|
|
20
20
|
}
|
|
21
21
|
catch {
|
|
22
|
-
log.warn("
|
|
22
|
+
log.warn("failed to parse tsconfig.json, falling back to config");
|
|
23
23
|
}
|
|
24
24
|
}
|
|
25
25
|
if (config_paths !== undefined)
|
|
@@ -4,6 +4,9 @@ type Normalize = (key: string) => string;
|
|
|
4
4
|
interface Schema<T> {
|
|
5
5
|
parse(input: unknown): T;
|
|
6
6
|
}
|
|
7
|
+
interface CoercibleSchema<T> extends Schema<T> {
|
|
8
|
+
coerce(input: unknown): T;
|
|
9
|
+
}
|
|
7
10
|
type Options = {
|
|
8
11
|
normalize?: Normalize;
|
|
9
12
|
raw?: string;
|
|
@@ -67,6 +70,7 @@ export default class RequestBag {
|
|
|
67
70
|
* @throws Whatever the schema throws.
|
|
68
71
|
*/
|
|
69
72
|
parse<T>(schema: Schema<T>): T;
|
|
73
|
+
coerce<T>(schema: CoercibleSchema<T>): T;
|
|
70
74
|
/** Returns {@link raw}. Useful in template strings. */
|
|
71
75
|
toString(): string;
|
|
72
76
|
/**
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import E from "#errors";
|
|
2
2
|
import assert from "@rcompat/assert";
|
|
3
3
|
import fn from "@rcompat/fn";
|
|
4
4
|
export default class RequestBag {
|
|
@@ -72,7 +72,7 @@ export default class RequestBag {
|
|
|
72
72
|
if (v !== undefined)
|
|
73
73
|
return v;
|
|
74
74
|
}
|
|
75
|
-
throw
|
|
75
|
+
throw E.request_bag_missing_key(this.#name, key);
|
|
76
76
|
}
|
|
77
77
|
/**
|
|
78
78
|
* Try to get a value by key.
|
|
@@ -107,6 +107,9 @@ export default class RequestBag {
|
|
|
107
107
|
parse(schema) {
|
|
108
108
|
return schema.parse(this.#contents);
|
|
109
109
|
}
|
|
110
|
+
coerce(schema) {
|
|
111
|
+
return schema.coerce(this.#contents);
|
|
112
|
+
}
|
|
110
113
|
/** Returns {@link raw}. Useful in template strings. */
|
|
111
114
|
toString() {
|
|
112
115
|
return this.raw;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { Dict, JSONValue
|
|
1
|
+
import type { Dict, JSONValue } from "@rcompat/type";
|
|
2
2
|
type Form = Dict<string>;
|
|
3
3
|
type Parsed = {
|
|
4
4
|
type: "binary";
|
|
@@ -16,19 +16,16 @@ type Parsed = {
|
|
|
16
16
|
type: "text";
|
|
17
17
|
value: string;
|
|
18
18
|
};
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
} ? R : never;
|
|
19
|
+
declare function parse(request: Request, url: URL): Promise<RequestBody>;
|
|
20
|
+
declare function none(): RequestBody;
|
|
22
21
|
export default class RequestBody {
|
|
23
22
|
#private;
|
|
24
|
-
static parse
|
|
25
|
-
static none
|
|
23
|
+
static parse: typeof parse;
|
|
24
|
+
static none: typeof none;
|
|
26
25
|
constructor(parsed: Parsed, files?: Dict<File>);
|
|
27
|
-
get type(): "
|
|
26
|
+
get type(): "json" | "binary" | "text" | "none" | "form";
|
|
28
27
|
json(): JSONValue;
|
|
29
|
-
json<S extends Schema<unknown>>(schema: S): ParseReturn<S>;
|
|
30
28
|
form(): Form;
|
|
31
|
-
form<S extends Schema<unknown>>(schema: S): ParseReturn<S>;
|
|
32
29
|
files(): Dict<File>;
|
|
33
30
|
text(): string;
|
|
34
31
|
binary(): Blob;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import
|
|
2
|
-
import MIME from "@rcompat/http
|
|
1
|
+
import E from "#errors";
|
|
2
|
+
import { MIME } from "@rcompat/http";
|
|
3
3
|
import is from "@rcompat/is";
|
|
4
4
|
async function anyform(request) {
|
|
5
5
|
const form = Object.create(null);
|
|
@@ -15,40 +15,41 @@ async function anyform(request) {
|
|
|
15
15
|
return { form, files };
|
|
16
16
|
}
|
|
17
17
|
;
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
case MIME.MULTIPART_FORM_DATA: {
|
|
31
|
-
const { form, files } = await anyform(request);
|
|
32
|
-
return new RequestBody({ type: "form", value: form }, files);
|
|
33
|
-
}
|
|
34
|
-
case MIME.APPLICATION_JSON:
|
|
35
|
-
return new RequestBody({ type: "json", value: await request.json() });
|
|
36
|
-
case MIME.TEXT_PLAIN:
|
|
37
|
-
return new RequestBody({ type: "text", value: await request.text() });
|
|
38
|
-
case "none":
|
|
39
|
-
return RequestBody.none();
|
|
40
|
-
default:
|
|
41
|
-
throw fail("{0}: unsupported content type {1}", path, type);
|
|
18
|
+
async function parse(request, url) {
|
|
19
|
+
const raw = request.headers.get("content-type") ?? "none";
|
|
20
|
+
const type = raw.split(";")[0].trim().toLowerCase();
|
|
21
|
+
const path = url.pathname;
|
|
22
|
+
try {
|
|
23
|
+
switch (type) {
|
|
24
|
+
case MIME.APPLICATION_OCTET_STREAM:
|
|
25
|
+
return new RequestBody({ type: "binary", value: await request.blob() });
|
|
26
|
+
case MIME.APPLICATION_X_WWW_FORM_URLENCODED:
|
|
27
|
+
case MIME.MULTIPART_FORM_DATA: {
|
|
28
|
+
const { form, files } = await anyform(request);
|
|
29
|
+
return new RequestBody({ type: "form", value: form }, files);
|
|
42
30
|
}
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
31
|
+
case MIME.APPLICATION_JSON:
|
|
32
|
+
return new RequestBody({ type: "json", value: await request.json() });
|
|
33
|
+
case MIME.TEXT_PLAIN:
|
|
34
|
+
return new RequestBody({ type: "text", value: await request.text() });
|
|
35
|
+
case "none":
|
|
36
|
+
return RequestBody.none();
|
|
37
|
+
default:
|
|
38
|
+
throw E.request_unsupported_mime(path, type);
|
|
47
39
|
}
|
|
48
40
|
}
|
|
49
|
-
|
|
50
|
-
|
|
41
|
+
catch (cause) {
|
|
42
|
+
throw E.request_unparsable_mime(path, type, cause);
|
|
51
43
|
}
|
|
44
|
+
}
|
|
45
|
+
function none() {
|
|
46
|
+
return new RequestBody({ type: "none", value: null });
|
|
47
|
+
}
|
|
48
|
+
export default class RequestBody {
|
|
49
|
+
#parsed;
|
|
50
|
+
#files;
|
|
51
|
+
static parse = parse;
|
|
52
|
+
static none = none;
|
|
52
53
|
constructor(parsed, files = {}) {
|
|
53
54
|
this.#parsed = parsed;
|
|
54
55
|
this.#files = files;
|
|
@@ -59,44 +60,38 @@ export default class RequestBody {
|
|
|
59
60
|
#value() {
|
|
60
61
|
return this.#parsed.value;
|
|
61
62
|
}
|
|
62
|
-
#
|
|
63
|
-
throw
|
|
63
|
+
#unexpected_body(expected) {
|
|
64
|
+
throw E.request_unexpected_body(expected, this.type);
|
|
64
65
|
}
|
|
65
|
-
json(
|
|
66
|
-
if (this.type !== "json")
|
|
67
|
-
this.#
|
|
68
|
-
|
|
69
|
-
const value = this.#value();
|
|
70
|
-
return schema ? schema.parse(value) : value;
|
|
66
|
+
json() {
|
|
67
|
+
if (this.type !== "json")
|
|
68
|
+
this.#unexpected_body("JSON");
|
|
69
|
+
return this.#value();
|
|
71
70
|
}
|
|
72
|
-
form(
|
|
73
|
-
if (this.type !== "form")
|
|
74
|
-
this.#
|
|
75
|
-
|
|
76
|
-
const value = this.#value();
|
|
77
|
-
return schema ? schema.parse(value) : value;
|
|
71
|
+
form() {
|
|
72
|
+
if (this.type !== "form")
|
|
73
|
+
this.#unexpected_body("form");
|
|
74
|
+
return this.#value();
|
|
78
75
|
}
|
|
79
76
|
files() {
|
|
80
|
-
if (this.type !== "form")
|
|
81
|
-
this.#
|
|
82
|
-
}
|
|
77
|
+
if (this.type !== "form")
|
|
78
|
+
this.#unexpected_body("form");
|
|
83
79
|
return this.#files;
|
|
84
80
|
}
|
|
85
81
|
text() {
|
|
86
|
-
if (this.type !== "text")
|
|
87
|
-
this.#
|
|
88
|
-
}
|
|
82
|
+
if (this.type !== "text")
|
|
83
|
+
this.#unexpected_body("plaintext");
|
|
89
84
|
return this.#value();
|
|
90
85
|
}
|
|
91
86
|
binary() {
|
|
92
87
|
if (this.type !== "binary") {
|
|
93
|
-
this.#
|
|
88
|
+
this.#unexpected_body("binary");
|
|
94
89
|
}
|
|
95
90
|
return this.#value();
|
|
96
91
|
}
|
|
97
92
|
none() {
|
|
98
93
|
if (this.type !== "none") {
|
|
99
|
-
this.#
|
|
94
|
+
this.#unexpected_body("none");
|
|
100
95
|
}
|
|
101
96
|
return null;
|
|
102
97
|
}
|
|
@@ -1,15 +1,10 @@
|
|
|
1
1
|
import type RequestBag from "#request/RequestBag";
|
|
2
2
|
import type RequestBody from "#request/RequestBody";
|
|
3
|
+
import type RequestView from "#request/RequestView";
|
|
4
|
+
import type Verb from "#request/Verb";
|
|
3
5
|
import type { Dict } from "@rcompat/type";
|
|
4
|
-
type RequestView = {
|
|
5
|
-
context: Dict;
|
|
6
|
-
cookies: Dict<string>;
|
|
7
|
-
headers: Dict<string>;
|
|
8
|
-
path: Dict<string>;
|
|
9
|
-
query: Dict<string>;
|
|
10
|
-
url: URL;
|
|
11
|
-
};
|
|
12
6
|
type RequestFacade = {
|
|
7
|
+
method: Verb;
|
|
13
8
|
body: RequestBody;
|
|
14
9
|
cookies: RequestBag;
|
|
15
10
|
forward(to: string, headers?: Dict<string>): Promise<Response>;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { Dict } from "@rcompat/type";
|
|
2
|
+
type RequestView = {
|
|
3
|
+
context: Dict;
|
|
4
|
+
cookies: Dict<string>;
|
|
5
|
+
headers: Dict<string>;
|
|
6
|
+
path: Dict<string>;
|
|
7
|
+
query: Dict<string>;
|
|
8
|
+
url: URL;
|
|
9
|
+
};
|
|
10
|
+
export type { RequestView as default };
|
|
11
|
+
//# sourceMappingURL=RequestView.d.ts.map
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { Status } from "@rcompat/http";
|
|
2
|
+
async function run(hooks, request) {
|
|
3
|
+
const [first, ...rest] = hooks;
|
|
4
|
+
if (first === undefined) {
|
|
5
|
+
return new Response(null, {
|
|
6
|
+
headers: {
|
|
7
|
+
"Content-Length": String(0),
|
|
8
|
+
"Cache-Control": "no-cache",
|
|
9
|
+
},
|
|
10
|
+
status: Status.INTERNAL_SERVER_ERROR,
|
|
11
|
+
});
|
|
12
|
+
}
|
|
13
|
+
return await first(request, next => run(rest, next));
|
|
14
|
+
}
|
|
15
|
+
export default function handle(app, request) {
|
|
16
|
+
return run(app.handle_hooks, request);
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=handle.js.map
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import
|
|
1
|
+
import E from "#errors";
|
|
2
2
|
import log from "#log";
|
|
3
3
|
import response_error from "#response/error";
|
|
4
4
|
import response_json from "#response/json";
|
|
5
5
|
import respond from "#response/respond";
|
|
6
|
-
import Status from "@rcompat/http
|
|
6
|
+
import { Status } from "@rcompat/http";
|
|
7
7
|
import ParseError from "pema/ParseError";
|
|
8
8
|
const result = (request, response) => ({ request, response });
|
|
9
9
|
function wrap_hook(h) {
|
|
@@ -12,17 +12,16 @@ function wrap_hook(h) {
|
|
|
12
12
|
let called_next = false;
|
|
13
13
|
const response = await h(request, async (r) => {
|
|
14
14
|
if (called_next)
|
|
15
|
-
throw
|
|
15
|
+
throw E.hook_reused_next();
|
|
16
16
|
called_next = true;
|
|
17
17
|
downstream = await next(r);
|
|
18
18
|
return downstream.response;
|
|
19
19
|
});
|
|
20
20
|
// hook returned nothing
|
|
21
21
|
if (response === undefined) {
|
|
22
|
-
if (called_next)
|
|
23
|
-
throw
|
|
24
|
-
|
|
25
|
-
throw fail("hook must return a response-like value or return next(request)");
|
|
22
|
+
if (called_next)
|
|
23
|
+
throw E.hook_no_return();
|
|
24
|
+
throw E.hook_bad_return();
|
|
26
25
|
}
|
|
27
26
|
// if the hook called next(), we preserve the downstream request (mutations) but
|
|
28
27
|
// allow the hook to override the response by returning something else.
|
|
@@ -48,10 +47,10 @@ export default async function (app, partial_request) {
|
|
|
48
47
|
}
|
|
49
48
|
const { errors, hooks, layouts, handler } = route;
|
|
50
49
|
errorRoute = errors[0];
|
|
51
|
-
const
|
|
50
|
+
const internal_hooks = app.route_hooks.map(wrap_hook);
|
|
52
51
|
const route_hooks = hooks.map(wrap_hook);
|
|
53
52
|
const last = async (req, _next) => result(req, await handler(req));
|
|
54
|
-
const { request, response } = await run([...
|
|
53
|
+
const { request, response } = await run([...internal_hooks, ...route_hooks, last], route.request);
|
|
55
54
|
return await respond(response)(app, {
|
|
56
55
|
layouts: await Promise.all(layouts.map(layout => layout(request))),
|
|
57
56
|
}, request);
|