@x12i/memorix-pipeline 1.1.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 (62) hide show
  1. package/README.md +93 -0
  2. package/dist/association/associated-buckets.d.ts +12 -0
  3. package/dist/association/associated-buckets.d.ts.map +1 -0
  4. package/dist/association/associated-buckets.js +66 -0
  5. package/dist/association/associated-buckets.js.map +1 -0
  6. package/dist/association/association-roll-down.d.ts +33 -0
  7. package/dist/association/association-roll-down.d.ts.map +1 -0
  8. package/dist/association/association-roll-down.js +154 -0
  9. package/dist/association/association-roll-down.js.map +1 -0
  10. package/dist/graph/entity-flow-graph.d.ts +17 -0
  11. package/dist/graph/entity-flow-graph.d.ts.map +1 -0
  12. package/dist/graph/entity-flow-graph.js +79 -0
  13. package/dist/graph/entity-flow-graph.js.map +1 -0
  14. package/dist/index.d.ts +13 -0
  15. package/dist/index.d.ts.map +1 -0
  16. package/dist/index.js +13 -0
  17. package/dist/index.js.map +1 -0
  18. package/dist/lifecycle/pipeline-lifecycle.d.ts +22 -0
  19. package/dist/lifecycle/pipeline-lifecycle.d.ts.map +1 -0
  20. package/dist/lifecycle/pipeline-lifecycle.js +82 -0
  21. package/dist/lifecycle/pipeline-lifecycle.js.map +1 -0
  22. package/dist/mongo/data-access.d.ts +17 -0
  23. package/dist/mongo/data-access.d.ts.map +1 -0
  24. package/dist/mongo/data-access.js +246 -0
  25. package/dist/mongo/data-access.js.map +1 -0
  26. package/dist/narratives/narrative-sync.d.ts +31 -0
  27. package/dist/narratives/narrative-sync.d.ts.map +1 -0
  28. package/dist/narratives/narrative-sync.js +289 -0
  29. package/dist/narratives/narrative-sync.js.map +1 -0
  30. package/dist/parts-catalog/build-catalog.d.ts +12 -0
  31. package/dist/parts-catalog/build-catalog.d.ts.map +1 -0
  32. package/dist/parts-catalog/build-catalog.js +285 -0
  33. package/dist/parts-catalog/build-catalog.js.map +1 -0
  34. package/dist/parts-catalog/index.d.ts +3 -0
  35. package/dist/parts-catalog/index.d.ts.map +1 -0
  36. package/dist/parts-catalog/index.js +2 -0
  37. package/dist/parts-catalog/index.js.map +1 -0
  38. package/dist/parts-catalog/types.d.ts +80 -0
  39. package/dist/parts-catalog/types.d.ts.map +1 -0
  40. package/dist/parts-catalog/types.js +2 -0
  41. package/dist/parts-catalog/types.js.map +1 -0
  42. package/dist/pipeline-engine.d.ts +87 -0
  43. package/dist/pipeline-engine.d.ts.map +1 -0
  44. package/dist/pipeline-engine.js +210 -0
  45. package/dist/pipeline-engine.js.map +1 -0
  46. package/dist/pipeline-job-types.d.ts +14 -0
  47. package/dist/pipeline-job-types.d.ts.map +1 -0
  48. package/dist/pipeline-job-types.js +48 -0
  49. package/dist/pipeline-job-types.js.map +1 -0
  50. package/dist/pipeline-jobs.d.ts +22 -0
  51. package/dist/pipeline-jobs.d.ts.map +1 -0
  52. package/dist/pipeline-jobs.js +27 -0
  53. package/dist/pipeline-jobs.js.map +1 -0
  54. package/dist/pipeline-stages.d.ts +44 -0
  55. package/dist/pipeline-stages.d.ts.map +1 -0
  56. package/dist/pipeline-stages.js +200 -0
  57. package/dist/pipeline-stages.js.map +1 -0
  58. package/dist/pipeline-status.d.ts +66 -0
  59. package/dist/pipeline-status.d.ts.map +1 -0
  60. package/dist/pipeline-status.js +137 -0
  61. package/dist/pipeline-status.js.map +1 -0
  62. package/package.json +54 -0
