graphddb 0.9.2 → 0.9.3

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.
@@ -1,7 +1,7 @@
1
- import { w as CdcEmulatorOptions, x as ChangeHandler, y as Unsubscribe, F as FaultSpec, z as ConcurrentRecomputeRef, v as ChangeEvent, A as EventLog, G as ReplayOptions, H as ShardId, I as MaintainTrigger, E as EffectPath, g as ProjectionMap, j as MembershipPredicate } from '../key-CWytoEaE.js';
2
- export { J as BatchResult, K as CdcMode, L as ChangeBatch, N as ChangeEventName, O as ClockMode, V as StartingPosition, X as StreamViewType, Y as SubscribeHandler, Z as SubscribeHandlers, _ as buildSubscribeHandler } from '../key-CWytoEaE.js';
3
- import { E as EntityMetadata } from '../types-nk5okD7d.js';
4
- import '../types-CgXS-4Ox.js';
1
+ import { w as CdcEmulatorOptions, x as ChangeHandler, y as Unsubscribe, F as FaultSpec, z as ConcurrentRecomputeRef, v as ChangeEvent, A as EventLog, G as ReplayOptions, H as ShardId, I as MaintainTrigger, E as EffectPath, g as ProjectionMap, j as MembershipPredicate } from '../key-C_6ScBbu.js';
2
+ export { J as BatchResult, K as CdcMode, L as ChangeBatch, N as ChangeEventName, O as ClockMode, V as StartingPosition, X as StreamViewType, Y as SubscribeHandler, Z as SubscribeHandlers, _ as buildSubscribeHandler } from '../key-C_6ScBbu.js';
3
+ import { E as EntityMetadata } from '../types-DLpvjjV_.js';
4
+ import '../types-DGwo00JB.js';
5
5
  import 'behavior-contracts';
6
6
 
