@tailor-platform/sdk 2.3.0 → 2.4.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 (102) hide show
  1. package/CHANGELOG.md +68 -0
  2. package/README.md +1 -1
  3. package/dist/{application-F-nl107y.mjs → application-C8a0UJ-z.mjs} +201 -149
  4. package/dist/application-C8a0UJ-z.mjs.map +1 -0
  5. package/dist/application-D4zOiLLa.mjs +3 -0
  6. package/dist/cli/commands/tailordb/migrate/diff-calculator.d.mts +4 -4
  7. package/dist/cli/commands/tailordb/migrate/generate.d.mts +3 -3
  8. package/dist/cli/commands/tailordb/migrate/snapshot.d.mts +5 -5
  9. package/dist/cli/commands/tailordb/truncate.d.mts +2 -2
  10. package/dist/cli/lib.mjs +2 -2
  11. package/dist/cli/lib.mjs.map +1 -1
  12. package/dist/cli/main.mjs +174 -106
  13. package/dist/cli/main.mjs.map +1 -1
  14. package/dist/cli/ts-hook.mjs +3 -1
  15. package/dist/completion/zsh-worker.zsh +19 -11
  16. package/dist/configure/config/index.d.mts +1 -1
  17. package/dist/configure/index.d.mts +2 -1
  18. package/dist/configure/index.mjs +2 -2
  19. package/dist/configure/index.mjs.map +1 -1
  20. package/dist/configure/services/aigateway/index.d.mts +5 -4
  21. package/dist/configure/services/aigateway/types.d.mts +6 -1
  22. package/dist/configure/services/auth/types.d.mts +2 -2
  23. package/dist/configure/services/tailordb/permission.d.mts +1 -1
  24. package/dist/configure/services/tailordb/schema.d.mts +1 -1
  25. package/dist/configure/services/tailordb/types.d.mts +7 -4
  26. package/dist/configure/types/auth-namespace-name.d.mts +18 -0
  27. package/dist/{crashreport-CINZ5dVN.mjs → crashreport-Cd4TqfZq.mjs} +1 -1
  28. package/dist/{crashreport-CIIfLnoO.mjs → crashreport-Q0pDAlrj.mjs} +8 -4
  29. package/dist/{crashreport-CIIfLnoO.mjs.map → crashreport-Q0pDAlrj.mjs.map} +1 -1
  30. package/dist/{errors-BVb6vYGy.mjs → errors-Bxut5_Sy.mjs} +2 -2
  31. package/dist/{errors-BVb6vYGy.mjs.map → errors-Bxut5_Sy.mjs.map} +1 -1
  32. package/dist/file-BUcmVIH2.mjs.map +1 -1
  33. package/dist/kysely/index.mjs +2 -1
  34. package/dist/kysely/index.mjs.map +1 -1
  35. package/dist/{logger-DSdExfor.mjs → logger-D0bEznPv.mjs} +9 -5
  36. package/dist/{logger-DSdExfor.mjs.map → logger-D0bEznPv.mjs.map} +1 -1
  37. package/dist/package-json-8b0O9TlX.mjs.map +1 -1
  38. package/dist/plugin/builtin/enum-constants/index.d.mts +1 -1
  39. package/dist/plugin/builtin/enum-constants/index.mjs +5 -5
  40. package/dist/plugin/builtin/enum-constants/index.mjs.map +1 -1
  41. package/dist/plugin/builtin/file-utils/index.d.mts +1 -1
  42. package/dist/plugin/builtin/file-utils/index.mjs +14 -11
  43. package/dist/plugin/builtin/file-utils/index.mjs.map +1 -1
  44. package/dist/plugin/builtin/kysely-type/index.d.mts +1 -1
  45. package/dist/plugin/builtin/kysely-type/index.mjs +9 -9
  46. package/dist/plugin/builtin/kysely-type/index.mjs.map +1 -1
  47. package/dist/plugin/builtin/seed/index.mjs +1 -1
  48. package/dist/plugin/builtin/seed/seed-type-processor.d.mts +4 -4
  49. package/dist/plugin/get-generated-type.d.mts +4 -4
  50. package/dist/plugin/index.mjs +13 -13
  51. package/dist/plugin/index.mjs.map +1 -1
  52. package/dist/plugin/types.d.mts +2 -2
  53. package/dist/plugin/with-context.d.mts +1 -1
  54. package/dist/{register-ts-hook-ClI226n2.mjs → register-ts-hook-Vqjza10T.mjs} +552 -416
  55. package/dist/register-ts-hook-Vqjza10T.mjs.map +1 -0
  56. package/dist/{repl-editor-BCozyiNq.mjs → repl-editor-F9LotMNx.mjs} +3 -2
  57. package/dist/{repl-editor-BCozyiNq.mjs.map → repl-editor-F9LotMNx.mjs.map} +1 -1
  58. package/dist/runtime/file.d.mts +14 -14
  59. package/dist/{schema--xYWRGfe.mjs → schema-D4TC4BC3.mjs} +4 -3
  60. package/dist/schema-D4TC4BC3.mjs.map +1 -0
  61. package/dist/seed/index.d.mts +4 -4
  62. package/dist/seed/index.mjs +3 -3
  63. package/dist/seed/index.mjs.map +1 -1
  64. package/dist/{seed-xqM9WIHP.mjs → seed-Cibjmtry.mjs} +46 -40
  65. package/dist/seed-Cibjmtry.mjs.map +1 -0
  66. package/dist/{service-C_WpbKHu.mjs → service-2grcAOCJ.mjs} +24 -24
  67. package/dist/service-2grcAOCJ.mjs.map +1 -0
  68. package/dist/service-CaBPNDIZ.mjs +3 -0
  69. package/dist/{service-hZskxZmg.mjs → service-LTfp03ZZ.mjs} +7 -5
  70. package/dist/{service-hZskxZmg.mjs.map → service-LTfp03ZZ.mjs.map} +1 -1
  71. package/dist/types/aigateway.generated.d.mts +2 -2
  72. package/dist/types/auth.generated.d.mts +3 -3
  73. package/dist/types/executor.generated.d.mts +1 -1
  74. package/dist/types/tailordb.generated.d.mts +12 -12
  75. package/dist/utils/test/index.d.mts +4 -4
  76. package/dist/utils/test/index.mjs +4 -4
  77. package/dist/utils/test/index.mjs.map +1 -1
  78. package/dist/vitest/index.mjs +13 -7
  79. package/dist/vitest/index.mjs.map +1 -1
  80. package/dist/vitest/mocks/file.d.mts +1 -1
  81. package/docs/cli/application.md +3 -1
  82. package/docs/cli/function.md +17 -13
  83. package/docs/cli/tailordb.md +30 -30
  84. package/docs/cli/workspace.md +2 -2
  85. package/docs/cli-reference.md +21 -21
  86. package/docs/configuration.md +2 -2
  87. package/docs/migration/v2.md +4 -4
  88. package/docs/migration/v3.md +41 -0
  89. package/docs/quickstart.md +1 -1
  90. package/docs/services/aigateway.md +33 -9
  91. package/docs/services/executor.md +5 -1
  92. package/docs/services/tailordb-migration.md +47 -47
  93. package/docs/services/tailordb.md +7 -7
  94. package/docs/testing.md +1 -1
  95. package/package.json +6 -6
  96. package/dist/application-BZfk4HKm.mjs +0 -3
  97. package/dist/application-F-nl107y.mjs.map +0 -1
  98. package/dist/register-ts-hook-ClI226n2.mjs.map +0 -1
  99. package/dist/schema--xYWRGfe.mjs.map +0 -1
  100. package/dist/seed-xqM9WIHP.mjs.map +0 -1
  101. package/dist/service-C_WpbKHu.mjs.map +0 -1
  102. package/dist/service-D1RCdzIL.mjs +0 -3
@@ -1,11 +1,11 @@
1
1
  import { n as isSdkBranded } from "./brand-Eo4pLXPJ.mjs";
2
2
  import { n as getScopedWaitPoints } from "./wait-point-registry-TL99zotw.mjs";
3
3
  import { t as assertDefined } from "./assert-DBxo8jPo.mjs";
4
- import { a as parseBoolean, n as logger, r as styles } from "./logger-DSdExfor.mjs";
5
- import { a as AuthConfigSchema, b as functionSchema, c as stripTailorDBTypeBuilderHelpers, d as applyRelationMetadataToFieldConfig, f as buildRelationInfo, h as loadFilesWithIgnores, l as TailorDBServiceConfigSchema, m as validateRelationConfig, n as loadExecutor, o as AuthInvokerSchema, p as processRelationMetadata, s as TailorFieldSchema, t as createExecutorService, u as TailorDBTypeSchema, y as importUserModule } from "./service-C_WpbKHu.mjs";
4
+ import { a as parseBoolean, n as logger, r as styles } from "./logger-D0bEznPv.mjs";
5
+ import { a as AuthConfigSchema, b as functionSchema, c as stripTailorDBTypeBuilderHelpers, d as applyRelationMetadataToFieldConfig, f as buildRelationInfo, h as loadFilesWithIgnores, l as TailorDBServiceConfigSchema, m as validateRelationConfig, n as loadExecutor, o as AuthInvokerSchema, p as processRelationMetadata, s as TailorFieldSchema, t as createExecutorService, u as TailorDBTypeSchema, y as importUserModule } from "./service-2grcAOCJ.mjs";
6
6
  import { t as multiline } from "./multiline-sfHpTZZK.mjs";
