@withone/cli 1.47.7 → 1.47.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -8300,6 +8300,10 @@ function registerSyncSubcommands(sync) {
8300
8300
  sync.command("sql <platform/model> <sql>").description("Run a read-only SELECT / WITH / EXPLAIN against the memory store (type-scoped helper)").action(async (platformModel, sql) => {
8301
8301
  await syncSqlCommand(platformModel, sql);
8302
8302
  });
8303
+ sync.command("schema <platform/model>").description("Inspect the JSON structure of synced records (field paths, types, examples) \u2014 useful before writing `sync sql` queries").action(async (platformModel) => {
8304
+ const { syncSchemaCommand } = await import("./schema-DXHEU47V.js");
8305
+ await syncSchemaCommand(platformModel);
8306
+ });
8303
8307
  sync.command("delete <platform/model>").description('Delete records from local sync data (e.g. one sync delete notion/pages --id "abc-123")').option("--id <value>", "Delete record by ID").option("--where <conditions>", 'Delete records matching conditions (e.g. "status=archived")').option("--where-sql <predicate>", `Delete using a raw SQL WHERE clause (e.g. "json_extract(data, '$.type') = 'promotion'")`).option("--yes", "Skip confirmation prompt").action(async (platformModel, options) => {
8304
8308
  await syncDeleteCommand(platformModel, options);
8305
8309
  });
@@ -10019,6 +10023,7 @@ one --agent sync run stripe
10019
10023
  one --agent mem sync run stripe # identical (alias)
10020
10024
 
10021
10025
  # 5. Query + search (read from memory)
10026
+ one --agent sync schema stripe/customers # inspect field paths/types first
10022
10027
  one --agent sync query stripe/balanceTransactions --where "status=available" --limit 20
10023
10028
  one --agent sync query stripe/customers --where 'address.city=SF' # dotted --where paths
10024
10029
  one --agent sync search "refund" --platform stripe # hybrid FTS + semantic
@@ -10259,6 +10264,7 @@ Every \`sync X\` command is also exposed as \`mem sync X\` \u2014 same handlers,
10259
10264
  | \`sync suggest-searchable <plat>/<model>\` | Rank candidate \`memory.searchable\` paths by signal density; emits paste-ready config |
10260
10265
  | \`sync run <platform>\` | Sync data (\`--full-refresh\`, \`--since\`, \`--dry-run\`, \`--no-memory\`) |
10261
10266
  | \`sync query <plat>/<model>\` | Query memory with \`--where\` (dotted paths), \`--after/before\` |
10267
+ | \`sync schema <plat>/<model>\` | Inspect the JSON structure of synced records (field paths, types, examples) \u2014 run before writing \`--where\` / query paths |
10262
10268
  | \`sync search "<query>"\` | Hybrid FTS + semantic across all synced data |
10263
10269
  | \`sync list [platform]\` | Show profiles, record counts, freshness |
10264
10270
  | \`sync schedule add/list/status/remove/repair\` | Manage cron schedules |
@@ -0,0 +1,109 @@
1
+ import {
2
+ isAgentMode,
3
+ note,
4
+ okJson,
5
+ requireMemoryInit
6
+ } from "./chunk-HS5AHQ4V.js";
7
+ import {
8
+ getBackend
9
+ } from "./chunk-OADHUAEU.js";
10
+ import "./chunk-TXTRXV74.js";
11
+ import "./chunk-K6MWE2ZH.js";
12
+
13
+ // src/lib/memory/sync/schema.ts
14
+ import pc from "picocolors";
15
+ var SAMPLE_SIZE = 100;
16
+ function typeOf(v) {
17
+ if (v === null) return "null";
18
+ if (Array.isArray(v)) return "array";
19
+ return typeof v;
20
+ }
21
+ function exampleOf(v) {
22
+ if (typeof v === "string") return v.length > 60 ? `${v.slice(0, 57)}\u2026` : v;
23
+ return v;
24
+ }
25
+ function addPath(path, value, acc) {
26
+ const t = typeOf(value);
27
+ let typeLabel;
28
+ if (t === "array") {
29
+ const arr = value;
30
+ const elemType = arr.length ? typeOf(arr[0]) : "unknown";
31
+ typeLabel = `array[${elemType}]`;
32
+ } else {
33
+ typeLabel = t;
34
+ }
35
+ const entry = acc.get(path) ?? { types: /* @__PURE__ */ new Set(), hasExample: false, presence: 0 };
36
+ entry.types.add(typeLabel);
37
+ entry.presence += 1;
38
+ if (!entry.hasExample && t !== "object" && t !== "array" && value !== null && value !== void 0) {
39
+ entry.example = exampleOf(value);
40
+ entry.hasExample = true;
41
+ }
42
+ acc.set(path, entry);
43
+ if (t === "object") {
44
+ for (const [k, v] of Object.entries(value)) {
45
+ addPath(path ? `${path}.${k}` : k, v, acc);
46
+ }
47
+ } else if (t === "array") {
48
+ const arr = value;
49
+ if (arr.length && typeOf(arr[0]) === "object") {
50
+ for (const [k, v] of Object.entries(arr[0])) {
51
+ addPath(`${path}[].${k}`, v, acc);
52
+ }
53
+ }
54
+ }
55
+ }
56
+ function inferSyncSchema(dataRecords) {
57
+ const acc = /* @__PURE__ */ new Map();
58
+ for (const data of dataRecords) {
59
+ if (!data || typeof data !== "object" || Array.isArray(data)) continue;
60
+ for (const [k, v] of Object.entries(data)) addPath(k, v, acc);
61
+ }
62
+ return [...acc.entries()].map(([path, e]) => ({
63
+ path,
64
+ types: [...e.types].sort(),
65
+ ...e.hasExample ? { example: e.example } : {},
66
+ presence: e.presence
67
+ })).sort((a, b) => a.path.localeCompare(b.path));
68
+ }
69
+ async function syncSchemaCommand(platformModel, _options = {}) {
70
+ requireMemoryInit();
71
+ const type = platformModel;
72
+ const backend = await getBackend();
73
+ let recordCount = 0;
74
+ try {
75
+ recordCount = await backend.count(type, { status: "active" });
76
+ } catch {
77
+ }
78
+ const records = await backend.list(type, { limit: SAMPLE_SIZE, status: "active" });
79
+ if (records.length === 0) {
80
+ if (isAgentMode()) {
81
+ okJson({ type, recordCount: 0, sampled: 0, fields: [] });
82
+ return;
83
+ }
84
+ note(`No records found for "${type}". Run \`one sync run <platform>\` first, or check \`one --agent sync status\`.`, "Schema");
85
+ return;
86
+ }
87
+ const fields = inferSyncSchema(records.map((r) => r.data));
88
+ if (isAgentMode()) {
89
+ okJson({ type, recordCount, sampled: records.length, fields });
90
+ return;
91
+ }
92
+ console.log();
93
+ console.log(`${pc.bold(type)} ${pc.dim(`(${recordCount.toLocaleString()} record${recordCount === 1 ? "" : "s"}, sampled ${records.length})`)}`);
94
+ console.log();
95
+ const pathWidth = Math.min(Math.max(...fields.map((f) => f.path.length), 4) + 2, 50);
96
+ const typeWidth = Math.max(...fields.map((f) => f.types.join("|").length), 4) + 2;
97
+ for (const f of fields) {
98
+ const optional = f.presence < records.length ? pc.yellow(" ?") : "";
99
+ const ex = f.example !== void 0 ? pc.dim(JSON.stringify(f.example)) : "";
100
+ console.log(` ${f.path.padEnd(pathWidth)}${pc.cyan(f.types.join("|").padEnd(typeWidth))}${ex}${optional}`);
101
+ }
102
+ console.log();
103
+ console.log(pc.dim(` ? = present in only some sampled records (optional/sparse field)`));
104
+ console.log();
105
+ }
106
+ export {
107
+ inferSyncSchema,
108
+ syncSchemaCommand
109
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@withone/cli",
3
- "version": "1.47.7",
3
+ "version": "1.47.8",
4
4
  "description": "CLI for managing One",
5
5
  "type": "module",
6
6
  "files": [
@@ -229,6 +229,7 @@ one --agent sync test attio/attioPeople --show-searchable
229
229
 
230
230
  # Run — memory is always written; pass --no-memory to skip (rare)
231
231
  one --agent sync run stripe
232
+ one --agent sync schema stripe/customers # inspect field paths/types before querying
232
233
  one --agent sync query stripe/balanceTransactions --where "status=available" --limit 20
233
234
  one --agent sync search "refund" # hybrid across all synced platforms
234
235
  one --agent sync list stripe # progress + freshness