7
7
  /**
@@ -1876,6 +1876,209 @@ function portableIrDocument(components) {
1876
1876
  };
1877
1877
  }
1878
1878
 
1879
+ // src/spec/type-notation.ts
1880
+ import {
1881
+ assertPortableComponentGraph
1882
+ } from "behavior-contracts";
1883
+ var UndeterminablePortableType = class extends Error {
1884
+ constructor(message) {
1885
+ super(message);
1886
+ this.name = "UndeterminablePortableType";
1887
+ }
1888
+ };
1889
+ function fieldTypeToPortable(fieldType, where) {
1890
+ switch (fieldType) {
1891
+ case "string":
1892
+ case "binary":
1893
+ return "string";
1894
+ case "number":
1895
+ return "float";
1896
+ case "boolean":
1897
+ return "bool";
1898
+ case "stringSet":
1899
+ return { arr: "string" };
1900
+ case "numberSet":
1901
+ return { arr: "float" };
1902
+ case "list":
1903
+ case "map":
1904
+ throw new UndeterminablePortableType(
1905
+ `type-notation: the '${fieldType}' field at ${where} has no portable type (a DynamoDB ${fieldType} attribute has no modeled element/record shape, and the portable type notation has no free-form/any type). The behavior is left untyped (byte-identical).`
1906
+ );
1907
+ }
1908
+ }
1909
+ var scalarType = fieldTypeToPortable;
1910
+ function relationSegments(nodeId) {
1911
+ return nodeId.split(".").filter((p) => p !== "items");
1912
+ }
1913
+ function nodePorts(node) {
1914
+ if ("map" in node) return node.map.ports;
1915
+ if ("cond" in node) return void 0;
1916
+ return node.ports;
1917
+ }
1918
+ function nodeComponent(node) {
1919
+ if ("map" in node) return node.map.component;
1920
+ if ("cond" in node) return void 0;
1921
+ return node.component;
1922
+ }
1923
+ function isConnectionRootOp(rootComponent, cardinalityOne) {
1924
+ return (rootComponent === "Query" || rootComponent === "BatchGetItem") && !cardinalityOne;
1925
+ }
1926
+ function nodeProjection(ports) {
1927
+ const port = ports.projection;
1928
+ return (port?.arr ?? []).filter((f) => typeof f === "string");
1929
+ }
1930
+ function insertNode(root, node, manifest, nodeById) {
1931
+ const ports = nodePorts(node);
1932
+ if (ports === void 0) return;
1933
+ const segments = relationSegments(node.id);
1934
+ if (segments.length === 0) return;
1935
+ let tree = root;
1936
+ let parent = root;
1937
+ let entity = root.entity;
1938
+ let kind = "single";
1939
+ for (const prop of segments) {
1940
+ parent = tree;
1941
+ const relation = manifest.entities[entity]?.relations[prop];
1942
+ if (relation === void 0) {
1943
+ throw new Error(
1944
+ `type-notation: relation segment '${prop}' of node has no relation on entity '${entity}'; cannot derive its result type. The components graph and the manifest have diverged.`
1945
+ );
1946
+ }
1947
+ kind = relation.type === "hasMany" || relation.type === "refs" ? "connection" : "single";
1948
+ const target = relation.target;
1949
+ let child = tree.children.get(prop);
1950
+ if (!child) {
1951
+ child = {
1952
+ entity: target,
1953
+ projection: [],
1954
+ children: /* @__PURE__ */ new Map(),
1955
+ implicitFields: /* @__PURE__ */ new Set(),
1956
+ relationKind: kind
1957
+ };
1958
+ tree.children.set(prop, child);
1959
+ }
1960
+ tree = child;
1961
+ entity = target;
1962
+ }
1963
+ tree.projection = nodeProjection(ports);
1964
+ tree.relationKind = kind;
1965
+ nodeById.set(node.id, tree);
1966
+ const implicit = ports.implicitSourceField;
1967
+ if (typeof implicit === "string") parent.implicitFields.add(implicit);
1968
+ }
1969
+ function wrapRelation(childObj, kind) {
1970
+ return kind === "connection" ? { obj: { cursor: { opt: "string" }, items: { arr: childObj } } } : { opt: childObj };
1971
+ }
1972
+ function nodeObjType(node, manifest, where, includeRelations) {
1973
+ const meta = manifest.entities[node.entity];
1974
+ const relationProps = new Set(node.children.keys());
1975
+ const scalarFields = node.projection.filter(
1976
+ (f) => !relationProps.has(f) && !node.implicitFields.has(f)
1977
+ );
1978
+ const fields = {};
1979
+ for (const f of scalarFields) {
1980
+ const ft = meta?.fields[f]?.type ?? "string";
1981
+ fields[f] = scalarType(ft, `${where}.${f}`);
1982
+ }
1983
+ if (includeRelations) {
1984
+ for (const [prop, child] of node.children) {
1985
+ const childObj = nodeObjType(child, manifest, `${where}.${prop}`, true);
1986
+ fields[prop] = wrapRelation(childObj, child.relationKind);
1987
+ }
1988
+ }
1989
+ if (Object.keys(fields).length === 0) {
1990
+ throw new UndeterminablePortableType(
1991
+ `type-notation: result node at ${where} (entity '${node.entity}') projects no fields and has no relations \u2014 an empty record has no useful portable type; the behavior is left untyped.`
1992
+ );
1993
+ }
1994
+ return { obj: fields };
1995
+ }
1996
+ function canonicalizeDeep(value) {
1997
+ if (Array.isArray(value)) return value.map(canonicalizeDeep);
1998
+ if (value !== null && typeof value === "object") {
1999
+ const src = value;
2000
+ const out = {};
2001
+ for (const k of Object.keys(src).sort((a, b) => a < b ? -1 : a > b ? 1 : 0)) {
2002
+ out[k] = canonicalizeDeep(src[k]);
2003
+ }
2004
+ return out;
2005
+ }
2006
+ return value;
2007
+ }
2008
+ function annotateQueryComponent(component, rootEntity, cardinalityOne, manifest) {
2009
+ const root = {
2010
+ entity: rootEntity,
2011
+ projection: [],
2012
+ children: /* @__PURE__ */ new Map(),
2013
+ implicitFields: /* @__PURE__ */ new Set()
2014
+ };
2015
+ const rootNode = component.body.find((n) => n.id === "root");
2016
+ if (rootNode !== void 0) {
2017
+ const ports = nodePorts(rootNode);
2018
+ if (ports !== void 0) root.projection = nodeProjection(ports);
2019
+ }
2020
+ const nodeById = /* @__PURE__ */ new Map();
2021
+ for (const node of component.body) {
2022
+ if (node.id === "root") continue;
2023
+ insertNode(root, node, manifest, nodeById);
2024
+ }
2025
+ const annotatedBody = component.body.map((node) => {
2026
+ if ("cond" in node) {
2027
+ throw new Error(
2028
+ `type-notation: unexpected 'cond' node '${node.id}' in query component '${component.name}'; query lowering does not emit conditionals, so its outType cannot be derived.`
2029
+ );
2030
+ }
2031
+ if (node.id === "root") {
2032
+ const outType2 = isConnectionRootOp(nodeComponent(node), cardinalityOne) ? wrapRelation(nodeObjType(root, manifest, `${component.name}.root`, true), "connection") : nodeObjType(root, manifest, `${component.name}.root`, false);
2033
+ return { ...node, outType: outType2 };
2034
+ }
2035
+ const rn = nodeById.get(node.id);
2036
+ if (rn === void 0) {
2037
+ throw new Error(
2038
+ `type-notation: no result-tree node for body node '${node.id}' in component '${component.name}'; the model\u2192annotation walk is incomplete (fail-closed \u2014 not skipped).`
2039
+ );
2040
+ }
2041
+ const obj = nodeObjType(rn, manifest, `${component.name}.${node.id}`, true);
2042
+ const outType = wrapRelation(obj, rn.relationKind);
2043
+ return { ...node, outType };
2044
+ });
2045
+ const hasRelations = root.children.size > 0;
2046
+ const rootIsConnection = rootNode !== void 0 && isConnectionRootOp(nodeComponent(rootNode), cardinalityOne);
2047
+ let outputType;
2048
+ if (rootIsConnection) {
2049
+ outputType = wrapRelation(nodeObjType(root, manifest, `${component.name}#output`, true), "connection");
2050
+ } else if (!hasRelations) {
2051
+ outputType = nodeObjType(root, manifest, `${component.name}#output.root`, false);
2052
+ } else {
2053
+ const rootObj = nodeObjType(root, manifest, `${component.name}#output.root`, false);
2054
+ const fields = { root: rootObj };
2055
+ for (const [prop, child] of root.children) {
2056
+ const childObj = nodeObjType(child, manifest, `${component.name}#output.${prop}`, true);
2057
+ fields[prop] = wrapRelation(childObj, child.relationKind);
2058
+ }
2059
+ outputType = { obj: fields };
2060
+ }
2061
+ return canonicalizeDeep({ ...component, body: annotatedBody, outputType });
2062
+ }
2063
+ function annotateComponents(components, typeFacts, manifest) {
2064
+ const out = components.map((c) => {
2065
+ const facts = typeFacts.get(c.name);
2066
+ if (facts === void 0) return c;
2067
+ try {
2068
+ return annotateQueryComponent(c, facts.rootEntity, facts.cardinalityOne, manifest);
2069
+ } catch (err) {
2070
+ if (err instanceof UndeterminablePortableType) return c;
2071
+ throw err;
2072
+ }
2073
+ });
2074
+ assertPortableComponentGraph({
2075
+ irVersion: 1,
2076
+ exprVersion: EXPR_VERSION,
2077
+ components: out
2078
+ });
2079
+ return out;
2080
+ }
2081
+
1879
2082
  // src/spec/operations.ts
