@x12i/memorix-descriptors 0.1.0 → 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 +390 -41
- package/dist/admin/create-admin.d.ts.map +1 -1
- package/dist/admin/create-admin.js +2 -1
- package/dist/admin/create-admin.js.map +1 -1
- package/dist/catalox/client.d.ts.map +1 -1
- package/dist/catalox/client.js +14 -1
- package/dist/catalox/client.js.map +1 -1
- package/dist/tests/fixtures.d.ts +54 -0
- package/dist/tests/fixtures.d.ts.map +1 -0
- package/dist/tests/fixtures.js +79 -0
- package/dist/tests/fixtures.js.map +1 -0
- package/dist/tests/helpers/live.d.ts +7 -0
- package/dist/tests/helpers/live.d.ts.map +1 -0
- package/dist/tests/helpers/live.js +31 -0
- package/dist/tests/helpers/live.js.map +1 -0
- package/dist/tests/integrity.test.d.ts +2 -0
- package/dist/tests/integrity.test.d.ts.map +1 -0
- package/dist/tests/integrity.test.js +49 -0
- package/dist/tests/integrity.test.js.map +1 -0
- package/dist/tests/live/catalox.live.test.d.ts +2 -0
- package/dist/tests/live/catalox.live.test.d.ts.map +1 -0
- package/dist/tests/live/catalox.live.test.js +110 -0
- package/dist/tests/live/catalox.live.test.js.map +1 -0
- package/dist/tests/mutations.test.d.ts +2 -0
- package/dist/tests/mutations.test.d.ts.map +1 -0
- package/dist/tests/mutations.test.js +99 -0
- package/dist/tests/mutations.test.js.map +1 -0
- package/dist/tests/seeds.test.d.ts +2 -0
- package/dist/tests/seeds.test.d.ts.map +1 -0
- package/dist/tests/seeds.test.js +57 -0
- package/dist/tests/seeds.test.js.map +1 -0
- package/dist/tests/setup.d.ts +2 -0
- package/dist/tests/setup.d.ts.map +1 -0
- package/dist/tests/setup.js +6 -0
- package/dist/tests/setup.js.map +1 -0
- package/dist/tests/validation.test.js +3 -62
- package/dist/tests/validation.test.js.map +1 -1
- package/package.json +5 -2
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
export const assetsEntityFixture = {
|
|
2
|
+
id: "assets",
|
|
3
|
+
entityName: "assets",
|
|
4
|
+
target: "entity",
|
|
5
|
+
defaultListDescriptorId: "assets-main-list",
|
|
6
|
+
defaultItemDescriptorId: "asset-detail-item",
|
|
7
|
+
collectionPrefix: "assets",
|
|
8
|
+
identity: {
|
|
9
|
+
allowedIdFields: ["entityId", "eventId"],
|
|
10
|
+
requiredExactlyOne: true,
|
|
11
|
+
defaultIdField: "entityId",
|
|
12
|
+
},
|
|
13
|
+
defaults: {
|
|
14
|
+
canonicalContentType: "snapshots",
|
|
15
|
+
dataRoot: "data",
|
|
16
|
+
effectiveDatePath: "capturedAt",
|
|
17
|
+
fallbackEffectiveDatePaths: [],
|
|
18
|
+
},
|
|
19
|
+
contentTypes: {
|
|
20
|
+
snapshots: {
|
|
21
|
+
postfix: "snapshots",
|
|
22
|
+
collection: "assets-snapshots",
|
|
23
|
+
isCanonical: true,
|
|
24
|
+
},
|
|
25
|
+
analysis: {
|
|
26
|
+
postfix: "analysis",
|
|
27
|
+
collection: "assets-analysis",
|
|
28
|
+
isCanonical: false,
|
|
29
|
+
},
|
|
30
|
+
},
|
|
31
|
+
properties: {
|
|
32
|
+
ipAddress: {
|
|
33
|
+
label: "IP Address",
|
|
34
|
+
source: { contentType: "snapshots", path: "data.ip_address" },
|
|
35
|
+
humanReadable: true,
|
|
36
|
+
},
|
|
37
|
+
hostName: {
|
|
38
|
+
label: "Host Name",
|
|
39
|
+
source: { contentType: "snapshots", path: "data.xdr.host_name" },
|
|
40
|
+
humanReadable: false,
|
|
41
|
+
},
|
|
42
|
+
},
|
|
43
|
+
relations: {},
|
|
44
|
+
};
|
|
45
|
+
export function sampleSnapshot() {
|
|
46
|
+
return {
|
|
47
|
+
entityDescriptors: {
|
|
48
|
+
assets: { ...assetsEntityFixture },
|
|
49
|
+
},
|
|
50
|
+
listDescriptors: {
|
|
51
|
+
"assets-main-list": {
|
|
52
|
+
id: "assets-main-list",
|
|
53
|
+
entity: "assets",
|
|
54
|
+
leadingContentType: "snapshots",
|
|
55
|
+
pagination: { enabled: true, defaultLimit: 50, maxLimit: 200 },
|
|
56
|
+
fields: ["ipAddress"],
|
|
57
|
+
},
|
|
58
|
+
},
|
|
59
|
+
itemDescriptors: {
|
|
60
|
+
"asset-detail-item": {
|
|
61
|
+
id: "asset-detail-item",
|
|
62
|
+
entity: "assets",
|
|
63
|
+
identity: { idField: "entityId" },
|
|
64
|
+
contentTypes: [{ contentType: "snapshots", required: true }],
|
|
65
|
+
sections: [{ id: "summary", title: "Summary", fields: ["ipAddress"] }],
|
|
66
|
+
},
|
|
67
|
+
},
|
|
68
|
+
completionMappings: {},
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
export function emptySnapshot() {
|
|
72
|
+
return {
|
|
73
|
+
entityDescriptors: {},
|
|
74
|
+
listDescriptors: {},
|
|
75
|
+
itemDescriptors: {},
|
|
76
|
+
completionMappings: {},
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
//# sourceMappingURL=fixtures.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fixtures.js","sourceRoot":"","sources":["../../src/tests/fixtures.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,mBAAmB,GAAG;IACjC,EAAE,EAAE,QAAQ;IACZ,UAAU,EAAE,QAAQ;IACpB,MAAM,EAAE,QAAQ;IAChB,uBAAuB,EAAE,kBAAkB;IAC3C,uBAAuB,EAAE,mBAAmB;IAC5C,gBAAgB,EAAE,QAAQ;IAC1B,QAAQ,EAAE;QACR,eAAe,EAAE,CAAC,UAAU,EAAE,SAAS,CAAC;QACxC,kBAAkB,EAAE,IAAI;QACxB,cAAc,EAAE,UAAU;KAC3B;IACD,QAAQ,EAAE;QACR,oBAAoB,EAAE,WAAW;QACjC,QAAQ,EAAE,MAAM;QAChB,iBAAiB,EAAE,YAAY;QAC/B,0BAA0B,EAAE,EAAE;KAC/B;IACD,YAAY,EAAE;QACZ,SAAS,EAAE;YACT,OAAO,EAAE,WAAW;YACpB,UAAU,EAAE,kBAAkB;YAC9B,WAAW,EAAE,IAAI;SAClB;QACD,QAAQ,EAAE;YACR,OAAO,EAAE,UAAU;YACnB,UAAU,EAAE,iBAAiB;YAC7B,WAAW,EAAE,KAAK;SACnB;KACF;IACD,UAAU,EAAE;QACV,SAAS,EAAE;YACT,KAAK,EAAE,YAAY;YACnB,MAAM,EAAE,EAAE,WAAW,EAAE,WAAW,EAAE,IAAI,EAAE,iBAAiB,EAAE;YAC7D,aAAa,EAAE,IAAI;SACpB;QACD,QAAQ,EAAE;YACR,KAAK,EAAE,WAAW;YAClB,MAAM,EAAE,EAAE,WAAW,EAAE,WAAW,EAAE,IAAI,EAAE,oBAAoB,EAAE;YAChE,aAAa,EAAE,KAAK;SACrB;KACF;IACD,SAAS,EAAE,EAAE;CACL,CAAC;AAEX,MAAM,UAAU,cAAc;IAC5B,OAAO;QACL,iBAAiB,EAAE;YACjB,MAAM,EAAE,EAAE,GAAG,mBAAmB,EAAE;SACnC;QACD,eAAe,EAAE;YACf,kBAAkB,EAAE;gBAClB,EAAE,EAAE,kBAAkB;gBACtB,MAAM,EAAE,QAAQ;gBAChB,kBAAkB,EAAE,WAAW;gBAC/B,UAAU,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,YAAY,EAAE,EAAE,EAAE,QAAQ,EAAE,GAAG,EAAE;gBAC9D,MAAM,EAAE,CAAC,WAAW,CAAC;aACtB;SACF;QACD,eAAe,EAAE;YACf,mBAAmB,EAAE;gBACnB,EAAE,EAAE,mBAAmB;gBACvB,MAAM,EAAE,QAAQ;gBAChB,QAAQ,EAAE,EAAE,OAAO,EAAE,UAAU,EAAE;gBACjC,YAAY,EAAE,CAAC,EAAE,WAAW,EAAE,WAAW,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;gBAC5D,QAAQ,EAAE,CAAC,EAAE,EAAE,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,CAAC,WAAW,CAAC,EAAE,CAAC;aACvE;SACF;QACD,kBAAkB,EAAE,EAAE;KACvB,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,aAAa;IAC3B,OAAO;QACL,iBAAiB,EAAE,EAAE;QACrB,eAAe,EAAE,EAAE;QACnB,eAAe,EAAE,EAAE;QACnB,kBAAkB,EAAE,EAAE;KACvB,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { MemorixDescriptorAdmin } from "../../admin/create-admin.js";
|
|
2
|
+
export declare function isLiveTestsEnabled(env?: NodeJS.ProcessEnv): boolean;
|
|
3
|
+
export declare function liveSkipReason(env?: NodeJS.ProcessEnv): string | null;
|
|
4
|
+
export declare function assertFirestoreReachable(): Promise<void>;
|
|
5
|
+
export declare function createLiveAdmin(): Promise<MemorixDescriptorAdmin>;
|
|
6
|
+
export declare function smokeEntityName(env?: NodeJS.ProcessEnv): string;
|
|
7
|
+
//# sourceMappingURL=live.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"live.d.ts","sourceRoot":"","sources":["../../../src/tests/helpers/live.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAC;AAE1E,wBAAgB,kBAAkB,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,OAAO,CAKhF;AAED,wBAAgB,cAAc,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,MAAM,GAAG,IAAI,CAGlF;AAED,wBAAsB,wBAAwB,IAAI,OAAO,CAAC,IAAI,CAAC,CAK9D;AAID,wBAAsB,eAAe,IAAI,OAAO,CAAC,sBAAsB,CAAC,CAQvE;AAED,wBAAgB,eAAe,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,MAAM,CAE5E"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { testFirestoreConnectionFromEnv } from "@x12i/catalox/firebase";
|
|
2
|
+
import { createMemorixDescriptorAdminFromEnv } from "../../admin/create-admin.js";
|
|
3
|
+
export function isLiveTestsEnabled(env = process.env) {
|
|
4
|
+
return (env.FIRESTORE_LIVE_TESTS === "1" ||
|
|
5
|
+
env.MEMORIX_DESCRIPTORS_LIVE_TESTS === "1");
|
|
6
|
+
}
|
|
7
|
+
export function liveSkipReason(env = process.env) {
|
|
8
|
+
if (isLiveTestsEnabled(env))
|
|
9
|
+
return null;
|
|
10
|
+
return "Set FIRESTORE_LIVE_TESTS=1 (or MEMORIX_DESCRIPTORS_LIVE_TESTS=1) in .env";
|
|
11
|
+
}
|
|
12
|
+
export async function assertFirestoreReachable() {
|
|
13
|
+
const probe = await testFirestoreConnectionFromEnv();
|
|
14
|
+
if (!probe.ok) {
|
|
15
|
+
throw probe.error ?? new Error("Firestore connectivity check failed");
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
let cachedAdmin;
|
|
19
|
+
export async function createLiveAdmin() {
|
|
20
|
+
if (!cachedAdmin) {
|
|
21
|
+
await assertFirestoreReachable();
|
|
22
|
+
cachedAdmin = await createMemorixDescriptorAdminFromEnv({
|
|
23
|
+
xronox: undefined,
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
return cachedAdmin;
|
|
27
|
+
}
|
|
28
|
+
export function smokeEntityName(env = process.env) {
|
|
29
|
+
return env.MEMORIX_SMOKE_ENTITY?.trim() || "assets";
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=live.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"live.js","sourceRoot":"","sources":["../../../src/tests/helpers/live.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,8BAA8B,EAAE,MAAM,wBAAwB,CAAC;AACxE,OAAO,EAAE,mCAAmC,EAAE,MAAM,6BAA6B,CAAC;AAGlF,MAAM,UAAU,kBAAkB,CAAC,MAAyB,OAAO,CAAC,GAAG;IACrE,OAAO,CACL,GAAG,CAAC,oBAAoB,KAAK,GAAG;QAChC,GAAG,CAAC,8BAA8B,KAAK,GAAG,CAC3C,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,MAAyB,OAAO,CAAC,GAAG;IACjE,IAAI,kBAAkB,CAAC,GAAG,CAAC;QAAE,OAAO,IAAI,CAAC;IACzC,OAAO,0EAA0E,CAAC;AACpF,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,wBAAwB;IAC5C,MAAM,KAAK,GAAG,MAAM,8BAA8B,EAAE,CAAC;IACrD,IAAI,CAAC,KAAK,CAAC,EAAE,EAAE,CAAC;QACd,MAAM,KAAK,CAAC,KAAK,IAAI,IAAI,KAAK,CAAC,qCAAqC,CAAC,CAAC;IACxE,CAAC;AACH,CAAC;AAED,IAAI,WAA+C,CAAC;AAEpD,MAAM,CAAC,KAAK,UAAU,eAAe;IACnC,IAAI,CAAC,WAAW,EAAE,CAAC;QACjB,MAAM,wBAAwB,EAAE,CAAC;QACjC,WAAW,GAAG,MAAM,mCAAmC,CAAC;YACtD,MAAM,EAAE,SAAS;SAClB,CAAC,CAAC;IACL,CAAC;IACD,OAAO,WAAW,CAAC;AACrB,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,MAAyB,OAAO,CAAC,GAAG;IAClE,OAAO,GAAG,CAAC,oBAAoB,EAAE,IAAI,EAAE,IAAI,QAAQ,CAAC;AACtD,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"integrity.test.d.ts","sourceRoot":"","sources":["../../src/tests/integrity.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import { validateDescriptorSnapshot } from "../integrity/validate.js";
|
|
3
|
+
import { assetsEntityFixture, sampleSnapshot } from "./fixtures.js";
|
|
4
|
+
describe("validateDescriptorSnapshot", () => {
|
|
5
|
+
it("accepts a connected minimal graph", () => {
|
|
6
|
+
const report = validateDescriptorSnapshot(sampleSnapshot());
|
|
7
|
+
expect(report.valid).toBe(true);
|
|
8
|
+
expect(report.errors).toHaveLength(0);
|
|
9
|
+
});
|
|
10
|
+
it("flags missing default list descriptor", () => {
|
|
11
|
+
const snapshot = sampleSnapshot();
|
|
12
|
+
snapshot.entityDescriptors.assets = {
|
|
13
|
+
...assetsEntityFixture,
|
|
14
|
+
defaultListDescriptorId: "missing-list",
|
|
15
|
+
};
|
|
16
|
+
const report = validateDescriptorSnapshot(snapshot);
|
|
17
|
+
expect(report.valid).toBe(false);
|
|
18
|
+
expect(report.errors.some((e) => e.code === "MISSING_DEFAULT_LIST")).toBe(true);
|
|
19
|
+
});
|
|
20
|
+
it("flags non-human-readable list fields", () => {
|
|
21
|
+
const snapshot = sampleSnapshot();
|
|
22
|
+
snapshot.listDescriptors["assets-main-list"] = {
|
|
23
|
+
...snapshot.listDescriptors["assets-main-list"],
|
|
24
|
+
fields: ["hostName"],
|
|
25
|
+
};
|
|
26
|
+
const report = validateDescriptorSnapshot(snapshot);
|
|
27
|
+
expect(report.valid).toBe(false);
|
|
28
|
+
expect(report.errors.some((e) => e.code === "NON_HUMAN_READABLE_LIST_FIELD" ||
|
|
29
|
+
e.code === "INVALID_LIST_DESCRIPTOR")).toBe(true);
|
|
30
|
+
});
|
|
31
|
+
it("flags unknown relation target", () => {
|
|
32
|
+
const snapshot = sampleSnapshot();
|
|
33
|
+
snapshot.entityDescriptors.assets = {
|
|
34
|
+
...assetsEntityFixture,
|
|
35
|
+
relations: {
|
|
36
|
+
toMissing: {
|
|
37
|
+
targetEntity: "not-real",
|
|
38
|
+
type: "oneToMany",
|
|
39
|
+
source: { contentType: "snapshots", path: "data.id" },
|
|
40
|
+
target: { contentType: "snapshots", path: "data.id" },
|
|
41
|
+
},
|
|
42
|
+
},
|
|
43
|
+
};
|
|
44
|
+
const report = validateDescriptorSnapshot(snapshot);
|
|
45
|
+
expect(report.valid).toBe(false);
|
|
46
|
+
expect(report.orphans.danglingReferences.length).toBeGreaterThan(0);
|
|
47
|
+
});
|
|
48
|
+
});
|
|
49
|
+
//# sourceMappingURL=integrity.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"integrity.test.js","sourceRoot":"","sources":["../../src/tests/integrity.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,0BAA0B,EAAE,MAAM,0BAA0B,CAAC;AACtE,OAAO,EAAE,mBAAmB,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAEpE,QAAQ,CAAC,4BAA4B,EAAE,GAAG,EAAE;IAC1C,EAAE,CAAC,mCAAmC,EAAE,GAAG,EAAE;QAC3C,MAAM,MAAM,GAAG,0BAA0B,CAAC,cAAc,EAAE,CAAC,CAAC;QAC5D,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAChC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IACxC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,uCAAuC,EAAE,GAAG,EAAE;QAC/C,MAAM,QAAQ,GAAG,cAAc,EAAE,CAAC;QAClC,QAAQ,CAAC,iBAAiB,CAAC,MAAM,GAAG;YAClC,GAAG,mBAAmB;YACtB,uBAAuB,EAAE,cAAc;SACxC,CAAC;QACF,MAAM,MAAM,GAAG,0BAA0B,CAAC,QAAQ,CAAC,CAAC;QACpD,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACjC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,sBAAsB,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAClF,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,sCAAsC,EAAE,GAAG,EAAE;QAC9C,MAAM,QAAQ,GAAG,cAAc,EAAE,CAAC;QAClC,QAAQ,CAAC,eAAe,CAAC,kBAAkB,CAAC,GAAG;YAC7C,GAAG,QAAQ,CAAC,eAAe,CAAC,kBAAkB,CAAE;YAChD,MAAM,EAAE,CAAC,UAAU,CAAC;SACrB,CAAC;QACF,MAAM,MAAM,GAAG,0BAA0B,CAAC,QAAQ,CAAC,CAAC;QACpD,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACjC,MAAM,CACJ,MAAM,CAAC,MAAM,CAAC,IAAI,CAChB,CAAC,CAAC,EAAE,EAAE,CACJ,CAAC,CAAC,IAAI,KAAK,+BAA+B;YAC1C,CAAC,CAAC,IAAI,KAAK,yBAAyB,CACvC,CACF,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACf,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,+BAA+B,EAAE,GAAG,EAAE;QACvC,MAAM,QAAQ,GAAG,cAAc,EAAE,CAAC;QAClC,QAAQ,CAAC,iBAAiB,CAAC,MAAM,GAAG;YAClC,GAAG,mBAAmB;YACtB,SAAS,EAAE;gBACT,SAAS,EAAE;oBACT,YAAY,EAAE,UAAU;oBACxB,IAAI,EAAE,WAAW;oBACjB,MAAM,EAAE,EAAE,WAAW,EAAE,WAAW,EAAE,IAAI,EAAE,SAAS,EAAE;oBACrD,MAAM,EAAE,EAAE,WAAW,EAAE,WAAW,EAAE,IAAI,EAAE,SAAS,EAAE;iBACtD;aACF;SACF,CAAC;QACF,MAAM,MAAM,GAAG,0BAA0B,CAAC,QAAQ,CAAC,CAAC;QACpD,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACjC,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,kBAAkB,CAAC,MAAM,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC;IACtE,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"catalox.live.test.d.ts","sourceRoot":"","sources":["../../../src/tests/live/catalox.live.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import { MEMORIX_ENTITY_DESCRIPTORS_CATALOG, MEMORIX_ITEM_DESCRIPTORS_CATALOG, MEMORIX_LIST_DESCRIPTORS_CATALOG, } from "../../catalog/ids.js";
|
|
3
|
+
import { createLiveAdmin, isLiveTestsEnabled, liveSkipReason, smokeEntityName, } from "../helpers/live.js";
|
|
4
|
+
import { createMemorixDescriptorAdminFromEnv } from "../../admin/create-admin.js";
|
|
5
|
+
const live = isLiveTestsEnabled();
|
|
6
|
+
const skipReason = liveSkipReason() ?? undefined;
|
|
7
|
+
describe.runIf(live)("live catalox / memorix-descriptors", () => {
|
|
8
|
+
it("loads admin and validates deployed descriptor graph", async () => {
|
|
9
|
+
const admin = await createLiveAdmin();
|
|
10
|
+
const report = await admin.validateMemorixDescriptors();
|
|
11
|
+
expect(report.counts.entityDescriptors).toBeGreaterThan(0);
|
|
12
|
+
expect(report.counts.listDescriptors).toBeGreaterThan(0);
|
|
13
|
+
expect(report.counts.itemDescriptors).toBeGreaterThan(0);
|
|
14
|
+
if (!report.valid) {
|
|
15
|
+
console.warn("Integrity warnings/errors (graph may have known legacy issues):", JSON.stringify({ errorCount: report.errors.length, warningCount: report.warnings.length }, null, 2));
|
|
16
|
+
}
|
|
17
|
+
expect(report.counts.entityDescriptors).toBeGreaterThanOrEqual(3);
|
|
18
|
+
}, 120_000);
|
|
19
|
+
it("loads smoke entity descriptor from Catalox", async () => {
|
|
20
|
+
const admin = await createLiveAdmin();
|
|
21
|
+
const entityName = smokeEntityName();
|
|
22
|
+
const snapshot = await admin.loadSnapshot();
|
|
23
|
+
const entity = snapshot.entityDescriptors[entityName];
|
|
24
|
+
expect(entity, `entity descriptor "${entityName}"`).toBeDefined();
|
|
25
|
+
expect(entity?.defaultListDescriptorId).toBeTruthy();
|
|
26
|
+
expect(entity?.defaultItemDescriptorId).toBeTruthy();
|
|
27
|
+
const listId = String(entity?.defaultListDescriptorId);
|
|
28
|
+
const itemId = String(entity?.defaultItemDescriptorId);
|
|
29
|
+
expect(snapshot.listDescriptors[listId]).toBeDefined();
|
|
30
|
+
expect(snapshot.itemDescriptors[itemId]).toBeDefined();
|
|
31
|
+
}, 60_000);
|
|
32
|
+
it("lists catalog items for entity, list, and item descriptors", async () => {
|
|
33
|
+
const admin = await createLiveAdmin();
|
|
34
|
+
const entityPage = await admin.catalox.listCatalogItems(MEMORIX_ENTITY_DESCRIPTORS_CATALOG, { limit: 50 });
|
|
35
|
+
expect(entityPage.listOutcome).not.toBe("mapping_blocked");
|
|
36
|
+
expect(entityPage.items.length).toBeGreaterThan(0);
|
|
37
|
+
const listPage = await admin.catalox.listCatalogItems(MEMORIX_LIST_DESCRIPTORS_CATALOG, { limit: 50 });
|
|
38
|
+
expect(listPage.items.length).toBeGreaterThan(0);
|
|
39
|
+
const itemPage = await admin.catalox.listCatalogItems(MEMORIX_ITEM_DESCRIPTORS_CATALOG, { limit: 50 });
|
|
40
|
+
expect(itemPage.items.length).toBeGreaterThan(0);
|
|
41
|
+
}, 60_000);
|
|
42
|
+
it("builds descriptor graph with default-list edges", async () => {
|
|
43
|
+
const admin = await createLiveAdmin();
|
|
44
|
+
const graph = await admin.getDescriptorGraph();
|
|
45
|
+
const entityName = smokeEntityName();
|
|
46
|
+
expect(graph.nodes.some((n) => n.id === entityName && n.kind === "entity")).toBe(true);
|
|
47
|
+
expect(graph.edges.some((e) => e.from === entityName && e.kind === "default-list")).toBe(true);
|
|
48
|
+
}, 60_000);
|
|
49
|
+
it("resolves collection name for smoke entity canonical content type", async () => {
|
|
50
|
+
const admin = await createLiveAdmin();
|
|
51
|
+
const entityName = smokeEntityName();
|
|
52
|
+
const snapshot = await admin.loadSnapshot();
|
|
53
|
+
const entity = snapshot.entityDescriptors[entityName];
|
|
54
|
+
const canonical = String(entity.defaults?.canonicalContentType ??
|
|
55
|
+
"snapshots");
|
|
56
|
+
const collection = await admin.resolveCollection(entityName, canonical);
|
|
57
|
+
expect(collection).toBeTruthy();
|
|
58
|
+
expect(collection).toMatch(/^[a-z0-9-]+$/);
|
|
59
|
+
}, 60_000);
|
|
60
|
+
it("dry-run addProperty on smoke entity does not write", async () => {
|
|
61
|
+
const admin = await createLiveAdmin();
|
|
62
|
+
const entityName = smokeEntityName();
|
|
63
|
+
const snapshot = await admin.loadSnapshot();
|
|
64
|
+
const entity = snapshot.entityDescriptors[entityName];
|
|
65
|
+
const canonical = String(entity.defaults?.canonicalContentType ??
|
|
66
|
+
Object.keys(entity.contentTypes)[0] ??
|
|
67
|
+
"snapshots");
|
|
68
|
+
const propKey = `_live-test-prop-${Date.now()}`;
|
|
69
|
+
const result = await admin.addProperty(entityName, propKey, {
|
|
70
|
+
label: "Live Test Property",
|
|
71
|
+
source: { contentType: canonical, path: "data._live_test" },
|
|
72
|
+
humanReadable: true,
|
|
73
|
+
}, { dryRun: true, addToDefaultList: false, addToDefaultItem: false });
|
|
74
|
+
expect(result.dryRun).toBe(true);
|
|
75
|
+
expect(result.cataloxWrites.length).toBeGreaterThan(0);
|
|
76
|
+
expect(result.errors.some((e) => ["ENTITY_NOT_FOUND", "VALIDATION_FAILED", "UNKNOWN_CONTENT_TYPE"].includes(e.code))).toBe(false);
|
|
77
|
+
}, 60_000);
|
|
78
|
+
it("reconcileDescriptorsWithMongo returns inventory when xronox is configured", async () => {
|
|
79
|
+
if (!process.env.MONGO_URI?.trim()) {
|
|
80
|
+
console.warn("Skipping reconcile — MONGO_URI not set in .env");
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
const admin = await createMemorixDescriptorAdminFromEnv();
|
|
84
|
+
try {
|
|
85
|
+
const result = await admin.reconcileDescriptorsWithMongo();
|
|
86
|
+
expect(result.inventory.entries).toBeDefined();
|
|
87
|
+
expect(Array.isArray(result.suggestions)).toBe(true);
|
|
88
|
+
expect(result.inventory.scannedAt).toBeTruthy();
|
|
89
|
+
}
|
|
90
|
+
catch (err) {
|
|
91
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
92
|
+
if (message.includes("data tier") ||
|
|
93
|
+
message.includes("xronox") ||
|
|
94
|
+
message.includes("Xronox")) {
|
|
95
|
+
console.warn("Skipping reconcile assertion — Xronox not configured:", message);
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
throw err;
|
|
99
|
+
}
|
|
100
|
+
}, 180_000);
|
|
101
|
+
});
|
|
102
|
+
describe("live test gate", () => {
|
|
103
|
+
it.skipIf(live)("skipped — live tests disabled", () => {
|
|
104
|
+
expect(skipReason).toBeTruthy();
|
|
105
|
+
});
|
|
106
|
+
it.runIf(!live)("documents how to enable live tests", () => {
|
|
107
|
+
expect(liveSkipReason()).toMatch(/FIRESTORE_LIVE_TESTS/);
|
|
108
|
+
});
|
|
109
|
+
});
|
|
110
|
+
//# sourceMappingURL=catalox.live.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"catalox.live.test.js","sourceRoot":"","sources":["../../../src/tests/live/catalox.live.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mutations.test.d.ts","sourceRoot":"","sources":["../../src/tests/mutations.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import { addContentType } from "../mutations/content-type.js";
|
|
3
|
+
import { addProperty, removeProperty } from "../mutations/property.js";
|
|
4
|
+
import { registerEntityDescriptor } from "../mutations/entity.js";
|
|
5
|
+
import { emptySnapshot, sampleSnapshot } from "./fixtures.js";
|
|
6
|
+
function mockCtx(snapshot = sampleSnapshot()) {
|
|
7
|
+
return {
|
|
8
|
+
catalox: {},
|
|
9
|
+
env: process.env,
|
|
10
|
+
loadSnapshot: async () => snapshot,
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
describe("content type mutations (dry-run)", () => {
|
|
14
|
+
it("rejects duplicate content type keys", async () => {
|
|
15
|
+
const result = await addContentType(mockCtx(), "assets", { key: "snapshots", postfix: "snapshots" }, { dryRun: true });
|
|
16
|
+
expect(result.ok).toBe(false);
|
|
17
|
+
expect(result.errors[0]?.code).toBe("CONTENT_TYPE_EXISTS");
|
|
18
|
+
});
|
|
19
|
+
it("plans add of a new content type", async () => {
|
|
20
|
+
const result = await addContentType(mockCtx(), "assets", { key: "enrichment", postfix: "enrichment" }, { dryRun: true, skipMongo: true });
|
|
21
|
+
expect(result.ok).toBe(true);
|
|
22
|
+
expect(result.cataloxWrites).toHaveLength(1);
|
|
23
|
+
expect(result.data?.key).toBe("enrichment");
|
|
24
|
+
});
|
|
25
|
+
it("blocks removal when content type is referenced by a property", async () => {
|
|
26
|
+
const snapshot = sampleSnapshot();
|
|
27
|
+
const assets = snapshot.entityDescriptors.assets;
|
|
28
|
+
snapshot.entityDescriptors.assets = {
|
|
29
|
+
...assets,
|
|
30
|
+
properties: {
|
|
31
|
+
...assets.properties,
|
|
32
|
+
enrichmentFlag: {
|
|
33
|
+
label: "Enrichment",
|
|
34
|
+
source: { contentType: "analysis", path: "data.flag" },
|
|
35
|
+
humanReadable: true,
|
|
36
|
+
},
|
|
37
|
+
},
|
|
38
|
+
};
|
|
39
|
+
const result = await import("../mutations/content-type.js").then((m) => m.removeContentType(mockCtx(snapshot), "assets", "analysis", { dryRun: true }));
|
|
40
|
+
expect(result.ok).toBe(false);
|
|
41
|
+
expect(result.errors[0]?.code).toBe("CONTENT_TYPE_IN_USE");
|
|
42
|
+
});
|
|
43
|
+
});
|
|
44
|
+
describe("property mutations (dry-run)", () => {
|
|
45
|
+
it("adds a property and cascades to default list/item", async () => {
|
|
46
|
+
const result = await addProperty(mockCtx(), "assets", "agentType", {
|
|
47
|
+
label: "Agent Type",
|
|
48
|
+
source: { contentType: "snapshots", path: "data.agent_type" },
|
|
49
|
+
humanReadable: true,
|
|
50
|
+
}, { dryRun: true, addToDefaultList: true, addToDefaultItem: true });
|
|
51
|
+
expect(result.ok).toBe(true);
|
|
52
|
+
expect(result.cataloxWrites.length).toBeGreaterThanOrEqual(1);
|
|
53
|
+
});
|
|
54
|
+
it("blocks removal when property path is used in a relation", async () => {
|
|
55
|
+
const snapshot = sampleSnapshot();
|
|
56
|
+
snapshot.entityDescriptors.assets = {
|
|
57
|
+
...snapshot.entityDescriptors.assets,
|
|
58
|
+
relations: {
|
|
59
|
+
linked: {
|
|
60
|
+
targetEntity: "assets",
|
|
61
|
+
type: "oneToMany",
|
|
62
|
+
source: { contentType: "snapshots", path: "data.ipAddress" },
|
|
63
|
+
target: { contentType: "snapshots", path: "data.id" },
|
|
64
|
+
},
|
|
65
|
+
},
|
|
66
|
+
};
|
|
67
|
+
const result = await removeProperty(mockCtx(snapshot), "assets", "ipAddress", { dryRun: true });
|
|
68
|
+
expect(result.ok).toBe(false);
|
|
69
|
+
expect(result.errors[0]?.code).toBe("PROPERTY_IN_RELATION");
|
|
70
|
+
});
|
|
71
|
+
});
|
|
72
|
+
describe("registerEntityDescriptor (dry-run)", () => {
|
|
73
|
+
it("rejects duplicate entity registration", async () => {
|
|
74
|
+
const result = await registerEntityDescriptor(mockCtx(), {
|
|
75
|
+
entityName: "assets",
|
|
76
|
+
target: "entity",
|
|
77
|
+
collectionPrefix: "assets",
|
|
78
|
+
canonicalContentType: { key: "snapshots", postfix: "snapshots" },
|
|
79
|
+
}, { dryRun: true });
|
|
80
|
+
expect(result.ok).toBe(false);
|
|
81
|
+
expect(result.errors[0]?.code).toBe("ENTITY_EXISTS");
|
|
82
|
+
});
|
|
83
|
+
it("registers a new knowledge entity graph in dry-run", async () => {
|
|
84
|
+
const result = await registerEntityDescriptor(mockCtx(emptySnapshot()), {
|
|
85
|
+
entityName: "impact-stories",
|
|
86
|
+
target: "knowledge",
|
|
87
|
+
collectionPrefix: "impact-stories",
|
|
88
|
+
canonicalContentType: {
|
|
89
|
+
key: "narratives",
|
|
90
|
+
postfix: "narratives",
|
|
91
|
+
collection: "impact-stories-narratives",
|
|
92
|
+
},
|
|
93
|
+
identity: { idField: "knowledgeId" },
|
|
94
|
+
}, { dryRun: true });
|
|
95
|
+
expect(result.ok).toBe(true);
|
|
96
|
+
expect(result.cataloxWrites).toHaveLength(3);
|
|
97
|
+
});
|
|
98
|
+
});
|
|
99
|
+
//# sourceMappingURL=mutations.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mutations.test.js","sourceRoot":"","sources":["../../src/tests/mutations.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"seeds.test.d.ts","sourceRoot":"","sources":["../../src/tests/seeds.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import { existsSync } from "node:fs";
|
|
3
|
+
import { dirname, resolve } from "node:path";
|
|
4
|
+
import { fileURLToPath } from "node:url";
|
|
5
|
+
import { buildDescriptorSeedManifest } from "../seeds/index.js";
|
|
6
|
+
import { sampleSnapshot } from "./fixtures.js";
|
|
7
|
+
const packageRoot = resolve(dirname(fileURLToPath(import.meta.url)), "..", "..");
|
|
8
|
+
const retrievalInputs = resolve(packageRoot, "..", "memorix-retrieval", "catalox-seeds", "inputs");
|
|
9
|
+
describe("buildDescriptorSeedManifest", () => {
|
|
10
|
+
it("builds manifest items from an in-memory snapshot", async () => {
|
|
11
|
+
const manifest = await buildDescriptorSeedManifest(sampleSnapshot(), {
|
|
12
|
+
domains: ["network"],
|
|
13
|
+
agents: ["neo"],
|
|
14
|
+
});
|
|
15
|
+
expect(manifest.items.length).toBeGreaterThanOrEqual(3);
|
|
16
|
+
expect(manifest.items.some((i) => i.catalogId.includes("entity"))).toBe(true);
|
|
17
|
+
expect(manifest.catalogs.some((c) => c.catalogId.includes("entity"))).toBe(true);
|
|
18
|
+
});
|
|
19
|
+
it.skipIf(!existsSync(retrievalInputs))("round-trips memorix-retrieval catalox-seeds/inputs when sibling repo exists", async () => {
|
|
20
|
+
const { createSeedInputsReader, loadMemorixRetrievalSeedScopeFromInputs } = await import("@x12i/memorix-retrieval");
|
|
21
|
+
const readJson = createSeedInputsReader(retrievalInputs);
|
|
22
|
+
const scope = await loadMemorixRetrievalSeedScopeFromInputs(retrievalInputs);
|
|
23
|
+
const snapshot = {
|
|
24
|
+
entityDescriptors: {},
|
|
25
|
+
listDescriptors: {},
|
|
26
|
+
itemDescriptors: {},
|
|
27
|
+
completionMappings: {},
|
|
28
|
+
};
|
|
29
|
+
for (const file of [
|
|
30
|
+
"entity-descriptors/assets.json",
|
|
31
|
+
"entity-descriptors/vulnerabilities.json",
|
|
32
|
+
"entity-descriptors/variabilities-groups.json",
|
|
33
|
+
"list-descriptors/assets-main-list.json",
|
|
34
|
+
"item-descriptors/asset-detail-item.json",
|
|
35
|
+
]) {
|
|
36
|
+
const data = await readJson(file);
|
|
37
|
+
const id = String(data.id);
|
|
38
|
+
if (file.startsWith("entity-descriptors/")) {
|
|
39
|
+
snapshot.entityDescriptors[id] = data;
|
|
40
|
+
}
|
|
41
|
+
else if (file.startsWith("list-descriptors/")) {
|
|
42
|
+
snapshot.listDescriptors[id] = data;
|
|
43
|
+
}
|
|
44
|
+
else {
|
|
45
|
+
snapshot.itemDescriptors[id] = data;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
const manifest = await buildDescriptorSeedManifest(snapshot, scope);
|
|
49
|
+
expect(manifest.items.length).toBeGreaterThanOrEqual(5);
|
|
50
|
+
const entityIds = manifest.items
|
|
51
|
+
.filter((i) => i.catalogId.includes("entity"))
|
|
52
|
+
.map((i) => String(i.data.id));
|
|
53
|
+
expect(entityIds).toContain("assets");
|
|
54
|
+
expect(entityIds).toContain("vulnerabilities");
|
|
55
|
+
});
|
|
56
|
+
});
|
|
57
|
+
//# sourceMappingURL=seeds.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"seeds.test.js","sourceRoot":"","sources":["../../src/tests/seeds.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"setup.d.ts","sourceRoot":"","sources":["../../src/tests/setup.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { config } from "dotenv";
|
|
2
|
+
import { dirname, resolve } from "node:path";
|
|
3
|
+
import { fileURLToPath } from "node:url";
|
|
4
|
+
const packageRoot = resolve(dirname(fileURLToPath(import.meta.url)), "..", "..");
|
|
5
|
+
config({ path: resolve(packageRoot, ".env") });
|
|
6
|
+
//# sourceMappingURL=setup.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"setup.js","sourceRoot":"","sources":["../../src/tests/setup.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAChC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,MAAM,WAAW,GAAG,OAAO,CAAC,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;AACjF,MAAM,CAAC,EAAE,IAAI,EAAE,OAAO,CAAC,WAAW,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC"}
|
|
@@ -2,62 +2,8 @@ import { describe, expect, it } from "vitest";
|
|
|
2
2
|
import { defaultItemDescriptorId, defaultListDescriptorId, isKebabCase, singularizeEntityName, validateMemorixEntityDescriptor, validateMemorixEntityListDescriptor, validateMemorixItemDescriptor, } from "../validation/descriptor-validation.js";
|
|
3
3
|
import { validateDescriptorSnapshot } from "../integrity/validate.js";
|
|
4
4
|
import { buildDescriptorGraph } from "../integrity/graph.js";
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
assets: {
|
|
8
|
-
id: "assets",
|
|
9
|
-
entityName: "assets",
|
|
10
|
-
target: "entity",
|
|
11
|
-
defaultListDescriptorId: "assets-main-list",
|
|
12
|
-
defaultItemDescriptorId: "asset-detail-item",
|
|
13
|
-
collectionPrefix: "assets",
|
|
14
|
-
identity: {
|
|
15
|
-
allowedIdFields: ["entityId", "eventId"],
|
|
16
|
-
requiredExactlyOne: true,
|
|
17
|
-
defaultIdField: "entityId",
|
|
18
|
-
},
|
|
19
|
-
defaults: {
|
|
20
|
-
canonicalContentType: "snapshots",
|
|
21
|
-
dataRoot: "data",
|
|
22
|
-
effectiveDatePath: "capturedAt",
|
|
23
|
-
fallbackEffectiveDatePaths: [],
|
|
24
|
-
},
|
|
25
|
-
contentTypes: {
|
|
26
|
-
snapshots: {
|
|
27
|
-
postfix: "snapshots",
|
|
28
|
-
collection: "assets-snapshots",
|
|
29
|
-
isCanonical: true,
|
|
30
|
-
},
|
|
31
|
-
},
|
|
32
|
-
properties: {
|
|
33
|
-
ipAddress: {
|
|
34
|
-
label: "IP Address",
|
|
35
|
-
source: { contentType: "snapshots", path: "data.ip_address" },
|
|
36
|
-
humanReadable: true,
|
|
37
|
-
},
|
|
38
|
-
},
|
|
39
|
-
},
|
|
40
|
-
},
|
|
41
|
-
listDescriptors: {
|
|
42
|
-
"assets-main-list": {
|
|
43
|
-
id: "assets-main-list",
|
|
44
|
-
entity: "assets",
|
|
45
|
-
leadingContentType: "snapshots",
|
|
46
|
-
pagination: { enabled: true, defaultLimit: 50, maxLimit: 200 },
|
|
47
|
-
fields: ["ipAddress"],
|
|
48
|
-
},
|
|
49
|
-
},
|
|
50
|
-
itemDescriptors: {
|
|
51
|
-
"asset-detail-item": {
|
|
52
|
-
id: "asset-detail-item",
|
|
53
|
-
entity: "assets",
|
|
54
|
-
identity: { idField: "entityId" },
|
|
55
|
-
contentTypes: [{ contentType: "snapshots", required: true }],
|
|
56
|
-
sections: [{ id: "summary", title: "Summary", fields: ["ipAddress"] }],
|
|
57
|
-
},
|
|
58
|
-
},
|
|
59
|
-
completionMappings: {},
|
|
60
|
-
});
|
|
5
|
+
import { emptySnapshot, sampleSnapshot } from "./fixtures.js";
|
|
6
|
+
import { registerEntityDescriptor } from "../mutations/entity.js";
|
|
61
7
|
describe("descriptor validation helpers", () => {
|
|
62
8
|
it("validates kebab-case entity names", () => {
|
|
63
9
|
expect(isKebabCase("impact-stories")).toBe(true);
|
|
@@ -86,15 +32,10 @@ describe("descriptor validation helpers", () => {
|
|
|
86
32
|
});
|
|
87
33
|
describe("register entity plan", () => {
|
|
88
34
|
it("projects entity + default list/item writes", async () => {
|
|
89
|
-
const { registerEntityDescriptor } = await import("../mutations/entity.js");
|
|
90
|
-
const snapshot = sampleSnapshot();
|
|
91
|
-
snapshot.entityDescriptors = {};
|
|
92
|
-
snapshot.listDescriptors = {};
|
|
93
|
-
snapshot.itemDescriptors = {};
|
|
94
35
|
const result = await registerEntityDescriptor({
|
|
95
36
|
catalox: {},
|
|
96
37
|
env: process.env,
|
|
97
|
-
loadSnapshot: async () =>
|
|
38
|
+
loadSnapshot: async () => emptySnapshot(),
|
|
98
39
|
}, {
|
|
99
40
|
entityName: "impact-stories",
|
|
100
41
|
target: "knowledge",
|