@catalyst-cloud/sdk 0.2.0 → 0.3.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/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/dist/live-sync-client.d.ts +18 -0
- package/dist/live-sync-client.d.ts.map +1 -1
- package/dist/live-sync-client.js +43 -2
- package/dist/live-sync-client.js.map +1 -1
- package/dist/node.d.ts +1 -0
- package/dist/node.d.ts.map +1 -1
- package/dist/node.js +4 -0
- package/dist/node.js.map +1 -1
- package/dist/otel.d.ts +166 -0
- package/dist/otel.d.ts.map +1 -0
- package/dist/otel.js +249 -0
- package/dist/otel.js.map +1 -0
- package/dist/replica/catalyst-replica.d.ts +55 -0
- package/dist/replica/catalyst-replica.d.ts.map +1 -1
- package/dist/replica/catalyst-replica.js +203 -45
- package/dist/replica/catalyst-replica.js.map +1 -1
- package/dist/replica/writer-lock.d.ts +7 -0
- package/dist/replica/writer-lock.d.ts.map +1 -1
- package/dist/replica/writer-lock.js +23 -13
- package/dist/replica/writer-lock.js.map +1 -1
- package/package.json +10 -1
package/dist/otel.js
ADDED
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
// @catalyst-cloud/sdk — guarded, zero-hard-dep OpenTelemetry seam (CTC-138).
|
|
2
|
+
//
|
|
3
|
+
// `@opentelemetry/api` is an OPTIONAL peer dependency. This module is the ONE place the SDK touches
|
|
4
|
+
// it, and it does so through a guarded **dynamic** import resolved once during the async `start()`
|
|
5
|
+
// path — never a static top-level `import`. That distinction is load-bearing:
|
|
6
|
+
//
|
|
7
|
+
// • A static `import { trace, metrics } from "@opentelemetry/api"` fails MODULE RESOLUTION when a
|
|
8
|
+
// consumer hasn't installed the package → a hard dependency in practice. The api package's
|
|
9
|
+
// built-in no-op tracer/meter only save you AFTER it has been resolved (i.e. when it's installed
|
|
10
|
+
// but no provider is registered); they do nothing for "not installed at all".
|
|
11
|
+
// • The guarded `await import("@opentelemetry/api")` here catches the resolution failure and falls
|
|
12
|
+
// back to hand-rolled no-op stubs, so the SDK imports + runs with the package entirely ABSENT.
|
|
13
|
+
//
|
|
14
|
+
// When the package IS present and the consumer has registered a global TracerProvider/MeterProvider,
|
|
15
|
+
// spans + metrics route through `trace.getTracer()` / `metrics.getMeter()` — so the consumer's
|
|
16
|
+
// Resource (service.name, etc.) flows through automatically. When present but with NO provider, the
|
|
17
|
+
// api's own no-ops apply and every call is harmless.
|
|
18
|
+
//
|
|
19
|
+
// Kept free of any node-only import so the browser bundle stays clean; the public surfaces below are
|
|
20
|
+
// declared STRUCTURALLY (no `@opentelemetry/api` type import) so no OTel type leaks into the package's
|
|
21
|
+
// generated `.d.ts`, and the whole seam tree-shakes away (package.json `sideEffects:false`) when
|
|
22
|
+
// telemetry is off.
|
|
23
|
+
/** The shared `catalyst.*` semconv attribute keys emitted across spans + metrics. */
|
|
24
|
+
export const CATALYST_ATTR = {
|
|
25
|
+
/** The tenant id (= mirror/account name). */
|
|
26
|
+
tenant: "catalyst.tenant",
|
|
27
|
+
/** The upstream system a row originates from: `"linear"` | `"github"`. */
|
|
28
|
+
source: "catalyst.source",
|
|
29
|
+
/** The durable change-feed cursor (last applied seq). */
|
|
30
|
+
cursor: "catalyst.replica.cursor",
|
|
31
|
+
/** head_seq − cursor (mirror lag in seqs), when head_seq is known. */
|
|
32
|
+
lagSeq: "catalyst.replica.lag_seq",
|
|
33
|
+
/** The connection lifecycle status string. */
|
|
34
|
+
status: "catalyst.replica.status",
|
|
35
|
+
/** Rows applied during a seed. */
|
|
36
|
+
rowCount: "catalyst.replica.row_count",
|
|
37
|
+
/** Rows in one seed apply-batch. */
|
|
38
|
+
batchRows: "catalyst.replica.batch_rows",
|
|
39
|
+
};
|
|
40
|
+
/** Metric instrument names (OTel metric stream names). */
|
|
41
|
+
export const REPLICA_METRIC = {
|
|
42
|
+
cursor: "catalyst.replica.cursor",
|
|
43
|
+
lagSeq: "catalyst.replica.lag_seq",
|
|
44
|
+
freshnessMs: "catalyst.replica.freshness_ms",
|
|
45
|
+
status: "catalyst.replica.status",
|
|
46
|
+
applied: "catalyst.replica.applied",
|
|
47
|
+
applyBatchRows: "catalyst.replica.apply_batch_rows",
|
|
48
|
+
};
|
|
49
|
+
/** Span names. */
|
|
50
|
+
export const REPLICA_SPAN = {
|
|
51
|
+
seed: "catalyst.replica.seed",
|
|
52
|
+
applyBatch: "catalyst.replica.apply_batch",
|
|
53
|
+
resync: "catalyst.replica.resync",
|
|
54
|
+
reconnect: "catalyst.replica.reconnect",
|
|
55
|
+
};
|
|
56
|
+
/** `LiveSyncStatus` → a numeric gauge code (the `catalyst.replica.status` gauge value). */
|
|
57
|
+
export const REPLICA_STATUS_CODE = {
|
|
58
|
+
connecting: 0,
|
|
59
|
+
live: 1,
|
|
60
|
+
reconnecting: 2,
|
|
61
|
+
resyncing: 3,
|
|
62
|
+
error: 4,
|
|
63
|
+
stopped: 5,
|
|
64
|
+
};
|
|
65
|
+
/** The default instrumentation-scope name for both the tracer and the meter. */
|
|
66
|
+
export const DEFAULT_SCOPE_NAME = "@catalyst-cloud/sdk";
|
|
67
|
+
/** The mirror entities sourced from GitHub (the rest are Linear) — drives the `catalyst.source` attr. */
|
|
68
|
+
const GITHUB_ENTITIES = new Set([
|
|
69
|
+
"pull_requests",
|
|
70
|
+
"check_runs",
|
|
71
|
+
"commit_statuses",
|
|
72
|
+
"reviews",
|
|
73
|
+
]);
|
|
74
|
+
/** Map a change-feed `entity` (table name) to its upstream source system, for `catalyst.source`. */
|
|
75
|
+
export function entitySource(entity) {
|
|
76
|
+
return GITHUB_ENTITIES.has(entity) ? "github" : "linear";
|
|
77
|
+
}
|
|
78
|
+
// ── No-op implementation (used when telemetry is OFF or `@opentelemetry/api` is absent). ───────────
|
|
79
|
+
const NOOP_SPAN_HANDLE = { setAttribute() { } };
|
|
80
|
+
const NOOP_MANUAL_SPAN = { setAttribute() { }, end() { } };
|
|
81
|
+
const NOOP_REGISTRATION = { remove() { } };
|
|
82
|
+
const NOOP_COUNTER = { add() { } };
|
|
83
|
+
const NOOP_HISTOGRAM = { record() { } };
|
|
84
|
+
/** A telemetry that does nothing but still threads the callback's return value through `withActiveSpan*`. */
|
|
85
|
+
export const NOOP_TELEMETRY = {
|
|
86
|
+
enabled: false,
|
|
87
|
+
withActiveSpan: (_name, _attributes, fn) => fn(NOOP_SPAN_HANDLE),
|
|
88
|
+
withActiveSpanSync: (_name, _attributes, fn) => fn(NOOP_SPAN_HANDLE),
|
|
89
|
+
startSpan: () => NOOP_MANUAL_SPAN,
|
|
90
|
+
observableGauge: () => NOOP_REGISTRATION,
|
|
91
|
+
counter: () => NOOP_COUNTER,
|
|
92
|
+
histogram: () => NOOP_HISTOGRAM,
|
|
93
|
+
};
|
|
94
|
+
/** Drop `undefined`-valued attributes (OTel rejects them) → a clean attribute record. */
|
|
95
|
+
function cleanAttrs(attributes) {
|
|
96
|
+
const out = {};
|
|
97
|
+
if (!attributes)
|
|
98
|
+
return out;
|
|
99
|
+
for (const [k, v] of Object.entries(attributes)) {
|
|
100
|
+
if (v !== undefined)
|
|
101
|
+
out[k] = v;
|
|
102
|
+
}
|
|
103
|
+
return out;
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Build a REAL telemetry facade over a resolved `@opentelemetry/api` surface (or the NO-OP when
|
|
107
|
+
* `api` is null — the "package absent" branch). Exported (but NOT re-exported from the package
|
|
108
|
+
* entrypoints) so it can be unit-tested directly with `null` for the absent case.
|
|
109
|
+
*/
|
|
110
|
+
export function buildTelemetry(api, names) {
|
|
111
|
+
if (!api)
|
|
112
|
+
return NOOP_TELEMETRY;
|
|
113
|
+
const tracer = api.trace.getTracer(names.tracerName);
|
|
114
|
+
const meter = api.metrics.getMeter(names.meterName);
|
|
115
|
+
const OK = api.SpanStatusCode.OK;
|
|
116
|
+
const ERROR = api.SpanStatusCode.ERROR;
|
|
117
|
+
const endSpan = (span, error) => {
|
|
118
|
+
if (error !== undefined) {
|
|
119
|
+
span.recordException(error);
|
|
120
|
+
span.setStatus({ code: ERROR, message: error instanceof Error ? error.message : String(error) });
|
|
121
|
+
}
|
|
122
|
+
else {
|
|
123
|
+
span.setStatus({ code: OK });
|
|
124
|
+
}
|
|
125
|
+
span.end();
|
|
126
|
+
};
|
|
127
|
+
const handleFor = (span) => ({
|
|
128
|
+
setAttribute: (k, v) => {
|
|
129
|
+
span.setAttribute(k, v);
|
|
130
|
+
},
|
|
131
|
+
});
|
|
132
|
+
return {
|
|
133
|
+
enabled: true,
|
|
134
|
+
withActiveSpan(name, attributes, fn) {
|
|
135
|
+
return tracer.startActiveSpan(name, { attributes: cleanAttrs(attributes) }, async (span) => {
|
|
136
|
+
try {
|
|
137
|
+
const result = await fn(handleFor(span));
|
|
138
|
+
endSpan(span);
|
|
139
|
+
return result;
|
|
140
|
+
}
|
|
141
|
+
catch (err) {
|
|
142
|
+
endSpan(span, err);
|
|
143
|
+
throw err;
|
|
144
|
+
}
|
|
145
|
+
});
|
|
146
|
+
},
|
|
147
|
+
withActiveSpanSync(name, attributes, fn) {
|
|
148
|
+
return tracer.startActiveSpan(name, { attributes: cleanAttrs(attributes) }, (span) => {
|
|
149
|
+
try {
|
|
150
|
+
const result = fn(handleFor(span));
|
|
151
|
+
endSpan(span);
|
|
152
|
+
return result;
|
|
153
|
+
}
|
|
154
|
+
catch (err) {
|
|
155
|
+
endSpan(span, err);
|
|
156
|
+
throw err;
|
|
157
|
+
}
|
|
158
|
+
});
|
|
159
|
+
},
|
|
160
|
+
startSpan(name, attributes) {
|
|
161
|
+
const span = tracer.startSpan(name, { attributes: cleanAttrs(attributes) });
|
|
162
|
+
return {
|
|
163
|
+
setAttribute: (k, v) => {
|
|
164
|
+
span.setAttribute(k, v);
|
|
165
|
+
},
|
|
166
|
+
end: (error) => endSpan(span, error),
|
|
167
|
+
};
|
|
168
|
+
},
|
|
169
|
+
observableGauge(name, options, callback) {
|
|
170
|
+
const gauge = meter.createObservableGauge(name, options);
|
|
171
|
+
const cb = (result) => {
|
|
172
|
+
callback({ observe: (value, attrs) => result.observe(value, cleanAttrs(attrs)) });
|
|
173
|
+
};
|
|
174
|
+
gauge.addCallback(cb);
|
|
175
|
+
return { remove: () => gauge.removeCallback(cb) };
|
|
176
|
+
},
|
|
177
|
+
counter(name, options) {
|
|
178
|
+
const instrument = meter.createCounter(name, options);
|
|
179
|
+
return { add: (value, attrs) => instrument.add(value, cleanAttrs(attrs)) };
|
|
180
|
+
},
|
|
181
|
+
histogram(name, options) {
|
|
182
|
+
const instrument = meter.createHistogram(name, options);
|
|
183
|
+
return { record: (value, attrs) => instrument.record(value, cleanAttrs(attrs)) };
|
|
184
|
+
},
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
// ── The guarded one-time dynamic import. ──────────────────────────────────────────────────────────
|
|
188
|
+
let apiPromise;
|
|
189
|
+
let warnedAbsent = false;
|
|
190
|
+
/** Dynamic-import `@opentelemetry/api` ONCE (cached). Resolves to its surface, or `null` if the
|
|
191
|
+
* package isn't installed — the catch is what makes it a TRUE optional peer dependency. */
|
|
192
|
+
async function loadOtelApi() {
|
|
193
|
+
if (apiPromise === undefined) {
|
|
194
|
+
apiPromise = import("@opentelemetry/api").then((mod) => {
|
|
195
|
+
// The named exports (trace/metrics/SpanStatusCode) may sit on the module namespace OR on
|
|
196
|
+
// `default`, depending on the CJS/ESM interop (node vs a bundler/test runner). Pick whichever
|
|
197
|
+
// object actually carries them rather than guessing `default ?? mod`.
|
|
198
|
+
const hasApi = (o) => typeof o === "object" &&
|
|
199
|
+
o !== null &&
|
|
200
|
+
"trace" in o &&
|
|
201
|
+
"metrics" in o &&
|
|
202
|
+
"SpanStatusCode" in o;
|
|
203
|
+
const ns = mod;
|
|
204
|
+
if (hasApi(mod))
|
|
205
|
+
return mod;
|
|
206
|
+
if (hasApi(ns.default))
|
|
207
|
+
return ns.default;
|
|
208
|
+
return null;
|
|
209
|
+
}, () => null);
|
|
210
|
+
}
|
|
211
|
+
return apiPromise;
|
|
212
|
+
}
|
|
213
|
+
/** True iff `value` is an already-resolved {@link Telemetry} (internal pass-through, e.g. a replica
|
|
214
|
+
* sharing its instance with the transport) rather than a {@link TelemetryConfig}. */
|
|
215
|
+
function isTelemetry(value) {
|
|
216
|
+
return (typeof value === "object" &&
|
|
217
|
+
value !== null &&
|
|
218
|
+
typeof value.withActiveSpan === "function");
|
|
219
|
+
}
|
|
220
|
+
/**
|
|
221
|
+
* Resolve the opt-in `telemetry` option into a {@link Telemetry}. Defaults to {@link NOOP_TELEMETRY}
|
|
222
|
+
* (no dynamic import attempted) when undefined/false so the off path is truly zero-overhead. When ON,
|
|
223
|
+
* guard-imports `@opentelemetry/api`; if absent, warns once and falls back to no-op (never throws). An
|
|
224
|
+
* already-resolved `Telemetry` is returned as-is so a replica + its transport share ONE instance.
|
|
225
|
+
*/
|
|
226
|
+
export async function createTelemetry(config, defaults) {
|
|
227
|
+
if (isTelemetry(config))
|
|
228
|
+
return config;
|
|
229
|
+
if (config === undefined || config === false)
|
|
230
|
+
return NOOP_TELEMETRY;
|
|
231
|
+
const names = config === true
|
|
232
|
+
? defaults
|
|
233
|
+
: {
|
|
234
|
+
tracerName: config.tracerName ?? defaults.tracerName,
|
|
235
|
+
meterName: config.meterName ?? defaults.meterName,
|
|
236
|
+
};
|
|
237
|
+
const api = await loadOtelApi();
|
|
238
|
+
if (!api) {
|
|
239
|
+
if (!warnedAbsent) {
|
|
240
|
+
warnedAbsent = true;
|
|
241
|
+
// eslint-disable-next-line no-console
|
|
242
|
+
console.warn("[catalyst-sdk:otel] telemetry was enabled but the optional peer '@opentelemetry/api' is not " +
|
|
243
|
+
"installed — running with no-op telemetry. Install '@opentelemetry/api' to emit spans/metrics.");
|
|
244
|
+
}
|
|
245
|
+
return NOOP_TELEMETRY;
|
|
246
|
+
}
|
|
247
|
+
return buildTelemetry(api, names);
|
|
248
|
+
}
|
|
249
|
+
//# sourceMappingURL=otel.js.map
|
package/dist/otel.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"otel.js","sourceRoot":"","sources":["../src/otel.ts"],"names":[],"mappings":"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"}
|
|
@@ -2,6 +2,7 @@ import { type SqlExecutor, type IssueView, type IssueDetailView, type PullView,
|
|
|
2
2
|
import { type AuthStrategy, type LiveSyncStatus, type LogLevel, type WebSocketFactory } from "../live-sync-client.js";
|
|
3
3
|
import { type EngineFactory, type ReplicaEngine } from "./engine.js";
|
|
4
4
|
import { type WriterGuardOptions } from "./writer-lock.js";
|
|
5
|
+
import { type TelemetryConfig } from "../otel.js";
|
|
5
6
|
export interface CatalystReplicaOptions {
|
|
6
7
|
/** http(s) origin incl. any path prefix (…/api/v1); the scheme is swapped to ws(s) for /connect. */
|
|
7
8
|
baseUrl: string;
|
|
@@ -37,6 +38,28 @@ export interface CatalystReplicaOptions {
|
|
|
37
38
|
* `:memory:`. Default: enabled. Set `{ disabled: true }` to skip, `{ override: true }` to steal.
|
|
38
39
|
*/
|
|
39
40
|
writerGuard?: WriterGuardOptions;
|
|
41
|
+
/**
|
|
42
|
+
* If set, `start()` rejects with a clear error if it doesn't reach `live` within this many ms (e.g.
|
|
43
|
+
* a wedged cold /snapshot), AFTER cleaning up — so a supervisor can fail-fast/restart instead of
|
|
44
|
+
* hanging. Off by default.
|
|
45
|
+
*/
|
|
46
|
+
startTimeoutMs?: number;
|
|
47
|
+
/**
|
|
48
|
+
* Opt-in OpenTelemetry (CTC-138). `false`/absent = OFF (strictly zero overhead; no
|
|
49
|
+
* `@opentelemetry/api` import is even attempted). `true` = ON with the default `@catalyst-cloud/sdk`
|
|
50
|
+
* instrumentation scope; an object overrides the tracer/meter name. When ON the replica emits:
|
|
51
|
+
* • SPANS — `catalyst.replica.seed` (snapshot pull+apply), `catalyst.replica.apply_batch` (per
|
|
52
|
+
* seed batch), plus the transport's `catalyst.replica.resync` + `catalyst.replica.reconnect`.
|
|
53
|
+
* • METRICS — observable gauges `catalyst.replica.cursor`, `catalyst.replica.lag_seq` (only when
|
|
54
|
+
* the mirror head_seq is known from the `x-catalyst-head-seq` /snapshot response header),
|
|
55
|
+
* `catalyst.replica.freshness_ms`, `catalyst.replica.status`; a `catalyst.replica.applied`
|
|
56
|
+
* counter (per live frame) and a `catalyst.replica.apply_batch_rows` histogram.
|
|
57
|
+
* All carry `catalyst.tenant` (+ `catalyst.source` where a single entity is involved). `@opentelemetry/api`
|
|
58
|
+
* is an OPTIONAL peer dep: enabling this without it installed logs once and runs no-op (never throws).
|
|
59
|
+
* Spans/metrics route through the consumer's GLOBAL TracerProvider/MeterProvider so their Resource
|
|
60
|
+
* (service.name) flows through.
|
|
61
|
+
*/
|
|
62
|
+
telemetry?: TelemetryConfig;
|
|
40
63
|
}
|
|
41
64
|
/**
|
|
42
65
|
* Options for a READ-ONLY reader ({@link CatalystReplica.openReadOnly}). A reader needs only the file
|
|
@@ -76,6 +99,19 @@ export declare class CatalystReplica {
|
|
|
76
99
|
* an initial seed failure. */
|
|
77
100
|
private liveResolve;
|
|
78
101
|
private liveReject;
|
|
102
|
+
/** Resolved once in start(); the no-op until then so any early metric/span call is safe. */
|
|
103
|
+
private telemetry;
|
|
104
|
+
/** Observable-gauge unregister handles, torn down in close() so a closed replica stops being scraped. */
|
|
105
|
+
private metricRegs;
|
|
106
|
+
/** Per-live-frame applied counter + per-seed-batch row histogram (no-op until telemetry is wired). */
|
|
107
|
+
private appliedCounter;
|
|
108
|
+
private applyBatchHistogram;
|
|
109
|
+
/** Last mirror head_seq + server clock observed from the `x-catalyst-head-seq` /snapshot headers
|
|
110
|
+
* (CTC-137), or null until seen. Drives the `lag_seq` gauge (emitted ONLY when non-null). */
|
|
111
|
+
private lastHeadSeq;
|
|
112
|
+
private lastServerTimeMs;
|
|
113
|
+
/** Wall-clock ms of the last applied delta (live frame or seed), or null. Drives `freshness_ms`. */
|
|
114
|
+
private lastAppliedAtMs;
|
|
79
115
|
constructor(opts: CatalystReplicaOptions);
|
|
80
116
|
/**
|
|
81
117
|
* Open a CatalystReplica as a READ-ONLY READER over a file another process owns as the WRITER
|
|
@@ -128,6 +164,15 @@ export declare class CatalystReplica {
|
|
|
128
164
|
get status(): LiveSyncStatus;
|
|
129
165
|
/** The raw driver Database the SDK owns — for `drizzle(replica.handle, { schema: mirrorSchema })`. */
|
|
130
166
|
get handle(): unknown;
|
|
167
|
+
/** Ms since the last applied delta (live frame or seed), or null before the first apply. The basis
|
|
168
|
+
* of the `catalyst.replica.freshness_ms` gauge — "how stale is the local copy right now". */
|
|
169
|
+
get freshnessMs(): number | null;
|
|
170
|
+
/** The last mirror head_seq read from the `x-catalyst-head-seq` /snapshot response header (CTC-137),
|
|
171
|
+
* or null if the header has never been observed. `headSeq − cursor` is the replica's lag in seqs. */
|
|
172
|
+
get headSeq(): number | null;
|
|
173
|
+
/** The mirror server clock (ms) read from the `x-catalyst-server-time-ms` /snapshot response header
|
|
174
|
+
* (CTC-137), or null if never observed — for a consumer that wants to estimate clock skew. */
|
|
175
|
+
get serverTimeMs(): number | null;
|
|
131
176
|
private resolveEngine;
|
|
132
177
|
/**
|
|
133
178
|
* Open the read-only engine and wire ONLY the read ports — no migrations, no `sync_meta` DDL, no
|
|
@@ -138,6 +183,13 @@ export declare class CatalystReplica {
|
|
|
138
183
|
private openReadOnlyInternal;
|
|
139
184
|
private handleStatus;
|
|
140
185
|
private clearLiveDeferred;
|
|
186
|
+
/**
|
|
187
|
+
* Register the four `catalyst.replica.*` observable gauges (whose async callbacks read live instance
|
|
188
|
+
* state) + create the per-frame counter and per-batch histogram. A no-op telemetry returns no-op
|
|
189
|
+
* instruments + empty registrations, so this is safe (and free) when telemetry is OFF. Idempotent
|
|
190
|
+
* per start(); the registrations are torn down in close().
|
|
191
|
+
*/
|
|
192
|
+
private registerMetrics;
|
|
141
193
|
/** Land one delta + advance the durable cursor atomically (a crash can't skip a seq), then signal. */
|
|
142
194
|
private applyFrame;
|
|
143
195
|
/**
|
|
@@ -148,6 +200,9 @@ export declare class CatalystReplica {
|
|
|
148
200
|
* atomic truncate+apply+setCursor safety without holding one giant transaction.
|
|
149
201
|
*/
|
|
150
202
|
private seedFromSnapshot;
|
|
203
|
+
/** Read CTC-137's `x-catalyst-head-seq` (+ `x-catalyst-server-time-ms`) off the /snapshot response,
|
|
204
|
+
* if present. Guarded so a header-less test fetch stand-in is a no-op. */
|
|
205
|
+
private readHeadSeqHeaders;
|
|
151
206
|
private feedHeaders;
|
|
152
207
|
}
|
|
153
208
|
//# sourceMappingURL=catalyst-replica.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"catalyst-replica.d.ts","sourceRoot":"","sources":["../../src/replica/catalyst-replica.ts"],"names":[],"mappings":"AA4BA,OAAO,EAQL,KAAK,WAAW,EAEhB,KAAK,SAAS,EACd,KAAK,eAAe,EACpB,KAAK,QAAQ,EACb,KAAK,WAAW,EAChB,KAAK,iBAAiB,EACtB,KAAK,cAAc,EACnB,KAAK,oBAAoB,EAC1B,MAAM,4BAA4B,CAAC;AAEpC,OAAO,EAGL,KAAK,YAAY,EACjB,KAAK,cAAc,EACnB,KAAK,QAAQ,EACb,KAAK,gBAAgB,EACtB,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EAGL,KAAK,aAAa,EAClB,KAAK,aAAa,EACnB,MAAM,aAAa,CAAC;AACrB,OAAO,EAEL,KAAK,kBAAkB,EAExB,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"catalyst-replica.d.ts","sourceRoot":"","sources":["../../src/replica/catalyst-replica.ts"],"names":[],"mappings":"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"}
|