1880
2083
  function paramSpecs(params) {
1881
2084
  const out = {};
@@ -2311,6 +2514,9 @@ function buildQuerySpec(def) {
2311
2514
  operations,
2312
2515
  // operation 'query' → a single entity object; 'list' → a connection.
2313
2516
  cardinality: def.operation === "query" ? "one" : "many",
2517
+ // The root model — the SSoT anchor for the bc#45 type-notation derivation
2518
+ // (build-internal; dropped by toPortableQuery, so operations.json is unchanged).
2519
+ entity: def.entity.name,
2314
2520
  ...executionPlan !== void 0 ? { executionPlan } : {},
2315
2521
  // Pure-documentation description (issue #154); absent → byte-identical spec.
2316
2522
  ...def.description !== void 0 ? { description: def.description } : {}
@@ -2398,6 +2604,15 @@ function buildOperations(queries = {}, commands = {}, transactions = {}, contrac
2398
2604
  },
2399
2605
  contractSpecs
2400
2606
  );
2607
+ const typeFacts = /* @__PURE__ */ new Map();
2608
+ for (const [name, spec] of Object.entries(querySpecs)) {
2609
+ if (spec.entity === void 0) continue;
2610
+ typeFacts.set(name, {
2611
+ rootEntity: spec.entity,
2612
+ cardinalityOne: spec.cardinality === "one"
2613
+ });
2614
+ }
2615
+ const annotatedComponents = typeFacts.size > 0 ? annotateComponents(components, typeFacts, buildManifest()) : components;
2401
2616
  const portableQueries = {};
2402
2617
  for (const [name, spec] of Object.entries(querySpecs)) {
2403
2618
  portableQueries[name] = toPortableQuery(name, spec);
@@ -2416,7 +2631,7 @@ function buildOperations(queries = {}, commands = {}, transactions = {}, contrac
2416
2631
  return {
2417
2632
  version: operationsSpecVersion(content),
2418
2633
  ...content,
2419
- ...components.length > 0 ? { components } : {}
2634
+ ...annotatedComponents.length > 0 ? { components: annotatedComponents } : {}
2420
2635
  };
2421
2636
  }
2422
2637