@tailor-platform/sdk 1.21.0 → 1.22.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 (76) hide show
  1. package/CHANGELOG.md +44 -0
  2. package/dist/application-CTQe2HSB.mjs +5723 -0
  3. package/dist/application-CTQe2HSB.mjs.map +1 -0
  4. package/dist/application-DdSu3baZ.mjs +8 -0
  5. package/dist/{brand-BZJCv6UY.mjs → brand-DyPrAzpM.mjs} +1 -1
  6. package/dist/{brand-BZJCv6UY.mjs.map → brand-DyPrAzpM.mjs.map} +1 -1
  7. package/dist/cli/index.mjs +544 -57
  8. package/dist/cli/index.mjs.map +1 -1
  9. package/dist/cli/lib.d.mts +49 -8
  10. package/dist/cli/lib.mjs +15 -16
  11. package/dist/cli/lib.mjs.map +1 -1
  12. package/dist/configure/index.d.mts +4 -4
  13. package/dist/configure/index.mjs +15 -4
  14. package/dist/configure/index.mjs.map +1 -1
  15. package/dist/{enum-constants-CGVvu3dd.mjs → enum-constants-B5Nl-yzx.mjs} +1 -1
  16. package/dist/{enum-constants-CGVvu3dd.mjs.map → enum-constants-B5Nl-yzx.mjs.map} +1 -1
  17. package/dist/{file-utils-GX_tGWl4.mjs → file-utils-sEOwAdJ4.mjs} +1 -1
  18. package/dist/{file-utils-GX_tGWl4.mjs.map → file-utils-sEOwAdJ4.mjs.map} +1 -1
  19. package/dist/{index-Dn61THJK.d.mts → index-BGPX26_D.d.mts} +2 -2
  20. package/dist/{index-CnHd6BNg.d.mts → index-BiutQT7m.d.mts} +4 -10
  21. package/dist/{index-DxlmLUag.d.mts → index-ClS0NClx.d.mts} +2 -2
  22. package/dist/{index-BWVAwea4.d.mts → index-Cwi86SUR.d.mts} +2 -2
  23. package/dist/{index-oZXVKyfX.d.mts → index-DPN_P0w3.d.mts} +2 -2
  24. package/dist/{interceptor-D8MeZOxX.mjs → interceptor-DiARwPfw.mjs} +1 -1
  25. package/dist/{interceptor-D8MeZOxX.mjs.map → interceptor-DiARwPfw.mjs.map} +1 -1
  26. package/dist/{job-2Q82qQ6N.mjs → job-CRavYLLk.mjs} +4 -24
  27. package/dist/job-CRavYLLk.mjs.map +1 -0
  28. package/dist/kysely/index.d.mts +2 -2
  29. package/dist/kysely/index.mjs +2 -2
  30. package/dist/kysely/index.mjs.map +1 -1
  31. package/dist/{kysely-type-Cpq5TNGY.mjs → kysely-type-CSlcwNFH.mjs} +1 -1
  32. package/dist/{kysely-type-Cpq5TNGY.mjs.map → kysely-type-CSlcwNFH.mjs.map} +1 -1
  33. package/dist/package-json-BI0ng3_5.mjs +3 -0
  34. package/dist/{package-json-3H5gfhA4.mjs → package-json-iVBhE5Ef.mjs} +1 -1
  35. package/dist/{package-json-3H5gfhA4.mjs.map → package-json-iVBhE5Ef.mjs.map} +1 -1
  36. package/dist/plugin/builtin/enum-constants/index.d.mts +2 -2
  37. package/dist/plugin/builtin/enum-constants/index.mjs +1 -1
  38. package/dist/plugin/builtin/file-utils/index.d.mts +2 -2
  39. package/dist/plugin/builtin/file-utils/index.mjs +1 -1
  40. package/dist/plugin/builtin/kysely-type/index.d.mts +2 -2
  41. package/dist/plugin/builtin/kysely-type/index.mjs +1 -1
  42. package/dist/plugin/builtin/seed/index.d.mts +2 -2
  43. package/dist/plugin/builtin/seed/index.mjs +1 -1
  44. package/dist/plugin/index.d.mts +1 -1
  45. package/dist/plugin/index.mjs +3 -3
  46. package/dist/plugin/index.mjs.map +1 -1
  47. package/dist/{update-9MTRN1UA.mjs → query-Bz2oDGhw.mjs} +915 -174
  48. package/dist/query-Bz2oDGhw.mjs.map +1 -0
  49. package/dist/{schema-D5Cpd8fQ.mjs → schema-Cjm-OvPF.mjs} +2 -2
  50. package/dist/{schema-D5Cpd8fQ.mjs.map → schema-Cjm-OvPF.mjs.map} +1 -1
  51. package/dist/{seed-D-rYCN5F.mjs → seed-CXvCW3Xc.mjs} +2 -2
  52. package/dist/{seed-D-rYCN5F.mjs.map → seed-CXvCW3Xc.mjs.map} +1 -1
  53. package/dist/telemetry-BAxP8-PR.mjs +3 -0
  54. package/dist/{telemetry-DuBhnd0X.mjs → telemetry-C46fds1l.mjs} +2 -2
  55. package/dist/{telemetry-DuBhnd0X.mjs.map → telemetry-C46fds1l.mjs.map} +1 -1
  56. package/dist/{types-ClK_HJ0G.mjs → types-CBTSg-LK.mjs} +1 -1
  57. package/dist/{types-ClK_HJ0G.mjs.map → types-CBTSg-LK.mjs.map} +1 -1
  58. package/dist/{types-C0o90Cmb.d.mts → types-DVMQNdTs.d.mts} +6 -2
  59. package/dist/{types-QKq1usl7.d.mts → types-bcuNRo1Y.d.mts} +8 -8
  60. package/dist/utils/test/index.d.mts +42 -4
  61. package/dist/utils/test/index.mjs +78 -3
  62. package/dist/utils/test/index.mjs.map +1 -1
  63. package/docs/cli/function.md +83 -3
  64. package/package.json +7 -5
  65. package/dist/application-CEv5c7TU.mjs +0 -102207
  66. package/dist/application-CEv5c7TU.mjs.map +0 -1
  67. package/dist/application-DiCzM9b0.mjs +0 -9
  68. package/dist/chunk-CqAI0b6X.mjs +0 -47
  69. package/dist/jiti-DfS9jItj.mjs +0 -4482
  70. package/dist/jiti-DfS9jItj.mjs.map +0 -1
  71. package/dist/job-2Q82qQ6N.mjs.map +0 -1
  72. package/dist/package-json-DTDAqRRJ.mjs +0 -3
  73. package/dist/src-Bb1UVstT.mjs +0 -1038
  74. package/dist/src-Bb1UVstT.mjs.map +0 -1
  75. package/dist/telemetry-Dhzj9Ncm.mjs +0 -3
  76. package/dist/update-9MTRN1UA.mjs.map +0 -1
