@semilayer/cli 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (73) hide show
  1. package/dist/auth-config-3MWVCUTJ.js +117 -0
  2. package/dist/auth-config-3MWVCUTJ.js.map +1 -0
  3. package/dist/billing-OY5GJP5X.js +265 -0
  4. package/dist/billing-OY5GJP5X.js.map +1 -0
  5. package/dist/bin.d.ts +2 -0
  6. package/dist/bin.js +49 -0
  7. package/dist/bin.js.map +1 -0
  8. package/dist/chunk-7TA63VHV.js +38 -0
  9. package/dist/chunk-7TA63VHV.js.map +1 -0
  10. package/dist/chunk-ALA4X7UU.js +19 -0
  11. package/dist/chunk-ALA4X7UU.js.map +1 -0
  12. package/dist/chunk-NIDLPHWY.js +53 -0
  13. package/dist/chunk-NIDLPHWY.js.map +1 -0
  14. package/dist/chunk-QMF7LD67.js +39 -0
  15. package/dist/chunk-QMF7LD67.js.map +1 -0
  16. package/dist/chunk-QXIVJY7K.js +56 -0
  17. package/dist/chunk-QXIVJY7K.js.map +1 -0
  18. package/dist/chunk-T3UROBMA.js +169 -0
  19. package/dist/chunk-T3UROBMA.js.map +1 -0
  20. package/dist/chunk-WZYOSGN3.js +88 -0
  21. package/dist/chunk-WZYOSGN3.js.map +1 -0
  22. package/dist/config-DACYO7JC.js +103 -0
  23. package/dist/config-DACYO7JC.js.map +1 -0
  24. package/dist/dev-R3AZSONQ.js +57 -0
  25. package/dist/dev-R3AZSONQ.js.map +1 -0
  26. package/dist/envs-RNZQ3OQP.js +105 -0
  27. package/dist/envs-RNZQ3OQP.js.map +1 -0
  28. package/dist/export-YRFR3JH2.js +81 -0
  29. package/dist/export-YRFR3JH2.js.map +1 -0
  30. package/dist/generate-QUETX3TN.js +41 -0
  31. package/dist/generate-QUETX3TN.js.map +1 -0
  32. package/dist/index.d.ts +43 -0
  33. package/dist/index.js +34 -0
  34. package/dist/index.js.map +1 -0
  35. package/dist/init-TWJAGUN3.js +187 -0
  36. package/dist/init-TWJAGUN3.js.map +1 -0
  37. package/dist/keys-JBKCYKJU.js +111 -0
  38. package/dist/keys-JBKCYKJU.js.map +1 -0
  39. package/dist/lenses-VZSDFH3D.js +51 -0
  40. package/dist/lenses-VZSDFH3D.js.map +1 -0
  41. package/dist/login-BZ6ZPFHC.js +119 -0
  42. package/dist/login-BZ6ZPFHC.js.map +1 -0
  43. package/dist/logout-VMPRV62T.js +38 -0
  44. package/dist/logout-VMPRV62T.js.map +1 -0
  45. package/dist/members-DVE5FDLZ.js +110 -0
  46. package/dist/members-DVE5FDLZ.js.map +1 -0
  47. package/dist/observe-W346RZBX.js +149 -0
  48. package/dist/observe-W346RZBX.js.map +1 -0
  49. package/dist/orgs-YA3TVA3T.js +67 -0
  50. package/dist/orgs-YA3TVA3T.js.map +1 -0
  51. package/dist/pause-GQ6PKBUA.js +50 -0
  52. package/dist/pause-GQ6PKBUA.js.map +1 -0
  53. package/dist/projects-DMA2AXH3.js +107 -0
  54. package/dist/projects-DMA2AXH3.js.map +1 -0
  55. package/dist/push-3ZK3W2AC.js +145 -0
  56. package/dist/push-3ZK3W2AC.js.map +1 -0
  57. package/dist/resume-KVRPLXZZ.js +50 -0
  58. package/dist/resume-KVRPLXZZ.js.map +1 -0
  59. package/dist/run-IR5B4AE3.js +375 -0
  60. package/dist/run-IR5B4AE3.js.map +1 -0
  61. package/dist/sources-S52HUWRK.js +170 -0
  62. package/dist/sources-S52HUWRK.js.map +1 -0
  63. package/dist/status-AUECH6RX.js +130 -0
  64. package/dist/status-AUECH6RX.js.map +1 -0
  65. package/dist/stream-V7RGHTPR.js +344 -0
  66. package/dist/stream-V7RGHTPR.js.map +1 -0
  67. package/dist/sync-NRTC3WX4.js +68 -0
  68. package/dist/sync-NRTC3WX4.js.map +1 -0
  69. package/dist/whoami-EQGW6V5D.js +50 -0
  70. package/dist/whoami-EQGW6V5D.js.map +1 -0
  71. package/dist/wizard-QLAR33T2.js +306 -0
  72. package/dist/wizard-QLAR33T2.js.map +1 -0
  73. package/package.json +40 -0
