@x12i/memorix-service 3.9.2 → 3.11.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 (80) hide show
  1. package/dist/analytics/content-allow.d.ts +17 -0
  2. package/dist/analytics/content-allow.d.ts.map +1 -0
  3. package/dist/analytics/content-allow.js +39 -0
  4. package/dist/analytics/content-allow.js.map +1 -0
  5. package/dist/analytics/definition.d.ts +179 -0
  6. package/dist/analytics/definition.d.ts.map +1 -0
  7. package/dist/analytics/definition.js +524 -0
  8. package/dist/analytics/definition.js.map +1 -0
  9. package/dist/analytics/engine.d.ts +63 -0
  10. package/dist/analytics/engine.d.ts.map +1 -0
  11. package/dist/analytics/engine.js +181 -0
  12. package/dist/analytics/engine.js.map +1 -0
  13. package/dist/analytics/host.d.ts +15 -0
  14. package/dist/analytics/host.d.ts.map +1 -0
  15. package/dist/analytics/host.js +143 -0
  16. package/dist/analytics/host.js.map +1 -0
  17. package/dist/analytics/index-store.d.ts +98 -0
  18. package/dist/analytics/index-store.d.ts.map +1 -0
  19. package/dist/analytics/index-store.js +295 -0
  20. package/dist/analytics/index-store.js.map +1 -0
  21. package/dist/analytics/materializer.d.ts +88 -0
  22. package/dist/analytics/materializer.d.ts.map +1 -0
  23. package/dist/analytics/materializer.js +364 -0
  24. package/dist/analytics/materializer.js.map +1 -0
  25. package/dist/analytics/pipeline-port.d.ts +10 -0
  26. package/dist/analytics/pipeline-port.d.ts.map +1 -0
  27. package/dist/analytics/pipeline-port.js +42 -0
  28. package/dist/analytics/pipeline-port.js.map +1 -0
  29. package/dist/analytics/projector.d.ts +60 -0
  30. package/dist/analytics/projector.d.ts.map +1 -0
  31. package/dist/analytics/projector.js +270 -0
  32. package/dist/analytics/projector.js.map +1 -0
  33. package/dist/analytics/property-index.d.ts +87 -0
  34. package/dist/analytics/property-index.d.ts.map +1 -0
  35. package/dist/analytics/property-index.js +537 -0
  36. package/dist/analytics/property-index.js.map +1 -0
  37. package/dist/analytics/state.d.ts +83 -0
  38. package/dist/analytics/state.d.ts.map +1 -0
  39. package/dist/analytics/state.js +273 -0
  40. package/dist/analytics/state.js.map +1 -0
  41. package/dist/analytics/tracker.d.ts +215 -0
  42. package/dist/analytics/tracker.d.ts.map +1 -0
  43. package/dist/analytics/tracker.js +1515 -0
  44. package/dist/analytics/tracker.js.map +1 -0
  45. package/dist/app.d.ts.map +1 -1
  46. package/dist/app.js +6 -0
  47. package/dist/app.js.map +1 -1
  48. package/dist/content-census-countex.d.ts +15 -0
  49. package/dist/content-census-countex.d.ts.map +1 -0
  50. package/dist/content-census-countex.js +18 -0
  51. package/dist/content-census-countex.js.map +1 -0
  52. package/dist/datasource-backfill.d.ts +2 -0
  53. package/dist/datasource-backfill.d.ts.map +1 -1
  54. package/dist/datasource-backfill.js +5 -1
  55. package/dist/datasource-backfill.js.map +1 -1
  56. package/dist/index.d.ts +4 -0
  57. package/dist/index.d.ts.map +1 -1
  58. package/dist/index.js +3 -0
  59. package/dist/index.js.map +1 -1
  60. package/dist/openapi/openapi.json +955 -210
  61. package/dist/platform.d.ts +6 -0
  62. package/dist/platform.d.ts.map +1 -1
  63. package/dist/platform.js +69 -4
  64. package/dist/platform.js.map +1 -1
  65. package/dist/routes/analytics-counters.d.ts +8 -0
  66. package/dist/routes/analytics-counters.d.ts.map +1 -0
  67. package/dist/routes/analytics-counters.js +100 -0
  68. package/dist/routes/analytics-counters.js.map +1 -0
  69. package/dist/routes/analytics-indexes.d.ts +8 -0
  70. package/dist/routes/analytics-indexes.d.ts.map +1 -0
  71. package/dist/routes/analytics-indexes.js +80 -0
  72. package/dist/routes/analytics-indexes.js.map +1 -0
  73. package/dist/routes/data.d.ts.map +1 -1
  74. package/dist/routes/data.js +22 -0
  75. package/dist/routes/data.js.map +1 -1
  76. package/dist/routes/datasource-backfill.d.ts.map +1 -1
  77. package/dist/routes/datasource-backfill.js +8 -1
  78. package/dist/routes/datasource-backfill.js.map +1 -1
  79. package/openapi/openapi.json +955 -210
  80. package/package.json +5 -5
