@aventara/core 1.0.0-rc.10 → 1.0.0-rc.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/CHANGELOG.md +79 -0
- package/ERRORS.md +82 -82
- package/README.md +57 -1
- package/dist/compiler/contract-compiler-diagnostic.guidance.js +1 -1
- package/dist/compiler/contract.compiler.js +56 -9
- package/dist/compiler/create-requirements.projector.js +1 -3
- package/dist/compiler/field-validator.compiler.js +1 -3
- package/dist/compiler/managed-elsewhere.projector.js +5 -5
- package/dist/config/cache-stage.factory.d.ts +24 -0
- package/dist/config/cache-stage.factory.js +3 -0
- package/dist/config/config.resolver.js +1 -7
- package/dist/config/config.validator.js +61 -13
- package/dist/config/exact-framework-config.d.ts +6 -0
- package/dist/config/field-compute.resolver.js +1 -3
- package/dist/config/pipeline-config.d.ts +16 -0
- package/dist/config/pipeline-tree.resolver.js +2 -3
- package/dist/contracts/canonical-json.writer.d.ts +7 -0
- package/dist/contracts/canonical-json.writer.js +55 -0
- package/dist/contracts/client-contract-structure.validator.d.ts +64 -0
- package/dist/contracts/client-contract-structure.validator.js +12 -0
- package/dist/contracts/contract-canonicalizer.js +5 -0
- package/dist/contracts/contract-limits.d.ts +6 -0
- package/dist/contracts/contract-limits.js +2 -0
- package/dist/contracts/contract.d.ts +15 -0
- package/dist/contracts/json-schema.projector.js +1 -3
- package/dist/framework/access-facade.js +1 -3
- package/dist/framework/framework.factory.js +42 -13
- package/dist/framework/operation-facade.d.ts +67 -6
- package/dist/framework/operation-facade.js +7 -0
- package/dist/framework/operation-set.runner.d.ts +47 -0
- package/dist/framework/operation-set.runner.js +168 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2 -0
- package/dist/internal.d.ts +2 -0
- package/dist/internal.js +2 -0
- package/dist/operations/operation-validator-core.js +2 -4
- package/dist/operations/structural-limits.walker.js +1 -3
- package/dist/policy/access-question.runtime.js +1 -3
- package/dist/policy/policy-admission.js +1 -3
- package/dist/policy/policy-after-update.runtime.js +1 -3
- package/dist/policy/policy-nested-write.runtime.js +3 -12
- package/dist/policy/policy-read.runtime.js +1 -3
- package/dist/policy/policy-reference-write.runtime.js +2 -11
- package/dist/policy/policy-request.d.ts +31 -0
- package/dist/policy/policy-request.js +69 -17
- package/dist/policy/policy-session.js +1 -3
- package/dist/policy/policy-write.runtime.js +1 -3
- package/dist/prebuilt/core-version.generated.d.ts +1 -1
- package/dist/prebuilt/core-version.generated.js +1 -1
- package/dist/prebuilt/prebuilt-changes.js +1 -3
- package/dist/prebuilt/prebuilt-contracts.loader.js +1 -3
- package/dist/prebuilt/prebuilt-inputs.fingerprint.js +1 -3
- package/dist/protocol/absent-route.responder.d.ts +69 -16
- package/dist/protocol/absent-route.responder.js +75 -31
- package/dist/protocol/contract-document.responder.d.ts +7 -0
- package/dist/protocol/contract-document.responder.js +3 -2
- package/dist/protocol/http-request.decoder.d.ts +33 -0
- package/dist/protocol/http-request.decoder.js +23 -7
- package/dist/protocol/http-request.reader.d.ts +4 -0
- package/dist/protocol/http-request.reader.js +11 -2
- package/dist/protocol/http-response.encoder.d.ts +12 -0
- package/dist/protocol/http-response.encoder.js +15 -1
- package/dist/protocol/operation-response.guard.js +1 -3
- package/dist/protocol/operation-set.decoder.d.ts +48 -0
- package/dist/protocol/operation-set.decoder.js +185 -0
- package/dist/protocol/operation-set.handler.d.ts +27 -0
- package/dist/protocol/operation-set.handler.js +179 -0
- package/dist/protocol/protocol-headers.d.ts +9 -0
- package/dist/protocol/protocol-headers.js +12 -5
- package/dist/protocol/protocol-surface.d.ts +12 -4
- package/dist/protocol/protocol-surface.js +34 -1
- package/dist/protocol/protocol.binder.d.ts +37 -1
- package/dist/protocol/protocol.binder.js +2 -0
- package/dist/protocol/protocol.handler.d.ts +35 -2
- package/dist/protocol/protocol.handler.js +84 -8
- package/dist/protocol/read-cache.responder.d.ts +26 -0
- package/dist/protocol/read-cache.responder.js +47 -0
- package/dist/protocol/read-query.codec.d.ts +34 -0
- package/dist/protocol/read-query.codec.js +125 -0
- package/dist/runtime/computed-read-runtime.js +2 -8
- package/dist/runtime/create-requirement.js +1 -3
- package/dist/runtime/diagnostics-reporter.d.ts +6 -1
- package/dist/runtime/diagnostics-reporter.js +3 -8
- package/dist/runtime/error.catalog.d.ts +2 -2
- package/dist/runtime/error.catalog.js +1 -1
- package/dist/runtime/field-stage.runtime.d.ts +0 -2
- package/dist/runtime/field-stage.runtime.js +1 -7
- package/dist/runtime/field-validator.runtime.js +2 -1
- package/dist/runtime/mutation-planner.js +1 -3
- package/dist/runtime/nested-write.walker.js +2 -1
- package/dist/runtime/output-validator.js +1 -3
- package/dist/runtime/owned-execution.registry.d.ts +22 -2
- package/dist/runtime/pipeline.d.ts +5 -1
- package/dist/runtime/record.guard.d.ts +14 -0
- package/dist/runtime/record.guard.js +10 -0
- package/dist/runtime/request-envelope.validator.js +13 -10
- package/dist/runtime/scalar-runtime.d.ts +0 -10
- package/dist/runtime/scalar-runtime.js +1 -10
- package/dist/runtime/thenable.guard.d.ts +7 -0
- package/dist/runtime/thenable.guard.js +5 -0
- package/dist/runtime/unsent-value.normalizer.js +2 -1
- package/dist/transactions/operation-arguments-encoder.js +1 -7
- package/dist/transactions/sql-statement.validator.js +2 -1
- package/dist/transactions/transaction-plan-assembler.js +1 -7
- package/dist/transactions/transaction-plan-validator.js +4 -6
- package/dist/transactions/transaction-reference-collector.js +8 -10
- package/dist/transactions/transaction-reference-resolver.js +1 -3
- package/dist/transactions/transaction-runtime.js +31 -2
- package/dist/transactions/transaction-stage.runtime.js +1 -3
- package/package.json +1 -1
|
@@ -1,10 +1,13 @@
|
|
|
1
|
+
import { isRecord } from "./record.guard.js";
|
|
1
2
|
const ORIGINS = ["application", "client", "agent"];
|
|
2
3
|
const OPERATION_IDENTITY_MEMBERS = ["resource", "family", "variant"];
|
|
3
4
|
export function validateOperationEnvelope(request) {
|
|
4
5
|
if (!isRecord(request)) {
|
|
5
6
|
return [issue([], "V1001", "Operation request must be an object.")];
|
|
6
7
|
}
|
|
7
|
-
const issues = [
|
|
8
|
+
const issues = [
|
|
9
|
+
...originAndIdentityIssues(request, request.family === "find"),
|
|
10
|
+
];
|
|
8
11
|
for (const member of OPERATION_IDENTITY_MEMBERS) {
|
|
9
12
|
const failure = requiredStringIssue(request, member);
|
|
10
13
|
if (failure !== undefined) {
|
|
@@ -17,9 +20,9 @@ export function validateTransactionEnvelope(request) {
|
|
|
17
20
|
if (!isRecord(request)) {
|
|
18
21
|
return [issue([], "V1001", "Transaction request must be an object.")];
|
|
19
22
|
}
|
|
20
|
-
return originAndIdentityIssues(request);
|
|
23
|
+
return originAndIdentityIssues(request, false);
|
|
21
24
|
}
|
|
22
|
-
function originAndIdentityIssues(request) {
|
|
25
|
+
function originAndIdentityIssues(request, readable) {
|
|
23
26
|
const issues = [];
|
|
24
27
|
const origin = request.origin;
|
|
25
28
|
if (origin === undefined) {
|
|
@@ -46,7 +49,7 @@ function originAndIdentityIssues(request) {
|
|
|
46
49
|
if (origin === "client" || origin === "agent") {
|
|
47
50
|
issues.push(...protocolIssues(request.protocol, origin));
|
|
48
51
|
if (request.transport !== undefined) {
|
|
49
|
-
issues.push(...transportIssues(request.transport));
|
|
52
|
+
issues.push(...transportIssues(request.transport, readable));
|
|
50
53
|
}
|
|
51
54
|
}
|
|
52
55
|
else if (origin === "application") {
|
|
@@ -84,15 +87,18 @@ function protocolIssues(protocol, origin) {
|
|
|
84
87
|
}
|
|
85
88
|
return issues;
|
|
86
89
|
}
|
|
87
|
-
function transportIssues(transport) {
|
|
90
|
+
function transportIssues(transport, readable) {
|
|
88
91
|
if (!isRecord(transport)) {
|
|
89
92
|
return [
|
|
90
93
|
issue(["transport"], "V1001", "Transport metadata must be an object."),
|
|
91
94
|
];
|
|
92
95
|
}
|
|
93
96
|
const issues = [];
|
|
94
|
-
if (transport.method !== "POST"
|
|
95
|
-
|
|
97
|
+
if (transport.method !== "POST" &&
|
|
98
|
+
!(readable && transport.method === "GET")) {
|
|
99
|
+
issues.push(issue(["transport", "method"], "V1001", readable
|
|
100
|
+
? 'Transport method must be "POST" or "GET".'
|
|
101
|
+
: 'Transport method must be "POST".'));
|
|
96
102
|
}
|
|
97
103
|
const headers = transport.headers;
|
|
98
104
|
if (!isRecord(headers)) {
|
|
@@ -115,9 +121,6 @@ function requiredStringIssue(request, member) {
|
|
|
115
121
|
? undefined
|
|
116
122
|
: issue([member], "V1001", `Property "${member}" must be a string.`);
|
|
117
123
|
}
|
|
118
|
-
function isRecord(value) {
|
|
119
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
120
|
-
}
|
|
121
124
|
function issue(path, code, message) {
|
|
122
125
|
return { path, code, message };
|
|
123
126
|
}
|
|
@@ -20,16 +20,6 @@ type ScalarValueNormalizationResult = {
|
|
|
20
20
|
readonly issues: readonly AvValidationIssue[];
|
|
21
21
|
};
|
|
22
22
|
type Path = readonly (string | number)[];
|
|
23
|
-
/**
|
|
24
|
-
* The one discriminant between an argument OBJECT and a VALUE wherever a position
|
|
25
|
-
* admits both — a filter position above all: a **plain** record is an operator object,
|
|
26
|
-
* and anything else — a `Date`, a core `AvDecimal`, a `Uint8Array` — is a value, which
|
|
27
|
-
* equality shorthand then holds to the field's scalar. The validator (`operation-
|
|
28
|
-
* validator-core.ts`) reads a filter position through this same answer, and an
|
|
29
|
-
* adapter's filter translation is expected to, so a position cannot be operators to
|
|
30
|
-
* one reader and a value to another.
|
|
31
|
-
*/
|
|
32
|
-
export declare function isPlainRecord(value: unknown): value is Readonly<Record<string, unknown>>;
|
|
33
23
|
/** The `V1001` of an `undefined` the request reads with. */
|
|
34
24
|
export declare function unsentReadValueIssue(path: Path): AvValidationIssue;
|
|
35
25
|
/**
|
|
@@ -6,6 +6,7 @@ import { decodeBase64, WIRE_SCALAR_PATTERNS, } from "../contracts/wire-scalar-fo
|
|
|
6
6
|
import { routeTransactionReferenceCandidate, } from "../transactions/transaction-reference.js";
|
|
7
7
|
import { AvDecimal, isAvDecimal } from "./decimal.js";
|
|
8
8
|
import { fieldCheckIssues } from "./field-check.evaluator.js";
|
|
9
|
+
import { isPlainRecord } from "./record.guard.js";
|
|
9
10
|
const INT_MIN = -(2 ** 31);
|
|
10
11
|
const INT_MAX = 2 ** 31 - 1;
|
|
11
12
|
const BIGINT_MIN = -(2n ** 63n);
|
|
@@ -15,16 +16,6 @@ const NAMED_FORMATS = new Set(AVZ_FORMATS);
|
|
|
15
16
|
function isNamedFormat(format) {
|
|
16
17
|
return NAMED_FORMATS.has(format);
|
|
17
18
|
}
|
|
18
|
-
function isRecord(value) {
|
|
19
|
-
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
20
|
-
}
|
|
21
|
-
export function isPlainRecord(value) {
|
|
22
|
-
if (!isRecord(value)) {
|
|
23
|
-
return false;
|
|
24
|
-
}
|
|
25
|
-
const prototype = Object.getPrototypeOf(value);
|
|
26
|
-
return prototype === Object.prototype || prototype === null;
|
|
27
|
-
}
|
|
28
19
|
function issue(code, path, message) {
|
|
29
20
|
return { code, path, message };
|
|
30
21
|
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Whether `value` is what `await` waits for rather than answers at once: an
|
|
3
|
+
* object or function whose `then` is a function. Reads `then` once; a `then`
|
|
4
|
+
* getter that throws throws here, so a caller reading an untrusted value guards
|
|
5
|
+
* the call.
|
|
6
|
+
*/
|
|
7
|
+
export declare function isThenable(value: unknown): value is PromiseLike<unknown>;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { lookupField, lookupResource } from "../contracts/contract-lookup.js";
|
|
2
|
-
import {
|
|
2
|
+
import { WRITE_KEYS } from "./field-stage.runtime.js";
|
|
3
3
|
import { isRelationMutationDirective, RELATION_MUTATION_RECORD_SITES, } from "./mutation-planner.js";
|
|
4
|
+
import { isPlainRecord } from "./record.guard.js";
|
|
4
5
|
const REMOVE = Symbol("remove");
|
|
5
6
|
const DEPTH_CEILING = 256;
|
|
6
7
|
function rebuilt(record, changes) {
|
|
@@ -2,14 +2,8 @@ import { lookupField, lookupResource } from "../contracts/contract-lookup.js";
|
|
|
2
2
|
import { encodeBase64 } from "../contracts/wire-scalar-format.js";
|
|
3
3
|
import { isAvDecimal } from "../runtime/decimal.js";
|
|
4
4
|
import { isRelationMutationDirective, RELATION_MUTATION_RECORD_SITES, } from "../runtime/mutation-planner.js";
|
|
5
|
+
import { isPlainRecord } from "../runtime/record.guard.js";
|
|
5
6
|
import { isTransactionReferenceCandidate } from "./transaction-reference.js";
|
|
6
|
-
function isPlainRecord(value) {
|
|
7
|
-
if (value === null || typeof value !== "object" || Array.isArray(value)) {
|
|
8
|
-
return false;
|
|
9
|
-
}
|
|
10
|
-
const prototype = Object.getPrototypeOf(value);
|
|
11
|
-
return prototype === Object.prototype || prototype === null;
|
|
12
|
-
}
|
|
13
7
|
function cloneRecord(value) {
|
|
14
8
|
return { ...value };
|
|
15
9
|
}
|
|
@@ -5,7 +5,8 @@ import { isAvDecimal } from "../runtime/decimal.js";
|
|
|
5
5
|
import { planStepPath } from "../runtime/error-boundary.js";
|
|
6
6
|
import { operationFailure } from "../runtime/operation-response.js";
|
|
7
7
|
import { mapValidationOutcome } from "../runtime/outcome-mapper.js";
|
|
8
|
-
import { isPlainRecord
|
|
8
|
+
import { isPlainRecord } from "../runtime/record.guard.js";
|
|
9
|
+
import { normalizeJsonValue } from "../runtime/scalar-runtime.js";
|
|
9
10
|
import { inspectReferenceCandidate, invalidSourceIndexIssue, referenceSourceAt, referenceSourceField, } from "./transaction-reference-validator.js";
|
|
10
11
|
import { transactionOperationFailure } from "./transaction-response.js";
|
|
11
12
|
function refused(issue, index) {
|
|
@@ -3,6 +3,7 @@ import { AvCallerDataError, } from "../runtime/caller-data.copier.js";
|
|
|
3
3
|
import { copyAtDoor, refuseCallerData } from "../runtime/caller-data.door.js";
|
|
4
4
|
import { operationFailure } from "../runtime/operation-response.js";
|
|
5
5
|
import { mapValidationOutcome } from "../runtime/outcome-mapper.js";
|
|
6
|
+
import { isPlainRecord } from "../runtime/record.guard.js";
|
|
6
7
|
import { withoutUnsentWriteValues } from "../runtime/unsent-value.normalizer.js";
|
|
7
8
|
import { encodeOperationArgumentsForWire } from "./operation-arguments-encoder.js";
|
|
8
9
|
import { computeOperationFingerprint } from "./operation-fingerprint.js";
|
|
@@ -10,13 +11,6 @@ import { readSqlTemplate } from "./sql-statement.js";
|
|
|
10
11
|
import { routeTransactionReferenceCandidate } from "./transaction-reference.js";
|
|
11
12
|
import { transactionOperationFailure } from "./transaction-response.js";
|
|
12
13
|
const SQL_STEP_NODE = Object.freeze({ fingerprint: null });
|
|
13
|
-
function isPlainRecord(value) {
|
|
14
|
-
if (value === null || typeof value !== "object" || Array.isArray(value)) {
|
|
15
|
-
return false;
|
|
16
|
-
}
|
|
17
|
-
const prototype = Object.getPrototypeOf(value);
|
|
18
|
-
return prototype === Object.prototype || prototype === null;
|
|
19
|
-
}
|
|
20
14
|
const KEEP = Symbol("keep");
|
|
21
15
|
function rebuildArguments(root, leaf) {
|
|
22
16
|
const pathOf = (parent, key) => () => {
|
|
@@ -12,6 +12,7 @@ import { createMisuseReporter } from "../runtime/misuse-reporter.js";
|
|
|
12
12
|
import { operationFailure } from "../runtime/operation-response.js";
|
|
13
13
|
import { activeContract, validateOperationRequest, validateProtocolIdentity, } from "../runtime/operation-runtime.js";
|
|
14
14
|
import { mapValidationOutcome, VALIDATION_OUTCOME_MESSAGES, } from "../runtime/outcome-mapper.js";
|
|
15
|
+
import { isRecord } from "../runtime/record.guard.js";
|
|
15
16
|
import { encodeOperationArgumentsForWire } from "./operation-arguments-encoder.js";
|
|
16
17
|
import { computeOperationFingerprint, isOperationFingerprint, } from "./operation-fingerprint.js";
|
|
17
18
|
import { validateSqlStatement } from "./sql-statement.validator.js";
|
|
@@ -104,9 +105,6 @@ const OPERATION_KEYS = [
|
|
|
104
105
|
"args",
|
|
105
106
|
"fingerprint",
|
|
106
107
|
];
|
|
107
|
-
function isObject(value) {
|
|
108
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
109
|
-
}
|
|
110
108
|
function operationKeyFailure(contract, step, operation) {
|
|
111
109
|
const { resource, family, variant } = step;
|
|
112
110
|
const issue = typeof family === "string" && typeof variant === "string"
|
|
@@ -199,7 +197,7 @@ function* relationTraversals(contract, resourceName, value, path) {
|
|
|
199
197
|
}
|
|
200
198
|
return;
|
|
201
199
|
}
|
|
202
|
-
if (!
|
|
200
|
+
if (!isRecord(value)) {
|
|
203
201
|
return;
|
|
204
202
|
}
|
|
205
203
|
for (const [key, entry] of Object.entries(value)) {
|
|
@@ -215,7 +213,7 @@ function* relationTraversals(contract, resourceName, value, path) {
|
|
|
215
213
|
}
|
|
216
214
|
}
|
|
217
215
|
function* operationTraversals(contract, request, index) {
|
|
218
|
-
if (!
|
|
216
|
+
if (!isRecord(request.arguments)) {
|
|
219
217
|
return;
|
|
220
218
|
}
|
|
221
219
|
const root = planOperationArgumentsPath(index);
|
|
@@ -229,7 +227,7 @@ function* operationTraversals(contract, request, index) {
|
|
|
229
227
|
function deletedResources(contract, request, index) {
|
|
230
228
|
const deleted = request.family === "delete" ? [request.resource] : [];
|
|
231
229
|
for (const traversal of operationTraversals(contract, request, index)) {
|
|
232
|
-
if (
|
|
230
|
+
if (isRecord(traversal.value) &&
|
|
233
231
|
Object.hasOwn(traversal.value, "$delete")) {
|
|
234
232
|
deleted.push(traversal.field.target);
|
|
235
233
|
}
|
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
import { lookupField, lookupOwn, lookupResource, } from "../contracts/contract-lookup.js";
|
|
2
2
|
import { planOperationArgumentsPath } from "../runtime/error-boundary.js";
|
|
3
|
-
import { isPlainRecord,
|
|
3
|
+
import { isPlainRecord, isRecord } from "../runtime/record.guard.js";
|
|
4
|
+
import { referenceOperandShape } from "../runtime/scalar-runtime.js";
|
|
4
5
|
import { routeTransactionReferenceCandidate, } from "./transaction-reference.js";
|
|
5
|
-
function isObject(value) {
|
|
6
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
7
|
-
}
|
|
8
6
|
function at(position, ...segments) {
|
|
9
7
|
return { ...position, path: [...position.path, ...segments] };
|
|
10
8
|
}
|
|
@@ -23,7 +21,7 @@ function collectValue(field, shape, value, path, candidates, written = false) {
|
|
|
23
21
|
return true;
|
|
24
22
|
}
|
|
25
23
|
function collectKey(position, selector, candidates) {
|
|
26
|
-
if (!
|
|
24
|
+
if (!isRecord(selector)) {
|
|
27
25
|
return;
|
|
28
26
|
}
|
|
29
27
|
const resource = lookupResource(position.contract, position.resource);
|
|
@@ -61,7 +59,7 @@ function collectScalarFilter(field, filter, path, candidates) {
|
|
|
61
59
|
}
|
|
62
60
|
}
|
|
63
61
|
function collectWhere(position, where, candidates) {
|
|
64
|
-
if (!
|
|
62
|
+
if (!isRecord(where)) {
|
|
65
63
|
return;
|
|
66
64
|
}
|
|
67
65
|
const resource = lookupResource(position.contract, position.resource);
|
|
@@ -87,7 +85,7 @@ function collectWhere(position, where, candidates) {
|
|
|
87
85
|
if (field.cardinality === "one") {
|
|
88
86
|
collectWhere(target, value, candidates);
|
|
89
87
|
}
|
|
90
|
-
else if (
|
|
88
|
+
else if (isRecord(value)) {
|
|
91
89
|
for (const operator of ["some", "every", "none"]) {
|
|
92
90
|
if (Object.hasOwn(value, operator)) {
|
|
93
91
|
collectWhere(at(target, operator), value[operator], candidates);
|
|
@@ -107,7 +105,7 @@ function eachEntry(position, operand, visit) {
|
|
|
107
105
|
visit(position, operand);
|
|
108
106
|
}
|
|
109
107
|
function collectRelationDirectives(position, edge, value, candidates) {
|
|
110
|
-
if (!
|
|
108
|
+
if (!isRecord(value)) {
|
|
111
109
|
return;
|
|
112
110
|
}
|
|
113
111
|
const target = { ...position, resource: edge.target };
|
|
@@ -129,7 +127,7 @@ function collectRelationDirectives(position, edge, value, candidates) {
|
|
|
129
127
|
case "$delete":
|
|
130
128
|
case "$upsert":
|
|
131
129
|
eachEntry(directivePosition, operand, (entryPosition, entry) => {
|
|
132
|
-
if (!
|
|
130
|
+
if (!isRecord(entry)) {
|
|
133
131
|
return;
|
|
134
132
|
}
|
|
135
133
|
const where = at(entryPosition, "where");
|
|
@@ -150,7 +148,7 @@ function collectRelationDirectives(position, edge, value, candidates) {
|
|
|
150
148
|
}
|
|
151
149
|
}
|
|
152
150
|
function collectData(position, data, candidates) {
|
|
153
|
-
if (!
|
|
151
|
+
if (!isRecord(data)) {
|
|
154
152
|
return;
|
|
155
153
|
}
|
|
156
154
|
const resource = lookupResource(position.contract, position.resource);
|
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
import { validationIssue } from "../operations/validation-code.js";
|
|
2
|
+
import { isRecord } from "../runtime/record.guard.js";
|
|
2
3
|
import { copyScalarFieldValue } from "../runtime/scalar-runtime.js";
|
|
3
4
|
import { replaceTransactionSlotValues } from "./transaction-slot-writer.js";
|
|
4
|
-
function isRecord(value) {
|
|
5
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
6
|
-
}
|
|
7
5
|
function unresolvedIssue(path) {
|
|
8
6
|
return validationIssue("V1018", [...path, "$ref", "path"], "Transaction reference resolved to no value.");
|
|
9
7
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { transactionLevelsOf } from "../config/pipeline-tree.resolver.js";
|
|
2
|
-
import { openRequestPolicy, } from "../policy/policy-request.js";
|
|
2
|
+
import { derivePolicyCaller, holdFirstPrincipal, openRequestPolicy, } from "../policy/policy-request.js";
|
|
3
3
|
import { AdapterBoundary, planOperationArgumentsPath, planStepPath, sanitizeOperationFailure, } from "../runtime/error-boundary.js";
|
|
4
4
|
import { internalFailure, operationSuccess, } from "../runtime/operation-response.js";
|
|
5
5
|
import { admitOperation, EVERY_FIELD, executeAdmittedOperation, prepareStep, STEP_PIPES, withRequestState, } from "../runtime/operation-runtime.js";
|
|
@@ -82,6 +82,35 @@ function standingReferences(core, operation, args, steps, subject) {
|
|
|
82
82
|
}
|
|
83
83
|
async function executeTransactionPlan(runtime, dependencies, request, plan, state, diagnostics, caller) {
|
|
84
84
|
const { adapter } = runtime;
|
|
85
|
+
const callers = new Map();
|
|
86
|
+
if (caller !== undefined) {
|
|
87
|
+
for (const step of plan.operations) {
|
|
88
|
+
if (step.kind === "operation") {
|
|
89
|
+
holdFirstPrincipal(runtime.config.policy, {
|
|
90
|
+
origin: step.request.origin,
|
|
91
|
+
state,
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
else {
|
|
97
|
+
for (const step of plan.operations) {
|
|
98
|
+
if (step.kind === "sql" || callers.has(step.request.origin)) {
|
|
99
|
+
continue;
|
|
100
|
+
}
|
|
101
|
+
try {
|
|
102
|
+
const derived = derivePolicyCaller(runtime.config.policy, {
|
|
103
|
+
origin: step.request.origin,
|
|
104
|
+
state,
|
|
105
|
+
});
|
|
106
|
+
callers.set(step.request.origin, derived instanceof Promise ? await derived : derived);
|
|
107
|
+
}
|
|
108
|
+
catch (error) {
|
|
109
|
+
diagnostics.operation(step.request, step.index)(error, "A3000");
|
|
110
|
+
return transactionOperationFailure(internalFailure(), step.index);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
85
114
|
const steps = new Map();
|
|
86
115
|
const stateful = (operation) => {
|
|
87
116
|
const known = steps.get(operation);
|
|
@@ -95,7 +124,7 @@ async function executeTransactionPlan(runtime, dependencies, request, plan, stat
|
|
|
95
124
|
steps.set(operation, step);
|
|
96
125
|
return step;
|
|
97
126
|
};
|
|
98
|
-
const policy = openRequestPolicy(runtime.config.policy, runtime.contracts.core, { origin: operation.request.origin, state }, caller, adapter);
|
|
127
|
+
const policy = openRequestPolicy(runtime.config.policy, runtime.contracts.core, { origin: operation.request.origin, state }, caller ?? callers.get(operation.request.origin), adapter);
|
|
99
128
|
return policy instanceof Promise ? policy.then(settle) : settle(policy);
|
|
100
129
|
};
|
|
101
130
|
const admitted = [];
|
|
@@ -3,6 +3,7 @@ import { runLevelLifecycle, } from "../runtime/level-lifecycle.runtime.js";
|
|
|
3
3
|
import { operationFailure } from "../runtime/operation-response.js";
|
|
4
4
|
import { AvPipeOutputError, PIPE_OUTPUT_FAILURE_MESSAGE, } from "../runtime/pipe-output.validator.js";
|
|
5
5
|
import { deepFreeze, frozenCopy } from "../runtime/readonly-value.js";
|
|
6
|
+
import { isRecord } from "../runtime/record.guard.js";
|
|
6
7
|
import { AvTransactionIntegrityError } from "./transaction-integrity-error.js";
|
|
7
8
|
export const TRANSACTION_ABORT = Object.freeze({ reason: "aventara-transaction-abort" });
|
|
8
9
|
export const TRANSACTION_PIPES = "Transaction pipes";
|
|
@@ -26,9 +27,6 @@ export function touchedTransactionLevels(plan, levelsOf) {
|
|
|
26
27
|
}
|
|
27
28
|
return [...touched].flatMap((resource) => levelsOf(resource));
|
|
28
29
|
}
|
|
29
|
-
function isRecord(value) {
|
|
30
|
-
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
31
|
-
}
|
|
32
30
|
function sameStructure(left, right) {
|
|
33
31
|
if (Object.is(left, right)) {
|
|
34
32
|
return true;
|