@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.
Files changed (108) hide show
  1. package/CHANGELOG.md +338 -0
  2. package/README.md +100 -3
  3. package/dist/adapters/adapter-model.d.ts +8 -0
  4. package/dist/adapters/adapter.interface.d.ts +6 -2
  5. package/dist/compiler/contract-compiler-diagnostic.d.ts +6 -0
  6. package/dist/compiler/contract.compiler.js +67 -0
  7. package/dist/config/config.resolver.d.ts +3 -0
  8. package/dist/config/config.resolver.js +1 -0
  9. package/dist/config/config.validator.js +6 -0
  10. package/dist/config/define-fields.d.ts +10 -3
  11. package/dist/config/framework-config.d.ts +4 -1
  12. package/dist/config/framework-fields-config.d.ts +6 -0
  13. package/dist/contracts/client-contract-structure.validator.d.ts +21 -1
  14. package/dist/contracts/client-contract-structure.validator.js +99 -2
  15. package/dist/contracts/contract-canonicalizer.js +32 -0
  16. package/dist/contracts/contract.d.ts +7 -0
  17. package/dist/contracts/field.d.ts +10 -0
  18. package/dist/contracts/json-shape.d.ts +65 -0
  19. package/dist/contracts/json-shape.js +1 -0
  20. package/dist/contracts/reference-write-limit.d.ts +7 -0
  21. package/dist/contracts/reference-write-limit.js +1 -0
  22. package/dist/contracts/scalar-value-type.d.ts +12 -1
  23. package/dist/framework/contract-view.d.ts +126 -21
  24. package/dist/framework/framework.d.ts +5 -3
  25. package/dist/framework/framework.factory.js +56 -13
  26. package/dist/index.d.ts +8 -40
  27. package/dist/index.js +0 -20
  28. package/dist/internal.d.ts +35 -0
  29. package/dist/internal.js +16 -0
  30. package/dist/json/avz.d.ts +96 -0
  31. package/dist/json/avz.js +212 -0
  32. package/dist/json/index.d.ts +6 -0
  33. package/dist/json/index.js +1 -0
  34. package/dist/json/json-shape.registry.d.ts +22 -0
  35. package/dist/json/json-shape.registry.js +16 -0
  36. package/dist/json/zod-issue.translator.d.ts +51 -0
  37. package/dist/json/zod-issue.translator.js +142 -0
  38. package/dist/operations/operation-arguments.d.ts +151 -101
  39. package/dist/operations/operation-identity.d.ts +2 -0
  40. package/dist/operations/operation-identity.js +3 -0
  41. package/dist/operations/operation-validator-core.d.ts +1 -1
  42. package/dist/operations/operation-validator-core.js +28 -10
  43. package/dist/operations/operation-validator.d.ts +20 -5
  44. package/dist/operations/operation-validator.js +26 -10
  45. package/dist/operations/projection-scope.resolver.d.ts +1 -1
  46. package/dist/operations/structural-limits.walker.d.ts +19 -0
  47. package/dist/operations/structural-limits.walker.js +344 -0
  48. package/dist/protocol/absent-route.responder.d.ts +2 -1
  49. package/dist/protocol/absent-route.responder.js +32 -6
  50. package/dist/protocol/http-request.decoder.d.ts +6 -0
  51. package/dist/protocol/http-request.decoder.js +11 -3
  52. package/dist/protocol/protocol.binder.d.ts +4 -2
  53. package/dist/protocol/protocol.binder.js +3 -1
  54. package/dist/protocol/protocol.handler.d.ts +6 -2
  55. package/dist/protocol/protocol.handler.js +14 -4
  56. package/dist/protocol/unmounted-route.error.d.ts +19 -0
  57. package/dist/protocol/unmounted-route.error.js +10 -0
  58. package/dist/runtime/caller-data.copier.d.ts +59 -0
  59. package/dist/runtime/caller-data.copier.js +470 -0
  60. package/dist/runtime/caller-data.door.d.ts +56 -0
  61. package/dist/runtime/caller-data.door.js +65 -0
  62. package/dist/runtime/computed-read-runtime.js +3 -10
  63. package/dist/runtime/computed-value.error.d.ts +13 -0
  64. package/dist/runtime/computed-value.error.js +9 -0
  65. package/dist/runtime/create-requirement.d.ts +43 -7
  66. package/dist/runtime/create-requirement.js +89 -9
  67. package/dist/runtime/diagnostics-reporter.d.ts +20 -4
  68. package/dist/runtime/diagnostics-reporter.js +11 -4
  69. package/dist/runtime/error-boundary.d.ts +8 -0
  70. package/dist/runtime/error-boundary.js +65 -35
  71. package/dist/runtime/field-behavior.d.ts +2 -2
  72. package/dist/runtime/framework-error.d.ts +12 -0
  73. package/dist/runtime/misuse-reporter.d.ts +32 -0
  74. package/dist/runtime/misuse-reporter.js +19 -0
  75. package/dist/runtime/mutation-planner.js +13 -11
  76. package/dist/runtime/operation-request.d.ts +4 -11
  77. package/dist/runtime/operation-runtime.d.ts +14 -7
  78. package/dist/runtime/operation-runtime.js +37 -18
  79. package/dist/runtime/outcome-mapper.js +12 -2
  80. package/dist/runtime/output-validator.d.ts +10 -0
  81. package/dist/runtime/output-validator.js +11 -0
  82. package/dist/runtime/owned-execution.registry.d.ts +13 -0
  83. package/dist/runtime/owned-execution.registry.js +7 -0
  84. package/dist/runtime/pipeline.d.ts +19 -7
  85. package/dist/runtime/referential-action.d.ts +7 -0
  86. package/dist/runtime/request-envelope.validator.d.ts +5 -0
  87. package/dist/runtime/request-envelope.validator.js +118 -0
  88. package/dist/runtime/scalar-runtime.d.ts +30 -2
  89. package/dist/runtime/scalar-runtime.js +162 -79
  90. package/dist/transactions/transaction-plan-assembler.d.ts +5 -1
  91. package/dist/transactions/transaction-plan-assembler.js +74 -75
  92. package/dist/transactions/transaction-plan-validator.d.ts +30 -7
  93. package/dist/transactions/transaction-plan-validator.js +204 -153
  94. package/dist/transactions/transaction-reference-collector.d.ts +30 -0
  95. package/dist/transactions/transaction-reference-collector.js +204 -0
  96. package/dist/transactions/transaction-reference-resolver.js +10 -5
  97. package/dist/transactions/transaction-reference-validator.js +24 -17
  98. package/dist/transactions/transaction-reference.d.ts +23 -51
  99. package/dist/transactions/transaction-request.d.ts +3 -3
  100. package/dist/transactions/transaction-response.d.ts +6 -1
  101. package/dist/transactions/transaction-response.js +24 -1
  102. package/dist/transactions/transaction-runtime.d.ts +4 -2
  103. package/dist/transactions/transaction-runtime.js +4 -3
  104. package/package.json +17 -3
  105. package/dist/operations/operation-boolean-nodes.d.ts +0 -11
  106. package/dist/operations/operation-boolean-nodes.js +0 -283
  107. package/dist/operations/operation-nesting.d.ts +0 -8
  108. 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 { routeTransactionReferenceCandidate } from "../transactions/transaction-reference.js";
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, scope, path, allowNull) {
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 (scope === "application") {
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 (scope === "application") {
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 (scope === "application") {
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 (scope === "application") {
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, scope, path) {
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, scope === "runtime" ? "application" : scope, [...path, index], false);
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, scope === "runtime" ? "application" : scope, path, field.nullable);
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, scope, path) {
394
- return normalizeScalarAtom(contract, field, value, scope, path, false);
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
- function normalizeScalarFilter(contract, field, value, scope, path, issues) {
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, scope, path), issues);
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, scope, operandPath, issues);
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, scope, [
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, scope, operandPath), issues);
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, scope, [
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, scope, operandPath), issues);
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, scope, path, issues) {
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, scope, [...path, key, index], issues));
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, scope, [...path, key], issues);
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, scope, [...path, key], issues);
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, scope, [...path, key], issues);
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], scope, [...path, key, relationOperator], issues);
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 normalizeUniqueSelector(contract, resourceName, selector, scope, path, issues) {
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, scope, [
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, scope, path, issues) {
521
- return normalizeUniqueSelector(contract, resourceName, cursor, scope, path, issues);
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, scope, path, issues) {
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, scope, [...path, "where"], issues);
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, scope, [...path, "cursor"], issues);
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], scope, [...path, mode], issues);
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, scope, path, issues) {
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], scope, [...path, index, relationName], issues),
641
+ [relationName]: normalizeRelationProjection(contract, edge, entry[relationName], origin, [...path, index, relationName], issues),
563
642
  };
