@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 @@
1
+ {"version":3,"file":"state.d.ts","sourceRoot":"","sources":["../../src/analytics/state.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,273 @@
1
+ const clone = (v) => structuredClone(v);
2
+ export function createMemoryAnalyticsState() {
3
+ const counters = new Map();
4
+ const ledger = new Map();
5
+ const pairs = new Map();
6
+ const rowId = (counterId, generation, key) => `${counterId}#${generation}|${key}`;
7
+ return {
8
+ async listCounters() {
9
+ return [...counters.values()].map(clone);
10
+ },
11
+ async getCounter(id) {
12
+ const c = counters.get(id);
13
+ return c ? clone(c) : null;
14
+ },
15
+ async saveCounter(record) {
16
+ counters.set(record.id, clone(record));
17
+ },
18
+ async patchCounter(id, patch, generation) {
19
+ const c = counters.get(id);
20
+ if (!c || (generation !== undefined && c.generation !== generation))
21
+ return false;
22
+ Object.assign(c, clone(patch));
23
+ return true;
24
+ },
25
+ async deleteCounter(id) {
26
+ counters.delete(id);
27
+ },
28
+ async readLedger(counterId, generation, keys) {
29
+ const out = new Map();
30
+ for (const key of keys) {
31
+ const row = ledger.get(rowId(counterId, generation, key));
32
+ if (row)
33
+ out.set(key, clone(row));
34
+ }
35
+ return out;
36
+ },
37
+ async writeIntents(counterId, generation, intents, now) {
38
+ const conflicts = [];
39
+ for (const i of intents) {
40
+ const id = rowId(counterId, generation, i.key);
41
+ const row = ledger.get(id);
42
+ const seq = row ? row.seq : null;
43
+ if (seq !== i.expectedSeq) {
44
+ conflicts.push(i.key);
45
+ continue;
46
+ }
47
+ const pending = i.next ? clone(i.next) : { removed: true };
48
+ if (row) {
49
+ row.seq += 1;
50
+ row.pending = pending;
51
+ row.pendingAt = now;
52
+ }
53
+ else {
54
+ ledger.set(id, {
55
+ counterId,
56
+ generation,
57
+ key: i.key,
58
+ scope: "",
59
+ at: "",
60
+ facts: [],
61
+ track: {},
62
+ seq: 1,
63
+ pending,
64
+ pendingAt: now,
65
+ });
66
+ }
67
+ }
68
+ return conflicts;
69
+ },
70
+ async commitIntents(counterId, generation, keys) {
71
+ for (const key of keys) {
72
+ const id = rowId(counterId, generation, key);
73
+ const row = ledger.get(id);
74
+ if (!row?.pending)
75
+ continue;
76
+ if ("removed" in row.pending) {
77
+ ledger.delete(id);
78
+ continue;
79
+ }
80
+ Object.assign(row, row.pending, { pending: null, pendingAt: null });
81
+ }
82
+ },
83
+ async stalePending(olderThan) {
84
+ const out = new Set();
85
+ for (const row of ledger.values()) {
86
+ if (row.pending && row.pendingAt && Date.parse(row.pendingAt) < olderThan.getTime()) {
87
+ out.add(row.counterId);
88
+ }
89
+ }
90
+ return [...out];
91
+ },
92
+ async dropGenerations(counterId, belowGeneration) {
93
+ for (const [id, row] of ledger) {
94
+ if (row.counterId === counterId && (belowGeneration === undefined || row.generation < belowGeneration)) {
95
+ ledger.delete(id);
96
+ }
97
+ }
98
+ for (const [id, row] of pairs) {
99
+ if (row.counterId === counterId && (belowGeneration === undefined || row.generation < belowGeneration)) {
100
+ pairs.delete(id);
101
+ }
102
+ }
103
+ },
104
+ async touchPair(row) {
105
+ const known = pairs.get(row.scope);
106
+ if (known) {
107
+ if (row.firstSeenAt < known.firstSeenAt)
108
+ known.firstSeenAt = row.firstSeenAt;
109
+ return false;
110
+ }
111
+ pairs.set(row.scope, clone(row));
112
+ return true;
113
+ },
114
+ async listPairs(counterId, generation, limit) {
115
+ return [...pairs.values()]
116
+ .filter((p) => p.counterId === counterId && p.generation === generation)
117
+ .sort((a, b) => b.firstSeenAt.localeCompare(a.firstSeenAt) || b.scope.localeCompare(a.scope))
118
+ .slice(0, limit)
119
+ .map(clone);
120
+ },
121
+ };
122
+ }
123
+ function isDuplicateKey(err) {
124
+ return Boolean(err && typeof err === "object" && err.code === 11000);
125
+ }
126
+ export function createMongoAnalyticsState(db) {
127
+ const countersCol = db.collection("analytics_counters");
128
+ const ledgerCol = db.collection("analytics_subject_state");
129
+ const pairsCol = db.collection("analytics_pairs");
130
+ let indexed = null;
131
+ const ensureIndexes = () => (indexed ??= Promise.all([
132
+ ledgerCol.createIndex({ counterId: 1, generation: 1 }),
133
+ ledgerCol.createIndex({ pendingAt: 1 }, { sparse: true }),
134
+ pairsCol.createIndex({ counterId: 1, generation: 1, firstSeenAt: -1 }),
135
+ ]).then(() => undefined));
136
+ const rowId = (counterId, generation, key) => `${counterId}#${generation}|${key}`;
137
+ const strip = (doc) => {
138
+ const { _id, ...rest } = doc;
139
+ void _id;
140
+ return rest;
141
+ };
142
+ return {
143
+ async listCounters() {
144
+ return (await countersCol.find({}).toArray()).map((d) => strip(d));
145
+ },
146
+ async getCounter(id) {
147
+ const d = await countersCol.findOne({ _id: id });
148
+ return d ? strip(d) : null;
149
+ },
150
+ async saveCounter(record) {
151
+ await countersCol.replaceOne({ _id: record.id }, record, { upsert: true });
152
+ },
153
+ async patchCounter(id, patch, generation) {
154
+ const { id: _ignored, ...fields } = patch;
155
+ void _ignored;
156
+ const res = await countersCol.updateOne(generation === undefined ? { _id: id } : { _id: id, generation }, { $set: fields });
157
+ return res.matchedCount > 0;
158
+ },
159
+ async deleteCounter(id) {
160
+ await countersCol.deleteOne({ _id: id });
161
+ },
162
+ async readLedger(counterId, generation, keys) {
163
+ await ensureIndexes();
164
+ const out = new Map();
165
+ if (keys.length === 0)
166
+ return out;
167
+ const docs = await ledgerCol
168
+ .find({ _id: { $in: keys.map((k) => rowId(counterId, generation, k)) } })
169
+ .toArray();
170
+ for (const d of docs)
171
+ out.set(d.key, strip(d));
172
+ return out;
173
+ },
174
+ async writeIntents(counterId, generation, intents, now) {
175
+ await ensureIndexes();
176
+ const conflicts = [];
177
+ for (const i of intents) {
178
+ const _id = rowId(counterId, generation, i.key);
179
+ const pending = i.next ?? { removed: true };
180
+ if (i.expectedSeq === null) {
181
+ try {
182
+ await ledgerCol.insertOne({
183
+ _id,
184
+ counterId,
185
+ generation,
186
+ key: i.key,
187
+ scope: "",
188
+ at: "",
189
+ facts: [],
190
+ track: {},
191
+ seq: 1,
192
+ pending,
193
+ pendingAt: now,
194
+ });
195
+ }
196
+ catch (err) {
197
+ if (!isDuplicateKey(err))
198
+ throw err;
199
+ conflicts.push(i.key);
200
+ }
201
+ continue;
202
+ }
203
+ const res = await ledgerCol.updateOne({ _id, seq: i.expectedSeq }, { $set: { pending, pendingAt: now }, $inc: { seq: 1 } });
204
+ if (res.matchedCount === 0)
205
+ conflicts.push(i.key);
206
+ }
207
+ return conflicts;
208
+ },
209
+ async commitIntents(counterId, generation, keys) {
210
+ if (keys.length === 0)
211
+ return;
212
+ const ids = keys.map((k) => rowId(counterId, generation, k));
213
+ await ledgerCol.deleteMany({ _id: { $in: ids }, "pending.removed": true });
214
+ await ledgerCol.updateMany({ _id: { $in: ids }, pending: { $type: "object" } }, [
215
+ {
216
+ $set: {
217
+ scope: "$pending.scope",
218
+ at: "$pending.at",
219
+ facts: "$pending.facts",
220
+ track: "$pending.track",
221
+ },
222
+ },
223
+ { $unset: ["pending", "pendingAt"] },
224
+ ]);
225
+ },
226
+ async stalePending(olderThan) {
227
+ await ensureIndexes();
228
+ const ids = await ledgerCol.distinct("counterId", {
229
+ pendingAt: { $lt: olderThan.toISOString() },
230
+ });
231
+ return ids.map(String);
232
+ },
233
+ async dropGenerations(counterId, belowGeneration) {
234
+ const filter = belowGeneration === undefined ? { counterId } : { counterId, generation: { $lt: belowGeneration } };
235
+ await ledgerCol.deleteMany(filter);
236
+ await pairsCol.deleteMany(filter);
237
+ },
238
+ async touchPair(row) {
239
+ await ensureIndexes();
240
+ const { firstSeenAt, ...rest } = row;
241
+ try {
242
+ const res = await pairsCol.updateOne({ _id: row.scope }, { $min: { firstSeenAt }, $setOnInsert: rest }, { upsert: true });
243
+ return res.upsertedCount > 0;
244
+ }
245
+ catch (err) {
246
+ if (isDuplicateKey(err))
247
+ return false;
248
+ throw err;
249
+ }
250
+ },
251
+ async listPairs(counterId, generation, limit) {
252
+ await ensureIndexes();
253
+ const docs = await pairsCol
254
+ .find({ counterId, generation })
255
+ .sort({ firstSeenAt: -1, _id: -1 })
256
+ .limit(limit)
257
+ .toArray();
258
+ return docs.map((d) => strip(d));
259
+ },
260
+ };
261
+ }
262
+ export function mongoAnalyticsStateFactory(dbFor) {
263
+ const cache = new Map();
264
+ return (orgId) => {
265
+ let s = cache.get(orgId);
266
+ if (!s) {
267
+ s = createMongoAnalyticsState(dbFor(orgId));
268
+ cache.set(orgId, s);
269
+ }
270
+ return s;
271
+ };
272
+ }
273
+ //# sourceMappingURL=state.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"state.js","sourceRoot":"","sources":["../../src/analytics/state.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,215 @@
1
+ /**
2
+ * Keeps registered counters current.
3
+ *
4
+ * Every write through the shared writer enqueues the touched subject. A reconcile reads the
5
+ * subject's current abstract projection, diffs it with the facts the ledger last counted,
6
+ * and emits only the -old / +new increments. Ledger rows stay pending until the Countex
7
+ * flush carrying their increments succeeds; a row left pending by a crashed process makes
8
+ * the counter rebuild, because Countex does not persist event ids across processes.
9
+ */
10
+ import type { ListContentQuery, MemorixAbstractWriter, MemorixContentReader, MemorixContentWriter, QueryFilter } from "@x12i/memorix-data";
11
+ import type { MemorixScope } from "../scope.js";
12
+ import { type CounterCatalog } from "./definition.js";
13
+ import { type AnalyticsCountex } from "./engine.js";
14
+ import { type SubjectDatasource } from "./projector.js";
15
+ import { type PropertyIndexStore } from "./index-store.js";
16
+ import type { AnalyticsStateStore, CounterOrigin, CounterRecord } from "./state.js";
17
+ /** Datasource service stamped on materialized records; writes carrying it are not counted. */
18
+ export declare const ANALYTICS_DATASOURCE_SERVICE = "memorix-analytics";
19
+ /** Built-in organization-wide census of current heads by data source. */
20
+ export declare const DATASOURCES_COUNTER_ID = "@datasources";
21
+ export type AnalyticsMetadataView = {
22
+ /** Raw `analytics` definitions visible to these agents (pack analytics[] items). */
23
+ analytics(): unknown[];
24
+ catalog: CounterCatalog;
25
+ /** Concrete members (objectType + contentType) of an abstract type. */
26
+ members(abstractType: string): Array<{
27
+ objectType: string;
28
+ contentType: string;
29
+ }>;
30
+ objectTypeName(objectType: string): string | null;
31
+ dataCategoryOf(objectType: string): "entity" | "event" | "knowledge";
32
+ };
33
+ export type HeadCollection = {
34
+ key: string;
35
+ objectType: string;
36
+ contentType: string;
37
+ };
38
+ export type HeadRow = {
39
+ id: string;
40
+ recordId: string;
41
+ datasource: SubjectDatasource | null;
42
+ };
43
+ /** Enumerates stored heads for the one-time `@datasources` backfill. */
44
+ export type HeadSource = {
45
+ collections(orgId: string): Promise<HeadCollection[]>;
46
+ page(orgId: string, key: string, afterId: string | null, limit: number): Promise<HeadRow[]>;
47
+ };
48
+ export type WriteEvent = {
49
+ objectType: string;
50
+ contentType: string;
51
+ recordId: string;
52
+ datasourceService?: string;
53
+ };
54
+ export type AnalyticsTrackerOptions = {
55
+ engine: AnalyticsCountex;
56
+ stateFor(orgId: string): AnalyticsStateStore;
57
+ metadataFor(agentIds: string[]): AnalyticsMetadataView;
58
+ portsFor(scope: MemorixScope): {
59
+ reader: MemorixContentReader;
60
+ writer: MemorixContentWriter;
61
+ };
62
+ /** Property indexes. Defaults to an in-memory store per org (tests). Mongo passes its own. */
63
+ indexesFor?(orgId: string): PropertyIndexStore;
64
+ /** Deletes Countex cells whose scope starts with the prefix (rebuild / unregister). */
65
+ dropCells?(orgId: string, scopePrefix: string): Promise<void>;
66
+ heads?: HeadSource | null;
67
+ /** Disable the built-in `@datasources` census. */
68
+ datasources?: boolean;
69
+ debounceMs?: number;
70
+ batchMs?: number;
71
+ pendingStaleMs?: number;
72
+ backfillPageSize?: number;
73
+ refreshMs?: number;
74
+ now?: () => Date;
75
+ log?: (message: string, extra?: Record<string, unknown>) => void;
76
+ };
77
+ export type SourceCensusKind = {
78
+ kind: string;
79
+ label: string;
80
+ count: number;
81
+ };
82
+ export type SourceCensusSystem = {
83
+ system: string;
84
+ name: string;
85
+ total: number;
86
+ kinds: SourceCensusKind[];
87
+ };
88
+ export type SourceCensusPayload = {
89
+ ok: true;
90
+ censusId: string | null;
91
+ timestamp: string;
92
+ status: "live" | "backfilling" | "error" | "disabled";
93
+ subjects: SourceCensusSystem[];
94
+ heads: SourceCensusSystem[];
95
+ };
96
+ export type MaterializeResult = {
97
+ materialized: boolean;
98
+ recordId: string | null;
99
+ historyRecordId: string | null;
100
+ status: CounterRecord["status"] | "missing";
101
+ };
102
+ /** Attribution order: `sources[0]`, then the declared `origin`, then the writing `service`. */
103
+ export declare function datasourceOfRecord(record: unknown): SubjectDatasource | null;
104
+ export declare class AnalyticsTracker {
105
+ private readonly o;
106
+ private readonly orgs;
107
+ private readonly orgInit;
108
+ private readonly queue;
109
+ private drainTimer;
110
+ private chain;
111
+ private readonly dirty;
112
+ private readonly backfills;
113
+ private readonly inflight;
114
+ private readonly memoryIndexes;
115
+ private readonly indexes;
116
+ private closed;
117
+ constructor(options: AnalyticsTrackerOptions);
118
+ private indexStore;
119
+ private now;
120
+ private log;
121
+ private track;
122
+ private serial;
123
+ private counters;
124
+ private reload;
125
+ /** Loads the org registry so target content types are readable before a content request. */
126
+ prepare(orgId: string): Promise<void>;
127
+ private syncGrants;
128
+ private ensureOrg;
129
+ private initOrg;
130
+ private recoverPending;
131
+ /** Called by the writer decorator after every successful write or remove. */
132
+ onWrite(scope: MemorixScope, event: WriteEvent): void;
133
+ private fanOut;
134
+ private taskKey;
135
+ private enqueue;
136
+ private scheduleDrain;
137
+ private drain;
138
+ private retry;
139
+ private applyEntries;
140
+ private subjectEntry;
141
+ private loadSubject;
142
+ private toSubject;
143
+ private processAbstract;
144
+ private subjectFromStored;
145
+ private loadContentSubject;
146
+ private processContent;
147
+ private headEntry;
148
+ private processHeads;
149
+ sourceCensus(scope: MemorixScope): Promise<SourceCensusPayload>;
150
+ /** Registers (or updates) the analytics[] items of the scope's installed packs. */
151
+ syncPack(scope: MemorixScope): Promise<void>;
152
+ validate(scope: MemorixScope, raw: unknown): import("./definition.js").CounterValidationIssue[];
153
+ register(scope: MemorixScope, raw: unknown, opts: {
154
+ origin: Exclude<CounterOrigin, "builtin">;
155
+ replace?: boolean;
156
+ registeredBy?: string | null;
157
+ }): Promise<CounterRecord>;
158
+ unregister(orgId: string, id: string, opts?: {
159
+ allowPack?: boolean;
160
+ }): Promise<boolean>;
161
+ /**
162
+ * Data-source stamps changed outside the writer (datasource backfill): rebuild the counters
163
+ * that count by `@datasource`, including the built-in census. Returns their ids.
164
+ */
165
+ datasourcesRestamped(orgId: string): Promise<string[]>;
166
+ rebuild(orgId: string, id: string): Promise<CounterRecord>;
167
+ private rebuildInternal;
168
+ /** A live index replaces the scan for counters of the same agent that read only its paths. */
169
+ private rebuildFromIndex;
170
+ private dropGeneration;
171
+ list(scope: MemorixScope): Promise<CounterRecord[]>;
172
+ get(scope: MemorixScope, id: string): Promise<CounterRecord | null>;
173
+ validateIndex(scope: MemorixScope, raw: unknown): import("./definition.js").CounterValidationIssue[];
174
+ registerIndex(scope: MemorixScope, raw: unknown, opts?: {
175
+ replace?: boolean;
176
+ registeredBy?: string | null;
177
+ }): Promise<import("./index-store.js").PropertyIndexRecord>;
178
+ listIndexes(scope: MemorixScope): Promise<import("./index-store.js").PropertyIndexRecord[]>;
179
+ getIndex(scope: MemorixScope, id: string): Promise<import("./index-store.js").PropertyIndexRecord | null>;
180
+ deleteIndex(scope: MemorixScope, id: string): Promise<boolean>;
181
+ countIndexed(scope: MemorixScope, query: {
182
+ objectType: string;
183
+ contentType: string;
184
+ filters?: QueryFilter[];
185
+ }): Promise<number | null>;
186
+ explainIndexed(scope: MemorixScope, query: {
187
+ objectType: string;
188
+ contentType: string;
189
+ filters?: QueryFilter[];
190
+ }): Promise<import("./index-store.js").IndexExplain | null>;
191
+ listFromIndex(scope: MemorixScope, query: ListContentQuery, reader: MemorixContentReader): Promise<import("@x12i/memorix-data").ListContentResult | null>;
192
+ private startBackfill;
193
+ private runBackfill;
194
+ private markDirty;
195
+ /**
196
+ * Materializes the counter now (pipeline step). With covering-scope values, that pair's
197
+ * history slot is rewritten as well as the current record.
198
+ */
199
+ materializeNow(scope: MemorixScope, id: string, scopeValues?: Record<string, unknown>): Promise<MaterializeResult>;
200
+ /** Publishes an all-`produced: false` body while the counter backfills. Never awaited: callers may hold the chain. */
201
+ private writePlaceholder;
202
+ private materialize;
203
+ private emptyLeaders;
204
+ private leaders;
205
+ private trends;
206
+ private writeRecord;
207
+ /** Resolves once queued reconciles, backfills, and debounced materializations have run. */
208
+ idle(timeoutMs?: number): Promise<void>;
209
+ close(): Promise<void>;
210
+ }
211
+ /** Wraps the shared content writer so every successful write reaches the tracker. */
212
+ export declare function withAnalyticsTracking(writer: MemorixContentWriter, onWrite: (scope: MemorixScope, event: WriteEvent) => void): MemorixContentWriter;
213
+ /** Abstract reverse-writes go through their own concrete writer; report them too. */
214
+ export declare function withAbstractTracking(abstractWriter: MemorixAbstractWriter, onWrite: (scope: MemorixScope, event: WriteEvent) => void): MemorixAbstractWriter;
215
+ //# sourceMappingURL=tracker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tracker.d.ts","sourceRoot":"","sources":["../../src/analytics/tracker.ts"],"names":[],"mappings":"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"}