-
Notifications
You must be signed in to change notification settings - Fork 56
quick silver #1631
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
quick silver #1631
Changes from all commits
60e89dd
584ad2e
c0eca08
55e8984
c5735f9
22df480
7bbe9c8
a3a10b6
c619ab6
6623f86
6a47c5e
c03f13b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,161 @@ | ||||||||||||||||||||||||||||||||||||||
| /* eslint-disable no-console */ | ||||||||||||||||||||||||||||||||||||||
| import { command, option, multioption, string, run, subcommands, array } from "cmd-ts"; | ||||||||||||||||||||||||||||||||||||||
| import { QSApi } from "./qs-api.js"; | ||||||||||||||||||||||||||||||||||||||
| import type { QSGet, QSPut } from "@fireproof/cloud-quick-silver-types"; | ||||||||||||||||||||||||||||||||||||||
| import { ensureSuperThis } from "@fireproof/core-runtime"; | ||||||||||||||||||||||||||||||||||||||
| import { processStream } from "@adviser/cement"; | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| const sthis = ensureSuperThis(); | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| // ── shared connection options ───────────────────────────────────────────────── | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| function connectionOpts() { | ||||||||||||||||||||||||||||||||||||||
| return { | ||||||||||||||||||||||||||||||||||||||
| url: option({ | ||||||||||||||||||||||||||||||||||||||
| long: "url", | ||||||||||||||||||||||||||||||||||||||
| short: "u", | ||||||||||||||||||||||||||||||||||||||
| description: "WebSocket URL of the quick-silver worker", | ||||||||||||||||||||||||||||||||||||||
| type: string, | ||||||||||||||||||||||||||||||||||||||
| }), | ||||||||||||||||||||||||||||||||||||||
| db: option({ | ||||||||||||||||||||||||||||||||||||||
| long: "db", | ||||||||||||||||||||||||||||||||||||||
| short: "d", | ||||||||||||||||||||||||||||||||||||||
| description: "Database name", | ||||||||||||||||||||||||||||||||||||||
| type: string, | ||||||||||||||||||||||||||||||||||||||
| }), | ||||||||||||||||||||||||||||||||||||||
| authType: option({ | ||||||||||||||||||||||||||||||||||||||
| long: "auth-type", | ||||||||||||||||||||||||||||||||||||||
| description: "Auth type", | ||||||||||||||||||||||||||||||||||||||
| type: string, | ||||||||||||||||||||||||||||||||||||||
| defaultValue: () => "anon", | ||||||||||||||||||||||||||||||||||||||
| }), | ||||||||||||||||||||||||||||||||||||||
| authToken: option({ | ||||||||||||||||||||||||||||||||||||||
| long: "auth-token", | ||||||||||||||||||||||||||||||||||||||
| short: "t", | ||||||||||||||||||||||||||||||||||||||
| description: "Auth token", | ||||||||||||||||||||||||||||||||||||||
| type: string, | ||||||||||||||||||||||||||||||||||||||
| defaultValue: () => "", | ||||||||||||||||||||||||||||||||||||||
| }), | ||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| function makeApi(args: { url: string; db: string; authType: string; authToken: string }): ReturnType<typeof QSApi> { | ||||||||||||||||||||||||||||||||||||||
| return QSApi({ | ||||||||||||||||||||||||||||||||||||||
| url: args.url, | ||||||||||||||||||||||||||||||||||||||
| db: args.db, | ||||||||||||||||||||||||||||||||||||||
| auth: () => ({ type: args.authType, token: args.authToken }), | ||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| // ── get ─────────────────────────────────────────────────────────────────────── | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| const getCmd = command({ | ||||||||||||||||||||||||||||||||||||||
| name: "get", | ||||||||||||||||||||||||||||||||||||||
| description: "Fetch one or more docs by key (comma-separated)", | ||||||||||||||||||||||||||||||||||||||
| args: { | ||||||||||||||||||||||||||||||||||||||
| ...connectionOpts(), | ||||||||||||||||||||||||||||||||||||||
| keys: multioption({ | ||||||||||||||||||||||||||||||||||||||
| long: "keys", | ||||||||||||||||||||||||||||||||||||||
| short: "k", | ||||||||||||||||||||||||||||||||||||||
| description: "Key to fetch (repeatable)", | ||||||||||||||||||||||||||||||||||||||
| type: array(string), | ||||||||||||||||||||||||||||||||||||||
| }), | ||||||||||||||||||||||||||||||||||||||
|
coderabbitai[bot] marked this conversation as resolved.
|
||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||
| handler: async (args) => { | ||||||||||||||||||||||||||||||||||||||
| const api = await makeApi(args); | ||||||||||||||||||||||||||||||||||||||
| const ops: QSGet[] = args.keys.map((key) => ({ key })); | ||||||||||||||||||||||||||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Implicit
🐛 Proposed fix- const ops: QSGet[] = args.keys.map((key) => ({ key }));
+ const ops: QSGet[] = args.keys.map((key: string) => ({ key }));- const ops: QSPut[] = args.pkg.map((pair) => {
+ const ops: QSPut[] = args.pkg.map((pair: string) => {📝 Committable suggestion
Suggested change
🧰 Tools🪛 GitHub Check: CI Core[failure] 65-65: 🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||
| await processStream(api.get(ops), async (r) => { | ||||||||||||||||||||||||||||||||||||||
| console.log(JSON.stringify(r)); | ||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||
| await api.close(); | ||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| // ── put ─────────────────────────────────────────────────────────────────────── | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| const putCmd = command({ | ||||||||||||||||||||||||||||||||||||||
| name: "put", | ||||||||||||||||||||||||||||||||||||||
| description: "Write docs by key (repeatable: --pkg key,{json})", | ||||||||||||||||||||||||||||||||||||||
| args: { | ||||||||||||||||||||||||||||||||||||||
| ...connectionOpts(), | ||||||||||||||||||||||||||||||||||||||
| pkg: multioption({ | ||||||||||||||||||||||||||||||||||||||
| long: "pkg", | ||||||||||||||||||||||||||||||||||||||
| short: "p", | ||||||||||||||||||||||||||||||||||||||
| description: "key,{json} pair to store (repeatable)", | ||||||||||||||||||||||||||||||||||||||
| type: array(string), | ||||||||||||||||||||||||||||||||||||||
| }), | ||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||
| handler: async (args) => { | ||||||||||||||||||||||||||||||||||||||
| const ops: QSPut[] = args.pkg.map((pair) => { | ||||||||||||||||||||||||||||||||||||||
| const comma = pair.indexOf(","); | ||||||||||||||||||||||||||||||||||||||
| if (comma === -1) throw new Error(`invalid --pkg "${pair}": expected key,{json}`); | ||||||||||||||||||||||||||||||||||||||
| const key = pair.slice(0, comma); | ||||||||||||||||||||||||||||||||||||||
| const data = sthis.ende.cbor.encodeToUint8(JSON.parse(pair.slice(comma + 1))) as Uint8Array<ArrayBuffer>; | ||||||||||||||||||||||||||||||||||||||
| return { key, data } satisfies QSPut; | ||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+89
to
+94
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
🛡️ Proposed fix- const data = sthis.ende.cbor.encodeToUint8(JSON.parse(pair.slice(comma + 1))) as Uint8Array<ArrayBuffer>;
+ let parsed: unknown;
+ try {
+ parsed = JSON.parse(pair.slice(comma + 1));
+ } catch {
+ throw new Error(`invalid --pkg "${pair}": JSON parse failed`);
+ }
+ const data = sthis.ende.cbor.encodeToUint8(parsed) as Uint8Array<ArrayBuffer>;📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||
| const api = await makeApi(args); | ||||||||||||||||||||||||||||||||||||||
| await processStream(api.put(ops), async (r) => { | ||||||||||||||||||||||||||||||||||||||
| console.log(JSON.stringify(r)); | ||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||
| await api.close(); | ||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| // ── all ─────────────────────────────────────────────────────────────────────── | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| const queryCmd = command({ | ||||||||||||||||||||||||||||||||||||||
| name: "query", | ||||||||||||||||||||||||||||||||||||||
| description: "Stream all docs in the database", | ||||||||||||||||||||||||||||||||||||||
| args: { | ||||||||||||||||||||||||||||||||||||||
| ...connectionOpts(), | ||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||
| handler: async (args) => { | ||||||||||||||||||||||||||||||||||||||
| const api = await makeApi(args); | ||||||||||||||||||||||||||||||||||||||
| await processStream(api.query(), async (r) => { | ||||||||||||||||||||||||||||||||||||||
| console.log(JSON.stringify(r)); | ||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||
| await api.close(); | ||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| // ── subscribe ───────────────────────────────────────────────────────────────── | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| const subscribeCmd = command({ | ||||||||||||||||||||||||||||||||||||||
| name: "subscribe", | ||||||||||||||||||||||||||||||||||||||
| description: "Subscribe to events for a subscribeId (streams until Ctrl+C)", | ||||||||||||||||||||||||||||||||||||||
| args: { | ||||||||||||||||||||||||||||||||||||||
| ...connectionOpts(), | ||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||
| handler: async (args) => { | ||||||||||||||||||||||||||||||||||||||
| const api = await makeApi(args); | ||||||||||||||||||||||||||||||||||||||
| const handle = api.subscribe(); | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| const cleanup = () => { | ||||||||||||||||||||||||||||||||||||||
| handle.close(); | ||||||||||||||||||||||||||||||||||||||
| api | ||||||||||||||||||||||||||||||||||||||
| .close() | ||||||||||||||||||||||||||||||||||||||
| .then(() => process.exit(0)) | ||||||||||||||||||||||||||||||||||||||
| .catch(() => process.exit(1)); | ||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||
| process.on("SIGINT", cleanup); | ||||||||||||||||||||||||||||||||||||||
| process.on("SIGTERM", cleanup); | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| await processStream(handle.events, async (r) => { | ||||||||||||||||||||||||||||||||||||||
| console.log(JSON.stringify(r)); | ||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||
| await api.close(); | ||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| // ── entry point ─────────────────────────────────────────────────────────────── | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| const cmd = subcommands({ | ||||||||||||||||||||||||||||||||||||||
| name: "qs", | ||||||||||||||||||||||||||||||||||||||
| description: "quick-silver CLI", | ||||||||||||||||||||||||||||||||||||||
| version: "0.0.0", | ||||||||||||||||||||||||||||||||||||||
| cmds: { get: getCmd, put: putCmd, query: queryCmd, subscribe: subscribeCmd }, | ||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| run(cmd, process.argv.slice(2)) | ||||||||||||||||||||||||||||||||||||||
| .then(() => process.exit(0)) | ||||||||||||||||||||||||||||||||||||||
| .catch(console.error); | ||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+159
to
+161
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Scripts and CI pipelines relying on exit codes will not detect CLI failures. 🛡️ Proposed fix run(cmd, process.argv.slice(2))
.then(() => process.exit(0))
- .catch(console.error);
+ .catch((e) => { console.error(e); process.exit(1); });📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,16 @@ | ||
| { | ||
| "name": "@fireproof/cloud-quick-silver-api", | ||
| "version": "0.0.0", | ||
| "type": "module", | ||
| "scripts": { | ||
| "build": "core-cli tsc", | ||
| "pack": "core-cli build --doPack", | ||
| "publish": "core-cli build" | ||
| }, | ||
| "dependencies": { | ||
| "@adviser/cement": "^0.5.22", | ||
| "@fireproof/cloud-quick-silver-types": "workspace:*", | ||
| "@fireproof/core-runtime": "workspace:*", | ||
| "cmd-ts": "^0.15.0" | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
QuickSilverconstructor requiressthis— build-breaking pipeline failure.QuickSilverOptshassthis: SuperThisas a required field, but the factory only provides{ name }. The build fails with TS2741.🐛 Proposed fix
📝 Committable suggestion
🧰 Tools
🪛 GitHub Actions: `@fireproof/core`
[error] 10-10: TypeScript error TS2741: Property 'sthis' is missing in type '{ name: string; }' but required in type 'QuickSilverOpts'.
🪛 GitHub Check: CI Core
[failure] 10-10:
Property 'sthis' is missing in type '{ name: string; }' but required in type 'QuickSilverOpts'.
🤖 Prompt for AI Agents