@functional-systems/srcx 0.1.0-dev.1

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 (52) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/CONTRIBUTING.md +54 -0
  3. package/DESIGN.md +1057 -0
  4. package/LICENSE +202 -0
  5. package/README.md +209 -0
  6. package/RELEASING.md +137 -0
  7. package/VALIDATION.md +181 -0
  8. package/dist/build.d.ts +94 -0
  9. package/dist/build.js +433 -0
  10. package/dist/build.js.map +1 -0
  11. package/dist/chunk.d.ts +30 -0
  12. package/dist/chunk.js +296 -0
  13. package/dist/chunk.js.map +1 -0
  14. package/dist/cli.d.ts +2 -0
  15. package/dist/cli.js +276 -0
  16. package/dist/cli.js.map +1 -0
  17. package/dist/common.d.ts +17 -0
  18. package/dist/common.js +74 -0
  19. package/dist/common.js.map +1 -0
  20. package/dist/git.d.ts +38 -0
  21. package/dist/git.js +224 -0
  22. package/dist/git.js.map +1 -0
  23. package/dist/publish.d.ts +60 -0
  24. package/dist/publish.js +341 -0
  25. package/dist/publish.js.map +1 -0
  26. package/dist/releases.d.ts +8 -0
  27. package/dist/releases.js +79 -0
  28. package/dist/releases.js.map +1 -0
  29. package/dist/remote.d.ts +53 -0
  30. package/dist/remote.js +136 -0
  31. package/dist/remote.js.map +1 -0
  32. package/dist/repository.d.ts +29 -0
  33. package/dist/repository.js +180 -0
  34. package/dist/repository.js.map +1 -0
  35. package/dist/search.d.ts +46 -0
  36. package/dist/search.js +181 -0
  37. package/dist/search.js.map +1 -0
  38. package/dist/settings.d.ts +10 -0
  39. package/dist/settings.js +35 -0
  40. package/dist/settings.js.map +1 -0
  41. package/package.json +58 -0
  42. package/src/build.ts +587 -0
  43. package/src/chunk.ts +328 -0
  44. package/src/cli.ts +366 -0
  45. package/src/common.ts +71 -0
  46. package/src/git.ts +286 -0
  47. package/src/publish.ts +487 -0
  48. package/src/releases.ts +108 -0
  49. package/src/remote.ts +230 -0
  50. package/src/repository.ts +306 -0
  51. package/src/search.ts +282 -0
  52. package/src/settings.ts +59 -0