@@ -1,14 +1,13 @@
1
1
  #!/usr/bin/env node
2
- import "../chunk-CqAI0b6X.mjs";
3
- import "../schema-D5Cpd8fQ.mjs";
4
- import "../brand-BZJCv6UY.mjs";
5
- import { A as generateCommand$1, At as getMigrationFiles, C as resumeCommand, Et as formatMigrationNumber, F as removeCommand$1, Gt as deploymentArgs, H as listCommand$6, Ht as apiCommand, I as listCommand$7, Jt as workspaceArgs, K as webhookCommand, Kt as jsonArgs, Mt as isValidMigrationNumber, N as showCommand, Nt as loadDiff, O as truncateCommand, Q as jobsCommand, R as getCommand$2, Rt as getNamespacesWithMigrations, S as healthCommand, T as listCommand$8, Ut as commonArgs, V as tokenCommand, W as generate, Wt as confirmationArgs, Y as listCommand$5, _ as createCommand$3, a as listCommand$10, at as executionsCommand, b as listCommand$9, ct as functionExecutionStatusToString, d as listCommand$11, ft as apply, gt as parseMigrationLabelNumber, h as deleteCommand$3, j as logBetaWarning, kt as getMigrationFilePath, l as restoreCommand, lt as formatKeyValueTable, p as getCommand$4, q as triggerCommand, qt as withCommonArgs, r as removeCommand, rt as getCommand$3, s as inviteCommand, t as updateCommand$2, tt as startCommand, ut as getCommand$1, zt as trnPrefix } from "../update-9MTRN1UA.mjs";
6
- import { B as FunctionExecution_Type, C as initOAuth2Client, Q as PATScope, S as fetchUserInfo, _ as loadWorkspaceId, b as fetchAll, ct as logger, i as loadConfig, lt as styles, m as loadAccessToken, p as fetchLatestToken, v as readPlatformConfig, w as initOperatorClient, y as writePlatformConfig } from "../application-CEv5c7TU.mjs";
7
- import { t as readPackageJson } from "../package-json-3H5gfhA4.mjs";
8
- import "../file-utils-GX_tGWl4.mjs";
9
- import "../kysely-type-Cpq5TNGY.mjs";
10
- import "../seed-D-rYCN5F.mjs";
11
- import "../telemetry-DuBhnd0X.mjs";
2
+ import "../schema-Cjm-OvPF.mjs";
3
+ import "../brand-DyPrAzpM.mjs";
4
+ import { A as truncateCommand, B as getCommand$2, Bt as getNamespacesWithMigrations, D as listCommand$8, F as showCommand, Ft as loadDiff, Gt as commonArgs, J as webhookCommand, Jt as jsonArgs, K as generate, Kt as confirmationArgs, L as removeCommand$1, M as generateCommand$1, Mt as getMigrationFiles, N as logBetaWarning, Ot as formatMigrationNumber, Pt as isValidMigrationNumber, R as listCommand$7, S as listCommand$9, T as resumeCommand, U as tokenCommand, Vt as trnPrefix, W as listCommand$6, Wt as apiCommand, Xt as workspaceArgs, Y as triggerCommand, Yt as withCommonArgs, Z as listCommand$5, _ as deleteCommand$3, a as removeCommand, at as getCommand$3, d as restoreCommand, dt as formatKeyValueTable, et as jobsCommand, ft as getCommand$1, h as getCommand$4, ht as executeScript, jt as getMigrationFilePath, l as inviteCommand, mt as apply, n as queryCommand, p as listCommand$11, qt as deploymentArgs, r as updateCommand$2, rt as startCommand, s as listCommand$10, st as executionsCommand, ut as functionExecutionStatusToString, vt as parseMigrationLabelNumber, w as healthCommand, y as createCommand$3 } from "../query-Bz2oDGhw.mjs";
5
+ import { C as readPlatformConfig, D as fetchUserInfo, G as FunctionExecution_Type, O as initOAuth2Client, S as loadWorkspaceId, T as fetchAll, X as AuthInvokerSchema, a as loadConfig, c as ExecutorSchema, g as getDistDir, i as resolveInlineSourcemap, k as initOperatorClient, mt as styles, o as WorkflowJobSchema, pt as logger, rt as PATScope, u as ResolverSchema, v as fetchLatestToken, w as writePlatformConfig, y as loadAccessToken } from "../application-CTQe2HSB.mjs";
6
+ import { t as readPackageJson } from "../package-json-iVBhE5Ef.mjs";
7
+ import "../file-utils-sEOwAdJ4.mjs";
8
+ import "../kysely-type-CSlcwNFH.mjs";
9
+ import "../seed-CXvCW3Xc.mjs";
10
+ import "../telemetry-C46fds1l.mjs";
12
11
  import { createRequire, register } from "node:module";
13
12
  import { arg, defineCommand, runCommand, runMain } from "politty";
14
13
  import { withCompletionCommand } from "politty/completion";
@@ -18,14 +17,18 @@ import * as path from "pathe";
18
17
  import { generateCodeVerifier } from "@badgateway/oauth2-client";
19
18
  import { timestampDate } from "@bufbuild/protobuf/wkt";
20
19
  import { Code, ConnectError } from "@connectrpc/connect";
20
+ import { resolveTSConfig } from "pkg-types";
21
21
  import ml from "multiline-ts";
22
22
  import * as crypto from "node:crypto";
23
- import * as fs$2 from "fs";
24
- import pLimit from "p-limit";
23
+ import { pathToFileURL } from "node:url";
24
+ import * as rolldown from "rolldown";
25
+ import { create } from "@bufbuild/protobuf";
25
26
  import { spawn, spawnSync } from "node:child_process";
26
27
  import * as http from "node:http";
27
28
  import open from "open";
29
+ import * as fs from "fs";
28
30
  import { lookup } from "mime-types";
31
+ import pLimit from "p-limit";
29
32
  import { setTimeout as setTimeout$1 } from "node:timers/promises";
30
33
 
31
34
  //#region src/cli/commands/apply/index.ts