7
7
  import { t as userAgent } from "./user-agent-Bgsszb5I.mjs";
8
- import { t as createCLIError } from "./errors-BVb6vYGy.mjs";
8
+ import { t as createCLIError } from "./errors-Bxut5_Sy.mjs";
9
9
  import { n as isNodeBuiltinImport, t as getNodeBuiltinMessage } from "./node-builtins-CmaL2Cbq.mjs";
10
10
  import { t as isPluginGeneratedType } from "./type-source-DH_LH20p.mjs";
11
11
  import { createRequire } from "node:module";
@@ -191,7 +191,8 @@ async function initOperatorClient(accessToken, config) {
191
191
  createTracingInterceptor(),
192
192
  concurrencyLimitInterceptor()
193
193
  ];
194
- return createClient(OperatorService, await createTransport(getPlatformBaseUrl(platformConfig), interceptors));
194
+ const transport = await createTransport(getPlatformBaseUrl(platformConfig), interceptors);
195
+ return createClient(OperatorService, transport);
195
196
  }
196
197
  /**
197
198
  * Create a Connect transport using connect-node (HTTP/2).
@@ -263,7 +264,7 @@ function retryInterceptor() {
263
264
  logger.debug(`retry: ${req.method.name} returned AlreadyExists on attempt ${i + 1}; treating as success (prior attempt likely committed)`);
264
265
  return synthesizeEmptyUnaryResponse(req);
265
266
  }
266
- const { reportCrash } = await import("./crashreport-CINZ5dVN.mjs");
267
+ const { reportCrash } = await import("./crashreport-Cd4TqfZq.mjs");
267
268
  await reportCrash(error, "handledError");
268
269
  }
269
270
  if (req.method.name !== "CreateWorkspace" && isRetirable(error, req.method.idempotency)) {
@@ -426,6 +427,7 @@ function isRetirable(error, idempotency) {
426
427
  }
427
428
  /**
428
429
  * Create an interceptor that enhances error messages from the Operator API.
430
+ * @internal
429
431
  * @returns Error handling interceptor
430
432
  */
431
433
  function errorHandlingInterceptor() {
@@ -435,8 +437,8 @@ function errorHandlingInterceptor() {
435
437
  } catch (error) {
436
438
  if (error instanceof ConnectError) {
437
439
  const { operation, resourceType } = parseMethodName(req.method.name);
438
- const requestParams = formatRequestParams(req.message);
439
- throw new ConnectError(`Failed to ${operation} ${resourceType}: ${error.rawMessage}\nRequest: ${requestParams}`, error.code, error.metadata);
440
+ const identity = formatRequestIdentity(req.message, req.method.name);
441
+ throw new ConnectError(`Failed to ${operation} ${resourceType}${identity}: ${error.rawMessage}`, error.code, error.metadata);
440
442
  }
441
443
  throw error;
442
444
  }
@@ -459,28 +461,45 @@ function parseMethodName(methodName) {
459
461
  resourceType: resource
460
462
  };
461
463
  }