@@ -0,0 +1,341 @@
1
+ import { mkdir, rm, readFile } from "node:fs/promises";
2
+ import { join } from "node:path";
3
+ import { randomUUID } from "node:crypto";
4
+ import { atomic, canonical, hash, invariant, optionalJson, sleep, } from "./common.js";
5
+ import { corpusMetadata, records, validateBuild } from "./build.js";
6
+ import { branch, tag, one } from "./remote.js";
7
+ export function versionTag(oid) {
8
+ return `ver-${hash(oid).slice(0, 40)}`;
9
+ }
10
+ export function versionId(oid) {
11
+ return `version-${oid}`;
12
+ }
13
+ export async function exclusive(directory, work) {
14
+ await mkdir(directory, { recursive: true, mode: 0o700 });
15
+ const lock = join(directory, "writer.lock");
16
+ try {
17
+ await mkdir(lock, { mode: 0o700 });
18
+ }
19
+ catch (e) {
20
+ if (e.code === "EEXIST") {
21
+ let owner = "unknown";
22
+ try {
23
+ owner = await readFile(join(lock, "owner.json"), "utf8");
24
+ }
25
+ catch { }
26
+ throw new Error(`Collection is locked: ${lock}. Owner: ${owner.trim()}. After a crash, verify no importing process is running before removing this lock directory.`);
27
+ }
28
+ throw e;
29
+ }
30
+ try {
31
+ await atomic(join(lock, "owner.json"), {
32
+ pid: process.pid,
33
+ startedAt: new Date().toISOString(),
34
+ });
35
+ return await work();
36
+ }
37
+ finally {
38
+ await rm(lock, { recursive: true, force: true });
39
+ }
40
+ }
41
+ export function matchesManifest(doc, b, binding, attemptId) {
42
+ return (!!doc &&
43
+ doc.kind === "manifest" &&
44
+ doc.role === "corpus" &&
45
+ doc.repoId === binding.repoId &&
46
+ doc.indexId === binding.indexId &&
47
+ doc.configHash === b.configHash &&
48
+ doc.commitOid === b.commitOid &&
49
+ doc.buildId === b.buildId &&
50
+ doc.recordsHash === b.recordsHash &&
51
+ doc.inventoryHash === b.inventoryHash &&
52
+ (!attemptId || doc.attemptId === attemptId));
53
+ }
54
+ /** Exact immutable inventory/content comparison, not merely a marker/count check. */
55
+ export async function validateCandidate(store, name, b, binding, attemptId) {
56
+ const root = await one(store, tag(name), "__manifest__");
57
+ if (!matchesManifest(root, b, binding, attemptId))
58
+ return false;
59
+ const expected = new Map(Object.entries(b.recordHashes));
60
+ for (const d of corpusMetadata(b, binding.repoId, binding.indexId, attemptId))
61
+ expected.set(d.id, hash(d));
62
+ for await (const d of store.list(tag(name))) {
63
+ if (expected.get(d.id) !== hash(d))
64
+ return false;
65
+ expected.delete(d.id);
66
+ }
67
+ if (expected.size)
68
+ return false;
69
+ if (b.counts.chunks) {
70
+ let query = {
71
+ queryString: { query: "kind:chunk" },
72
+ };
73
+ for await (const d of records(b.directory)) {
74
+ if (d.kind !== "chunk")
75
+ continue;
76
+ // Keep a complete surface token: the standard analyzer may retain dots
77
+ // (e.g. code.ts), so extracting an alphanumeric substring is not a valid probe.
78
+ const term = String(d.symbol ?? d.searchText).match(/\S+/u)?.[0];
79
+ if (!term)
80
+ continue;
81
+ query = {
82
+ bool: [
83
+ {
84
+ queryString: {
85
+ query: "chunk",
86
+ defaultField: "kind",
87
+ skipSyntax: true,
88
+ },
89
+ occur: "filter",
90
+ },
91
+ {
92
+ queryString: {
93
+ query: d.fileId,
94
+ defaultField: "fileId",
95
+ skipSyntax: true,
96
+ },
97
+ occur: "filter",
98
+ },
99
+ {
100
+ queryString: {
101
+ query: term,
102
+ defaultField: "searchText",
103
+ skipSyntax: true,
104
+ },
105
+ occur: "must",
106
+ },
107
+ ],
108
+ };
109
+ break;
110
+ }
111
+ const found = await store.query(name, query, 1);
112
+ if (!found.length ||
113
+ found.some((h) => h.doc.kind !== "chunk" || b.recordHashes[h.doc.id] !== hash(h.doc)))
114
+ return false;
115
+ }
116
+ return true;
117
+ }
118
+ async function* batches(input) {
119
+ let batch = [];
120
+ let bytes = 32;
121
+ for await (const doc of input) {
122
+ const size = Buffer.byteLength(canonical(doc)) + 1;
123
+ invariant(size < 4_900_000, "Document exceeds safe request limit.");
124
+ if (batch.length >= 500 || bytes + size > 4_900_000) {
125
+ yield batch;
126
+ batch = [];
127
+ bytes = 32;
128
+ }
129
+ batch.push(doc);
130
+ bytes += size;
131
+ }
132
+ if (batch.length)
133
+ yield batch;
134
+ }
135
+ export async function published(store, binding) {
136
+ const tags = await store.tags();
137
+ const result = [];
138
+ // Control reads include accepted writes, while code reads always pin an immutable Tag.
139
+ for (const t of tags.filter((t) => t.name.startsWith("ver-"))) {
140
+ const root = await one(store, tag(t.name), "__manifest__");
141
+ if (!root ||
142
+ root.repoId !== binding.repoId ||
143
+ root.indexId !== binding.indexId ||
144
+ root.configHash !== binding.configHash)
145
+ continue;
146
+ const v = await one(store, branch("main"), versionId(String(root.commitOid)), true);
147
+ if (v?.role === "published" &&
148
+ v.tagName === t.name &&
149
+ v.snapshotId === t.snapshotId &&
150
+ v.buildId === root.buildId &&
151
+ v.attemptId === root.attemptId &&
152
+ v.recordsHash === root.recordsHash &&
153
+ v.inventoryHash === root.inventoryHash)
154
+ result.push(v);
155
+ }
156
+ return result.sort((a, b) => String(a.commitTime).localeCompare(String(b.commitTime)) ||
157
+ a.commitOid.localeCompare(b.commitOid));
158
+ }
159
+ /** Caller holds the per-collection lock for the complete import. */
160
+ export async function publish(args) {
161
+ const { store, binding, build: b, state } = args;
162
+ invariant(b.repoKey === binding.repoKey && b.configHash === binding.configHash, "Build does not belong to this index.");
163
+ invariant(!b.preset.embedding, "CLI publication currently supports only the embedding=none preset.");
164
+ await validateBuild(b);
165
+ const journalPath = join(state, "pending.json");
166
+ let j = await optionalJson(journalPath);
167
+ if (j) {
168
+ invariant(j.buildId === b.buildId &&
169
+ j.recordsHash === b.recordsHash &&
170
+ j.inventoryHash === b.inventoryHash, "Another build is pending. Resume the artifact recorded in pending.json before importing a new commit.");
171
+ invariant(args.resume, "Pending import found; use --resume with the same artifact.");
172
+ }
173
+ const existing = (await published(store, binding)).find((v) => v.commitOid === b.commitOid);
174
+ if (existing) {
175
+ invariant(await validateCandidate(store, existing.tagName, b, binding, existing.attemptId), "Existing published version differs from this build.");
176
+ await atomic(join(state, "last-build.json"), {
177
+ artifact: b.directory,
178
+ version: existing,
179
+ });
180
+ if (j)
181
+ await rm(journalPath);
182
+ return existing;
183
+ }
184
+ if (!j) {
185
+ let source = "checkpoint-empty";
186
+ let baseline;
187
+ if (args.baseline) {
188
+ const prev = args.baseline;
189
+ await validateBuild(prev.build);
190
+ invariant(prev.build.repoKey === b.repoKey &&
191
+ prev.build.configHash === b.configHash, "Baseline configuration mismatch.");
192
+ const current = (await store.branches()).find((x) => x.name === prev.version.writer);
193
+ invariant(current?.snapshotId === prev.version.snapshotId, "Writer baseline has changed; refusing to fork it.");
194
+ invariant(await validateCandidate(store, prev.version.tagName, prev.build, binding, prev.version.attemptId), "Baseline Tag validation failed.");
195
+ source = prev.version.writer;
196
+ baseline = prev.version;
197
+ }
198
+ const attemptId = randomUUID();
199
+ j = {
200
+ buildId: b.buildId,
201
+ recordsHash: b.recordsHash,
202
+ inventoryHash: b.inventoryHash,
203
+ artifact: b.directory,
204
+ attemptId,
205
+ writer: `work-${attemptId}`,
206
+ source,
207
+ baseline,
208
+ phase: "branch",
209
+ batches: [],
210
+ };
211
+ await atomic(journalPath, j);
212
+ }
213
+ const save = () => atomic(journalPath, j);
214
+ if (j.phase === "branch") {
215
+ const branches = await store.branches();
216
+ const found = branches.find((x) => x.name === j.writer);
217
+ if (found)
218
+ invariant(found.parent === j.source &&
219
+ found.snapshotId === (j.baseline?.snapshotId ?? null), "Partially created writer has an unexpected baseline.");
220
+ else {
221
+ const source = branches.find((x) => x.name === j.source);
222
+ invariant(source &&
223
+ (j.baseline
224
+ ? source.snapshotId === j.baseline.snapshotId
225
+ : source.snapshotId === null), "Source Branch is no longer the expected baseline.");
226
+ await store.branch(j.writer, j.source);
227
+ }
228
+ j.phase = "writing";
229
+ await save();
230
+ }
231
+ const metadata = corpusMetadata(b, binding.repoId, binding.indexId, j.attemptId);
232
+ const marker = metadata.at(-1);
233
+ if (j.phase === "writing") {
234
+ // Reconcile from the immutable old Tag, never from a half-written writer.
235
+ const oldIds = new Set();
236
+ const oldHashes = new Map();
237
+ if (j.baseline)
238
+ for await (const d of store.list(tag(j.baseline.tagName))) {
239
+ oldIds.add(d.id);
240
+ oldHashes.set(d.id, hash(d));
241
+ }
242
+ const newIds = new Set([
243
+ ...Object.keys(b.recordHashes),
244
+ ...metadata.map((d) => d.id),
245
+ ]);
246
+ const obsolete = [...oldIds].filter((id) => !newIds.has(id));
247
+ const mutate = async (operation, payload, send) => {
248
+ const receipt = {
249
+ operation,
250
+ hash: hash(payload),
251
+ outcome: "unknown",
252
+ };
253
+ j.batches.push(receipt);
254
+ await save();
255
+ await send();
256
+ receipt.outcome = "accepted";
257
+ await save();
258
+ };
259
+ for (let i = 0; i < obsolete.length; i += 500) {
260
+ const ids = obsolete.slice(i, i + 500);
261
+ await mutate("delete", ids, () => store.delete(j.writer, ids));
262
+ }
263
+ async function* changed() {
264
+ for await (const d of records(b.directory))
265
+ if (oldHashes.get(d.id) !== hash(d))
266
+ yield d;
267
+ for (const d of metadata.slice(0, -1))
268
+ yield d;
269
+ }
270
+ for await (const docs of batches(changed()))
271
+ await mutate("upsert", docs, () => store.upsert(j.writer, docs));
272
+ // An explicit same-build replay supersedes unknown earlier receipts only after every write ACKs.
273
+ await mutate("final-marker", [marker], () => store.upsert(j.writer, [marker]));
274
+ for (const receipt of j.batches)
275
+ if (receipt.outcome === "unknown")
276
+ receipt.outcome = "superseded";
277
+ j.phase = "waiting";
278
+ await save();
279
+ }
280
+ const deadline = Date.now() + (args.timeoutMs ?? 120_000);
281
+ const pause = args.pollMs ?? 1000;
282
+ let rejectedSnapshot;
283
+ while (j.phase === "waiting") {
284
+ invariant(Date.now() < deadline, "Index validation timed out; build remains unpublished. Resume this artifact with --resume.");
285
+ const visible = await one(store, branch(j.writer), "__manifest__", false);
286
+ if (!matchesManifest(visible, b, binding, j.attemptId)) {
287
+ await sleep(pause);
288
+ continue;
289
+ }
290
+ if (rejectedSnapshot) {
291
+ const head = (await store.branches()).find((b) => b.name === j.writer)?.snapshotId;
292
+ if (!head || head === rejectedSnapshot) {
293
+ await sleep(pause);
294
+ continue;
295
+ }
296
+ }
297
+ const candidate = await store.tag(`try-${randomUUID()}`, branch(j.writer));
298
+ if (!(await validateCandidate(store, candidate.name, b, binding, j.attemptId))) {
299
+ rejectedSnapshot = candidate.snapshotId;
300
+ await sleep(pause);
301
+ continue;
302
+ }
303
+ j.candidate = candidate;
304
+ j.phase = "publishing";
305
+ await save();
306
+ }
307
+ invariant(j.candidate, "Missing validated candidate.");
308
+ invariant(await validateCandidate(store, j.candidate.name, b, binding, j.attemptId), "Validated candidate is missing or changed.");
309
+ const name = versionTag(b.commitOid);
310
+ const found = (await store.tags()).find((t) => t.name === name);
311
+ const final = found ?? (await store.tag(name, tag(j.candidate.name)));
312
+ invariant(final.snapshotId === j.candidate.snapshotId, "Published Tag name already points to a different snapshot.");
313
+ const result = {
314
+ id: versionId(b.commitOid),
315
+ kind: "manifest",
316
+ role: "published",
317
+ schemaVersion: 1,
318
+ configHash: b.configHash,
319
+ repoId: binding.repoId,
320
+ indexId: binding.indexId,
321
+ commitOid: b.commitOid,
322
+ commitTime: b.commitTime,
323
+ tagName: name,
324
+ snapshotId: final.snapshotId,
325
+ writer: j.writer,
326
+ buildId: b.buildId,
327
+ recordsHash: b.recordsHash,
328
+ inventoryHash: b.inventoryHash,
329
+ attemptId: j.attemptId,
330
+ counts: b.counts,
331
+ validation: { inventory: true, content: true, query: true },
332
+ };
333
+ await store.upsert("main", [result]);
334
+ await atomic(join(state, "last-build.json"), {
335
+ artifact: b.directory,
336
+ version: result,
337
+ });
338
+ await rm(journalPath);
339
+ return result;
340
+ }
341
+ //# sourceMappingURL=publish.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"publish.js","sourceRoot":"","sources":["../src/publish.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ import { type Doc } from "./common.js";
2
+ import { type CollectionStore } from "./remote.js";
3
+ import { type Binding, type Published } from "./publish.js";
4
+ export declare const releaseAlias: (ref: string) => string;
5
+ export declare const releaseId: (ref: string) => string;
6
+ /** Only observed local tags. Absence is not deletion authority; this command never prunes. */
7
+ export declare function syncTags(store: CollectionStore, binding: Binding, path: string): Promise<Doc[]>;
8
+ export declare function resolveVersion(store: CollectionStore, binding: Binding, selector: string): Promise<Published>;
@@ -0,0 +1,79 @@
1
+ import { hash, invariant } from "./common.js";
2
+ import { gitTags } from "./git.js";
3
+ import { one, branch } from "./remote.js";
4
+ import { published } from "./publish.js";
5
+ export const releaseAlias = (ref) => `rel-${hash(ref).slice(0, 40)}`;
6
+ export const releaseId = (ref) => `ref-${hash(ref)}`;
7
+ /** Only observed local tags. Absence is not deletion authority; this command never prunes. */
8
+ export async function syncTags(store, binding, path) {
9
+ const releases = await gitTags(path), versions = await published(store, binding), aliases = await store.aliases(), results = [];
10
+ for (const release of releases) {
11
+ const version = versions.find((v) => v.commitOid === release.oid);
12
+ const name = releaseAlias(release.ref);
13
+ let control = {
14
+ id: releaseId(release.ref),
15
+ kind: "manifest",
16
+ role: "git-ref",
17
+ schemaVersion: 1,
18
+ configHash: binding.configHash,
19
+ repoId: binding.repoId,
20
+ indexId: binding.indexId,
21
+ gitRef: release.ref,
22
+ desiredOid: release.oid,
23
+ aliasName: name,
24
+ status: "pending",
25
+ };
26
+ // Save moved-ref intent first so interrupted sync cannot expose the stale target as current.
27
+ await store.upsert("main", [control]);
28
+ if (version) {
29
+ const alias = aliases.find((a) => a.name === name);
30
+ if (!alias ||
31
+ alias.target !== version.tagName ||
32
+ alias.kind !== "TAG" ||
33
+ alias.dangling)
34
+ await store.alias(name, version.tagName, !!alias);
35
+ control = {
36
+ ...control,
37
+ status: "available",
38
+ tagName: version.tagName,
39
+ snapshotId: version.snapshotId,
40
+ };
41
+ await store.upsert("main", [control]);
42
+ }
43
+ results.push(control);
44
+ }
45
+ return results;
46
+ }
47
+ export async function resolveVersion(store, binding, selector) {
48
+ const versions = await published(store, binding);
49
+ const ref = selector.startsWith("refs/tags/")
50
+ ? selector
51
+ : `refs/tags/${selector}`;
52
+ const control = await one(store, branch("main"), releaseId(ref), true);
53
+ // Like Git import, a known tag name takes precedence over an OID spelling.
54
+ // Its pending or invalid state must not fall back to an unrelated commit.
55
+ if (!control && !selector.startsWith("refs/")) {
56
+ const direct = versions.filter((v) => v.commitOid === selector ||
57
+ v.tagName === selector ||
58
+ (/^[a-f0-9]{7,64}$/.test(selector) && v.commitOid.startsWith(selector)));
59
+ if (direct.length) {
60
+ invariant(direct.length === 1, "Ambiguous commit prefix.");
61
+ return direct[0];
62
+ }
63
+ }
64
+ invariant(control?.gitRef === ref &&
65
+ control.repoId === binding.repoId &&
66
+ control.indexId === binding.indexId &&
67
+ control.configHash === binding.configHash, "Version is not indexed or Git tag has not been synchronized.");
68
+ invariant(control.status === "available", "Git tag target is pending; import its desired commit and run git sync-tags.");
69
+ const alias = (await store.aliases()).find((a) => a.name === control.aliasName);
70
+ invariant(alias?.kind === "TAG" &&
71
+ !alias.dangling &&
72
+ alias.target === control.tagName, "Git tag Alias is out of sync; run git sync-tags.");
73
+ const result = versions.find((v) => v.commitOid === control.desiredOid &&
74
+ v.tagName === alias.target &&
75
+ v.snapshotId === control.snapshotId);
76
+ invariant(result, "Release target is not a published version.");
77
+ return result;
78
+ }
79
+ //# sourceMappingURL=releases.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"releases.js","sourceRoot":"","sources":["../src/releases.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,53 @@
1
+ import { LambdaDBClient, type IndexConfigsUnion } from "@functional-systems/lambdadb";
2
+ import { type Doc } from "./common.js";
3
+ import type { Settings } from "./settings.js";
4
+ export type Ref = {
5
+ kind: "branch" | "tag";
6
+ name: string;
7
+ };
8
+ export type Snapshot = {
9
+ name: string;
10
+ snapshotId: string;
11
+ };
12
+ export type Branch = {
13
+ name: string;
14
+ snapshotId: string | null;
15
+ parent: string | null;
16
+ };
17
+ export type Alias = {
18
+ name: string;
19
+ target: string;
20
+ kind: string;
21
+ dangling: boolean;
22
+ };
23
+ export type Hit = {
24
+ doc: Doc;
25
+ score?: number;
26
+ };
27
+ /** Narrow protocol boundary for fault-injection tests; LambdaDB is the only CLI backend. */
28
+ export interface CollectionStore {
29
+ fetch(ref: Ref, ids: string[], consistent?: boolean): Promise<Doc[]>;
30
+ list(ref: Ref): AsyncIterable<Doc>;
31
+ upsert(branch: string, docs: Doc[]): Promise<void>;
32
+ delete(branch: string, ids: string[]): Promise<void>;
33
+ branches(): Promise<Branch[]>;
34
+ branch(name: string, source: string): Promise<void>;
35
+ tags(): Promise<Snapshot[]>;
36
+ tag(name: string, source: Ref): Promise<Snapshot>;
37
+ aliases(): Promise<Alias[]>;
38
+ alias(name: string, target: string, exists: boolean): Promise<void>;
39
+ query(tag: string, query: Record<string, unknown>, size: number): Promise<Hit[]>;
40
+ }
41
+ export declare class RemoteError extends Error {
42
+ }
43
+ export declare class LambdaRemote {
44
+ readonly settings: Settings;
45
+ readonly client: LambdaDBClient;
46
+ constructor(settings: Settings);
47
+ collections(): Promise<import("@functional-systems/lambdadb").CollectionResponseWithDates[]>;
48
+ create(name: string, indexConfigs: Record<string, IndexConfigsUnion>, description: string, tags: Record<string, string>): Promise<void>;
49
+ store(name: string): CollectionStore;
50
+ }
51
+ export declare const branch: (name: string) => Ref;
52
+ export declare const tag: (name: string) => Ref;
53
+ export declare function one(store: CollectionStore, ref: Ref, id: string, consistent?: boolean): Promise<Doc | undefined>;
package/dist/remote.js ADDED
@@ -0,0 +1,136 @@
1
+ import { LambdaDBClient, branchRef, tagRef, branchSource, tagSource, tagTarget, } from "@functional-systems/lambdadb";
2
+ import { invariant } from "./common.js";
3
+ export class RemoteError extends Error {
4
+ }
5
+ async function request(operation, call) {
6
+ try {
7
+ return await call();
8
+ }
9
+ catch (e) {
10
+ // SDK errors can contain response bodies/source text. Never echo them or credentials.
11
+ const status = e.statusCode;
12
+ throw new RemoteError(`LambdaDB ${operation} failed${typeof status === "number" ? ` (HTTP ${status})` : ""}. Mutation outcome may be unknown; retain the retry journal.`, { cause: e });
13
+ }
14
+ }
15
+ export class LambdaRemote {
16
+ settings;
17
+ client;
18
+ constructor(settings) {
19
+ this.settings = settings;
20
+ const key = process.env[settings.apiKeyEnv];
21
+ invariant(key, `Missing environment variable ${settings.apiKeyEnv}.`);
22
+ this.client = new LambdaDBClient({
23
+ baseUrl: settings.endpoint,
24
+ projectName: settings.project,
25
+ projectApiKey: key,
26
+ retryConfig: { strategy: "none" },
27
+ timeoutMs: 30_000,
28
+ });
29
+ }
30
+ async collections() {
31
+ return request("list collections", async () => (await this.client.listAllCollections({ size: 100 })).collections);
32
+ }
33
+ async create(name, indexConfigs, description, tags) {
34
+ await request("create collection", () => this.client.createCollection({
35
+ collectionName: name,
36
+ indexConfigs,
37
+ description,
38
+ tags,
39
+ }));
40
+ }
41
+ store(name) {
42
+ const c = this.client.collection(name);
43
+ const ref = (r) => r.kind === "tag" ? tagRef(r.name) : branchRef(r.name);
44
+ return {
45
+ fetch: (r, ids, consistent = false) => request("fetch", async () => {
46
+ invariant(!consistent || r.kind === "branch", "Consistent reads require a Branch.");
47
+ const result = await c.docs.fetch(r.kind === "branch"
48
+ ? {
49
+ ref: branchRef(r.name),
50
+ ids,
51
+ consistentRead: consistent,
52
+ includeVectors: true,
53
+ }
54
+ : {
55
+ ref: tagRef(r.name),
56
+ ids,
57
+ consistentRead: false,
58
+ includeVectors: true,
59
+ });
60
+ return result.docs.map((d) => d.doc);
61
+ }),
62
+ async *list(r) {
63
+ let cursor;
64
+ const seen = new Set();
65
+ do {
66
+ const page = await request("list documents", () => c.docs.list({
67
+ ref: ref(r),
68
+ size: 100,
69
+ includeVectors: true,
70
+ pageToken: cursor,
71
+ }));
72
+ for (const d of page.docs)
73
+ yield d.doc;
74
+ cursor = page.nextPageToken || undefined;
75
+ if (cursor) {
76
+ invariant(!seen.has(cursor), "LambdaDB repeated a pagination cursor.");
77
+ seen.add(cursor);
78
+ }
79
+ } while (cursor);
80
+ },
81
+ upsert: async (branch, docs) => {
82
+ await request("upsert", () => c.docs.upsert({ branch, docs }));
83
+ },
84
+ delete: async (branch, ids) => {
85
+ if (ids.length)
86
+ await request("delete", () => c.docs.delete({ branch, ids }));
87
+ },
88
+ branches: () => request("list branches", async () => (await c.branches.list()).branches.map((b) => ({
89
+ name: b.name,
90
+ snapshotId: b.headSnapshot?.snapshotId ?? null,
91
+ parent: b.parentBranch?.name ?? null,
92
+ }))),
93
+ branch: async (name, source) => {
94
+ await request("create branch", () => c.branches.create({ branchName: name, source: branchSource(source) }));
95
+ },
96
+ tags: () => request("list tags", async () => (await c.tags.list()).tags.map((t) => ({
97
+ name: t.name,
98
+ snapshotId: t.snapshotId,
99
+ }))),
100
+ tag: (name, source) => request("create tag", async () => {
101
+ const t = (await c.tags.create({
102
+ tagName: name,
103
+ source: source.kind === "tag"
104
+ ? tagSource(source.name)
105
+ : branchSource(source.name),
106
+ })).tag;
107
+ return { name: t.name, snapshotId: t.snapshotId };
108
+ }),
109
+ aliases: () => request("list aliases", async () => (await c.aliases.list()).aliases.map((a) => ({
110
+ name: a.aliasName,
111
+ target: a.targetName,
112
+ kind: a.targetKind,
113
+ dangling: a.dangling,
114
+ }))),
115
+ alias: async (name, target, exists) => {
116
+ await request("set alias", () => exists
117
+ ? c.aliases.retarget(name, { target: tagTarget(target) })
118
+ : c.aliases.create({ aliasName: name, target: tagTarget(target) }));
119
+ },
120
+ query: (tag, query, size) => request("query", async () => (await c.query({
121
+ ref: tagRef(tag),
122
+ consistentRead: false,
123
+ query,
124
+ size,
125
+ })).docs.map((h) => ({ doc: h.doc, score: h.score }))),
126
+ };
127
+ }
128
+ }
129
+ export const branch = (name) => ({ kind: "branch", name });
130
+ export const tag = (name) => ({ kind: "tag", name });
131
+ export async function one(store, ref, id, consistent = false) {
132
+ const docs = await store.fetch(ref, [id], consistent);
133
+ invariant(docs.length <= 1 && docs.every((d) => d.id === id), "Unexpected fetch result.");
134
+ return docs[0];
135
+ }
136
+ //# sourceMappingURL=remote.js.map