@onyx.dev/onyx-database 1.0.0 → 1.0.3

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.
@@ -78,7 +78,7 @@ function readEnv(targetId) {
78
78
  return res;
79
79
  }
80
80
  async function readProjectFile(databaseId) {
81
- if (!isNode) return {};
81
+ if (!isNode) return { config: {} };
82
82
  const fs = await nodeImport("node:fs/promises");
83
83
  const path2 = await nodeImport("node:path");
84
84
  const cwd = gProcess?.cwd?.() ?? ".";
@@ -87,7 +87,7 @@ async function readProjectFile(databaseId) {
87
87
  const sanitized = txt.replace(/[\r\n]+/g, "");
88
88
  const json = dropUndefined(JSON.parse(sanitized));
89
89
  dbg("project file:", p, "\u2192", mask(json));
90
- return json;
90
+ return { config: json, path: p };
91
91
  };
92
92
  if (databaseId) {
93
93
  const specific = path2.resolve(cwd, `onyx-database-${databaseId}.json`);
@@ -102,11 +102,11 @@ async function readProjectFile(databaseId) {
102
102
  return await tryRead(fallback);
103
103
  } catch {
104
104
  dbg("project file not found:", fallback);
105
- return {};
105
+ return { config: {} };
106
106
  }
107
107
  }
108
108
  async function readHomeProfile(databaseId) {
109
- if (!isNode) return {};
109
+ if (!isNode) return { config: {} };
110
110
  const fs = await nodeImport("node:fs/promises");
111
111
  const os = await nodeImport("node:os");
112
112
  const path2 = await nodeImport("node:path");
@@ -126,7 +126,7 @@ async function readHomeProfile(databaseId) {
126
126
  const sanitized = txt.replace(/[\r\n]+/g, "");
127
127
  const json = dropUndefined(JSON.parse(sanitized));
128
128
  dbg("home profile used:", p, "\u2192", mask(json));
129
- return json;
129
+ return { config: json, path: p };
130
130
  } catch (e) {
131
131
  const msg = e instanceof Error ? e.message : String(e);
132
132
  throw new OnyxConfigError(`Failed to read ${p}: ${msg}`);
@@ -145,7 +145,7 @@ async function readHomeProfile(databaseId) {
145
145
  dbg("no home-root fallback:", defaultInHome);
146
146
  if (!await fileExists(dir)) {
147
147
  dbg("~/.onyx does not exist:", dir);
148
- return {};
148
+ return { config: {} };
149
149
  }
150
150
  const files = await fs.readdir(dir).catch(() => []);
151
151
  const matches = files.filter((f) => f.startsWith("onyx-database-") && f.endsWith(".json"));
@@ -159,10 +159,10 @@ async function readHomeProfile(databaseId) {
159
159
  );
160
160
  }
161
161
  dbg("no usable home profiles found in", dir);
162
- return {};
162
+ return { config: {} };
163
163
  }
164
164
  async function readConfigPath(p) {
165
- if (!isNode) return {};
165
+ if (!isNode) return { config: {} };
166
166
  const fs = await nodeImport("node:fs/promises");
167
167
  const path2 = await nodeImport("node:path");
168
168
  const cwd = gProcess?.cwd?.() ?? ".";
@@ -172,7 +172,7 @@ async function readConfigPath(p) {
172
172
  const sanitized = txt.replace(/[\r\n]+/g, "");
173
173
  const json = dropUndefined(JSON.parse(sanitized));
174
174
  dbg("config path:", resolved, "\u2192", mask(json));
175
- return json;
175
+ return { config: json, path: resolved };
176
176
  } catch (e) {
177
177
  const msg = e instanceof Error ? e.message : String(e);
178
178
  throw new OnyxConfigError(`Failed to read ${resolved}: ${msg}`);
@@ -183,7 +183,8 @@ async function resolveConfig(input) {
183
183
  const env = readEnv(input?.databaseId);
184
184
  let cfgPath = {};
185
185
  if (configPath) {
186
- cfgPath = await readConfigPath(configPath);
186
+ const cfgRes = await readConfigPath(configPath);
187
+ cfgPath = cfgRes.config;
187
188
  }
188
189
  const targetId = input?.databaseId ?? env.databaseId ?? cfgPath.databaseId;
189
190
  let haveDbId = !!(input?.databaseId ?? env.databaseId ?? cfgPath.databaseId);
@@ -191,14 +192,16 @@ async function resolveConfig(input) {
191
192
  let haveApiSecret = !!(input?.apiSecret ?? env.apiSecret ?? cfgPath.apiSecret);
192
193
  let project = {};
193
194
  if (!(haveDbId && haveApiKey && haveApiSecret)) {
194
- project = await readProjectFile(targetId);
195
+ const projRes = await readProjectFile(targetId);
196
+ project = projRes.config;
195
197
  if (project.databaseId) haveDbId = true;
196
198
  if (project.apiKey) haveApiKey = true;
197
199
  if (project.apiSecret) haveApiSecret = true;
198
200
  }
199
201
  let home = {};
200
202
  if (!(haveDbId && haveApiKey && haveApiSecret)) {
201
- home = await readHomeProfile(targetId);
203
+ const homeRes = await readHomeProfile(targetId);
204
+ home = homeRes.config;
202
205
  }
203
206
  const merged = {
204
207
  baseUrl: DEFAULT_BASE_URL,
@@ -217,6 +220,10 @@ async function resolveConfig(input) {
217
220
  const fetchImpl = merged.fetch ?? (typeof gfetch === "function" ? (u, i) => gfetch(u, i) : async () => {
218
221
  throw new OnyxConfigError("No fetch available; provide OnyxConfig.fetch");
219
222
  });
223
+ const retryConfig = input?.retry ?? env.retry ?? cfgPath.retry ?? project.retry ?? home.retry ?? {};
224
+ const retryEnabled = retryConfig.enabled ?? true;
225
+ const maxRetries = retryConfig.maxRetries ?? 3;
226
+ const retryInitialDelayMs = retryConfig.initialDelayMs ?? 300;
220
227
  const missing = [];
221
228
  if (!databaseId) missing.push("databaseId");
222
229
  if (!apiKey) missing.push("apiKey");
@@ -239,7 +246,16 @@ async function resolveConfig(input) {
239
246
  `Missing required config: ${missing.join(", ")}. Sources: ${sources.join(", ")}`
240
247
  );
241
248
  }
242
- const resolved = { baseUrl, databaseId, apiKey, apiSecret, fetch: fetchImpl };
249
+ const resolved = {
250
+ baseUrl,
251
+ databaseId,
252
+ apiKey,
253
+ apiSecret,
254
+ fetch: fetchImpl,
255
+ retryEnabled,
256
+ maxRetries,
257
+ retryInitialDelayMs
258
+ };
243
259
  const source = {
244
260
  databaseId: input?.databaseId ? "explicit config" : env.databaseId ? "env" : cfgPath.databaseId ? "env ONYX_CONFIG_PATH" : project.databaseId ? "project file" : home.databaseId ? "home profile" : "unknown",
245
261
  apiKey: input?.apiKey ? "explicit config" : env.apiKey ? "env" : cfgPath.apiKey ? "env ONYX_CONFIG_PATH" : project.apiKey ? "project file" : home.apiKey ? "home profile" : "unknown",
@@ -249,6 +265,27 @@ async function resolveConfig(input) {
249
265
  dbg("resolved:", mask(resolved));
250
266
  return resolved;
251
267
  }
268
+ async function resolveConfigWithSource(input) {
269
+ const configPathEnv = gProcess?.env?.ONYX_CONFIG_PATH;
270
+ const env = readEnv(input?.databaseId);
271
+ const cfgPathRes = configPathEnv ? await readConfigPath(configPathEnv) : { config: {} };
272
+ const cfgPath = cfgPathRes.config;
273
+ const projectRes = await readProjectFile(env.databaseId ?? cfgPath.databaseId);
274
+ const project = projectRes.config;
275
+ const homeRes = await readHomeProfile(env.databaseId ?? cfgPath.databaseId);
276
+ const home = homeRes.config;
277
+ const base = await resolveConfig(input);
278
+ const sources = {
279
+ baseUrl: input?.baseUrl ? "explicit config" : env.baseUrl ? "env" : cfgPath.baseUrl ? "env ONYX_CONFIG_PATH" : project.baseUrl ? "project file" : home.baseUrl ? "home profile" : "default",
280
+ databaseId: input?.databaseId ? "explicit config" : env.databaseId ? "env" : cfgPath.databaseId ? "env ONYX_CONFIG_PATH" : project.databaseId ? "project file" : home.databaseId ? "home profile" : "unknown",
281
+ apiKey: input?.apiKey ? "explicit config" : env.apiKey ? "env" : cfgPath.apiKey ? "env ONYX_CONFIG_PATH" : project.apiKey ? "project file" : home.apiKey ? "home profile" : "unknown",
282
+ apiSecret: input?.apiSecret ? "explicit config" : env.apiSecret ? "env" : cfgPath.apiSecret ? "env ONYX_CONFIG_PATH" : project.apiSecret ? "project file" : home.apiSecret ? "home profile" : "unknown",
283
+ configPath: cfgPathRes.path,
284
+ projectFile: projectRes.path,
285
+ homeProfile: homeRes.path
286
+ };
287
+ return { ...base, sources };
288
+ }
252
289
  function mask(obj) {
253
290
  if (!obj) return obj;
254
291
  const clone = { ...obj };
@@ -296,7 +333,7 @@ function parseJsonAllowNaN(txt) {
296
333
  return JSON.parse(fixed);
297
334
  }
298
335
  }
299
- var HttpClient = class {
336
+ var HttpClient = class _HttpClient {
300
337
  baseUrl;
301
338
  apiKey;
302
339
  apiSecret;
@@ -304,6 +341,25 @@ var HttpClient = class {
304
341
  defaults;
305
342
  requestLoggingEnabled;
306
343
  responseLoggingEnabled;
344
+ retryEnabled;
345
+ maxRetries;
346
+ retryInitialDelayMs;
347
+ shouldRetry;
348
+ static parseRetryAfter(header) {
349
+ if (!header) return null;
350
+ const trimmed = header.trim();
351
+ if (trimmed === "") return null;
352
+ const seconds = Number(trimmed);
353
+ if (Number.isFinite(seconds)) {
354
+ return Math.max(0, seconds * 1e3);
355
+ }
356
+ const dateMs = Date.parse(trimmed);
357
+ if (!Number.isNaN(dateMs)) {
358
+ const now = Date.now();
359
+ return Math.max(0, dateMs - now);
360
+ }
361
+ return null;
362
+ }
307
363
  constructor(opts) {
308
364
  if (!opts.baseUrl || opts.baseUrl.trim() === "") {
309
365
  throw new OnyxConfigError("baseUrl is required");
@@ -328,6 +384,10 @@ var HttpClient = class {
328
384
  const envDebug = globalThis.process?.env?.ONYX_DEBUG === "true";
329
385
  this.requestLoggingEnabled = !!opts.requestLoggingEnabled || envDebug;
330
386
  this.responseLoggingEnabled = !!opts.responseLoggingEnabled || envDebug;
387
+ this.retryEnabled = opts.retryEnabled ?? true;
388
+ this.maxRetries = Math.max(0, opts.maxRetries ?? 2);
389
+ this.retryInitialDelayMs = Math.max(0, opts.retryInitialDelayMs ?? 100);
390
+ this.shouldRetry = (method, path2) => method === "GET" || path2.startsWith("/query/");
331
391
  }
332
392
  headers(extra) {
333
393
  const extras = { ...extra ?? {} };
@@ -368,9 +428,8 @@ var HttpClient = class {
368
428
  headers,
369
429
  body: payload
370
430
  };
371
- const isQuery = path2.includes("/query/") && !/\/query\/(?:update|delete)\//.test(path2);
372
- const canRetry = method === "GET" || isQuery;
373
- const maxAttempts = canRetry ? 3 : 1;
431
+ const canRetry = this.retryEnabled && this.shouldRetry(method, path2);
432
+ const maxAttempts = canRetry ? this.maxRetries + 1 : 1;
374
433
  for (let attempt = 0; attempt < maxAttempts; attempt++) {
375
434
  try {
376
435
  const res = await this.fetchImpl(url, init);
@@ -388,7 +447,10 @@ var HttpClient = class {
388
447
  if (!res.ok) {
389
448
  const msg = typeof data === "object" && data !== null && "error" in data && typeof data.error?.message === "string" ? String(data.error.message) : `${res.status} ${res.statusText}`;
390
449
  if (canRetry && res.status >= 500 && attempt + 1 < maxAttempts) {
391
- await new Promise((r) => setTimeout(r, 100 * 2 ** attempt));
450
+ const serverRetry = _HttpClient.parseRetryAfter(res.headers.get("retry-after"));
451
+ const backoff = this.retryInitialDelayMs * 2 ** attempt;
452
+ const delay = serverRetry ?? backoff;
453
+ await new Promise((r) => setTimeout(r, delay));
392
454
  continue;
393
455
  }
394
456
  throw new OnyxHttpError(msg, res.status, res.statusText, data, raw);
@@ -397,7 +459,8 @@ var HttpClient = class {
397
459
  } catch (err) {
398
460
  const retryable = canRetry && (!(err instanceof OnyxHttpError) || err.status >= 500);
399
461
  if (attempt + 1 < maxAttempts && retryable) {
400
- await new Promise((r) => setTimeout(r, 100 * 2 ** attempt));
462
+ const delay = this.retryInitialDelayMs * 2 ** attempt;
463
+ await new Promise((r) => setTimeout(r, delay));
401
464
  continue;
402
465
  }
403
466
  throw err;
@@ -958,31 +1021,299 @@ var CascadeRelationshipBuilder = class {
958
1021
  }
959
1022
  };
960
1023
 
961
- // src/errors/onyx-error.ts
962
- var OnyxError = class extends Error {
963
- name = "OnyxError";
964
- constructor(message) {
965
- super(message);
1024
+ // src/helpers/schema-diff.ts
1025
+ function mapByName(items) {
1026
+ const map = /* @__PURE__ */ new Map();
1027
+ for (const item of items ?? []) {
1028
+ if (!item?.name) continue;
1029
+ map.set(item.name, item);
966
1030
  }
967
- };
968
-
969
- // src/impl/onyx.ts
970
- var DEFAULT_CACHE_TTL = 5 * 60 * 1e3;
971
- var cachedCfg = null;
972
- function resolveConfigWithCache(config) {
973
- const ttl = config?.ttl ?? DEFAULT_CACHE_TTL;
974
- const now = Date.now();
975
- if (cachedCfg && cachedCfg.expires > now) {
976
- return cachedCfg.promise;
977
- }
978
- const { ttl: _ttl, requestLoggingEnabled: _reqLog, responseLoggingEnabled: _resLog, ...rest } = config ?? {};
979
- const promise = resolveConfig(rest);
980
- cachedCfg = { promise, expires: now + ttl };
981
- return promise;
1031
+ return map;
1032
+ }
1033
+ function normalizeEntities(schema) {
1034
+ if (Array.isArray(schema.entities)) {
1035
+ return schema.entities ?? [];
1036
+ }
1037
+ const tables = schema.tables;
1038
+ if (!Array.isArray(tables)) return [];
1039
+ return tables.map((table) => ({
1040
+ name: table.name,
1041
+ attributes: table.attributes ?? []
1042
+ }));
1043
+ }
1044
+ function normalizePartition(partition) {
1045
+ if (partition == null) return "";
1046
+ const trimmed = partition.trim();
1047
+ return trimmed;
1048
+ }
1049
+ function identifiersEqual(a, b) {
1050
+ if (!a && !b) return true;
1051
+ if (!a || !b) return false;
1052
+ return a.name === b.name && a.generator === b.generator && a.type === b.type;
1053
+ }
1054
+ function diffAttributes(apiAttrs, localAttrs) {
1055
+ const apiMap = mapByName(apiAttrs);
1056
+ const localMap = mapByName(localAttrs);
1057
+ const added = [];
1058
+ const removed = [];
1059
+ const changed = [];
1060
+ for (const [name, local] of localMap.entries()) {
1061
+ if (!apiMap.has(name)) {
1062
+ added.push(local);
1063
+ continue;
1064
+ }
1065
+ const api = apiMap.get(name);
1066
+ const apiNull = Boolean(api.isNullable);
1067
+ const localNull = Boolean(local.isNullable);
1068
+ if (api.type !== local.type || apiNull !== localNull) {
1069
+ changed.push({
1070
+ name,
1071
+ from: { type: api.type, isNullable: apiNull },
1072
+ to: { type: local.type, isNullable: localNull }
1073
+ });
1074
+ }
1075
+ }
1076
+ for (const name of apiMap.keys()) {
1077
+ if (!localMap.has(name)) removed.push(name);
1078
+ }
1079
+ added.sort((a, b) => a.name.localeCompare(b.name));
1080
+ removed.sort();
1081
+ changed.sort((a, b) => a.name.localeCompare(b.name));
1082
+ if (!added.length && !removed.length && !changed.length) return null;
1083
+ return { added, removed, changed };
1084
+ }
1085
+ function diffIndexes(apiIndexes, localIndexes) {
1086
+ const apiMap = mapByName(apiIndexes);
1087
+ const localMap = mapByName(localIndexes);
1088
+ const added = [];
1089
+ const removed = [];
1090
+ const changed = [];
1091
+ for (const [name, local] of localMap.entries()) {
1092
+ if (!apiMap.has(name)) {
1093
+ added.push(local);
1094
+ continue;
1095
+ }
1096
+ const api = apiMap.get(name);
1097
+ const apiType = api.type ?? "DEFAULT";
1098
+ const localType = local.type ?? "DEFAULT";
1099
+ const apiScore = api.minimumScore;
1100
+ const localScore = local.minimumScore;
1101
+ if (apiType !== localType || apiScore !== localScore) {
1102
+ changed.push({ name, from: api, to: local });
1103
+ }
1104
+ }
1105
+ for (const name of apiMap.keys()) {
1106
+ if (!localMap.has(name)) removed.push(name);
1107
+ }
1108
+ added.sort((a, b) => a.name.localeCompare(b.name));
1109
+ removed.sort();
1110
+ changed.sort((a, b) => a.name.localeCompare(b.name));
1111
+ if (!added.length && !removed.length && !changed.length) return null;
1112
+ return { added, removed, changed };
1113
+ }
1114
+ function diffResolvers(apiResolvers, localResolvers) {
1115
+ const apiMap = mapByName(apiResolvers);
1116
+ const localMap = mapByName(localResolvers);
1117
+ const added = [];
1118
+ const removed = [];
1119
+ const changed = [];
1120
+ for (const [name, local] of localMap.entries()) {
1121
+ if (!apiMap.has(name)) {
1122
+ added.push(local);
1123
+ continue;
1124
+ }
1125
+ const api = apiMap.get(name);
1126
+ if (api.resolver !== local.resolver) {
1127
+ changed.push({ name, from: api, to: local });
1128
+ }
1129
+ }
1130
+ for (const name of apiMap.keys()) {
1131
+ if (!localMap.has(name)) removed.push(name);
1132
+ }
1133
+ added.sort((a, b) => a.name.localeCompare(b.name));
1134
+ removed.sort();
1135
+ changed.sort((a, b) => a.name.localeCompare(b.name));
1136
+ if (!added.length && !removed.length && !changed.length) return null;
1137
+ return { added, removed, changed };
1138
+ }
1139
+ function diffTriggers(apiTriggers, localTriggers) {
1140
+ const apiMap = mapByName(apiTriggers);
1141
+ const localMap = mapByName(localTriggers);
1142
+ const added = [];
1143
+ const removed = [];
1144
+ const changed = [];
1145
+ for (const [name, local] of localMap.entries()) {
1146
+ if (!apiMap.has(name)) {
1147
+ added.push(local);
1148
+ continue;
1149
+ }
1150
+ const api = apiMap.get(name);
1151
+ if (api.event !== local.event || api.trigger !== local.trigger) {
1152
+ changed.push({ name, from: api, to: local });
1153
+ }
1154
+ }
1155
+ for (const name of apiMap.keys()) {
1156
+ if (!localMap.has(name)) removed.push(name);
1157
+ }
1158
+ added.sort((a, b) => a.name.localeCompare(b.name));
1159
+ removed.sort();
1160
+ changed.sort((a, b) => a.name.localeCompare(b.name));
1161
+ if (!added.length && !removed.length && !changed.length) return null;
1162
+ return { added, removed, changed };
1163
+ }
1164
+ function computeSchemaDiff(apiSchema, localSchema) {
1165
+ const apiEntities = normalizeEntities(apiSchema);
1166
+ const localEntities = normalizeEntities(localSchema);
1167
+ const apiMap = mapByName(apiEntities);
1168
+ const localMap = mapByName(localEntities);
1169
+ const newTables = [];
1170
+ const removedTables = [];
1171
+ const changedTables = [];
1172
+ for (const [name, localEntity] of localMap.entries()) {
1173
+ if (!apiMap.has(name)) {
1174
+ newTables.push(name);
1175
+ continue;
1176
+ }
1177
+ const apiEntity = apiMap.get(name);
1178
+ const tableDiff = { name };
1179
+ const partitionFrom = normalizePartition(apiEntity.partition);
1180
+ const partitionTo = normalizePartition(localEntity.partition);
1181
+ if (partitionFrom !== partitionTo) {
1182
+ tableDiff.partition = { from: partitionFrom || null, to: partitionTo || null };
1183
+ }
1184
+ if (!identifiersEqual(apiEntity.identifier, localEntity.identifier)) {
1185
+ tableDiff.identifier = {
1186
+ from: apiEntity.identifier ?? null,
1187
+ to: localEntity.identifier ?? null
1188
+ };
1189
+ }
1190
+ const attrs = diffAttributes(apiEntity.attributes, localEntity.attributes);
1191
+ if (attrs) tableDiff.attributes = attrs;
1192
+ const indexes = diffIndexes(apiEntity.indexes, localEntity.indexes);
1193
+ if (indexes) tableDiff.indexes = indexes;
1194
+ const resolvers = diffResolvers(apiEntity.resolvers, localEntity.resolvers);
1195
+ if (resolvers) tableDiff.resolvers = resolvers;
1196
+ const triggers = diffTriggers(apiEntity.triggers, localEntity.triggers);
1197
+ if (triggers) tableDiff.triggers = triggers;
1198
+ const hasChange = tableDiff.partition || tableDiff.identifier || tableDiff.attributes || tableDiff.indexes || tableDiff.resolvers || tableDiff.triggers;
1199
+ if (hasChange) {
1200
+ changedTables.push(tableDiff);
1201
+ }
1202
+ }
1203
+ for (const name of apiMap.keys()) {
1204
+ if (!localMap.has(name)) removedTables.push(name);
1205
+ }
1206
+ newTables.sort();
1207
+ removedTables.sort();
1208
+ changedTables.sort((a, b) => a.name.localeCompare(b.name));
1209
+ return { newTables, removedTables, changedTables };
1210
+ }
1211
+ function isScalar(value) {
1212
+ return value == null || value instanceof Date || typeof value === "string" || typeof value === "number" || typeof value === "boolean";
1213
+ }
1214
+ function formatScalar(value) {
1215
+ if (value === null || value === void 0) return "null";
1216
+ if (value instanceof Date) return JSON.stringify(value.toISOString());
1217
+ if (typeof value === "string") return JSON.stringify(value);
1218
+ return String(value);
1219
+ }
1220
+ function isRecord(value) {
1221
+ return !!value && typeof value === "object" && !Array.isArray(value) && !(value instanceof Date);
1222
+ }
1223
+ function toYamlLines(value, indent = 0) {
1224
+ const pad = " ".repeat(indent);
1225
+ if (Array.isArray(value)) {
1226
+ if (!value.length) return [`${pad}[]`];
1227
+ const lines = [];
1228
+ for (const item of value) {
1229
+ if (isScalar(item)) {
1230
+ lines.push(`${pad}- ${formatScalar(item)}`);
1231
+ continue;
1232
+ }
1233
+ const nested = toYamlLines(item, indent + 2);
1234
+ const [first, ...rest] = nested;
1235
+ lines.push(`${pad}- ${first ? first.trimStart() : "{}"}`);
1236
+ for (const line of rest) lines.push(line);
1237
+ }
1238
+ return lines;
1239
+ }
1240
+ if (isRecord(value)) {
1241
+ const entries = Object.entries(value).filter(([, v]) => v !== void 0);
1242
+ if (!entries.length) return [`${pad}{}`];
1243
+ const lines = [];
1244
+ for (const [key, val] of entries) {
1245
+ if (Array.isArray(val) && val.length === 0) {
1246
+ lines.push(`${pad}${key}: []`);
1247
+ continue;
1248
+ }
1249
+ if (isScalar(val)) {
1250
+ lines.push(`${pad}${key}: ${formatScalar(val)}`);
1251
+ } else {
1252
+ lines.push(`${pad}${key}:`);
1253
+ lines.push(...toYamlLines(val, indent + 2));
1254
+ }
1255
+ }
1256
+ return lines;
1257
+ }
1258
+ return [`${pad}${formatScalar(value)}`];
1259
+ }
1260
+ function pruneTableDiff(table) {
1261
+ const pruned = { name: table.name };
1262
+ if (table.partition && table.partition.from !== table.partition.to) {
1263
+ pruned.partition = table.partition;
1264
+ }
1265
+ if (table.identifier && !identifiersEqual(table.identifier.from ?? void 0, table.identifier.to ?? void 0)) {
1266
+ pruned.identifier = table.identifier;
1267
+ }
1268
+ if (table.attributes) {
1269
+ const { added = [], removed = [], changed = [] } = table.attributes;
1270
+ if (added.length || removed.length || changed.length) {
1271
+ pruned.attributes = { added, removed, changed };
1272
+ }
1273
+ }
1274
+ if (table.indexes) {
1275
+ const { added = [], removed = [], changed = [] } = table.indexes;
1276
+ if (added.length || removed.length || changed.length) {
1277
+ pruned.indexes = { added, removed, changed };
1278
+ }
1279
+ }
1280
+ if (table.resolvers) {
1281
+ const { added = [], removed = [], changed = [] } = table.resolvers;
1282
+ if (added.length || removed.length || changed.length) {
1283
+ pruned.resolvers = { added, removed, changed };
1284
+ }
1285
+ }
1286
+ if (table.triggers) {
1287
+ const { added = [], removed = [], changed = [] } = table.triggers;
1288
+ if (added.length || removed.length || changed.length) {
1289
+ pruned.triggers = { added, removed, changed };
1290
+ }
1291
+ }
1292
+ const hasChange = pruned.partition || pruned.identifier || pruned.attributes && (pruned.attributes.added.length || pruned.attributes.removed.length || pruned.attributes.changed.length) || pruned.indexes && (pruned.indexes.added.length || pruned.indexes.removed.length || pruned.indexes.changed.length) || pruned.resolvers && (pruned.resolvers.added.length || pruned.resolvers.removed.length || pruned.resolvers.changed.length) || pruned.triggers && (pruned.triggers.added.length || pruned.triggers.removed.length || pruned.triggers.changed.length);
1293
+ return hasChange ? pruned : null;
982
1294
  }
983
- function clearCacheConfig() {
984
- cachedCfg = null;
1295
+ function formatSchemaDiff(diff, filePath) {
1296
+ const hasChanges = diff.newTables.length || diff.removedTables.length || diff.changedTables.length;
1297
+ if (!hasChanges) {
1298
+ return `No differences found between API schema and ${filePath ?? "local schema"}.
1299
+ `;
1300
+ }
1301
+ const header = filePath ? `# Diff between API schema and ${filePath}
1302
+ ` : "# Schema diff";
1303
+ const prunedTables = diff.changedTables.map(pruneTableDiff).filter((t) => Boolean(t));
1304
+ const yamlObject = {
1305
+ newTables: [...diff.newTables],
1306
+ removedTables: [...diff.removedTables],
1307
+ changedTables: prunedTables
1308
+ };
1309
+ const bodyLines = toYamlLines(yamlObject);
1310
+ return `${header}
1311
+ ${bodyLines.join("\n")}
1312
+ `;
985
1313
  }
1314
+
1315
+ // src/impl/onyx-core.ts
1316
+ var DEFAULT_CACHE_TTL = 5 * 60 * 1e3;
986
1317
  function toSingleCondition(criteria) {
987
1318
  return { conditionType: "SingleCondition", criteria };
988
1319
  }
@@ -1036,7 +1367,20 @@ function normalizeDate(value) {
1036
1367
  return Number.isNaN(ts.getTime()) ? void 0 : ts;
1037
1368
  }
1038
1369
  function normalizeSchemaRevision(input, fallbackDatabaseId) {
1039
- const { meta, createdAt, publishedAt, revisionId, entityText, ...rest } = input;
1370
+ const {
1371
+ meta,
1372
+ createdAt,
1373
+ publishedAt,
1374
+ revisionId,
1375
+ entityText,
1376
+ databaseId,
1377
+ entities,
1378
+ revisionDescription,
1379
+ ...rest
1380
+ } = input;
1381
+ const dbId = typeof databaseId === "string" ? databaseId : fallbackDatabaseId;
1382
+ const entityList = Array.isArray(entities) ? entities : [];
1383
+ const revisionDesc = typeof revisionDescription === "string" ? revisionDescription : void 0;
1040
1384
  const mergedMeta = {
1041
1385
  revisionId: meta?.revisionId ?? revisionId,
1042
1386
  createdAt: normalizeDate(meta?.createdAt ?? createdAt),
@@ -1044,10 +1388,11 @@ function normalizeSchemaRevision(input, fallbackDatabaseId) {
1044
1388
  };
1045
1389
  const cleanedMeta = mergedMeta.revisionId || mergedMeta.createdAt || mergedMeta.publishedAt ? mergedMeta : void 0;
1046
1390
  return {
1047
- ...rest,
1048
- databaseId: input.databaseId ?? fallbackDatabaseId,
1391
+ databaseId: dbId,
1392
+ revisionDescription: revisionDesc,
1393
+ entities: entityList,
1049
1394
  meta: cleanedMeta,
1050
- entities: input.entities ?? []
1395
+ ...rest
1051
1396
  };
1052
1397
  }
1053
1398
  var OnyxDatabaseImpl = class {
@@ -1058,7 +1403,7 @@ var OnyxDatabaseImpl = class {
1058
1403
  requestLoggingEnabled;
1059
1404
  responseLoggingEnabled;
1060
1405
  defaultPartition;
1061
- constructor(config) {
1406
+ constructor(config, resolveConfigWithCache) {
1062
1407
  this.requestLoggingEnabled = !!config?.requestLoggingEnabled;
1063
1408
  this.responseLoggingEnabled = !!config?.responseLoggingEnabled;
1064
1409
  this.defaultPartition = config?.partition;
@@ -1075,7 +1420,10 @@ var OnyxDatabaseImpl = class {
1075
1420
  apiSecret: this.resolved.apiSecret,
1076
1421
  fetchImpl: this.resolved.fetch,
1077
1422
  requestLoggingEnabled: this.requestLoggingEnabled,
1078
- responseLoggingEnabled: this.responseLoggingEnabled
1423
+ responseLoggingEnabled: this.responseLoggingEnabled,
1424
+ retryEnabled: this.resolved.retryEnabled,
1425
+ maxRetries: this.resolved.maxRetries,
1426
+ retryInitialDelayMs: this.resolved.retryInitialDelayMs
1079
1427
  });
1080
1428
  }
1081
1429
  return {
@@ -1159,7 +1507,8 @@ var OnyxDatabaseImpl = class {
1159
1507
  const path2 = `/data/${encodeURIComponent(databaseId)}/${encodeURIComponent(
1160
1508
  table
1161
1509
  )}/${encodeURIComponent(primaryKey)}${params.toString() ? `?${params.toString()}` : ""}`;
1162
- return http.request("DELETE", path2);
1510
+ await http.request("DELETE", path2);
1511
+ return true;
1163
1512
  }
1164
1513
  async saveDocument(doc) {
1165
1514
  const { http, databaseId } = await this.ensureClient();
@@ -1202,6 +1551,10 @@ var OnyxDatabaseImpl = class {
1202
1551
  const res = await http.request("GET", path2);
1203
1552
  return Array.isArray(res) ? res.map((entry) => normalizeSchemaRevision(entry, databaseId)) : [];
1204
1553
  }
1554
+ async diffSchema(localSchema) {
1555
+ const apiSchema = await this.getSchema();
1556
+ return computeSchemaDiff(apiSchema, localSchema);
1557
+ }
1205
1558
  async updateSchema(schema, options) {
1206
1559
  const { http, databaseId } = await this.ensureClient();
1207
1560
  const params = new URLSearchParams();
@@ -1535,7 +1888,6 @@ var QueryBuilderImpl = class {
1535
1888
  }
1536
1889
  async firstOrNull() {
1537
1890
  if (this.mode !== "select") throw new Error("Cannot call firstOrNull() in update mode.");
1538
- if (!this.conditions) throw new OnyxError("firstOrNull() requires a where() clause.");
1539
1891
  this.limitValue = 1;
1540
1892
  const pg = await this.page();
1541
1893
  return Array.isArray(pg.records) && pg.records.length > 0 ? pg.records[0] : null;
@@ -1627,219 +1979,33 @@ var CascadeBuilderImpl = class {
1627
1979
  return this.db.delete(table, primaryKey, opts);
1628
1980
  }
1629
1981
  };
1630
- var onyx = {
1631
- init(config) {
1632
- return new OnyxDatabaseImpl(config);
1633
- },
1634
- clearCacheConfig
1635
- };
1636
-
1637
- // schema/cli/diff.ts
1638
- function mapByName(items) {
1639
- const map = /* @__PURE__ */ new Map();
1640
- for (const item of items ?? []) {
1641
- if (!item?.name) continue;
1642
- map.set(item.name, item);
1643
- }
1644
- return map;
1645
- }
1646
- function normalizeEntities(schema) {
1647
- if (Array.isArray(schema.entities)) {
1648
- return schema.entities ?? [];
1649
- }
1650
- const tables = schema.tables;
1651
- if (!Array.isArray(tables)) return [];
1652
- return tables.map((table) => ({
1653
- name: table.name,
1654
- attributes: table.attributes ?? []
1655
- }));
1656
- }
1657
- function formatIdentifier(id) {
1658
- if (!id) return "";
1659
- const parts = [id.name ? `name=${id.name}` : null, id.generator ? `generator=${id.generator}` : null, id.type ? `type=${id.type}` : null].filter(Boolean);
1660
- return parts.join(", ");
1661
- }
1662
- function describeIdentifierChange(api, local) {
1663
- if (!api && !local) return null;
1664
- if (!api && local) return "identifier removed";
1665
- if (api && !local) return "identifier added";
1666
- if (!api || !local) return null;
1667
- if (api.name === local.name && api.generator === local.generator && api.type === local.type) {
1668
- return null;
1669
- }
1670
- return `identifier: ${formatIdentifier(api) || "none"} -> ${formatIdentifier(local) || "none"}`;
1671
- }
1672
- function describePartitionChange(api, local) {
1673
- const norm = (v) => v == null || v === "" ? "" : v;
1674
- if (norm(api) === norm(local)) return null;
1675
- return `partition: ${norm(api) || "none"} -> ${norm(local) || "none"}`;
1676
- }
1677
- function describeAttribute(attr) {
1678
- const nullable = attr.isNullable ? "true" : "false";
1679
- return `${attr.name} (${attr.type ?? "unknown"}, nullable: ${nullable})`;
1680
- }
1681
- function describeAttributeChange(api, local) {
1682
- const diffs = [];
1683
- if (api.type !== local.type) {
1684
- diffs.push(`type ${api.type ?? "unknown"} -> ${local.type ?? "unknown"}`);
1685
- }
1686
- const apiNull = Boolean(api.isNullable);
1687
- const localNull = Boolean(local.isNullable);
1688
- if (apiNull !== localNull) {
1689
- diffs.push(`nullable ${apiNull} -> ${localNull}`);
1690
- }
1691
- if (!diffs.length) return null;
1692
- return `${local.name}: ${diffs.join("; ")}`;
1693
- }
1694
- function describeIndex(idx) {
1695
- const parts = [`type: ${idx.type ?? "DEFAULT"}`];
1696
- if (idx.minimumScore != null) parts.push(`minScore: ${idx.minimumScore}`);
1697
- return `${idx.name} (${parts.join(", ")})`;
1698
- }
1699
- function describeIndexChange(api, local) {
1700
- const diffs = [];
1701
- if (api.type !== local.type) {
1702
- diffs.push(`type ${api.type ?? "DEFAULT"} -> ${local.type ?? "DEFAULT"}`);
1703
- }
1704
- if (api.minimumScore !== local.minimumScore) {
1705
- diffs.push(`minScore ${api.minimumScore ?? "none"} -> ${local.minimumScore ?? "none"}`);
1706
- }
1707
- if (!diffs.length) return null;
1708
- return `${local.name}: ${diffs.join("; ")}`;
1709
- }
1710
- function describeResolverChange(api, local) {
1711
- if (api.resolver === local.resolver) return null;
1712
- return `${local.name}: resolver changed`;
1713
- }
1714
- function describeTrigger(trigger) {
1715
- return `${trigger.name} (${trigger.event})`;
1716
- }
1717
- function describeTriggerChange(api, local) {
1718
- const diffs = [];
1719
- if (api.event !== local.event) {
1720
- diffs.push(`event ${api.event ?? "none"} -> ${local.event ?? "none"}`);
1721
- }
1722
- if (api.trigger !== local.trigger) {
1723
- diffs.push("trigger changed");
1724
- }
1725
- if (!diffs.length) return null;
1726
- return `${local.name}: ${diffs.join("; ")}`;
1727
- }
1728
- function diffCollections(apiItems, localItems, describeAdd, describeChange) {
1729
- const apiMap = mapByName(apiItems);
1730
- const localMap = mapByName(localItems);
1731
- const added = [];
1732
- const removed = [];
1733
- const changed = [];
1734
- for (const [name, local] of localMap.entries()) {
1735
- if (!apiMap.has(name)) {
1736
- added.push(describeAdd(local));
1737
- continue;
1738
- }
1739
- if (describeChange) {
1740
- const detail = describeChange(apiMap.get(name), local);
1741
- if (detail) changed.push(detail);
1742
- }
1743
- }
1744
- for (const name of apiMap.keys()) {
1745
- if (!localMap.has(name)) removed.push(name);
1746
- }
1747
- return { added, removed, changed };
1748
- }
1749
- function computeSchemaDiff(apiSchema, localSchema) {
1750
- const apiEntities = normalizeEntities(apiSchema);
1751
- const localEntities = normalizeEntities(localSchema);
1752
- const apiMap = mapByName(apiEntities);
1753
- const localMap = mapByName(localEntities);
1754
- const newTables = [];
1755
- const removedTables = [];
1756
- const changedTables = [];
1757
- for (const [name, localEntity] of localMap.entries()) {
1758
- if (!apiMap.has(name)) {
1759
- newTables.push(name);
1760
- continue;
1761
- }
1762
- const apiEntity = apiMap.get(name);
1763
- const details = [];
1764
- const partitionChange = describePartitionChange(apiEntity.partition, localEntity.partition);
1765
- if (partitionChange) details.push(partitionChange);
1766
- const idChange = describeIdentifierChange(apiEntity.identifier, localEntity.identifier);
1767
- if (idChange) details.push(idChange);
1768
- const attrDiff = diffCollections(apiEntity.attributes, localEntity.attributes, (attr) => `+ ${describeAttribute(attr)}`, describeAttributeChange);
1769
- if (attrDiff.added.length || attrDiff.removed.length || attrDiff.changed.length) {
1770
- details.push("attributes:");
1771
- for (const a of attrDiff.added) details.push(` ${a}`);
1772
- for (const c of attrDiff.changed) details.push(` ~ ${c}`);
1773
- for (const r of attrDiff.removed) details.push(` - ${r}`);
1774
- }
1775
- const idxDiff = diffCollections(apiEntity.indexes, localEntity.indexes, (idx) => `+ ${describeIndex(idx)}`, describeIndexChange);
1776
- if (idxDiff.added.length || idxDiff.removed.length || idxDiff.changed.length) {
1777
- details.push("indexes:");
1778
- for (const a of idxDiff.added) details.push(` ${a}`);
1779
- for (const c of idxDiff.changed) details.push(` ~ ${c}`);
1780
- for (const r of idxDiff.removed) details.push(` - ${r}`);
1781
- }
1782
- const resolverDiff = diffCollections(apiEntity.resolvers, localEntity.resolvers, (resolver) => `+ ${resolver.name}`, describeResolverChange);
1783
- if (resolverDiff.added.length || resolverDiff.removed.length || resolverDiff.changed.length) {
1784
- details.push("resolvers:");
1785
- for (const a of resolverDiff.added) details.push(` ${a}`);
1786
- for (const c of resolverDiff.changed) details.push(` ~ ${c}`);
1787
- for (const r of resolverDiff.removed) details.push(` - ${r}`);
1788
- }
1789
- const triggerDiff = diffCollections(apiEntity.triggers, localEntity.triggers, (trigger) => `+ ${describeTrigger(trigger)}`, describeTriggerChange);
1790
- if (triggerDiff.added.length || triggerDiff.removed.length || triggerDiff.changed.length) {
1791
- details.push("triggers:");
1792
- for (const a of triggerDiff.added) details.push(` ${a}`);
1793
- for (const c of triggerDiff.changed) details.push(` ~ ${c}`);
1794
- for (const r of triggerDiff.removed) details.push(` - ${r}`);
1982
+ function createOnyxFacade(resolveConfig2) {
1983
+ let cachedCfg = null;
1984
+ function resolveConfigWithCache(config) {
1985
+ const ttl = config?.ttl ?? DEFAULT_CACHE_TTL;
1986
+ const now = Date.now();
1987
+ if (cachedCfg && cachedCfg.expires > now) {
1988
+ return cachedCfg.promise;
1795
1989
  }
1796
- if (details.length) {
1797
- changedTables.push({ name, details });
1798
- }
1799
- }
1800
- for (const name of apiMap.keys()) {
1801
- if (!localMap.has(name)) removedTables.push(name);
1802
- }
1803
- newTables.sort();
1804
- removedTables.sort();
1805
- changedTables.sort((a, b) => a.name.localeCompare(b.name));
1806
- return { newTables, removedTables, changedTables };
1807
- }
1808
- function formatSchemaDiff(diff, filePath) {
1809
- const lines = [];
1810
- const hasChanges = diff.newTables.length || diff.removedTables.length || diff.changedTables.length;
1811
- if (!hasChanges) {
1812
- return `No differences found between API schema and ${filePath ?? "local file"}.
1813
- `;
1990
+ const { ttl: _ttl, requestLoggingEnabled: _reqLog, responseLoggingEnabled: _resLog, ...rest } = config ?? {};
1991
+ const promise = resolveConfig2(rest);
1992
+ cachedCfg = { promise, expires: now + ttl };
1993
+ return promise;
1814
1994
  }
1815
- if (filePath) lines.push(`Comparing API schema to ${filePath}`);
1816
- lines.push("New Tables:");
1817
- if (diff.newTables.length) {
1818
- for (const t of diff.newTables) lines.push(` ${t}`);
1819
- } else {
1820
- lines.push(" (none)");
1821
- }
1822
- lines.push("Removed Tables:");
1823
- if (diff.removedTables.length) {
1824
- for (const t of diff.removedTables) lines.push(` ${t}`);
1825
- } else {
1826
- lines.push(" (none)");
1827
- }
1828
- lines.push("Changes:");
1829
- if (diff.changedTables.length) {
1830
- for (const table of diff.changedTables) {
1831
- lines.push(` ${table.name}`);
1832
- for (const detail of table.details) {
1833
- lines.push(` ${detail}`);
1834
- }
1835
- }
1836
- } else {
1837
- lines.push(" (none)");
1995
+ function clearCacheConfig() {
1996
+ cachedCfg = null;
1838
1997
  }
1839
- return `${lines.join("\n")}
1840
- `;
1998
+ return {
1999
+ init(config) {
2000
+ return new OnyxDatabaseImpl(config, resolveConfigWithCache);
2001
+ },
2002
+ clearCacheConfig
2003
+ };
1841
2004
  }
1842
2005
 
2006
+ // src/impl/onyx.ts
2007
+ var onyx = createOnyxFacade((config) => resolveConfig(config));
2008
+
1843
2009
  // schema/cli/schema.ts
1844
2010
  var DEFAULT_SCHEMA_PATH = "./onyx.schema.json";
1845
2011
  function printHelp() {
@@ -1850,10 +2016,12 @@ Usage:
1850
2016
  onyx-schema get [file] [--tables tableA,tableB]
1851
2017
  onyx-schema validate [file]
1852
2018
  onyx-schema diff [file]
2019
+ onyx-schema info
1853
2020
 
1854
2021
  Options:
1855
2022
  [file] Path to schema JSON (default: ./onyx.schema.json)
1856
2023
  --tables <list> Comma-separated list of tables to fetch (for get)
2024
+ --print Print the fetched schema to stdout instead of writing a file
1857
2025
  -h, --help Show this help message
1858
2026
  `);
1859
2027
  }
@@ -1865,7 +2033,7 @@ function parseTables(value) {
1865
2033
  function parseArgs(argv) {
1866
2034
  const cmd = (argv[2] ?? "").toLowerCase();
1867
2035
  let command = "help";
1868
- if (cmd === "publish" || cmd === "get" || cmd === "validate" || cmd === "diff") {
2036
+ if (cmd === "publish" || cmd === "get" || cmd === "validate" || cmd === "diff" || cmd === "info") {
1869
2037
  command = cmd;
1870
2038
  }
1871
2039
  let idx = 3;
@@ -1875,6 +2043,7 @@ function parseArgs(argv) {
1875
2043
  idx++;
1876
2044
  }
1877
2045
  let tables;
2046
+ let print = false;
1878
2047
  for (; idx < argv.length; idx++) {
1879
2048
  const arg = argv[idx];
1880
2049
  switch (arg) {
@@ -1882,6 +2051,9 @@ function parseArgs(argv) {
1882
2051
  tables = parseTables(argv[idx + 1]);
1883
2052
  idx++;
1884
2053
  break;
2054
+ case "--print":
2055
+ print = true;
2056
+ break;
1885
2057
  case "-h":
1886
2058
  case "--help":
1887
2059
  command = "help";
@@ -1896,7 +2068,7 @@ function parseArgs(argv) {
1896
2068
  }
1897
2069
  }
1898
2070
  }
1899
- return { command, filePath, tables };
2071
+ return { command, filePath, tables, print };
1900
2072
  }
1901
2073
  async function readFileJson(filePath) {
1902
2074
  const fs = await import('fs/promises');
@@ -1911,10 +2083,10 @@ async function writeFileJson(filePath, data) {
1911
2083
  `;
1912
2084
  await fs.writeFile(resolved, serialized, "utf8");
1913
2085
  }
1914
- async function fetchSchema(filePath, tables) {
2086
+ async function fetchSchema(filePath, tables, print) {
1915
2087
  const db = onyx.init();
1916
2088
  const schema = await db.getSchema({ tables });
1917
- if (tables?.length) {
2089
+ if (tables?.length || print) {
1918
2090
  process__default.default.stdout.write(`${JSON.stringify(schema, null, 2)}
1919
2091
  `);
1920
2092
  return;
@@ -1952,14 +2124,45 @@ ${formatSchemaErrors(result.errors)}`);
1952
2124
  }
1953
2125
  async function diffSchema(filePath) {
1954
2126
  const db = onyx.init();
1955
- const [apiSchema, localSchema] = await Promise.all([
1956
- db.getSchema(),
1957
- readFileJson(filePath)
1958
- ]);
1959
- const diff = computeSchemaDiff(apiSchema, localSchema);
2127
+ const localSchema = await readFileJson(filePath);
2128
+ const diff = await db.diffSchema(localSchema);
1960
2129
  const output = formatSchemaDiff(diff, filePath);
1961
2130
  process__default.default.stdout.write(output);
1962
2131
  }
2132
+ function maskValue(value) {
2133
+ if (!value) return "";
2134
+ if (value.length <= 4) return value;
2135
+ return `${value.slice(0, 2)}...${value.slice(-2)}`;
2136
+ }
2137
+ function formatSource(source) {
2138
+ if (!source) return "unknown";
2139
+ if (source.includes("env")) return "env";
2140
+ if (source.includes("file") || source.includes("profile") || source.includes("config")) return "file";
2141
+ if (source === "explicit config") return "explicit";
2142
+ return source;
2143
+ }
2144
+ async function printInfo() {
2145
+ const resolved = await resolveConfigWithSource();
2146
+ const db = onyx.init();
2147
+ const cfgFile = resolved.sources.configPath ?? resolved.sources.projectFile ?? resolved.sources.homeProfile ?? "(none)";
2148
+ let connection = "ok";
2149
+ try {
2150
+ await db.getSchema({ tables: [] });
2151
+ } catch (err) {
2152
+ const msg = err instanceof Error ? err.message : String(err);
2153
+ connection = msg;
2154
+ }
2155
+ const lines = [
2156
+ `Database ID: ${resolved.databaseId} (source: ${formatSource(resolved.sources.databaseId)})`,
2157
+ `Base URL : ${resolved.baseUrl} (source: ${formatSource(resolved.sources.baseUrl)})`,
2158
+ `API Key : ${maskValue(resolved.apiKey)} (source: ${formatSource(resolved.sources.apiKey)})`,
2159
+ `API Secret : ${maskValue(resolved.apiSecret)} (source: ${formatSource(resolved.sources.apiSecret)})`,
2160
+ `Config file: ${cfgFile}`,
2161
+ `Connection : ${connection}`
2162
+ ];
2163
+ process__default.default.stdout.write(`${lines.join("\n")}
2164
+ `);
2165
+ }
1963
2166
  (async () => {
1964
2167
  try {
1965
2168
  const parsed = parseArgs(process__default.default.argv);
@@ -1968,7 +2171,7 @@ async function diffSchema(filePath) {
1968
2171
  await publishSchema(parsed.filePath);
1969
2172
  break;
1970
2173
  case "get":
1971
- await fetchSchema(parsed.filePath, parsed.tables);
2174
+ await fetchSchema(parsed.filePath, parsed.tables, parsed.print);
1972
2175
  break;
1973
2176
  case "validate":
1974
2177
  await validateSchema(parsed.filePath);
@@ -1976,6 +2179,9 @@ async function diffSchema(filePath) {
1976
2179
  case "diff":
1977
2180
  await diffSchema(parsed.filePath);
1978
2181
  break;
2182
+ case "info":
2183
+ await printInfo();
2184
+ break;
1979
2185
  default:
1980
2186
  printHelp();
1981
2187
  return;