462
- /**
463
- * JSON.stringify replacer that converts BigInt values to strings.
464
- * @param _key - Object key (unused)
465
- * @param value - Value to serialize
466
- * @returns Serializable value
467
- */
468
- function bigIntReplacer(_key, value) {
469
- if (typeof value === "bigint") return value.toString();
470
- return value;
464
+ const IDENTITY_KEYS = /* @__PURE__ */ new Set(["name", "id"]);
465
+ const IDENTITY_KEY_SUFFIXES = [
466
+ "Name",
467
+ "Id",
468
+ "Namespace"
469
+ ];
470
+ const NESTED_IDENTITY_KEY = "name";
471
+ const METHOD_IDENTITY_KEYS = {
472
+ GetMetadata: ["trn"],
473
+ SetMetadata: ["trn"],
474
+ AddCustomDomain: ["domain"],
475
+ GetCustomDomain: ["domain"],
476
+ RemoveCustomDomain: ["domain"],
477
+ CreateWorkflowJobFunctionExecutionPolicy: ["executionPolicyKey"],
478
+ UpdateWorkflowJobFunctionExecutionPolicy: ["executionPolicyKey"],
479
+ GetWorkflowJobFunctionExecutionPolicyByKey: ["executionPolicyKey"]
480
+ };
481
+ function isIdentityKey(key, methodName) {
482
+ if (key.startsWith("$")) return false;
483
+ return IDENTITY_KEYS.has(key) || IDENTITY_KEY_SUFFIXES.some((suffix) => key.endsWith(suffix)) || (METHOD_IDENTITY_KEYS[methodName]?.includes(key) ?? false);
471
484
  }
472
485
  /**
473
- * @internal
474
- * @param message - Request message to format
475
- * @returns Pretty-printed JSON or error placeholder
476
- */
477
- function formatRequestParams(message) {
478
- try {
479
- if (message && typeof message === "object" && "toJson" in message) return JSON.stringify(message.toJson(), bigIntReplacer, 2);
480
- return JSON.stringify(message, bigIntReplacer, 2);
481
- } catch {
482
- return "(unable to serialize request)";
486
+ * Format an allowlisted identity suffix for enhanced error messages.
487
+ *
488
+ * Only resource identifiers are included — the rest of the request payload
489
+ * can carry credentials and must never reach terminal or CI logs.
490
+ * @param message - Request message to extract identifiers from
491
+ * @param methodName - RPC method name used to resolve method-scoped identifiers
492
+ * @returns Identity suffix like " (namespaceName: x, type.name: y)", or an empty string
493
+ */
494
+ function formatRequestIdentity(message, methodName) {
495
+ if (typeof message !== "object" || message === null) return "";
496
+ const parts = [];
497
+ for (const [key, value] of Object.entries(message)) if (typeof value === "string" && value !== "" && isIdentityKey(key, methodName)) parts.push(`${key}: ${value}`);
498
+ else if (!key.startsWith("$") && value !== null && typeof value === "object" && !Array.isArray(value) && typeof value.$typeName === "string") {
499
+ const nestedName = value[NESTED_IDENTITY_KEY];
500
+ if (typeof nestedName === "string" && nestedName !== "") parts.push(`${key}.${NESTED_IDENTITY_KEY}: ${nestedName}`);
483
501
  }
502
+ return parts.length === 0 ? "" : ` (${parts.join(", ")})`;
484
503
  }
485
504
  const MAX_PAGE_SIZE = 1e3;
486
505
  /**
@@ -977,7 +996,7 @@ function isPluginExecutorWithFile(executor) {
977
996
  * @param executors - Array of plugin executor information
978
997
  * @param outputDir - Base output directory (e.g., .tailor)
979
998
  * @param typeGenerationResult - Result from plugin type generation (for import resolution)
980
- * @param sourceTypeInfoMap - Map of source type names to their source info
999
+ * @param sourceTypeInfoMap - Map of source table names to their source info
981
1000
  * @param configPath - Path to tailor.config.ts (used for resolving plugin import paths)
982
1001
  * @returns Array of generated file paths
983
1002
  */
@@ -998,7 +1017,7 @@ function generatePluginExecutorFiles(executors, outputDir, typeGenerationResult,
998
1017
  * @param info - Plugin executor metadata and definition
999
1018
  * @param outputDir - Base output directory (e.g., .tailor)
1000
1019
  * @param typeGenerationResult - Result from plugin type generation
1001
- * @param sourceTypeInfoMap - Map of source type names to their source info
1020
+ * @param sourceTypeInfoMap - Map of source table names to their source info
1002
1021
  * @param baseDirs - Base directories for resolving plugin import paths
1003
1022
  * @returns Absolute path to the generated file
1004
1023
  */
@@ -1021,7 +1040,7 @@ function generateSingleExecutorFile(info, outputDir, typeGenerationResult, sourc
1021
1040
  * @param executor - Executor definition with resolve
1022
1041
  * @param outputDir - Base output directory
1023
1042
  * @param typeGenerationResult - Result from plugin type generation
1024
- * @param sourceTypeInfoMap - Map of source type names to their source info
1043
+ * @param sourceTypeInfoMap - Map of source table names to their source info
1025
1044
  * @param baseDirs - Base directories for resolving plugin import paths
1026
1045
  * @returns TypeScript source code for executor file
1027
1046
  */
@@ -1056,7 +1075,7 @@ function generateExecutorFileContentNew(info, executor, outputDir, typeGeneratio
1056
1075
  * @param outputDir - Base output directory for generated files
1057
1076
  * @param pluginId - Plugin identifier used for output paths
1058
1077
  * @param typeGenerationResult - Result from plugin type generation
1059
- * @param sourceTypeInfoMap - Map of source type names to their source info
1078
+ * @param sourceTypeInfoMap - Map of source table names to their source info
1060
1079
  * @returns Map of context keys to their import information
1061
1080
  */
1062
1081
  function collectTypeImports(context, outputDir, pluginId, typeGenerationResult, sourceTypeInfoMap) {
@@ -1103,9 +1122,9 @@ function generateContextCode(context, typeImports) {
1103
1122
  return `{\n${entries.join(",\n")},\n}`;
1104
1123
  }
1105
1124
  /**
1106
- * Check if a value is a TailorDB type object.
1125
+ * Check if a value is a TailorDB table object.
1107
1126
  * @param value - Value to inspect
1108
- * @returns True if value is a type object with name and fields
1127
+ * @returns True if value is a table object with name and fields
1109
1128
  */
1110
1129
  function isTypeObject(value) {
1111
1130
  return typeof value === "object" && value !== null && "name" in value && "fields" in value && typeof value.name === "string";
@@ -1303,15 +1322,15 @@ function toKebabCase$1(str) {
1303
1322
  /**
1304
1323
  * Plugin Type Generator
1305
1324
  *
1306
- * Generates TypeScript files for plugin-generated types (TailorDB types).
1307
- * These files can be imported by plugin executors to reference generated types.
1325
+ * Generates TypeScript files for plugin-generated types (TailorDB tables).
1326
+ * These files can be imported by plugin executors to reference generated tables.
1308
1327
  */
1309
1328
  function isFieldDefinition(value) {
1310
1329
  return typeof value === "object" && value !== null;
1311
1330
  }
1312
1331
  /**
1313
- * Generate TypeScript files for plugin-generated types.
1314
- * These files export the type definition and can be imported by executor files.
1332
+ * Generate TypeScript files for plugin-generated tables.
1333
+ * These files export the table definition and can be imported by executor files.
1315
1334
  * @param types - Array of plugin type information
1316
1335
  * @param outputDir - Base output directory (e.g., .tailor)
1317
1336
  * @returns Generation result with file paths
@@ -1326,7 +1345,7 @@ function generatePluginTypeFiles(types, outputDir) {
1326
1345
  const seenTypeNames = /* @__PURE__ */ new Map();
1327
1346
  for (const info of types) {
1328
1347
  const existing = seenTypeNames.get(info.type.name);
1329
- if (existing) throw new Error(`Duplicate plugin-generated type name "${info.type.name}" detected. First: plugin "${existing.pluginId}" (kind: "${existing.kind}", source type: "${existing.sourceTypeName}"), Second: plugin "${info.pluginId}" (kind: "${info.kind}", source type: "${info.sourceTypeName}"). Plugin-generated type names must be unique.`);
1348
+ if (existing) throw new Error(`Duplicate plugin-generated table name "${info.type.name}" detected. First: plugin "${existing.pluginId}" (kind: "${existing.kind}", source: "${existing.sourceTypeName}"), Second: plugin "${info.pluginId}" (kind: "${info.kind}", source: "${info.sourceTypeName}"). Plugin-generated table names must be unique.`);
1330
1349
  seenTypeNames.set(info.type.name, info);
1331
1350
  const pluginDir = sanitizePluginId(info.pluginId);
1332
1351
  const typeOutputDir = path.join(outputDir, pluginDir, "types");
@@ -1357,8 +1376,8 @@ function generateTypeFileContent(info) {
1357
1376
  const fieldsCode = generateFieldsCode(type);
1358
1377
  return multiline`
1359
1378
  /**
1360
- * Auto-generated type by plugin: ${pluginId}
1361
- * Source type: ${sourceTypeName}
1379
+ * Auto-generated table by plugin: ${pluginId}
1380
+ * Source: ${sourceTypeName}
1362
1381
  * Kind: ${kind}
1363
1382
  *
1364
1383
  * DO NOT EDIT - This file is generated by @tailor-platform/sdk
@@ -1372,8 +1391,8 @@ function generateTypeFileContent(info) {
1372
1391
  }
1373
1392
  /**
1374
1393
  * Generate TypeScript code for field definitions.
1375
- * This creates a simplified version of the type's fields.
1376
- * @param type - TailorDB type
1394
+ * This creates a simplified version of the table's fields.
1395
+ * @param type - TailorDB table
1377
1396
  * @returns TypeScript code for fields object
1378
1397
  */
1379
1398
  function generateFieldsCode(type) {
@@ -1386,7 +1405,7 @@ function generateFieldsCode(type) {
1386
1405
  return `{\n${fieldEntries.join(",\n")},\n}`;
1387
1406
  }
1388
1407
  /**
1389
- * Map from TailorDB type to SDK method name.
1408
+ * Map from TailorDB table to SDK method name.
1390
1409
  */
1391
1410
  const typeToMethodMap = {
1392
1411
  string: "string",
@@ -1629,7 +1648,8 @@ function collectSdkBindings(program, functionName) {
1629
1648
  if (nodeType === "VariableDeclaration") {
1630
1649
  const varDecl = node;
1631
1650
  for (const decl of varDecl.declarations) {
1632
- const source = getImportSource(unwrapAwait(decl.init));
1651
+ const init = unwrapAwait(decl.init);
1652
+ const source = getImportSource(init);
1633
1653
  if (source && isTailorSdkSource(source)) {
1634
1654
  const id = decl.id;
1635
1655
  if (id.type === "Identifier") bindings.add(`__namespace__:${id.name}`);
@@ -1759,7 +1779,8 @@ function findAllWorkflows(program, _sourceText) {
1759
1779
  const args = node.arguments;
1760
1780
  const firstArg = args[0];
1761
1781
  if (args.length >= 1 && firstArg?.type === "ObjectExpression") {
1762
- const nameProp = findProperty(assertDefined(firstArg, "createWorkflow first argument missing").properties, "name");
1782
+ const configObj = assertDefined(firstArg, "createWorkflow first argument missing");
1783
+ const nameProp = findProperty(configObj.properties, "name");
1763
1784
  if (nameProp && isStringLiteral(nameProp.value)) {
1764
1785
  let exportName;
1765
1786
  let isDefaultExport = false;
@@ -2082,10 +2103,12 @@ function transformStartCalls(source, startContext, currentFilePath) {
2082
2103
  let transformedCall;
2083
2104
  if (call.kind === "workflow") {
2084
2105
  let optionsPart = "";
2085
- if (call.optionsText !== void 0) if (authNamespace) {
2086
- optionsPart = `, ${NORMALIZER_IDENTIFIER}(${call.optionsText})`;
2087
- needsNormalizerHelper = true;
2088
- } else optionsPart = `, ${call.optionsText}`;
2106
+ if (call.optionsText !== void 0) {
2107
+ if (authNamespace) {
2108
+ optionsPart = `, ${NORMALIZER_IDENTIFIER}(${call.optionsText})`;
2109
+ needsNormalizerHelper = true;
2110
+ } else optionsPart = `, ${call.optionsText}`;
2111
+ }
2089
2112
  transformedCall = `tailor.workflow.startWorkflow(${JSON.stringify(call.targetName)}, ${call.argsText || "undefined"}${optionsPart})`;
2090
2113
  } else {
2091
2114
  const optionsPart = call.optionsText !== void 0 ? `, ${call.optionsText}` : "";
@@ -2139,11 +2162,14 @@ function createBundleLog(options = {}) {
2139
2162
  }
2140
2163
  function unresolvedImportError(logs, tsconfig) {
2141
2164
  const imports = logs.map(formatUnresolvedImport);
2165
+ const message = imports.length === 1 ? `Could not resolve ${imports[0]}.` : `Could not resolve ${imports.length} imports.`;
2166
+ const details = imports.length === 1 ? void 0 : imports.map((item) => `- ${item}`).join("\n");
2167
+ const suggestion = unresolvedImportSuggestion(logs, tsconfig);
2142
2168
  return createCLIError({
2143
2169
  code: "UNRESOLVED_IMPORT",
2144
- message: imports.length === 1 ? `Could not resolve ${imports[0]}.` : `Could not resolve ${imports.length} imports.`,
2145
- details: imports.length === 1 ? void 0 : imports.map((item) => `- ${item}`).join("\n"),
2146
- suggestion: unresolvedImportSuggestion(logs, tsconfig)
2170
+ message,
2171
+ details,
2172
+ suggestion
2147
2173
  });
2148
2174
  }
2149
2175
  function unresolvedImportSuggestion(logs, tsconfig) {
@@ -2444,19 +2470,22 @@ async function bundleAuthHooks(options) {
2444
2470
  const absoluteConfigPath = path.resolve(configPath);
2445
2471
  const tsconfig = await resolveTSConfigWithFallback(baseDir);
2446
2472
  const functionName = `auth-hook--${authName}--before-login`;
2473
+ const serializedStartContext = serializeStartContext(startContext);
2474
+ const sortedEnvPrefix = JSON.stringify(Object.fromEntries(Object.entries(env).toSorted(([a], [b]) => a.localeCompare(b))));
2475
+ const contextHash = computeBundlerContextHash({
2476
+ sourceFile: absoluteConfigPath,
2477
+ extraContext: serializedStartContext,
2478
+ tsconfig,
2479
+ inlineSourcemap,
2480
+ bundleLogLevel,
2481
+ prefix: sortedEnvPrefix
2482
+ });
2447
2483
  const code = await withCache({
2448
2484
  cache,
2449
2485
  kind: "auth-hook",
2450
2486
  name: functionName,
2451
2487
  sourceFile: absoluteConfigPath,
2452
- contextHash: computeBundlerContextHash({
2453
- sourceFile: absoluteConfigPath,
2454
- extraContext: serializeStartContext(startContext),
2455
- tsconfig,
2456
- inlineSourcemap,
2457
- bundleLogLevel,
2458
- prefix: JSON.stringify(Object.fromEntries(Object.entries(env).toSorted(([a], [b]) => a.localeCompare(b))))
2459
- }),
2488
+ contextHash,
2460
2489
  async build(cachePlugins, trackDependency) {
2461
2490
  const entryContent = multiline`
2462
2491
  import _config from "${absoluteConfigPath}";
@@ -2658,17 +2687,20 @@ function formatScriptContext(kind, context) {
2658
2687
  const convertToScriptExpr = (fn, kind, context) => {
2659
2688
  const precompiledExpr = getPrecompiledScriptExpr(fn);
2660
2689
  if (precompiledExpr) return precompiledExpr;
2661
- return assertParsableExpression(`(${stringifyFunction(fn)})(${kind === "validate" ? `{ value: _value }` : kind === "hooks.create" ? `{ input: _value, invoker: ${PRINCIPAL_VAR}, now: _now }` : `{ input: _value, oldValue: _oldValue, invoker: ${PRINCIPAL_VAR}, now: _now }`})`, formatScriptContext(kind, context));
2690
+ const normalized = stringifyFunction(fn);
2691
+ return assertParsableExpression(`(${normalized})(${kind === "validate" ? `{ value: _value }` : kind === "hooks.create" ? `{ input: _value, invoker: ${PRINCIPAL_VAR}, now: _now }` : `{ input: _value, oldValue: _oldValue, invoker: ${PRINCIPAL_VAR}, now: _now }`})`, formatScriptContext(kind, context));
2662
2692
  };
2663
2693
  const convertTypeHookToExpr = (fn) => {
2664
2694
  const precompiledExpr = getPrecompiledScriptExpr(fn);
2665
2695
  if (precompiledExpr) return precompiledExpr;
2666
- return assertParsableExpression(`(${stringifyFunction(fn)})({ input: _input, oldRecord: _oldRecord, invoker: ${PRINCIPAL_VAR}, now: _now })`, "type-hook");
2696
+ const normalized = stringifyFunction(fn);
2697
+ return assertParsableExpression(`(${normalized})({ input: _input, oldRecord: _oldRecord, invoker: ${PRINCIPAL_VAR}, now: _now })`, "type-hook");
2667
2698
  };
2668
2699
  const convertTypeValidateToExpr = (fn) => {
2669
2700
  const precompiledExpr = getPrecompiledScriptExpr(fn);
2670
2701
  if (precompiledExpr) return precompiledExpr;
2671
- return assertParsableExpression(`(${stringifyFunction(fn)})({ newRecord: _newRecord, oldRecord: _oldRecord, invoker: ${PRINCIPAL_VAR} }, __issues)`, "type-validate");
2702
+ const normalized = stringifyFunction(fn);
2703
+ return assertParsableExpression(`(${normalized})({ newRecord: _newRecord, oldRecord: _oldRecord, invoker: ${PRINCIPAL_VAR} }, __issues)`, "type-validate");
2672
2704
  };
2673
2705
  /**
2674
2706
  * Parse TailorDBField into OperatorFieldConfig.
@@ -2681,8 +2713,8 @@ function parseFieldConfig(field, context) {
2681
2713
  const metadata = field.metadata;
2682
2714
  const fieldType = field.type;
2683
2715
  const rawRelation = field.rawRelation;
2684
- if (context && context.fieldPath.length > 1 && metadata.default !== void 0) throw new Error(`Field "${context.fieldPath.join(".")}" on type "${context.typeName}": .default() cannot be used on nested inner fields`);
2685
- if (context && context.fieldPath.length > 1 && metadata.hooks) throw new Error(`Field "${context.fieldPath.join(".")}" on type "${context.typeName}": .hooks() cannot be used on nested inner fields`);
2716
+ if (context && context.fieldPath.length > 1 && metadata.default !== void 0) throw new Error(`Field "${context.fieldPath.join(".")}" on table "${context.typeName}": .default() cannot be used on nested inner fields`);
2717
+ if (context && context.fieldPath.length > 1 && metadata.hooks) throw new Error(`Field "${context.fieldPath.join(".")}" on table "${context.typeName}": .hooks() cannot be used on nested inner fields`);
2686
2718
  const nestedFields = field.fields;
2687
2719
  return {
2688
2720
  type: fieldType,
@@ -2743,7 +2775,7 @@ function isSingleArrayConditionFormat(cond) {
2743
2775
  }
2744
2776
  /**
2745
2777
  * Normalize record-level permissions into a standard structure.
2746
- * @param permission - Tailor type permission
2778
+ * @param permission - Tailor table permission
2747
2779
  * @returns Normalized record permissions
2748
2780
  */
2749
2781
  function normalizePermission(permission) {
@@ -2845,8 +2877,8 @@ function findOmittedPermitRules(rawPermissions) {
2845
2877
  return locations;
2846
2878
  }
2847
2879
  /**
2848
- * Check whether GraphQL exposure is fully disabled for a type, given its
2849
- * effective gqlOperations (the type's own setting, falling back to the
2880
+ * Check whether GraphQL exposure is fully disabled for a table, given its
2881
+ * effective gqlOperations (the table's own setting, falling back to the
2850
2882
  * TailorDB namespace default). `undefined` means the default of all
2851
2883
  * operations enabled, so it is never considered fully disabled.
2852
2884
  * @param gqlOperations - Effective, normalized gqlOperations configuration
@@ -2857,15 +2889,15 @@ function isGqlOperationsFullyDisabled(gqlOperations) {
2857
2889
  return gqlOperations.create === false && gqlOperations.update === false && gqlOperations.delete === false && gqlOperations.read === false;
2858
2890
  }
2859
2891
  /**
2860
- * Find missing permission configuration for a TailorDB type.
2892
+ * Find missing permission configuration for a TailorDB table.
2861
2893
  *
2862
2894
  * Record-level permission is always required: TailorDB denies all record
2863
- * operations for a type without it, regardless of whether the type is
2895
+ * operations for a table without it, regardless of whether the table is
2864
2896
  * exposed via GraphQL. GraphQL permission is required whenever GraphQL
2865
- * exposure is enabled for the type (the default, unless every operation is
2897
+ * exposure is enabled for the table (the default, unless every operation is
2866
2898
  * explicitly disabled via `gqlOperations`).
2867
- * @param rawPermissions - Raw permissions definition for the type
2868
- * @param effectiveGqlOperations - The type's own gqlOperations, falling back to the namespace default
2899
+ * @param rawPermissions - Raw permissions definition for the table
2900
+ * @param effectiveGqlOperations - The table's own gqlOperations, falling back to the namespace default
2869
2901
  * @returns Which permission configuration, if any, is missing
2870
2902
  */
2871
2903
  function findMissingPermissionConfig(rawPermissions, effectiveGqlOperations) {
@@ -2878,12 +2910,12 @@ function findMissingPermissionConfig(rawPermissions, effectiveGqlOperations) {
2878
2910
  //#endregion
2879
2911
  //#region src/parser/service/tailordb/type-parser.ts
2880
2912
  /**
2881
- * Parse multiple TailorDB types, build relationships, and validate uniqueness.
2882
- * This is the main entry point for parsing TailorDB types.
2883
- * @param rawTypes - Raw TailorDB types keyed by name
2913
+ * Parse multiple TailorDB tables, build relationships, and validate uniqueness.
2914
+ * This is the main entry point for parsing TailorDB tables.
2915
+ * @param rawTypes - Raw TailorDB tables keyed by name
2884
2916
  * @param namespace - TailorDB namespace name
2885
- * @param typeSourceInfo - Optional type source information
2886
- * @returns Parsed types
2917
+ * @param typeSourceInfo - Optional table source information
2918
+ * @returns Parsed tables
2887
2919
  */
2888
2920
  function parseTypes(rawTypes, namespace, typeSourceInfo) {
2889
2921
  const types = createRecord();
@@ -2895,11 +2927,11 @@ function parseTypes(rawTypes, namespace, typeSourceInfo) {
2895
2927
  }
2896
2928
  /**
2897
2929
  * Parse a TailorDBTypeSchemaOutput into a TailorDBType.
2898
- * @param type - TailorDB type to parse
2899
- * @param allTypeNames - Set of all TailorDB type names
2900
- * @param rawTypes - All raw TailorDB types keyed by name
2901
- * @param typeSourceInfo - Optional type source information
2902
- * @returns Parsed TailorDB type
2930
+ * @param type - TailorDB table to parse
2931
+ * @param allTypeNames - Set of all TailorDB table names
2932
+ * @param rawTypes - All raw TailorDB tables keyed by name
2933
+ * @param typeSourceInfo - Optional table source information
2934
+ * @returns Parsed TailorDB table
2903
2935
  */
2904
2936
  function parseTailorDBType(type, allTypeNames, rawTypes, typeSourceInfo) {
2905
2937
  const metadata = type.metadata;
@@ -2924,12 +2956,12 @@ function parseTailorDBType(type, allTypeNames, rawTypes, typeSourceInfo) {
2924
2956
  "n-1",
2925
2957
  "manyToOne",
2926
2958
  "N-1"
2927
- ].includes(rawRelation.type) && fieldConfig.unique) throw new Error(`Field "${fieldName}" on type "${type.name}": cannot set unique on n-1 (manyToOne) relation. Use 1-1 (oneToOne) relation instead, or remove the unique constraint.`);
2959
+ ].includes(rawRelation.type) && fieldConfig.unique) throw new Error(`Field "${fieldName}" on table "${type.name}": cannot set unique on n-1 (manyToOne) relation. Use 1-1 (oneToOne) relation instead, or remove the unique constraint.`);
2928
2960
  const relationMetadata = processRelationMetadata(rawRelation, context, fieldConfig.array);
2929
2961
  fieldConfig = applyRelationMetadataToFieldConfig(fieldConfig, relationMetadata);
2930
2962
  }
2931
- if (fieldConfig.array && fieldConfig.index) throw new Error(`Field "${fieldName}" on type "${type.name}": index cannot be set on array fields`);
2932
- if (fieldConfig.array && fieldConfig.unique) throw new Error(`Field "${fieldName}" on type "${type.name}": unique cannot be set on array fields`);
2963
+ if (fieldConfig.array && fieldConfig.index) throw new Error(`Field "${fieldName}" on table "${type.name}": index cannot be set on array fields`);
2964
+ if (fieldConfig.array && fieldConfig.unique) throw new Error(`Field "${fieldName}" on table "${type.name}": unique cannot be set on array fields`);
2933
2965
  const parsedField = {
2934
2966
  name: fieldName,
2935
2967
  config: fieldConfig
@@ -2938,14 +2970,14 @@ function parseTailorDBType(type, allTypeNames, rawTypes, typeSourceInfo) {
2938
2970
  if (relationInfo) {
2939
2971
  parsedField.relation = { ...relationInfo };
2940
2972
  const forwardName = relationInfo.forwardName;
2941
- if (forwardName.length === 0) throw new Error(`Forward relation name for field "${fieldName}" on type "${type.name}"${typeLocation} cannot be empty. Use the "as" option in .relation({ toward: { as: ... } }) to specify a non-empty name.`);
2973
+ if (forwardName.length === 0) throw new Error(`Forward relation name for field "${fieldName}" on table "${type.name}"${typeLocation} cannot be empty. Use the "as" option in .relation({ toward: { as: ... } }) to specify a non-empty name.`);
2942
2974
  const existingForward = forwardRelationships[forwardName];
2943
- if (existingForward) throw new Error(`Forward relation name "${forwardName}" on type "${type.name}"${typeLocation} is duplicated between fields "${existingForward.targetField}" and "${fieldName}". Use the "as" option in .relation({ toward: { as: ... } }) to specify a unique name.`);
2975
+ if (existingForward) throw new Error(`Forward relation name "${forwardName}" on table "${type.name}"${typeLocation} is duplicated between fields "${existingForward.targetField}" and "${fieldName}". Use the "as" option in .relation({ toward: { as: ... } }) to specify a unique name.`);
2944
2976
  if (Object.hasOwn(type.fields, forwardName)) {
2945
- const message = forwardName === fieldName ? `Forward relation name "${forwardName}" on type "${type.name}"${typeLocation} is the same as its own relation field "${fieldName}". Use the "as" option in .relation({ toward: { as: ... } }) to specify a different name.` : `Forward relation name "${forwardName}" from field "${fieldName}" on type "${type.name}"${typeLocation} conflicts with existing field "${forwardName}". Use the "as" option in .relation({ toward: { as: ... } }) to specify a different name.`;
2977
+ const message = forwardName === fieldName ? `Forward relation name "${forwardName}" on table "${type.name}"${typeLocation} is the same as its own relation field "${fieldName}". Use the "as" option in .relation({ toward: { as: ... } }) to specify a different name.` : `Forward relation name "${forwardName}" from field "${fieldName}" on table "${type.name}"${typeLocation} conflicts with existing field "${forwardName}". Use the "as" option in .relation({ toward: { as: ... } }) to specify a different name.`;
2946
2978
  throw new Error(message);
2947
2979
  }
2948
- if (Object.hasOwn(metadata.files, forwardName)) throw new Error(`Forward relation name "${forwardName}" from field "${fieldName}" on type "${type.name}"${typeLocation} conflicts with files field "${forwardName}". Use the "as" option in .relation({ toward: { as: ... } }) to specify a different name.`);
2980
+ if (Object.hasOwn(metadata.files, forwardName)) throw new Error(`Forward relation name "${forwardName}" from field "${fieldName}" on table "${type.name}"${typeLocation} conflicts with files field "${forwardName}". Use the "as" option in .relation({ toward: { as: ... } }) to specify a different name.`);
2949
2981
  const targetType = rawTypes[relationInfo.targetType];
2950
2982
  forwardRelationships[forwardName] = {
2951
2983
  name: forwardName,
@@ -2977,11 +3009,11 @@ function parseTailorDBType(type, allTypeNames, rawTypes, typeSourceInfo) {
2977
3009
  };
2978
3010
  }
2979
3011
  /**
2980
- * Build backward relationships between parsed types.
2981
- * Also validates that backward relation names are unique within each type.
2982
- * @param types - Parsed types
3012
+ * Build backward relationships between parsed tables.
3013
+ * Also validates that backward relation names are unique within each table.
3014
+ * @param types - Parsed tables
2983
3015
  * @param namespace - TailorDB namespace name
2984
- * @param typeSourceInfo - Optional type source information
3016
+ * @param typeSourceInfo - Optional table source information
2985
3017
  */
2986
3018
  function buildBackwardRelationships(types, namespace, typeSourceInfo) {
2987
3019
  const backwardNameSources = Object.create(null);
@@ -3021,25 +3053,25 @@ function buildBackwardRelationships(types, namespace, typeSourceInfo) {
3021
3053
  const location = formatTypeSourceLocation(getTypeSourceInfo(typeSourceInfo, s.sourceType));
3022
3054
  return `${s.sourceType}.${s.fieldName}${location}`;
3023
3055
  }).join(", ");
3024
- errors.push(`Backward relation name "${backwardName}" on type "${targetTypeName}" is duplicated from: ${sourceList}. Use the "backward" option in .relation() to specify unique names.`);
3056
+ errors.push(`Backward relation name "${backwardName}" on table "${targetTypeName}" is duplicated from: ${sourceList}. Use the "backward" option in .relation() to specify unique names.`);
3025
3057
  }
3026
3058
  if (Object.hasOwn(targetType.fields, backwardName)) {
3027
3059
  const source = sources[0];
3028
3060
  if (source === void 0) throw new Error(`no source found for backward name: ${backwardName}`);
3029
3061
  const sourceLocation = formatTypeSourceLocation(getTypeSourceInfo(typeSourceInfo, source.sourceType));
3030
- errors.push(`Backward relation name "${backwardName}" from ${source.sourceType}.${source.fieldName}${sourceLocation} conflicts with existing field "${backwardName}" on type "${targetTypeName}"${targetLocation}. Use the "backward" option in .relation() to specify a different name.`);
3062
+ errors.push(`Backward relation name "${backwardName}" from ${source.sourceType}.${source.fieldName}${sourceLocation} conflicts with existing field "${backwardName}" on table "${targetTypeName}"${targetLocation}. Use the "backward" option in .relation() to specify a different name.`);
3031
3063
  }
3032
3064
  if (targetType.files && Object.hasOwn(targetType.files, backwardName)) {
3033
3065
  const source = sources[0];
3034
3066
  if (source === void 0) throw new Error(`no source found for backward name: ${backwardName}`);
3035
3067
  const sourceLocation = formatTypeSourceLocation(getTypeSourceInfo(typeSourceInfo, source.sourceType));
3036
- errors.push(`Backward relation name "${backwardName}" from ${source.sourceType}.${source.fieldName}${sourceLocation} conflicts with files field "${backwardName}" on type "${targetTypeName}"${targetLocation}. Use the "backward" option in .relation() to specify a different name.`);
3068
+ errors.push(`Backward relation name "${backwardName}" from ${source.sourceType}.${source.fieldName}${sourceLocation} conflicts with files field "${backwardName}" on table "${targetTypeName}"${targetLocation}. Use the "backward" option in .relation() to specify a different name.`);
3037
3069
  }
3038
3070
  if (Object.hasOwn(targetType.forwardRelationships, backwardName)) {
3039
3071
  const source = sources[0];
3040
3072
  if (source === void 0) throw new Error(`no source found for backward name: ${backwardName}`);
3041
3073
  const sourceLocation = formatTypeSourceLocation(getTypeSourceInfo(typeSourceInfo, source.sourceType));
3042
- errors.push(`Relation name "${backwardName}" on type "${targetTypeName}"${targetLocation} is used by both a forward relationship and a backward relationship from ${source.sourceType}.${source.fieldName}${sourceLocation}. Use the "as" option in .relation({ toward: { as: ... } }) or the "backward" option in .relation() to specify unique names.`);
3074
+ errors.push(`Relation name "${backwardName}" on table "${targetTypeName}"${targetLocation} is used by both a forward relationship and a backward relationship from ${source.sourceType}.${source.fieldName}${sourceLocation}. Use the "as" option in .relation({ toward: { as: ... } }) or the "backward" option in .relation() to specify unique names.`);
3043
3075
  }
3044
3076
  }
3045
3077
  }
@@ -3048,11 +3080,11 @@ function buildBackwardRelationships(types, namespace, typeSourceInfo) {
3048
3080
  /**
3049
3081
  * Validate GraphQL query field name uniqueness.
3050
3082
  * Checks for:
3051
- * 1. Each type's singular query name != plural query name
3052
- * 2. No duplicate query names across all types
3053
- * @param types - Parsed types
3083
+ * 1. Each table's singular query name != plural query name
3084
+ * 2. No duplicate query names across all tables
3085
+ * @param types - Parsed tables
3054
3086
  * @param namespace - TailorDB namespace name
3055
- * @param typeSourceInfo - Optional type source information
3087
+ * @param typeSourceInfo - Optional table source information
3056
3088
  */
3057
3089
  function validatePluralFormUniqueness(types, namespace, typeSourceInfo) {
3058
3090
  const errors = [];
@@ -3060,7 +3092,7 @@ function validatePluralFormUniqueness(types, namespace, typeSourceInfo) {
3060
3092
  const singularQuery = inflection.camelize(parsedType.name, true);
3061
3093
  if (singularQuery === inflection.camelize(parsedType.pluralForm, true)) {
3062
3094
  const location = formatTypeSourceLocation(getTypeSourceInfo(typeSourceInfo, parsedType.name));
3063
- errors.push(`Type "${parsedType.name}"${location} has identical singular and plural query names "${singularQuery}". Use db.table(["${parsedType.name}", "UniquePluralForm"], {...}) to set a unique pluralForm.`);
3095
+ errors.push(`Table "${parsedType.name}"${location} has identical singular and plural query names "${singularQuery}". Use db.table(["${parsedType.name}", "UniquePluralForm"], {...}) to set a unique pluralForm.`);
3064
3096
  }
3065
3097
  }
3066
3098
  const queryNameToSource = /* @__PURE__ */ new Map();
@@ -3134,12 +3166,12 @@ function collectBindingsFromPattern(pattern, bindings) {
3134
3166
  else collectBindingsFromPattern(prop.value, bindings);
3135
3167
  break;
3136
3168
  case "ArrayPattern":
3137
- for (const elem of pattern.elements) if (elem) if (elem.type === "RestElement") collectBindingsFromPattern(elem.argument, bindings);
3138
- else collectBindingsFromPattern(elem, bindings);
3139
- break;
3140
- case "AssignmentPattern":
3141
- collectBindingsFromPattern(pattern.left, bindings);
3169
+ for (const elem of pattern.elements) if (elem) {
3170
+ if (elem.type === "RestElement") collectBindingsFromPattern(elem.argument, bindings);
3171
+ else collectBindingsFromPattern(elem, bindings);
3172
+ }
3142
3173
  break;
3174
+ case "AssignmentPattern": collectBindingsFromPattern(pattern.left, bindings);
3143
3175
  }
3144
3176
  }
3145
3177
  /** Fields that contain TypeScript type annotations (not runtime references). */
@@ -3454,8 +3486,8 @@ async function bundleScriptTarget(args) {
3454
3486
  * Precompile TailorDB hooks/validators into self-contained script expressions using rolldown.
3455
3487
  * Uses oxc-parser AST walking to extract free variables from functions, then builds
3456
3488
  * minimal entry points containing only the needed imports and declarations.
3457
- * @param type - TailorDB type schema output.
3458
- * @param sourceFilePath - Source file where the type is defined.
3489
+ * @param type - TailorDB table schema output.
3490
+ * @param sourceFilePath - Source file where the table is defined.
3459
3491
  * @param tsconfig - Resolved tsconfig path, or undefined if not found.
3460
3492
  */
3461
3493
  async function precompileTailorDBTypeScripts(type, sourceFilePath, tsconfig) {
@@ -3479,8 +3511,8 @@ async function precompileTailorDBTypeScripts(type, sourceFilePath, tsconfig) {
3479
3511
  //#endregion
3480
3512
  //#region src/cli/services/tailordb/type-name-validation.ts
3481
3513
  /**
3482
- * Format a TailorDB type source for validation errors.
3483
- * @param sourceInfo - Source information captured when loading the type
3514
+ * Format a TailorDB table source for validation errors.
3515
+ * @param sourceInfo - Source information captured when loading the table
3484
3516
  * @returns Human-readable source detail
3485
3517
  */
3486
3518
  function formatTailorDBTypeSourceInfo(sourceInfo) {
@@ -3495,9 +3527,9 @@ function formatTailorDBTypeSourceInfo(sourceInfo) {
3495
3527
  return `${sourceInfo.filePath} export ${sourceInfo.exportName}`;
3496
3528
  }
3497
3529
  /**
3498
- * Collect TailorDB type-name sources from loaded local services.
3530
+ * Collect TailorDB table-name sources from loaded local services.
3499
3531
  * @param args - Collection inputs
3500
- * @returns Type-name sources for local services
3532
+ * @returns Table-name sources for local services
3501
3533
  */
3502
3534
  function collectLocalTailorDBTypeNameSources(args) {
3503
3535
  const sources = [];
@@ -3510,9 +3542,9 @@ function collectLocalTailorDBTypeNameSources(args) {
3510
3542
  return sources;
3511
3543
  }
3512
3544
  /**
3513
- * Fetch TailorDB type-name sources for external namespaces.
3545
+ * Fetch TailorDB table-name sources for external namespaces.
3514
3546
  * @param args - Fetch inputs
3515
- * @returns Type-name sources for external services
3547
+ * @returns Table-name sources for external services
3516
3548
  */
3517
3549
  async function fetchExternalTailorDBTypeNameSources(args) {
3518
3550
  return (await Promise.all(args.externalTailorDBNamespaces.map(async (namespace) => {
@@ -3540,7 +3572,7 @@ async function fetchExternalTailorDBTypeNameSources(args) {
3540
3572
  }))).flat();
3541
3573
  }
3542
3574
  /**
3543
- * Assert that TailorDB type names are unique across all supplied sources.
3575
+ * Assert that TailorDB table names are unique across all supplied sources.
3544
3576
  * @param args - Validation inputs
3545
3577
  */
3546
3578
  function assertUniqueTailorDBTypeNames(args) {
@@ -3554,20 +3586,20 @@ function assertUniqueTailorDBTypeNames(args) {
3554
3586
  for (const [typeName, sources] of sourcesByTypeName) {
3555
3587
  if (sources.length <= 1) continue;
3556
3588
  const sourceList = sources.map(formatTailorDBTypeNameSource).join(", ");
3557
- errors.push(`Type "${typeName}" is defined more than once: ${sourceList}`);
3589
+ errors.push(`Table "${typeName}" is defined more than once: ${sourceList}`);
3558
3590
  }
3559
- if (errors.length > 0) throw new Error(`Duplicate TailorDB type names detected.
3560
- ${errors.map((error) => ` - ${error}`).join("\n")}\nTailorDB type names must be unique across all TailorDB namespaces in an application.`);
3591
+ if (errors.length > 0) throw new Error(`Duplicate TailorDB table names detected.
3592
+ ${errors.map((error) => ` - ${error}`).join("\n")}\nTailorDB table names must be unique across all TailorDB namespaces in an application.`);
3561
3593
  }
3562
3594
  /**
3563
- * Assert local TailorDB type names are unique.
3595
+ * Assert local TailorDB table names are unique.
3564
3596
  * @param args - Validation inputs
3565
3597
  */
3566
3598
  function assertUniqueLocalTailorDBTypeNames(args) {
3567
3599
  assertUniqueTailorDBTypeNames({ sources: collectLocalTailorDBTypeNameSources(args) });
3568
3600
  }
3569
3601
  /**
3570
- * Assert TailorDB type names are unique across local and external namespaces.
3602
+ * Assert TailorDB table names are unique across local and external namespaces.
3571
3603
  * @param args - Validation inputs
3572
3604
  */
3573
3605
  async function assertUniqueTailorDBTypeNamesWithExternal(args) {
@@ -3615,7 +3647,7 @@ function createTailorDBService(params) {
3615
3647
  if (existingSourceInfo) {
3616
3648
  const firstSource = formatTailorDBTypeSourceInfo(existingSourceInfo) ?? "unknown source";
3617
3649
  const secondSource = formatTailorDBTypeSourceInfo(sourceInfo) ?? "unknown source";
3618
- throw new Error(`Duplicate TailorDB type name "${typeName}" detected in TailorDB service "${namespace}". First: ${firstSource}. Second: ${secondSource}. TailorDB type names must be unique across all TailorDB files in a service.`);
3650
+ throw new Error(`Duplicate TailorDB table name "${typeName}" detected in TailorDB service "${namespace}". First: ${firstSource}. Second: ${secondSource}. TailorDB table names must be unique across all TailorDB files in a service.`);
3619
3651
  }
3620
3652
  assertDefined(rawTypes[rawTypesKey], `raw types entry missing for key: ${rawTypesKey}`)[typeName] = type;
3621
3653
  typeSourceInfo[typeName] = sourceInfo;
@@ -3628,7 +3660,7 @@ function createTailorDBService(params) {
3628
3660
  const warnOmittedPermit = () => {
3629
3661
  for (const fileTypes of Object.values(rawTypes)) for (const [typeName, type] of Object.entries(fileTypes)) {
3630
3662
  const locations = findOmittedPermitRules(type.metadata.permissions);
3631
- if (locations.length > 0) logger.warn(`TailorDB type "${typeName}" has permission rule(s) ${locations.join(", ")} in object form without an explicit "permit"; they default to "deny". Set permit: true (allow) or permit: false (deny) to silence this warning.`);
3663
+ if (locations.length > 0) logger.warn(`TailorDB table "${typeName}" has permission rule(s) ${locations.join(", ")} in object form without an explicit "permit"; they default to "deny". Set permit: true (allow) or permit: false (deny) to silence this warning.`);
3632
3664
  }
3633
3665
  };
3634
3666
  const validateRequiredPermissions = () => {
@@ -3639,16 +3671,16 @@ function createTailorDBService(params) {
3639
3671
  if (!missingPermission && !missingGqlPermission) continue;
3640
3672
  const source = formatTailorDBTypeSourceInfo(typeSourceInfo[typeName]);
3641
3673
  const location = source ? ` (${source})` : "";
3642
- if (missingPermission) errors.push(`TailorDB type "${typeName}"${location} has no .permission() configured. TailorDB denies all record operations for types without permission; call .permission(...) to grant access explicitly.`);
3643
- if (missingGqlPermission) errors.push(`TailorDB type "${typeName}"${location} has no .gqlPermission() configured, but GraphQL operations are enabled for it. Call .gqlPermission(...) to grant GraphQL access explicitly, or disable GraphQL exposure with .features({ gqlOperations: { create: false, update: false, delete: false, read: false } }).`);
3674
+ if (missingPermission) errors.push(`TailorDB table "${typeName}"${location} has no .permission() configured. TailorDB denies all record operations for tables without permission; call .permission(...) to grant access explicitly.`);
3675
+ if (missingGqlPermission) errors.push(`TailorDB table "${typeName}"${location} has no .gqlPermission() configured, but GraphQL operations are enabled for it. Call .gqlPermission(...) to grant GraphQL access explicitly, or disable GraphQL exposure with .features({ gqlOperations: { create: false, update: false, delete: false, read: false } }).`);
3644
3676
  }
3645
3677
  if (errors.length > 0) throw new Error(`TailorDB permission configuration errors in service "${namespace}":\n${errors.map((e) => ` - ${e}`).join("\n")}`);
3646
3678
  };
3647
3679
  /**
3648
- * Process plugins for a type and add generated types to rawTypes
3649
- * @param rawType - The raw TailorDB type being processed
3650
- * @param attachments - Plugin attachments for this type
3651
- * @param sourceFilePath - The file path where the type was loaded from
3680
+ * Process plugins for a table and add generated tables to rawTypes
3681
+ * @param rawType - The raw TailorDB table being processed
3682
+ * @param attachments - Plugin attachments for this table
3683
+ * @param sourceFilePath - The file path where the table was loaded from
3652
3684
  */
3653
3685
  const processPluginsForType = async (rawType, attachments, sourceFilePath) => {
3654
3686
  if (!pluginManager) return;
@@ -3703,7 +3735,7 @@ function createTailorDBService(params) {
3703
3735
  }
3704
3736
  } catch (error) {
3705
3737
  const relativePath = path.relative(process.cwd(), typeFile);
3706
- logger.error(`Failed to load type from ${styles.bold(relativePath)}`);
3738
+ logger.error(`Failed to load table from ${styles.bold(relativePath)}`);
3707
3739
  logger.error(String(error));
3708
3740
  throw error;
3709
3741
  }
@@ -3727,7 +3759,7 @@ function createTailorDBService(params) {
3727
3759
  const typeFiles = [...new Set(loadFilesWithIgnores(config, baseDir))];
3728
3760
  const tsconfig = await resolveTSConfigWithFallback(baseDir);
3729
3761
  logger.newline();
3730
- logger.log(`Found ${styles.highlight(typeFiles.length.toString())} type files for TailorDB service ${styles.highlight(`"${namespace}"`)}`);
3762
+ logger.log(`Found ${styles.highlight(typeFiles.length.toString())} table files for TailorDB service ${styles.highlight(`"${namespace}"`)}`);
3731
3763
  if (pluginManager) for (const typeFile of typeFiles) await loadTypeFile(typeFile, tsconfig);
3732
3764
  else await Promise.all(typeFiles.map((typeFile) => loadTypeFile(typeFile, tsconfig)));
3733
3765
  doParseTypes();
@@ -4062,7 +4094,7 @@ function buildResolverPermissionGuardExpr(permission) {
4062
4094
  }
4063
4095
  /**
4064
4096
  * Build the permission guard and input-validation statements shared by every
4065
- * resolver entry wrapper (production bundling and `function test-run`).
4097
+ * resolver entry wrapper (production bundling and `function run`).
4066
4098
  *
4067
4099
  * Kept as a single generator so a resolver-wrapping behavior (like the
4068
4100
  * permission guard) can't be added to one entry-point template and forgotten
@@ -4236,8 +4268,8 @@ const HttpAdapterConfigSchema = z.strictObject({
4236
4268
 
4237
4269
  //#endregion
4238
4270
  //#region src/cli/services/http-adapter/bundler.ts
4239
- const ADAPTER_BUNDLE_WARN_BYTES = 64 * 1024;
4240
- const ADAPTER_BUNDLE_ERROR_BYTES = 256 * 1024;
4271
+ const ADAPTER_BUNDLE_WARN_BYTES = 65536;
4272
+ const ADAPTER_BUNDLE_ERROR_BYTES = 262144;
4241
4273
  const GRAPHQL_WEB_MODULE = createRequire(import.meta.url).resolve("@0no-co/graphql.web");
4242
4274
  /**
4243
4275
  * Bundle each adapter's `input` (and `output`, if present) into a standalone
@@ -4258,12 +4290,13 @@ async function bundleHttpAdapters(adapters, baseDir, cache, bundleLogLevel = "DE
4258
4290
  logger.newline();
4259
4291
  logger.log(`Bundling ${styles.highlight(adapters.length.toString())} files for ${styles.info("\"http-adapter\"")}`);
4260
4292
  const tsconfig = await resolveTSConfigWithFallback(baseDir);
4261
- const results = await withBundleConcurrency(adapters.flatMap((adapter) => {
4293
+ const tasks = adapters.flatMap((adapter) => {
4262
4294
  return (adapter.hasOutput ? ["input", "output"] : ["input"]).map((kind) => ({
4263
4295
  adapter,
4264
4296
  kind
4265
4297
  }));
4266
- }), ({ adapter, kind }) => bundleAdapterScript(adapter, kind, tsconfig, cache, bundleLogLevel, tsconfigCache));
4298
+ });
4299
+ const results = await withBundleConcurrency(tasks, ({ adapter, kind }) => bundleAdapterScript(adapter, kind, tsconfig, cache, bundleLogLevel, tsconfigCache));
4267
4300
  const bundledInputs = /* @__PURE__ */ new Map();
4268
4301
  const bundledOutputs = /* @__PURE__ */ new Map();
4269
4302
  for (const [name, kind, code] of results) if (kind === "input") bundledInputs.set(name, code);
@@ -4638,16 +4671,17 @@ async function bundleSingleResolver(options) {
4638
4671
  contextHash,
4639
4672
  async build(cachePlugins, trackDependency) {
4640
4673
  const absoluteSourcePath = path.resolve(resolver.sourceFile);
4674
+ const guardAndInputCheckExpr = buildResolverPermissionAndInputCheckExpr({
4675
+ permission: resolver.permission,
4676
+ defaultPermission
4677
+ });
4641
4678
  const entryContent = multiline`
4642
4679
  import _internalResolver from "${absoluteSourcePath}";
4643
4680
  import { t } from "@tailor-platform/sdk";
4644
4681
 
4645
4682
  const $tailor_resolver_body = async (context) => {
4646
4683
  const invoker = ${INVOKER_EXPR};
4647
- ${buildResolverPermissionAndInputCheckExpr({
4648
- permission: resolver.permission,
4649
- defaultPermission
4650
- })}
4684
+ ${guardAndInputCheckExpr}
4651
4685
  return _internalResolver.body({ ...context, invoker });
4652
4686
  };
4653
4687
 
@@ -4702,7 +4736,7 @@ function parseResolverDefaultPermission(params) {
4702
4736
  /**
4703
4737
  * Find the `defaultPermission` of the resolver namespace a file belongs to.
4704
4738
  *
4705
- * `function test-run` receives a single file rather than a namespace, so the
4739
+ * `function run` receives a single file rather than a namespace, so the
4706
4740
  * namespace is recovered by matching the file against each namespace's own
4707
4741
  * patterns — otherwise a test run would skip a guard the deployed resolver has.
4708
4742
  *
@@ -5328,6 +5362,16 @@ async function loadFileContent(filePath) {
5328
5362
  function getApplicationAuthNamespace(application) {
5329
5363
  return application.authService?.config.name ?? application.config?.auth?.name;
5330
5364
  }
5365
+ /**
5366
+ * Resolve the auth namespace configured for an application, throwing when none is configured.
5367
+ * @param application - Loaded application with local or external Auth config
5368
+ * @returns Auth namespace
5369
+ */
5370
+ function requireApplicationAuthNamespace(application) {
5371
+ const authNamespace = getApplicationAuthNamespace(application);
5372
+ if (!authNamespace) throw new Error("No Auth service configured");
5373
+ return authNamespace;
5374
+ }
5331
5375
 
5332
5376
  //#endregion
5333
5377
  //#region src/cli/shared/inline-sourcemap.ts
@@ -5360,7 +5404,7 @@ const NAME_PATTERN = /^[a-z0-9][a-z0-9-]{1,28}[a-z0-9]$/;
5360
5404
  const AUTH_NAMESPACE_PATTERN = /^[a-z0-9][a-z0-9-]{1,61}[a-z0-9]$/;
5361
5405
  const AIGatewaySchema = z.strictObject({
5362
5406
  name: z.string().regex(NAME_PATTERN, "Must be 3-30 lowercase alphanumeric characters or hyphens").describe("AI Gateway name"),
5363
- authNamespace: z.string().regex(AUTH_NAMESPACE_PATTERN, "Must be 3-63 lowercase alphanumeric characters or hyphens").describe("Auth namespace used to resolve request tokens against the workspace's auth"),
5407
+ authNamespace: z.string().regex(AUTH_NAMESPACE_PATTERN, "Must be 3-63 lowercase alphanumeric characters or hyphens").optional().describe("Auth namespace used to resolve request tokens against the workspace's auth. Defaults to the application's own auth service when omitted; omitting it without an Auth service configured is rejected."),
5364
5408
  cors: z.array(z.string()).optional().describe("Allowed CORS origins for browser-based clients. Each entry is `*`, `http(s)://*`, `http(s)://*.example.com`, or `http(s)://app.example.com`, optionally with `:port`. Empty list disables cross-origin access.")
5365
5409
  }).brand("AIGatewayConfig");
5366
5410
 
@@ -5632,9 +5676,10 @@ function defineTailorDB(config, baseDir, pluginManager) {
5632
5676
  for (const [namespace, serviceConfig] of Object.entries(config)) {
5633
5677
  if ("external" in serviceConfig) externalTailorDBNamespaces.push(namespace);
5634
5678
  else {
5679
+ const parsedConfig = TailorDBServiceConfigSchema.parse(serviceConfig);
5635
5680
  const tailorDB = createTailorDBService({
5636
5681
  namespace,
5637
- config: TailorDBServiceConfigSchema.parse(serviceConfig),
5682
+ config: parsedConfig,
5638
5683
  pluginManager,
5639
5684
  baseDir
5640
5685
  });
@@ -5760,13 +5805,17 @@ function defineStaticWebsites(websites) {
5760
5805
  });
5761
5806
  return staticWebsiteServices;
5762
5807
  }
5763
- function defineAIGateways(gateways) {
5808
+ function defineAIGateways(gateways, applicationAuthNamespace) {
5764
5809
  const aiGatewayServices = [];
5765
5810
  const gatewayNames = /* @__PURE__ */ new Set();
5766
5811
  (gateways ?? []).forEach((config) => {
5767
5812
  const gateway = AIGatewaySchema.parse(config);
5768
5813
  if (gatewayNames.has(gateway.name)) throw new Error(`AI Gateway with name "${gateway.name}" already defined.`);
5769
5814
  gatewayNames.add(gateway.name);
5815
+ if (gateway.authNamespace === void 0) {
5816
+ if (!applicationAuthNamespace) throw new Error(`AI Gateway "${gateway.name}" has no "authNamespace" and no Auth service is configured to default to. Define an Auth service, or set "authNamespace" explicitly.`);
5817
+ gateway.authNamespace = applicationAuthNamespace;
5818
+ }
5770
5819
  aiGatewayServices.push(gateway);
5771
5820
  });
5772
5821
  return aiGatewayServices;
@@ -5799,7 +5848,10 @@ function defineServices(config, baseDir, pluginManager) {
5799
5848
  const idpResult = defineIdp(config.idp);
5800
5849
  const authResult = defineAuth(config.auth, tailordbResult.tailorDBServices, tailordbResult.externalTailorDBNamespaces);
5801
5850
  const staticWebsiteServices = defineStaticWebsites(config.staticWebsites);
5802
- const aiGatewayServices = defineAIGateways(config.aiGateways);
5851
+ const aiGatewayServices = defineAIGateways(config.aiGateways, getApplicationAuthNamespace({
5852
+ authService: authResult.authService,
5853
+ config
5854
+ }));
5803
5855
  const { secrets, ignoreNullishValues } = parseSecretManager(config.secrets);
5804
5856
  return {
5805
5857
  tailordbResult,
@@ -5867,9 +5919,9 @@ function defineApplication(params) {
5867
5919
  }
5868
5920
  /**
5869
5921
  * Generate plugin type and executor files if a plugin manager is provided.
5870
- * Collects source type info from TailorDB services and delegates to PluginManager.
5922
+ * Collects source table info from TailorDB services and delegates to PluginManager.
5871
5923
  * @param pluginManager - Plugin manager instance (skips if undefined)
5872
- * @param tailorDBServices - TailorDB services to collect type source info from
5924
+ * @param tailorDBServices - TailorDB services to collect table source info from
5873
5925
  * @param configPath - Path to tailor.config.ts for resolving plugin imports
5874
5926
  * @returns Generated executor file paths
5875
5927
  */
@@ -6015,5 +6067,5 @@ async function loadApplication(params) {
6015
6067
  }
6016
6068
 
6017
6069
  //#endregion
6018
- export { resolveStaticWebsiteUrls as $, hasGenerationHooks as A, fetchPaged as B, resolveTSConfigWithFallback as C, resolveBundleLogLevel as D, createLogLevelTreeshakeOptions as E, closeConnectionPool as F, getOrNull as G, fetchUserInfo as H, defaultPlatformBaseUrl as I, initOperatorClient as J, getPlatformBaseUrl as K, fetchAll as L, getDistDir as M, hashContent as N, createBundleLog as O, hashFile as P, rememberPlatformConfigForToken as Q, fetchAllTolerant as R, createTsconfigPathsPlugin as S, composeFunctionTreeshakeOptions as T, getConsoleBaseUrl as U, fetchPlatformMachineUserToken as V, getOAuth2ClientId as W, isNotFoundError as X, isDefaultPlatform as Y, normalizeBaseUrl as Z, assertUniqueTailorDBTypeNamesWithExternal as _, resolveInlineSourcemap as a, tailorPrincipalMap as b, WorkflowJobSchema as c, HTTP_METHODS as d, byName as et, INVOKER_EXPR as f, assertUniqueLocalTailorDBTypeNames as g, buildResolverPermissionAndInputCheckExpr as h, resolverBundleKey as i, createBundleCache as j, getPluginGenerationDependencies as k, resolveResolverDefaultPermissionForFile as l, buildResolverOperationHookExpr as m, generatePluginFilesIfNeeded as n, LOG_LEVELS as nt, getApplicationAuthNamespace as o, buildExecutorArgsExpr as p, initOAuth2Client as q, loadApplication as r, WorkflowJobFunctionExecutionPolicySchema as s, defineApplication as t, createApplyLimiter as tt, ResolverSchema as u, PRINCIPAL_VAR as v, platformBundleDefinePlugin as w, createGeneratedEntryResolverPlugin as x, stringifyFunction as y, fetchMachineUserToken as z };
6019
- //# sourceMappingURL=application-F-nl107y.mjs.map
6070
+ export { rememberPlatformConfigForToken as $, getPluginGenerationDependencies as A, fetchMachineUserToken as B, createTsconfigPathsPlugin as C, createLogLevelTreeshakeOptions as D, composeFunctionTreeshakeOptions as E, hashFile as F, getOAuth2ClientId as G, fetchPlatformMachineUserToken as H, closeConnectionPool as I, initOAuth2Client as J, getOrNull as K, defaultPlatformBaseUrl as L, createBundleCache as M, getDistDir as N, resolveBundleLogLevel as O, hashContent as P, normalizeBaseUrl as Q, fetchAll as R, createGeneratedEntryResolverPlugin as S, platformBundleDefinePlugin as T, fetchUserInfo as U, fetchPaged as V, getConsoleBaseUrl as W, isDefaultPlatform as X, initOperatorClient as Y, isNotFoundError as Z, assertUniqueLocalTailorDBTypeNames as _, resolveInlineSourcemap as a, stringifyFunction as b, WorkflowJobFunctionExecutionPolicySchema as c, ResolverSchema as d, resolveStaticWebsiteUrls as et, HTTP_METHODS as f, buildResolverPermissionAndInputCheckExpr as g, buildResolverOperationHookExpr as h, resolverBundleKey as i, hasGenerationHooks as j, createBundleLog as k, WorkflowJobSchema as l, buildExecutorArgsExpr as m, generatePluginFilesIfNeeded as n, createApplyLimiter as nt, getApplicationAuthNamespace as o, INVOKER_EXPR as p, getPlatformBaseUrl as q, loadApplication as r, LOG_LEVELS as rt, requireApplicationAuthNamespace as s, defineApplication as t, byName as tt, resolveResolverDefaultPermissionForFile as u, assertUniqueTailorDBTypeNamesWithExternal as v, resolveTSConfigWithFallback as w, tailorPrincipalMap as x, PRINCIPAL_VAR as y, fetchAllTolerant as z };
6071
+ //# sourceMappingURL=application-C8a0UJ-z.mjs.map