@x12i/memorix-associator 1.0.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/README.md +90 -0
- package/dist/associated-properties/index.d.ts +16 -0
- package/dist/associated-properties/index.d.ts.map +1 -0
- package/dist/associated-properties/index.js +118 -0
- package/dist/associated-properties/index.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +88 -0
- package/dist/cli.js.map +1 -0
- package/dist/engine.d.ts +12 -0
- package/dist/engine.d.ts.map +1 -0
- package/dist/engine.js +115 -0
- package/dist/engine.js.map +1 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +13 -0
- package/dist/index.js.map +1 -0
- package/dist/planning/build-plan.d.ts +10 -0
- package/dist/planning/build-plan.d.ts.map +1 -0
- package/dist/planning/build-plan.js +319 -0
- package/dist/planning/build-plan.js.map +1 -0
- package/dist/planning/fingerprint.d.ts +19 -0
- package/dist/planning/fingerprint.d.ts.map +1 -0
- package/dist/planning/fingerprint.js +47 -0
- package/dist/planning/fingerprint.js.map +1 -0
- package/dist/request/schema.d.ts +213 -0
- package/dist/request/schema.d.ts.map +1 -0
- package/dist/request/schema.js +2 -0
- package/dist/request/schema.js.map +1 -0
- package/dist/request/validate.d.ts +6 -0
- package/dist/request/validate.d.ts.map +1 -0
- package/dist/request/validate.js +64 -0
- package/dist/request/validate.js.map +1 -0
- package/dist/store/mongo.d.ts +4 -0
- package/dist/store/mongo.d.ts.map +1 -0
- package/dist/store/mongo.js +26 -0
- package/dist/store/mongo.js.map +1 -0
- package/dist/store/types.d.ts +30 -0
- package/dist/store/types.d.ts.map +1 -0
- package/dist/store/types.js +64 -0
- package/dist/store/types.js.map +1 -0
- package/dist/verification/associated-shape.d.ts +7 -0
- package/dist/verification/associated-shape.d.ts.map +1 -0
- package/dist/verification/associated-shape.js +52 -0
- package/dist/verification/associated-shape.js.map +1 -0
- package/dist/writing/failures.d.ts +13 -0
- package/dist/writing/failures.d.ts.map +1 -0
- package/dist/writing/failures.js +18 -0
- package/dist/writing/failures.js.map +1 -0
- package/dist/writing/smart-merge.d.ts +19 -0
- package/dist/writing/smart-merge.d.ts.map +1 -0
- package/dist/writing/smart-merge.js +77 -0
- package/dist/writing/smart-merge.js.map +1 -0
- package/docs/running-associations.md +340 -0
- package/examples/minimal-association-request.json +46 -0
- package/package.json +57 -0
package/README.md
ADDED
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
# @x12i/memorix-associator
|
|
2
|
+
|
|
3
|
+
Memorix cross-record association materialization — plan, apply, verify, and associated-property metadata.
|
|
4
|
+
|
|
5
|
+
## Responsibilities
|
|
6
|
+
|
|
7
|
+
- Build reviewable association plans from declarative rules.
|
|
8
|
+
- Apply idempotent smart merges onto `associated*` snapshot fields.
|
|
9
|
+
- Write technical failure records to `<objectType>-failed` collections.
|
|
10
|
+
- Discover and merge associated snapshot property metadata (`managed`, `discovered`, `both`).
|
|
11
|
+
|
|
12
|
+
Resolver logic lives in [`@x12i/memorix-resolvers`](../memorix-resolvers/). This package consumes resolver output but does not hard-code resolver types.
|
|
13
|
+
|
|
14
|
+
## Associated property metadata
|
|
15
|
+
|
|
16
|
+
### Discovery (FR A)
|
|
17
|
+
|
|
18
|
+
For `contentType === "snapshots"`, any root-level field whose name starts with `associated` is a valid associated property — including custom names like `associatedRiskScores`.
|
|
19
|
+
|
|
20
|
+
### Managed metadata (FR B)
|
|
21
|
+
|
|
22
|
+
Managed descriptor entries describe associated properties intentionally (linked object type, content type, value shape, description).
|
|
23
|
+
|
|
24
|
+
### Merge contract
|
|
25
|
+
|
|
26
|
+
`mergeAssociatedPropertyDescriptors()` returns one list with `source: "managed" | "discovered" | "both"`. Managed metadata is authoritative; discovery fills gaps.
|
|
27
|
+
|
|
28
|
+
### Consumer guidance
|
|
29
|
+
|
|
30
|
+
```text
|
|
31
|
+
Consumers should prefer Memorix associated-property metadata when available. Until metadata is available, or when reading older/custom records, fall back to the prefix rule: root-level snapshot fields whose names start with "associated".
|
|
32
|
+
|
|
33
|
+
The well-known names associatedData, associatedInferred, and associatedAnalysis are conventions only.
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
See `ASSOCIATED_PROPERTY_CONSUMER_GUIDANCE` export.
|
|
37
|
+
|
|
38
|
+
## API
|
|
39
|
+
|
|
40
|
+
```typescript
|
|
41
|
+
import { planAssociations, applyAssociations, InMemoryRecordStore } from "@x12i/memorix-associator";
|
|
42
|
+
|
|
43
|
+
const plan = await planAssociations(request, { store });
|
|
44
|
+
const result = await applyAssociations({ ...request, mode: "apply" }, { store });
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Running associations
|
|
48
|
+
|
|
49
|
+
**Full guide:** [docs/running-associations.md](docs/running-associations.md)
|
|
50
|
+
|
|
51
|
+
Quick start:
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
export MONGO_URI="mongodb://…"
|
|
55
|
+
npm run build
|
|
56
|
+
|
|
57
|
+
# 1. Dry-run — review counts and planFingerprint
|
|
58
|
+
memorix-associator plan \
|
|
59
|
+
--request examples/minimal-association-request.json \
|
|
60
|
+
--output temp/plan.json
|
|
61
|
+
|
|
62
|
+
# 2. Apply — requires the reviewed plan report
|
|
63
|
+
memorix-associator apply \
|
|
64
|
+
--request examples/minimal-association-request.json \
|
|
65
|
+
--reviewed-report temp/plan.json
|
|
66
|
+
|
|
67
|
+
# 3. Verify associated field shapes
|
|
68
|
+
memorix-associator verify --request examples/minimal-association-request.json
|
|
69
|
+
|
|
70
|
+
# 4. Re-run plan — expect zero associatedItemsWouldAppend when converged
|
|
71
|
+
memorix-associator plan --request examples/minimal-association-request.json
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
- **Metadata-managed:** use a request whose `rules[].ruleKey` matches `refreshRuleKey` on the entity descriptor's `associatedProperties`.
|
|
75
|
+
- **Ad-hoc:** edit `examples/minimal-association-request.json` (or add your own) with source, target, and join paths.
|
|
76
|
+
- **Re-runs are safe:** apply is append-unique and idempotent; a second plan after apply should show no pending updates.
|
|
77
|
+
|
|
78
|
+
## CLI reference
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
memorix-associator plan --request <file.json> [--output <report.json>]
|
|
82
|
+
memorix-associator apply --request <file.json> --reviewed-report <report.json> [--output <report.json>]
|
|
83
|
+
memorix-associator verify --request <file.json>
|
|
84
|
+
memorix-associator --help
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## Related
|
|
88
|
+
|
|
89
|
+
- [Operational design note](../memorix-schema-api/src/operational/memorix-enrichment-processes.md)
|
|
90
|
+
- [Memorix format — associated buckets](../docs/memorix-format.md)
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { AssociatedPropertyDescriptor, AssociatedPropertyValueShape, DiscoveredAssociatedProperty, ManagedAssociatedProperty } from "../request/schema.js";
|
|
2
|
+
export declare function inferAssociatedValueShape(value: unknown): AssociatedPropertyValueShape;
|
|
3
|
+
export declare function discoverAssociatedPropertiesFromRecord(record: Record<string, unknown>, contentType: string): DiscoveredAssociatedProperty[];
|
|
4
|
+
export declare function discoverAssociatedPropertiesFromRecords(records: Array<Record<string, unknown>>, contentType: string): DiscoveredAssociatedProperty[];
|
|
5
|
+
export declare function mergeAssociatedPropertyDescriptors(input: {
|
|
6
|
+
managed: ManagedAssociatedProperty[];
|
|
7
|
+
discovered: DiscoveredAssociatedProperty[];
|
|
8
|
+
}): AssociatedPropertyDescriptor[];
|
|
9
|
+
export declare function suggestManagedMetadataFromRules(rules: Array<{
|
|
10
|
+
associatedProperty: string;
|
|
11
|
+
target: {
|
|
12
|
+
objectType: string;
|
|
13
|
+
contentType: string;
|
|
14
|
+
};
|
|
15
|
+
}>): ManagedAssociatedProperty[];
|
|
16
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/associated-properties/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,4BAA4B,EAC5B,4BAA4B,EAC5B,4BAA4B,EAC5B,yBAAyB,EAC1B,MAAM,sBAAsB,CAAC;AAG9B,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,OAAO,GAAG,4BAA4B,CAKtF;AAED,wBAAgB,sCAAsC,CACpD,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/B,WAAW,EAAE,MAAM,GAClB,4BAA4B,EAAE,CA+BhC;AAED,wBAAgB,uCAAuC,CACrD,OAAO,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,EACvC,WAAW,EAAE,MAAM,GAClB,4BAA4B,EAAE,CAgBhC;AAED,wBAAgB,kCAAkC,CAAC,KAAK,EAAE;IACxD,OAAO,EAAE,yBAAyB,EAAE,CAAC;IACrC,UAAU,EAAE,4BAA4B,EAAE,CAAC;CAC5C,GAAG,4BAA4B,EAAE,CA0CjC;AAED,wBAAgB,+BAA+B,CAC7C,KAAK,EAAE,KAAK,CAAC;IAAE,kBAAkB,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE,CAAC,GAChG,yBAAyB,EAAE,CAiB7B"}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import { isAssociatedPropertyName } from "@x12i/memorix-resolvers";
|
|
2
|
+
import { isPlainObject } from "../planning/fingerprint.js";
|
|
3
|
+
export function inferAssociatedValueShape(value) {
|
|
4
|
+
if (!Array.isArray(value))
|
|
5
|
+
return "unknown";
|
|
6
|
+
if (value.length === 0)
|
|
7
|
+
return "array<unknown>";
|
|
8
|
+
if (value.every((item) => isPlainObject(item)))
|
|
9
|
+
return "array<object>";
|
|
10
|
+
return "array<unknown>";
|
|
11
|
+
}
|
|
12
|
+
export function discoverAssociatedPropertiesFromRecord(record, contentType) {
|
|
13
|
+
if (contentType !== "snapshots")
|
|
14
|
+
return [];
|
|
15
|
+
const discovered = new Map();
|
|
16
|
+
for (const [name, value] of Object.entries(record)) {
|
|
17
|
+
if (!isAssociatedPropertyName(name))
|
|
18
|
+
continue;
|
|
19
|
+
if (value === undefined)
|
|
20
|
+
continue;
|
|
21
|
+
const existing = discovered.get(name);
|
|
22
|
+
const shape = inferAssociatedValueShape(value);
|
|
23
|
+
if (existing) {
|
|
24
|
+
existing.observedCount += 1;
|
|
25
|
+
if (existing.valueShape === "unknown" && shape !== "unknown") {
|
|
26
|
+
existing.valueShape = shape;
|
|
27
|
+
}
|
|
28
|
+
continue;
|
|
29
|
+
}
|
|
30
|
+
discovered.set(name, {
|
|
31
|
+
name,
|
|
32
|
+
contentType: "snapshots",
|
|
33
|
+
kind: "associated",
|
|
34
|
+
valueShape: shape,
|
|
35
|
+
managed: false,
|
|
36
|
+
observedPath: name,
|
|
37
|
+
observedCount: 1,
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
return [...discovered.values()].sort((a, b) => a.name.localeCompare(b.name));
|
|
41
|
+
}
|
|
42
|
+
export function discoverAssociatedPropertiesFromRecords(records, contentType) {
|
|
43
|
+
const merged = new Map();
|
|
44
|
+
for (const record of records) {
|
|
45
|
+
for (const entry of discoverAssociatedPropertiesFromRecord(record, contentType)) {
|
|
46
|
+
const existing = merged.get(entry.name);
|
|
47
|
+
if (!existing) {
|
|
48
|
+
merged.set(entry.name, { ...entry });
|
|
49
|
+
continue;
|
|
50
|
+
}
|
|
51
|
+
existing.observedCount += entry.observedCount;
|
|
52
|
+
if (existing.valueShape === "unknown" && entry.valueShape !== "unknown") {
|
|
53
|
+
existing.valueShape = entry.valueShape;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
return [...merged.values()].sort((a, b) => a.name.localeCompare(b.name));
|
|
58
|
+
}
|
|
59
|
+
export function mergeAssociatedPropertyDescriptors(input) {
|
|
60
|
+
const byName = new Map();
|
|
61
|
+
for (const entry of input.managed) {
|
|
62
|
+
byName.set(entry.name, {
|
|
63
|
+
name: entry.name,
|
|
64
|
+
contentType: entry.contentType,
|
|
65
|
+
kind: entry.kind,
|
|
66
|
+
valueShape: entry.valueShape,
|
|
67
|
+
linkedObjectType: entry.linkedObjectType,
|
|
68
|
+
linkedContentType: entry.linkedContentType,
|
|
69
|
+
description: entry.description,
|
|
70
|
+
managed: true,
|
|
71
|
+
source: "managed",
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
for (const entry of input.discovered) {
|
|
75
|
+
const existing = byName.get(entry.name);
|
|
76
|
+
if (!existing) {
|
|
77
|
+
byName.set(entry.name, {
|
|
78
|
+
name: entry.name,
|
|
79
|
+
contentType: entry.contentType,
|
|
80
|
+
kind: entry.kind,
|
|
81
|
+
valueShape: entry.valueShape,
|
|
82
|
+
managed: false,
|
|
83
|
+
source: "discovered",
|
|
84
|
+
observedPath: entry.observedPath,
|
|
85
|
+
observedCount: entry.observedCount,
|
|
86
|
+
});
|
|
87
|
+
continue;
|
|
88
|
+
}
|
|
89
|
+
existing.source = "both";
|
|
90
|
+
existing.observedPath = entry.observedPath;
|
|
91
|
+
existing.observedCount = (existing.observedCount ?? 0) + entry.observedCount;
|
|
92
|
+
if (!existing.valueShape && entry.valueShape) {
|
|
93
|
+
existing.valueShape = entry.valueShape;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
return [...byName.values()].sort((a, b) => a.name.localeCompare(b.name));
|
|
97
|
+
}
|
|
98
|
+
export function suggestManagedMetadataFromRules(rules) {
|
|
99
|
+
const suggestions = new Map();
|
|
100
|
+
for (const rule of rules) {
|
|
101
|
+
if (!isAssociatedPropertyName(rule.associatedProperty))
|
|
102
|
+
continue;
|
|
103
|
+
if (suggestions.has(rule.associatedProperty))
|
|
104
|
+
continue;
|
|
105
|
+
suggestions.set(rule.associatedProperty, {
|
|
106
|
+
name: rule.associatedProperty,
|
|
107
|
+
contentType: "snapshots",
|
|
108
|
+
kind: "associated",
|
|
109
|
+
valueShape: "array<object>",
|
|
110
|
+
linkedObjectType: rule.target.objectType,
|
|
111
|
+
linkedContentType: rule.target.contentType,
|
|
112
|
+
description: `Associated ${rule.target.objectType} ${rule.target.contentType} payloads`,
|
|
113
|
+
managed: true,
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
return [...suggestions.values()];
|
|
117
|
+
}
|
|
118
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/associated-properties/index.ts"],"names":[],"mappings":"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"}
|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { readFile, writeFile, mkdir } from "node:fs/promises";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { MongoClient } from "mongodb";
|
|
5
|
+
import { applyAssociations, planAssociations, verifyAssociations } from "./engine.js";
|
|
6
|
+
import { createMongoRecordStore } from "./store/mongo.js";
|
|
7
|
+
function parseArgs(argv) {
|
|
8
|
+
const args = argv.slice(2);
|
|
9
|
+
const has = (flag) => args.includes(flag);
|
|
10
|
+
const valueAfter = (flag) => {
|
|
11
|
+
const idx = args.indexOf(flag);
|
|
12
|
+
return idx >= 0 ? args[idx + 1] : undefined;
|
|
13
|
+
};
|
|
14
|
+
return {
|
|
15
|
+
plan: has("plan") || (!has("apply") && !has("verify")),
|
|
16
|
+
apply: has("apply"),
|
|
17
|
+
verify: has("verify"),
|
|
18
|
+
help: has("--help") || has("-h"),
|
|
19
|
+
requestPath: valueAfter("--request"),
|
|
20
|
+
reviewedReport: valueAfter("--reviewed-report"),
|
|
21
|
+
output: valueAfter("--output"),
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
function printHelp() {
|
|
25
|
+
console.log(`Usage:
|
|
26
|
+
memorix-associator plan --request <file.json> [--output <report.json>]
|
|
27
|
+
memorix-associator apply --request <file.json> --reviewed-report <report.json> [--output <report.json>]
|
|
28
|
+
memorix-associator verify --request <file.json>
|
|
29
|
+
|
|
30
|
+
See docs/running-associations.md for the full plan → review → apply → re-run workflow.`);
|
|
31
|
+
}
|
|
32
|
+
async function loadRequest(requestPath) {
|
|
33
|
+
const raw = await readFile(requestPath, "utf8");
|
|
34
|
+
return JSON.parse(raw);
|
|
35
|
+
}
|
|
36
|
+
async function main() {
|
|
37
|
+
const args = parseArgs(process.argv);
|
|
38
|
+
if (args.help || !args.requestPath) {
|
|
39
|
+
printHelp();
|
|
40
|
+
process.exit(args.help ? 0 : 1);
|
|
41
|
+
}
|
|
42
|
+
const request = await loadRequest(path.resolve(args.requestPath));
|
|
43
|
+
const mongoUri = process.env[request.connection.mongoUriEnv ?? "MONGO_URI"];
|
|
44
|
+
if (!mongoUri) {
|
|
45
|
+
throw new Error(`Mongo URI env var not set: ${request.connection.mongoUriEnv ?? "MONGO_URI"}`);
|
|
46
|
+
}
|
|
47
|
+
const client = new MongoClient(mongoUri);
|
|
48
|
+
await client.connect();
|
|
49
|
+
const store = createMongoRecordStore(client);
|
|
50
|
+
try {
|
|
51
|
+
if (args.verify) {
|
|
52
|
+
const verification = await verifyAssociations(request, { store });
|
|
53
|
+
console.log(JSON.stringify(verification, null, 2));
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
if (args.apply) {
|
|
57
|
+
const applyRequest = {
|
|
58
|
+
...request,
|
|
59
|
+
mode: "apply",
|
|
60
|
+
safety: {
|
|
61
|
+
...request.safety,
|
|
62
|
+
reviewedReportPath: args.reviewedReport ?? request.safety.reviewedReportPath,
|
|
63
|
+
},
|
|
64
|
+
};
|
|
65
|
+
const result = await applyAssociations(applyRequest, { store });
|
|
66
|
+
const outputPath = args.output ?? path.join(process.cwd(), "temp", `associator-apply-${Date.now()}.json`);
|
|
67
|
+
await mkdir(path.dirname(outputPath), { recursive: true });
|
|
68
|
+
await writeFile(outputPath, JSON.stringify(result.report, null, 2));
|
|
69
|
+
console.log(`Applied association plan. Report: ${outputPath}`);
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
const planRequest = { ...request, mode: "dry-run" };
|
|
73
|
+
const result = await planAssociations(planRequest, { store });
|
|
74
|
+
const outputPath = args.output ?? path.join(process.cwd(), "temp", `associator-plan-${Date.now()}.json`);
|
|
75
|
+
await mkdir(path.dirname(outputPath), { recursive: true });
|
|
76
|
+
await writeFile(outputPath, JSON.stringify(result.report, null, 2));
|
|
77
|
+
console.log(`Plan fingerprint: ${result.planFingerprint}`);
|
|
78
|
+
console.log(`Report: ${outputPath}`);
|
|
79
|
+
}
|
|
80
|
+
finally {
|
|
81
|
+
await client.close();
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
main().catch((error) => {
|
|
85
|
+
console.error(error instanceof Error ? error.message : error);
|
|
86
|
+
process.exit(1);
|
|
87
|
+
});
|
|
88
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|
package/dist/engine.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { type ResolverRegistry } from "@x12i/memorix-resolvers";
|
|
2
|
+
import type { AssociationApplyResult, AssociationPlanResult, AssociationReport, MemorixAssociationRequest, VerificationReport } from "./request/schema.js";
|
|
3
|
+
import type { RecordStore } from "./store/types.js";
|
|
4
|
+
export type AssociatorOptions = {
|
|
5
|
+
store: RecordStore;
|
|
6
|
+
registry?: ResolverRegistry;
|
|
7
|
+
};
|
|
8
|
+
export declare function planAssociations(request: MemorixAssociationRequest, options: AssociatorOptions): Promise<AssociationPlanResult>;
|
|
9
|
+
export declare function applyAssociations(request: MemorixAssociationRequest, options: AssociatorOptions): Promise<AssociationApplyResult>;
|
|
10
|
+
export declare function verifyAssociations(request: MemorixAssociationRequest, options: AssociatorOptions): Promise<VerificationReport>;
|
|
11
|
+
export type { AssociationReport, AssociationPlanResult, AssociationApplyResult };
|
|
12
|
+
//# sourceMappingURL=engine.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../src/engine.ts"],"names":[],"mappings":"AACA,OAAO,EAGL,KAAK,gBAAgB,EACtB,MAAM,yBAAyB,CAAC;AAEjC,OAAO,KAAK,EACV,sBAAsB,EACtB,qBAAqB,EACrB,iBAAiB,EACjB,yBAAyB,EACzB,kBAAkB,EAGnB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAGpD,MAAM,MAAM,iBAAiB,GAAG;IAC9B,KAAK,EAAE,WAAW,CAAC;IACnB,QAAQ,CAAC,EAAE,gBAAgB,CAAC;CAC7B,CAAC;AAQF,wBAAsB,gBAAgB,CACpC,OAAO,EAAE,yBAAyB,EAClC,OAAO,EAAE,iBAAiB,GACzB,OAAO,CAAC,qBAAqB,CAAC,CAuBhC;AAED,wBAAsB,iBAAiB,CACrC,OAAO,EAAE,yBAAyB,EAClC,OAAO,EAAE,iBAAiB,GACzB,OAAO,CAAC,sBAAsB,CAAC,CA2GjC;AAED,wBAAsB,kBAAkB,CACtC,OAAO,EAAE,yBAAyB,EAClC,OAAO,EAAE,iBAAiB,GACzB,OAAO,CAAC,kBAAkB,CAAC,CAY7B;AAED,YAAY,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,sBAAsB,EAAE,CAAC"}
|
package/dist/engine.js
ADDED
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { readFile } from "node:fs/promises";
|
|
2
|
+
import { builtinResolvers, createResolverRegistry, } from "@x12i/memorix-resolvers";
|
|
3
|
+
import { buildAssociationPlan } from "./planning/build-plan.js";
|
|
4
|
+
import { validateAssociationRequest } from "./request/validate.js";
|
|
5
|
+
import { verifyAssociatedShapes } from "./verification/associated-shape.js";
|
|
6
|
+
async function loadReviewedFingerprint(path) {
|
|
7
|
+
const raw = await readFile(path, "utf8");
|
|
8
|
+
const parsed = JSON.parse(raw);
|
|
9
|
+
return parsed.planFingerprint;
|
|
10
|
+
}
|
|
11
|
+
export async function planAssociations(request, options) {
|
|
12
|
+
validateAssociationRequest(request);
|
|
13
|
+
const registry = options.registry ?? createResolverRegistry(builtinResolvers);
|
|
14
|
+
const plan = await buildAssociationPlan(request, {
|
|
15
|
+
store: options.store,
|
|
16
|
+
registry,
|
|
17
|
+
apply: false,
|
|
18
|
+
});
|
|
19
|
+
if (request.safety.verifyAfterPlan) {
|
|
20
|
+
const records = [];
|
|
21
|
+
for await (const record of options.store.scanRecords(request.source.db, request.source.collection, request.source.filter, request.safety.limit)) {
|
|
22
|
+
records.push(record);
|
|
23
|
+
}
|
|
24
|
+
plan.report.verification = verifyAssociatedShapes(records);
|
|
25
|
+
}
|
|
26
|
+
return plan;
|
|
27
|
+
}
|
|
28
|
+
export async function applyAssociations(request, options) {
|
|
29
|
+
validateAssociationRequest({ ...request, mode: "apply" });
|
|
30
|
+
if (request.safety.requireReviewedReportForApply) {
|
|
31
|
+
const expected = request.safety.expectedPlanFingerprint ??
|
|
32
|
+
(request.safety.reviewedReportPath
|
|
33
|
+
? await loadReviewedFingerprint(request.safety.reviewedReportPath)
|
|
34
|
+
: undefined);
|
|
35
|
+
if (!expected) {
|
|
36
|
+
throw new Error("Reviewed plan fingerprint is required for apply");
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
const registry = options.registry ?? createResolverRegistry(builtinResolvers);
|
|
40
|
+
const plan = await buildAssociationPlan(request, {
|
|
41
|
+
store: options.store,
|
|
42
|
+
registry,
|
|
43
|
+
apply: true,
|
|
44
|
+
});
|
|
45
|
+
if (request.safety.requireReviewedReportForApply) {
|
|
46
|
+
const expected = request.safety.expectedPlanFingerprint ??
|
|
47
|
+
(request.safety.reviewedReportPath
|
|
48
|
+
? await loadReviewedFingerprint(request.safety.reviewedReportPath)
|
|
49
|
+
: undefined);
|
|
50
|
+
if (expected && expected !== plan.planFingerprint) {
|
|
51
|
+
throw new Error(`Plan fingerprint mismatch: expected ${expected}, got ${plan.planFingerprint}`);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
const backupManifest = [];
|
|
55
|
+
if (request.safety.backupBeforeApply && options.store.backupCollection) {
|
|
56
|
+
backupManifest.push(await options.store.backupCollection(request.source.db, request.source.collection));
|
|
57
|
+
}
|
|
58
|
+
const grouped = new Map();
|
|
59
|
+
for (const update of plan.updates) {
|
|
60
|
+
const key = `${update.db}/${update.collection}`;
|
|
61
|
+
const bucket = grouped.get(key) ?? [];
|
|
62
|
+
bucket.push(update);
|
|
63
|
+
grouped.set(key, bucket);
|
|
64
|
+
}
|
|
65
|
+
for (const [key, updates] of grouped.entries()) {
|
|
66
|
+
const [db, collection] = key.split("/");
|
|
67
|
+
const result = await options.store.bulkWrite(db, collection, updates.map((entry) => entry.operation));
|
|
68
|
+
if (plan.report.sourceCollections[0]) {
|
|
69
|
+
plan.report.sourceCollections[0].writeErrors += result.errors;
|
|
70
|
+
plan.report.sourceCollections[0].sourceRecordsUpdated +=
|
|
71
|
+
updates.length - result.errors;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
if (request.failurePolicy.writeFailures && plan.failures.length > 0) {
|
|
75
|
+
const failureGroups = new Map();
|
|
76
|
+
for (const failure of plan.failures) {
|
|
77
|
+
const key = `${failure.db}/${failure.collection}`;
|
|
78
|
+
const bucket = failureGroups.get(key) ?? [];
|
|
79
|
+
bucket.push(failure);
|
|
80
|
+
failureGroups.set(key, bucket);
|
|
81
|
+
}
|
|
82
|
+
for (const [key, failureEntries] of failureGroups.entries()) {
|
|
83
|
+
const [db, collection] = key.split("/");
|
|
84
|
+
await options.store.bulkWrite(db, collection, failureEntries.map((entry) => ({
|
|
85
|
+
updateOne: {
|
|
86
|
+
filter: entry.filter,
|
|
87
|
+
update: { $set: entry.record },
|
|
88
|
+
upsert: true,
|
|
89
|
+
},
|
|
90
|
+
})));
|
|
91
|
+
if (plan.report.sourceCollections[0]) {
|
|
92
|
+
plan.report.sourceCollections[0].failureRecordsWritten += failureEntries.length;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
plan.report.mode = "apply";
|
|
97
|
+
plan.report.backupManifest = backupManifest.length > 0 ? backupManifest : undefined;
|
|
98
|
+
if (request.safety.verifyAfterApply) {
|
|
99
|
+
const records = [];
|
|
100
|
+
for await (const record of options.store.scanRecords(request.source.db, request.source.collection, request.source.filter, request.safety.limit)) {
|
|
101
|
+
records.push(record);
|
|
102
|
+
}
|
|
103
|
+
plan.report.verification = verifyAssociatedShapes(records);
|
|
104
|
+
}
|
|
105
|
+
return { report: plan.report, applied: true };
|
|
106
|
+
}
|
|
107
|
+
export async function verifyAssociations(request, options) {
|
|
108
|
+
validateAssociationRequest(request);
|
|
109
|
+
const records = [];
|
|
110
|
+
for await (const record of options.store.scanRecords(request.source.db, request.source.collection, request.source.filter, request.safety.limit)) {
|
|
111
|
+
records.push(record);
|
|
112
|
+
}
|
|
113
|
+
return verifyAssociatedShapes(records);
|
|
114
|
+
}
|
|
115
|
+
//# sourceMappingURL=engine.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"engine.js","sourceRoot":"","sources":["../src/engine.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export { planAssociations, applyAssociations, verifyAssociations, type AssociatorOptions, } from "./engine.js";
|
|
2
|
+
export type { MemorixAssociationRequest, AssociationRule, AssociationReport, AssociationPlanResult, AssociationApplyResult, AssociationFailureRecord, VerificationReport, AssociatedPropertyDescriptor, AssociatedPropertySource, ManagedAssociatedProperty, DiscoveredAssociatedProperty, NormalizationStep, ResolverStepRef, } from "./request/schema.js";
|
|
3
|
+
export { validateAssociationRequest, AssociationRequestValidationError } from "./request/validate.js";
|
|
4
|
+
export { buildPlanFingerprint } from "./planning/fingerprint.js";
|
|
5
|
+
export { buildAssociationPlan } from "./planning/build-plan.js";
|
|
6
|
+
export { discoverAssociatedPropertiesFromRecord, discoverAssociatedPropertiesFromRecords, mergeAssociatedPropertyDescriptors, suggestManagedMetadataFromRules, inferAssociatedValueShape, } from "./associated-properties/index.js";
|
|
7
|
+
export { normalizeAssociatedValue, mergeAssociatedAppendUnique, buildUpdateOperation, } from "./writing/smart-merge.js";
|
|
8
|
+
export { verifyAssociatedShapes, verifyAssociatedShapeOnRecord } from "./verification/associated-shape.js";
|
|
9
|
+
export { InMemoryRecordStore, type RecordStore, type BulkWriteOperation } from "./store/types.js";
|
|
10
|
+
export { createMongoRecordStore } from "./store/mongo.js";
|
|
11
|
+
export declare const ASSOCIATED_PROPERTY_CONSUMER_GUIDANCE = "Consumers should prefer Memorix associated-property metadata when available. In the next Memorix release, associated snapshot properties are expected to be exposed through descriptors/metadata. Until that metadata is available, or when reading older/custom records, consumers should fall back to the prefix rule: root-level snapshot fields whose names start with \"associated\".\n\nThe well-known names associatedData, associatedInferred, and associatedAnalysis are conventions only. The complete set comes from Memorix metadata plus the associated* fallback rule.";
|
|
12
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,gBAAgB,EAChB,iBAAiB,EACjB,kBAAkB,EAClB,KAAK,iBAAiB,GACvB,MAAM,aAAa,CAAC;AAErB,YAAY,EACV,yBAAyB,EACzB,eAAe,EACf,iBAAiB,EACjB,qBAAqB,EACrB,sBAAsB,EACtB,wBAAwB,EACxB,kBAAkB,EAClB,4BAA4B,EAC5B,wBAAwB,EACxB,yBAAyB,EACzB,4BAA4B,EAC5B,iBAAiB,EACjB,eAAe,GAChB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EAAE,0BAA0B,EAAE,iCAAiC,EAAE,MAAM,uBAAuB,CAAC;AACtG,OAAO,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AACjE,OAAO,EAAE,oBAAoB,EAAE,MAAM,0BAA0B,CAAC;AAEhE,OAAO,EACL,sCAAsC,EACtC,uCAAuC,EACvC,kCAAkC,EAClC,+BAA+B,EAC/B,yBAAyB,GAC1B,MAAM,kCAAkC,CAAC;AAE1C,OAAO,EACL,wBAAwB,EACxB,2BAA2B,EAC3B,oBAAoB,GACrB,MAAM,0BAA0B,CAAC;AAElC,OAAO,EAAE,sBAAsB,EAAE,6BAA6B,EAAE,MAAM,oCAAoC,CAAC;AAE3G,OAAO,EAAE,mBAAmB,EAAE,KAAK,WAAW,EAAE,KAAK,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAClG,OAAO,EAAE,sBAAsB,EAAE,MAAM,kBAAkB,CAAC;AAE1D,eAAO,MAAM,qCAAqC,yjBAEqI,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export { planAssociations, applyAssociations, verifyAssociations, } from "./engine.js";
|
|
2
|
+
export { validateAssociationRequest, AssociationRequestValidationError } from "./request/validate.js";
|
|
3
|
+
export { buildPlanFingerprint } from "./planning/fingerprint.js";
|
|
4
|
+
export { buildAssociationPlan } from "./planning/build-plan.js";
|
|
5
|
+
export { discoverAssociatedPropertiesFromRecord, discoverAssociatedPropertiesFromRecords, mergeAssociatedPropertyDescriptors, suggestManagedMetadataFromRules, inferAssociatedValueShape, } from "./associated-properties/index.js";
|
|
6
|
+
export { normalizeAssociatedValue, mergeAssociatedAppendUnique, buildUpdateOperation, } from "./writing/smart-merge.js";
|
|
7
|
+
export { verifyAssociatedShapes, verifyAssociatedShapeOnRecord } from "./verification/associated-shape.js";
|
|
8
|
+
export { InMemoryRecordStore } from "./store/types.js";
|
|
9
|
+
export { createMongoRecordStore } from "./store/mongo.js";
|
|
10
|
+
export const ASSOCIATED_PROPERTY_CONSUMER_GUIDANCE = `Consumers should prefer Memorix associated-property metadata when available. In the next Memorix release, associated snapshot properties are expected to be exposed through descriptors/metadata. Until that metadata is available, or when reading older/custom records, consumers should fall back to the prefix rule: root-level snapshot fields whose names start with "associated".
|
|
11
|
+
|
|
12
|
+
The well-known names associatedData, associatedInferred, and associatedAnalysis are conventions only. The complete set comes from Memorix metadata plus the associated* fallback rule.`;
|
|
13
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,gBAAgB,EAChB,iBAAiB,EACjB,kBAAkB,GAEnB,MAAM,aAAa,CAAC;AAkBrB,OAAO,EAAE,0BAA0B,EAAE,iCAAiC,EAAE,MAAM,uBAAuB,CAAC;AACtG,OAAO,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AACjE,OAAO,EAAE,oBAAoB,EAAE,MAAM,0BAA0B,CAAC;AAEhE,OAAO,EACL,sCAAsC,EACtC,uCAAuC,EACvC,kCAAkC,EAClC,+BAA+B,EAC/B,yBAAyB,GAC1B,MAAM,kCAAkC,CAAC;AAE1C,OAAO,EACL,wBAAwB,EACxB,2BAA2B,EAC3B,oBAAoB,GACrB,MAAM,0BAA0B,CAAC;AAElC,OAAO,EAAE,sBAAsB,EAAE,6BAA6B,EAAE,MAAM,oCAAoC,CAAC;AAE3G,OAAO,EAAE,mBAAmB,EAA6C,MAAM,kBAAkB,CAAC;AAClG,OAAO,EAAE,sBAAsB,EAAE,MAAM,kBAAkB,CAAC;AAE1D,MAAM,CAAC,MAAM,qCAAqC,GAAG;;uLAEkI,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { type ResolverRegistry } from "@x12i/memorix-resolvers";
|
|
2
|
+
import type { AssociationPlanResult, MemorixAssociationRequest } from "../request/schema.js";
|
|
3
|
+
import type { RecordStore } from "../store/types.js";
|
|
4
|
+
export type BuildPlanOptions = {
|
|
5
|
+
store: RecordStore;
|
|
6
|
+
registry?: ResolverRegistry;
|
|
7
|
+
apply?: boolean;
|
|
8
|
+
};
|
|
9
|
+
export declare function buildAssociationPlan(request: MemorixAssociationRequest, options: BuildPlanOptions): Promise<AssociationPlanResult>;
|
|
10
|
+
//# sourceMappingURL=build-plan.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"build-plan.d.ts","sourceRoot":"","sources":["../../src/planning/build-plan.ts"],"names":[],"mappings":"AAAA,OAAO,EASL,KAAK,gBAAgB,EACtB,MAAM,yBAAyB,CAAC;AAEjC,OAAO,KAAK,EAEV,qBAAqB,EAGrB,yBAAyB,EAI1B,MAAM,sBAAsB,CAAC;AAC9B,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAsJrD,MAAM,MAAM,gBAAgB,GAAG;IAC7B,KAAK,EAAE,WAAW,CAAC;IACnB,QAAQ,CAAC,EAAE,gBAAgB,CAAC;IAC5B,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB,CAAC;AAEF,wBAAsB,oBAAoB,CACxC,OAAO,EAAE,yBAAyB,EAClC,OAAO,EAAE,gBAAgB,GACxB,OAAO,CAAC,qBAAqB,CAAC,CAgOhC"}
|