@@ -0,0 +1,375 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ loadContext
4
+ } from "./chunk-QMF7LD67.js";
5
+ import {
6
+ createApiClient
7
+ } from "./chunk-T3UROBMA.js";
8
+ import "./chunk-7TA63VHV.js";
9
+ import {
10
+ bold,
11
+ dim,
12
+ error,
13
+ info,
14
+ label,
15
+ newline,
16
+ table
17
+ } from "./chunk-WZYOSGN3.js";
18
+
19
+ // src/commands/run.ts
20
+ import { defineCommand } from "citty";
21
+ function isApiKey(value) {
22
+ return value.startsWith("sk_") || value.startsWith("pk_") || value.startsWith("ik_");
23
+ }
24
+ function outputFormat(flag) {
25
+ if (flag === "json") return "json";
26
+ if (flag === "table") return "table";
27
+ return process.stdout.isTTY ? "table" : "json";
28
+ }
29
+ function printJson(data) {
30
+ console.log(JSON.stringify(data, null, 2));
31
+ }
32
+ function printTable(data) {
33
+ const items = data.results ?? data.rows ?? [];
34
+ if (items.length === 0) {
35
+ info("No results");
36
+ return;
37
+ }
38
+ const allKeys = /* @__PURE__ */ new Set();
39
+ for (const item of items) {
40
+ for (const key of Object.keys(item)) {
41
+ allKeys.add(key);
42
+ }
43
+ }
44
+ const keys = [...allKeys];
45
+ const headerRow = keys.map((k) => bold(k));
46
+ const rows = [headerRow];
47
+ for (const item of items) {
48
+ rows.push(keys.map((k) => formatCell(item[k])));
49
+ }
50
+ table(rows);
51
+ newline();
52
+ const meta = data.meta;
53
+ const parts = [];
54
+ if (meta.count !== void 0) parts.push(`${meta.count} result${meta.count === 1 ? "" : "s"}`);
55
+ if (meta.durationMs !== void 0) parts.push(`${meta.durationMs}ms`);
56
+ if (meta.total !== void 0) parts.push(`total: ${meta.total}`);
57
+ if (meta.nextCursor) parts.push(`next cursor: ${meta.nextCursor}`);
58
+ if (parts.length > 0) info(dim(parts.join(" \xB7 ")));
59
+ }
60
+ function formatCell(value) {
61
+ if (value === null || value === void 0) return dim("null");
62
+ if (typeof value === "string") {
63
+ return value.length > 60 ? value.slice(0, 57) + "..." : value;
64
+ }
65
+ if (typeof value === "object") return dim(JSON.stringify(value));
66
+ return String(value);
67
+ }
68
+ async function readStdin() {
69
+ const chunks = [];
70
+ for await (const chunk of process.stdin) {
71
+ chunks.push(chunk);
72
+ }
73
+ return Buffer.concat(chunks).toString("utf-8");
74
+ }
75
+ async function resolveJoin(joinSpec) {
76
+ const match = joinSpec.match(/^stdin:(\w+)=(\w+)$/);
77
+ if (!match) {
78
+ throw new Error(
79
+ `Invalid --join format. Expected: stdin:<source_field>=<target_field>
80
+ Example: --join stdin:id=user_id`
81
+ );
82
+ }
83
+ const [, sourceField, targetField] = match;
84
+ const raw = await readStdin();
85
+ let parsed;
86
+ try {
87
+ parsed = JSON.parse(raw);
88
+ } catch {
89
+ throw new Error("Failed to parse stdin as JSON. Pipe output from another `semilayer run` command with --output json.");
90
+ }
91
+ const items = parsed.results ?? parsed.rows ?? [];
92
+ if (items.length === 0) {
93
+ throw new Error("Piped input contains no results/rows to join on.");
94
+ }
95
+ const values = items.map((item) => item[sourceField]).filter((v) => v !== null && v !== void 0);
96
+ if (values.length === 0) {
97
+ throw new Error(`Field '${sourceField}' not found in piped results.`);
98
+ }
99
+ return { [targetField]: { $in: values } };
100
+ }
101
+ async function createRequestFn(apiKeyFlag) {
102
+ if (apiKeyFlag) {
103
+ const key = apiKeyFlag;
104
+ if (!isApiKey(key)) {
105
+ throw new Error("--api-key must be an API key (sk_*, pk_*, or ik_*)");
106
+ }
107
+ const ctx2 = await loadContext();
108
+ const serviceUrl = ctx2?.serviceUrl ?? "https://api.semilayer.com";
109
+ return {
110
+ mode: "apikey",
111
+ async request(method, path, body) {
112
+ const res = await fetch(`${serviceUrl}${path}`, {
113
+ method,
114
+ headers: {
115
+ Authorization: `Bearer ${key}`,
116
+ "Content-Type": "application/json"
117
+ },
118
+ body: body !== void 0 ? JSON.stringify(body) : void 0
119
+ });
120
+ if (!res.ok) {
121
+ const text = await res.text().catch(() => "");
122
+ throw new Error(`API error ${res.status}: ${text}`);
123
+ }
124
+ return res.json();
125
+ }
126
+ };
127
+ }
128
+ const ctx = await loadContext();
129
+ if (!ctx) {
130
+ throw new Error("No .semilayerrc found. Run `semilayer init` first, or use --api-key.");
131
+ }
132
+ const api = await createApiClient();
133
+ return {
134
+ mode: "jwt",
135
+ ctx,
136
+ async request(method, path, body) {
137
+ if (method === "POST") return api.post(path, body);
138
+ return api.get(path);
139
+ }
140
+ };
141
+ }
142
+ function buildPath(mode, op, lens, ctx) {
143
+ if (mode === "apikey") {
144
+ return `/v1/${op}/${lens}`;
145
+ }
146
+ return `/v1/orgs/${ctx.orgSlug}/projects/${ctx.projectSlug}/envs/${ctx.envSlug}/run/${op}/${lens}`;
147
+ }
148
+ var searchCommand = defineCommand({
149
+ meta: { name: "search", description: "Semantic search on a lens" },
150
+ args: {
151
+ lens: {
152
+ type: "positional",
153
+ description: "Lens name to search",
154
+ required: true
155
+ },
156
+ query: {
157
+ type: "string",
158
+ description: "Search query text",
159
+ required: true,
160
+ alias: "q"
161
+ },
162
+ limit: {
163
+ type: "string",
164
+ description: "Max results (default: 10)"
165
+ },
166
+ "min-score": {
167
+ type: "string",
168
+ description: "Minimum similarity score 0-1 (default: 0)"
169
+ },
170
+ "api-key": {
171
+ type: "string",
172
+ description: "Use an API key instead of platform JWT"
173
+ },
174
+ output: {
175
+ type: "string",
176
+ description: "Output format: json or table (default: auto-detect)",
177
+ alias: "o"
178
+ }
179
+ },
180
+ async run({ args }) {
181
+ try {
182
+ const { request, mode, ...rest } = await createRequestFn(args["api-key"]);
183
+ const ctx = "ctx" in rest ? rest.ctx : void 0;
184
+ const path = buildPath(mode, "search", args.lens, ctx);
185
+ const body = {
186
+ query: args.query,
187
+ ...args.limit && { limit: parseInt(args.limit, 10) },
188
+ ...args["min-score"] && { minScore: parseFloat(args["min-score"]) }
189
+ };
190
+ const data = await request("POST", path, body);
191
+ const fmt = outputFormat(args.output);
192
+ newline();
193
+ if (fmt === "json") {
194
+ printJson(data);
195
+ } else {
196
+ label("Search", `${bold(args.lens)} \u2192 "${args.query}"`);
197
+ newline();
198
+ printTable(data);
199
+ }
200
+ } catch (err) {
201
+ error(err.message);
202
+ process.exitCode = 1;
203
+ }
204
+ }
205
+ });
206
+ var queryCommand = defineCommand({
207
+ meta: { name: "query", description: "Direct query on a lens" },
208
+ args: {
209
+ lens: {
210
+ type: "positional",
211
+ description: "Lens name to query",
212
+ required: true
213
+ },
214
+ where: {
215
+ type: "string",
216
+ description: `WHERE filter as JSON (e.g. '{"status":"active"}')`,
217
+ alias: "w"
218
+ },
219
+ "order-by": {
220
+ type: "string",
221
+ description: "Order by field (prefix with - for desc, e.g. -created_at)"
222
+ },
223
+ limit: {
224
+ type: "string",
225
+ description: "Max rows (default: 50)",
226
+ alias: "l"
227
+ },
228
+ offset: {
229
+ type: "string",
230
+ description: "Offset for pagination"
231
+ },
232
+ select: {
233
+ type: "string",
234
+ description: "Comma-separated fields to select",
235
+ alias: "s"
236
+ },
237
+ join: {
238
+ type: "string",
239
+ description: "Join with piped input: stdin:<source_field>=<target_field>",
240
+ alias: "j"
241
+ },
242
+ "api-key": {
243
+ type: "string",
244
+ description: "Use an API key instead of platform JWT"
245
+ },
246
+ output: {
247
+ type: "string",
248
+ description: "Output format: json or table (default: auto-detect)",
249
+ alias: "o"
250
+ }
251
+ },
252
+ async run({ args }) {
253
+ try {
254
+ const { request, mode, ...rest } = await createRequestFn(args["api-key"]);
255
+ const ctx = "ctx" in rest ? rest.ctx : void 0;
256
+ const path = buildPath(mode, "query", args.lens, ctx);
257
+ let where;
258
+ if (args.where) {
259
+ try {
260
+ where = JSON.parse(args.where);
261
+ } catch {
262
+ throw new Error("--where must be valid JSON");
263
+ }
264
+ }
265
+ if (args.join) {
266
+ const joinWhere = await resolveJoin(args.join);
267
+ where = { ...where, ...joinWhere };
268
+ }
269
+ let orderBy;
270
+ if (args["order-by"]) {
271
+ const raw = args["order-by"];
272
+ if (raw.startsWith("-")) {
273
+ orderBy = { field: raw.slice(1), dir: "desc" };
274
+ } else {
275
+ orderBy = { field: raw, dir: "asc" };
276
+ }
277
+ }
278
+ const body = {
279
+ ...where && { where },
280
+ ...orderBy && { orderBy },
281
+ ...args.limit && { limit: parseInt(args.limit, 10) },
282
+ ...args.offset && { offset: parseInt(args.offset, 10) },
283
+ ...args.select && { select: args.select.split(",").map((s) => s.trim()) }
284
+ };
285
+ const data = await request("POST", path, body);
286
+ const fmt = outputFormat(args.output);
287
+ newline();
288
+ if (fmt === "json") {
289
+ printJson(data);
290
+ } else {
291
+ const parts = [bold(args.lens)];
292
+ if (args.where) parts.push(dim(`where: ${args.where}`));
293
+ if (args.join) parts.push(dim(`join: ${args.join}`));
294
+ label("Query", parts.join(" "));
295
+ newline();
296
+ printTable(data);
297
+ }
298
+ } catch (err) {
299
+ error(err.message);
300
+ process.exitCode = 1;
301
+ }
302
+ }
303
+ });
304
+ var similarCommand = defineCommand({
305
+ meta: { name: "similar", description: "Find similar records in a lens" },
306
+ args: {
307
+ lens: {
308
+ type: "positional",
309
+ description: "Lens name",
310
+ required: true
311
+ },
312
+ id: {
313
+ type: "string",
314
+ description: "Source record ID to find similar records for",
315
+ required: true
316
+ },
317
+ limit: {
318
+ type: "string",
319
+ description: "Max results (default: 5)"
320
+ },
321
+ "min-score": {
322
+ type: "string",
323
+ description: "Minimum similarity score 0-1 (default: 0)"
324
+ },
325
+ "api-key": {
326
+ type: "string",
327
+ description: "Use an API key instead of platform JWT"
328
+ },
329
+ output: {
330
+ type: "string",
331
+ description: "Output format: json or table (default: auto-detect)",
332
+ alias: "o"
333
+ }
334
+ },
335
+ async run({ args }) {
336
+ try {
337
+ const { request, mode, ...rest } = await createRequestFn(args["api-key"]);
338
+ const ctx = "ctx" in rest ? rest.ctx : void 0;
339
+ const path = buildPath(mode, "similar", args.lens, ctx);
340
+ const body = {
341
+ id: args.id,
342
+ ...args.limit && { limit: parseInt(args.limit, 10) },
343
+ ...args["min-score"] && { minScore: parseFloat(args["min-score"]) }
344
+ };
345
+ const data = await request("POST", path, body);
346
+ const fmt = outputFormat(args.output);
347
+ newline();
348
+ if (fmt === "json") {
349
+ printJson(data);
350
+ } else {
351
+ label("Similar", `${bold(args.lens)} \u2192 id: ${args.id}`);
352
+ newline();
353
+ printTable(data);
354
+ }
355
+ } catch (err) {
356
+ error(err.message);
357
+ process.exitCode = 1;
358
+ }
359
+ }
360
+ });
361
+ var run_default = defineCommand({
362
+ meta: {
363
+ name: "run",
364
+ description: "Run search, query, or similar operations against your data"
365
+ },
366
+ subCommands: {
367
+ search: searchCommand,
368
+ query: queryCommand,
369
+ similar: similarCommand
370
+ }
371
+ });
372
+ export {
373
+ run_default as default
374
+ };
375
+ //# sourceMappingURL=run-IR5B4AE3.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/commands/run.ts"],"sourcesContent":["import { defineCommand } from 'citty'\nimport { loadContext } from '../lib/context.js'\nimport { createApiClient } from '../lib/api.js'\nimport { error, info, dim, bold, newline, table, label } from '../lib/output.js'\n\n// ── Shared helpers ─────────────────────────────────────────\n\ninterface RunResponse {\n results?: Array<Record<string, unknown>>\n rows?: Array<Record<string, unknown>>\n meta: Record<string, unknown>\n}\n\nfunction isApiKey(value: string): boolean {\n return value.startsWith('sk_') || value.startsWith('pk_') || value.startsWith('ik_')\n}\n\nfunction outputFormat(flag: string | undefined): 'json' | 'table' {\n if (flag === 'json') return 'json'\n if (flag === 'table') return 'table'\n // Auto-detect: pipe → json, TTY → table\n return process.stdout.isTTY ? 'table' : 'json'\n}\n\nfunction printJson(data: RunResponse): void {\n console.log(JSON.stringify(data, null, 2))\n}\n\nfunction printTable(data: RunResponse): void {\n const items = data.results ?? data.rows ?? []\n if (items.length === 0) {\n info('No results')\n return\n }\n\n // Collect all unique keys across all items\n const allKeys = new Set<string>()\n for (const item of items) {\n for (const key of Object.keys(item)) {\n allKeys.add(key)\n }\n }\n const keys = [...allKeys]\n\n // Header\n const headerRow = keys.map((k) => bold(k))\n const rows = [headerRow]\n\n // Data rows\n for (const item of items) {\n rows.push(keys.map((k) => formatCell(item[k])))\n }\n\n table(rows)\n\n // Meta line\n newline()\n const meta = data.meta\n const parts: string[] = []\n if (meta.count !== undefined) parts.push(`${meta.count} result${meta.count === 1 ? '' : 's'}`)\n if (meta.durationMs !== undefined) parts.push(`${meta.durationMs}ms`)\n if (meta.total !== undefined) parts.push(`total: ${meta.total}`)\n if (meta.nextCursor) parts.push(`next cursor: ${meta.nextCursor}`)\n if (parts.length > 0) info(dim(parts.join(' · ')))\n}\n\nfunction formatCell(value: unknown): string {\n if (value === null || value === undefined) return dim('null')\n if (typeof value === 'string') {\n // Truncate long strings for table display\n return value.length > 60 ? value.slice(0, 57) + '...' : value\n }\n if (typeof value === 'object') return dim(JSON.stringify(value))\n return String(value)\n}\n\nasync function readStdin(): Promise<string> {\n const chunks: Buffer[] = []\n for await (const chunk of process.stdin) {\n chunks.push(chunk as Buffer)\n }\n return Buffer.concat(chunks).toString('utf-8')\n}\n\n/**\n * Parse --join flag: \"stdin:<their_field>=<our_field>\"\n * Reads piped JSON from stdin, extracts values, returns a WHERE IN clause.\n */\nasync function resolveJoin(\n joinSpec: string,\n): Promise<Record<string, unknown>> {\n const match = joinSpec.match(/^stdin:(\\w+)=(\\w+)$/)\n if (!match) {\n throw new Error(\n `Invalid --join format. Expected: stdin:<source_field>=<target_field>\\n` +\n ` Example: --join stdin:id=user_id`,\n )\n }\n const [, sourceField, targetField] = match\n\n const raw = await readStdin()\n let parsed: RunResponse\n try {\n parsed = JSON.parse(raw)\n } catch {\n throw new Error('Failed to parse stdin as JSON. Pipe output from another `semilayer run` command with --output json.')\n }\n\n const items = parsed.results ?? parsed.rows ?? []\n if (items.length === 0) {\n throw new Error('Piped input contains no results/rows to join on.')\n }\n\n const values = items\n .map((item) => item[sourceField!])\n .filter((v) => v !== null && v !== undefined)\n\n if (values.length === 0) {\n throw new Error(`Field '${sourceField}' not found in piped results.`)\n }\n\n return { [targetField!]: { $in: values } }\n}\n\n/**\n * Build request URL + headers depending on auth mode:\n * - API key: call /v1/<op>/<lens> directly with Bearer key\n * - JWT: call /v1/orgs/.../run/<op>/<lens> with platform token\n */\nasync function createRequestFn(apiKeyFlag: string | undefined) {\n if (apiKeyFlag) {\n // Direct API key mode\n const key = apiKeyFlag\n if (!isApiKey(key)) {\n throw new Error('--api-key must be an API key (sk_*, pk_*, or ik_*)')\n }\n\n // Need a service URL — try context, fallback to default\n const ctx = await loadContext()\n const serviceUrl = ctx?.serviceUrl ?? 'https://api.semilayer.com'\n\n return {\n mode: 'apikey' as const,\n async request<T>(method: string, path: string, body?: unknown): Promise<T> {\n const res = await fetch(`${serviceUrl}${path}`, {\n method,\n headers: {\n Authorization: `Bearer ${key}`,\n 'Content-Type': 'application/json',\n },\n body: body !== undefined ? JSON.stringify(body) : undefined,\n })\n if (!res.ok) {\n const text = await res.text().catch(() => '')\n throw new Error(`API error ${res.status}: ${text}`)\n }\n return res.json() as Promise<T>\n },\n }\n }\n\n // JWT mode via standard API client\n const ctx = await loadContext()\n if (!ctx) {\n throw new Error('No .semilayerrc found. Run `semilayer init` first, or use --api-key.')\n }\n\n const api = await createApiClient()\n\n return {\n mode: 'jwt' as const,\n ctx,\n async request<T>(method: string, path: string, body?: unknown): Promise<T> {\n if (method === 'POST') return api.post<T>(path, body)\n return api.get<T>(path)\n },\n }\n}\n\nfunction buildPath(\n mode: 'apikey' | 'jwt',\n op: string,\n lens: string,\n ctx?: { orgSlug: string; projectSlug: string; envSlug: string },\n): string {\n if (mode === 'apikey') {\n return `/v1/${op}/${lens}`\n }\n return `/v1/orgs/${ctx!.orgSlug}/projects/${ctx!.projectSlug}/envs/${ctx!.envSlug}/run/${op}/${lens}`\n}\n\n// ── Subcommands ────────────────────────────────────────────\n\nconst searchCommand = defineCommand({\n meta: { name: 'search', description: 'Semantic search on a lens' },\n args: {\n lens: {\n type: 'positional',\n description: 'Lens name to search',\n required: true,\n },\n query: {\n type: 'string',\n description: 'Search query text',\n required: true,\n alias: 'q',\n },\n limit: {\n type: 'string',\n description: 'Max results (default: 10)',\n },\n 'min-score': {\n type: 'string',\n description: 'Minimum similarity score 0-1 (default: 0)',\n },\n 'api-key': {\n type: 'string',\n description: 'Use an API key instead of platform JWT',\n },\n output: {\n type: 'string',\n description: 'Output format: json or table (default: auto-detect)',\n alias: 'o',\n },\n },\n async run({ args }) {\n try {\n const { request, mode, ...rest } = await createRequestFn(args['api-key'])\n const ctx = 'ctx' in rest ? rest.ctx : undefined\n const path = buildPath(mode, 'search', args.lens, ctx)\n\n const body = {\n query: args.query,\n ...(args.limit && { limit: parseInt(args.limit, 10) }),\n ...(args['min-score'] && { minScore: parseFloat(args['min-score']) }),\n }\n\n const data = await request<RunResponse>('POST', path, body)\n const fmt = outputFormat(args.output)\n\n newline()\n if (fmt === 'json') {\n printJson(data)\n } else {\n label('Search', `${bold(args.lens)} → \"${args.query}\"`)\n newline()\n printTable(data)\n }\n } catch (err) {\n error((err as Error).message)\n process.exitCode = 1\n }\n },\n})\n\nconst queryCommand = defineCommand({\n meta: { name: 'query', description: 'Direct query on a lens' },\n args: {\n lens: {\n type: 'positional',\n description: 'Lens name to query',\n required: true,\n },\n where: {\n type: 'string',\n description: 'WHERE filter as JSON (e.g. \\'{\"status\":\"active\"}\\')',\n alias: 'w',\n },\n 'order-by': {\n type: 'string',\n description: 'Order by field (prefix with - for desc, e.g. -created_at)',\n },\n limit: {\n type: 'string',\n description: 'Max rows (default: 50)',\n alias: 'l',\n },\n offset: {\n type: 'string',\n description: 'Offset for pagination',\n },\n select: {\n type: 'string',\n description: 'Comma-separated fields to select',\n alias: 's',\n },\n join: {\n type: 'string',\n description: 'Join with piped input: stdin:<source_field>=<target_field>',\n alias: 'j',\n },\n 'api-key': {\n type: 'string',\n description: 'Use an API key instead of platform JWT',\n },\n output: {\n type: 'string',\n description: 'Output format: json or table (default: auto-detect)',\n alias: 'o',\n },\n },\n async run({ args }) {\n try {\n const { request, mode, ...rest } = await createRequestFn(args['api-key'])\n const ctx = 'ctx' in rest ? rest.ctx : undefined\n const path = buildPath(mode, 'query', args.lens, ctx)\n\n // Build WHERE clause\n let where: Record<string, unknown> | undefined\n if (args.where) {\n try {\n where = JSON.parse(args.where)\n } catch {\n throw new Error('--where must be valid JSON')\n }\n }\n\n // Join from stdin\n if (args.join) {\n const joinWhere = await resolveJoin(args.join)\n where = { ...where, ...joinWhere }\n }\n\n // Parse orderBy\n let orderBy: { field: string; dir?: 'asc' | 'desc' } | undefined\n if (args['order-by']) {\n const raw = args['order-by']\n if (raw.startsWith('-')) {\n orderBy = { field: raw.slice(1), dir: 'desc' }\n } else {\n orderBy = { field: raw, dir: 'asc' }\n }\n }\n\n const body = {\n ...(where && { where }),\n ...(orderBy && { orderBy }),\n ...(args.limit && { limit: parseInt(args.limit, 10) }),\n ...(args.offset && { offset: parseInt(args.offset, 10) }),\n ...(args.select && { select: args.select.split(',').map((s) => s.trim()) }),\n }\n\n const data = await request<RunResponse>('POST', path, body)\n const fmt = outputFormat(args.output)\n\n newline()\n if (fmt === 'json') {\n printJson(data)\n } else {\n const parts = [bold(args.lens)]\n if (args.where) parts.push(dim(`where: ${args.where}`))\n if (args.join) parts.push(dim(`join: ${args.join}`))\n label('Query', parts.join(' '))\n newline()\n printTable(data)\n }\n } catch (err) {\n error((err as Error).message)\n process.exitCode = 1\n }\n },\n})\n\nconst similarCommand = defineCommand({\n meta: { name: 'similar', description: 'Find similar records in a lens' },\n args: {\n lens: {\n type: 'positional',\n description: 'Lens name',\n required: true,\n },\n id: {\n type: 'string',\n description: 'Source record ID to find similar records for',\n required: true,\n },\n limit: {\n type: 'string',\n description: 'Max results (default: 5)',\n },\n 'min-score': {\n type: 'string',\n description: 'Minimum similarity score 0-1 (default: 0)',\n },\n 'api-key': {\n type: 'string',\n description: 'Use an API key instead of platform JWT',\n },\n output: {\n type: 'string',\n description: 'Output format: json or table (default: auto-detect)',\n alias: 'o',\n },\n },\n async run({ args }) {\n try {\n const { request, mode, ...rest } = await createRequestFn(args['api-key'])\n const ctx = 'ctx' in rest ? rest.ctx : undefined\n const path = buildPath(mode, 'similar', args.lens, ctx)\n\n const body = {\n id: args.id,\n ...(args.limit && { limit: parseInt(args.limit, 10) }),\n ...(args['min-score'] && { minScore: parseFloat(args['min-score']) }),\n }\n\n const data = await request<RunResponse>('POST', path, body)\n const fmt = outputFormat(args.output)\n\n newline()\n if (fmt === 'json') {\n printJson(data)\n } else {\n label('Similar', `${bold(args.lens)} → id: ${args.id}`)\n newline()\n printTable(data)\n }\n } catch (err) {\n error((err as Error).message)\n process.exitCode = 1\n }\n },\n})\n\n// ── Parent command ─────────────────────────────────────────\n\nexport default defineCommand({\n meta: {\n name: 'run',\n description: 'Run search, query, or similar operations against your data',\n },\n subCommands: {\n search: searchCommand,\n query: queryCommand,\n similar: similarCommand,\n },\n})\n"],"mappings":"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","names":["ctx"]}
@@ -0,0 +1,170 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ envPath
4
+ } from "./chunk-ALA4X7UU.js";
5
+ import {
6
+ loadContext
7
+ } from "./chunk-QMF7LD67.js";
8
+ import {
9
+ confirm,
10
+ input,
11
+ secret,
12
+ select
13
+ } from "./chunk-QXIVJY7K.js";
14
+ import {
15
+ createApiClient
16
+ } from "./chunk-T3UROBMA.js";
17
+ import "./chunk-7TA63VHV.js";
18
+ import {
19
+ bold,
20
+ dim,
21
+ error,
22
+ info,
23
+ newline,
24
+ success,
25
+ table
26
+ } from "./chunk-WZYOSGN3.js";
27
+
28
+ // src/commands/sources.ts
29
+ import { defineCommand } from "citty";
30
+ var list = defineCommand({
31
+ meta: { name: "list", description: "List connected sources" },
32
+ async run() {
33
+ try {
34
+ const ctx = await loadContext();
35
+ if (!ctx) {
36
+ error("No .semilayerrc found. Run `semilayer init` first.");
37
+ process.exitCode = 1;
38
+ return;
39
+ }
40
+ const api = await createApiClient();
41
+ const data = await api.get(`${envPath(ctx)}/sources`);
42
+ newline();
43
+ if (data.sources.length === 0) {
44
+ info("No sources connected. Run `semilayer sources connect` to add one.");
45
+ } else {
46
+ console.log(` ${bold("Sources:")}`);
47
+ table(data.sources.map((s) => [
48
+ ` ${s.name}`,
49
+ dim(s.bridge),
50
+ dim(new Date(s.createdAt).toLocaleDateString())
51
+ ]));
52
+ }
53
+ newline();
54
+ } catch (err) {
55
+ error(err.message);
56
+ process.exitCode = 1;
57
+ }
58
+ }
59
+ });
60
+ var BRIDGE_CHOICES = [
61
+ "@semilayer/bridge-postgres"
62
+ ];
63
+ var connect = defineCommand({
64
+ meta: { name: "connect", description: "Connect a new database source" },
65
+ args: {
66
+ name: { type: "string", description: "Source name" },
67
+ bridge: { type: "string", description: "Bridge package name" }
68
+ },
69
+ async run({ args }) {
70
+ try {
71
+ const ctx = await loadContext();
72
+ if (!ctx) {
73
+ error("No .semilayerrc found. Run `semilayer init` first.");
74
+ process.exitCode = 1;
75
+ return;
76
+ }
77
+ newline();
78
+ console.log(` ${bold("Connect a database source")}`);
79
+ newline();
80
+ const name = args.name || await input("Source name", "main");
81
+ let bridge = args.bridge;
82
+ if (!bridge) {
83
+ console.log(` ${bold("Select a bridge:")}`);
84
+ bridge = await select("Choice:", BRIDGE_CHOICES);
85
+ }
86
+ let config;
87
+ if (bridge.includes("postgres")) {
88
+ newline();
89
+ info("Enter your PostgreSQL connection details:");
90
+ newline();
91
+ const method = await select("Connection method:", ["Connection string", "Individual fields"]);
92
+ if (method === "Connection string") {
93
+ const url = await secret("Connection string (postgresql://...)");
94
+ config = { url };
95
+ } else {
96
+ const host = await input("Host", "localhost");
97
+ const port = await input("Port", "5432");
98
+ const database = await input("Database");
99
+ const user = await input("Username");
100
+ const password = await secret("Password");
101
+ const ssl = await confirm("Use SSL?");
102
+ config = {
103
+ url: `postgresql://${user}:${password}@${host}:${port}/${database}${ssl ? "?sslmode=require" : ""}`
104
+ };
105
+ }
106
+ } else {
107
+ newline();
108
+ info("Enter connection config as key=value pairs (empty line to finish):");
109
+ config = {};
110
+ while (true) {
111
+ const pair = await input("key=value (or empty to finish)");
112
+ if (!pair) break;
113
+ const [key, ...rest] = pair.split("=");
114
+ if (key && rest.length > 0) {
115
+ config[key.trim()] = rest.join("=").trim();
116
+ }
117
+ }
118
+ }
119
+ const api = await createApiClient();
120
+ await api.post(`${envPath(ctx)}/sources`, { name, bridge, config });
121
+ newline();
122
+ success(`Source ${bold(name)} connected via ${dim(bridge)}`);
123
+ info("Credentials are encrypted server-side.");
124
+ newline();
125
+ info(`Next: run ${bold("semilayer push --resume-ingest")} to start indexing.`);
126
+ } catch (err) {
127
+ error(err.message);
128
+ process.exitCode = 1;
129
+ }
130
+ }
131
+ });
132
+ var del = defineCommand({
133
+ meta: { name: "delete", description: "Delete a connected source" },
134
+ args: {
135
+ "source-id": { type: "string", description: "Source ID to delete", required: true }
136
+ },
137
+ async run({ args }) {
138
+ try {
139
+ const ctx = await loadContext();
140
+ if (!ctx) {
141
+ error("No .semilayerrc found. Run `semilayer init` first.");
142
+ process.exitCode = 1;
143
+ return;
144
+ }
145
+ const ok = await confirm(`Delete source ${args["source-id"]}?`);
146
+ if (!ok) {
147
+ info("Aborted.");
148
+ return;
149
+ }
150
+ const api = await createApiClient();
151
+ await api.del(`${envPath(ctx)}/sources/${args["source-id"]}`);
152
+ success("Source deleted.");
153
+ } catch (err) {
154
+ error(err.message);
155
+ process.exitCode = 1;
156
+ }
157
+ }
158
+ });
159
+ var sources_default = defineCommand({
160
+ meta: { name: "sources", description: "Manage database sources" },
161
+ subCommands: {
162
+ list,
163
+ connect,
164
+ delete: del
165
+ }
166
+ });
167
+ export {
168
+ sources_default as default
169
+ };
170
+ //# sourceMappingURL=sources-S52HUWRK.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/commands/sources.ts"],"sourcesContent":["import { defineCommand } from 'citty'\nimport type { Source } from '@semilayer/core'\nimport { createApiClient } from '../lib/api.js'\nimport { loadContext } from '../lib/context.js'\nimport { envPath } from '../lib/env-path.js'\nimport { success, error, info, bold, dim, newline, table } from '../lib/output.js'\nimport { input, secret, select, confirm } from '../lib/prompt.js'\n\n// ── List ─────────────────────────────────────────────────────────\n\nconst list = defineCommand({\n meta: { name: 'list', description: 'List connected sources' },\n async run() {\n try {\n const ctx = await loadContext()\n if (!ctx) { error('No .semilayerrc found. Run `semilayer init` first.'); process.exitCode = 1; return }\n\n const api = await createApiClient()\n const data = await api.get<{ sources: Source[] }>(`${envPath(ctx)}/sources`)\n\n newline()\n if (data.sources.length === 0) {\n info('No sources connected. Run `semilayer sources connect` to add one.')\n } else {\n console.log(` ${bold('Sources:')}`)\n table(data.sources.map((s) => [\n ` ${s.name}`,\n dim(s.bridge),\n dim(new Date(s.createdAt).toLocaleDateString()),\n ]))\n }\n newline()\n } catch (err) {\n error((err as Error).message)\n process.exitCode = 1\n }\n },\n})\n\n// ── Connect ──────────────────────────────────────────────────────\n\nconst BRIDGE_CHOICES = [\n '@semilayer/bridge-postgres',\n]\n\nconst connect = defineCommand({\n meta: { name: 'connect', description: 'Connect a new database source' },\n args: {\n name: { type: 'string', description: 'Source name' },\n bridge: { type: 'string', description: 'Bridge package name' },\n },\n async run({ args }) {\n try {\n const ctx = await loadContext()\n if (!ctx) { error('No .semilayerrc found. Run `semilayer init` first.'); process.exitCode = 1; return }\n\n newline()\n console.log(` ${bold('Connect a database source')}`)\n newline()\n\n // Source name\n const name = args.name || await input('Source name', 'main')\n\n // Bridge selection\n let bridge = args.bridge\n if (!bridge) {\n console.log(` ${bold('Select a bridge:')}`)\n bridge = await select('Choice:', BRIDGE_CHOICES)\n }\n\n // Bridge-specific config prompts\n let config: Record<string, unknown>\n\n if (bridge.includes('postgres')) {\n newline()\n info('Enter your PostgreSQL connection details:')\n newline()\n\n const method = await select('Connection method:', ['Connection string', 'Individual fields'])\n\n if (method === 'Connection string') {\n const url = await secret('Connection string (postgresql://...)')\n config = { url }\n } else {\n const host = await input('Host', 'localhost')\n const port = await input('Port', '5432')\n const database = await input('Database')\n const user = await input('Username')\n const password = await secret('Password')\n const ssl = await confirm('Use SSL?')\n config = {\n url: `postgresql://${user}:${password}@${host}:${port}/${database}${ssl ? '?sslmode=require' : ''}`,\n }\n }\n } else {\n // Generic config for unknown bridges\n newline()\n info('Enter connection config as key=value pairs (empty line to finish):')\n config = {}\n while (true) {\n const pair = await input('key=value (or empty to finish)')\n if (!pair) break\n const [key, ...rest] = pair.split('=')\n if (key && rest.length > 0) {\n config[key.trim()] = rest.join('=').trim()\n }\n }\n }\n\n // Send to API (server encrypts the config)\n const api = await createApiClient()\n await api.post(`${envPath(ctx)}/sources`, { name, bridge, config })\n\n newline()\n success(`Source ${bold(name)} connected via ${dim(bridge)}`)\n info('Credentials are encrypted server-side.')\n newline()\n info(`Next: run ${bold('semilayer push --resume-ingest')} to start indexing.`)\n } catch (err) {\n error((err as Error).message)\n process.exitCode = 1\n }\n },\n})\n\n// ── Delete ────────────���──────────────────────────────────────────\n\nconst del = defineCommand({\n meta: { name: 'delete', description: 'Delete a connected source' },\n args: {\n 'source-id': { type: 'string', description: 'Source ID to delete', required: true },\n },\n async run({ args }) {\n try {\n const ctx = await loadContext()\n if (!ctx) { error('No .semilayerrc found. Run `semilayer init` first.'); process.exitCode = 1; return }\n\n const ok = await confirm(`Delete source ${args['source-id']}?`)\n if (!ok) { info('Aborted.'); return }\n\n const api = await createApiClient()\n await api.del(`${envPath(ctx)}/sources/${args['source-id']}`)\n success('Source deleted.')\n } catch (err) {\n error((err as Error).message)\n process.exitCode = 1\n }\n },\n})\n\n// ── Main ───��─────────────────────────────────────────────────────\n\nexport default defineCommand({\n meta: { name: 'sources', description: 'Manage database sources' },\n subCommands: {\n list,\n connect,\n delete: del,\n },\n})\n"],"mappings":"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","names":[]}