graphddb 0.7.10 → 0.8.1
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/README.md +6 -6
- package/dist/cdc/index.d.ts +389 -5
- package/dist/cdc/index.js +4 -4
- package/dist/{chunk-AD6ZQTTE.js → chunk-GS4C5VGO.js} +2 -6
- package/dist/{chunk-DFUKGU2Q.js → chunk-HNY2EJPV.js} +216 -229
- package/dist/{chunk-3ZU2VW3L.js → chunk-L2NEDS7U.js} +582 -781
- package/dist/chunk-L4QRCHRQ.js +278 -0
- package/dist/chunk-LAT64YCZ.js +1987 -0
- package/dist/chunk-S2NI4PBW.js +187 -0
- package/dist/{chunk-EOJDN3SA.js → chunk-T44OB5GU.js} +3757 -6138
- package/dist/{chunk-PDUVTYC5.js → chunk-XTWXMOHD.js} +0 -1
- package/dist/cli.js +63 -254
- package/dist/index.d.ts +23 -1550
- package/dist/index.js +94 -1850
- package/dist/internal/index.d.ts +84 -0
- package/dist/internal/index.js +701 -0
- package/dist/{maintenance-view-adapter-BAZ9uBGe.d.ts → key-DZtjAQDh.d.ts} +573 -1817
- package/dist/linter/index.d.ts +39 -7
- package/dist/linter/index.js +22 -4
- package/dist/{registry-LWE54Sdc.d.ts → linter-DQY7gUEk.d.ts} +22 -22
- package/dist/prepared-artifact-HFealr1q.d.ts +281 -0
- package/dist/spec/index.d.ts +506 -5
- package/dist/spec/index.js +22 -18
- package/dist/testing/index.d.ts +2 -3
- package/dist/testing/index.js +4 -4
- package/dist/transform/index.d.ts +1 -1
- package/dist/transform/index.js +4 -4
- package/dist/{types-BQLzTEqh.d.ts → types-2PMXEn5x.d.ts} +8 -10
- package/dist/types-DW__-Icc.d.ts +450 -0
- package/docs/cdc-projection.md +5 -5
- package/docs/class-hydration.md +1 -1
- package/docs/cqrs-contract.md +79 -20
- package/docs/design-patterns.md +5 -5
- package/docs/docs-generation.md +6 -6
- package/docs/middleware.md +15 -15
- package/docs/mutation-command-derivation.md +52 -42
- package/docs/prepared-statements.md +14 -14
- package/docs/python-bridge.md +96 -65
- package/docs/spec.md +153 -124
- package/docs/testing.md +9 -8
- package/package.json +14 -4
- package/dist/chunk-3UD3XIF2.js +0 -860
- package/dist/chunk-MMVHOUM4.js +0 -24
- package/dist/from-change-Ty95KA8C.d.ts +0 -327
- package/dist/index-Dc7d8mWI.d.ts +0 -1089
- package/dist/relation-depth-BRS513Tq.d.ts +0 -36
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
import {
|
|
2
|
+
evaluateKey
|
|
3
|
+
} from "./chunk-T44OB5GU.js";
|
|
4
|
+
import {
|
|
5
|
+
SPEC_VERSION
|
|
6
|
+
} from "./chunk-L4QRCHRQ.js";
|
|
7
|
+
import {
|
|
8
|
+
MetadataRegistry
|
|
9
|
+
} from "./chunk-L2NEDS7U.js";
|
|
10
|
+
import {
|
|
11
|
+
TableMapping
|
|
12
|
+
} from "./chunk-XTWXMOHD.js";
|
|
13
|
+
|
|
14
|
+
// src/spec/manifest.ts
|
|
15
|
+
var DYNAMO_TYPE_TO_FIELD_TYPE = {
|
|
16
|
+
S: "string",
|
|
17
|
+
N: "number",
|
|
18
|
+
BOOL: "boolean",
|
|
19
|
+
B: "binary",
|
|
20
|
+
SS: "stringSet",
|
|
21
|
+
NS: "numberSet",
|
|
22
|
+
L: "list",
|
|
23
|
+
M: "map"
|
|
24
|
+
};
|
|
25
|
+
function sortedRecord(record) {
|
|
26
|
+
const out = {};
|
|
27
|
+
for (const key of Object.keys(record).sort()) {
|
|
28
|
+
out[key] = record[key];
|
|
29
|
+
}
|
|
30
|
+
return out;
|
|
31
|
+
}
|
|
32
|
+
function buildKey(key) {
|
|
33
|
+
if (!key) return null;
|
|
34
|
+
const { pk, sk } = evaluateKey(key.segmented, "param");
|
|
35
|
+
return {
|
|
36
|
+
inputFields: [...key.inputFieldNames],
|
|
37
|
+
pkTemplate: pk,
|
|
38
|
+
skTemplate: sk ?? null
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
function buildGsis(metadata) {
|
|
42
|
+
return [...metadata.gsiDefinitions].sort((a, b) => a.indexName.localeCompare(b.indexName)).map((gsi) => {
|
|
43
|
+
const { pk, sk } = evaluateKey(gsi.segmented, "param");
|
|
44
|
+
return {
|
|
45
|
+
indexName: gsi.indexName,
|
|
46
|
+
unique: gsi.unique,
|
|
47
|
+
inputFields: [...gsi.inputFieldNames],
|
|
48
|
+
pkTemplate: pk,
|
|
49
|
+
skTemplate: sk ?? null,
|
|
50
|
+
// Purely-documentary GSI description (issue #166); emitted only when declared
|
|
51
|
+
// so an undescribed index is byte-identical to the pre-#166 manifest.
|
|
52
|
+
...gsi.description !== void 0 ? { description: gsi.description } : {}
|
|
53
|
+
};
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
function buildRelations(metadata) {
|
|
57
|
+
const relations = {};
|
|
58
|
+
for (const rel of metadata.relations) {
|
|
59
|
+
const targetClass = rel.targetFactory();
|
|
60
|
+
relations[rel.propertyName] = {
|
|
61
|
+
type: rel.type,
|
|
62
|
+
target: targetClass.name,
|
|
63
|
+
keyBinding: { ...rel.keyBinding },
|
|
64
|
+
// List-valued source descriptor for a `refs` relation (issue #197); emitted
|
|
65
|
+
// only for `refs` so a scalar-keyed relation is byte-identical to the pre-#197
|
|
66
|
+
// manifest.
|
|
67
|
+
...rel.refs !== void 0 ? { refs: { ...rel.refs } } : {},
|
|
68
|
+
// Purely-documentary relation description (issue #166); emitted only when
|
|
69
|
+
// declared so an undescribed relation is byte-identical to the pre-#166 manifest.
|
|
70
|
+
...rel.options?.description !== void 0 ? { description: rel.options.description } : {}
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
return sortedRecord(relations);
|
|
74
|
+
}
|
|
75
|
+
function buildFields(metadata) {
|
|
76
|
+
const fields = {};
|
|
77
|
+
for (const field of metadata.fields) {
|
|
78
|
+
const format = field.options?.format;
|
|
79
|
+
const description = field.options?.description;
|
|
80
|
+
fields[field.propertyName] = {
|
|
81
|
+
type: DYNAMO_TYPE_TO_FIELD_TYPE[field.dynamoType],
|
|
82
|
+
...format ? { format } : {},
|
|
83
|
+
...description !== void 0 ? { description } : {}
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
return sortedRecord(fields);
|
|
87
|
+
}
|
|
88
|
+
function buildManifestEntity(metadata) {
|
|
89
|
+
return buildEntity(metadata);
|
|
90
|
+
}
|
|
91
|
+
function buildEntity(metadata) {
|
|
92
|
+
return {
|
|
93
|
+
table: metadata.tableName,
|
|
94
|
+
physicalName: TableMapping.resolve(metadata.tableName),
|
|
95
|
+
prefix: metadata.prefix,
|
|
96
|
+
fields: buildFields(metadata),
|
|
97
|
+
key: buildKey(metadata.primaryKey),
|
|
98
|
+
gsis: buildGsis(metadata),
|
|
99
|
+
relations: buildRelations(metadata),
|
|
100
|
+
...metadata.description !== void 0 ? { description: metadata.description } : {},
|
|
101
|
+
// TTL (issue #172, Epic #167 — C4): a physical-schema fact carried on the
|
|
102
|
+
// manifest so the CFn emitter can render `TimeToLiveSpecification`. Absent
|
|
103
|
+
// when no `@ttl` field is declared (byte-identical to the pre-#172 manifest).
|
|
104
|
+
...metadata.ttlAttribute !== void 0 ? { ttlAttribute: metadata.ttlAttribute } : {}
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
function buildManifest(registry = MetadataRegistry) {
|
|
108
|
+
const all = registry.getAll();
|
|
109
|
+
const entitiesByName = /* @__PURE__ */ new Map();
|
|
110
|
+
for (const [cls, metadata] of all) {
|
|
111
|
+
entitiesByName.set(cls.name, metadata);
|
|
112
|
+
}
|
|
113
|
+
const entities = {};
|
|
114
|
+
const tables = {};
|
|
115
|
+
const ttlByPhysicalTable = /* @__PURE__ */ new Map();
|
|
116
|
+
for (const name of [...entitiesByName.keys()].sort()) {
|
|
117
|
+
const metadata = entitiesByName.get(name);
|
|
118
|
+
entities[name] = buildEntity(metadata);
|
|
119
|
+
const physicalName = TableMapping.resolve(metadata.tableName);
|
|
120
|
+
tables[metadata.tableName] = {
|
|
121
|
+
physicalName
|
|
122
|
+
};
|
|
123
|
+
if (metadata.ttlAttribute !== void 0) {
|
|
124
|
+
const existing = ttlByPhysicalTable.get(physicalName);
|
|
125
|
+
if (existing && existing.attr !== metadata.ttlAttribute) {
|
|
126
|
+
throw new Error(
|
|
127
|
+
`Manifest build: physical table '${physicalName}' has more than one TTL attribute \u2014 entity '${existing.entity}' declares \`@ttl\` on '${existing.attr}' and entity '${name}' on '${metadata.ttlAttribute}'. DynamoDB allows exactly one TTL attribute per table; align the \`@ttl\` attribute across all entities sharing this table (or drop one).`
|
|
128
|
+
);
|
|
129
|
+
}
|
|
130
|
+
if (!existing) {
|
|
131
|
+
ttlByPhysicalTable.set(physicalName, {
|
|
132
|
+
entity: name,
|
|
133
|
+
attr: metadata.ttlAttribute
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
return {
|
|
139
|
+
version: SPEC_VERSION,
|
|
140
|
+
tables: sortedRecord(tables),
|
|
141
|
+
entities
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// src/spec/prepared-artifact.ts
|
|
146
|
+
var PREPARED_FORMAT_VERSION = "2";
|
|
147
|
+
function canonicalJson(value) {
|
|
148
|
+
return JSON.stringify(value, (_k, v) => {
|
|
149
|
+
if (v !== null && typeof v === "object" && !Array.isArray(v)) {
|
|
150
|
+
const sorted = {};
|
|
151
|
+
for (const key of Object.keys(v).sort()) {
|
|
152
|
+
sorted[key] = v[key];
|
|
153
|
+
}
|
|
154
|
+
return sorted;
|
|
155
|
+
}
|
|
156
|
+
return v;
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
var FNV64_OFFSET_BASIS = 0xcbf29ce484222325n;
|
|
160
|
+
var FNV64_PRIME = 0x100000001b3n;
|
|
161
|
+
var U64_MASK = 0xffffffffffffffffn;
|
|
162
|
+
function fnv1a64Hex(input) {
|
|
163
|
+
let hash = FNV64_OFFSET_BASIS;
|
|
164
|
+
for (let i = 0; i < input.length; i++) {
|
|
165
|
+
const unit = input.charCodeAt(i);
|
|
166
|
+
hash ^= BigInt(unit & 255);
|
|
167
|
+
hash = hash * FNV64_PRIME & U64_MASK;
|
|
168
|
+
hash ^= BigInt(unit >>> 8);
|
|
169
|
+
hash = hash * FNV64_PRIME & U64_MASK;
|
|
170
|
+
}
|
|
171
|
+
return hash.toString(16).padStart(16, "0");
|
|
172
|
+
}
|
|
173
|
+
function entityFingerprint(metadata) {
|
|
174
|
+
return fnv1a64Hex(canonicalJson(buildManifestEntity(metadata)));
|
|
175
|
+
}
|
|
176
|
+
function planFingerprint(plan) {
|
|
177
|
+
return fnv1a64Hex(canonicalJson(plan));
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
export {
|
|
181
|
+
buildManifestEntity,
|
|
182
|
+
buildManifest,
|
|
183
|
+
PREPARED_FORMAT_VERSION,
|
|
184
|
+
canonicalJson,
|
|
185
|
+
entityFingerprint,
|
|
186
|
+
planFingerprint
|
|
187
|
+
};
|