@aventara/core 0.1.0-pilot.4 → 1.0.0-rc.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/CHANGELOG.md +338 -0
- package/README.md +100 -3
- package/dist/adapters/adapter-model.d.ts +8 -0
- package/dist/adapters/adapter.interface.d.ts +6 -2
- package/dist/compiler/contract-compiler-diagnostic.d.ts +6 -0
- package/dist/compiler/contract.compiler.js +67 -0
- package/dist/config/config.resolver.d.ts +3 -0
- package/dist/config/config.resolver.js +1 -0
- package/dist/config/config.validator.js +6 -0
- package/dist/config/define-fields.d.ts +10 -3
- package/dist/config/framework-config.d.ts +4 -1
- package/dist/config/framework-fields-config.d.ts +6 -0
- package/dist/contracts/client-contract-structure.validator.d.ts +21 -1
- package/dist/contracts/client-contract-structure.validator.js +99 -2
- package/dist/contracts/contract-canonicalizer.js +32 -0
- package/dist/contracts/contract.d.ts +7 -0
- package/dist/contracts/field.d.ts +10 -0
- package/dist/contracts/json-shape.d.ts +65 -0
- package/dist/contracts/json-shape.js +1 -0
- package/dist/contracts/reference-write-limit.d.ts +7 -0
- package/dist/contracts/reference-write-limit.js +1 -0
- package/dist/contracts/scalar-value-type.d.ts +12 -1
- package/dist/framework/contract-view.d.ts +126 -21
- package/dist/framework/framework.d.ts +5 -3
- package/dist/framework/framework.factory.js +56 -13
- package/dist/index.d.ts +8 -40
- package/dist/index.js +0 -20
- package/dist/internal.d.ts +35 -0
- package/dist/internal.js +16 -0
- package/dist/json/avz.d.ts +96 -0
- package/dist/json/avz.js +212 -0
- package/dist/json/index.d.ts +6 -0
- package/dist/json/index.js +1 -0
- package/dist/json/json-shape.registry.d.ts +22 -0
- package/dist/json/json-shape.registry.js +16 -0
- package/dist/json/zod-issue.translator.d.ts +51 -0
- package/dist/json/zod-issue.translator.js +142 -0
- package/dist/operations/operation-arguments.d.ts +151 -101
- package/dist/operations/operation-identity.d.ts +2 -0
- package/dist/operations/operation-identity.js +3 -0
- package/dist/operations/operation-validator-core.d.ts +1 -1
- package/dist/operations/operation-validator-core.js +28 -10
- package/dist/operations/operation-validator.d.ts +20 -5
- package/dist/operations/operation-validator.js +26 -10
- package/dist/operations/projection-scope.resolver.d.ts +1 -1
- package/dist/operations/structural-limits.walker.d.ts +19 -0
- package/dist/operations/structural-limits.walker.js +344 -0
- package/dist/protocol/absent-route.responder.d.ts +2 -1
- package/dist/protocol/absent-route.responder.js +32 -6
- package/dist/protocol/http-request.decoder.d.ts +6 -0
- package/dist/protocol/http-request.decoder.js +11 -3
- package/dist/protocol/protocol.binder.d.ts +4 -2
- package/dist/protocol/protocol.binder.js +3 -1
- package/dist/protocol/protocol.handler.d.ts +6 -2
- package/dist/protocol/protocol.handler.js +14 -4
- package/dist/protocol/unmounted-route.error.d.ts +19 -0
- package/dist/protocol/unmounted-route.error.js +10 -0
- package/dist/runtime/caller-data.copier.d.ts +59 -0
- package/dist/runtime/caller-data.copier.js +470 -0
- package/dist/runtime/caller-data.door.d.ts +56 -0
- package/dist/runtime/caller-data.door.js +65 -0
- package/dist/runtime/computed-read-runtime.js +3 -10
- package/dist/runtime/computed-value.error.d.ts +13 -0
- package/dist/runtime/computed-value.error.js +9 -0
- package/dist/runtime/create-requirement.d.ts +43 -7
- package/dist/runtime/create-requirement.js +89 -9
- package/dist/runtime/diagnostics-reporter.d.ts +20 -4
- package/dist/runtime/diagnostics-reporter.js +11 -4
- package/dist/runtime/error-boundary.d.ts +8 -0
- package/dist/runtime/error-boundary.js +65 -35
- package/dist/runtime/field-behavior.d.ts +2 -2
- package/dist/runtime/framework-error.d.ts +12 -0
- package/dist/runtime/misuse-reporter.d.ts +32 -0
- package/dist/runtime/misuse-reporter.js +19 -0
- package/dist/runtime/mutation-planner.js +13 -11
- package/dist/runtime/operation-request.d.ts +4 -11
- package/dist/runtime/operation-runtime.d.ts +14 -7
- package/dist/runtime/operation-runtime.js +37 -18
- package/dist/runtime/outcome-mapper.js +12 -2
- package/dist/runtime/output-validator.d.ts +10 -0
- package/dist/runtime/output-validator.js +11 -0
- package/dist/runtime/owned-execution.registry.d.ts +13 -0
- package/dist/runtime/owned-execution.registry.js +7 -0
- package/dist/runtime/pipeline.d.ts +19 -7
- package/dist/runtime/referential-action.d.ts +7 -0
- package/dist/runtime/request-envelope.validator.d.ts +5 -0
- package/dist/runtime/request-envelope.validator.js +118 -0
- package/dist/runtime/scalar-runtime.d.ts +30 -2
- package/dist/runtime/scalar-runtime.js +162 -79
- package/dist/transactions/transaction-plan-assembler.d.ts +5 -1
- package/dist/transactions/transaction-plan-assembler.js +74 -75
- package/dist/transactions/transaction-plan-validator.d.ts +30 -7
- package/dist/transactions/transaction-plan-validator.js +204 -153
- package/dist/transactions/transaction-reference-collector.d.ts +30 -0
- package/dist/transactions/transaction-reference-collector.js +204 -0
- package/dist/transactions/transaction-reference-resolver.js +10 -5
- package/dist/transactions/transaction-reference-validator.js +24 -17
- package/dist/transactions/transaction-reference.d.ts +23 -51
- package/dist/transactions/transaction-request.d.ts +3 -3
- package/dist/transactions/transaction-response.d.ts +6 -1
- package/dist/transactions/transaction-response.js +24 -1
- package/dist/transactions/transaction-runtime.d.ts +4 -2
- package/dist/transactions/transaction-runtime.js +4 -3
- package/package.json +17 -3
- package/dist/operations/operation-boolean-nodes.d.ts +0 -11
- package/dist/operations/operation-boolean-nodes.js +0 -283
- package/dist/operations/operation-nesting.d.ts +0 -8
- package/dist/operations/operation-nesting.js +0 -307
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { lookupField, lookupResource } from "../contracts/contract-lookup.js";
|
|
1
|
+
import { lookupField, lookupOwn, lookupResource, } from "../contracts/contract-lookup.js";
|
|
2
2
|
import { decodeBase64, WIRE_SCALAR_PATTERNS, } from "../contracts/wire-scalar-format.js";
|
|
3
|
-
import {
|
|
3
|
+
import { shapeOfField } from "../json/json-shape.registry.js";
|
|
4
|
+
import { routeTransactionReferenceCandidate, } from "../transactions/transaction-reference.js";
|
|
4
5
|
import { Decimal } from "./decimal.js";
|
|
5
6
|
const INT_MIN = -(2 ** 31);
|
|
6
7
|
const INT_MAX = 2 ** 31 - 1;
|
|
@@ -26,8 +27,9 @@ function typeIssue(path, expected) {
|
|
|
26
27
|
function formatIssue(path, expected) {
|
|
27
28
|
return issue("V1003", path, `Value must use ${expected}.`);
|
|
28
29
|
}
|
|
30
|
+
let writeInPlace = false;
|
|
29
31
|
function cloneRecord(value) {
|
|
30
|
-
return { ...value };
|
|
32
|
+
return writeInPlace ? value : { ...value };
|
|
31
33
|
}
|
|
32
34
|
function materializeJsonPath(root, link) {
|
|
33
35
|
const segments = [];
|
|
@@ -125,7 +127,7 @@ function normalizeJsonValue(value, path, seen) {
|
|
|
125
127
|
}
|
|
126
128
|
return issues.length > 0 ? { ok: false, issues } : { ok: true, value: root };
|
|
127
129
|
}
|
|
128
|
-
function normalizeScalarAtom(contract, field, value,
|
|
130
|
+
function normalizeScalarAtom(contract, field, value, origin, path, allowNull) {
|
|
129
131
|
if (value === null) {
|
|
130
132
|
return allowNull
|
|
131
133
|
? { ok: true, value: null }
|
|
@@ -195,7 +197,7 @@ function normalizeScalarAtom(contract, field, value, scope, path, allowNull) {
|
|
|
195
197
|
}
|
|
196
198
|
break;
|
|
197
199
|
case "bigint":
|
|
198
|
-
if (
|
|
200
|
+
if (origin === "application") {
|
|
199
201
|
normalized =
|
|
200
202
|
typeof value === "bigint"
|
|
201
203
|
? { ok: true, value }
|
|
@@ -228,7 +230,7 @@ function normalizeScalarAtom(contract, field, value, scope, path, allowNull) {
|
|
|
228
230
|
}
|
|
229
231
|
break;
|
|
230
232
|
case "decimal":
|
|
231
|
-
if (
|
|
233
|
+
if (origin === "application") {
|
|
232
234
|
normalized =
|
|
233
235
|
value instanceof Decimal
|
|
234
236
|
? { ok: true, value }
|
|
@@ -253,7 +255,7 @@ function normalizeScalarAtom(contract, field, value, scope, path, allowNull) {
|
|
|
253
255
|
}
|
|
254
256
|
break;
|
|
255
257
|
case "datetime":
|
|
256
|
-
if (
|
|
258
|
+
if (origin === "application") {
|
|
257
259
|
if (!(value instanceof Date)) {
|
|
258
260
|
normalized = { ok: false, issues: [typeIssue(path, "a Date")] };
|
|
259
261
|
}
|
|
@@ -289,7 +291,7 @@ function normalizeScalarAtom(contract, field, value, scope, path, allowNull) {
|
|
|
289
291
|
}
|
|
290
292
|
break;
|
|
291
293
|
case "bytes":
|
|
292
|
-
if (
|
|
294
|
+
if (origin === "application") {
|
|
293
295
|
normalized =
|
|
294
296
|
value instanceof Uint8Array
|
|
295
297
|
? { ok: true, value }
|
|
@@ -334,7 +336,7 @@ function normalizeScalarAtom(contract, field, value, scope, path, allowNull) {
|
|
|
334
336
|
}
|
|
335
337
|
return normalized;
|
|
336
338
|
}
|
|
337
|
-
export function normalizeScalarFieldValue(contract, field, value,
|
|
339
|
+
export function normalizeScalarFieldValue(contract, field, value, origin, path) {
|
|
338
340
|
if (value === null) {
|
|
339
341
|
return field.nullable
|
|
340
342
|
? { ok: true, value: null }
|
|
@@ -347,7 +349,7 @@ export function normalizeScalarFieldValue(contract, field, value, scope, path) {
|
|
|
347
349
|
const normalized = [];
|
|
348
350
|
const issues = [];
|
|
349
351
|
value.forEach((entry, index) => {
|
|
350
|
-
const result = normalizeScalarAtom(contract, field, entry,
|
|
352
|
+
const result = normalizeScalarAtom(contract, field, entry, origin === "runtime" ? "application" : origin, [...path, index], false);
|
|
351
353
|
if (result.ok) {
|
|
352
354
|
normalized.push(result.value);
|
|
353
355
|
}
|
|
@@ -359,7 +361,41 @@ export function normalizeScalarFieldValue(contract, field, value, scope, path) {
|
|
|
359
361
|
? { ok: false, issues }
|
|
360
362
|
: { ok: true, value: normalized };
|
|
361
363
|
}
|
|
362
|
-
return normalizeScalarAtom(contract, field, value,
|
|
364
|
+
return normalizeScalarAtom(contract, field, value, origin === "runtime" ? "application" : origin, path, field.nullable);
|
|
365
|
+
}
|
|
366
|
+
export function jsonShapeIssues(field, value, path, position = "value") {
|
|
367
|
+
if (field.json === undefined || value === null || value === undefined) {
|
|
368
|
+
return [];
|
|
369
|
+
}
|
|
370
|
+
const shape = shapeOfField(field);
|
|
371
|
+
if (shape === undefined) {
|
|
372
|
+
throw new Error("a shaped Json field reached validation with no shape bound to it");
|
|
373
|
+
}
|
|
374
|
+
const at = (entry, entryPath) => shape.validate(entry).map((found) => ({
|
|
375
|
+
...found,
|
|
376
|
+
path: [...entryPath, ...(found.path ?? [])],
|
|
377
|
+
}));
|
|
378
|
+
return field.list && position === "value" && Array.isArray(value)
|
|
379
|
+
? value.flatMap((entry, index) => at(entry, [...path, index]))
|
|
380
|
+
: at(value, path);
|
|
381
|
+
}
|
|
382
|
+
function normalizeWrittenValue(contract, field, value, origin, path, issues) {
|
|
383
|
+
const result = normalizeScalarFieldValue(contract, field, value, origin, path);
|
|
384
|
+
if (!result.ok) {
|
|
385
|
+
issues.push(...result.issues);
|
|
386
|
+
return undefined;
|
|
387
|
+
}
|
|
388
|
+
issues.push(...jsonShapeIssues(field, result.value, path));
|
|
389
|
+
return result.value;
|
|
390
|
+
}
|
|
391
|
+
function normalizeWrittenElement(contract, field, value, origin, path, issues) {
|
|
392
|
+
const result = normalizeListElement(contract, field, value, origin, path);
|
|
393
|
+
if (!result.ok) {
|
|
394
|
+
issues.push(...result.issues);
|
|
395
|
+
return undefined;
|
|
396
|
+
}
|
|
397
|
+
issues.push(...jsonShapeIssues(field, result.value, path, "entry"));
|
|
398
|
+
return result.value;
|
|
363
399
|
}
|
|
364
400
|
const SCALAR_ATOM_COPIERS = {
|
|
365
401
|
string: (value) => value,
|
|
@@ -390,8 +426,8 @@ export function copyScalarFieldValue(field, value) {
|
|
|
390
426
|
}
|
|
391
427
|
return items;
|
|
392
428
|
}
|
|
393
|
-
function normalizeListElement(contract, field, value,
|
|
394
|
-
return normalizeScalarAtom(contract, field, value,
|
|
429
|
+
function normalizeListElement(contract, field, value, origin, path) {
|
|
430
|
+
return normalizeScalarAtom(contract, field, value, origin, path, false);
|
|
395
431
|
}
|
|
396
432
|
function mergeResult(result, issues) {
|
|
397
433
|
if (result.ok) {
|
|
@@ -400,9 +436,41 @@ function mergeResult(result, issues) {
|
|
|
400
436
|
issues.push(...result.issues);
|
|
401
437
|
return undefined;
|
|
402
438
|
}
|
|
403
|
-
|
|
439
|
+
export const REFERENCE_OPERANDS = Object.freeze({
|
|
440
|
+
equals: "value",
|
|
441
|
+
not: "value",
|
|
442
|
+
lt: "nonNullValue",
|
|
443
|
+
lte: "nonNullValue",
|
|
444
|
+
gt: "nonNullValue",
|
|
445
|
+
gte: "nonNullValue",
|
|
446
|
+
contains: "nonNullValue",
|
|
447
|
+
startsWith: "nonNullValue",
|
|
448
|
+
endsWith: "nonNullValue",
|
|
449
|
+
has: "entry",
|
|
450
|
+
in: "entries",
|
|
451
|
+
notIn: "entries",
|
|
452
|
+
hasEvery: "entries",
|
|
453
|
+
hasSome: "entries",
|
|
454
|
+
});
|
|
455
|
+
export function referenceOperandShape(operator) {
|
|
456
|
+
return lookupOwn(REFERENCE_OPERANDS, operator);
|
|
457
|
+
}
|
|
458
|
+
function acceptsNullOperand(operator) {
|
|
459
|
+
return NULL_OPERAND_OPERATORS.has(operator);
|
|
460
|
+
}
|
|
461
|
+
const NULL_OPERAND_OPERATORS = new Set([
|
|
462
|
+
"equals",
|
|
463
|
+
"not",
|
|
464
|
+
"arrayContains",
|
|
465
|
+
"arrayStartsWith",
|
|
466
|
+
"arrayEndsWith",
|
|
467
|
+
]);
|
|
468
|
+
function normalizeScalarFilter(contract, field, value, origin, path, issues, references = false) {
|
|
469
|
+
if (isKeptReference(references, value)) {
|
|
470
|
+
return value;
|
|
471
|
+
}
|
|
404
472
|
if (!isPlainRecord(value)) {
|
|
405
|
-
return mergeResult(normalizeScalarFieldValue(contract, field, value,
|
|
473
|
+
return mergeResult(normalizeScalarFieldValue(contract, field, value, origin, path), issues);
|
|
406
474
|
}
|
|
407
475
|
const keys = Object.keys(value);
|
|
408
476
|
if (keys.length === 0 || !keys.some((key) => key in value)) {
|
|
@@ -411,11 +479,19 @@ function normalizeScalarFilter(contract, field, value, scope, path, issues) {
|
|
|
411
479
|
const normalized = cloneRecord(value);
|
|
412
480
|
for (const [operator, operand] of Object.entries(value)) {
|
|
413
481
|
const operandPath = [...path, operator];
|
|
482
|
+
if (operand === null && !acceptsNullOperand(operator)) {
|
|
483
|
+
issues.push(typeIssue(operandPath, "non-null"));
|
|
484
|
+
continue;
|
|
485
|
+
}
|
|
414
486
|
if (operator === "mode" || operator === "isEmpty" || operator === "path") {
|
|
415
487
|
continue;
|
|
416
488
|
}
|
|
489
|
+
if (referenceOperandShape(operator) !== undefined &&
|
|
490
|
+
isKeptReference(references, operand)) {
|
|
491
|
+
continue;
|
|
492
|
+
}
|
|
417
493
|
if (operator === "not" && isPlainRecord(operand)) {
|
|
418
|
-
normalized[operator] = normalizeScalarFilter(contract, field, operand,
|
|
494
|
+
normalized[operator] = normalizeScalarFilter(contract, field, operand, origin, operandPath, issues, references);
|
|
419
495
|
continue;
|
|
420
496
|
}
|
|
421
497
|
if (operator === "in" || operator === "notIn") {
|
|
@@ -423,14 +499,14 @@ function normalizeScalarFilter(contract, field, value, scope, path, issues) {
|
|
|
423
499
|
issues.push(typeIssue(operandPath, "an array"));
|
|
424
500
|
continue;
|
|
425
501
|
}
|
|
426
|
-
normalized[operator] = operand.map((entry, index) => mergeResult(normalizeListElement(contract, field, entry,
|
|
502
|
+
normalized[operator] = operand.map((entry, index) => mergeResult(normalizeListElement(contract, field, entry, origin, [
|
|
427
503
|
...operandPath,
|
|
428
504
|
index,
|
|
429
505
|
]), issues));
|
|
430
506
|
continue;
|
|
431
507
|
}
|
|
432
508
|
if (operator === "has") {
|
|
433
|
-
normalized[operator] = mergeResult(normalizeListElement(contract, field, operand,
|
|
509
|
+
normalized[operator] = mergeResult(normalizeListElement(contract, field, operand, origin, operandPath), issues);
|
|
434
510
|
continue;
|
|
435
511
|
}
|
|
436
512
|
if (operator === "hasEvery" || operator === "hasSome") {
|
|
@@ -438,7 +514,7 @@ function normalizeScalarFilter(contract, field, value, scope, path, issues) {
|
|
|
438
514
|
issues.push(typeIssue(operandPath, "an array"));
|
|
439
515
|
continue;
|
|
440
516
|
}
|
|
441
|
-
normalized[operator] = operand.map((entry, index) => mergeResult(normalizeListElement(contract, field, entry,
|
|
517
|
+
normalized[operator] = operand.map((entry, index) => mergeResult(normalizeListElement(contract, field, entry, origin, [
|
|
442
518
|
...operandPath,
|
|
443
519
|
index,
|
|
444
520
|
]), issues));
|
|
@@ -451,11 +527,11 @@ function normalizeScalarFilter(contract, field, value, scope, path, issues) {
|
|
|
451
527
|
normalized[operator] = mergeResult(jsonResult, issues);
|
|
452
528
|
continue;
|
|
453
529
|
}
|
|
454
|
-
normalized[operator] = mergeResult(normalizeScalarFieldValue(contract, field, operand,
|
|
530
|
+
normalized[operator] = mergeResult(normalizeScalarFieldValue(contract, field, operand, origin, operandPath), issues);
|
|
455
531
|
}
|
|
456
532
|
return normalized;
|
|
457
533
|
}
|
|
458
|
-
function normalizeWhere(contract, resourceName, where,
|
|
534
|
+
function normalizeWhere(contract, resourceName, where, origin, path, issues, references = false) {
|
|
459
535
|
if (!isPlainRecord(where)) {
|
|
460
536
|
return where;
|
|
461
537
|
}
|
|
@@ -467,28 +543,28 @@ function normalizeWhere(contract, resourceName, where, scope, path, issues) {
|
|
|
467
543
|
for (const [key, value] of Object.entries(where)) {
|
|
468
544
|
if (key === "AND" || key === "OR") {
|
|
469
545
|
if (Array.isArray(value)) {
|
|
470
|
-
normalized[key] = value.map((entry, index) => normalizeWhere(contract, resourceName, entry,
|
|
546
|
+
normalized[key] = value.map((entry, index) => normalizeWhere(contract, resourceName, entry, origin, [...path, key, index], issues, references));
|
|
471
547
|
}
|
|
472
548
|
continue;
|
|
473
549
|
}
|
|
474
550
|
if (key === "NOT") {
|
|
475
|
-
normalized[key] = normalizeWhere(contract, resourceName, value,
|
|
551
|
+
normalized[key] = normalizeWhere(contract, resourceName, value, origin, [...path, key], issues, references);
|
|
476
552
|
continue;
|
|
477
553
|
}
|
|
478
554
|
const field = lookupField(resource, key);
|
|
479
555
|
if (field?.kind === "scalar") {
|
|
480
|
-
normalized[key] = normalizeScalarFilter(contract, field, value,
|
|
556
|
+
normalized[key] = normalizeScalarFilter(contract, field, value, origin, [...path, key], issues, references);
|
|
481
557
|
continue;
|
|
482
558
|
}
|
|
483
559
|
if (field?.kind === "relation" && isPlainRecord(value)) {
|
|
484
560
|
if (field.cardinality === "one") {
|
|
485
|
-
normalized[key] = normalizeWhere(contract, field.target, value,
|
|
561
|
+
normalized[key] = normalizeWhere(contract, field.target, value, origin, [...path, key], issues, references);
|
|
486
562
|
}
|
|
487
563
|
else {
|
|
488
564
|
const relationValue = cloneRecord(value);
|
|
489
565
|
for (const relationOperator of ["some", "every", "none"]) {
|
|
490
566
|
if (relationOperator in value) {
|
|
491
|
-
relationValue[relationOperator] = normalizeWhere(contract, field.target, value[relationOperator],
|
|
567
|
+
relationValue[relationOperator] = normalizeWhere(contract, field.target, value[relationOperator], origin, [...path, key, relationOperator], issues, references);
|
|
492
568
|
}
|
|
493
569
|
}
|
|
494
570
|
normalized[key] = relationValue;
|
|
@@ -497,7 +573,10 @@ function normalizeWhere(contract, resourceName, where, scope, path, issues) {
|
|
|
497
573
|
}
|
|
498
574
|
return normalized;
|
|
499
575
|
}
|
|
500
|
-
function
|
|
576
|
+
function isKeptReference(references, value) {
|
|
577
|
+
return (references && routeTransactionReferenceCandidate(value).kind !== "ordinary");
|
|
578
|
+
}
|
|
579
|
+
function normalizeUniqueSelector(contract, resourceName, selector, origin, path, issues, references = false) {
|
|
501
580
|
if (!isPlainRecord(selector)) {
|
|
502
581
|
return selector;
|
|
503
582
|
}
|
|
@@ -508,8 +587,8 @@ function normalizeUniqueSelector(contract, resourceName, selector, scope, path,
|
|
|
508
587
|
const normalized = cloneRecord(selector);
|
|
509
588
|
for (const [fieldName, value] of Object.entries(selector)) {
|
|
510
589
|
const field = lookupField(resource, fieldName);
|
|
511
|
-
if (field?.kind === "scalar") {
|
|
512
|
-
normalized[fieldName] = mergeResult(normalizeScalarFieldValue(contract, field, value,
|
|
590
|
+
if (field?.kind === "scalar" && !isKeptReference(references, value)) {
|
|
591
|
+
normalized[fieldName] = mergeResult(normalizeScalarFieldValue(contract, field, value, origin, [
|
|
513
592
|
...path,
|
|
514
593
|
fieldName,
|
|
515
594
|
]), issues);
|
|
@@ -517,28 +596,28 @@ function normalizeUniqueSelector(contract, resourceName, selector, scope, path,
|
|
|
517
596
|
}
|
|
518
597
|
return normalized;
|
|
519
598
|
}
|
|
520
|
-
function normalizeCursor(contract, resourceName, cursor,
|
|
521
|
-
return normalizeUniqueSelector(contract, resourceName, cursor,
|
|
599
|
+
function normalizeCursor(contract, resourceName, cursor, origin, path, issues, references = false) {
|
|
600
|
+
return normalizeUniqueSelector(contract, resourceName, cursor, origin, path, issues, references);
|
|
522
601
|
}
|
|
523
|
-
function normalizeRelationProjection(contract, edge, value,
|
|
602
|
+
function normalizeRelationProjection(contract, edge, value, origin, path, issues) {
|
|
524
603
|
if (!isPlainRecord(value)) {
|
|
525
604
|
return value;
|
|
526
605
|
}
|
|
527
606
|
const normalized = cloneRecord(value);
|
|
528
607
|
if ("where" in value) {
|
|
529
|
-
normalized.where = normalizeWhere(contract, edge.target, value.where,
|
|
608
|
+
normalized.where = normalizeWhere(contract, edge.target, value.where, origin, [...path, "where"], issues);
|
|
530
609
|
}
|
|
531
610
|
if ("cursor" in value) {
|
|
532
|
-
normalized.cursor = normalizeCursor(contract, edge.target, value.cursor,
|
|
611
|
+
normalized.cursor = normalizeCursor(contract, edge.target, value.cursor, origin, [...path, "cursor"], issues);
|
|
533
612
|
}
|
|
534
613
|
for (const mode of ["select", "include"]) {
|
|
535
614
|
if (mode in value) {
|
|
536
|
-
normalized[mode] = normalizeProjection(contract, edge.target, value[mode],
|
|
615
|
+
normalized[mode] = normalizeProjection(contract, edge.target, value[mode], origin, [...path, mode], issues);
|
|
537
616
|
}
|
|
538
617
|
}
|
|
539
618
|
return normalized;
|
|
540
619
|
}
|
|
541
|
-
function normalizeProjection(contract, resourceName, projection,
|
|
620
|
+
function normalizeProjection(contract, resourceName, projection, origin, path, issues) {
|
|
542
621
|
if (!Array.isArray(projection)) {
|
|
543
622
|
return projection;
|
|
544
623
|
}
|
|
@@ -559,23 +638,20 @@ function normalizeProjection(contract, resourceName, projection, scope, path, is
|
|
|
559
638
|
return entry;
|
|
560
639
|
}
|
|
561
640
|
return {
|
|
562
|
-
[relationName]: normalizeRelationProjection(contract, edge, entry[relationName],
|
|
641
|
+
[relationName]: normalizeRelationProjection(contract, edge, entry[relationName], origin, [...path, index, relationName], issues),
|
|
563
642
|
};
|
|
564
643
|
});
|
|
565
644
|
}
|
|
566
|
-
function normalizeScalarMutation(contract, field, value,
|
|
567
|
-
if (transactionReferences) {
|
|
568
|
-
|
|
569
|
-
if (route.kind !== "ordinary") {
|
|
570
|
-
return value;
|
|
571
|
-
}
|
|
645
|
+
function normalizeScalarMutation(contract, field, value, origin, path, issues, transactionReferences = false) {
|
|
646
|
+
if (isKeptReference(transactionReferences, value)) {
|
|
647
|
+
return value;
|
|
572
648
|
}
|
|
573
649
|
if (!isPlainRecord(value)) {
|
|
574
|
-
return
|
|
650
|
+
return normalizeWrittenValue(contract, field, value, origin, path, issues);
|
|
575
651
|
}
|
|
576
652
|
const directiveKeys = Object.keys(value).filter((key) => key.startsWith("$"));
|
|
577
653
|
if (directiveKeys.length === 0) {
|
|
578
|
-
return
|
|
654
|
+
return normalizeWrittenValue(contract, field, value, origin, path, issues);
|
|
579
655
|
}
|
|
580
656
|
const normalized = cloneRecord(value);
|
|
581
657
|
for (const [directive, operand] of Object.entries(value)) {
|
|
@@ -585,21 +661,18 @@ function normalizeScalarMutation(contract, field, value, scope, path, issues, tr
|
|
|
585
661
|
}
|
|
586
662
|
if (directive === "$push" && field.list) {
|
|
587
663
|
if (Array.isArray(operand)) {
|
|
588
|
-
normalized[directive] = operand.map((entry, index) =>
|
|
589
|
-
...operandPath,
|
|
590
|
-
index,
|
|
591
|
-
]), issues));
|
|
664
|
+
normalized[directive] = operand.map((entry, index) => normalizeWrittenElement(contract, field, entry, origin, [...operandPath, index], issues));
|
|
592
665
|
}
|
|
593
666
|
else {
|
|
594
|
-
normalized[directive] =
|
|
667
|
+
normalized[directive] = normalizeWrittenElement(contract, field, operand, origin, operandPath, issues);
|
|
595
668
|
}
|
|
596
669
|
continue;
|
|
597
670
|
}
|
|
598
|
-
normalized[directive] = mergeResult(normalizeListElement(contract, field, operand,
|
|
671
|
+
normalized[directive] = mergeResult(normalizeListElement(contract, field, operand, origin, operandPath), issues);
|
|
599
672
|
}
|
|
600
673
|
return normalized;
|
|
601
674
|
}
|
|
602
|
-
function normalizeRelationMutation(contract, edge, value,
|
|
675
|
+
function normalizeRelationMutation(contract, edge, value, origin, path, issues, references = false) {
|
|
603
676
|
if (!isPlainRecord(value)) {
|
|
604
677
|
return value;
|
|
605
678
|
}
|
|
@@ -612,8 +685,8 @@ function normalizeRelationMutation(contract, edge, value, scope, path, issues) {
|
|
|
612
685
|
if (directive === "$create") {
|
|
613
686
|
normalized[directive] =
|
|
614
687
|
edge.cardinality === "many" && Array.isArray(operand)
|
|
615
|
-
? entries.map((entry, index) => normalizeMutationData(contract, edge.target, entry,
|
|
616
|
-
: normalizeMutationData(contract, edge.target, operand,
|
|
688
|
+
? entries.map((entry, index) => normalizeMutationData(contract, edge.target, entry, origin, [...directivePath, index], issues, references))
|
|
689
|
+
: normalizeMutationData(contract, edge.target, operand, origin, directivePath, issues, references);
|
|
617
690
|
continue;
|
|
618
691
|
}
|
|
619
692
|
if (directive === "$connect" || directive === "$set") {
|
|
@@ -621,8 +694,8 @@ function normalizeRelationMutation(contract, edge, value, scope, path, issues) {
|
|
|
621
694
|
continue;
|
|
622
695
|
}
|
|
623
696
|
normalized[directive] = Array.isArray(operand)
|
|
624
|
-
? operand.map((entry, index) => normalizeUniqueSelector(contract, edge.target, entry,
|
|
625
|
-
: normalizeUniqueSelector(contract, edge.target, operand,
|
|
697
|
+
? operand.map((entry, index) => normalizeUniqueSelector(contract, edge.target, entry, origin, [...directivePath, index], issues, references))
|
|
698
|
+
: normalizeUniqueSelector(contract, edge.target, operand, origin, directivePath, issues, references);
|
|
626
699
|
continue;
|
|
627
700
|
}
|
|
628
701
|
if (directive === "$disconnect") {
|
|
@@ -630,8 +703,8 @@ function normalizeRelationMutation(contract, edge, value, scope, path, issues) {
|
|
|
630
703
|
continue;
|
|
631
704
|
}
|
|
632
705
|
normalized[directive] = Array.isArray(operand)
|
|
633
|
-
? operand.map((entry, index) => normalizeUniqueSelector(contract, edge.target, entry,
|
|
634
|
-
: normalizeUniqueSelector(contract, edge.target, operand,
|
|
706
|
+
? operand.map((entry, index) => normalizeUniqueSelector(contract, edge.target, entry, origin, [...directivePath, index], issues, references))
|
|
707
|
+
: normalizeUniqueSelector(contract, edge.target, operand, origin, directivePath, issues, references);
|
|
635
708
|
continue;
|
|
636
709
|
}
|
|
637
710
|
if (directive === "$connectOrCreate") {
|
|
@@ -641,8 +714,8 @@ function normalizeRelationMutation(contract, edge, value, scope, path, issues) {
|
|
|
641
714
|
}
|
|
642
715
|
return {
|
|
643
716
|
...entry,
|
|
644
|
-
where: normalizeUniqueSelector(contract, edge.target, entry.where,
|
|
645
|
-
create: normalizeMutationData(contract, edge.target, entry.create,
|
|
717
|
+
where: normalizeUniqueSelector(contract, edge.target, entry.where, origin, [...directivePath, index, "where"], issues, references),
|
|
718
|
+
create: normalizeMutationData(contract, edge.target, entry.create, origin, [...directivePath, index, "create"], issues, references),
|
|
646
719
|
};
|
|
647
720
|
});
|
|
648
721
|
normalized[directive] =
|
|
@@ -660,10 +733,10 @@ function normalizeRelationMutation(contract, edge, value, scope, path, issues) {
|
|
|
660
733
|
...entry,
|
|
661
734
|
...(entry.where !== undefined
|
|
662
735
|
? {
|
|
663
|
-
where: normalizeWhere(contract, edge.target, entry.where,
|
|
736
|
+
where: normalizeWhere(contract, edge.target, entry.where, origin, [...directivePath, index, "where"], issues, references),
|
|
664
737
|
}
|
|
665
738
|
: {}),
|
|
666
|
-
data: normalizeMutationData(contract, edge.target, entry.data,
|
|
739
|
+
data: normalizeMutationData(contract, edge.target, entry.data, origin, [...directivePath, index, "data"], issues, references),
|
|
667
740
|
};
|
|
668
741
|
});
|
|
669
742
|
normalized[directive] =
|
|
@@ -679,7 +752,7 @@ function normalizeRelationMutation(contract, edge, value, scope, path, issues) {
|
|
|
679
752
|
}
|
|
680
753
|
return {
|
|
681
754
|
...entry,
|
|
682
|
-
where: normalizeWhere(contract, edge.target, entry.where,
|
|
755
|
+
where: normalizeWhere(contract, edge.target, entry.where, origin, [...directivePath, index, "where"], issues, references),
|
|
683
756
|
};
|
|
684
757
|
});
|
|
685
758
|
normalized[directive] =
|
|
@@ -697,11 +770,11 @@ function normalizeRelationMutation(contract, edge, value, scope, path, issues) {
|
|
|
697
770
|
...entry,
|
|
698
771
|
...(entry.where !== undefined
|
|
699
772
|
? {
|
|
700
|
-
where: normalizeUniqueSelector(contract, edge.target, entry.where,
|
|
773
|
+
where: normalizeUniqueSelector(contract, edge.target, entry.where, origin, [...directivePath, index, "where"], issues, references),
|
|
701
774
|
}
|
|
702
775
|
: {}),
|
|
703
|
-
create: normalizeMutationData(contract, edge.target, entry.create,
|
|
704
|
-
update: normalizeMutationData(contract, edge.target, entry.update,
|
|
776
|
+
create: normalizeMutationData(contract, edge.target, entry.create, origin, [...directivePath, index, "create"], issues, references),
|
|
777
|
+
update: normalizeMutationData(contract, edge.target, entry.update, origin, [...directivePath, index, "update"], issues, references),
|
|
705
778
|
};
|
|
706
779
|
});
|
|
707
780
|
normalized[directive] =
|
|
@@ -712,7 +785,7 @@ function normalizeRelationMutation(contract, edge, value, scope, path, issues) {
|
|
|
712
785
|
}
|
|
713
786
|
return normalized;
|
|
714
787
|
}
|
|
715
|
-
function normalizeMutationData(contract, resourceName, data,
|
|
788
|
+
function normalizeMutationData(contract, resourceName, data, origin, path, issues, transactionReferences = false) {
|
|
716
789
|
if (!isPlainRecord(data)) {
|
|
717
790
|
return data;
|
|
718
791
|
}
|
|
@@ -724,10 +797,10 @@ function normalizeMutationData(contract, resourceName, data, scope, path, issues
|
|
|
724
797
|
for (const [fieldName, value] of Object.entries(data)) {
|
|
725
798
|
const field = lookupField(resource, fieldName);
|
|
726
799
|
if (field?.kind === "scalar") {
|
|
727
|
-
normalized[fieldName] = normalizeScalarMutation(contract, field, value,
|
|
800
|
+
normalized[fieldName] = normalizeScalarMutation(contract, field, value, origin, [...path, fieldName], issues, transactionReferences);
|
|
728
801
|
}
|
|
729
802
|
else if (field?.kind === "relation") {
|
|
730
|
-
normalized[fieldName] = normalizeRelationMutation(contract, field, value,
|
|
803
|
+
normalized[fieldName] = normalizeRelationMutation(contract, field, value, origin, [...path, fieldName], issues, transactionReferences);
|
|
731
804
|
}
|
|
732
805
|
}
|
|
733
806
|
return normalized;
|
|
@@ -739,36 +812,46 @@ function isUniqueOperation(request) {
|
|
|
739
812
|
request.family === "delete" ||
|
|
740
813
|
request.family === "upsert"));
|
|
741
814
|
}
|
|
742
|
-
export function normalizeOperationScalarValues(contract, request,
|
|
815
|
+
export function normalizeOperationScalarValues(contract, request, origin, options, write = "copy") {
|
|
816
|
+
const previous = writeInPlace;
|
|
817
|
+
writeInPlace = write === "in-place";
|
|
818
|
+
try {
|
|
819
|
+
return normalizeArguments(contract, request, origin, options);
|
|
820
|
+
}
|
|
821
|
+
finally {
|
|
822
|
+
writeInPlace = previous;
|
|
823
|
+
}
|
|
824
|
+
}
|
|
825
|
+
function normalizeArguments(contract, request, origin, options) {
|
|
743
826
|
const issues = [];
|
|
744
827
|
const args = cloneRecord(request.arguments);
|
|
745
828
|
if ("where" in args) {
|
|
746
829
|
args.where = isUniqueOperation(request)
|
|
747
|
-
? normalizeUniqueSelector(contract, request.resource, args.where,
|
|
748
|
-
: normalizeWhere(contract, request.resource, args.where,
|
|
830
|
+
? normalizeUniqueSelector(contract, request.resource, args.where, origin, ["arguments", "where"], issues, options?.transactionReferences === true)
|
|
831
|
+
: normalizeWhere(contract, request.resource, args.where, origin, ["arguments", "where"], issues, options?.transactionReferences === true);
|
|
749
832
|
}
|
|
750
833
|
if ("cursor" in args) {
|
|
751
|
-
args.cursor = normalizeCursor(contract, request.resource, args.cursor,
|
|
834
|
+
args.cursor = normalizeCursor(contract, request.resource, args.cursor, origin, ["arguments", "cursor"], issues, options?.transactionReferences === true);
|
|
752
835
|
}
|
|
753
836
|
for (const mode of ["select", "include"]) {
|
|
754
837
|
if (mode in args) {
|
|
755
|
-
args[mode] = normalizeProjection(contract, request.resource, args[mode],
|
|
838
|
+
args[mode] = normalizeProjection(contract, request.resource, args[mode], origin, ["arguments", mode], issues);
|
|
756
839
|
}
|
|
757
840
|
}
|
|
758
841
|
if (request.family === "create" && "data" in args) {
|
|
759
842
|
args.data = Array.isArray(args.data)
|
|
760
|
-
? args.data.map((entry, index) => normalizeMutationData(contract, request.resource, entry,
|
|
761
|
-
: normalizeMutationData(contract, request.resource, args.data,
|
|
843
|
+
? args.data.map((entry, index) => normalizeMutationData(contract, request.resource, entry, origin, ["arguments", "data", index], issues, options?.transactionReferences === true))
|
|
844
|
+
: normalizeMutationData(contract, request.resource, args.data, origin, ["arguments", "data"], issues, options?.transactionReferences === true);
|
|
762
845
|
}
|
|
763
846
|
if (request.family === "update" && "data" in args) {
|
|
764
|
-
args.data = normalizeMutationData(contract, request.resource, args.data,
|
|
847
|
+
args.data = normalizeMutationData(contract, request.resource, args.data, origin, ["arguments", "data"], issues, options?.transactionReferences === true);
|
|
765
848
|
}
|
|
766
849
|
if (request.family === "upsert") {
|
|
767
850
|
if ("create" in args) {
|
|
768
|
-
args.create = normalizeMutationData(contract, request.resource, args.create,
|
|
851
|
+
args.create = normalizeMutationData(contract, request.resource, args.create, origin, ["arguments", "create"], issues, options?.transactionReferences === true);
|
|
769
852
|
}
|
|
770
853
|
if ("update" in args) {
|
|
771
|
-
args.update = normalizeMutationData(contract, request.resource, args.update,
|
|
854
|
+
args.update = normalizeMutationData(contract, request.resource, args.update, origin, ["arguments", "update"], issues, options?.transactionReferences === true);
|
|
772
855
|
}
|
|
773
856
|
}
|
|
774
857
|
return issues.length > 0
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import type { FrameworkContracts } from "../compiler/contract.compiler.js";
|
|
2
2
|
import type { RequestOrigin } from "../config/config-layer.js";
|
|
3
3
|
import type { OperationIdentity } from "../operations/operation-identity.js";
|
|
4
|
+
import type { CallerDataError } from "../runtime/caller-data.copier.js";
|
|
5
|
+
import type { MisuseReporter } from "../runtime/misuse-reporter.js";
|
|
4
6
|
import type { ClientProtocolIdentity } from "../runtime/operation-request.js";
|
|
5
7
|
import type { OperationFailureResponse } from "../runtime/operation-response.js";
|
|
6
8
|
import type { Operation, OperationFingerprint } from "./deferred-operation.js";
|
|
@@ -20,6 +22,8 @@ export type AssembledTransactionPlan = {
|
|
|
20
22
|
};
|
|
21
23
|
/** Each operation's own origin, by index (mixed plans). */
|
|
22
24
|
readonly origins: readonly TransactionOperationOrigin[];
|
|
25
|
+
/** The steps whose arguments their builder could not copy, by index. */
|
|
26
|
+
readonly refused: ReadonlyMap<number, CallerDataError>;
|
|
23
27
|
} | {
|
|
24
28
|
readonly ok: false;
|
|
25
29
|
readonly response: OperationFailureResponse;
|
|
@@ -35,5 +39,5 @@ export type TransactionPlanAssembler = {
|
|
|
35
39
|
* handle, so a handle another instance built — typed against another model,
|
|
36
40
|
* bound to other Contracts — is refused rather than run.
|
|
37
41
|
*/
|
|
38
|
-
export declare function createTransactionPlanAssembler(contracts: FrameworkContracts, protocol: ClientProtocolIdentity): TransactionPlanAssembler;
|
|
42
|
+
export declare function createTransactionPlanAssembler(contracts: FrameworkContracts, protocol: ClientProtocolIdentity, misuse: MisuseReporter): TransactionPlanAssembler;
|
|
39
43
|
export {};
|