@functional-systems/lambdadb-cli 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.
package/VALIDATION.md ADDED
@@ -0,0 +1,222 @@
1
+ # Validation record
2
+
3
+ Date: 2026-09-18. Local contract tests use loopback servers and synthetic
4
+ credentials. A separate authenticated development-project smoke is recorded below.
5
+
6
+ ## Automatic development-release validation
7
+
8
+ On Node.js 24.15.0, lint, type checking and all 46 source tests passed, including
9
+ six release-automation tests. The tests cover deterministic first-parent version
10
+ numbers, numeric channel ordering, stale commits, registry lookup failures,
11
+ artifact/commit conflicts, identical reruns and uncertain publication outcomes.
12
+ Registry writes use an injected fake npm runner; no package was published.
13
+ A real read-only npm lookup also confirmed the structured E404 handling.
14
+
15
+ A temporary local Git repository and bare remote exercised the actual prepare
16
+ command, including rejected PR/wrong-commit contexts and stale remote heads.
17
+ A separate clean source copy generated `0.1.0-dev.2`, installed locked
18
+ dependencies, packed and installed the generated artifact, and passed all 35
19
+ installed-CLI contracts. Its source `gitHead` and license metadata were preserved
20
+ and its Git HEAD did not change. The normal `0.1.0-dev.1` artifact also passed
21
+ all 35 installed-CLI contracts.
22
+
23
+ `actionlint` 1.7.12 accepted the combined CI/publishing workflow. The existing
24
+ `Node.js 22` and `Node.js 24` check names are retained. Publishing needs both jobs
25
+ and is restricted to explicit releases or opted-in develop pushes. The repository
26
+ variable enabling automatic dev publication was not set during this validation.
27
+ Actual OIDC authentication, registry writes, provenance and GitHub job ordering
28
+ remain unverified until the first authorized automated publication.
29
+
30
+ ## Authenticated development-project smoke
31
+
32
+ Tested the CLI from develop commit `a040f53` (version `0.1.0-dev.1`, SDK `0.5.1`)
33
+ with Node.js 24.15.0 against the development target supplied by the maintainer in
34
+ the primary checkout's ignored `.env.local`. The designated development target is:
35
+
36
+ - Endpoint: `https://internal-dev-aws-apne2-v3-c05a2b5d492a.lambdadb.ai`
37
+ - Project: `bench-recall`
38
+
39
+ The API key is excluded from this record. The file used `LAMBDADB_BASE_URL`,
40
+ `LAMBDADB_PROJECT_NAME`, `LAMBDADB_PROJECT_API_KEY` and an explicit
41
+ `LAMBDADB_RUN_LIVE_TESTS=1`. An in-memory launcher mapped the first three to
42
+ `LAMBDADB_ENDPOINT`, `LAMBDADB_PROJECT`, `LAMBDADB_API_KEY`, and supplied the
43
+ confirmed development project as `LAMBDADB_LIVE_CONFIRM_PROJECT` for this run.
44
+ Neither the file nor the CLI's environment-variable contract was changed.
45
+
46
+ After `npm run build`, the launcher ran `node --test test/live/cli.test.mjs`:
47
+
48
+ - The original 75-second query observation window failed after writes were
49
+ accepted. This was a failed smoke, not proof of a service or CLI defect.
50
+ - The follow-up harness allows up to 300 seconds per read stage, matching the
51
+ SDK live smoke's committed-document observation window. It reports elapsed
52
+ time and matched-document counts without printing responses or credentials.
53
+ - The follow-up run passed: doctor and creation completed within the first
54
+ second; two ordinary writes (3 MiB payload each) and one bulk write were
55
+ accepted at about 2 seconds. Query returned all three expected documents with
56
+ exact contents at about 65 seconds, and ID fetch verified them at about 66
57
+ seconds. Both reads selected `branch:main` without a pending-write overlay.
58
+ - Cleanup was accepted for both temporary collections. Subsequent SDK get calls
59
+ returned `ResourceNotFoundError` for
60
+ `cli-smoke-9797d164-abb3-4a7e-ae26-f5ae251ad72c` and
61
+ `cli-smoke-b926fd65-c371-462f-9727-9d5d9edecc1c`, confirming their absence.
62
+
63
+ The two runs demonstrate variable observation time; 300 seconds is a test budget,
64
+ not a readiness or latency guarantee. Full content was verified for a combined
65
+ response above 6 MiB, but the CLI harness did not inspect the service's wire
66
+ response to prove selection of `docsUrl`. Live tag/alias reads remain unverified.
67
+
68
+ ### Review follow-up: enforce the observation budget
69
+
70
+ The harness now uses a monotonic deadline, caps CLI and child-process timeouts
71
+ to the remaining budget, and limits the final polling sleep. It checks the
72
+ deadline after each observation, including content comparison, before accepting
73
+ success. Process termination and event-loop scheduling can delay reporting, but
74
+ a response at or after the deadline cannot pass the stage.
75
+
76
+ On Node.js 24.15.0, lint, type checking and all 53 source tests passed. Seven new
77
+ deterministic tests cover timely success, late success/failure, success exactly
78
+ at the deadline, a capped final sleep, an in-flight timeout and an earlier fatal
79
+ error. The regression reproduces a response arriving at 318 seconds and rejects
80
+ it; the final request receives only the remaining 2-second budget.
81
+ The packed and separately installed CLI also passed all 35 contract tests.
82
+
83
+ Re-ran `node --test test/live/cli.test.mjs` with this review fix in the working
84
+ tree based on `6642eeb`, using the same designated endpoint/project and launcher
85
+ above. The CLI runtime source remained identical to `a040f53`; SDK version was
86
+ `0.5.1`. Doctor and collection creation passed within the first second, ordinary
87
+ and bulk writes were accepted at about 3 seconds, and exact query/fetch contents
88
+ passed at about 91 seconds (test duration: 91.231 seconds). Both reads used
89
+ `branch:main`. Cleanup was accepted for
90
+ `cli-smoke-3cb15833-414d-4265-9b57-70df164b28ef`; a subsequent SDK get returned
91
+ `ResourceNotFoundError`, confirming absence. Deadline boundary cases were
92
+ verified deterministically above, not by inducing a live service timeout.
93
+
94
+ ## 0.1.0-dev.1 release preparation
95
+
96
+ Revalidated on 2026-09-18 in a fresh worktree based on develop commit `52e7aa2`
97
+ with Node.js 24.15.0 and npm 11.12.1. `npm ci`, lint, type checking and version
98
+ checks passed. Source tests passed (40), and the separately installed tarball's
99
+ CLI tests passed (35), with no failures or skips. The version assertion now
100
+ compares the executable against package metadata instead of a fixed version.
101
+
102
+ `RELEASE_TAG=v0.1.0-dev.1 RELEASE_PRERELEASE=true npm run check:version -- --release`
103
+ passed and selected the `dev` channel. This checks release metadata only; it does
104
+ not publish or establish main ancestry, npm permissions or live-service behavior.
105
+ At the initial release-preparation stage no development connection settings were
106
+ supplied, so live validation was not attempted then. See the later smoke above.
107
+
108
+ ## Completed local validation
109
+
110
+ | Check | Result |
111
+ | --- | --- |
112
+ | `npm run typecheck` | Passed with TypeScript 5.8.3. |
113
+ | `npm run lint` and `npm run check:version` | Passed; package and lockfile metadata agree. |
114
+ | `npm test` on Node.js 24.15.0 | 40 tests passed, zero failed or skipped. |
115
+ | Prior CLI MVP suite on Node.js 22.23.2 via `npm exec --yes --package=node@22 -- node --test test/*.test.mjs` | 40 tests passed, zero failed or skipped; new automation tests are recorded separately above. |
116
+ | Fresh temporary source directory: `npm ci`, `npm run build`, CLI version | Passed without the development checkout's node_modules or dist. |
117
+ | `npm run test:package`: pack, inspect inventory, install in a temporary consumer, invoke executable version/help and repeat CLI contracts | 35 installed-CLI tests passed on Node 24. Package was never published. |
118
+ | `actionlint` on CI and publish workflows | Passed. This is static validation, not an OIDC publication. |
119
+ | Live command without opt-in | Expected nonzero exit before network calls; not counted as a live test pass. |
120
+ | npm install dependency audit | Zero vulnerabilities reported at installation time. |
121
+ | Apache-2.0 license packaging | Official license text from apache.org is included byte-for-byte as `package/LICENSE` in the built tarball; package.json and lockfile license metadata agree. |
122
+ | Reference SDK status and specified sbrain file status | Unchanged. |
123
+
124
+ Tests use the actual published SDK and CLI subprocesses; they do not replace the
125
+ SDK with a fake client for transport tests. The workflow unit tests separately
126
+ cover byte accounting and cancellation between batches.
127
+
128
+ ## Behavior exercised
129
+
130
+ - Configure, doctor, create (HTTP 201), JSONL upsert (HTTP 202), query, fetch,
131
+ describe and paginated collection listing.
132
+ - Exact branch/tag/alias request bodies and result targets on query and fetch;
133
+ write branch forwarded on ordinary and bulk requests.
134
+ - SDK pagination with an opaque continuation token.
135
+ - SDK bulk metadata, signed headers, upload body and finalization; no project
136
+ credential sent to object storage.
137
+ - SDK offloaded query/fetch downloads for each ref kind, including 1 MiB returned
138
+ document bodies; consumed signed URLs omitted from CLI output.
139
+ - Complete-file preflight rejects malformed later JSONL lines, invalid IDs,
140
+ empty files and oversized individual batch entries before any request.
141
+ - Invalid query fields, conflicting file/flag refs, invalid query size and
142
+ branch-only consistency constraints rejected before requests.
143
+ - Query `size: null` normalized to SDK omission and branch consistency forwarded.
144
+ - Accepted/rejected/not-attempted batch counts and physical line ranges.
145
+ - Disconnect, HTTP 503, malformed 202 and timeout classified as unknown writes
146
+ without mutation retries, preserving previously accepted batches.
147
+ - Failed bulk upload not retried or finalized; reported conservatively as unknown
148
+ because the SDK helper has no structured error stage.
149
+ - Shared deadline applies to API calls, signed downloads and signed uploads;
150
+ cancellation between batches leaves unsent rows not attempted.
151
+ - Actual SIGINT/SIGTERM during an active second write preserve the accepted first
152
+ batch, mark the active batch unknown and leave the third batch unattempted.
153
+ - Release channels and rejection of version drift, invalid tags/flags, private
154
+ publication and missing license metadata.
155
+ - Empty results succeed; 401/403 authentication failures, other API failures and
156
+ invalid response schemas fail; creation conflicts differ from uncertain writes.
157
+ - All documented exit codes, JSON parseability, stdout/stderr separation, human
158
+ summaries, help and version.
159
+ - Flag/environment/saved-config precedence, explicit missing config, missing
160
+ selected key, custom key-variable names and POSIX config file mode 0600.
161
+ - SDK debug suppression and credential redaction in errors and returned documents,
162
+ including secret strings containing JSON structural characters.
163
+ - Short keys preserve JSON envelope fields, CLI command/state/check tokens,
164
+ ref kinds and error codes. Arbitrary document/index/tag keys and variable
165
+ values remain redacted; human output retains its structured data section.
166
+ - Redacted map-key collisions preserve all entries and unchanged field names.
167
+ Query/fetch regressions cover both input orders, multiple colliding renamed
168
+ keys, preexisting suffixes and nested maps; collection metadata covers tag and
169
+ index-config collisions. Generated suffixes cannot overwrite reserved names.
170
+ - Exactly 100,000 documents are accepted by input preflight; excess rows are
171
+ rejected with their physical line number, excluding blank lines from the count.
172
+ CRLF and a final line without a newline are covered.
173
+ - A 3 MB file of one million small documents exits 2 before any API request under
174
+ a 128 MiB V8 heap limit. The pre-fix reader reproduced heap exhaustion with
175
+ that input. Ten million blank lines followed by invalid JSON also exit 2 within
176
+ that heap limit, preserving the final line number without a split array.
177
+
178
+ ## Source and public-contract inspection
179
+
180
+ Verified npm latest and installed SDK 0.5.1; checked current local SDK source and
181
+ published OpenAPI/quickstart. Evidence revisions and compatibility findings are
182
+ in [DESIGN.md](DESIGN.md). These checks establish the chosen contract, not the
183
+ deployment state of an individual LambdaDB endpoint.
184
+
185
+ ## Not performed / not established
186
+
187
+ - The live smoke verifies one designated development target and a bounded sample;
188
+ it does not establish general query/index readiness, search ranking, managed
189
+ embedding behavior, exhaustive signed-storage policies or production-scale
190
+ performance. Credentials were not searched for in other repositories.
191
+ - No proof of exactly-once delivery, durable resume, or a committed-through write
192
+ receipt. Those capabilities are not implemented.
193
+ - No Windows-specific permission or signal validation. POSIX modes and injected
194
+ SIGINT/SIGTERM were checked on macOS; CI targets Linux.
195
+ - No npm publication, Trusted Publisher configuration, registry provenance or
196
+ release-workflow execution. The `0.1.0-dev.1` candidate sets `private: false`
197
+ and targets the `dev` channel. npm organization permissions, authorized
198
+ bootstrap publication, trust setup and automatic-dev activation remain pending.
199
+ Main promotion is required for explicit rc/stable releases;
200
+ Apache-2.0 is recorded in LICENSE and package metadata.
201
+ - Mock large-response tests cover SDK routing/credential separation at 1 MiB;
202
+ the live sample verifies combined content above 6 MiB. Neither is an exhaustive
203
+ memory/size stress test. Imports buffer a maximum 64 MiB source file
204
+ and retain at most 100,000 documents. Complex documents can still use much more
205
+ memory than their serialized size; the count limit is not a process memory cap.
206
+
207
+ ## Requirements for live verification
208
+
209
+ Follow the explicit settings and `npm run test:live` procedure in
210
+ [RELEASING.md](RELEASING.md#explicit-live-smoke). The authenticated main-branch
211
+ flow and cleanup have been exercised as recorded above. For non-main refs,
212
+ supply existing development branch/tag/alias
213
+ targets whose expected contents are known. Record evidence without keys or signed
214
+ URLs. Temporary collection deletion is performed by the harness through the SDK,
215
+ not exposed as a CLI command.
216
+
217
+ During expanded validation, a second-write timeout hung repeatedly in the source
218
+ and installed package. An explicit timer alone was insufficient; binding the
219
+ command signal through SDK HTTPClient fetch dispatch resolved the observed local
220
+ regressions. See [DESIGN.md](DESIGN.md) for the compatibility boundary; the exact
221
+ upstream cause is not claimed. Commits, pushes and CI runs are recorded in Git
222
+ and the pull request; local checks do not imply service or publication success.
package/dist/cli.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
package/dist/cli.js ADDED
@@ -0,0 +1,208 @@
1
+ #!/usr/bin/env node
2
+ import { Command, CommanderError, Option } from 'commander';
3
+ import { readFileSync } from 'node:fs';
4
+ import { integer, name, resolveConfig, saveSettings } from './config.js';
5
+ import { createInput, parseRef, queryInput, readJson, readJsonl } from './input.js';
6
+ import { importDocuments, planBatches } from './import-workflow.js';
7
+ import { definitelyRejected, describeError, InputError, isInputError } from './errors.js';
8
+ import { Output } from './output.js';
9
+ import { runtime } from './runtime.js';
10
+ const output = new Output();
11
+ output.protect(process.env.LAMBDADB_API_KEY);
12
+ if (process.env.LAMBDADB_API_KEY_ENV)
13
+ output.protect(process.env[process.env.LAMBDADB_API_KEY_ENV]);
14
+ let commandName = 'lambdadb';
15
+ let target;
16
+ let mutationStarted = false;
17
+ const program = new Command()
18
+ .name('lambdadb')
19
+ .description('Project-scoped LambdaDB CLI. All commands are non-interactive.')
20
+ .version(JSON.parse(readFileSync(new URL('../package.json', import.meta.url), 'utf8')).version)
21
+ .option('--json', 'Emit one versioned JSON result on stdout; diagnostics stay on stderr')
22
+ .option('--endpoint <url>', 'API origin (overrides LAMBDADB_ENDPOINT and saved configuration)')
23
+ .option('--project <name>', 'Existing project (overrides LAMBDADB_PROJECT and saved configuration)')
24
+ .option('--api-key-env <name>', 'Environment variable holding the key; never pass a key as an argument')
25
+ .option('--config <path>', 'Configuration path (overrides LAMBDADB_CONFIG)')
26
+ .option('--timeout-ms <ms>', 'Total network budget, 1–3600000 ms (default 30000)')
27
+ .showSuggestionAfterError(false)
28
+ .exitOverride()
29
+ .configureOutput({ writeErr: () => { } })
30
+ .addHelpText('after', '\nExamples:\n lambdadb configure --endpoint https://api.lambdadb.ai --project my-project\n lambdadb doctor --json\n lambdadb query --collection demo-docs --ref branch:main --file examples/query.json --json\n\nExit codes: 0 success, 2 input/config error, 3 API/request failure, 4 partial import, 5 unknown write outcome.');
31
+ function result(data, summary, exitCode = 0) {
32
+ const envelope = { schemaVersion: 1, command: commandName, ok: exitCode === 0, target, data };
33
+ output.emit(envelope, summary);
34
+ process.exitCode = exitCode;
35
+ }
36
+ async function connected(command, action) {
37
+ const config = await resolveConfig(command.optsWithGlobals());
38
+ output.protect(config.apiKey);
39
+ target = { endpoint: config.endpoint, project: config.project };
40
+ const ctx = runtime(config);
41
+ try {
42
+ await action(ctx);
43
+ }
44
+ finally {
45
+ ctx.close();
46
+ }
47
+ }
48
+ function scoped(command) {
49
+ const collection = name(command.opts().collection, 'Collection name');
50
+ target = { ...target, collection };
51
+ return collection;
52
+ }
53
+ program.hook('preAction', (_parent, command) => {
54
+ output.json = !!command.optsWithGlobals().json;
55
+ commandName = command.name();
56
+ if (command.parent && command.parent !== program)
57
+ commandName = `${command.parent.name()} ${commandName}`;
58
+ });
59
+ program.command('configure')
60
+ .description('Save endpoint, project and API-key environment variable name (no secret is saved)')
61
+ .action(async (_opts, cmd) => {
62
+ const saved = await saveSettings(cmd.optsWithGlobals());
63
+ result(saved, 'Configuration saved. Supply the key in the selected environment variable, then run doctor.');
64
+ });
65
+ program.command('doctor')
66
+ .description('Check configuration, authentication and project collection-list access')
67
+ .action(async (_opts, cmd) => connected(cmd, async ({ client, options }) => {
68
+ await client.listCollections({ size: 1 }, options);
69
+ result({ checks: [
70
+ { name: 'configuration', status: 'passed' },
71
+ { name: 'authentication_and_project_collection_list', status: 'passed' },
72
+ ], writesVerified: false, queryReadinessVerified: false }, 'Connection verified using the project collection-list API.');
73
+ }));
74
+ const collections = program.command('collections').description('List, describe and create collections');
75
+ collections.command('list')
76
+ .description('Fetch one page by default, or use the SDK iterator for all pages')
77
+ .option('--size <count>', 'Page size, 1–100', '20')
78
+ .option('--page-token <token>', 'Opaque continuation token')
79
+ .option('--all', 'Fetch all pages within the total timeout (results are buffered)')
80
+ .action(async (opts, cmd) => {
81
+ const size = integer(opts.size, 'Page size', 1, 100);
82
+ await connected(cmd, async ({ client, options }) => {
83
+ const params = { size, pageToken: opts.pageToken };
84
+ if (!opts.all) {
85
+ const page = await client.listCollections(params, options);
86
+ result(page, `${page.collections.length} collection(s)${page.nextPageToken ? '; more pages available' : ''}.`);
87
+ }
88
+ else {
89
+ const items = [];
90
+ for await (const page of client.listCollectionsPages(params, options))
91
+ items.push(...page.collections);
92
+ result({ collections: items }, `${items.length} collection(s).`);
93
+ }
94
+ });
95
+ });
96
+ collections.command('describe')
97
+ .description('Get collection metadata; counts describe the committed main branch')
98
+ .requiredOption('--collection <name>', 'Collection name')
99
+ .action(async (_opts, cmd) => connected(cmd, async ({ client, options }) => {
100
+ const collection = scoped(cmd);
101
+ result(await client.collection(collection).get(options), 'Collection metadata (main-branch counts are not a readiness signal).');
102
+ }));
103
+ collections.command('create')
104
+ .description('Create a collection from a JSON field-to-index map')
105
+ .requiredOption('--collection <name>', 'New collection name')
106
+ .requiredOption('--index-config <path>', 'JSON indexConfigs map (see examples/index-config.json)')
107
+ .action(async (opts, cmd) => {
108
+ const input = createInput(name(opts.collection, 'Collection name'), await readJson(opts.indexConfig));
109
+ await connected(cmd, async ({ client, options }) => {
110
+ scoped(cmd);
111
+ mutationStarted = true;
112
+ const created = await client.createCollection(input, { ...options, retries: { strategy: 'none' } });
113
+ result({ ...created, state: 'created', searchable: 'not_verified' }, 'Collection created; query-serving readiness has not been verified.');
114
+ });
115
+ });
116
+ const docs = program.command('docs').description('Import JSONL and fetch documents by ID');
117
+ docs.command('import')
118
+ .description('Validate JSONL, submit sequential batches, stop on first error; acceptance is not search readiness')
119
+ .requiredOption('--collection <name>', 'Collection name')
120
+ .requiredOption('--branch <name>', 'Explicit writable branch (for example main)')
121
+ .requiredOption('--file <path>', 'UTF-8 JSONL file, at most 64 MiB and 100000 documents')
122
+ .addOption(new Option('--mode <mode>', 'SDK write method').choices(['upsert', 'bulk']).default('upsert'))
123
+ .option('--batch-size <count>', 'Maximum documents per batch, 1–10000', '1000')
124
+ .option('--batch-bytes <bytes>', 'Serialized byte cap (default 4000000 upsert, 16000000 bulk)')
125
+ .action(async (opts, cmd) => {
126
+ name(opts.collection, 'Collection name');
127
+ const branch = name(opts.branch, 'Branch name');
128
+ const bulk = opts.mode === 'bulk';
129
+ const batchSize = integer(opts.batchSize, 'Batch size', 1, 10000);
130
+ const maxBytes = integer(opts.batchBytes ?? (bulk ? '16000000' : '4000000'), 'Batch bytes', 64, bulk ? 64000000 : 4000000);
131
+ const rows = await readJsonl(opts.file);
132
+ const batches = planBatches(rows, branch, batchSize, maxBytes, bulk);
133
+ await connected(cmd, async ({ client, options }) => {
134
+ const collection = scoped(cmd);
135
+ target = { ...target, branch };
136
+ output.diagnostic(`Validated ${rows.length} document(s); submitting ${batches.length} batch(es) using ${opts.mode}.`);
137
+ const imported = await importDocuments(client.collection(collection).docs, batches, branch, bulk, options, batch => {
138
+ output.diagnostic(`Batch ${batch.batch}: ${batch.state}, ${batch.documents} document(s), lines ${batch.firstLine}–${batch.lastLine}.`);
139
+ });
140
+ const exitCode = imported.state === 'accepted' ? 0 : imported.state === 'unknown' ? 5 : imported.state === 'partial' ? 4 : 3;
141
+ result(imported, `${imported.accepted}/${imported.total} document(s) accepted; search visibility not verified.`, exitCode);
142
+ if (exitCode)
143
+ output.diagnostic('Import stopped. Inspect batch outcomes and the selected branch before retrying; automatic resume is not supported.');
144
+ });
145
+ });
146
+ docs.command('fetch')
147
+ .description('Fetch up to 100 IDs at an explicit ref; missing IDs are a successful empty/partial result')
148
+ .requiredOption('--collection <name>', 'Collection name')
149
+ .requiredOption('--ref <kind:name>', 'branch:NAME, tag:NAME or alias:NAME')
150
+ .requiredOption('--ids <id...>', 'One or more IDs (separate with spaces)')
151
+ .option('--consistent-read', 'Overlay eligible pending writes; direct branch only, excludes bulk imports')
152
+ .option('--include-vectors', 'Include vector fields in returned documents')
153
+ .action(async (opts, cmd) => {
154
+ const ref = parseRef(opts.ref);
155
+ if (opts.ids.length > 100 || opts.ids.some((id) => !id))
156
+ throw new InputError('Fetch requires 1–100 nonempty IDs.');
157
+ if (opts.consistentRead && ref.kind !== 'branch')
158
+ throw new InputError('Consistent reads require a direct branch ref.');
159
+ await connected(cmd, async ({ client, options }) => {
160
+ const collection = scoped(cmd);
161
+ target = { ...target, ref };
162
+ const fetched = await client.collection(collection).docs.fetch({
163
+ ids: opts.ids, includeVectors: opts.includeVectors ?? false,
164
+ ...(ref.kind === 'branch' ? { ref, consistentRead: !!opts.consistentRead } : { ref, consistentRead: false }),
165
+ }, options);
166
+ const found = new Set(fetched.docs.map(item => item.doc.id));
167
+ const { docsUrl: _signedUrl, ...data } = fetched;
168
+ result({ ...data, missingIds: opts.ids.filter((id) => !found.has(id)) }, `${fetched.docs.length} document(s) fetched.`);
169
+ });
170
+ });
171
+ program.command('query')
172
+ .description('Submit a supported query request JSON file; empty matches are a successful result')
173
+ .requiredOption('--collection <name>', 'Collection name')
174
+ .requiredOption('--ref <kind:name>', 'branch:NAME, tag:NAME or alias:NAME; must match any ref in the file')
175
+ .requiredOption('--file <path>', 'JSON request body including query (see examples/query.json)')
176
+ .action(async (opts, cmd) => {
177
+ const ref = parseRef(opts.ref);
178
+ const input = queryInput(await readJson(opts.file), ref);
179
+ await connected(cmd, async ({ client, options }) => {
180
+ const collection = scoped(cmd);
181
+ target = { ...target, ref };
182
+ const queried = await client.collection(collection).query(input, options);
183
+ const { docsUrl: _signedUrl, ...data } = queried;
184
+ result(data, `${queried.docs.length} match(es).`);
185
+ });
186
+ });
187
+ try {
188
+ await program.parseAsync(process.argv);
189
+ }
190
+ catch (error) {
191
+ if (error instanceof CommanderError && error.exitCode === 0) {
192
+ process.exitCode = 0;
193
+ }
194
+ else {
195
+ output.json ||= process.argv.includes('--json');
196
+ const failure = error instanceof CommanderError
197
+ ? new InputError('Invalid or incomplete command. Run lambdadb --help or the command-specific --help.') : error;
198
+ const unknownWrite = mutationStarted && !definitelyRejected(failure);
199
+ const exitCode = isInputError(failure) ? 2 : unknownWrite ? 5 : 3;
200
+ output.emit({
201
+ schemaVersion: 1, command: commandName, ok: false, target,
202
+ ...(unknownWrite ? { data: { state: 'unknown', searchable: 'not_verified' } } : {}),
203
+ error: describeError(failure),
204
+ }, unknownWrite ? 'Write outcome unknown. Inspect the target before retrying.' : 'Command failed.');
205
+ process.exitCode = exitCode;
206
+ }
207
+ }
208
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ export type Settings = {
2
+ endpoint?: string;
3
+ project?: string;
4
+ apiKeyEnv?: string;
5
+ };
6
+ export type Config = Required<Settings> & {
7
+ apiKey: string;
8
+ timeoutMs: number;
9
+ };
10
+ export type Options = Settings & {
11
+ config?: string;
12
+ timeoutMs?: string;
13
+ };
14
+ export declare function configPath(options: Options): string;
15
+ export declare function endpoint(value: string): string;
16
+ export declare function name(value: unknown, label: string): string;
17
+ export declare function integer(value: string, label: string, min: number, max: number): number;
18
+ export declare function loadSettings(path: string, explicitlySelected?: boolean): Promise<Settings>;
19
+ export declare function settings(options: Options, creating?: boolean): Promise<Required<Settings>>;
20
+ export declare function resolveConfig(options: Options): Promise<Config>;
21
+ export declare function saveSettings(options: Options): Promise<{
22
+ path: string;
23
+ settings: Required<Settings>;
24
+ }>;
package/dist/config.js ADDED
@@ -0,0 +1,105 @@
1
+ import { homedir } from 'node:os';
2
+ import { dirname, join, resolve } from 'node:path';
3
+ import { mkdir, readFile, rename, rm, writeFile } from 'node:fs/promises';
4
+ import { randomUUID } from 'node:crypto';
5
+ import { InputError } from './errors.js';
6
+ export function configPath(options) {
7
+ return resolve(options.config ?? process.env.LAMBDADB_CONFIG
8
+ ?? join(process.env.XDG_CONFIG_HOME ?? join(homedir(), '.config'), 'lambdadb', 'config.json'));
9
+ }
10
+ export function endpoint(value) {
11
+ let url;
12
+ try {
13
+ url = new URL(value);
14
+ }
15
+ catch {
16
+ throw new InputError('Endpoint must be an absolute HTTPS origin.');
17
+ }
18
+ const loopback = ['localhost', '127.0.0.1', '[::1]'].includes(url.hostname);
19
+ if ((url.protocol !== 'https:' && !(url.protocol === 'http:' && loopback))
20
+ || url.username || url.password || url.search || url.hash || url.pathname !== '/') {
21
+ throw new InputError('Endpoint must be an HTTPS origin without credentials, path, query or fragment (HTTP loopback is allowed for local tests).');
22
+ }
23
+ return url.origin;
24
+ }
25
+ export function name(value, label) {
26
+ if (typeof value !== 'string' || !/^[a-zA-Z0-9_-]{3,52}$/.test(value)) {
27
+ throw new InputError(`${label} must contain 3–52 letters, digits, underscores or hyphens.`);
28
+ }
29
+ return value;
30
+ }
31
+ function environmentName(value) {
32
+ if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(value))
33
+ throw new InputError('API-key environment variable name is invalid.');
34
+ return value;
35
+ }
36
+ export function integer(value, label, min, max) {
37
+ if (!/^\d+$/.test(value) || !Number.isSafeInteger(Number(value)) || Number(value) < min || Number(value) > max) {
38
+ throw new InputError(`${label} must be an integer from ${min} to ${max}.`);
39
+ }
40
+ return Number(value);
41
+ }
42
+ export async function loadSettings(path, explicitlySelected = false) {
43
+ let text;
44
+ try {
45
+ text = await readFile(path, 'utf8');
46
+ }
47
+ catch (error) {
48
+ if (error.code === 'ENOENT' && !explicitlySelected)
49
+ return {};
50
+ throw new InputError('Cannot read the selected configuration file.');
51
+ }
52
+ try {
53
+ const value = JSON.parse(text);
54
+ if (!value || typeof value !== 'object' || Array.isArray(value)
55
+ || Object.keys(value).some(k => !['endpoint', 'project', 'apiKeyEnv'].includes(k))
56
+ || Object.values(value).some(v => typeof v !== 'string'))
57
+ throw new Error();
58
+ return value;
59
+ }
60
+ catch {
61
+ throw new InputError('Configuration must be a JSON object with only endpoint, project and apiKeyEnv strings. Never store an API key in it.');
62
+ }
63
+ }
64
+ export async function settings(options, creating = false) {
65
+ const saved = await loadSettings(configPath(options), !creating && !!(options.config ?? process.env.LAMBDADB_CONFIG));
66
+ const selectedEndpoint = options.endpoint ?? process.env.LAMBDADB_ENDPOINT ?? saved.endpoint;
67
+ const project = options.project ?? process.env.LAMBDADB_PROJECT ?? saved.project;
68
+ if (!selectedEndpoint || !project)
69
+ throw new InputError('Endpoint and project are required. Run configure or set LAMBDADB_ENDPOINT and LAMBDADB_PROJECT.');
70
+ // Project names are encoded as a single SDK URL segment, with no implicit playground fallback.
71
+ if (!/^[a-zA-Z0-9_-]+$/.test(project))
72
+ throw new InputError('Project must contain only letters, digits, underscores or hyphens.');
73
+ return {
74
+ endpoint: endpoint(selectedEndpoint), project,
75
+ apiKeyEnv: environmentName(options.apiKeyEnv ?? process.env.LAMBDADB_API_KEY_ENV ?? saved.apiKeyEnv ?? 'LAMBDADB_API_KEY'),
76
+ };
77
+ }
78
+ export async function resolveConfig(options) {
79
+ const selected = await settings(options);
80
+ const apiKey = process.env[selected.apiKeyEnv];
81
+ if (!apiKey || !apiKey.trim() || /[\r\n]/.test(apiKey))
82
+ throw new InputError('The selected API-key environment variable is missing or invalid. Supply it through your shell or CI secret manager.');
83
+ return {
84
+ ...selected, apiKey,
85
+ timeoutMs: integer(options.timeoutMs ?? process.env.LAMBDADB_TIMEOUT_MS ?? '30000', 'Timeout', 1, 3600000),
86
+ };
87
+ }
88
+ export async function saveSettings(options) {
89
+ const value = await settings(options, true);
90
+ const path = configPath(options);
91
+ const temp = `${path}.${randomUUID()}.tmp`;
92
+ try {
93
+ await mkdir(dirname(path), { recursive: true, mode: 0o700 });
94
+ await writeFile(temp, `${JSON.stringify(value, null, 2)}\n`, { flag: 'wx', mode: 0o600 });
95
+ await rename(temp, path);
96
+ }
97
+ catch {
98
+ throw new InputError('Cannot save configuration. Check the selected path and directory permissions.');
99
+ }
100
+ finally {
101
+ await rm(temp, { force: true }).catch(() => { });
102
+ }
103
+ return { path, settings: value };
104
+ }
105
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ export declare class InputError extends Error {
2
+ }
3
+ export type SafeError = {
4
+ code: string;
5
+ message: string;
6
+ hint: string;
7
+ httpStatus?: number;
8
+ };
9
+ export declare function describeError(error: unknown): SafeError;
10
+ export declare function isInputError(error: unknown): boolean;
11
+ export declare function definitelyRejected(error: unknown): boolean;