@lovrozagar/oat 0.12.7 → 0.12.11
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/dist/conformance/suite.d.ts.map +1 -1
- package/dist/conformance/suite.js +3 -0
- package/dist/conformance/suite.js.map +1 -1
- package/dist/reference/defects.d.ts +2 -0
- package/dist/reference/defects.d.ts.map +1 -1
- package/dist/reference/defects.js +2 -0
- package/dist/reference/defects.js.map +1 -1
- package/dist/reference/http.d.ts.map +1 -1
- package/dist/reference/http.js +12 -0
- package/dist/reference/http.js.map +1 -1
- package/dist/reference/spec.d.ts.map +1 -1
- package/dist/reference/spec.js +41 -1
- package/dist/reference/spec.js.map +1 -1
- package/dist/runtime/check-costs.d.ts.map +1 -1
- package/dist/runtime/check-costs.js +1 -0
- package/dist/runtime/check-costs.js.map +1 -1
- package/dist/runtime/check-ids.d.ts +1 -1
- package/dist/runtime/check-ids.d.ts.map +1 -1
- package/dist/runtime/check-ids.js +1 -0
- package/dist/runtime/check-ids.js.map +1 -1
- package/dist/runtime/checks.d.ts.map +1 -1
- package/dist/runtime/checks.js +42 -0
- package/dist/runtime/checks.js.map +1 -1
- package/dist/runtime/effects.d.ts.map +1 -1
- package/dist/runtime/effects.js +5 -2
- package/dist/runtime/effects.js.map +1 -1
- package/dist/runtime/run.js +1 -1
- package/dist/runtime/run.js.map +1 -1
- package/dist/runtime/scope.d.ts.map +1 -1
- package/dist/runtime/scope.js +9 -1
- package/dist/runtime/scope.js.map +1 -1
- package/dist/runtime/world.d.ts.map +1 -1
- package/dist/runtime/world.js +1 -0
- package/dist/runtime/world.js.map +1 -1
- package/package.json +31 -9
package/dist/runtime/checks.js
CHANGED
|
@@ -856,6 +856,44 @@ function itemParamFor(ctx, id) {
|
|
|
856
856
|
const param = op?.pathParams.at(-1);
|
|
857
857
|
return param === undefined ? {} : { [param]: id };
|
|
858
858
|
}
|
|
859
|
+
function listedRowMatches(listed, body) {
|
|
860
|
+
if (body === null || typeof body !== "object" || Array.isArray(body))
|
|
861
|
+
return false;
|
|
862
|
+
const got = body;
|
|
863
|
+
return Object.entries(listed).every(([key, value]) => JSON.stringify(got[key]) === JSON.stringify(value));
|
|
864
|
+
}
|
|
865
|
+
/** A list with no create still has a get. The get body is the row the list already returned. */
|
|
866
|
+
const listedRowIsTheGet = {
|
|
867
|
+
plan: (ctx) => {
|
|
868
|
+
if (ctx.readOp === undefined || ctx.createOp !== undefined)
|
|
869
|
+
return cannot();
|
|
870
|
+
const listed = ctx.records[0];
|
|
871
|
+
const id = listed?.[ctx.identity];
|
|
872
|
+
if (listed === undefined || (typeof id !== "string" && typeof id !== "number")) {
|
|
873
|
+
return cannot("the list returned no id");
|
|
874
|
+
}
|
|
875
|
+
return ready({ id: String(id), listed });
|
|
876
|
+
},
|
|
877
|
+
id: "list.item-matches-listed-row",
|
|
878
|
+
needs: "a list with no create and one listed row",
|
|
879
|
+
subjects: (entity) => (entity.read === undefined ? [] : [entity.read]),
|
|
880
|
+
async run(ctx, { id, listed }) {
|
|
881
|
+
const op = ctx.readOp;
|
|
882
|
+
if (op === undefined)
|
|
883
|
+
return standDown("the entity has no read");
|
|
884
|
+
const item = await ctx.client.get(fillPath(op.path, { ...ctx.scope, ...itemParamFor(ctx, id) }), {
|
|
885
|
+
headers: ctx.auth(),
|
|
886
|
+
operationId: op.operationId,
|
|
887
|
+
});
|
|
888
|
+
if (item.status >= 300) {
|
|
889
|
+
return ctx.findings.backend(this.id, ctx.entityName, "the listed row is not returned by its get", `${op.operationId} returned ${item.status} for ${ctx.entityName} ${id}`, [item]);
|
|
890
|
+
}
|
|
891
|
+
if (!listedRowMatches(listed, item.responseBody)) {
|
|
892
|
+
return ctx.findings.backend(this.id, ctx.entityName, "the get body is not the listed row", `${op.operationId} returned a body that does not contain the row ${ctx.listOp?.operationId ?? "the list"} already returned for ${id}`, [item]);
|
|
893
|
+
}
|
|
894
|
+
return ASSERTED;
|
|
895
|
+
},
|
|
896
|
+
};
|
|
859
897
|
/**
|
|
860
898
|
* Isolation checks need a tenant boundary to have meaning. A public catalogue has neither
|
|
861
899
|
* `x-tenant` nor a path parameter that looks like one; a 200 from another principal is the
|
|
@@ -4029,6 +4067,9 @@ const errorSchemaHonoured = {
|
|
|
4029
4067
|
]),
|
|
4030
4068
|
],
|
|
4031
4069
|
async run(ctx, { raw, readOp, validator }) {
|
|
4070
|
+
/* An empty list has no id to miss. Probing one would grade the get without a row. */
|
|
4071
|
+
if (ctx.createOp === undefined && ctx.records.length === 0)
|
|
4072
|
+
return standDown("the list returned no id");
|
|
4032
4073
|
const judged = [];
|
|
4033
4074
|
if (graded(ctx, readOp)) {
|
|
4034
4075
|
await probeMissingItemError(ctx, readOp, raw, validator, this.id);
|
|
@@ -6977,6 +7018,7 @@ export const CHECKS = [
|
|
|
6977
7018
|
* Everything below assumes these hold, so they must be evaluated first for cascade
|
|
6978
7019
|
* suppression to have anything to consult. */
|
|
6979
7020
|
readAfterWrite,
|
|
7021
|
+
listedRowIsTheGet,
|
|
6980
7022
|
createPersistsFields,
|
|
6981
7023
|
createStatusMatchesSpec,
|
|
6982
7024
|
successSchemaHonoured,
|