@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
package/lib/private/db/test.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { Code } from "#db/
|
|
1
|
+
import { Code } from "#db/errors";
|
|
2
2
|
import key from "#orm/key";
|
|
3
3
|
import relation from "#orm/relation";
|
|
4
|
-
import
|
|
4
|
+
import store from "#orm/store";
|
|
5
5
|
import test from "@rcompat/test";
|
|
6
6
|
import any from "@rcompat/test/any";
|
|
7
7
|
import p from "pema";
|
|
@@ -106,108 +106,147 @@ async function throws(assert, code, fn) {
|
|
|
106
106
|
}
|
|
107
107
|
export default (db) => {
|
|
108
108
|
test.ended(() => db.close());
|
|
109
|
-
const Post =
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
109
|
+
const Post = store({
|
|
110
|
+
name: "post",
|
|
111
|
+
db,
|
|
112
|
+
schema: {
|
|
113
|
+
id: key.primary(p.uuid),
|
|
114
|
+
title: p.string,
|
|
115
|
+
user_id: p.uint,
|
|
116
|
+
},
|
|
117
|
+
});
|
|
114
118
|
Post.update;
|
|
115
|
-
const User =
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
119
|
+
const User = store({
|
|
120
|
+
name: "user",
|
|
121
|
+
db,
|
|
122
|
+
schema: {
|
|
123
|
+
id: key.primary(p.uuid),
|
|
124
|
+
age: p.u8.optional(),
|
|
125
|
+
lastname: p.string.optional(),
|
|
126
|
+
name: p.string.default("Donald"),
|
|
127
|
+
},
|
|
128
|
+
});
|
|
129
|
+
const UserN = store({
|
|
130
|
+
name: "user_n",
|
|
131
|
+
db,
|
|
132
|
+
schema: {
|
|
133
|
+
id: key.primary(p.u32),
|
|
134
|
+
age: p.u8.optional(),
|
|
135
|
+
lastname: p.string.optional(),
|
|
136
|
+
name: p.string.default("Donald"),
|
|
137
|
+
},
|
|
138
|
+
});
|
|
139
|
+
const UserB = store({
|
|
140
|
+
name: "user_b",
|
|
141
|
+
db,
|
|
142
|
+
schema: {
|
|
143
|
+
id: key.primary(p.u128),
|
|
144
|
+
age: p.u8.optional(),
|
|
145
|
+
lastname: p.string.optional(),
|
|
146
|
+
name: p.string.default("Donald"),
|
|
147
|
+
},
|
|
148
|
+
});
|
|
133
149
|
const USER_STORES = [User, UserN, UserB];
|
|
134
|
-
const Type =
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
150
|
+
const Type = store({
|
|
151
|
+
name: "type",
|
|
152
|
+
db,
|
|
153
|
+
schema: {
|
|
154
|
+
id: key.primary(p.uuid),
|
|
155
|
+
boolean: p.boolean.optional(),
|
|
156
|
+
date: p.date.optional(),
|
|
157
|
+
f32: p.f32.optional(),
|
|
158
|
+
f64: p.f64.optional(),
|
|
159
|
+
i128: p.i128.optional(),
|
|
160
|
+
i16: p.i16.optional(),
|
|
161
|
+
i32: p.i32.optional(),
|
|
162
|
+
i64: p.i64.optional(),
|
|
163
|
+
i8: p.i8.optional(),
|
|
164
|
+
string: p.string.optional(),
|
|
165
|
+
u128: p.u128.optional(),
|
|
166
|
+
u16: p.u16.optional(),
|
|
167
|
+
u32: p.u32.optional(),
|
|
168
|
+
u64: p.u64.optional(),
|
|
169
|
+
u8: p.u8.optional(),
|
|
170
|
+
json: p.json().optional(),
|
|
171
|
+
},
|
|
172
|
+
});
|
|
152
173
|
// this stresses identifier quoting in CREATE/INSERT/SELECT/UPDATE/DELETE
|
|
153
|
-
const Reserved =
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
174
|
+
const Reserved = store({
|
|
175
|
+
// deliberately reserved-like table name
|
|
176
|
+
name: "select",
|
|
177
|
+
db,
|
|
178
|
+
schema: {
|
|
179
|
+
id: key.primary(p.uuid),
|
|
180
|
+
// deliberately reserved-looking column name
|
|
181
|
+
order: p.u8.optional(),
|
|
182
|
+
name: p.string,
|
|
183
|
+
},
|
|
184
|
+
});
|
|
159
185
|
const AuthorSchema = {
|
|
160
|
-
id: key.primary(p.
|
|
186
|
+
id: key.primary(p.uuid),
|
|
161
187
|
name: p.string,
|
|
162
188
|
};
|
|
163
189
|
const ArticleSchema = {
|
|
164
|
-
id: key.primary(p.
|
|
190
|
+
id: key.primary(p.uuid),
|
|
165
191
|
title: p.string,
|
|
166
|
-
author_id: key.foreign(p.
|
|
192
|
+
author_id: key.foreign(p.uuid),
|
|
167
193
|
};
|
|
168
194
|
const ProfileSchema = {
|
|
169
|
-
id: key.primary(p.
|
|
195
|
+
id: key.primary(p.uuid),
|
|
170
196
|
bio: p.string,
|
|
171
197
|
url: p.url.optional(),
|
|
172
|
-
author_id: key.foreign(p.
|
|
198
|
+
author_id: key.foreign(p.uuid),
|
|
173
199
|
};
|
|
174
|
-
const Author =
|
|
200
|
+
const Author = store({
|
|
175
201
|
db,
|
|
176
202
|
name: "author",
|
|
203
|
+
schema: AuthorSchema,
|
|
177
204
|
relations: {
|
|
178
205
|
articles: relation.many(ArticleSchema, "author_id"),
|
|
179
206
|
profile: relation.one(ProfileSchema, "author_id"),
|
|
180
207
|
},
|
|
181
208
|
});
|
|
182
|
-
const
|
|
209
|
+
/*const AuthorWithJSON = store({
|
|
210
|
+
name: "author_json",
|
|
211
|
+
db,
|
|
212
|
+
schema: {
|
|
213
|
+
id: key.primary(p.uuid),
|
|
214
|
+
name: p.string,
|
|
215
|
+
meta: p.json(p({ views: p.u32, tags: p.array(p.string) })),
|
|
216
|
+
notes: p.json(), // untyped
|
|
217
|
+
},
|
|
218
|
+
});*/
|
|
219
|
+
const Article = store({
|
|
183
220
|
db,
|
|
184
221
|
name: "article",
|
|
222
|
+
schema: ArticleSchema,
|
|
185
223
|
relations: {
|
|
186
224
|
author: relation.one(AuthorSchema, "author_id", { reverse: true }),
|
|
187
225
|
},
|
|
188
226
|
});
|
|
189
|
-
const Profile =
|
|
227
|
+
const Profile = store({
|
|
190
228
|
db,
|
|
191
229
|
name: "profile",
|
|
230
|
+
schema: ProfileSchema,
|
|
192
231
|
relations: {
|
|
193
232
|
author: relation.one(AuthorSchema, "author_id", { reverse: true }),
|
|
194
233
|
},
|
|
195
234
|
});
|
|
196
|
-
function $store(label,
|
|
235
|
+
function $store(label, s, body) {
|
|
197
236
|
test.case(label, async (assert) => {
|
|
198
|
-
await
|
|
237
|
+
await s.table.create();
|
|
199
238
|
try {
|
|
200
239
|
await body(assert);
|
|
201
240
|
}
|
|
202
241
|
finally {
|
|
203
|
-
await
|
|
242
|
+
await s.table.delete();
|
|
204
243
|
}
|
|
205
244
|
});
|
|
206
245
|
}
|
|
207
246
|
function $user(label, body) {
|
|
208
247
|
test.case(label, async (assert) => {
|
|
209
248
|
for (const S of USER_STORES)
|
|
210
|
-
await S.
|
|
249
|
+
await S.table.create();
|
|
211
250
|
try {
|
|
212
251
|
for (const u of Object.values(USERS)) {
|
|
213
252
|
for (const S of USER_STORES)
|
|
@@ -217,7 +256,7 @@ export default (db) => {
|
|
|
217
256
|
}
|
|
218
257
|
finally {
|
|
219
258
|
for (const S of USER_STORES)
|
|
220
|
-
await S.
|
|
259
|
+
await S.table.delete();
|
|
221
260
|
}
|
|
222
261
|
});
|
|
223
262
|
}
|
|
@@ -229,9 +268,9 @@ export default (db) => {
|
|
|
229
268
|
}
|
|
230
269
|
function $rel(label, body) {
|
|
231
270
|
test.case(`relation: ${label}`, async (assert) => {
|
|
232
|
-
await Author.
|
|
233
|
-
await Article.
|
|
234
|
-
await Profile.
|
|
271
|
+
await Author.table.create();
|
|
272
|
+
await Article.table.create();
|
|
273
|
+
await Profile.table.create();
|
|
235
274
|
try {
|
|
236
275
|
const john = await Author.insert({ name: "John" });
|
|
237
276
|
const bob = await Author.insert({ name: "Bob" });
|
|
@@ -257,9 +296,9 @@ export default (db) => {
|
|
|
257
296
|
await body(assert);
|
|
258
297
|
}
|
|
259
298
|
finally {
|
|
260
|
-
await Profile.
|
|
261
|
-
await Article.
|
|
262
|
-
await Author.
|
|
299
|
+
await Profile.table.delete();
|
|
300
|
+
await Article.table.delete();
|
|
301
|
+
await Author.table.delete();
|
|
263
302
|
}
|
|
264
303
|
});
|
|
265
304
|
}
|
|
@@ -309,19 +348,24 @@ export default (db) => {
|
|
|
309
348
|
assert(user.id).type();
|
|
310
349
|
assert(await UserB.has(user.id)).true();
|
|
311
350
|
});
|
|
312
|
-
const ManualUser =
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
351
|
+
const ManualUser = store({
|
|
352
|
+
name: "manual_user",
|
|
353
|
+
db,
|
|
354
|
+
schema: {
|
|
355
|
+
id: key.primary(p.uuid, { generate: false }),
|
|
356
|
+
name: p.string,
|
|
357
|
+
},
|
|
358
|
+
});
|
|
316
359
|
$store("insert: generate=false requires PK", ManualUser, async (assert) => {
|
|
317
360
|
await throws(assert, Code.pk_required, () => {
|
|
318
361
|
return ManualUser.insert({ name: "Test" });
|
|
319
362
|
});
|
|
320
363
|
});
|
|
321
364
|
$store("insert: generate=false accepts provided PK", ManualUser, async (assert) => {
|
|
322
|
-
const
|
|
323
|
-
|
|
324
|
-
assert(
|
|
365
|
+
const id = "4d0996db-bda9-4f95-ad7c-7075b10d4ba6";
|
|
366
|
+
const user = await ManualUser.insert({ id, name: "Test" });
|
|
367
|
+
assert(user.id).equals(id);
|
|
368
|
+
assert(await ManualUser.has(id)).true();
|
|
325
369
|
});
|
|
326
370
|
$store("insert: defaults apply", User, async (assert) => {
|
|
327
371
|
const u = await User.insert({});
|
|
@@ -781,6 +825,12 @@ export default (db) => {
|
|
|
781
825
|
// returned shape must not contain null
|
|
782
826
|
assert(got.lastname).undefined();
|
|
783
827
|
});
|
|
828
|
+
$store("insert: default fields can be omitted", User, async (assert) => {
|
|
829
|
+
// User has name: p.string.default("Donald")
|
|
830
|
+
// should be insertable without providing name
|
|
831
|
+
const user = await User.insert({ age: 30 });
|
|
832
|
+
assert(user.name).equals("Donald");
|
|
833
|
+
});
|
|
784
834
|
$store("reserved table / column names", Reserved, async (assert) => {
|
|
785
835
|
const a = await Reserved.insert({ name: "alpha", order: 1 });
|
|
786
836
|
const b = await Reserved.insert({ name: "beta", order: 2 });
|
|
@@ -973,17 +1023,20 @@ export default (db) => {
|
|
|
973
1023
|
});
|
|
974
1024
|
});
|
|
975
1025
|
$user("get/try: missing id", async (assert) => {
|
|
976
|
-
const missing =
|
|
1026
|
+
const missing = "00000000-0000-4000-8000-000000000000";
|
|
1027
|
+
// const missing = `missing-${Date.now()}-${Math.random()}`;
|
|
977
1028
|
await throws(assert, Code.record_not_found, () => User.get(missing));
|
|
978
1029
|
assert(await User.try(missing)).undefined();
|
|
979
1030
|
});
|
|
980
1031
|
$rel("get/try: missing id (with relations)", async (assert) => {
|
|
981
|
-
const missing = `missing-${Date.now()}-${Math.random()}`;
|
|
1032
|
+
//const missing = `missing-${Date.now()}-${Math.random()}`;
|
|
1033
|
+
const missing = "00000000-0000-4000-8000-000000000000";
|
|
982
1034
|
await throws(assert, Code.record_not_found, () => Article.get(missing, { with: { author: true } }));
|
|
983
1035
|
assert(await Article.try(missing, { with: { author: true } })).undefined();
|
|
984
1036
|
});
|
|
985
1037
|
$rel("get/try: missing id (+ parent)", async (assert) => {
|
|
986
|
-
const missing =
|
|
1038
|
+
const missing = "00000000-0000-4000-8000-000000000000";
|
|
1039
|
+
//const missing = `missing-${Date.now()}-${Math.random()}`;
|
|
987
1040
|
await throws(assert, Code.record_not_found, () => Author.get(missing, { with: { articles: true, profile: true } }));
|
|
988
1041
|
assert(await Author.try(missing, {
|
|
989
1042
|
with: { articles: true, profile: true },
|
|
@@ -1103,12 +1156,76 @@ export default (db) => {
|
|
|
1103
1156
|
const results = await Type.find({
|
|
1104
1157
|
where: {
|
|
1105
1158
|
string: "combo",
|
|
1106
|
-
u8: { $gte: 150, $ne: 200 }
|
|
1159
|
+
u8: { $gte: 150, $ne: 200 },
|
|
1107
1160
|
},
|
|
1108
1161
|
sort: { u8: "asc" },
|
|
1109
1162
|
});
|
|
1110
1163
|
assert(results.map(r => r.u8)).equals([150]);
|
|
1111
1164
|
});
|
|
1165
|
+
$type("json: opaque roundtrip", async (assert) => {
|
|
1166
|
+
const json = { a: 1, b: [true, "x"], c: null };
|
|
1167
|
+
const t = await Type.insert({ json });
|
|
1168
|
+
assert(t.json).equals(json);
|
|
1169
|
+
assert((await Type.get(t.id)).json).equals(json);
|
|
1170
|
+
});
|
|
1171
|
+
$type("json: update", async (assert) => {
|
|
1172
|
+
const t = await Type.insert({ json: { x: 1 } });
|
|
1173
|
+
await Type.update(t.id, { set: { json: { x: 2, y: "hello" } } });
|
|
1174
|
+
assert((await Type.get(t.id)).json).equals({ x: 2, y: "hello" });
|
|
1175
|
+
});
|
|
1176
|
+
$type("json: nested object", async (assert) => {
|
|
1177
|
+
const value = { outer: { inner: { deep: true } } };
|
|
1178
|
+
const t = await Type.insert({ json: value });
|
|
1179
|
+
assert((await Type.get(t.id)).json).equals(value);
|
|
1180
|
+
});
|
|
1181
|
+
$type("json: array at root", async (assert) => {
|
|
1182
|
+
const value = [1, "two", false, null];
|
|
1183
|
+
const t = await Type.insert({ json: value });
|
|
1184
|
+
assert((await Type.get(t.id)).json).equals(value);
|
|
1185
|
+
});
|
|
1186
|
+
$type("json: null value unsets field", async (assert) => {
|
|
1187
|
+
const t = await Type.insert({ json: { x: 1 } });
|
|
1188
|
+
await Type.update(t.id, { set: { json: null } });
|
|
1189
|
+
assert((await Type.get(t.id)).json).undefined();
|
|
1190
|
+
});
|
|
1191
|
+
$type("json: empty object", async (assert) => {
|
|
1192
|
+
const t = await Type.insert({ json: {} });
|
|
1193
|
+
assert((await Type.get(t.id)).json).equals({});
|
|
1194
|
+
});
|
|
1195
|
+
$type("json: empty array", async (assert) => {
|
|
1196
|
+
const t = await Type.insert({ json: [] });
|
|
1197
|
+
assert((await Type.get(t.id)).json).equals([]);
|
|
1198
|
+
});
|
|
1199
|
+
$type("json: primitive string", async (assert) => {
|
|
1200
|
+
const t = await Type.insert({ json: "hello" });
|
|
1201
|
+
assert((await Type.get(t.id)).json).equals("hello");
|
|
1202
|
+
});
|
|
1203
|
+
$type("json: primitive number", async (assert) => {
|
|
1204
|
+
const t = await Type.insert({ json: 42 });
|
|
1205
|
+
assert((await Type.get(t.id)).json).equals(42);
|
|
1206
|
+
});
|
|
1207
|
+
$type("json: primitive float", async (assert) => {
|
|
1208
|
+
const t = await Type.insert({ json: 3.14 });
|
|
1209
|
+
assert((await Type.get(t.id)).json).equals(3.14);
|
|
1210
|
+
});
|
|
1211
|
+
$type("json: primitive boolean true", async (assert) => {
|
|
1212
|
+
const t = await Type.insert({ json: true });
|
|
1213
|
+
assert((await Type.get(t.id)).json).equals(true);
|
|
1214
|
+
});
|
|
1215
|
+
$type("json: primitive boolean false", async (assert) => {
|
|
1216
|
+
const t = await Type.insert({ json: false });
|
|
1217
|
+
assert((await Type.get(t.id)).json).equals(false);
|
|
1218
|
+
});
|
|
1219
|
+
$type("json: null inside object survives roundtrip", async (assert) => {
|
|
1220
|
+
const value = { a: 1, b: null };
|
|
1221
|
+
const t = await Type.insert({ json: value });
|
|
1222
|
+
assert((await Type.get(t.id)).json).equals({ a: 1, b: null });
|
|
1223
|
+
});
|
|
1224
|
+
$type("json: null inside array survives roundtrip", async (assert) => {
|
|
1225
|
+
const value = [1, null, "three"];
|
|
1226
|
+
const t = await Type.insert({ json: value });
|
|
1227
|
+
assert((await Type.get(t.id)).json).equals([1, null, "three"]);
|
|
1228
|
+
});
|
|
1112
1229
|
$store("where: null matches omitted optional field", User, async (assert) => {
|
|
1113
1230
|
const u = await User.insert({ name: "NoLast" });
|
|
1114
1231
|
const rows = await User.find({
|
|
@@ -1118,6 +1235,75 @@ export default (db) => {
|
|
|
1118
1235
|
assert(rows.length).equals(1);
|
|
1119
1236
|
assert(rows[0].id).equals(u.id);
|
|
1120
1237
|
});
|
|
1238
|
+
/*$store("json column: inferred type on insert", AuthorWithJSON, async assert => {
|
|
1239
|
+
const author = await AuthorWithJSON.insert({
|
|
1240
|
+
name: "John",
|
|
1241
|
+
articles: [{ title: "First", published: new Date() }],
|
|
1242
|
+
meta: { views: 0, tags: ["typescript"] },
|
|
1243
|
+
});
|
|
1244
|
+
|
|
1245
|
+
assert(author).type<{
|
|
1246
|
+
id: string;
|
|
1247
|
+
name: string;
|
|
1248
|
+
articles?: { title: string; published: Date }[];
|
|
1249
|
+
meta?: { views: number; tags: string[] };
|
|
1250
|
+
notes?: JSONValue;
|
|
1251
|
+
}>();
|
|
1252
|
+
});
|
|
1253
|
+
|
|
1254
|
+
$store("json column: inferred type on find", AuthorWithJSON, async assert => {
|
|
1255
|
+
const authors = await AuthorWithJSON.find();
|
|
1256
|
+
assert(authors).type<{
|
|
1257
|
+
id: string;
|
|
1258
|
+
name: string;
|
|
1259
|
+
articles?: { title: string; published: Date }[];
|
|
1260
|
+
meta?: { views: number; tags: string[] };
|
|
1261
|
+
notes?: JSONValue;
|
|
1262
|
+
}[]>();
|
|
1263
|
+
});
|
|
1264
|
+
|
|
1265
|
+
$store("json column: inferred type on get", AuthorWithJSON, async assert => {
|
|
1266
|
+
const a = await AuthorWithJSON.insert({
|
|
1267
|
+
name: "John",
|
|
1268
|
+
articles: [{ title: "First", published: new Date() }],
|
|
1269
|
+
meta: { views: 0, tags: ["typescript"] },
|
|
1270
|
+
});
|
|
1271
|
+
const author = await AuthorWithJSON.get(a.id);
|
|
1272
|
+
|
|
1273
|
+
assert(author.articles).type<{ title: string; published: Date }[] | undefined>();
|
|
1274
|
+
assert(author.meta).type<{ views: number; tags: string[] } | undefined>();
|
|
1275
|
+
assert(author.notes).type<JSONValue | undefined>();
|
|
1276
|
+
|
|
1277
|
+
// inner field access fully typed
|
|
1278
|
+
assert(author.articles?.[0].title).type<string | undefined>();
|
|
1279
|
+
assert(author.articles?.[0].published).type<Date | undefined>();
|
|
1280
|
+
});
|
|
1281
|
+
|
|
1282
|
+
$store("json column: roundtrip preserves types", AuthorWithJSON, async assert => {
|
|
1283
|
+
const now = new Date();
|
|
1284
|
+
const a = await AuthorWithJSON.insert({
|
|
1285
|
+
name: "John",
|
|
1286
|
+
articles: [{ title: "First", published: now }],
|
|
1287
|
+
meta: { views: 42, tags: ["ts", "primate"] },
|
|
1288
|
+
});
|
|
1289
|
+
|
|
1290
|
+
const author = await AuthorWithJSON.get(a.id);
|
|
1291
|
+
|
|
1292
|
+
assert(author.articles?.[0].title).equals("First");
|
|
1293
|
+
assert(author.articles?.[0].published?.getTime()).equals(now.getTime());
|
|
1294
|
+
assert(author.meta?.views).equals(42);
|
|
1295
|
+
assert(author.meta?.tags).equals(["ts", "primate"]);
|
|
1296
|
+
});
|
|
1297
|
+
|
|
1298
|
+
$store("json column: nested where is typed", AuthorWithJSON, async assert => {
|
|
1299
|
+
// these should compile
|
|
1300
|
+
await AuthorWithJSON.find({ where: { articles: { title: "First" } } });
|
|
1301
|
+
await AuthorWithJSON.find({ where: { meta: { views: { $gt: 10 } } } });
|
|
1302
|
+
await AuthorWithJSON.find({ where: { meta: { tags: { $like: "%ts%" } } } });
|
|
1303
|
+
|
|
1304
|
+
// $contains always available, untyped
|
|
1305
|
+
await AuthorWithJSON.find({ where: { articles: { $contains: { title: "First" } } } });
|
|
1306
|
+
});*/
|
|
1121
1307
|
$user("where: null matches unset via update", async (assert) => {
|
|
1122
1308
|
const [paul] = await User.find({ where: { name: "Paul" } });
|
|
1123
1309
|
await User.update(paul.id, { set: { lastname: null } });
|
|
@@ -1185,9 +1371,10 @@ export default (db) => {
|
|
|
1185
1371
|
});
|
|
1186
1372
|
});
|
|
1187
1373
|
$rel("one relation returns null when FK missing", async (assert) => {
|
|
1374
|
+
const author_id = "4d0996db-bda9-4f95-ad7c-7075b10d4ba6";
|
|
1188
1375
|
const orphan = await Article.insert({
|
|
1189
1376
|
title: "Orphan",
|
|
1190
|
-
author_id
|
|
1377
|
+
author_id,
|
|
1191
1378
|
});
|
|
1192
1379
|
const got = await Article.get(orphan.id, { with: { author: true } });
|
|
1193
1380
|
assert(got.author).null();
|
|
@@ -1237,11 +1424,14 @@ export default (db) => {
|
|
|
1237
1424
|
});
|
|
1238
1425
|
});
|
|
1239
1426
|
$user$("inject invalid identifier (table name)", async (assert) => {
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1427
|
+
await throws(assert, Code.identifier_invalid, () => {
|
|
1428
|
+
store({
|
|
1429
|
+
name: "users; DROP TABLE users",
|
|
1430
|
+
db,
|
|
1431
|
+
schema: {
|
|
1432
|
+
id: key.primary(p.uuid),
|
|
1433
|
+
},
|
|
1434
|
+
});
|
|
1245
1435
|
});
|
|
1246
1436
|
});
|
|
1247
1437
|
$user("find: $like: literal percent sign", async (assert) => {
|
|
@@ -1300,31 +1490,33 @@ export default (db) => {
|
|
|
1300
1490
|
});
|
|
1301
1491
|
$rel("with: joined relations decode URL fields (base + rel)", async (assert) => {
|
|
1302
1492
|
const ParentSchema = {
|
|
1303
|
-
id: key.primary(p.
|
|
1493
|
+
id: key.primary(p.uuid),
|
|
1304
1494
|
name: p.string,
|
|
1305
1495
|
url: p.url.optional(),
|
|
1306
1496
|
};
|
|
1307
1497
|
const ChildSchema = {
|
|
1308
|
-
id: key.primary(p.
|
|
1309
|
-
parent_id: key.foreign(p.
|
|
1498
|
+
id: key.primary(p.uuid),
|
|
1499
|
+
parent_id: key.foreign(p.uuid),
|
|
1310
1500
|
url: p.url.optional(),
|
|
1311
1501
|
};
|
|
1312
|
-
const Parent =
|
|
1313
|
-
db,
|
|
1502
|
+
const Parent = store({
|
|
1314
1503
|
name: "j_parent",
|
|
1504
|
+
db,
|
|
1505
|
+
schema: ParentSchema,
|
|
1315
1506
|
relations: {
|
|
1316
1507
|
children: relation.many(ChildSchema, "parent_id"),
|
|
1317
1508
|
},
|
|
1318
1509
|
});
|
|
1319
|
-
const Child =
|
|
1510
|
+
const Child = store({
|
|
1320
1511
|
db,
|
|
1321
1512
|
name: "j_child",
|
|
1513
|
+
schema: ChildSchema,
|
|
1322
1514
|
relations: {
|
|
1323
1515
|
parent: relation.one(ParentSchema, "parent_id", { reverse: true }),
|
|
1324
1516
|
},
|
|
1325
1517
|
});
|
|
1326
|
-
await Parent.
|
|
1327
|
-
await Child.
|
|
1518
|
+
await Parent.table.create();
|
|
1519
|
+
await Child.table.create();
|
|
1328
1520
|
try {
|
|
1329
1521
|
const p0 = await Parent.insert({
|
|
1330
1522
|
name: "P0",
|
|
@@ -1356,8 +1548,8 @@ export default (db) => {
|
|
|
1356
1548
|
assert(c0.url.href).equals("https://example.com/joined");
|
|
1357
1549
|
}
|
|
1358
1550
|
finally {
|
|
1359
|
-
await Child.
|
|
1360
|
-
await Parent.
|
|
1551
|
+
await Child.table.delete();
|
|
1552
|
+
await Parent.table.delete();
|
|
1361
1553
|
}
|
|
1362
1554
|
});
|
|
1363
1555
|
$rel("find: limit applies to parent rows, not joined rows", async (assert) => {
|
|
@@ -1380,5 +1572,179 @@ export default (db) => {
|
|
|
1380
1572
|
for (const c of BAD_WHERE_COLUMN) {
|
|
1381
1573
|
bad_where(c.label, () => ({ base: c.base, with: c.with }), c.expected);
|
|
1382
1574
|
}
|
|
1575
|
+
test.case("store: relation name conflicts with field throws", async (assert) => {
|
|
1576
|
+
await throws(assert, Code.relation_conflicts_with_field, async () => store({
|
|
1577
|
+
name: "conflict",
|
|
1578
|
+
db,
|
|
1579
|
+
schema: {
|
|
1580
|
+
id: key.primary(p.uuid),
|
|
1581
|
+
articles: p.string,
|
|
1582
|
+
},
|
|
1583
|
+
relations: {
|
|
1584
|
+
articles: relation.many(ArticleSchema, "author_id"),
|
|
1585
|
+
},
|
|
1586
|
+
}));
|
|
1587
|
+
});
|
|
1588
|
+
// introspect: returns null for non-existent table
|
|
1589
|
+
test.case("schema: introspect non-existent", async (assert) => {
|
|
1590
|
+
assert(await db.schema.introspect("no_such_table")).null();
|
|
1591
|
+
});
|
|
1592
|
+
// UUID pk (User): wrong JS type
|
|
1593
|
+
$store("pk: get rejects non-string for uuid pk", User, async (assert) => {
|
|
1594
|
+
await throws(assert, Code.pk_invalid, () => User.get(123));
|
|
1595
|
+
});
|
|
1596
|
+
$store("pk: has rejects non-string for uuid pk", User, async (assert) => {
|
|
1597
|
+
await throws(assert, Code.pk_invalid, () => User.has(123));
|
|
1598
|
+
});
|
|
1599
|
+
$store("pk: delete rejects non-string for uuid pk", User, async (assert) => {
|
|
1600
|
+
await throws(assert, Code.pk_invalid, () => User.delete(123));
|
|
1601
|
+
});
|
|
1602
|
+
$store("pk: update rejects non-string for uuid pk", User, async (assert) => {
|
|
1603
|
+
await throws(assert, Code.pk_invalid, () => User.update(123, { set: { name: "x" } }));
|
|
1604
|
+
});
|
|
1605
|
+
// UUID pk (User): valid JS type but malformed UUID
|
|
1606
|
+
$store("pk: get rejects malformed uuid", User, async (assert) => {
|
|
1607
|
+
await throws(assert, Code.pk_invalid, () => User.get("not-a-uuid"));
|
|
1608
|
+
});
|
|
1609
|
+
$store("pk: has rejects malformed uuid", User, async (assert) => {
|
|
1610
|
+
await throws(assert, Code.pk_invalid, () => User.has("not-a-uuid"));
|
|
1611
|
+
});
|
|
1612
|
+
$store("pk: delete rejects malformed uuid", User, async (assert) => {
|
|
1613
|
+
await throws(assert, Code.pk_invalid, () => User.delete("not-a-uuid"));
|
|
1614
|
+
});
|
|
1615
|
+
$store("pk: update rejects malformed uuid", User, async (assert) => {
|
|
1616
|
+
await throws(assert, Code.pk_invalid, () => User.update("not-a-uuid", { set: { name: "x" } }));
|
|
1617
|
+
});
|
|
1618
|
+
// Numeric pk (UserN u32): wrong JS type
|
|
1619
|
+
$store("pk: get rejects string for numeric pk", UserN, async (assert) => {
|
|
1620
|
+
await throws(assert, Code.pk_invalid, () => UserN.get("abc"));
|
|
1621
|
+
});
|
|
1622
|
+
$store("pk: has rejects string for numeric pk", UserN, async (assert) => {
|
|
1623
|
+
await throws(assert, Code.pk_invalid, () => UserN.has("abc"));
|
|
1624
|
+
});
|
|
1625
|
+
$store("pk: delete rejects string for numeric pk", UserN, async (assert) => {
|
|
1626
|
+
await throws(assert, Code.pk_invalid, () => UserN.delete("abc"));
|
|
1627
|
+
});
|
|
1628
|
+
$store("pk: update rejects string for numeric pk", UserN, async (assert) => {
|
|
1629
|
+
await throws(assert, Code.pk_invalid, () => UserN.update("abc", { set: { name: "x" } }));
|
|
1630
|
+
});
|
|
1631
|
+
// Numeric pk (UserN u32): negative value
|
|
1632
|
+
$store("pk: get rejects negative for unsigned pk", UserN, async (assert) => {
|
|
1633
|
+
await throws(assert, Code.pk_invalid, () => UserN.get(-1));
|
|
1634
|
+
});
|
|
1635
|
+
// Bigint pk (UserB u128): wrong JS type
|
|
1636
|
+
$store("pk: get rejects string for bigint pk", UserB, async (assert) => {
|
|
1637
|
+
await throws(assert, Code.pk_invalid, () => UserB.get("abc"));
|
|
1638
|
+
});
|
|
1639
|
+
$store("pk: get rejects negative for unsigned bigint pk", UserB, async (assert) => {
|
|
1640
|
+
await throws(assert, Code.pk_invalid, () => UserB.get(-1n));
|
|
1641
|
+
});
|
|
1642
|
+
// introspect: returns correct types after create
|
|
1643
|
+
$store("schema: introspect after create", User, async (assert) => {
|
|
1644
|
+
// insert a record so MongoDB has something to sample
|
|
1645
|
+
await User.insert({ name: "test", age: 1, lastname: "test" });
|
|
1646
|
+
const types = await db.schema.introspect(User.name, User.pk);
|
|
1647
|
+
assert(types).not.null();
|
|
1648
|
+
if (types !== null) {
|
|
1649
|
+
assert(types.id).includes("uuid");
|
|
1650
|
+
assert(types.name).includes("string");
|
|
1651
|
+
assert(types.age).includes("u8");
|
|
1652
|
+
assert(types.lastname).includes("string");
|
|
1653
|
+
}
|
|
1654
|
+
});
|
|
1655
|
+
// alter: add a field
|
|
1656
|
+
$store("schema: alter add", User, async (assert) => {
|
|
1657
|
+
await db.schema.alter("user", {
|
|
1658
|
+
add: { email: "string" }, drop: [], rename: [],
|
|
1659
|
+
});
|
|
1660
|
+
const MigratedUser = store({
|
|
1661
|
+
name: "user",
|
|
1662
|
+
db,
|
|
1663
|
+
schema: {
|
|
1664
|
+
id: key.primary(p.uuid),
|
|
1665
|
+
age: p.u8.optional(),
|
|
1666
|
+
lastname: p.string.optional(),
|
|
1667
|
+
name: p.string.default("Donald"),
|
|
1668
|
+
email: p.string.email(),
|
|
1669
|
+
},
|
|
1670
|
+
});
|
|
1671
|
+
await MigratedUser.insert({ name: "test", age: 1, email: "test@test.com" });
|
|
1672
|
+
const types = await db.schema.introspect("user");
|
|
1673
|
+
assert(types.email).includes("string");
|
|
1674
|
+
});
|
|
1675
|
+
// alter: drop a field
|
|
1676
|
+
$store("schema: alter drop", User, async (assert) => {
|
|
1677
|
+
await db.schema.alter("user", { add: {}, drop: ["lastname"], rename: [] });
|
|
1678
|
+
const types = await db.schema.introspect("user");
|
|
1679
|
+
assert(types.lastname).undefined();
|
|
1680
|
+
});
|
|
1681
|
+
// alter: rename a field
|
|
1682
|
+
$store("schema: alter rename", User, async (assert) => {
|
|
1683
|
+
await db.schema.alter("user", {
|
|
1684
|
+
add: {}, drop: [], rename: [["lastname", "surname"]],
|
|
1685
|
+
});
|
|
1686
|
+
const MigratedUser = store({
|
|
1687
|
+
name: "user",
|
|
1688
|
+
db,
|
|
1689
|
+
schema: {
|
|
1690
|
+
id: key.primary(p.uuid),
|
|
1691
|
+
age: p.u8.optional(),
|
|
1692
|
+
surname: p.string.optional(),
|
|
1693
|
+
name: p.string.default("Donald"),
|
|
1694
|
+
},
|
|
1695
|
+
});
|
|
1696
|
+
await MigratedUser.insert({ name: "Donald", surname: "Adams" });
|
|
1697
|
+
const types = await db.schema.introspect("user");
|
|
1698
|
+
assert(types.lastname).undefined();
|
|
1699
|
+
assert(types.surname).includes("string");
|
|
1700
|
+
});
|
|
1701
|
+
// alter: combined add + drop
|
|
1702
|
+
$store("schema: alter add and drop", User, async (assert) => {
|
|
1703
|
+
await db.schema.alter("user", {
|
|
1704
|
+
add: { email: "string" }, drop: ["lastname"], rename: [],
|
|
1705
|
+
});
|
|
1706
|
+
const MigratedUser = store({
|
|
1707
|
+
name: "user",
|
|
1708
|
+
db,
|
|
1709
|
+
schema: {
|
|
1710
|
+
id: key.primary(p.uuid),
|
|
1711
|
+
age: p.u8.optional(),
|
|
1712
|
+
name: p.string.default("Donald"),
|
|
1713
|
+
email: p.string.email(),
|
|
1714
|
+
},
|
|
1715
|
+
});
|
|
1716
|
+
await MigratedUser.insert({ name: "Donald", email: "test@test.com" });
|
|
1717
|
+
const types = await db.schema.introspect("user");
|
|
1718
|
+
assert(types.email).includes("string");
|
|
1719
|
+
assert(types.lastname).undefined();
|
|
1720
|
+
});
|
|
1721
|
+
const UUIDTest = store({
|
|
1722
|
+
name: "uuid_test",
|
|
1723
|
+
db,
|
|
1724
|
+
schema: {
|
|
1725
|
+
id: key.primary(p.uuid),
|
|
1726
|
+
uuid: p.uuid,
|
|
1727
|
+
uuid_v4: p.uuid.v4(),
|
|
1728
|
+
uuid_v7: p.uuid.v7(),
|
|
1729
|
+
},
|
|
1730
|
+
});
|
|
1731
|
+
$store("uuid: round-trips uuid column", UUIDTest, async (assert) => {
|
|
1732
|
+
const uuid = "4d0996db-bda9-4f95-ad7c-7075b10d4ba6"; // any valid uuid
|
|
1733
|
+
const uuid_v4 = "7c9e6679-7425-40de-944b-e07fc1f90ae7"; // distinct v4
|
|
1734
|
+
const uuid_v7 = "01932b6e-5a2f-7e4f-9a3b-4f6d2c8b1a0e"; // v7
|
|
1735
|
+
const row = await UUIDTest.insert({ uuid, uuid_v4, uuid_v7 });
|
|
1736
|
+
assert(row.uuid).equals(uuid).type();
|
|
1737
|
+
assert(row.uuid_v4).equals(uuid_v4).type();
|
|
1738
|
+
assert(row.uuid_v7).equals(uuid_v7).type();
|
|
1739
|
+
const fetched = await UUIDTest.get(row.id);
|
|
1740
|
+
assert(fetched.uuid).equals(uuid);
|
|
1741
|
+
assert(fetched.uuid_v4).equals(uuid_v4);
|
|
1742
|
+
assert(fetched.uuid_v7).equals(uuid_v7);
|
|
1743
|
+
});
|
|
1744
|
+
test.case("schema: alter non-existent throws", async (assert) => {
|
|
1745
|
+
await throws(assert, Code.table_not_found, () => db.schema.alter("no_such_table", {
|
|
1746
|
+
add: { email: "string" }, drop: [], rename: [],
|
|
1747
|
+
}));
|
|
1748
|
+
});
|
|
1383
1749
|
};
|
|
1384
1750
|
//# sourceMappingURL=test.js.map
|