564
643
  });
565
644
  }
566
- function normalizeScalarMutation(contract, field, value, scope, path, issues, transactionReferences = false) {
567
- if (transactionReferences) {
568
- const route = routeTransactionReferenceCandidate(value);
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 mergeResult(normalizeScalarFieldValue(contract, field, value, scope, path), issues);
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 mergeResult(normalizeScalarFieldValue(contract, field, value, scope, path), issues);
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) => mergeResult(normalizeListElement(contract, field, entry, scope, [
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] = mergeResult(normalizeListElement(contract, field, operand, scope, operandPath), issues);
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, scope, operandPath), issues);
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, scope, path, issues) {
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, scope, [...directivePath, index], issues))
616
- : normalizeMutationData(contract, edge.target, operand, scope, directivePath, issues);
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, scope, [...directivePath, index], issues))
625
- : normalizeUniqueSelector(contract, edge.target, operand, scope, directivePath, issues);
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, scope, [...directivePath, index], issues))
634
- : normalizeUniqueSelector(contract, edge.target, operand, scope, directivePath, issues);
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, scope, [...directivePath, index, "where"], issues),
645
- create: normalizeMutationData(contract, edge.target, entry.create, scope, [...directivePath, index, "create"], issues),
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, scope, [...directivePath, index, "where"], issues),
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, scope, [...directivePath, index, "data"], issues),
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, scope, [...directivePath, index, "where"], issues),
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, scope, [...directivePath, index, "where"], issues),
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, scope, [...directivePath, index, "create"], issues),
704
- update: normalizeMutationData(contract, edge.target, entry.update, scope, [...directivePath, index, "update"], issues),
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, scope, path, issues, transactionReferences = false) {
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, scope, [...path, fieldName], issues, transactionReferences);
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, scope, [...path, fieldName], issues);
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, scope, options) {
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, scope, ["arguments", "where"], issues)
748
- : normalizeWhere(contract, request.resource, args.where, scope, ["arguments", "where"], issues);
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, scope, ["arguments", "cursor"], issues);
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], scope, ["arguments", mode], issues);
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, scope, ["arguments", "data", index], issues, options?.transactionReferences === true))
761
- : normalizeMutationData(contract, request.resource, args.data, scope, ["arguments", "data"], issues, options?.transactionReferences === true);
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, scope, ["arguments", "data"], issues, options?.transactionReferences === true);
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, scope, ["arguments", "create"], issues, options?.transactionReferences === true);
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, scope, ["arguments", "update"], issues, options?.transactionReferences === true);
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 {};