@nxgt/janus 0.18.0 → 0.20.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 +148 -12
- package/dist/auth/email-flows/reset-password.d.ts.map +1 -1
- package/dist/auth/events.d.ts +3 -3
- package/dist/auth/index.d.ts +1 -1
- package/dist/auth/index.d.ts.map +1 -1
- package/dist/auth/magic-link.d.ts +3 -0
- package/dist/auth/magic-link.d.ts.map +1 -1
- package/dist/auth/one-time/issue.d.ts +6 -0
- package/dist/auth/one-time/issue.d.ts.map +1 -1
- package/dist/auth/port/assert-stores.d.ts.map +1 -1
- package/dist/auth/port/memory/users.d.ts.map +1 -1
- package/dist/auth/port/types/stores.d.ts +5 -0
- package/dist/auth/port/types/stores.d.ts.map +1 -1
- package/dist/auth/port/types/users.d.ts +17 -0
- package/dist/auth/port/types/users.d.ts.map +1 -1
- package/dist/auth/prepared.d.ts +21 -0
- package/dist/auth/prepared.d.ts.map +1 -0
- package/dist/auth/proven-sign-in.d.ts +22 -0
- package/dist/auth/proven-sign-in.d.ts.map +1 -0
- package/dist/auth/sign-in-code.d.ts +4 -0
- package/dist/auth/sign-in-code.d.ts.map +1 -1
- package/dist/auth/types/email-flows.d.ts +18 -0
- package/dist/auth/types/email-flows.d.ts.map +1 -1
- package/dist/auth/types/index.d.ts +2 -0
- package/dist/auth/types/index.d.ts.map +1 -1
- package/dist/auth/types/janus.d.ts +7 -5
- package/dist/auth/types/janus.d.ts.map +1 -1
- package/dist/auth/types/magic-link.d.ts +11 -0
- package/dist/auth/types/magic-link.d.ts.map +1 -1
- package/dist/auth/types/prepared.d.ts +41 -0
- package/dist/auth/types/prepared.d.ts.map +1 -0
- package/dist/auth/types/proven-sign-in.d.ts +43 -0
- package/dist/auth/types/proven-sign-in.d.ts.map +1 -0
- package/dist/auth/types/sign-in.d.ts +2 -2
- package/dist/auth/types/user-type.d.ts +15 -0
- package/dist/auth/types/user-type.d.ts.map +1 -1
- package/dist/auth/users/any-type-api.d.ts +2 -2
- package/dist/auth/users/any-type-api.d.ts.map +1 -1
- package/dist/auth/users/find-many.d.ts +29 -0
- package/dist/auth/users/find-many.d.ts.map +1 -0
- package/dist/auth/users/record-flows.d.ts.map +1 -1
- package/dist/auth/users/type-api.d.ts +2 -2
- package/dist/auth/users/type-api.d.ts.map +1 -1
- package/dist/chunks/{index-kvjj5xkp.js → index-6bjfv4xv.js} +8 -2
- package/dist/chunks/{index-kvjj5xkp.js.map → index-6bjfv4xv.js.map} +3 -3
- package/dist/conformance/cases/outage.d.ts.map +1 -1
- package/dist/conformance/cases/users/batch.d.ts +8 -0
- package/dist/conformance/cases/users/batch.d.ts.map +1 -0
- package/dist/conformance/cases/users/index.d.ts.map +1 -1
- package/dist/conformance/describe.d.ts +2 -1
- package/dist/conformance/describe.d.ts.map +1 -1
- package/dist/conformance/index.d.ts +1 -1
- package/dist/conformance/index.d.ts.map +1 -1
- package/dist/conformance/index.js +104 -44
- package/dist/conformance/index.js.map +7 -6
- package/dist/conformance/types.d.ts +10 -2
- package/dist/conformance/types.d.ts.map +1 -1
- package/dist/index.js +150 -23
- package/dist/index.js.map +14 -11
- package/docs/README.md +1 -1
- package/docs/guide/adapters.md +44 -4
- package/docs/guide/devices.md +4 -0
- package/docs/guide/email-flows.md +105 -0
- package/docs/guide/errors.md +2 -2
- package/docs/guide/events.md +2 -2
- package/docs/guide/magic-link.md +49 -2
- package/docs/guide/passwords.md +5 -2
- package/docs/guide/second-factor.md +1 -1
- package/docs/guide/sessions.md +94 -1
- package/docs/guide/sign-in-code.md +54 -2
- package/docs/guide/users.md +49 -0
- package/docs/roadmap.md +28 -39
- package/docs/troubleshooting.md +120 -7
- package/package.json +1 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
mintId2,
|
|
3
3
|
createMemoryStores2
|
|
4
|
-
} from "../chunks/index-
|
|
4
|
+
} from "../chunks/index-6bjfv4xv.js";
|
|
5
5
|
import {
|
|
6
6
|
JanusError2,
|
|
7
7
|
StoreFailure2,
|
|
@@ -180,6 +180,10 @@ var seed = async ({ stores }) => {
|
|
|
180
180
|
};
|
|
181
181
|
var outageCases = [
|
|
182
182
|
outage("users", "findUser", ({ stores }) => stores.users.findUser(user.id), seed),
|
|
183
|
+
{
|
|
184
|
+
...outage("users", "findUsers", async ({ stores }) => stores.users.findUsers?.call(stores.users, [user.id]), seed),
|
|
185
|
+
needs: ["faults", "findUsers"]
|
|
186
|
+
},
|
|
183
187
|
outage("users", "findUserByLogin", ({ stores }) => stores.users.findUserByLogin(user.type, user.logins[0] ?? ""), seed),
|
|
184
188
|
outage("users", "listUsers", ({ stores }) => stores.users.listUsers({ type: user.type, after: null, limit: 10 }), seed),
|
|
185
189
|
outage("sessions", "findSessionByTokenHash", ({ stores }) => stores.sessions.findSessionByTokenHash(session.tokenHash), seed),
|
|
@@ -755,12 +759,51 @@ var tokenStoreCases = [
|
|
|
755
759
|
...tokenKindCases,
|
|
756
760
|
...tokenDeletionCases
|
|
757
761
|
];
|
|
758
|
-
// src/conformance/cases/users/
|
|
762
|
+
// src/conformance/cases/users/batch.ts
|
|
759
763
|
var group13 = "users";
|
|
764
|
+
var byId = (a, b) => a.id < b.id ? -1 : a.id > b.id ? 1 : 0;
|
|
765
|
+
var userBatchCases = [
|
|
766
|
+
{
|
|
767
|
+
id: "users.findUsers",
|
|
768
|
+
group: group13,
|
|
769
|
+
name: "findUsers answers each stored user once, byte for byte and whatever its type, and leaves out an id nobody holds",
|
|
770
|
+
needs: "findUsers",
|
|
771
|
+
async run({ stores }) {
|
|
772
|
+
const findUsers = stores.users.findUsers;
|
|
773
|
+
ok(findUsers !== undefined, "findUsers should be present");
|
|
774
|
+
const patient = userRecord({ type: "patient" });
|
|
775
|
+
const staff = userRecord({ type: "staff" });
|
|
776
|
+
const other = userRecord();
|
|
777
|
+
for (const record of [patient, staff, other]) {
|
|
778
|
+
await stores.users.insertUser(record);
|
|
779
|
+
}
|
|
780
|
+
const answer = await findUsers?.call(stores.users, [
|
|
781
|
+
staff.id,
|
|
782
|
+
mintId2(),
|
|
783
|
+
patient.id
|
|
784
|
+
]);
|
|
785
|
+
ok(Array.isArray(answer), "findUsers should answer a list — an absence is a shorter list, never null");
|
|
786
|
+
equal([...answer ?? []].sort(byId), [patient, staff].sort(byId), "findUsers should answer the two stored users exactly as written, and only them");
|
|
787
|
+
}
|
|
788
|
+
},
|
|
789
|
+
{
|
|
790
|
+
id: "users.findUsersNone",
|
|
791
|
+
group: group13,
|
|
792
|
+
name: "findUsers answers an empty list, not null, when no id is held",
|
|
793
|
+
needs: "findUsers",
|
|
794
|
+
async run({ stores }) {
|
|
795
|
+
await stores.users.insertUser(userRecord());
|
|
796
|
+
equal(await stores.users.findUsers?.call(stores.users, [mintId2(), mintId2()]), [], "findUsers for ids nobody holds should answer []");
|
|
797
|
+
}
|
|
798
|
+
}
|
|
799
|
+
];
|
|
800
|
+
|
|
801
|
+
// src/conformance/cases/users/deletion.ts
|
|
802
|
+
var group14 = "users";
|
|
760
803
|
var userDeletionCases = [
|
|
761
804
|
{
|
|
762
805
|
id: "users.delete",
|
|
763
|
-
group:
|
|
806
|
+
group: group14,
|
|
764
807
|
name: "deletes a user and frees their logins, answers false for nobody, and touches no other user",
|
|
765
808
|
async run({ stores }) {
|
|
766
809
|
const record = userRecord();
|
|
@@ -780,11 +823,11 @@ var userDeletionCases = [
|
|
|
780
823
|
];
|
|
781
824
|
|
|
782
825
|
// src/conformance/cases/users/inserts.ts
|
|
783
|
-
var
|
|
826
|
+
var group15 = "users";
|
|
784
827
|
var userInsertCases = [
|
|
785
828
|
{
|
|
786
829
|
id: "users.idempotentInsert",
|
|
787
|
-
group:
|
|
830
|
+
group: group15,
|
|
788
831
|
name: "is idempotent under retry: inserting an existing id answers the stored record and writes nothing",
|
|
789
832
|
async run({ stores }) {
|
|
790
833
|
const record = userRecord();
|
|
@@ -799,7 +842,7 @@ var userInsertCases = [
|
|
|
799
842
|
},
|
|
800
843
|
{
|
|
801
844
|
id: "users.uniqueness",
|
|
802
|
-
group:
|
|
845
|
+
group: group15,
|
|
803
846
|
name: "lets exactly one of twenty concurrent inserts hold a login: uniqueness is a constraint, not a read",
|
|
804
847
|
async run({ stores }) {
|
|
805
848
|
const records = Array.from({ length: 20 }, () => userRecord({ logins: ["contested@example.test"] }));
|
|
@@ -824,11 +867,11 @@ var userInsertCases = [
|
|
|
824
867
|
];
|
|
825
868
|
|
|
826
869
|
// src/conformance/cases/users/listing.ts
|
|
827
|
-
var
|
|
870
|
+
var group16 = "users";
|
|
828
871
|
var userListingCases = [
|
|
829
872
|
{
|
|
830
873
|
id: "users.pagination",
|
|
831
|
-
group:
|
|
874
|
+
group: group16,
|
|
832
875
|
name: "pages 25 users of one type by 10 in ascending id order, with no gap, no repeat and no other type, and ends on a null cursor",
|
|
833
876
|
async run({ stores }) {
|
|
834
877
|
const records = Array.from({ length: 25 }, () => userRecord());
|
|
@@ -929,11 +972,11 @@ async function nullClearsCodes(stores, id) {
|
|
|
929
972
|
}
|
|
930
973
|
|
|
931
974
|
// src/conformance/cases/users/patches.ts
|
|
932
|
-
var
|
|
975
|
+
var group17 = "users";
|
|
933
976
|
var userPatchCases = [
|
|
934
977
|
{
|
|
935
978
|
id: "users.omission",
|
|
936
|
-
group:
|
|
979
|
+
group: group17,
|
|
937
980
|
name: "omission — the Kratos PUT trap: an update leaves every field it does not name exactly as it was",
|
|
938
981
|
async run({ stores }) {
|
|
939
982
|
const record = userRecord({
|
|
@@ -958,7 +1001,7 @@ var userPatchCases = [
|
|
|
958
1001
|
},
|
|
959
1002
|
{
|
|
960
1003
|
id: "users.passwordSlot",
|
|
961
|
-
group:
|
|
1004
|
+
group: group17,
|
|
962
1005
|
name: "keeps a password the patch does not name, and removes one the patch names null",
|
|
963
1006
|
async run({ stores }) {
|
|
964
1007
|
const record = userRecord();
|
|
@@ -972,7 +1015,7 @@ var userPatchCases = [
|
|
|
972
1015
|
secondFactorSlotCase,
|
|
973
1016
|
{
|
|
974
1017
|
id: "users.loginsMove",
|
|
975
|
-
group:
|
|
1018
|
+
group: group17,
|
|
976
1019
|
name: "moves logins on update: the old one is free, the new one found, one held elsewhere refused",
|
|
977
1020
|
async run({ stores }) {
|
|
978
1021
|
const record = userRecord();
|
|
@@ -993,11 +1036,11 @@ var userPatchCases = [
|
|
|
993
1036
|
];
|
|
994
1037
|
|
|
995
1038
|
// src/conformance/cases/users/reads.ts
|
|
996
|
-
var
|
|
1039
|
+
var group18 = "users";
|
|
997
1040
|
var userReadCases = [
|
|
998
1041
|
{
|
|
999
1042
|
id: "users.roundTrip",
|
|
1000
|
-
group:
|
|
1043
|
+
group: group18,
|
|
1001
1044
|
name: 'round-trips a record byte for byte: nested fields, a 1 that stays a number, a "1" that stays a string',
|
|
1002
1045
|
async run({ stores }) {
|
|
1003
1046
|
const record = userRecord({
|
|
@@ -1021,7 +1064,7 @@ var userReadCases = [
|
|
|
1021
1064
|
},
|
|
1022
1065
|
{
|
|
1023
1066
|
id: "users.edgeCharacters",
|
|
1024
|
-
group:
|
|
1067
|
+
group: group18,
|
|
1025
1068
|
name: "round-trips every character the core lets through: control characters, U+FFFF and a surrogate pair",
|
|
1026
1069
|
async run({ stores }) {
|
|
1027
1070
|
const edge = "a\x01\x1F \uD83D\uDE00 z";
|
|
@@ -1036,7 +1079,7 @@ var userReadCases = [
|
|
|
1036
1079
|
},
|
|
1037
1080
|
{
|
|
1038
1081
|
id: "users.absence",
|
|
1039
|
-
group:
|
|
1082
|
+
group: group18,
|
|
1040
1083
|
name: "answers null for an absence, never undefined, and an empty page for an empty store",
|
|
1041
1084
|
async run({ stores }) {
|
|
1042
1085
|
isNull(await stores.users.findUser(mintId2()), "findUser for an unknown id");
|
|
@@ -1046,7 +1089,7 @@ var userReadCases = [
|
|
|
1046
1089
|
},
|
|
1047
1090
|
{
|
|
1048
1091
|
id: "users.loginBytes",
|
|
1049
|
-
group:
|
|
1092
|
+
group: group18,
|
|
1050
1093
|
name: "compares logins as bytes, within one type: no case folding, no trimming, no collation",
|
|
1051
1094
|
async run({ stores }) {
|
|
1052
1095
|
const upper = userRecord({ logins: ["Ada@Example.test"] });
|
|
@@ -1063,11 +1106,11 @@ var userReadCases = [
|
|
|
1063
1106
|
];
|
|
1064
1107
|
|
|
1065
1108
|
// src/conformance/cases/users/versions.ts
|
|
1066
|
-
var
|
|
1109
|
+
var group19 = "users";
|
|
1067
1110
|
var userVersionCases = [
|
|
1068
1111
|
{
|
|
1069
1112
|
id: "users.versionIncrements",
|
|
1070
|
-
group:
|
|
1113
|
+
group: group19,
|
|
1071
1114
|
name: "applies an update at the expected version, and answers the record written with its version one higher",
|
|
1072
1115
|
async run({ stores }) {
|
|
1073
1116
|
const record = userRecord();
|
|
@@ -1085,7 +1128,7 @@ var userVersionCases = [
|
|
|
1085
1128
|
},
|
|
1086
1129
|
{
|
|
1087
1130
|
id: "users.versionConflict",
|
|
1088
|
-
group:
|
|
1131
|
+
group: group19,
|
|
1089
1132
|
name: "refuses a stale version with both versions, and leaves the record identical byte for byte",
|
|
1090
1133
|
async run({ stores }) {
|
|
1091
1134
|
const record = userRecord();
|
|
@@ -1106,7 +1149,7 @@ var userVersionCases = [
|
|
|
1106
1149
|
},
|
|
1107
1150
|
{
|
|
1108
1151
|
id: "users.unknownUpdate",
|
|
1109
|
-
group:
|
|
1152
|
+
group: group19,
|
|
1110
1153
|
name: "refuses an update to an unknown id with NotFoundError, told apart from a version conflict",
|
|
1111
1154
|
async run({ stores }) {
|
|
1112
1155
|
const error = await rejects(stores.users.updateUser(mintId2(), { updatedAt: at("2026-02-01T00:00:00.000Z") }, 0), "updateUser on an unknown id should reject");
|
|
@@ -1118,6 +1161,7 @@ var userVersionCases = [
|
|
|
1118
1161
|
// src/conformance/cases/users/index.ts
|
|
1119
1162
|
var userStoreCases = [
|
|
1120
1163
|
...userReadCases,
|
|
1164
|
+
...userBatchCases,
|
|
1121
1165
|
...userInsertCases,
|
|
1122
1166
|
...userVersionCases,
|
|
1123
1167
|
...userPatchCases,
|
|
@@ -1133,17 +1177,15 @@ var allCases = [
|
|
|
1133
1177
|
];
|
|
1134
1178
|
var SKIP_REASONS = {
|
|
1135
1179
|
faults: "faults not provided: the outage invariant is not proven for this adapter",
|
|
1136
|
-
deleteExpiredSessions: "stores.sessions does not implement the optional deleteExpiredSessions"
|
|
1180
|
+
deleteExpiredSessions: "stores.sessions does not implement the optional deleteExpiredSessions",
|
|
1181
|
+
findUsers: "stores.users does not implement the optional findUsers: findMany reads with findUser instead"
|
|
1137
1182
|
};
|
|
1138
1183
|
async function runCase(conformanceCase, harness) {
|
|
1139
1184
|
const opened = await harness.open();
|
|
1140
1185
|
try {
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
if (conformanceCase.needs === "deleteExpiredSessions" && opened.stores.sessions.deleteExpiredSessions === undefined) {
|
|
1145
|
-
return { skipped: SKIP_REASONS.deleteExpiredSessions };
|
|
1146
|
-
}
|
|
1186
|
+
const missing = needsOf(conformanceCase).find((need) => !provides(opened, need));
|
|
1187
|
+
if (missing !== undefined)
|
|
1188
|
+
return { skipped: SKIP_REASONS[missing] };
|
|
1147
1189
|
await conformanceCase.run({
|
|
1148
1190
|
stores: opened.stores,
|
|
1149
1191
|
faults: opened.faults ?? null
|
|
@@ -1153,6 +1195,20 @@ async function runCase(conformanceCase, harness) {
|
|
|
1153
1195
|
await opened.close?.();
|
|
1154
1196
|
}
|
|
1155
1197
|
}
|
|
1198
|
+
function needsOf(conformanceCase) {
|
|
1199
|
+
const { needs } = conformanceCase;
|
|
1200
|
+
return needs === undefined ? [] : typeof needs === "string" ? [needs] : needs;
|
|
1201
|
+
}
|
|
1202
|
+
function provides(opened, need) {
|
|
1203
|
+
switch (need) {
|
|
1204
|
+
case "faults":
|
|
1205
|
+
return opened.faults !== undefined;
|
|
1206
|
+
case "deleteExpiredSessions":
|
|
1207
|
+
return opened.stores.sessions.deleteExpiredSessions !== undefined;
|
|
1208
|
+
case "findUsers":
|
|
1209
|
+
return opened.stores.users.findUsers !== undefined;
|
|
1210
|
+
}
|
|
1211
|
+
}
|
|
1156
1212
|
function describeJanusStores(options) {
|
|
1157
1213
|
describeSuite({
|
|
1158
1214
|
title: `${options.name} — @nxgt/janus conformance`,
|
|
@@ -1163,6 +1219,10 @@ function describeJanusStores(options) {
|
|
|
1163
1219
|
faults: options.faults
|
|
1164
1220
|
});
|
|
1165
1221
|
}
|
|
1222
|
+
function needsList(described) {
|
|
1223
|
+
const { needs } = described;
|
|
1224
|
+
return needs === undefined ? [] : typeof needs === "string" ? [needs] : needs;
|
|
1225
|
+
}
|
|
1166
1226
|
function describeSuite(options) {
|
|
1167
1227
|
const { runner, skip, cases } = options;
|
|
1168
1228
|
const groups = [...new Set(cases.map((c) => c.group))];
|
|
@@ -1176,7 +1236,7 @@ function describeSuite(options) {
|
|
|
1176
1236
|
runner.it.skip(`${conformanceCase.name} — skipped: ${reason}`, async () => {});
|
|
1177
1237
|
continue;
|
|
1178
1238
|
}
|
|
1179
|
-
if (conformanceCase.
|
|
1239
|
+
if (needsList(conformanceCase).includes("faults") && options.faults === false) {
|
|
1180
1240
|
runner.it.skip(`${conformanceCase.name} — skipped: ${SKIP_REASONS.faults}`, async () => {});
|
|
1181
1241
|
continue;
|
|
1182
1242
|
}
|
|
@@ -1249,11 +1309,11 @@ var tuple = (object, relation, subject) => ({ object, relation, subject });
|
|
|
1249
1309
|
var sorted = (subjects) => subjects.map(formatSubject2).sort();
|
|
1250
1310
|
|
|
1251
1311
|
// src/conformance/relations/cases/deletion.ts
|
|
1252
|
-
var
|
|
1312
|
+
var group20 = "relations";
|
|
1253
1313
|
var relationDeletionCases = [
|
|
1254
1314
|
{
|
|
1255
1315
|
id: "relations.deleteEntity",
|
|
1256
|
-
group:
|
|
1316
|
+
group: group20,
|
|
1257
1317
|
name: "deletes every tuple naming an entity — as object, as subject, as a set’s entity — and counts them",
|
|
1258
1318
|
async run({ store }) {
|
|
1259
1319
|
const team = entity("team");
|
|
@@ -1280,11 +1340,11 @@ var relationDeletionCases = [
|
|
|
1280
1340
|
];
|
|
1281
1341
|
|
|
1282
1342
|
// src/conformance/relations/cases/reads.ts
|
|
1283
|
-
var
|
|
1343
|
+
var group21 = "relations";
|
|
1284
1344
|
var relationReadCases = [
|
|
1285
1345
|
{
|
|
1286
1346
|
id: "relations.roundTrip",
|
|
1287
|
-
group:
|
|
1347
|
+
group: group21,
|
|
1288
1348
|
name: "holds exactly the tuples written, byte for byte: staff:u1 is not patient:u1, and a set is not its entity",
|
|
1289
1349
|
async run({ store }) {
|
|
1290
1350
|
const record = entity("record", "R:1 — ÿ");
|
|
@@ -1300,7 +1360,7 @@ var relationReadCases = [
|
|
|
1300
1360
|
},
|
|
1301
1361
|
{
|
|
1302
1362
|
id: "relations.edgeCharacters",
|
|
1303
|
-
group:
|
|
1363
|
+
group: group21,
|
|
1304
1364
|
name: "round-trips every character the core lets through in an id: control characters, U+FFFF and a surrogate pair",
|
|
1305
1365
|
async run({ store }) {
|
|
1306
1366
|
const edge = "a\x01\x1F \uD83D\uDE00 z";
|
|
@@ -1323,7 +1383,7 @@ var relationReadCases = [
|
|
|
1323
1383
|
},
|
|
1324
1384
|
{
|
|
1325
1385
|
id: "relations.undefinedRelation",
|
|
1326
|
-
group:
|
|
1386
|
+
group: group21,
|
|
1327
1387
|
name: "reads a subject whose relation is undefined as its entity, not as a set",
|
|
1328
1388
|
async run({ store }) {
|
|
1329
1389
|
const record = entity("record");
|
|
@@ -1353,7 +1413,7 @@ var relationReadCases = [
|
|
|
1353
1413
|
},
|
|
1354
1414
|
{
|
|
1355
1415
|
id: "relations.absence",
|
|
1356
|
-
group:
|
|
1416
|
+
group: group21,
|
|
1357
1417
|
name: "answers false, [], an empty page and 0 for an empty store — never null or undefined",
|
|
1358
1418
|
async run({ store }) {
|
|
1359
1419
|
const record = entity("record");
|
|
@@ -1374,11 +1434,11 @@ var relationReadCases = [
|
|
|
1374
1434
|
];
|
|
1375
1435
|
|
|
1376
1436
|
// src/conformance/relations/cases/traversal.ts
|
|
1377
|
-
var
|
|
1437
|
+
var group22 = "relations";
|
|
1378
1438
|
var relationTraversalCases = [
|
|
1379
1439
|
{
|
|
1380
1440
|
id: "relations.oneHop",
|
|
1381
|
-
group:
|
|
1441
|
+
group: group22,
|
|
1382
1442
|
name: "answers one hop: the subject sets and the entities holding one relation on one object, and nothing else",
|
|
1383
1443
|
async run({ store }) {
|
|
1384
1444
|
const record = entity("record");
|
|
@@ -1402,7 +1462,7 @@ var relationTraversalCases = [
|
|
|
1402
1462
|
},
|
|
1403
1463
|
{
|
|
1404
1464
|
id: "relations.objects",
|
|
1405
|
-
group:
|
|
1465
|
+
group: group22,
|
|
1406
1466
|
name: "pages 25 objects by 10 in ascending id order, for one type, relation and exact subject, and ends on a null cursor",
|
|
1407
1467
|
async run({ store }) {
|
|
1408
1468
|
const staff = entity("staff");
|
|
@@ -1449,11 +1509,11 @@ var relationTraversalCases = [
|
|
|
1449
1509
|
];
|
|
1450
1510
|
|
|
1451
1511
|
// src/conformance/relations/cases/writes.ts
|
|
1452
|
-
var
|
|
1512
|
+
var group23 = "relations";
|
|
1453
1513
|
var relationWriteCases = [
|
|
1454
1514
|
{
|
|
1455
1515
|
id: "relations.idempotentWrite",
|
|
1456
|
-
group:
|
|
1516
|
+
group: group23,
|
|
1457
1517
|
name: "is idempotent under retry: adding a stored tuple and removing an absent one write nothing",
|
|
1458
1518
|
async run({ store }) {
|
|
1459
1519
|
const record = entity("record");
|
|
@@ -1466,7 +1526,7 @@ var relationWriteCases = [
|
|
|
1466
1526
|
},
|
|
1467
1527
|
{
|
|
1468
1528
|
id: "relations.uniqueness",
|
|
1469
|
-
group:
|
|
1529
|
+
group: group23,
|
|
1470
1530
|
name: "keeps one tuple when twenty concurrent writes add it: uniqueness is a constraint, not a read",
|
|
1471
1531
|
async run({ store }) {
|
|
1472
1532
|
const record = entity("record");
|
|
@@ -1477,7 +1537,7 @@ var relationWriteCases = [
|
|
|
1477
1537
|
},
|
|
1478
1538
|
{
|
|
1479
1539
|
id: "relations.removeThenAdd",
|
|
1480
|
-
group:
|
|
1540
|
+
group: group23,
|
|
1481
1541
|
name: "applies one write’s removals and additions together",
|
|
1482
1542
|
async run({ store }) {
|
|
1483
1543
|
const record = entity("record");
|
|
@@ -1612,5 +1672,5 @@ export {
|
|
|
1612
1672
|
userStoreCases
|
|
1613
1673
|
};
|
|
1614
1674
|
|
|
1615
|
-
//# debugId=
|
|
1675
|
+
//# debugId=E36CAD1FA03131AF64756E2164756E21
|
|
1616
1676
|
//# sourceMappingURL=index.js.map
|