@@ -0,0 +1,181 @@
1
+ import { createCountex, } from "@x12i/countex";
2
+ import { MemoryCache, MemoryDurable } from "@x12i/countex/adapters/memory";
3
+ import { DurableReadCache } from "@x12i/countex/adapters/durable-cache";
4
+ export const ANALYTICS_COUNTER_ID = "memorix_analytics";
5
+ export const analyticsCounterMap = {
6
+ counterId: ANALYTICS_COUNTER_ID,
7
+ scope: { path: "$.scope" },
8
+ eventTime: { path: "$.at" },
9
+ subjects: [{ type: "s", path: "$.subject", required: true }],
10
+ metrics: [{ path: "$.metric", required: true }],
11
+ dimensions: [{ name: "split", path: "$.split" }],
12
+ measures: [{ name: "value", path: "$.value", aggregations: ["sum"], onMissing: "skip" }],
13
+ delta: { path: "$.delta", default: 1 },
14
+ timeframes: ["all", "hour", "day"],
15
+ options: { normalizeValues: false, skipMissingOptionalDimensions: true },
16
+ cardinality: {
17
+ maxDimensionValuesPerName: 10_000,
18
+ maxSubjectsPerScope: 500_000,
19
+ onLimit: "overflow",
20
+ overflowValue: "__OTHER__",
21
+ },
22
+ };
23
+ export function countexScope(parts) {
24
+ const pair = parts.pair
25
+ ? `${encodeURIComponent(parts.pair[0])}|${encodeURIComponent(parts.pair[1])}`
26
+ : "*";
27
+ return [
28
+ encodeURIComponent(parts.orgId),
29
+ `${encodeURIComponent(parts.counterId)}#${parts.generation}`,
30
+ pair,
31
+ ].join("|");
32
+ }
33
+ export function orgOfCountexScope(scope) {
34
+ return decodeURIComponent(scope.slice(0, scope.indexOf("|")));
35
+ }
36
+ /**
37
+ * Countex trims and lowercases subject and metric dictionary keys. Bucket names are case
38
+ * sensitive, so keys are URI-encoded (no raw `^` survives) and upper-case letters escaped.
39
+ */
40
+ export function encodeKey(value) {
41
+ return encodeURIComponent(value).replace(/[A-Z]/g, (c) => `^${c.toLowerCase()}`);
42
+ }
43
+ export function decodeKey(value) {
44
+ return decodeURIComponent(value.replace(/\^([a-z])/g, (_, c) => c.toUpperCase()));
45
+ }
46
+ function hourKey(d) {
47
+ return d.toISOString().slice(0, 13);
48
+ }
49
+ function dayKey(d) {
50
+ return d.toISOString().slice(0, 10);
51
+ }
52
+ function rowsOf(result) {
53
+ return result.rows.filter((r) => !!r && typeof r === "object" && "keys" in r && typeof r.count === "number");
54
+ }
55
+ export async function createAnalyticsCountex(opts = {}) {
56
+ let durable;
57
+ let storage = "memory";
58
+ if (opts.durable) {
59
+ durable = opts.durable;
60
+ }
61
+ else if (opts.mongoClient) {
62
+ const { MongoDurable } = await import("@x12i/countex/adapters/mongo");
63
+ const dbNameFor = opts.dbNameFor ?? ((orgId) => `${orgId}_operational`);
64
+ durable = new MongoDurable({
65
+ client: opts.mongoClient,
66
+ dbResolver: ({ scope }) => dbNameFor(orgOfCountexScope(scope)),
67
+ cellsCollection: "analytics_countex_cells",
68
+ dictCollection: "analytics_countex_dict",
69
+ seqCollection: "analytics_countex_seq",
70
+ });
71
+ storage = "mongo";
72
+ }
73
+ else {
74
+ durable = new MemoryDurable();
75
+ }
76
+ const countex = createCountex({
77
+ maps: [analyticsCounterMap],
78
+ durable,
79
+ cache: storage === "mongo" ? new DurableReadCache(durable) : new MemoryCache(),
80
+ flush: {
81
+ everyMs: 60_000,
82
+ maxBufferedCells: 200_000,
83
+ maxBufferedEvents: 100_000,
84
+ flushOnShutdown: true,
85
+ onOverflow: "block",
86
+ },
87
+ });
88
+ await countex.init();
89
+ const query = async (spec) => rowsOf(await countex.query({
90
+ counterId: ANALYTICS_COUNTER_ID,
91
+ format: "table",
92
+ resolveLabels: true,
93
+ ...spec,
94
+ }));
95
+ return {
96
+ countex,
97
+ storage,
98
+ async ingest(increments) {
99
+ if (increments.length === 0)
100
+ return;
101
+ await countex.ingestBatch(increments.map((i) => ({
102
+ scope: i.scope,
103
+ at: i.at,
104
+ metric: encodeKey(i.metric),
105
+ subject: encodeKey(i.subject),
106
+ ...(i.split !== undefined ? { split: i.split } : {}),
107
+ ...(i.value !== undefined ? { value: i.value * Math.sign(i.delta) } : {}),
108
+ delta: i.delta,
109
+ })));
110
+ },
111
+ async flush() {
112
+ await countex.flush();
113
+ },
114
+ async readCells(scope) {
115
+ const rows = await query({
116
+ scope,
117
+ timeframe: { type: "all", from: "all", to: "all" },
118
+ groupBy: ["metric", "subject", "dim:split"],
119
+ measures: ["value"],
120
+ });
121
+ const out = [];
122
+ for (const r of rows) {
123
+ if (r.count === 0 && !r.measures?.value?.sum)
124
+ continue;
125
+ const split = r.keys["dim:split"];
126
+ out.push({
127
+ metric: decodeKey(String(r.keys.metric)),
128
+ subject: decodeKey(String(r.keys.subject)),
129
+ split: split === undefined || split === null || split === "" ? null : String(split),
130
+ count: r.count,
131
+ sum: Number(r.measures?.value?.sum ?? 0),
132
+ });
133
+ }
134
+ return out;
135
+ },
136
+ async readWindow(scope, window, now) {
137
+ const hours = window === "24h" ? 24 : window === "7d" ? 7 * 24 : 30 * 24;
138
+ const from = new Date(now.getTime() - (hours - 1) * 3_600_000);
139
+ const rows = window === "24h"
140
+ ? await query({
141
+ scope,
142
+ timeframe: { type: "hour", from: hourKey(from), to: hourKey(now) },
143
+ groupBy: ["metric"],
144
+ })
145
+ : await query({
146
+ scope,
147
+ timeframe: {
148
+ type: "day",
149
+ from: dayKey(new Date(now.getTime() - (hours / 24 - 1) * 86_400_000)),
150
+ to: dayKey(now),
151
+ },
152
+ groupBy: ["metric"],
153
+ });
154
+ const out = new Map();
155
+ for (const r of rows) {
156
+ const metric = decodeKey(String(r.keys.metric));
157
+ out.set(metric, (out.get(metric) ?? 0) + r.count);
158
+ }
159
+ return out;
160
+ },
161
+ async readDaily(scope, metric, days, now) {
162
+ const rows = await query({
163
+ scope,
164
+ timeframe: {
165
+ type: "day",
166
+ from: dayKey(new Date(now.getTime() - (days - 1) * 86_400_000)),
167
+ to: dayKey(now),
168
+ },
169
+ groupBy: ["timeframeKey"],
170
+ metrics: [encodeKey(metric)],
171
+ });
172
+ return rows
173
+ .map((r) => ({ at: String(r.keys.timeframeKey), value: r.count }))
174
+ .sort((a, b) => a.at.localeCompare(b.at));
175
+ },
176
+ async shutdown() {
177
+ await countex.shutdown().catch(() => undefined);
178
+ },
179
+ };
180
+ }
181
+ //# sourceMappingURL=engine.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"engine.js","sourceRoot":"","sources":["../../src/analytics/engine.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Platform adapters for the analytics tracker: metadata views, stored-head enumeration
3
+ * for the `@datasources` backfill, and cell cleanup on rebuild.
4
+ */
5
+ import type { MongoClient } from "mongodb";
6
+ import type { UnifiedMetadataClient } from "@x12i/memorix-metadata-runtime";
7
+ import { type AnalyticsMetadataView, type HeadSource } from "./tracker.js";
8
+ export declare function createAnalyticsMetadataViews(metadata: UnifiedMetadataClient): {
9
+ viewFor(agentIds: string[]): AnalyticsMetadataView;
10
+ invalidate(): void;
11
+ };
12
+ /** Pages current heads out of the org's content databases, in `_id` order per collection. */
13
+ export declare function createMongoHeadSource(client: MongoClient): HeadSource;
14
+ export declare function dropAnalyticsCells(client: MongoClient, dbName: string, scopePrefix: string): Promise<void>;
15
+ //# sourceMappingURL=host.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"host.d.ts","sourceRoot":"","sources":["../../src/analytics/host.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAC3C,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,gCAAgC,CAAC;AAK5E,OAAO,EAAsB,KAAK,qBAAqB,EAAE,KAAK,UAAU,EAAE,MAAM,cAAc,CAAC;AAQ/F,wBAAgB,4BAA4B,CAAC,QAAQ,EAAE,qBAAqB,GAAG;IAC7E,OAAO,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,qBAAqB,CAAC;IACnD,UAAU,IAAI,IAAI,CAAC;CACpB,CAqFA;AAED,6FAA6F;AAC7F,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,WAAW,GAAG,UAAU,CA4CrE;AAMD,wBAAsB,kBAAkB,CAAC,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAKhH"}
@@ -0,0 +1,143 @@
1
+ import { databaseNameFor } from "@x12i/memorix-data";
2
+ import { catalogFromMetadataClient } from "../catalog-bridge.js";
3
+ import { resolveObjectAndContentType } from "../data-changes.js";
4
+ import { isContentCollectionName } from "../datasource-backfill.js";
5
+ import { datasourceOfRecord } from "./tracker.js";
6
+ function asCategory(v) {
7
+ return v === "event" || v === "knowledge" ? v : "entity";
8
+ }
9
+ export function createAnalyticsMetadataViews(metadata) {
10
+ const cache = new Map();
11
+ const build = (agentIds) => {
12
+ const effective = metadata.resolveEffective(agentIds).effective ?? [];
13
+ const analytics = effective.filter((e) => e.kind === "analytics").map((e) => e.definition);
14
+ const abstractProps = new Map();
15
+ const objectTypes = new Map();
16
+ for (const e of effective) {
17
+ const def = e.definition;
18
+ if (e.kind === "abstract-types") {
19
+ const props = new Map();
20
+ for (const p of Array.isArray(def.properties) ? def.properties : []) {
21
+ const prop = p;
22
+ if (typeof prop.id !== "string")
23
+ continue;
24
+ props.set(prop.id, Array.isArray(prop.enum) ? { enum: prop.enum.filter((v) => typeof v === "string") } : {});
25
+ }
26
+ abstractProps.set(String(def.id ?? e.id), props);
27
+ }
28
+ else if (e.kind === "object-types") {
29
+ const contentTypes = (Array.isArray(def.contentTypes) ? def.contentTypes : [])
30
+ .map((ct) => (typeof ct === "string" ? ct : String(ct.id ?? "")))
31
+ .filter(Boolean);
32
+ const fields = new Map();
33
+ for (const raw of Array.isArray(def.fields) ? def.fields : []) {
34
+ const field = raw;
35
+ if (typeof field.path !== "string" || !field.path.trim())
36
+ continue;
37
+ fields.set(field.path, Array.isArray(field.enum) ? { enum: field.enum.filter((v) => typeof v === "string") } : {});
38
+ }
39
+ objectTypes.set(String(def.id ?? e.id), {
40
+ name: typeof def.name === "string" && def.name.trim() ? def.name : null,
41
+ dataCategory: asCategory(def.dataCategory),
42
+ contentTypes,
43
+ fields,
44
+ });
45
+ }
46
+ }
47
+ const catalog = catalogFromMetadataClient(metadata, agentIds);
48
+ const members = new Map();
49
+ return {
50
+ analytics: () => analytics,
51
+ catalog: {
52
+ abstractProperties: (abstractType) => abstractProps.get(abstractType) ?? null,
53
+ hasObjectType: (objectType) => objectTypes.has(objectType),
54
+ contentTypes: (objectType) => objectTypes.get(objectType)?.contentTypes ?? null,
55
+ fieldEnum: (objectType, path) => objectTypes.get(objectType)?.fields.get(path)?.enum ?? null,
56
+ },
57
+ members(abstractType) {
58
+ let list = members.get(abstractType);
59
+ if (!list) {
60
+ list = (catalog.getAbstractPlan?.(abstractType)?.members ?? []).map((m) => ({
61
+ objectType: m.objectType,
62
+ contentType: m.contentType,
63
+ }));
64
+ members.set(abstractType, list);
65
+ }
66
+ return list;
67
+ },
68
+ objectTypeName: (objectType) => objectTypes.get(objectType)?.name ?? null,
69
+ dataCategoryOf: (objectType) => objectTypes.get(objectType)?.dataCategory ?? "entity",
70
+ };
71
+ };
72
+ return {
73
+ viewFor(agentIds) {
74
+ const key = [...agentIds].sort().join(",");
75
+ let v = cache.get(key);
76
+ if (!v) {
77
+ v = build(agentIds);
78
+ cache.set(key, v);
79
+ }
80
+ return v;
81
+ },
82
+ invalidate() {
83
+ cache.clear();
84
+ },
85
+ };
86
+ }
87
+ /** Pages current heads out of the org's content databases, in `_id` order per collection. */
88
+ export function createMongoHeadSource(client) {
89
+ return {
90
+ async collections(orgId) {
91
+ let objectTypes = [];
92
+ try {
93
+ objectTypes = (await client.db(databaseNameFor(orgId, "operational")).collection("record-directory").distinct("objectType")).map(String);
94
+ }
95
+ catch {
96
+ objectTypes = [];
97
+ }
98
+ const out = [];
99
+ for (const category of ["entity", "event", "knowledge"]) {
100
+ const dbName = databaseNameFor(orgId, category);
101
+ const names = await client
102
+ .db(dbName)
103
+ .listCollections({}, { nameOnly: true })
104
+ .toArray()
105
+ .catch(() => []);
106
+ for (const { name } of names) {
107
+ if (!isContentCollectionName(name))
108
+ continue;
109
+ const { objectType, contentType } = resolveObjectAndContentType(name, objectTypes);
110
+ if (!contentType)
111
+ continue;
112
+ out.push({ key: `${dbName}/${name}`, objectType, contentType });
113
+ }
114
+ }
115
+ return out.sort((a, b) => a.key.localeCompare(b.key));
116
+ },
117
+ async page(_orgId, key, afterId, limit) {
118
+ const slash = key.indexOf("/");
119
+ const coll = client.db(key.slice(0, slash)).collection(key.slice(slash + 1));
120
+ const docs = await coll
121
+ .find(afterId === null ? {} : { _id: { $gt: afterId } })
122
+ .sort({ _id: 1 })
123
+ .limit(limit)
124
+ .project({ _id: 1, recordId: 1, "_system._datasource": 1 })
125
+ .toArray();
126
+ return docs.map((d) => ({
127
+ id: String(d._id),
128
+ recordId: String(d.recordId ?? d._id),
129
+ datasource: datasourceOfRecord(d),
130
+ }));
131
+ },
132
+ };
133
+ }
134
+ function escapeRegex(s) {
135
+ return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
136
+ }
137
+ export async function dropAnalyticsCells(client, dbName, scopePrefix) {
138
+ const filter = { scopeId: { $regex: `^${escapeRegex(scopePrefix)}` } };
139
+ const db = client.db(dbName);
140
+ await db.collection("analytics_countex_cells").deleteMany(filter);
141
+ await db.collection("analytics_countex_dict").deleteMany(filter);
142
+ }
143
+ //# sourceMappingURL=host.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"host.js","sourceRoot":"","sources":["../../src/analytics/host.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,98 @@
1
+ /**
2
+ * Agent-declared property indexes. The registry and the rows live in the org operational
3
+ * database, beside the counter registry. Rows are not a Mongo index on the content collection:
4
+ * that collection is shared by every agent.
5
+ */
6
+ import type { Db } from "mongodb";
7
+ import type { BackfillProgress } from "./state.js";
8
+ export type PropertyIndexDefinition = {
9
+ id: string;
10
+ objectType: string;
11
+ contentType: string;
12
+ properties: string[];
13
+ };
14
+ export type PropertyIndexStatus = "backfilling" | "live" | "error";
15
+ export type PropertyIndexRecord = {
16
+ id: string;
17
+ orgId: string;
18
+ agentIds: string[];
19
+ definition: PropertyIndexDefinition;
20
+ hash: string;
21
+ generation: number;
22
+ status: PropertyIndexStatus;
23
+ backfill: BackfillProgress;
24
+ registeredAt: string;
25
+ updatedAt: string;
26
+ registeredBy?: string | null;
27
+ liveAt?: string | null;
28
+ error?: string | null;
29
+ };
30
+ export type IndexPredicate = {
31
+ op: "eq" | "in" | "exists";
32
+ value?: unknown;
33
+ };
34
+ export type IndexExplain = {
35
+ stages: string[];
36
+ docsExamined: number;
37
+ nReturned: number;
38
+ totalRows: number;
39
+ };
40
+ export interface PropertyIndexStore {
41
+ listIndexes(): Promise<PropertyIndexRecord[]>;
42
+ getIndex(id: string): Promise<PropertyIndexRecord | null>;
43
+ saveIndex(record: PropertyIndexRecord): Promise<void>;
44
+ patchIndex(id: string, patch: Partial<PropertyIndexRecord>, generation?: number): Promise<boolean>;
45
+ deleteIndex(id: string): Promise<void>;
46
+ writeRecord(indexId: string, generation: number, recordId: string, values: Record<string, unknown>): Promise<void>;
47
+ deleteRecord(indexId: string, generation: number, recordId: string): Promise<void>;
48
+ /** Drops rows with `generation < belowGeneration`, or every row of the index when omitted. */
49
+ dropRows(indexId: string, belowGeneration?: number): Promise<void>;
50
+ /** Every stored record for one property, in `recordId` order, including null values. */
51
+ pageRecords(args: {
52
+ indexId: string;
53
+ generation: number;
54
+ property: string;
55
+ afterRecordId: string | null;
56
+ limit: number;
57
+ }): Promise<{
58
+ recordIds: string[];
59
+ hasMore: boolean;
60
+ }>;
61
+ /** Property values for the given records. Missing properties are null. */
62
+ valuesFor(indexId: string, generation: number, recordIds: string[]): Promise<Map<string, Record<string, unknown>>>;
63
+ matchRecords(args: {
64
+ indexId: string;
65
+ generation: number;
66
+ property: string;
67
+ predicate: IndexPredicate;
68
+ afterRecordId: string | null;
69
+ limit: number;
70
+ }): Promise<{
71
+ recordIds: string[];
72
+ hasMore: boolean;
73
+ }>;
74
+ countRecords(args: {
75
+ indexId: string;
76
+ generation: number;
77
+ property: string;
78
+ predicate: IndexPredicate;
79
+ }): Promise<number>;
80
+ /** All record ids matching a predicate. Used to intersect several paths. */
81
+ recordIdsFor(args: {
82
+ indexId: string;
83
+ generation: number;
84
+ property: string;
85
+ predicate: IndexPredicate;
86
+ }): Promise<string[]>;
87
+ /** Null on the in-memory store. Mongo explains the row query, hinted onto the lookup index. */
88
+ explainMatch(args: {
89
+ indexId: string;
90
+ generation: number;
91
+ property: string;
92
+ predicate: IndexPredicate;
93
+ }): Promise<IndexExplain | null>;
94
+ }
95
+ export declare function createMemoryPropertyIndexStore(): PropertyIndexStore;
96
+ export declare function createMongoPropertyIndexStore(db: Db): PropertyIndexStore;
97
+ export declare function mongoPropertyIndexFactory(dbFor: (orgId: string) => Db): (orgId: string) => PropertyIndexStore;
98
+ //# sourceMappingURL=index-store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index-store.d.ts","sourceRoot":"","sources":["../../src/analytics/index-store.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAEnD,MAAM,MAAM,uBAAuB,GAAG;IACpC,EAAE,EAAE,MAAM,CAAC;IACX,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,EAAE,CAAC;CACtB,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG,aAAa,GAAG,MAAM,GAAG,OAAO,CAAC;AAEnE,MAAM,MAAM,mBAAmB,GAAG;IAChC,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,UAAU,EAAE,uBAAuB,CAAC;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,mBAAmB,CAAC;IAC5B,QAAQ,EAAE,gBAAgB,CAAC;IAC3B,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACvB,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG;IAC3B,EAAE,EAAE,IAAI,GAAG,IAAI,GAAG,QAAQ,CAAC;IAC3B,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG;IACzB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,MAAM,WAAW,kBAAkB;IACjC,WAAW,IAAI,OAAO,CAAC,mBAAmB,EAAE,CAAC,CAAC;IAC9C,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,mBAAmB,GAAG,IAAI,CAAC,CAAC;IAC1D,SAAS,CAAC,MAAM,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACtD,UAAU,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,CAAC,mBAAmB,CAAC,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACnG,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEvC,WAAW,CACT,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC9B,OAAO,CAAC,IAAI,CAAC,CAAC;IACjB,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACnF,8FAA8F;IAC9F,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,eAAe,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEnE,wFAAwF;IACxF,WAAW,CAAC,IAAI,EAAE;QAChB,OAAO,EAAE,MAAM,CAAC;QAChB,UAAU,EAAE,MAAM,CAAC;QACnB,QAAQ,EAAE,MAAM,CAAC;QACjB,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;QAC7B,KAAK,EAAE,MAAM,CAAC;KACf,GAAG,OAAO,CAAC;QAAE,SAAS,EAAE,MAAM,EAAE,CAAC;QAAC,OAAO,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;IAEvD,0EAA0E;IAC1E,SAAS,CACP,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,EAAE,GAClB,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC;IAEjD,YAAY,CAAC,IAAI,EAAE;QACjB,OAAO,EAAE,MAAM,CAAC;QAChB,UAAU,EAAE,MAAM,CAAC;QACnB,QAAQ,EAAE,MAAM,CAAC;QACjB,SAAS,EAAE,cAAc,CAAC;QAC1B,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;QAC7B,KAAK,EAAE,MAAM,CAAC;KACf,GAAG,OAAO,CAAC;QAAE,SAAS,EAAE,MAAM,EAAE,CAAC;QAAC,OAAO,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;IAEvD,YAAY,CAAC,IAAI,EAAE;QACjB,OAAO,EAAE,MAAM,CAAC;QAChB,UAAU,EAAE,MAAM,CAAC;QACnB,QAAQ,EAAE,MAAM,CAAC;QACjB,SAAS,EAAE,cAAc,CAAC;KAC3B,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAEpB,4EAA4E;IAC5E,YAAY,CAAC,IAAI,EAAE;QACjB,OAAO,EAAE,MAAM,CAAC;QAChB,UAAU,EAAE,MAAM,CAAC;QACnB,QAAQ,EAAE,MAAM,CAAC;QACjB,SAAS,EAAE,cAAc,CAAC;KAC3B,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IAEtB,+FAA+F;IAC/F,YAAY,CAAC,IAAI,EAAE;QACjB,OAAO,EAAE,MAAM,CAAC;QAChB,UAAU,EAAE,MAAM,CAAC;QACnB,QAAQ,EAAE,MAAM,CAAC;QACjB,SAAS,EAAE,cAAc,CAAC;KAC3B,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAAC;CAClC;AAgCD,wBAAgB,8BAA8B,IAAI,kBAAkB,CA+FnE;AAuBD,wBAAgB,6BAA6B,CAAC,EAAE,EAAE,EAAE,GAAG,kBAAkB,CA8JxE;AAED,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,EAAE,GAAG,CAAC,KAAK,EAAE,MAAM,KAAK,kBAAkB,CAU7G"}