@@ -43,7 +46,7 @@ const applyCommand = defineCommand({
43
46
  "no-schema-check": arg(z.boolean().optional(), { description: "Skip schema diff check against migration snapshots" }),
44
47
  "no-cache": arg(z.boolean().optional(), { description: "Disable bundle caching for this run" }),
45
48
  "clean-cache": arg(z.boolean().optional(), { description: "Clean the bundle cache before building" })
46
- }),
49
+ }).strict(),
47
50
  run: withCommonArgs(async (args) => {
48
51
  await apply({
49
52
  workspaceId: args["workspace-id"],
@@ -161,7 +164,7 @@ const logsCommand = defineCommand({
161
164
  positional: true,
162
165
  description: "Execution ID (if provided, shows details with logs)"
163
166
  })
164
- }),
167
+ }).strict(),
165
168
  run: withCommonArgs(async (args) => {
166
169
  const client = await initOperatorClient(await loadAccessToken({
167
170
  useProfile: true,
@@ -198,12 +201,493 @@ const logsCommand = defineCommand({
198
201
  })
199
202
  });
200
203
 
204
+ //#endregion
205
+ //#region src/cli/commands/function/bundle.ts
206
+ /**
207
+ * Bundler for function test-run command
208
+ *
209
+ * Bundles a single function file for execution via the TestExecScript API.
210
+ * Generates an entry file based on the detected function type and bundles
211
+ * with rolldown, following the same patterns as the existing bundlers.
212
+ */
213
+ /**
214
+ * Bundle a function file for test-run execution via TestExecScript API.
215
+ * @param options - Bundle options
216
+ * @returns Bundled code and script name
217
+ */
218
+ async function bundleForTestRun(options) {
219
+ const { detected, sourceFile, env = {}, machineUser, workspaceId } = options;
220
+ const inlineSourcemap = resolveInlineSourcemap(options.inlineSourcemap);
221
+ const outputDir = path.resolve(getDistDir(), "test-run");
222
+ fs$1.mkdirSync(outputDir, { recursive: true });
223
+ const baseName = `test-run--${detected.name}`;
224
+ const scriptName = `${baseName}.js`;
225
+ const entryPath = path.join(outputDir, `${baseName}.entry.js`);
226
+ const outputPath = path.join(outputDir, scriptName);
227
+ const entryContent = generateEntry(detected, sourceFile, env, machineUser, workspaceId);
228
+ fs$1.writeFileSync(entryPath, entryContent);
229
+ let tsconfig;
230
+ try {
231
+ tsconfig = await resolveTSConfig();
232
+ } catch {
233
+ tsconfig = void 0;
234
+ }
235
+ await rolldown.build(rolldown.defineConfig({
236
+ input: entryPath,
237
+ output: {
238
+ file: outputPath,
239
+ format: "esm",
240
+ sourcemap: inlineSourcemap ? "inline" : true,
241
+ minify: inlineSourcemap ? { mangle: { keepNames: true } } : true,
242
+ inlineDynamicImports: true
243
+ },
244
+ tsconfig,
245
+ treeshake: {
246
+ moduleSideEffects: false,
247
+ annotations: true,
248
+ unknownGlobalSideEffects: false
249
+ },
250
+ logLevel: "silent"
251
+ }));
252
+ return {
253
+ bundledCode: fs$1.readFileSync(outputPath, "utf-8"),
254
+ scriptName
255
+ };
256
+ }
257
+ /**
258
+ * Generate entry file content based on the detected function type.
259
+ * @param detected - Detected function info
260
+ * @param sourceFile - Absolute path to the source file
261
+ * @param env - Environment variables for workflow job bundles
262
+ * @param machineUser - Resolved machine user info
263
+ * @param workspaceId - Workspace ID
264
+ * @returns Entry file content string
265
+ */
266
+ function generateEntry(detected, sourceFile, env, machineUser, workspaceId) {
267
+ const absoluteSourcePath = path.resolve(sourceFile);
268
+ switch (detected.type) {
269
+ case "plain":
270
+ if (detected.namedMain) return ml`
271
+ export { main } from "${absoluteSourcePath}";
272
+ `;
273
+ return ml`
274
+ import _fn from "${absoluteSourcePath}";
275
+ export { _fn as main };
276
+ `;
277
+ case "resolver": {
278
+ const userExpr = buildMachineUserExpr(machineUser, workspaceId);
279
+ return ml`
280
+ import _internalResolver from "${absoluteSourcePath}";
281
+ import { t } from "@tailor-platform/sdk";
282
+
283
+ const _env = ${JSON.stringify(env)};
284
+ const _user = ${userExpr};
285
+
286
+ const $tailor_resolver_body = async (context) => {
287
+ const enrichedContext = { ...context, env: _env, user: _user };
288
+
289
+ if (_internalResolver.input) {
290
+ const result = t.object(_internalResolver.input).parse({
291
+ value: enrichedContext.input,
292
+ data: enrichedContext.input,
293
+ user: enrichedContext.user,
294
+ });
295
+
296
+ if (result.issues) {
297
+ const errorMessages = result.issues
298
+ .map(issue => {
299
+ const path = issue.path ? issue.path.join('.') : '';
300
+ return path ? \` \${path}: \${issue.message}\` : issue.message;
301
+ })
302
+ .join('\\n');
303
+ throw new Error(\`Failed to input validation:\\n\${errorMessages}\`);
304
+ }
305
+ }
306
+
307
+ return _internalResolver.body(enrichedContext);
308
+ };
309
+
310
+ export { $tailor_resolver_body as main };
311
+ `;
312
+ }
313
+ case "executor": {
314
+ const actorExpr = buildMachineActorExpr(machineUser, workspaceId);
315
+ return ml`
316
+ import _internalExecutor from "${absoluteSourcePath}";
317
+
318
+ const _env = ${JSON.stringify(env)};
319
+ const _actor = ${actorExpr};
320
+
321
+ const __executor_function = async (args) => {
322
+ return _internalExecutor.operation.body({ ...args, env: _env, actor: _actor });
323
+ };
324
+
325
+ export { __executor_function as main };
326
+ `;
327
+ }
328
+ case "workflow-job": {
329
+ const exportName = detected.exportName;
330
+ return ml`
331
+ import { ${exportName} } from "${absoluteSourcePath}";
332
+
333
+ const env = ${JSON.stringify(env)};
334
+
335
+ export async function main(input) {
336
+ return await ${exportName}.body(input, { env });
337
+ }
338
+ `;
339
+ }
340
+ }
341
+ }
342
+ /**
343
+ * Build a JSON expression for a machine user TailorUser object.
344
+ * @param machineUser - Resolved machine user info
345
+ * @param workspaceId - Workspace ID
346
+ * @returns JSON string for the user expression
347
+ */
348
+ function buildMachineUserExpr(machineUser, workspaceId) {
349
+ return JSON.stringify({
350
+ id: machineUser.id,
351
+ type: "machine_user",
352
+ workspaceId,
353
+ attributes: machineUser.attributes,
354
+ attributeList: machineUser.attributeList
355
+ });
356
+ }
357
+ /**
358
+ * Build a JSON expression for a machine user TailorActor object.
359
+ * @param machineUser - Resolved machine user info
360
+ * @param workspaceId - Workspace ID
361
+ * @returns JSON string for the actor expression
362
+ */
363
+ function buildMachineActorExpr(machineUser, workspaceId) {
364
+ return JSON.stringify({
365
+ workspaceId,
366
+ userId: machineUser.id,
367
+ attributes: machineUser.attributes,
368
+ attributeList: machineUser.attributeList,
369
+ userType: "USER_TYPE_MACHINE_USER"
370
+ });
371
+ }
372
+
373
+ //#endregion
374
+ //#region src/cli/commands/function/detect.ts
375
+ /**
376
+ * Function type detection for test-run command
377
+ *
378
+ * Detects the function type (resolver, executor, workflow job, or plain function)
379
+ * by dynamically importing the module and checking against known schemas.
380
+ */
381
+ /**
382
+ * Detect the function type from a file by importing it and checking against schemas.
383
+ * @param options - Detection options
384
+ * @returns Detected function information
385
+ */
386
+ async function detectFunctionType(options) {
387
+ const { filePath, jobName } = options;
388
+ const module = await import(pathToFileURL(filePath).href);
389
+ const resolverResult = ResolverSchema.safeParse(module.default);
390
+ if (resolverResult.success) return {
391
+ type: "resolver",
392
+ name: resolverResult.data.name
393
+ };
394
+ const executorResult = ExecutorSchema.safeParse(module.default);
395
+ if (executorResult.success) {
396
+ const { operation } = executorResult.data;
397
+ if (operation.kind === "function" || operation.kind === "jobFunction") return {
398
+ type: "executor",
399
+ name: executorResult.data.name
400
+ };
401
+ }
402
+ const workflowJobResult = detectWorkflowJob(module, jobName);
403
+ if (workflowJobResult) return workflowJobResult;
404
+ if (typeof module.default === "function") return {
405
+ type: "plain",
406
+ name: deriveNameFromPath(filePath)
407
+ };
408
+ if (typeof module.main === "function") return {
409
+ type: "plain",
410
+ name: deriveNameFromPath(filePath),
411
+ namedMain: true
412
+ };
413
+ throw new Error(`Could not detect function type from ${filePath}.\nThe file must have one of:
414
+ - A default-exported resolver (createResolver)
415
+ - A default-exported executor (createExecutor) with function/jobFunction operation
416
+ - A named-exported workflow job (createWorkflowJob)
417
+ - A default-exported function
418
+ - A named-exported "main" function`);
419
+ }
420
+ /**
421
+ * Scan all named exports for workflow jobs.
422
+ * If jobName is specified, find the job whose `.name` matches.
423
+ * If not specified and exactly one job exists, use it.
424
+ * If multiple jobs exist, throw an error with the list.
425
+ * @param module - The imported module
426
+ * @param jobName - Workflow job name to select
427
+ * @returns Detected function or null if no workflow jobs found
428
+ */
429
+ function detectWorkflowJob(module, jobName) {
430
+ const jobs = [];
431
+ for (const [exportName, exportValue] of Object.entries(module)) {
432
+ if (exportName === "default") continue;
433
+ const result = WorkflowJobSchema.safeParse(exportValue);
434
+ if (result.success) jobs.push({
435
+ name: result.data.name,
436
+ exportName
437
+ });
438
+ }
439
+ if (jobs.length === 0) return null;
440
+ if (jobName) {
441
+ const match = jobs.find((j) => j.name === jobName);
442
+ if (!match) {
443
+ const available$1 = jobs.map((j) => ` - "${j.name}" (export: ${j.exportName})`).join("\n");
444
+ throw new Error(`Workflow job "${jobName}" not found. Available jobs:\n${available$1}`);
445
+ }
446
+ return {
447
+ type: "workflow-job",
448
+ name: match.name,
449
+ exportName: match.exportName
450
+ };
451
+ }
452
+ if (jobs.length === 1) return {
453
+ type: "workflow-job",
454
+ name: jobs[0].name,
455
+ exportName: jobs[0].exportName
456
+ };
457
+ const available = jobs.map((j) => ` - "${j.name}" (export: ${j.exportName})`).join("\n");
458
+ throw new Error(`Multiple workflow jobs found. Specify one with --name:\n${available}`);
459
+ }
460
+ /**
461
+ * Derive a script name from a file path (filename without extension).
462
+ * @param filePath - Absolute path to the function file
463
+ * @returns Filename without extension
464
+ */
465
+ function deriveNameFromPath(filePath) {
466
+ return path.basename(filePath, path.extname(filePath));
467
+ }
468
+
469
+ //#endregion
470
+ //#region src/cli/commands/function/test-run.ts
471
+ /**
472
+ * `tailor-sdk function test-run` command
473
+ *
474
+ * Bundles and executes a function on the Tailor Platform server
475
+ * without deploying (applying) the application.
476
+ */
477
+ const testRunCommand = defineCommand({
478
+ name: "test-run",
479
+ description: "Run a function on the Tailor Platform server without deploying.",
480
+ args: z.object({
481
+ ...commonArgs,
482
+ ...jsonArgs,
483
+ ...workspaceArgs,
484
+ file: arg(z.string(), {
485
+ positional: true,
486
+ description: "Path to the function file"
487
+ }),
488
+ name: arg(z.string().optional(), {
489
+ alias: "n",
490
+ description: "Workflow job name to run (matches the `name` field of createWorkflowJob)"
491
+ }),
492
+ arg: arg(z.string().optional(), {
493
+ alias: "a",
494
+ description: "JSON argument to pass to the function"
495
+ }),
496
+ "machine-user": arg(z.string().optional(), {
497
+ alias: "m",
498
+ description: "Machine user name for authentication"
499
+ }),
500
+ config: arg(z.string().default("tailor.config.ts"), {
501
+ alias: "c",
502
+ description: "Path to SDK config file"
503
+ })
504
+ }),
505
+ notes: `You can pass either a source file (\`.ts\`) or a pre-bundled file (\`.js\`).
506
+ When a \`.js\` file is provided, detection and bundling are skipped and the file is executed as-is.
507
+
508
+ > [!WARNING]
509
+ > Workflow job \`.trigger()\` calls do not work in test-run mode.
510
+ > Triggered jobs are not executed; only the target job's \`body\` function runs in isolation.`,
511
+ examples: [
512
+ {
513
+ cmd: "resolvers/add.ts --arg '{\"input\":{\"a\":1,\"b\":2}}'",
514
+ desc: "Run a resolver with input arguments"
515
+ },
516
+ {
517
+ cmd: "workflows/sample.ts --name validate-order",
518
+ desc: "Run a specific workflow job by name"
519
+ },
520
+ {
521
+ cmd: ".tailor-sdk/resolvers/add.js --arg '{\"input\":{\"a\":1,\"b\":2}}'",
522
+ desc: "Run a pre-bundled .js file directly"
523
+ }
524
+ ],
525
+ run: withCommonArgs(async (args) => {
526
+ const filePath = path.resolve(args.file);
527
+ if (!fs$1.existsSync(filePath)) throw new Error(`File not found: ${filePath}`);
528
+ const { config } = await loadConfig(args.config);
529
+ const authNamespace = resolveAuthNamespace(config.auth);
530
+ const machineUserName = resolveMachineUserName(args["machine-user"], config.auth);
531
+ const client = await initOperatorClient(await loadAccessToken({
532
+ useProfile: true,
533
+ profile: args.profile
534
+ }));
535
+ const workspaceId = loadWorkspaceId({
536
+ workspaceId: args["workspace-id"],
537
+ profile: args.profile
538
+ });
539
+ const machineUser = await resolveMachineUser({
540
+ client,
541
+ workspaceId,
542
+ authNamespace,
543
+ machineUserName,
544
+ authConfig: config.auth
545
+ });
546
+ const relativePath = path.relative(process.cwd(), filePath);
547
+ const isPreBundled = filePath.endsWith(".js");
548
+ let bundledCode;
549
+ let scriptName;
550
+ let functionType;
551
+ let functionName;
552
+ if (isPreBundled) {
553
+ scriptName = path.basename(filePath);
554
+ bundledCode = fs$1.readFileSync(filePath, "utf-8");
555
+ logger.info(`Using pre-bundled script ${styles.bold(scriptName)}`);
556
+ } else {
557
+ logger.info(`Detecting function type from ${styles.path(relativePath)}`);
558
+ const detected = await detectFunctionType({
559
+ filePath,
560
+ jobName: args.name
561
+ });
562
+ functionType = detected.type;
563
+ functionName = detected.name;
564
+ logger.info(`Detected: ${styles.bold(detected.type)} ${styles.info(`"${detected.name}"`)}`);
565
+ logger.info("Bundling...");
566
+ ({bundledCode, scriptName} = await bundleForTestRun({
567
+ detected,
568
+ sourceFile: filePath,
569
+ env: config.env ?? {},
570
+ inlineSourcemap: config.inlineSourcemap,
571
+ machineUser,
572
+ workspaceId
573
+ }));
574
+ logger.info(`Bundled as ${styles.bold(scriptName)}`);
575
+ }
576
+ const authInvoker = create(AuthInvokerSchema, {
577
+ namespace: authNamespace,
578
+ machineUserName: machineUser.name
579
+ });
580
+ logger.info(`Executing on workspace ${styles.dim(workspaceId)}...`);
581
+ const result = await executeScript({
582
+ client,
583
+ workspaceId,
584
+ name: scriptName,
585
+ code: bundledCode,
586
+ arg: args.arg,
587
+ invoker: authInvoker
588
+ });
589
+ if (args.json) logger.out({
590
+ success: result.success,
591
+ scriptName,
592
+ functionType,
593
+ functionName,
594
+ logs: result.logs,
595
+ result: result.result,
596
+ error: result.error
597
+ });
598
+ else {
599
+ if (result.success) logger.success("Execution succeeded");
600
+ else logger.error("Execution failed");
601
+ if (result.logs?.trim()) {
602
+ logger.log(styles.bold("\nLogs:"));
603
+ for (const line of result.logs.split("\n")) logger.log(` ${line}`);
604
+ }
605
+ if (result.result && result.success) {
606
+ logger.log(styles.bold("\nResult:"));
607
+ try {
608
+ const parsed = JSON.parse(result.result);
609
+ logger.log(` ${JSON.stringify(parsed, null, 2).split("\n").join("\n ")}`);
610
+ } catch {
611
+ logger.log(` ${result.result}`);
612
+ }
613
+ }
614
+ if (result.error && !result.success) {
615
+ logger.log(styles.bold("\nError:"));
616
+ logger.log(` ${styles.error(result.error)}`);
617
+ }
618
+ }
619
+ if (!result.success) process.exit(1);
620
+ })
621
+ });
622
+ /**
623
+ * Resolve auth namespace from config.
624
+ * @param authConfig - Auth configuration from tailor.config.ts
625
+ * @returns Resolved auth namespace
626
+ */
627
+ function resolveAuthNamespace(authConfig) {
628
+ if (authConfig?.name) return authConfig.name;
629
+ throw new Error("Auth namespace is required. Ensure tailor.config.ts has an auth config.");
630
+ }
631
+ /**
632
+ * Resolve machine user name from CLI args or config. Priority: --machine-user > first key of config.auth.machineUsers
633
+ * @param cliMachineUser - CLI --machine-user value
634
+ * @param authConfig - Auth configuration from tailor.config.ts
635
+ * @returns Resolved machine user name
636
+ */
637
+ function resolveMachineUserName(cliMachineUser, authConfig) {
638
+ if (cliMachineUser) return cliMachineUser;
639
+ if (authConfig && !("external" in authConfig && authConfig.external)) {
640
+ const machineUsers = authConfig.machineUsers;
641
+ if (machineUsers) {
642
+ const keys = Object.keys(machineUsers);
643
+ if (keys.length > 0) return keys[0];
644
+ }
645
+ }
646
+ throw new Error("Machine user is required. Provide --machine-user or ensure tailor.config.ts has machine users configured.");
647
+ }
648
+ /**
649
+ * Resolve full machine user info: name, id (from API), and attributes (from config).
650
+ * @param options - Options for resolving machine user
651
+ * @returns Resolved machine user with id, attributes, and attributeList
652
+ */
653
+ async function resolveMachineUser(options) {
654
+ const { client, workspaceId, authNamespace, machineUserName, authConfig } = options;
655
+ let id = "00000000-0000-0000-0000-000000000000";
656
+ try {
657
+ const { machineUser } = await client.getAuthMachineUser({
658
+ workspaceId,
659
+ authNamespace,
660
+ name: machineUserName
661
+ });
662
+ if (machineUser?.id) id = machineUser.id;
663
+ } catch {
664
+ logger.debug(`Could not fetch machine user "${machineUserName}" from server, using nil UUID`);
665
+ }
666
+ const machineUserConfig = authConfig?.machineUsers?.[machineUserName];
667
+ let attributes = null;
668
+ let attributeList = [];
669
+ if (machineUserConfig && typeof machineUserConfig === "object") {
670
+ const cfg = machineUserConfig;
671
+ attributes = cfg.attributes ?? null;
672
+ attributeList = cfg.attributeList ?? [];
673
+ }
674
+ return {
675
+ name: machineUserName,
676
+ id,
677
+ attributes,
678
+ attributeList
679
+ };
680
+ }
681
+
201
682
  //#endregion
202
683
  //#region src/cli/commands/function/index.ts
203
684
  const functionCommand = defineCommand({
204
685
  name: "function",
205
686
  description: "Manage functions",
206
- subCommands: { logs: logsCommand },
687
+ subCommands: {
688
+ logs: logsCommand,
689
+ "test-run": testRunCommand
690
+ },
207
691
  async run() {
208
692
  await runCommand(logsCommand, []);
209
693
  }
@@ -224,7 +708,7 @@ const generateCommand = defineCommand({
224
708
  alias: "W",
225
709
  description: "Watch for type/resolver changes and regenerate"
226
710
  })
227
- }),
711
+ }).strict(),
228
712
  run: withCommonArgs(async (args) => {
229
713
  await generate({
230
714
  configPath: args.config,
@@ -260,7 +744,7 @@ const initCommand = defineCommand({
260
744
  alias: "t",
261
745
  description: "Template name"
262
746
  })
263
- }),
747
+ }).strict(),
264
748
  run: withCommonArgs(async (args) => {
265
749
  const packageJson$1 = await readPackageJson();
266
750
  const version = packageJson$1.version && packageJson$1.version !== "0.0.0" ? packageJson$1.version : "latest";
@@ -292,7 +776,7 @@ const startAuthServer = async () => {
292
776
  const client = initOAuth2Client();
293
777
  const state = randomState();
294
778
  const codeVerifier = await generateCodeVerifier();
295
- return new Promise((resolve, reject) => {
779
+ return new Promise((resolve$1, reject) => {
296
780
  const server = http.createServer(async (req, res) => {
297
781
  try {
298
782
  if (!req.url?.startsWith("/callback")) throw new Error("Invalid callback URL");
@@ -318,7 +802,7 @@ const startAuthServer = async () => {
318
802
  status: "ok",
319
803
  message: "Successfully authenticated. Please close this window."
320
804
  }));
321
- resolve();
805
+ resolve$1();
322
806
  } catch (error) {
323
807
  res.writeHead(401);
324
808
  res.end("Authentication failed");
@@ -355,7 +839,7 @@ const startAuthServer = async () => {
355
839
  const loginCommand = defineCommand({
356
840
  name: "login",
357
841
  description: "Login to Tailor Platform.",
358
- args: z.object({ ...commonArgs }),
842
+ args: z.object({ ...commonArgs }).strict(),
359
843
  run: withCommonArgs(async () => {
360
844
  await startAuthServer();
361
845
  logger.success("Successfully logged in to Tailor Platform.");
@@ -367,7 +851,7 @@ const loginCommand = defineCommand({
367
851
  const logoutCommand = defineCommand({
368
852
  name: "logout",
369
853
  description: "Logout from Tailor Platform.",
370
- args: z.object({ ...commonArgs }),
854
+ args: z.object({ ...commonArgs }).strict(),
371
855
  run: withCommonArgs(async () => {
372
856
  const pfConfig = readPlatformConfig();
373
857
  const tokens = pfConfig.current_user ? pfConfig.users[pfConfig.current_user] : void 0;
@@ -424,7 +908,7 @@ const openCommand = defineCommand({
424
908
  args: z.object({
425
909
  ...commonArgs,
426
910
  ...deploymentArgs
427
- }),
911
+ }).strict(),
428
912
  run: withCommonArgs(async (args) => {
429
913
  const workspaceId = loadWorkspaceId({
430
914
  workspaceId: args["workspace-id"],
@@ -466,7 +950,7 @@ const createCommand$2 = defineCommand({
466
950
  alias: "w",
467
951
  description: "Workspace ID"
468
952
  })
469
- }),
953
+ }).strict(),
470
954
  run: withCommonArgs(async (args) => {
471
955
  const config = readPlatformConfig();
472
956
  if (config.profiles[args.name]) throw new Error(`Profile "${args.name}" already exists.`);
@@ -504,7 +988,7 @@ const deleteCommand$2 = defineCommand({
504
988
  positional: true,
505
989
  description: "Profile name"
506
990
  })
507
- }),
991
+ }).strict(),
508
992
  run: withCommonArgs(async (args) => {
509
993
  const config = readPlatformConfig();
510
994
  if (!config.profiles[args.name]) throw new Error(`Profile "${args.name}" not found.`);
@@ -522,7 +1006,7 @@ const listCommand$4 = defineCommand({
522
1006
  args: z.object({
523
1007
  ...commonArgs,
524
1008
  ...jsonArgs
525
- }),
1009
+ }).strict(),
526
1010
  run: withCommonArgs(async () => {
527
1011
  const config = readPlatformConfig();
528
1012
  const profiles = Object.entries(config.profiles);
@@ -562,7 +1046,7 @@ const updateCommand$1 = defineCommand({
562
1046
  alias: "w",
563
1047
  description: "New workspace ID"
564
1048
  })
565
- }),
1049
+ }).strict(),
566
1050
  run: withCommonArgs(async (args) => {
567
1051
  const config = readPlatformConfig();
568
1052
  if (!config.profiles[args.name]) throw new Error(`Profile "${args.name}" not found.`);
@@ -648,7 +1132,7 @@ const createSecretCommand = defineCommand({
648
1132
  ...commonArgs,
649
1133
  ...workspaceArgs,
650
1134
  ...secretValueArgs
651
- }),
1135
+ }).strict(),
652
1136
  run: withCommonArgs(async (args) => {
653
1137
  const client = await initOperatorClient(await loadAccessToken({
654
1138
  useProfile: true,
@@ -686,7 +1170,7 @@ const deleteSecretCommand = defineCommand({
686
1170
  ...workspaceArgs,
687
1171
  ...secretIdentifyArgs,
688
1172
  ...confirmationArgs
689
- }),
1173
+ }).strict(),
690
1174
  run: withCommonArgs(async (args) => {
691
1175
  const client = await initOperatorClient(await loadAccessToken({
692
1176
  useProfile: true,
@@ -757,7 +1241,7 @@ const listSecretCommand = defineCommand({
757
1241
  ...jsonArgs,
758
1242
  ...workspaceArgs,
759
1243
  ...vaultArgs
760
- }),
1244
+ }).strict(),
761
1245
  run: withCommonArgs(async (args) => {
762
1246
  try {
763
1247
  const secrets = await secretList({
@@ -782,7 +1266,7 @@ const updateSecretCommand = defineCommand({
782
1266
  ...commonArgs,
783
1267
  ...workspaceArgs,
784
1268
  ...secretValueArgs
785
- }),
1269
+ }).strict(),
786
1270
  run: withCommonArgs(async (args) => {
787
1271
  const client = await initOperatorClient(await loadAccessToken({
788
1272
  useProfile: true,
@@ -823,7 +1307,7 @@ const createCommand$1 = defineCommand({
823
1307
  ...commonArgs,
824
1308
  ...workspaceArgs,
825
1309
  ...nameArgs
826
- }),
1310
+ }).strict(),
827
1311
  run: withCommonArgs(async (args) => {
828
1312
  const client = await initOperatorClient(await loadAccessToken({
829
1313
  useProfile: true,
@@ -856,7 +1340,7 @@ const deleteCommand$1 = defineCommand({
856
1340
  ...workspaceArgs,
857
1341
  ...nameArgs,
858
1342
  ...confirmationArgs
859
- }),
1343
+ }).strict(),
860
1344
  run: withCommonArgs(async (args) => {
861
1345
  const client = await initOperatorClient(await loadAccessToken({
862
1346
  useProfile: true,
@@ -924,7 +1408,7 @@ const listCommand$3 = defineCommand({
924
1408
  ...commonArgs,
925
1409
  ...jsonArgs,
926
1410
  ...workspaceArgs
927
- }),
1411
+ }).strict(),
928
1412
  run: withCommonArgs(async (args) => {
929
1413
  const vaults = await vaultList({
930
1414
  workspaceId: args["workspace-id"],
@@ -1066,7 +1550,7 @@ async function uploadDirectory(client, workspaceId, deploymentId, rootDir, showP
1066
1550
  */
1067
1551
  async function collectFiles(rootDir, currentDir = "") {
1068
1552
  const dirPath = path.join(rootDir, currentDir);
1069
- const entries = await fs$2.promises.readdir(dirPath, { withFileTypes: true });
1553
+ const entries = await fs.promises.readdir(dirPath, { withFileTypes: true });
1070
1554
  const files = [];
1071
1555
  for (const entry of entries) {
1072
1556
  const rel = path.join(currentDir, entry.name);
@@ -1085,7 +1569,7 @@ async function uploadSingleFile(client, workspaceId, deploymentId, rootDir, file
1085
1569
  return;
1086
1570
  }
1087
1571
  const contentType = mime;
1088
- const readStream = fs$2.createReadStream(absPath, { highWaterMark: CHUNK_SIZE });
1572
+ const readStream = fs.createReadStream(absPath, { highWaterMark: CHUNK_SIZE });
1089
1573
  async function* requestStream() {
1090
1574
  yield { payload: {
1091
1575
  case: "initialMetadata",
@@ -1136,9 +1620,10 @@ const deployCommand = defineCommand({
1136
1620
  }),
1137
1621
  dir: arg(z.string(), {
1138
1622
  alias: "d",
1139
- description: "Path to the static website files"
1623
+ description: "Path to the static website files",
1624
+ completion: { type: "directory" }
1140
1625
  })
1141
- }),
1626
+ }).strict(),
1142
1627
  run: withCommonArgs(async (args) => {
1143
1628
  logger.info(`Deploying static website "${args.name}" from directory: ${args.dir}`);
1144
1629
  const client = await initOperatorClient(await loadAccessToken({
@@ -1151,7 +1636,7 @@ const deployCommand = defineCommand({
1151
1636
  workspaceId: args["workspace-id"],
1152
1637
  profile: args.profile
1153
1638
  });
1154
- if (!fs$2.existsSync(dir) || !fs$2.statSync(dir).isDirectory()) throw new Error(`Directory not found or not a directory: ${dir}`);
1639
+ if (!fs.existsSync(dir) || !fs.statSync(dir).isDirectory()) throw new Error(`Directory not found or not a directory: ${dir}`);
1155
1640
  const { url, skippedFiles } = await withTimeout(deployStaticWebsite(client, workspaceId, name, dir, !args.json), 10 * 6e4, "Deployment timed out after 10 minutes.");
1156
1641
  if (args.json) logger.out({
1157
1642
  name,
@@ -1179,7 +1664,7 @@ const getCommand = defineCommand({
1179
1664
  positional: true,
1180
1665
  description: "Static website name"
1181
1666
  })
1182
- }),
1667
+ }).strict(),
1183
1668
  run: withCommonArgs(async (args) => {
1184
1669
  const client = await initOperatorClient(await loadAccessToken({
1185
1670
  useProfile: true,
@@ -1249,7 +1734,7 @@ const listCommand$2 = defineCommand({
1249
1734
  ...commonArgs,
1250
1735
  ...jsonArgs,
1251
1736
  ...workspaceArgs
1252
- }),
1737
+ }).strict(),
1253
1738
  run: withCommonArgs(async (args) => {
1254
1739
  const websites = await listStaticWebsites({
1255
1740
  workspaceId: args["workspace-id"],
@@ -1523,7 +2008,7 @@ function resolveAllNamespaces(config, options) {
1523
2008
  */
1524
2009
  async function runLiamBuild(schemaPath, cwd) {
1525
2010
  fs$1.mkdirSync(cwd, { recursive: true });
1526
- return await new Promise((resolve, reject) => {
2011
+ return await new Promise((resolve$1, reject) => {
1527
2012
  let liamBinPath;
1528
2013
  try {
1529
2014
  liamBinPath = resolveCliBinPath({
@@ -1560,7 +2045,7 @@ async function runLiamBuild(schemaPath, cwd) {
1560
2045
  reject(error);
1561
2046
  });
1562
2047
  child.on("close", (code) => {
1563
- if (code === 0) resolve();
2048
+ if (code === 0) resolve$1();
1564
2049
  else {
1565
2050
  if (stderrOutput) logger.error(stderrOutput);
1566
2051
  logger.error("liam CLI exited with a non-zero code. Ensure `@liam-hq/cli erd build --format tbls --input schema.json` works in your project.");
@@ -1637,9 +2122,10 @@ const erdExportCommand = defineCommand({
1637
2122
  }),
1638
2123
  output: arg(z.string().default(DEFAULT_ERD_BASE_DIR), {
1639
2124
  alias: "o",
1640
- description: "Output directory path for tbls-compatible ERD JSON (writes to `<outputDir>/<namespace>/schema.json`)"
2125
+ description: "Output directory path for tbls-compatible ERD JSON (writes to `<outputDir>/<namespace>/schema.json`)",
2126
+ completion: { type: "directory" }
1641
2127
  })
1642
- }),
2128
+ }).strict(),
1643
2129
  run: withCommonArgs(async (args) => {
1644
2130
  const { client, workspaceId, config } = await initErdContext(args);
1645
2131
  const outputDir = path.resolve(process.cwd(), String(args.output));
@@ -1677,7 +2163,7 @@ const erdDeployCommand = defineCommand({
1677
2163
  alias: "n",
1678
2164
  description: "TailorDB namespace name (optional - deploys all namespaces with erdSite if omitted)"
1679
2165
  })
1680
- }),
2166
+ }).strict(),
1681
2167
  run: withCommonArgs(async (args) => {
1682
2168
  const { client, workspaceId, config } = await initErdContext(args);
1683
2169
  const buildResults = await prepareErdBuilds({
@@ -1723,7 +2209,7 @@ async function runServeDist(results) {
1723
2209
  logger.warn(`Multiple namespaces found. To serve another namespace, run:\n${commands}`);
1724
2210
  }
1725
2211
  fs$1.mkdirSync(primary.erdDir, { recursive: true });
1726
- return await new Promise((resolve, reject) => {
2212
+ return await new Promise((resolve$1, reject) => {
1727
2213
  let serveBinPath;
1728
2214
  try {
1729
2215
  serveBinPath = resolveCliBinPath({
@@ -1744,7 +2230,7 @@ async function runServeDist(results) {
1744
2230
  reject(error);
1745
2231
  });
1746
2232
  child.on("exit", (code) => {
1747
- if (code === 0) resolve();
2233
+ if (code === 0) resolve$1();
1748
2234
  else {
1749
2235
  logger.error("serve CLI exited with a non-zero code. Ensure `serve dist` works in your project.");
1750
2236
  reject(/* @__PURE__ */ new Error(`serve CLI exited with code ${code ?? 1}`));
@@ -1762,7 +2248,7 @@ const erdServeCommand = defineCommand({
1762
2248
  alias: "n",
1763
2249
  description: "TailorDB namespace name (uses first namespace in config if not specified)"
1764
2250
  })
1765
- }),
2251
+ }).strict(),
1766
2252
  run: withCommonArgs(async (args) => {
1767
2253
  const { client, workspaceId, config } = await initErdContext(args);
1768
2254
  await runServeDist(await prepareErdBuilds({
@@ -1875,7 +2361,7 @@ const setCommand = defineCommand({
1875
2361
  alias: "n",
1876
2362
  description: "Target TailorDB namespace (required if multiple namespaces exist)"
1877
2363
  })
1878
- }),
2364
+ }).strict(),
1879
2365
  run: withCommonArgs(async (args) => {
1880
2366
  await set({
1881
2367
  configPath: args.config,
@@ -1948,7 +2434,7 @@ const statusCommand = defineCommand({
1948
2434
  alias: "n",
1949
2435
  description: "Target TailorDB namespace (shows all namespaces if not specified)"
1950
2436
  })
1951
- }),
2437
+ }).strict(),
1952
2438
  run: withCommonArgs(async (args) => {
1953
2439
  await status({
1954
2440
  configPath: args.config,
@@ -1996,7 +2482,7 @@ const tailordbCommand = defineCommand({
1996
2482
  const currentCommand = defineCommand({
1997
2483
  name: "current",
1998
2484
  description: "Show current user.",
1999
- args: z.object({ ...commonArgs }),
2485
+ args: z.object({ ...commonArgs }).strict(),
2000
2486
  run: withCommonArgs(async () => {
2001
2487
  const config = readPlatformConfig();
2002
2488
  if (!config.current_user) throw new Error(ml`
@@ -2019,7 +2505,7 @@ const listCommand$1 = defineCommand({
2019
2505
  args: z.object({
2020
2506
  ...commonArgs,
2021
2507
  ...jsonArgs
2022
- }),
2508
+ }).strict(),
2023
2509
  run: withCommonArgs(async (args) => {
2024
2510
  const config = readPlatformConfig();
2025
2511
  const users = Object.keys(config.users);
@@ -2113,7 +2599,7 @@ const createCommand = defineCommand({
2113
2599
  alias: "W",
2114
2600
  description: "Grant write permission (default: read-only)"
2115
2601
  })
2116
- }),
2602
+ }).strict(),
2117
2603
  run: withCommonArgs(async (args) => {
2118
2604
  const config = readPlatformConfig();
2119
2605
  if (!config.current_user) throw new Error(ml`
@@ -2142,7 +2628,7 @@ const deleteCommand = defineCommand({
2142
2628
  positional: true,
2143
2629
  description: "Token name"
2144
2630
  })
2145
- }),
2631
+ }).strict(),
2146
2632
  run: withCommonArgs(async (args) => {
2147
2633
  const config = readPlatformConfig();
2148
2634
  if (!config.current_user) throw new Error(ml`
@@ -2162,7 +2648,7 @@ const listCommand = defineCommand({
2162
2648
  args: z.object({
2163
2649
  ...commonArgs,
2164
2650
  ...jsonArgs
2165
- }),
2651
+ }).strict(),
2166
2652
  run: withCommonArgs(async (args) => {
2167
2653
  const config = readPlatformConfig();
2168
2654
  if (!config.current_user) throw new Error(ml`
@@ -2215,7 +2701,7 @@ const updateCommand = defineCommand({
2215
2701
  alias: "W",
2216
2702
  description: "Grant write permission (if not specified, keeps read-only)"
2217
2703
  })
2218
- }),
2704
+ }).strict(),
2219
2705
  run: withCommonArgs(async (args) => {
2220
2706
  const config = readPlatformConfig();
2221
2707
  if (!config.current_user) throw new Error(ml`
@@ -2262,7 +2748,7 @@ const switchCommand = defineCommand({
2262
2748
  positional: true,
2263
2749
  description: "User email"
2264
2750
  })
2265
- }),
2751
+ }).strict(),
2266
2752
  run: withCommonArgs(async (args) => {
2267
2753
  const config = readPlatformConfig();
2268
2754
  if (!config.users[args.user]) throw new Error(ml`
@@ -2378,6 +2864,7 @@ const mainCommand = withCompletionCommand(defineCommand({
2378
2864
  oauth2client: oauth2clientCommand,
2379
2865
  open: openCommand,
2380
2866
  profile: profileCommand,
2867
+ query: queryCommand,
2381
2868
  remove: removeCommand$1,
2382
2869
  secret: secretCommand,
2383
2870
  show: showCommand,