@x12i/memorix-service 3.12.4 → 3.13.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 +1 -1
- package/dist/anomaly/catalog.d.ts +4 -0
- package/dist/anomaly/catalog.d.ts.map +1 -0
- package/dist/anomaly/catalog.js +315 -0
- package/dist/anomaly/catalog.js.map +1 -0
- package/dist/anomaly/descriptors.d.ts +11 -0
- package/dist/anomaly/descriptors.d.ts.map +1 -0
- package/dist/anomaly/descriptors.js +113 -0
- package/dist/anomaly/descriptors.js.map +1 -0
- package/dist/anomaly/index.d.ts +6 -0
- package/dist/anomaly/index.d.ts.map +1 -0
- package/dist/anomaly/index.js +5 -0
- package/dist/anomaly/index.js.map +1 -0
- package/dist/anomaly/records.d.ts +28 -0
- package/dist/anomaly/records.d.ts.map +1 -0
- package/dist/anomaly/records.js +384 -0
- package/dist/anomaly/records.js.map +1 -0
- package/dist/anomaly/types.d.ts +116 -0
- package/dist/anomaly/types.d.ts.map +1 -0
- package/dist/anomaly/types.js +24 -0
- package/dist/anomaly/types.js.map +1 -0
- package/dist/anomaly/values.d.ts +31 -0
- package/dist/anomaly/values.d.ts.map +1 -0
- package/dist/anomaly/values.js +171 -0
- package/dist/anomaly/values.js.map +1 -0
- package/dist/app.d.ts.map +1 -1
- package/dist/app.js +12 -0
- package/dist/app.js.map +1 -1
- package/dist/catalog-bridge.d.ts +18 -0
- package/dist/catalog-bridge.d.ts.map +1 -1
- package/dist/catalog-bridge.js +85 -0
- package/dist/catalog-bridge.js.map +1 -1
- package/dist/errors.d.ts +5 -0
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +18 -0
- package/dist/errors.js.map +1 -1
- package/dist/knowledge-upstream.d.ts +32 -0
- package/dist/knowledge-upstream.d.ts.map +1 -1
- package/dist/knowledge-upstream.js +86 -2
- package/dist/knowledge-upstream.js.map +1 -1
- package/dist/mcp/nexum-tools.d.ts +1 -1
- package/dist/mcp/nexum-tools.d.ts.map +1 -1
- package/dist/mcp/nexum-tools.js +39 -22
- package/dist/mcp/nexum-tools.js.map +1 -1
- package/dist/nexum-analysis/enqueue.d.ts.map +1 -1
- package/dist/nexum-analysis/enqueue.js +2 -1
- package/dist/nexum-analysis/enqueue.js.map +1 -1
- package/dist/nexum-analysis/knowledge-read.d.ts +45 -0
- package/dist/nexum-analysis/knowledge-read.d.ts.map +1 -0
- package/dist/nexum-analysis/knowledge-read.js +26 -0
- package/dist/nexum-analysis/knowledge-read.js.map +1 -0
- package/dist/openapi/openapi.json +18354 -17718
- package/dist/patches/access.d.ts +15 -0
- package/dist/patches/access.d.ts.map +1 -0
- package/dist/patches/access.js +27 -0
- package/dist/patches/access.js.map +1 -0
- package/dist/patches/engine.d.ts +67 -0
- package/dist/patches/engine.d.ts.map +1 -0
- package/dist/patches/engine.js +966 -0
- package/dist/patches/engine.js.map +1 -0
- package/dist/patches/guards.d.ts +23 -0
- package/dist/patches/guards.d.ts.map +1 -0
- package/dist/patches/guards.js +77 -0
- package/dist/patches/guards.js.map +1 -0
- package/dist/patches/legacy-rows.d.ts +56 -0
- package/dist/patches/legacy-rows.d.ts.map +1 -0
- package/dist/patches/legacy-rows.js +162 -0
- package/dist/patches/legacy-rows.js.map +1 -0
- package/dist/patches/ops.d.ts +24 -0
- package/dist/patches/ops.d.ts.map +1 -0
- package/dist/patches/ops.js +204 -0
- package/dist/patches/ops.js.map +1 -0
- package/dist/patches/parse.d.ts +5 -0
- package/dist/patches/parse.d.ts.map +1 -0
- package/dist/patches/parse.js +323 -0
- package/dist/patches/parse.js.map +1 -0
- package/dist/patches/paths.d.ts +38 -0
- package/dist/patches/paths.d.ts.map +1 -0
- package/dist/patches/paths.js +204 -0
- package/dist/patches/paths.js.map +1 -0
- package/dist/patches/service.d.ts +16 -0
- package/dist/patches/service.d.ts.map +1 -0
- package/dist/patches/service.js +128 -0
- package/dist/patches/service.js.map +1 -0
- package/dist/patches/store.d.ts +87 -0
- package/dist/patches/store.d.ts.map +1 -0
- package/dist/patches/store.js +27 -0
- package/dist/patches/store.js.map +1 -0
- package/dist/patches/types.d.ts +112 -0
- package/dist/patches/types.d.ts.map +1 -0
- package/dist/patches/types.js +5 -0
- package/dist/patches/types.js.map +1 -0
- package/dist/platform.d.ts +8 -0
- package/dist/platform.d.ts.map +1 -1
- package/dist/platform.js +98 -4
- package/dist/platform.js.map +1 -1
- package/dist/routes/anomaly.d.ts +5 -0
- package/dist/routes/anomaly.d.ts.map +1 -0
- package/dist/routes/anomaly.js +308 -0
- package/dist/routes/anomaly.js.map +1 -0
- package/dist/routes/data.d.ts.map +1 -1
- package/dist/routes/data.js +190 -202
- package/dist/routes/data.js.map +1 -1
- package/dist/routes/knowledge.d.ts.map +1 -1
- package/dist/routes/knowledge.js +6 -22
- package/dist/routes/knowledge.js.map +1 -1
- package/dist/routes/metadata.d.ts.map +1 -1
- package/dist/routes/metadata.js +28 -1
- package/dist/routes/metadata.js.map +1 -1
- package/dist/routes/patches.d.ts +7 -0
- package/dist/routes/patches.d.ts.map +1 -0
- package/dist/routes/patches.js +111 -0
- package/dist/routes/patches.js.map +1 -0
- package/dist/routes/subject-roots-backfill.d.ts +4 -0
- package/dist/routes/subject-roots-backfill.d.ts.map +1 -0
- package/dist/routes/subject-roots-backfill.js +15 -0
- package/dist/routes/subject-roots-backfill.js.map +1 -0
- package/dist/single-read-discriminator.d.ts +17 -0
- package/dist/single-read-discriminator.d.ts.map +1 -0
- package/dist/single-read-discriminator.js +67 -0
- package/dist/single-read-discriminator.js.map +1 -0
- package/dist/subject-roots-backfill.d.ts +24 -0
- package/dist/subject-roots-backfill.d.ts.map +1 -0
- package/dist/subject-roots-backfill.js +133 -0
- package/dist/subject-roots-backfill.js.map +1 -0
- package/dist/write-precondition.d.ts +5 -1
- package/dist/write-precondition.d.ts.map +1 -1
- package/dist/write-precondition.js +11 -3
- package/dist/write-precondition.js.map +1 -1
- package/dist/writes/content-write.d.ts +170 -0
- package/dist/writes/content-write.d.ts.map +1 -0
- package/dist/writes/content-write.js +569 -0
- package/dist/writes/content-write.js.map +1 -0
- package/dist/writes/effects.d.ts +13 -0
- package/dist/writes/effects.d.ts.map +1 -0
- package/dist/writes/effects.js +28 -0
- package/dist/writes/effects.js.map +1 -0
- package/dist/writes/error-shape.d.ts +11 -0
- package/dist/writes/error-shape.d.ts.map +1 -0
- package/dist/writes/error-shape.js +100 -0
- package/dist/writes/error-shape.js.map +1 -0
- package/dist/writes/receipt-store.d.ts +81 -0
- package/dist/writes/receipt-store.d.ts.map +1 -0
- package/dist/writes/receipt-store.js +171 -0
- package/dist/writes/receipt-store.js.map +1 -0
- package/dist/writes/worker.d.ts +9 -0
- package/dist/writes/worker.d.ts.map +1 -0
- package/dist/writes/worker.js +20 -0
- package/dist/writes/worker.js.map +1 -0
- package/openapi/openapi.json +18354 -17718
- package/package.json +4 -4
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Discriminator selection for single-record reads (`recordId` set) on
|
|
3
|
+
* GET /api/data/content and GET /api/data/content/context.
|
|
4
|
+
*/
|
|
5
|
+
import { ServiceError } from "./errors.js";
|
|
6
|
+
/**
|
|
7
|
+
* The value that picks one instance of a discriminated content type.
|
|
8
|
+
* `filter` may only carry an `eq` on the discriminator path; any other filter
|
|
9
|
+
* with `recordId` is READ_QUERY_INVALID instead of being dropped.
|
|
10
|
+
*/
|
|
11
|
+
export function singleReadDiscriminatorValue(args) {
|
|
12
|
+
const explicit = args.discriminatorValue?.trim() || undefined;
|
|
13
|
+
if (!args.filters?.length)
|
|
14
|
+
return explicit;
|
|
15
|
+
const path = args.discriminatorPath;
|
|
16
|
+
const fromFilter = new Set();
|
|
17
|
+
const unused = [];
|
|
18
|
+
for (const f of args.filters) {
|
|
19
|
+
if (path && f.field === path && f.op === "eq" && typeof f.value === "string" && f.value.trim()) {
|
|
20
|
+
fromFilter.add(f.value.trim());
|
|
21
|
+
}
|
|
22
|
+
else {
|
|
23
|
+
unused.push(f);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
if (unused.length) {
|
|
27
|
+
throw new ServiceError("READ_QUERY_INVALID", path
|
|
28
|
+
? `filter is not allowed with recordId. Only an eq filter on the discriminator ${path} is read; pass discriminatorValue to pick the instance.`
|
|
29
|
+
: "filter is not allowed with recordId. This content type has no discriminator; drop filter or omit recordId to list.", 400, {
|
|
30
|
+
field: "filter",
|
|
31
|
+
parameter: "filter",
|
|
32
|
+
unused,
|
|
33
|
+
...(path ? { discriminatorPath: path } : {}),
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
if (fromFilter.size > 1) {
|
|
37
|
+
throw new ServiceError("READ_QUERY_INVALID", `filter names more than one value for ${path}; a single-record read picks one instance.`, 400, { field: "filter", parameter: "filter", discriminatorPath: path, values: [...fromFilter] });
|
|
38
|
+
}
|
|
39
|
+
const [filtered] = [...fromFilter];
|
|
40
|
+
if (explicit && filtered && explicit !== filtered) {
|
|
41
|
+
throw new ServiceError("READ_QUERY_INVALID", `discriminatorValue '${explicit}' and the filter on ${path} ('${filtered}') disagree.`, 400, { field: "discriminatorValue", parameter: "discriminatorValue", discriminatorPath: path });
|
|
42
|
+
}
|
|
43
|
+
return explicit ?? filtered;
|
|
44
|
+
}
|
|
45
|
+
function errorCode(err) {
|
|
46
|
+
return err && typeof err === "object" && typeof err.code === "string"
|
|
47
|
+
? err.code
|
|
48
|
+
: "";
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* READ_DISCRIMINATOR_REQUIRED names the query parameter that supplies the value
|
|
52
|
+
* and, when the pack declares them, the values it accepts.
|
|
53
|
+
*/
|
|
54
|
+
export function withDiscriminatorHelp(err, allowedValues) {
|
|
55
|
+
if (errorCode(err) !== "READ_DISCRIMINATOR_REQUIRED")
|
|
56
|
+
return err;
|
|
57
|
+
const raw = err.details;
|
|
58
|
+
const details = raw && typeof raw === "object" && !Array.isArray(raw) ? { ...raw } : {};
|
|
59
|
+
const declared = Array.isArray(details.allowedValues) ? undefined : allowedValues();
|
|
60
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
61
|
+
return new ServiceError("READ_DISCRIMINATOR_REQUIRED", `${message}. Pass discriminatorValue in the query string to pick the instance.`, 400, {
|
|
62
|
+
...details,
|
|
63
|
+
parameter: "discriminatorValue",
|
|
64
|
+
...(declared ? { allowedValues: declared } : {}),
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=single-read-discriminator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"single-read-discriminator.js","sourceRoot":"","sources":["../src/single-read-discriminator.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Move estate scope onto `_metadata`, context payloads onto `context`,
|
|
3
|
+
* and noise out of subject `data`.
|
|
4
|
+
* Does not patch security-map rows. Does not change revision or `_system.modifiedAt`.
|
|
5
|
+
*/
|
|
6
|
+
import type { MongoClient } from "mongodb";
|
|
7
|
+
export type SubjectRootsBackfillRequest = {
|
|
8
|
+
confirm: true;
|
|
9
|
+
dryRun: boolean;
|
|
10
|
+
includeHistory: false;
|
|
11
|
+
};
|
|
12
|
+
export type SubjectRootsBackfillResult = {
|
|
13
|
+
dryRun: boolean;
|
|
14
|
+
scanned: number;
|
|
15
|
+
wouldPatch: number;
|
|
16
|
+
unchanged: number;
|
|
17
|
+
skippedSecurityMap: number;
|
|
18
|
+
skippedInvalid: number;
|
|
19
|
+
};
|
|
20
|
+
export declare function parseSubjectRootsBackfillRequest(body: unknown): SubjectRootsBackfillRequest;
|
|
21
|
+
export declare function runSubjectRootsBackfill(client: MongoClient, request: SubjectRootsBackfillRequest, now: string, options?: {
|
|
22
|
+
onlyOrgIds?: string[];
|
|
23
|
+
}): Promise<SubjectRootsBackfillResult>;
|
|
24
|
+
//# sourceMappingURL=subject-roots-backfill.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"subject-roots-backfill.d.ts","sourceRoot":"","sources":["../src/subject-roots-backfill.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAc3C,MAAM,MAAM,2BAA2B,GAAG;IACxC,OAAO,EAAE,IAAI,CAAC;IACd,MAAM,EAAE,OAAO,CAAC;IAChB,cAAc,EAAE,KAAK,CAAC;CACvB,CAAC;AAEF,MAAM,MAAM,0BAA0B,GAAG;IACvC,MAAM,EAAE,OAAO,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,cAAc,EAAE,MAAM,CAAC;CACxB,CAAC;AAwBF,wBAAgB,gCAAgC,CAAC,IAAI,EAAE,OAAO,GAAG,2BAA2B,CAgB3F;AAED,wBAAsB,uBAAuB,CAC3C,MAAM,EAAE,WAAW,EACnB,OAAO,EAAE,2BAA2B,EACpC,GAAG,EAAE,MAAM,EACX,OAAO,CAAC,EAAE;IAAE,UAAU,CAAC,EAAE,MAAM,EAAE,CAAA;CAAE,GAClC,OAAO,CAAC,0BAA0B,CAAC,CAuErC"}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import { jsonMarkdown, relocateStoredSubject } from "@x12i/memorix-data";
|
|
2
|
+
import { ServiceError } from "./errors.js";
|
|
3
|
+
import { resolveObjectAndContentType } from "./data-changes.js";
|
|
4
|
+
import { normalizeOrgId } from "./scope.js";
|
|
5
|
+
const CATEGORY_SUFFIXES = ["entity", "event", "knowledge"];
|
|
6
|
+
const RESERVED_COLLECTIONS = new Set([
|
|
7
|
+
"relationships",
|
|
8
|
+
"record-directory",
|
|
9
|
+
"system.profile",
|
|
10
|
+
]);
|
|
11
|
+
function isContentCollectionName(name) {
|
|
12
|
+
if (!name || RESERVED_COLLECTIONS.has(name))
|
|
13
|
+
return false;
|
|
14
|
+
if (name.startsWith("system."))
|
|
15
|
+
return false;
|
|
16
|
+
if (name.includes("_"))
|
|
17
|
+
return false;
|
|
18
|
+
if (!name.includes("-"))
|
|
19
|
+
return false;
|
|
20
|
+
return /^[a-z][a-z0-9-]*$/.test(name);
|
|
21
|
+
}
|
|
22
|
+
function orgFromDatabase(name) {
|
|
23
|
+
for (const kind of CATEGORY_SUFFIXES) {
|
|
24
|
+
const suffix = `-memorix-${kind}`;
|
|
25
|
+
if (!name.endsWith(suffix))
|
|
26
|
+
continue;
|
|
27
|
+
const orgId = name.slice(0, -suffix.length);
|
|
28
|
+
return orgId || null;
|
|
29
|
+
}
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
function isPlainObject(value) {
|
|
33
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
34
|
+
}
|
|
35
|
+
export function parseSubjectRootsBackfillRequest(body) {
|
|
36
|
+
if (!body || typeof body !== "object" || Array.isArray(body)) {
|
|
37
|
+
throw new ServiceError("VALIDATION", "backfill body must be an object", 400);
|
|
38
|
+
}
|
|
39
|
+
const raw = body;
|
|
40
|
+
if (raw.confirm !== true) {
|
|
41
|
+
throw new ServiceError("VALIDATION", "confirm: true is required", 400);
|
|
42
|
+
}
|
|
43
|
+
if (raw.includeHistory === true) {
|
|
44
|
+
throw new ServiceError("VALIDATION", "includeHistory must be false; only the current head is patched", 400);
|
|
45
|
+
}
|
|
46
|
+
return { confirm: true, dryRun: raw.dryRun !== false, includeHistory: false };
|
|
47
|
+
}
|
|
48
|
+
export async function runSubjectRootsBackfill(client, request, now, options) {
|
|
49
|
+
const result = {
|
|
50
|
+
dryRun: request.dryRun,
|
|
51
|
+
scanned: 0,
|
|
52
|
+
wouldPatch: 0,
|
|
53
|
+
unchanged: 0,
|
|
54
|
+
skippedSecurityMap: 0,
|
|
55
|
+
skippedInvalid: 0,
|
|
56
|
+
};
|
|
57
|
+
const listed = await client.db().admin().listDatabases();
|
|
58
|
+
for (const entry of listed.databases ?? []) {
|
|
59
|
+
const databaseName = String(entry.name ?? "");
|
|
60
|
+
const orgId = orgFromDatabase(databaseName);
|
|
61
|
+
if (!orgId)
|
|
62
|
+
continue;
|
|
63
|
+
if (options?.onlyOrgIds &&
|
|
64
|
+
!options.onlyOrgIds.some((id) => normalizeOrgId(id) === normalizeOrgId(orgId))) {
|
|
65
|
+
continue;
|
|
66
|
+
}
|
|
67
|
+
const objectTypes = await objectTypesFor(client, orgId);
|
|
68
|
+
const collections = await client.db(databaseName).listCollections().toArray();
|
|
69
|
+
for (const collection of collections) {
|
|
70
|
+
const collectionName = String(collection.name ?? "");
|
|
71
|
+
if (!isContentCollectionName(collectionName))
|
|
72
|
+
continue;
|
|
73
|
+
const fromName = resolveObjectAndContentType(collectionName, objectTypes);
|
|
74
|
+
const coll = client.db(databaseName).collection(collectionName);
|
|
75
|
+
const cursor = coll.find({});
|
|
76
|
+
for await (const doc of cursor) {
|
|
77
|
+
result.scanned += 1;
|
|
78
|
+
const record = doc;
|
|
79
|
+
if (!isPlainObject(record.data)) {
|
|
80
|
+
result.skippedInvalid += 1;
|
|
81
|
+
continue;
|
|
82
|
+
}
|
|
83
|
+
const objectType = typeof record.objectType === "string" ? record.objectType : fromName.objectType;
|
|
84
|
+
const contentType = typeof record.contentType === "string" ? record.contentType : fromName.contentType;
|
|
85
|
+
const relocated = relocateStoredSubject({
|
|
86
|
+
objectType,
|
|
87
|
+
contentType,
|
|
88
|
+
data: record.data,
|
|
89
|
+
metadata: isPlainObject(record._metadata) ? record._metadata : undefined,
|
|
90
|
+
context: isPlainObject(record.context) ? record.context : undefined,
|
|
91
|
+
});
|
|
92
|
+
if (relocated.skipped === "security-map") {
|
|
93
|
+
result.skippedSecurityMap += 1;
|
|
94
|
+
continue;
|
|
95
|
+
}
|
|
96
|
+
if (!relocated.changed) {
|
|
97
|
+
result.unchanged += 1;
|
|
98
|
+
continue;
|
|
99
|
+
}
|
|
100
|
+
result.wouldPatch += 1;
|
|
101
|
+
if (request.dryRun)
|
|
102
|
+
continue;
|
|
103
|
+
const $set = { data: relocated.data };
|
|
104
|
+
if (relocated.metadata)
|
|
105
|
+
$set._metadata = relocated.metadata;
|
|
106
|
+
if (relocated.context)
|
|
107
|
+
$set.context = relocated.context;
|
|
108
|
+
if (relocated.dataChanged) {
|
|
109
|
+
const markdown = record._markdown;
|
|
110
|
+
const source = isPlainObject(markdown) ? markdown.source : undefined;
|
|
111
|
+
if (source === undefined || source === "json") {
|
|
112
|
+
$set._markdown = jsonMarkdown(relocated.data, now);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
await coll.updateOne({ _id: String(record._id) }, { $set });
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
return result;
|
|
120
|
+
}
|
|
121
|
+
async function objectTypesFor(client, orgId) {
|
|
122
|
+
try {
|
|
123
|
+
const types = await client
|
|
124
|
+
.db(`${orgId}-memorix-operational`)
|
|
125
|
+
.collection("record-directory")
|
|
126
|
+
.distinct("objectType");
|
|
127
|
+
return types.map((type) => String(type)).filter((type) => type.length > 0);
|
|
128
|
+
}
|
|
129
|
+
catch {
|
|
130
|
+
return [];
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
//# sourceMappingURL=subject-roots-backfill.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"subject-roots-backfill.js","sourceRoot":"","sources":["../src/subject-roots-backfill.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,11 +1,15 @@
|
|
|
1
|
-
export type WireWritePrecondition = "absent" | "exact-revision" | {
|
|
1
|
+
export type WireWritePrecondition = "absent" | "exact-revision" | "none" | {
|
|
2
2
|
kind: "absent";
|
|
3
|
+
} | {
|
|
4
|
+
kind: "none";
|
|
3
5
|
} | {
|
|
4
6
|
kind: "revision";
|
|
5
7
|
revision: number;
|
|
6
8
|
};
|
|
7
9
|
export type NormalizedWritePrecondition = {
|
|
8
10
|
form: "absent";
|
|
11
|
+
} | {
|
|
12
|
+
form: "none";
|
|
9
13
|
} | {
|
|
10
14
|
form: "exact-revision";
|
|
11
15
|
expectedRevision: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"write-precondition.d.ts","sourceRoot":"","sources":["../src/write-precondition.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"write-precondition.d.ts","sourceRoot":"","sources":["../src/write-precondition.ts"],"names":[],"mappings":"AAWA,MAAM,MAAM,qBAAqB,GAC7B,QAAQ,GACR,gBAAgB,GAChB,MAAM,GACN;IAAE,IAAI,EAAE,QAAQ,CAAA;CAAE,GAClB;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,GAChB;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC;AAE3C,MAAM,MAAM,2BAA2B,GACnC;IAAE,IAAI,EAAE,QAAQ,CAAA;CAAE,GAClB;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,GAChB;IAAE,IAAI,EAAE,gBAAgB,CAAC;IAAC,gBAAgB,EAAE,MAAM,CAAA;CAAE,CAAC;AAEzD,wBAAgB,0BAA0B,CACxC,GAAG,EAAE,OAAO,EACZ,gBAAgB,CAAC,EAAE,OAAO,GACzB,2BAA2B,CAmD7B"}
|
|
@@ -1,15 +1,20 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Normalize POST /api/data/content write preconditions.
|
|
3
3
|
*
|
|
4
|
-
* Canonical wire form is string `"absent" | "exact-revision"` (+ `expectedRevision`
|
|
5
|
-
*
|
|
4
|
+
* Canonical wire form is string `"absent" | "exact-revision" | "none"` (+ `expectedRevision`
|
|
5
|
+
* when the precondition is exact-revision).
|
|
6
|
+
* Also accept the writer-native object form `{ kind: "absent" | "none" }` /
|
|
6
7
|
* `{ kind: "revision", revision }` so clients do not silently fall through to create.
|
|
8
|
+
* `none` creates a missing row and replaces an existing row.
|
|
7
9
|
*/
|
|
8
10
|
import { ServiceError } from "./errors.js";
|
|
9
11
|
export function normalizeWritePrecondition(raw, expectedRevision) {
|
|
10
12
|
if (raw === "absent") {
|
|
11
13
|
return { form: "absent" };
|
|
12
14
|
}
|
|
15
|
+
if (raw === "none") {
|
|
16
|
+
return { form: "none" };
|
|
17
|
+
}
|
|
13
18
|
if (raw === "exact-revision") {
|
|
14
19
|
if (expectedRevision === undefined || expectedRevision === null || expectedRevision === "") {
|
|
15
20
|
throw new ServiceError("VALIDATION", "expectedRevision required when precondition is exact-revision", 400);
|
|
@@ -25,6 +30,9 @@ export function normalizeWritePrecondition(raw, expectedRevision) {
|
|
|
25
30
|
if (kind === "absent") {
|
|
26
31
|
return { form: "absent" };
|
|
27
32
|
}
|
|
33
|
+
if (kind === "none") {
|
|
34
|
+
return { form: "none" };
|
|
35
|
+
}
|
|
28
36
|
if (kind === "revision") {
|
|
29
37
|
const fromBody = raw.revision;
|
|
30
38
|
const revision = Number(fromBody !== undefined && fromBody !== null && fromBody !== ""
|
|
@@ -36,6 +44,6 @@ export function normalizeWritePrecondition(raw, expectedRevision) {
|
|
|
36
44
|
return { form: "exact-revision", expectedRevision: revision };
|
|
37
45
|
}
|
|
38
46
|
}
|
|
39
|
-
throw new ServiceError("VALIDATION", 'precondition required: "absent" | "exact-revision" | { kind: "absent" } | { kind: "revision", revision }', 400);
|
|
47
|
+
throw new ServiceError("VALIDATION", 'precondition required: "absent" | "exact-revision" | "none" | { kind: "absent" } | { kind: "none" } | { kind: "revision", revision }', 400);
|
|
40
48
|
}
|
|
41
49
|
//# sourceMappingURL=write-precondition.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"write-precondition.js","sourceRoot":"","sources":["../src/write-precondition.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"write-precondition.js","sourceRoot":"","sources":["../src/write-precondition.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAe3C,MAAM,UAAU,0BAA0B,CACxC,GAAY,EACZ,gBAA0B;IAE1B,IAAI,GAAG,KAAK,QAAQ,EAAE,CAAC;QACrB,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;IAC5B,CAAC;IACD,IAAI,GAAG,KAAK,MAAM,EAAE,CAAC;QACnB,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;IAC1B,CAAC;IACD,IAAI,GAAG,KAAK,gBAAgB,EAAE,CAAC;QAC7B,IAAI,gBAAgB,KAAK,SAAS,IAAI,gBAAgB,KAAK,IAAI,IAAI,gBAAgB,KAAK,EAAE,EAAE,CAAC;YAC3F,MAAM,IAAI,YAAY,CACpB,YAAY,EACZ,+DAA+D,EAC/D,GAAG,CACJ,CAAC;QACJ,CAAC;QACD,MAAM,QAAQ,GAAG,MAAM,CAAC,gBAAgB,CAAC,CAAC;QAC1C,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC/B,MAAM,IAAI,YAAY,CAAC,YAAY,EAAE,mCAAmC,EAAE,GAAG,CAAC,CAAC;QACjF,CAAC;QACD,OAAO,EAAE,IAAI,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,QAAQ,EAAE,CAAC;IAChE,CAAC;IACD,IAAI,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;QAC1D,MAAM,IAAI,GAAI,GAA0B,CAAC,IAAI,CAAC;QAC9C,IAAI,IAAI,KAAK,QAAQ,EAAE,CAAC;YACtB,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;QAC5B,CAAC;QACD,IAAI,IAAI,KAAK,MAAM,EAAE,CAAC;YACpB,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;QAC1B,CAAC;QACD,IAAI,IAAI,KAAK,UAAU,EAAE,CAAC;YACxB,MAAM,QAAQ,GAAI,GAA8B,CAAC,QAAQ,CAAC;YAC1D,MAAM,QAAQ,GAAG,MAAM,CACrB,QAAQ,KAAK,SAAS,IAAI,QAAQ,KAAK,IAAI,IAAI,QAAQ,KAAK,EAAE;gBAC5D,CAAC,CAAC,QAAQ;gBACV,CAAC,CAAC,gBAAgB,CACrB,CAAC;YACF,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;gBAC/B,MAAM,IAAI,YAAY,CACpB,YAAY,EACZ,4EAA4E,EAC5E,GAAG,CACJ,CAAC;YACJ,CAAC;YACD,OAAO,EAAE,IAAI,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,QAAQ,EAAE,CAAC;QAChE,CAAC;IACH,CAAC;IACD,MAAM,IAAI,YAAY,CACpB,YAAY,EACZ,sIAAsI,EACtI,GAAG,CACJ,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
import { type DatasourceWriteInput, type LogicalV2Record, type MemorixRecordDraft, type WriterMetadataCatalog } from "@x12i/memorix-data";
|
|
2
|
+
import { ServiceError } from "../errors.js";
|
|
3
|
+
import type { MemorixScope } from "../scope.js";
|
|
4
|
+
import { type StoredContentWrite, type WriteOperation, type WriteReceiptRow, type WriteReceiptStore } from "./receipt-store.js";
|
|
5
|
+
export declare const CONTENT_BATCH_LIMIT = 500;
|
|
6
|
+
export type ContentWriteBody = {
|
|
7
|
+
objectType?: string;
|
|
8
|
+
contentType?: string;
|
|
9
|
+
record?: Record<string, unknown>;
|
|
10
|
+
precondition?: unknown;
|
|
11
|
+
expectedRevision?: number;
|
|
12
|
+
op?: "add" | "upsert" | "patch" | "replace" | "remove";
|
|
13
|
+
patch?: unknown;
|
|
14
|
+
datasource?: unknown;
|
|
15
|
+
suppressHooks?: unknown;
|
|
16
|
+
discriminatorValue?: string;
|
|
17
|
+
writeId?: unknown;
|
|
18
|
+
subject?: unknown;
|
|
19
|
+
};
|
|
20
|
+
export type ContentWritePorts = {
|
|
21
|
+
writer: {
|
|
22
|
+
add(req: {
|
|
23
|
+
scope: MemorixScope;
|
|
24
|
+
precondition: {
|
|
25
|
+
kind: "absent";
|
|
26
|
+
};
|
|
27
|
+
record: MemorixRecordDraft;
|
|
28
|
+
datasource?: DatasourceWriteInput;
|
|
29
|
+
suppressHooks?: boolean;
|
|
30
|
+
}): Promise<{
|
|
31
|
+
record: LogicalV2Record;
|
|
32
|
+
created: boolean;
|
|
33
|
+
unchanged?: boolean;
|
|
34
|
+
}>;
|
|
35
|
+
upsert(req: {
|
|
36
|
+
scope: MemorixScope;
|
|
37
|
+
precondition: {
|
|
38
|
+
kind: "absent";
|
|
39
|
+
} | {
|
|
40
|
+
kind: "revision";
|
|
41
|
+
revision: number;
|
|
42
|
+
} | {
|
|
43
|
+
kind: "none";
|
|
44
|
+
};
|
|
45
|
+
record: MemorixRecordDraft;
|
|
46
|
+
datasource?: DatasourceWriteInput;
|
|
47
|
+
suppressHooks?: boolean;
|
|
48
|
+
}): Promise<{
|
|
49
|
+
record: LogicalV2Record;
|
|
50
|
+
created: boolean;
|
|
51
|
+
unchanged?: boolean;
|
|
52
|
+
}>;
|
|
53
|
+
replace(req: {
|
|
54
|
+
scope: MemorixScope;
|
|
55
|
+
precondition: {
|
|
56
|
+
kind: "revision";
|
|
57
|
+
revision: number;
|
|
58
|
+
};
|
|
59
|
+
record: MemorixRecordDraft;
|
|
60
|
+
datasource?: DatasourceWriteInput;
|
|
61
|
+
suppressHooks?: boolean;
|
|
62
|
+
}): Promise<{
|
|
63
|
+
record: LogicalV2Record;
|
|
64
|
+
created: boolean;
|
|
65
|
+
unchanged?: boolean;
|
|
66
|
+
}>;
|
|
67
|
+
patch(req: {
|
|
68
|
+
scope: MemorixScope;
|
|
69
|
+
precondition: {
|
|
70
|
+
kind: "revision";
|
|
71
|
+
revision: number;
|
|
72
|
+
};
|
|
73
|
+
objectType: string;
|
|
74
|
+
contentType: string;
|
|
75
|
+
recordId: string;
|
|
76
|
+
discriminatorValue?: string;
|
|
77
|
+
ops: unknown;
|
|
78
|
+
datasource?: DatasourceWriteInput;
|
|
79
|
+
suppressHooks?: boolean;
|
|
80
|
+
}): Promise<{
|
|
81
|
+
record: LogicalV2Record;
|
|
82
|
+
created: boolean;
|
|
83
|
+
unchanged?: boolean;
|
|
84
|
+
}>;
|
|
85
|
+
remove(req: {
|
|
86
|
+
scope: MemorixScope;
|
|
87
|
+
objectType: string;
|
|
88
|
+
contentType: string;
|
|
89
|
+
recordId: string;
|
|
90
|
+
discriminatorValue?: string;
|
|
91
|
+
precondition: {
|
|
92
|
+
kind: "revision";
|
|
93
|
+
revision: number;
|
|
94
|
+
};
|
|
95
|
+
datasource?: DatasourceWriteInput;
|
|
96
|
+
suppressHooks?: boolean;
|
|
97
|
+
}): Promise<{
|
|
98
|
+
recordId: string;
|
|
99
|
+
objectType: string;
|
|
100
|
+
contentType: string;
|
|
101
|
+
removed: true;
|
|
102
|
+
previousRevision: number;
|
|
103
|
+
}>;
|
|
104
|
+
};
|
|
105
|
+
reader: {
|
|
106
|
+
getContent(scope: MemorixScope, address: {
|
|
107
|
+
objectType: string;
|
|
108
|
+
contentType: string;
|
|
109
|
+
recordId: string;
|
|
110
|
+
discriminatorValue?: string;
|
|
111
|
+
}): Promise<LogicalV2Record>;
|
|
112
|
+
};
|
|
113
|
+
catalog: WriterMetadataCatalog;
|
|
114
|
+
publications: {
|
|
115
|
+
list(): Promise<Array<{
|
|
116
|
+
status: string;
|
|
117
|
+
publicationId: string;
|
|
118
|
+
members: Array<{
|
|
119
|
+
recordId: string;
|
|
120
|
+
objectType: string;
|
|
121
|
+
contentType: string;
|
|
122
|
+
}>;
|
|
123
|
+
}>>;
|
|
124
|
+
};
|
|
125
|
+
};
|
|
126
|
+
export type CommittedWrite = {
|
|
127
|
+
operation: WriteOperation;
|
|
128
|
+
objectType: string;
|
|
129
|
+
contentType: string;
|
|
130
|
+
recordId: string;
|
|
131
|
+
revision: number;
|
|
132
|
+
data?: Record<string, unknown>;
|
|
133
|
+
hooks?: {
|
|
134
|
+
queued: number;
|
|
135
|
+
subscriptionIds: string[];
|
|
136
|
+
failed?: boolean;
|
|
137
|
+
};
|
|
138
|
+
};
|
|
139
|
+
export type ContentWriteDeps = {
|
|
140
|
+
scope: MemorixScope;
|
|
141
|
+
caller: string;
|
|
142
|
+
datasource: DatasourceWriteInput;
|
|
143
|
+
ports: ContentWritePorts;
|
|
144
|
+
receipts: WriteReceiptStore;
|
|
145
|
+
now?: () => string;
|
|
146
|
+
onCommitted?: (event: CommittedWrite) => Promise<unknown>;
|
|
147
|
+
/** Rejects the prepared write before a receipt is opened (patch guards). */
|
|
148
|
+
checkWrite?: (request: StoredContentWrite) => Promise<void>;
|
|
149
|
+
};
|
|
150
|
+
export type ContentWriteOutcome = {
|
|
151
|
+
kind: "stored";
|
|
152
|
+
httpStatus: 200;
|
|
153
|
+
body: Record<string, unknown>;
|
|
154
|
+
} | {
|
|
155
|
+
kind: "pending";
|
|
156
|
+
httpStatus: 202;
|
|
157
|
+
body: {
|
|
158
|
+
receiptId: string;
|
|
159
|
+
status: "pending";
|
|
160
|
+
retryAfterMs: number;
|
|
161
|
+
};
|
|
162
|
+
} | {
|
|
163
|
+
kind: "rejected";
|
|
164
|
+
error: ServiceError;
|
|
165
|
+
};
|
|
166
|
+
export declare function runContentWrite(deps: ContentWriteDeps, body: ContentWriteBody, replay?: WriteReceiptRow): Promise<ContentWriteOutcome>;
|
|
167
|
+
export declare function runContentBatch(deps: ContentWriteDeps, body: unknown, datasourceFor: (body: ContentWriteBody) => DatasourceWriteInput): Promise<{
|
|
168
|
+
results: unknown[];
|
|
169
|
+
}>;
|
|
170
|
+
//# sourceMappingURL=content-write.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"content-write.d.ts","sourceRoot":"","sources":["../../src/writes/content-write.ts"],"names":[],"mappings":"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"}
|