package/README.md ADDED
@@ -0,0 +1,93 @@
1
+ # @x12i/memorix-pipeline
2
+
3
+ Descriptor-driven entity processing pipeline for Memorix.
4
+
5
+ ## Platform vs custom processing
6
+
7
+ | Layer | Responsibility |
8
+ |-------|----------------|
9
+ | **Platform** (`memorix-pipeline`) | Read descriptor metadata, build entity flow graph, run resolvers/insights by ID, roll associated data, stamp `_system.lifecycle` |
10
+ | **Resolvers** (`memorix-resolvers`) | Domain-specific join/normalization behind registered types |
11
+ | **Insights** (`memorix-insights`) | Staged fact resolution and judgment generation |
12
+ | **Association** | Generic roll-down driven by `processing.entityRoutes` and postfix policy |
13
+
14
+ ## Lifecycle order
15
+
16
+ 1. Run assigned resolvers on `data` (`resolution`)
17
+ 2. Run assigned insight stages (`enrichment`)
18
+ 3. Resolve parent links from entity routes (`association`)
19
+ 4. Roll parent context into `associatedData`
20
+ 5. Re-associate same-record side content by postfix
21
+ 6. Stamp route and processing metadata
22
+
23
+ ## Package API
24
+
25
+ ```ts
26
+ import {
27
+ runPipelineJob,
28
+ getPipelineRecordStatus,
29
+ listPipelineRecordsByStatus,
30
+ compilePipelineStatusFilter,
31
+ createMongoPipelineDataAccess,
32
+ } from "@x12i/memorix-pipeline";
33
+
34
+ const result = await runPipelineJob({
35
+ descriptors,
36
+ dataAccess: createMongoPipelineDataAccess({ client, descriptors }),
37
+ stages: ["resolution", "enrichment", "association"],
38
+ objectTypes: ["assets"],
39
+ dryRun: true,
40
+ rerun: false,
41
+ });
42
+ ```
43
+
44
+ ### Stages
45
+
46
+ | Stage | Job type id | Primary lifecycle |
47
+ |-------|-------------|-------------------|
48
+ | `resolution` | `entity-pipeline.resolution` | `entity-resolved` |
49
+ | `enrichment` | `entity-pipeline.enrichment` | `entity-insights-processed` |
50
+ | `association` | `entity-pipeline.association` | `entity-associated` |
51
+
52
+ Status is persisted on records under:
53
+
54
+ - `_system.processing.entityPipeline` — lifecycle + route statuses
55
+ - `_system._jobTypeRuns.<jobTypeId>` — run status (`in_progress`, `done`, `failed`)
56
+
57
+ ### Status filters
58
+
59
+ ```ts
60
+ compilePipelineStatusFilter({ stageNotDone: { stage: "resolution" } });
61
+ compilePipelineStatusFilter({ stageJobStatus: { stage: "association", status: "failed" } });
62
+ compilePipelineStatusFilter({ routeStatus: { status: "deferred" } });
63
+ ```
64
+
65
+ ## Explorer HTTP API
66
+
67
+ Routes are exposed by `@x12i/memorix-explorer-api`:
68
+
69
+ | Method | Route | Purpose |
70
+ |--------|-------|---------|
71
+ | `POST` | `/api/explorer/pipeline/run` | Run selected stages (default dry-run) |
72
+ | `POST` | `/api/explorer/pipeline/rerun` | Re-run selected stages |
73
+ | `GET` | `/api/explorer/pipeline/status?objectType=&recordId=` | Read one record's pipeline status |
74
+ | `GET` | `/api/explorer/pipeline/records?objectType=&stage=&status=` | List records filtered by status |
75
+
76
+ Apply mode requires `MEMORIX_EXPLORER_ENABLE_PIPELINE_WRITES=true` and request body `{ "apply": true }` or `{ "dryRun": false }`.
77
+
78
+ Example:
79
+
80
+ ```bash
81
+ curl -X POST http://localhost:5181/api/explorer/pipeline/run \
82
+ -H 'Content-Type: application/json' \
83
+ -d '{"stages":["resolution"],"objectTypes":["assets"],"apply":true}'
84
+ ```
85
+
86
+ ## CLI
87
+
88
+ ```bash
89
+ node memorix-pipeline/scripts/run-entity-pipeline.mjs --dry-run
90
+ node memorix-pipeline/scripts/run-entity-pipeline.mjs --apply
91
+ ```
92
+
93
+ Entity routes, resolver assignments, and insight stages are declared in object-type descriptor `processing` metadata.
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Maps a content postfix to its associated* bucket name.
3
+ * snapshots/data → associatedData; analysis → associatedAnalysis; discovery → associatedDiscovery.
4
+ */
5
+ export declare function associatedPropertyForPostfix(postfix: string): string;
6
+ export declare function isExcludedAssociationPostfix(postfix: string, excludePostfixes?: string[]): boolean;
7
+ export declare function eligibleSideContentPostfixes(contentTypes: Record<string, {
8
+ postfix?: string;
9
+ }>, excludePostfixes?: string[]): string[];
10
+ export declare function buildAssociatedPayload(sourceRecord: Record<string, unknown>, contentPostfix: string): Record<string, unknown>;
11
+ export declare function appendUniqueAssociatedItem(target: Record<string, unknown>, propertyName: string, item: Record<string, unknown>): void;
12
+ //# sourceMappingURL=associated-buckets.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"associated-buckets.d.ts","sourceRoot":"","sources":["../../src/association/associated-buckets.ts"],"names":[],"mappings":"AAUA;;;GAGG;AACH,wBAAgB,4BAA4B,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAMpE;AAED,wBAAgB,4BAA4B,CAC1C,OAAO,EAAE,MAAM,EACf,gBAAgB,GAAE,MAAM,EAAoC,GAC3D,OAAO,CAIT;AAED,wBAAgB,4BAA4B,CAC1C,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE;IAAE,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,EAClD,gBAAgB,GAAE,MAAM,EAAoC,GAC3D,MAAM,EAAE,CASV;AAED,wBAAgB,sBAAsB,CACpC,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACrC,cAAc,EAAE,MAAM,GACrB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAezB;AAED,wBAAgB,0BAA0B,CACxC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/B,YAAY,EAAE,MAAM,EACpB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC5B,IAAI,CAgBN"}
@@ -0,0 +1,66 @@
1
+ const DEFAULT_EXCLUDED_POSTFIXES = new Set(["core", "raw"]);
2
+ function pascalCase(value) {
3
+ return value
4
+ .split(/[-_]/)
5
+ .filter(Boolean)
6
+ .map((part) => part.charAt(0).toUpperCase() + part.slice(1))
7
+ .join("");
8
+ }
9
+ /**
10
+ * Maps a content postfix to its associated* bucket name.
11
+ * snapshots/data → associatedData; analysis → associatedAnalysis; discovery → associatedDiscovery.
12
+ */
13
+ export function associatedPropertyForPostfix(postfix) {
14
+ const normalized = postfix.trim().toLowerCase();
15
+ if (normalized === "snapshots" || normalized === "data") {
16
+ return "associatedData";
17
+ }
18
+ return `associated${pascalCase(normalized)}`;
19
+ }
20
+ export function isExcludedAssociationPostfix(postfix, excludePostfixes = [...DEFAULT_EXCLUDED_POSTFIXES]) {
21
+ const normalized = postfix.trim().toLowerCase();
22
+ const exclusions = new Set(excludePostfixes.map((p) => p.trim().toLowerCase()));
23
+ return exclusions.has(normalized);
24
+ }
25
+ export function eligibleSideContentPostfixes(contentTypes, excludePostfixes = [...DEFAULT_EXCLUDED_POSTFIXES]) {
26
+ const postfixes = new Set();
27
+ for (const ct of Object.values(contentTypes)) {
28
+ const postfix = (ct.postfix ?? "").trim().toLowerCase();
29
+ if (!postfix || isExcludedAssociationPostfix(postfix, excludePostfixes))
30
+ continue;
31
+ if (postfix === "snapshots")
32
+ continue;
33
+ postfixes.add(postfix);
34
+ }
35
+ return [...postfixes].sort();
36
+ }
37
+ export function buildAssociatedPayload(sourceRecord, contentPostfix) {
38
+ const bucket = contentPostfix === "snapshots" ? "data" : contentPostfix;
39
+ const payload = bucket === "data"
40
+ ? sourceRecord.data
41
+ : sourceRecord[bucket];
42
+ const item = {
43
+ ...(payload ?? {}),
44
+ contentType: contentPostfix,
45
+ };
46
+ if (typeof sourceRecord.recordId === "string") {
47
+ item.recordId = sourceRecord.recordId;
48
+ }
49
+ return item;
50
+ }
51
+ export function appendUniqueAssociatedItem(target, propertyName, item) {
52
+ const existing = target[propertyName];
53
+ const list = Array.isArray(existing) ? [...existing] : [];
54
+ const recordId = item.recordId;
55
+ if (typeof recordId === "string") {
56
+ const duplicate = list.some((entry) => entry &&
57
+ typeof entry === "object" &&
58
+ entry.recordId === recordId &&
59
+ entry.contentType === item.contentType);
60
+ if (duplicate)
61
+ return;
62
+ }
63
+ list.push(item);
64
+ target[propertyName] = list;
65
+ }
66
+ //# sourceMappingURL=associated-buckets.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"associated-buckets.js","sourceRoot":"","sources":["../../src/association/associated-buckets.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,33 @@
1
+ import type { MemorixEntityRouteDescriptor } from "@x12i/memorix-descriptors/types";
2
+ export type ParentLinkResult = {
3
+ routeKey: string;
4
+ parentObjectType: string;
5
+ linked: boolean;
6
+ status: "linked" | "unlinked" | "skipped" | "deferred" | "prerequisite-missing";
7
+ reason?: string;
8
+ parentRecordIds: string[];
9
+ };
10
+ export type AssociationRollDownResult = {
11
+ record: Record<string, unknown>;
12
+ parentLinks: ParentLinkResult[];
13
+ associatedPropertiesTouched: string[];
14
+ };
15
+ export declare function rollParentAssociatedData(childRecord: Record<string, unknown>, parentRecords: Array<Record<string, unknown>>): Record<string, unknown>;
16
+ export declare function attachSideContentFromRecord(record: Record<string, unknown>, contentTypes: Record<string, {
17
+ postfix?: string;
18
+ }>, excludePostfixes?: string[]): {
19
+ record: Record<string, unknown>;
20
+ propertiesTouched: string[];
21
+ };
22
+ export declare function applyAssociationRollDown(input: {
23
+ childRecord: Record<string, unknown>;
24
+ routes: MemorixEntityRouteDescriptor[];
25
+ parentRecordsByType: Map<string, Array<Record<string, unknown>>>;
26
+ parentSideContentByType?: Map<string, Map<string, Record<string, unknown>>>;
27
+ contentTypes: Record<string, {
28
+ postfix?: string;
29
+ }>;
30
+ rollParentSnapshots?: boolean;
31
+ excludePostfixes?: string[];
32
+ }): AssociationRollDownResult;
33
+ //# sourceMappingURL=association-roll-down.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"association-roll-down.d.ts","sourceRoot":"","sources":["../../src/association/association-roll-down.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,4BAA4B,EAE7B,MAAM,iCAAiC,CAAC;AAUzC,MAAM,MAAM,gBAAgB,GAAG;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,gBAAgB,EAAE,MAAM,CAAC;IACzB,MAAM,EAAE,OAAO,CAAC;IAChB,MAAM,EAAE,QAAQ,GAAG,UAAU,GAAG,SAAS,GAAG,UAAU,GAAG,sBAAsB,CAAC;IAChF,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,eAAe,EAAE,MAAM,EAAE,CAAC;CAC3B,CAAC;AAEF,MAAM,MAAM,yBAAyB,GAAG;IACtC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAChC,WAAW,EAAE,gBAAgB,EAAE,CAAC;IAChC,2BAA2B,EAAE,MAAM,EAAE,CAAC;CACvC,CAAC;AA+EF,wBAAgB,wBAAwB,CACtC,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACpC,aAAa,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GAC5C,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAkBzB;AAED,wBAAgB,2BAA2B,CACzC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/B,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE;IAAE,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,EAClD,gBAAgB,GAAE,MAAM,EAAoB,GAC3C;IAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAAC,iBAAiB,EAAE,MAAM,EAAE,CAAA;CAAE,CAoBlE;AAED,wBAAgB,wBAAwB,CAAC,KAAK,EAAE;IAC9C,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACrC,MAAM,EAAE,4BAA4B,EAAE,CAAC;IACvC,mBAAmB,EAAE,GAAG,CAAC,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC;IACjE,uBAAuB,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC;IAC5E,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE;QAAE,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACnD,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC;CAC7B,GAAG,yBAAyB,CAmE5B"}
@@ -0,0 +1,154 @@
1
+ import { getByPath, normalizeJoinValues } from "@x12i/memorix-resolvers";
2
+ import { appendUniqueAssociatedItem, associatedPropertyForPostfix, buildAssociatedPayload, eligibleSideContentPostfixes, } from "./associated-buckets.js";
3
+ import { hasLifecycleProcess } from "../lifecycle/pipeline-lifecycle.js";
4
+ function mapPrerequisiteAction(action) {
5
+ switch (action) {
6
+ case "skip":
7
+ return "skipped";
8
+ case "defer":
9
+ return "deferred";
10
+ case "markUnresolved":
11
+ return "prerequisite-missing";
12
+ default:
13
+ return "prerequisite-missing";
14
+ }
15
+ }
16
+ function evaluatePrerequisites(prerequisites, parentRecords, parentSideContent) {
17
+ if (!prerequisites || prerequisites.length === 0) {
18
+ return { satisfied: true, status: "linked" };
19
+ }
20
+ for (const prerequisite of prerequisites) {
21
+ if (prerequisite.lifecycleProcess) {
22
+ const hasProcess = parentRecords.some((parent) => hasLifecycleProcess(parent, prerequisite.lifecycleProcess));
23
+ if (!hasProcess) {
24
+ return {
25
+ satisfied: false,
26
+ status: mapPrerequisiteAction(prerequisite.onMissing),
27
+ reason: `Parent missing lifecycle process ${prerequisite.lifecycleProcess}`,
28
+ };
29
+ }
30
+ }
31
+ if (prerequisite.parentContentPostfix) {
32
+ const postfix = prerequisite.parentContentPostfix;
33
+ const hasContent = parentRecords.some((parent) => {
34
+ if (postfix === "snapshots" || postfix === "data")
35
+ return Boolean(parent.data);
36
+ return Boolean(parent[postfix]);
37
+ });
38
+ const fromSideMap = parentSideContent?.has(postfix);
39
+ if (!hasContent && !fromSideMap) {
40
+ return {
41
+ satisfied: false,
42
+ status: mapPrerequisiteAction(prerequisite.onMissing),
43
+ reason: `Parent missing content postfix ${postfix}`,
44
+ };
45
+ }
46
+ }
47
+ }
48
+ return { satisfied: true, status: "linked" };
49
+ }
50
+ function matchParentRecords(childRecord, route, parentRecords) {
51
+ const childValues = normalizeJoinValues(getByPath(childRecord, route.source.path));
52
+ if (childValues.length === 0)
53
+ return [];
54
+ const matches = [];
55
+ for (const parent of parentRecords) {
56
+ const parentValues = normalizeJoinValues(getByPath(parent, route.target.path));
57
+ const hit = childValues.some((childValue) => parentValues.some((parentValue) => String(childValue) === String(parentValue)));
58
+ if (hit)
59
+ matches.push(parent);
60
+ }
61
+ return matches;
62
+ }
63
+ export function rollParentAssociatedData(childRecord, parentRecords) {
64
+ const next = { ...childRecord };
65
+ for (const parent of parentRecords) {
66
+ const parentAssociated = parent.associatedData;
67
+ if (!Array.isArray(parentAssociated))
68
+ continue;
69
+ for (const item of parentAssociated) {
70
+ if (!item || typeof item !== "object")
71
+ continue;
72
+ appendUniqueAssociatedItem(next, "associatedData", {
73
+ ...item,
74
+ inheritedFrom: parent.recordId,
75
+ contentType: "snapshots",
76
+ });
77
+ }
78
+ const parentData = buildAssociatedPayload(parent, "snapshots");
79
+ appendUniqueAssociatedItem(next, "associatedData", parentData);
80
+ }
81
+ return next;
82
+ }
83
+ export function attachSideContentFromRecord(record, contentTypes, excludePostfixes = ["core", "raw"]) {
84
+ const next = { ...record };
85
+ const propertiesTouched = [];
86
+ const postfixes = eligibleSideContentPostfixes(contentTypes, excludePostfixes);
87
+ for (const postfix of postfixes) {
88
+ const propertyName = associatedPropertyForPostfix(postfix);
89
+ const payload = buildAssociatedPayload(record, postfix);
90
+ const bucket = postfix === "snapshots" ? "data" : postfix;
91
+ const hasContent = bucket === "data"
92
+ ? Boolean(record.data && typeof record.data === "object")
93
+ : Boolean(record[bucket]);
94
+ if (!hasContent)
95
+ continue;
96
+ appendUniqueAssociatedItem(next, propertyName, payload);
97
+ propertiesTouched.push(propertyName);
98
+ }
99
+ return { record: next, propertiesTouched };
100
+ }
101
+ export function applyAssociationRollDown(input) {
102
+ let record = { ...input.childRecord };
103
+ const parentLinks = [];
104
+ const associatedPropertiesTouched = [];
105
+ for (const route of input.routes) {
106
+ const parents = input.parentRecordsByType.get(route.parentObjectType) ?? [];
107
+ const matchedParents = matchParentRecords(record, route, parents);
108
+ const prerequisite = evaluatePrerequisites(route.prerequisites, matchedParents.length > 0 ? matchedParents : parents, input.parentSideContentByType?.get(route.parentObjectType));
109
+ if (!prerequisite.satisfied) {
110
+ parentLinks.push({
111
+ routeKey: route.routeKey,
112
+ parentObjectType: route.parentObjectType,
113
+ linked: false,
114
+ status: prerequisite.status,
115
+ reason: prerequisite.reason,
116
+ parentRecordIds: [],
117
+ });
118
+ continue;
119
+ }
120
+ if (matchedParents.length === 0) {
121
+ parentLinks.push({
122
+ routeKey: route.routeKey,
123
+ parentObjectType: route.parentObjectType,
124
+ linked: false,
125
+ status: "unlinked",
126
+ reason: "No parent record matched join paths",
127
+ parentRecordIds: [],
128
+ });
129
+ continue;
130
+ }
131
+ if (input.rollParentSnapshots !== false) {
132
+ record = rollParentAssociatedData(record, matchedParents);
133
+ associatedPropertiesTouched.push("associatedData");
134
+ }
135
+ parentLinks.push({
136
+ routeKey: route.routeKey,
137
+ parentObjectType: route.parentObjectType,
138
+ linked: true,
139
+ status: "linked",
140
+ parentRecordIds: matchedParents
141
+ .map((parent) => parent.recordId)
142
+ .filter((id) => typeof id === "string"),
143
+ });
144
+ }
145
+ const sideContent = attachSideContentFromRecord(record, input.contentTypes, input.excludePostfixes);
146
+ record = sideContent.record;
147
+ associatedPropertiesTouched.push(...sideContent.propertiesTouched);
148
+ return {
149
+ record,
150
+ parentLinks,
151
+ associatedPropertiesTouched: [...new Set(associatedPropertiesTouched)],
152
+ };
153
+ }
154
+ //# sourceMappingURL=association-roll-down.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"association-roll-down.js","sourceRoot":"","sources":["../../src/association/association-roll-down.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ import type { MemorixEntityDescriptor, MemorixEntityRouteDescriptor } from "@x12i/memorix-descriptors/types";
2
+ export type EntityFlowNode = {
3
+ objectType: string;
4
+ descriptor: MemorixEntityDescriptor;
5
+ depth: number;
6
+ parents: string[];
7
+ children: string[];
8
+ };
9
+ export type EntityFlowGraph = {
10
+ nodes: Map<string, EntityFlowNode>;
11
+ routes: MemorixEntityRouteDescriptor[];
12
+ processingOrder: string[];
13
+ };
14
+ export declare function buildEntityFlowGraph(descriptors: MemorixEntityDescriptor[]): EntityFlowGraph;
15
+ export declare function routesForChild(graph: EntityFlowGraph, childObjectType: string): MemorixEntityRouteDescriptor[];
16
+ export declare function routesForParentChild(graph: EntityFlowGraph, parentObjectType: string, childObjectType: string): MemorixEntityRouteDescriptor[];
17
+ //# sourceMappingURL=entity-flow-graph.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"entity-flow-graph.d.ts","sourceRoot":"","sources":["../../src/graph/entity-flow-graph.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,uBAAuB,EACvB,4BAA4B,EAC7B,MAAM,iCAAiC,CAAC;AAEzC,MAAM,MAAM,cAAc,GAAG;IAC3B,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,uBAAuB,CAAC;IACpC,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC5B,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;IACnC,MAAM,EAAE,4BAA4B,EAAE,CAAC;IACvC,eAAe,EAAE,MAAM,EAAE,CAAC;CAC3B,CAAC;AAiEF,wBAAgB,oBAAoB,CAClC,WAAW,EAAE,uBAAuB,EAAE,GACrC,eAAe,CAoBjB;AAED,wBAAgB,cAAc,CAC5B,KAAK,EAAE,eAAe,EACtB,eAAe,EAAE,MAAM,GACtB,4BAA4B,EAAE,CAIhC;AAED,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,eAAe,EACtB,gBAAgB,EAAE,MAAM,EACxB,eAAe,EAAE,MAAM,GACtB,4BAA4B,EAAE,CAMhC"}
@@ -0,0 +1,79 @@
1
+ function collectRoutes(descriptors) {
2
+ const routes = [];
3
+ for (const descriptor of descriptors) {
4
+ const entityRoutes = descriptor.processing?.entityRoutes ?? [];
5
+ for (const route of entityRoutes) {
6
+ routes.push({
7
+ ...route,
8
+ childObjectType: route.childObjectType ?? descriptor.entityName,
9
+ });
10
+ }
11
+ }
12
+ return routes;
13
+ }
14
+ function buildAdjacency(routes) {
15
+ const parents = new Map();
16
+ const children = new Map();
17
+ for (const route of routes) {
18
+ const child = route.childObjectType ?? "";
19
+ const parent = route.parentObjectType;
20
+ if (!child || !parent)
21
+ continue;
22
+ if (!parents.has(child))
23
+ parents.set(child, new Set());
24
+ parents.get(child).add(parent);
25
+ if (!children.has(parent))
26
+ children.set(parent, new Set());
27
+ children.get(parent).add(child);
28
+ }
29
+ return { parents, children };
30
+ }
31
+ function topologicalOrder(objectTypes, parents) {
32
+ const inDegree = new Map();
33
+ for (const type of objectTypes) {
34
+ inDegree.set(type, parents.get(type)?.size ?? 0);
35
+ }
36
+ const queue = objectTypes.filter((type) => (inDegree.get(type) ?? 0) === 0);
37
+ const order = [];
38
+ while (queue.length > 0) {
39
+ const current = queue.shift();
40
+ order.push(current);
41
+ for (const [child, parentSet] of parents.entries()) {
42
+ if (!parentSet.has(current))
43
+ continue;
44
+ const next = (inDegree.get(child) ?? 0) - 1;
45
+ inDegree.set(child, next);
46
+ if (next === 0)
47
+ queue.push(child);
48
+ }
49
+ }
50
+ const remaining = objectTypes.filter((type) => !order.includes(type));
51
+ return [...order, ...remaining];
52
+ }
53
+ export function buildEntityFlowGraph(descriptors) {
54
+ const descriptorByType = new Map(descriptors.map((d) => [d.entityName, d]));
55
+ const routes = collectRoutes(descriptors);
56
+ const { parents, children } = buildAdjacency(routes);
57
+ const objectTypes = [...descriptorByType.keys()];
58
+ const processingOrder = topologicalOrder(objectTypes, parents);
59
+ const nodes = new Map();
60
+ for (const objectType of objectTypes) {
61
+ const descriptor = descriptorByType.get(objectType);
62
+ nodes.set(objectType, {
63
+ objectType,
64
+ descriptor,
65
+ depth: processingOrder.indexOf(objectType),
66
+ parents: [...(parents.get(objectType) ?? [])],
67
+ children: [...(children.get(objectType) ?? [])],
68
+ });
69
+ }
70
+ return { nodes, routes, processingOrder };
71
+ }
72
+ export function routesForChild(graph, childObjectType) {
73
+ return graph.routes.filter((route) => (route.childObjectType ?? childObjectType) === childObjectType);
74
+ }
75
+ export function routesForParentChild(graph, parentObjectType, childObjectType) {
76
+ return graph.routes.filter((route) => route.parentObjectType === parentObjectType &&
77
+ (route.childObjectType ?? childObjectType) === childObjectType);
78
+ }
79
+ //# sourceMappingURL=entity-flow-graph.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"entity-flow-graph.js","sourceRoot":"","sources":["../../src/graph/entity-flow-graph.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ export { associatedPropertyForPostfix, isExcludedAssociationPostfix, eligibleSideContentPostfixes, buildAssociatedPayload, appendUniqueAssociatedItem, } from "./association/associated-buckets.js";
2
+ export { applyAssociationRollDown, rollParentAssociatedData, attachSideContentFromRecord, type ParentLinkResult, type AssociationRollDownResult, } from "./association/association-roll-down.js";
3
+ export { buildEntityFlowGraph, routesForChild, routesForParentChild, type EntityFlowGraph, type EntityFlowNode, } from "./graph/entity-flow-graph.js";
4
+ export { stampPipelineLifecycle, stampRouteStatus, readPipelineProcessingState, hasLifecycleProcess, type PipelineLifecycleProcess, type PipelineRouteStatus, type PipelineProcessingState, } from "./lifecycle/pipeline-lifecycle.js";
5
+ export { createMongoPipelineDataAccess, pipelineRecordRefToMemorixRef, type CreateMongoPipelineDataAccessOptions, } from "./mongo/data-access.js";
6
+ export { PIPELINE_STAGES, PIPELINE_JOB_TYPE_IDS, STAGE_PRIMARY_LIFECYCLE, STAGE_LIFECYCLE_PROCESSES, jobTypeIdForStage, primaryLifecycleForStage, defaultStages, type PipelineStage, } from "./pipeline-job-types.js";
7
+ export { runResolutionStage, runEnrichmentStage, runAssociationStage, runNarrativeSyncStage, type StageRunResult, } from "./pipeline-stages.js";
8
+ export { evaluateHavingNarratives, applyNarrativeSync, NARRATIVE_SYNC_DETECTED_BY, type NarrativeSyncResult, type NarrativeSyncDataAccess, } from "./narratives/narrative-sync.js";
9
+ export { compilePipelineStatusFilter, compilePipelineStatusFilters, getPipelineRecordStatus, listPipelineRecordsByStatus, type PipelineRecordListItem, type PipelineRecordStatus, type PipelineStatusFilterInput, } from "./pipeline-status.js";
10
+ export { runPipelineJob, type RunPipelineJobOptions, type RunPipelineJobResult, } from "./pipeline-jobs.js";
11
+ export { processEntityPipeline, recordIsPipelineReady, type PipelineDataAccess, type PipelineJobTypeRunHooks, type PipelineRecordRef, type PipelineRecordContext, type PipelineRunSummary, type ProcessEntityPipelineOptions, type ProcessEntityPipelineResult, type ProcessedEntityRecord, } from "./pipeline-engine.js";
12
+ export { loadPipelinePartsCatalog, catalogPartIdsForObjectType, stageReferenceMeta, defaultRepoRoot, type PipelinePart, type PipelinePartKind, type PipelinePartsCatalog, type EnrichmentPlaybook, type LoadPipelinePartsCatalogOptions, } from "./parts-catalog/index.js";
13
+ //# 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,4BAA4B,EAC5B,4BAA4B,EAC5B,4BAA4B,EAC5B,sBAAsB,EACtB,0BAA0B,GAC3B,MAAM,qCAAqC,CAAC;AAE7C,OAAO,EACL,wBAAwB,EACxB,wBAAwB,EACxB,2BAA2B,EAC3B,KAAK,gBAAgB,EACrB,KAAK,yBAAyB,GAC/B,MAAM,wCAAwC,CAAC;AAEhD,OAAO,EACL,oBAAoB,EACpB,cAAc,EACd,oBAAoB,EACpB,KAAK,eAAe,EACpB,KAAK,cAAc,GACpB,MAAM,8BAA8B,CAAC;AAEtC,OAAO,EACL,sBAAsB,EACtB,gBAAgB,EAChB,2BAA2B,EAC3B,mBAAmB,EACnB,KAAK,wBAAwB,EAC7B,KAAK,mBAAmB,EACxB,KAAK,uBAAuB,GAC7B,MAAM,mCAAmC,CAAC;AAE3C,OAAO,EACL,6BAA6B,EAC7B,6BAA6B,EAC7B,KAAK,oCAAoC,GAC1C,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EACL,eAAe,EACf,qBAAqB,EACrB,uBAAuB,EACvB,yBAAyB,EACzB,iBAAiB,EACjB,wBAAwB,EACxB,aAAa,EACb,KAAK,aAAa,GACnB,MAAM,yBAAyB,CAAC;AAEjC,OAAO,EACL,kBAAkB,EAClB,kBAAkB,EAClB,mBAAmB,EACnB,qBAAqB,EACrB,KAAK,cAAc,GACpB,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EACL,wBAAwB,EACxB,kBAAkB,EAClB,0BAA0B,EAC1B,KAAK,mBAAmB,EACxB,KAAK,uBAAuB,GAC7B,MAAM,gCAAgC,CAAC;AAExC,OAAO,EACL,2BAA2B,EAC3B,4BAA4B,EAC5B,uBAAuB,EACvB,2BAA2B,EAC3B,KAAK,sBAAsB,EAC3B,KAAK,oBAAoB,EACzB,KAAK,yBAAyB,GAC/B,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EACL,cAAc,EACd,KAAK,qBAAqB,EAC1B,KAAK,oBAAoB,GAC1B,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EACL,qBAAqB,EACrB,qBAAqB,EACrB,KAAK,kBAAkB,EACvB,KAAK,uBAAuB,EAC5B,KAAK,iBAAiB,EACtB,KAAK,qBAAqB,EAC1B,KAAK,kBAAkB,EACvB,KAAK,4BAA4B,EACjC,KAAK,2BAA2B,EAChC,KAAK,qBAAqB,GAC3B,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EACL,wBAAwB,EACxB,2BAA2B,EAC3B,kBAAkB,EAClB,eAAe,EACf,KAAK,YAAY,EACjB,KAAK,gBAAgB,EACrB,KAAK,oBAAoB,EACzB,KAAK,kBAAkB,EACvB,KAAK,+BAA+B,GACrC,MAAM,0BAA0B,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,13 @@
1
+ export { associatedPropertyForPostfix, isExcludedAssociationPostfix, eligibleSideContentPostfixes, buildAssociatedPayload, appendUniqueAssociatedItem, } from "./association/associated-buckets.js";
2
+ export { applyAssociationRollDown, rollParentAssociatedData, attachSideContentFromRecord, } from "./association/association-roll-down.js";
3
+ export { buildEntityFlowGraph, routesForChild, routesForParentChild, } from "./graph/entity-flow-graph.js";
4
+ export { stampPipelineLifecycle, stampRouteStatus, readPipelineProcessingState, hasLifecycleProcess, } from "./lifecycle/pipeline-lifecycle.js";
5
+ export { createMongoPipelineDataAccess, pipelineRecordRefToMemorixRef, } from "./mongo/data-access.js";
6
+ export { PIPELINE_STAGES, PIPELINE_JOB_TYPE_IDS, STAGE_PRIMARY_LIFECYCLE, STAGE_LIFECYCLE_PROCESSES, jobTypeIdForStage, primaryLifecycleForStage, defaultStages, } from "./pipeline-job-types.js";
7
+ export { runResolutionStage, runEnrichmentStage, runAssociationStage, runNarrativeSyncStage, } from "./pipeline-stages.js";
8
+ export { evaluateHavingNarratives, applyNarrativeSync, NARRATIVE_SYNC_DETECTED_BY, } from "./narratives/narrative-sync.js";
9
+ export { compilePipelineStatusFilter, compilePipelineStatusFilters, getPipelineRecordStatus, listPipelineRecordsByStatus, } from "./pipeline-status.js";
10
+ export { runPipelineJob, } from "./pipeline-jobs.js";
11
+ export { processEntityPipeline, recordIsPipelineReady, } from "./pipeline-engine.js";
12
+ export { loadPipelinePartsCatalog, catalogPartIdsForObjectType, stageReferenceMeta, defaultRepoRoot, } from "./parts-catalog/index.js";
13
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,4BAA4B,EAC5B,4BAA4B,EAC5B,4BAA4B,EAC5B,sBAAsB,EACtB,0BAA0B,GAC3B,MAAM,qCAAqC,CAAC;AAE7C,OAAO,EACL,wBAAwB,EACxB,wBAAwB,EACxB,2BAA2B,GAG5B,MAAM,wCAAwC,CAAC;AAEhD,OAAO,EACL,oBAAoB,EACpB,cAAc,EACd,oBAAoB,GAGrB,MAAM,8BAA8B,CAAC;AAEtC,OAAO,EACL,sBAAsB,EACtB,gBAAgB,EAChB,2BAA2B,EAC3B,mBAAmB,GAIpB,MAAM,mCAAmC,CAAC;AAE3C,OAAO,EACL,6BAA6B,EAC7B,6BAA6B,GAE9B,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EACL,eAAe,EACf,qBAAqB,EACrB,uBAAuB,EACvB,yBAAyB,EACzB,iBAAiB,EACjB,wBAAwB,EACxB,aAAa,GAEd,MAAM,yBAAyB,CAAC;AAEjC,OAAO,EACL,kBAAkB,EAClB,kBAAkB,EAClB,mBAAmB,EACnB,qBAAqB,GAEtB,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EACL,wBAAwB,EACxB,kBAAkB,EAClB,0BAA0B,GAG3B,MAAM,gCAAgC,CAAC;AAExC,OAAO,EACL,2BAA2B,EAC3B,4BAA4B,EAC5B,uBAAuB,EACvB,2BAA2B,GAI5B,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EACL,cAAc,GAGf,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EACL,qBAAqB,EACrB,qBAAqB,GAStB,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EACL,wBAAwB,EACxB,2BAA2B,EAC3B,kBAAkB,EAClB,eAAe,GAMhB,MAAM,0BAA0B,CAAC"}
@@ -0,0 +1,22 @@
1
+ export type PipelineLifecycleProcess = "entity-resolved" | "entity-insights-processed" | "entity-parent-linked" | "entity-associated" | "entity-side-content-associated" | "entity-route-unlinked" | "entity-route-skipped" | "entity-route-deferred" | "entity-prerequisite-missing" | "entity-narratives-synced";
2
+ export type PipelineRouteStatus = {
3
+ routeKey: string;
4
+ parentObjectType: string;
5
+ status: "linked" | "unlinked" | "skipped" | "deferred" | "prerequisite-missing";
6
+ reason?: string;
7
+ at: string;
8
+ };
9
+ export type PipelineProcessingState = {
10
+ lifecycle: Array<{
11
+ process: string;
12
+ processedAt: string;
13
+ }>;
14
+ routeStatuses: PipelineRouteStatus[];
15
+ lastRunAt?: string;
16
+ graphId?: string;
17
+ };
18
+ export declare function stampPipelineLifecycle(record: Record<string, unknown>, process: PipelineLifecycleProcess, processedAt?: string): Record<string, unknown>;
19
+ export declare function stampRouteStatus(record: Record<string, unknown>, status: Omit<PipelineRouteStatus, "at">, at?: string): Record<string, unknown>;
20
+ export declare function readPipelineProcessingState(record: Record<string, unknown>): PipelineProcessingState;
21
+ export declare function hasLifecycleProcess(record: Record<string, unknown>, process: string): boolean;
22
+ //# sourceMappingURL=pipeline-lifecycle.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pipeline-lifecycle.d.ts","sourceRoot":"","sources":["../../src/lifecycle/pipeline-lifecycle.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,wBAAwB,GAChC,iBAAiB,GACjB,2BAA2B,GAC3B,sBAAsB,GACtB,mBAAmB,GACnB,gCAAgC,GAChC,uBAAuB,GACvB,sBAAsB,GACtB,uBAAuB,GACvB,6BAA6B,GAC7B,0BAA0B,CAAC;AAE/B,MAAM,MAAM,mBAAmB,GAAG;IAChC,QAAQ,EAAE,MAAM,CAAC;IACjB,gBAAgB,EAAE,MAAM,CAAC;IACzB,MAAM,EAAE,QAAQ,GAAG,UAAU,GAAG,SAAS,GAAG,UAAU,GAAG,sBAAsB,CAAC;IAChF,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,EAAE,EAAE,MAAM,CAAC;CACZ,CAAC;AAEF,MAAM,MAAM,uBAAuB,GAAG;IACpC,SAAS,EAAE,KAAK,CAAC;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC3D,aAAa,EAAE,mBAAmB,EAAE,CAAC;IACrC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AA4BF,wBAAgB,sBAAsB,CACpC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/B,OAAO,EAAE,wBAAwB,EACjC,WAAW,GAAE,MAAiC,GAC7C,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CA4BzB;AAED,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/B,MAAM,EAAE,IAAI,CAAC,mBAAmB,EAAE,IAAI,CAAC,EACvC,EAAE,GAAE,MAAiC,GACpC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAwBzB;AAED,wBAAgB,2BAA2B,CACzC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC9B,uBAAuB,CAEzB;AAED,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/B,OAAO,EAAE,MAAM,GACd,OAAO,CAUT"}