@tailor-platform/sdk 2.0.0-next.3 → 2.0.0-next.4

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 (118) hide show
  1. package/CHANGELOG.md +45 -0
  2. package/dist/aigateway-DR4Kwuik.mjs +9 -0
  3. package/dist/{aigateway-B3oZZE6v.mjs.map → aigateway-DR4Kwuik.mjs.map} +1 -1
  4. package/dist/application-BO4ZF8wP.mjs +3 -0
  5. package/dist/{application-eHp9jXld.mjs → application-BX13RArL.mjs} +293 -17
  6. package/dist/application-BX13RArL.mjs.map +1 -0
  7. package/dist/authconnection-CZvi9ANm.mjs +9 -0
  8. package/dist/authconnection-CZvi9ANm.mjs.map +1 -0
  9. package/dist/brand-Eo4pLXPJ.mjs.map +1 -1
  10. package/dist/cli/commands/deploy/workflow-execution-policy.d.mts +1 -0
  11. package/dist/cli/index.mjs +138 -38
  12. package/dist/cli/index.mjs.map +1 -1
  13. package/dist/cli/lib.mjs +4 -4
  14. package/dist/cli/query/index.d.mts +4 -0
  15. package/dist/cli/ts-hook.mjs +43 -13
  16. package/dist/completion/zsh-worker.zsh +10 -10
  17. package/dist/configure/config/types.d.mts +3 -1
  18. package/dist/configure/index.d.mts +3 -1
  19. package/dist/configure/index.mjs +114 -4
  20. package/dist/configure/index.mjs.map +1 -1
  21. package/dist/configure/services/index.d.mts +3 -1
  22. package/dist/configure/services/tailordb/schema.d.mts +20 -20
  23. package/dist/configure/services/workflow/execution-policy.d.mts +71 -0
  24. package/dist/configure/services/workflow/execution-policy.types.d.mts +104 -0
  25. package/dist/configure/services/workflow/index.d.mts +3 -1
  26. package/dist/configure/services/workflow/job.d.mts +7 -2
  27. package/dist/{context-Bd266-ru.mjs → context-DYQVYWqZ.mjs} +4 -5
  28. package/dist/{context-Bd266-ru.mjs.map → context-DYQVYWqZ.mjs.map} +1 -1
  29. package/dist/{file-BbdFGdMV.mjs → file-BUcmVIH2.mjs} +12 -14
  30. package/dist/file-BUcmVIH2.mjs.map +1 -0
  31. package/dist/{file-utils-CYZnO1pX.mjs → file-utils-yEiIS4nJ.mjs} +2 -2
  32. package/dist/file-utils-yEiIS4nJ.mjs.map +1 -0
  33. package/dist/{globals-DhwZj0RB.mjs → globals-BjhJJ2dN.mjs} +2 -2
  34. package/dist/globals-BjhJJ2dN.mjs.map +1 -0
  35. package/dist/iconv-QWaZh0TT.mjs +38 -0
  36. package/dist/iconv-QWaZh0TT.mjs.map +1 -0
  37. package/dist/{idp-Bx25ZBdN.mjs → idp-RA_swu-h.mjs} +4 -5
  38. package/dist/idp-RA_swu-h.mjs.map +1 -0
  39. package/dist/{kysely-type-5eAChaHO.mjs → kysely-type-D-zflMGf.mjs} +1 -3
  40. package/dist/kysely-type-D-zflMGf.mjs.map +1 -0
  41. package/dist/plugin/builtin/file-utils/index.mjs +1 -1
  42. package/dist/plugin/builtin/kysely-type/index.mjs +1 -1
  43. package/dist/{register-ts-hook-ZpBacA07.mjs → register-ts-hook-BM1caLT0.mjs} +255 -256
  44. package/dist/register-ts-hook-BM1caLT0.mjs.map +1 -0
  45. package/dist/{registry-DH4m7eYo.mjs → registry-BSbq6SPo.mjs} +4 -3
  46. package/dist/registry-BSbq6SPo.mjs.map +1 -0
  47. package/dist/resource_pb-BRv7AMXK.mjs +49 -0
  48. package/dist/resource_pb-BRv7AMXK.mjs.map +1 -0
  49. package/dist/runtime/aigateway.d.mts +5 -14
  50. package/dist/runtime/aigateway.mjs +2 -2
  51. package/dist/runtime/authconnection.d.mts +5 -14
  52. package/dist/runtime/authconnection.mjs +2 -2
  53. package/dist/runtime/context.d.mts +14 -5
  54. package/dist/runtime/context.mjs +2 -2
  55. package/dist/runtime/file.d.mts +14 -54
  56. package/dist/runtime/file.mjs +2 -2
  57. package/dist/runtime/globals.d.mts +1 -1
  58. package/dist/runtime/iconv.d.mts +5 -53
  59. package/dist/runtime/iconv.mjs +2 -2
  60. package/dist/runtime/idp.d.mts +13 -70
  61. package/dist/runtime/idp.mjs +2 -2
  62. package/dist/runtime/index.d.mts +11 -11
  63. package/dist/runtime/index.mjs +9 -9
  64. package/dist/runtime/secretmanager.d.mts +7 -20
  65. package/dist/runtime/secretmanager.mjs +2 -2
  66. package/dist/runtime/workflow.d.mts +42 -41
  67. package/dist/runtime/workflow.mjs +2 -2
  68. package/dist/{schema-89dYxNC2.mjs → schema-C4LYbXVG.mjs} +5 -5
  69. package/dist/{schema-89dYxNC2.mjs.map → schema-C4LYbXVG.mjs.map} +1 -1
  70. package/dist/secretmanager-CYlpffsz.mjs +13 -0
  71. package/dist/secretmanager-CYlpffsz.mjs.map +1 -0
  72. package/dist/{service_pb-DjwIn4jO.mjs → service_pb-B2FF59sP.mjs} +1 -1
  73. package/dist/{service_pb-CIrhGwHk.mjs → service_pb-B5w9rjPY.mjs} +17 -50
  74. package/dist/service_pb-B5w9rjPY.mjs.map +1 -0
  75. package/dist/tailor-proto/src/tailor/v1/service_pb.d.mts +1 -1
  76. package/dist/tailor-proto/src/tailor/v1/workflow_pb.d.mts +29 -9
  77. package/dist/tailor-proto/src/tailor/v1/workflow_resource_pb.d.mts +35 -1
  78. package/dist/utils/test/index.mjs.map +1 -1
  79. package/dist/vitest/environment.mjs +1 -1
  80. package/dist/vitest/index.mjs +11 -11
  81. package/dist/vitest/index.mjs.map +1 -1
  82. package/dist/vitest/mocks/workflow.d.mts +5 -3
  83. package/dist/vitest/setup.mjs +1 -1
  84. package/dist/workflow-GNuSnsTx.mjs +22 -0
  85. package/dist/workflow-GNuSnsTx.mjs.map +1 -0
  86. package/docs/cli/auth.md +3 -3
  87. package/docs/cli/setup.md +8 -8
  88. package/docs/configuration.md +24 -0
  89. package/docs/migration/v2.md +111 -0
  90. package/docs/plugin/custom.md +4 -4
  91. package/docs/plugin/index.md +2 -2
  92. package/docs/runtime.md +4 -2
  93. package/docs/services/auth.md +2 -2
  94. package/docs/services/resolver.md +1 -1
  95. package/docs/services/tailordb-migration.md +1 -1
  96. package/docs/services/tailordb.md +31 -31
  97. package/docs/services/workflow.md +78 -0
  98. package/package.json +1 -1
  99. package/dist/aigateway-B3oZZE6v.mjs +0 -15
  100. package/dist/application-D2hSK1ZL.mjs +0 -3
  101. package/dist/application-eHp9jXld.mjs.map +0 -1
  102. package/dist/authconnection-BGQM8FZI.mjs +0 -15
  103. package/dist/authconnection-BGQM8FZI.mjs.map +0 -1
  104. package/dist/file-BbdFGdMV.mjs.map +0 -1
  105. package/dist/file-utils-CYZnO1pX.mjs.map +0 -1
  106. package/dist/globals-DhwZj0RB.mjs.map +0 -1
  107. package/dist/iconv-D2vi8G36.mjs +0 -63
  108. package/dist/iconv-D2vi8G36.mjs.map +0 -1
  109. package/dist/idp-Bx25ZBdN.mjs.map +0 -1
  110. package/dist/kysely-type-5eAChaHO.mjs.map +0 -1
  111. package/dist/register-ts-hook-ZpBacA07.mjs.map +0 -1
  112. package/dist/registry-DH4m7eYo.mjs.map +0 -1
  113. package/dist/rolldown-runtime-DXywRVcq.mjs +0 -20
  114. package/dist/secretmanager-BVxw3ih_.mjs +0 -24
  115. package/dist/secretmanager-BVxw3ih_.mjs.map +0 -1
  116. package/dist/service_pb-CIrhGwHk.mjs.map +0 -1
  117. package/dist/workflow-Bo59B75H.mjs +0 -50
  118. package/dist/workflow-Bo59B75H.mjs.map +0 -1
@@ -286,6 +286,30 @@ export default defineConfig({
286
286
 
287
287
  **ignores**: Glob patterns to exclude files. Optional.
288
288
 
289
+ ### Workflow Execution Policies
290
+
291
+ Register workspace-scoped execution policies that workflow job functions reference at runtime for per-key concurrency control. See [Execution Policies](./services/workflow.md#execution-policies) in the Workflow guide for the declaration API.
292
+
293
+ ```typescript
294
+ import { defineWorkflowExecutionPolicies } from "@tailor-platform/sdk";
295
+
296
+ const executionPolicies = defineWorkflowExecutionPolicies((define) => ({
297
+ premium: define({ concurrencyPolicy: { maxConcurrentExecutions: 5 } }),
298
+ tenantApi: define({
299
+ name: "tenant-api",
300
+ matchType: "prefix",
301
+ concurrencyPolicy: { maxConcurrentExecutions: 3 },
302
+ }),
303
+ }));
304
+
305
+ export default defineConfig({
306
+ workflow: {
307
+ files: ["workflows/**/*.ts"],
308
+ executionPolicies,
309
+ },
310
+ });
311
+ ```
312
+
289
313
  ### Plugins
290
314
 
291
315
  Configure plugins using `definePlugins()`. Plugins must be exported as a named export.
@@ -436,6 +436,74 @@ wrapper or global tailor.authconnection.
436
436
 
437
437
  </details>
438
438
 
439
+ ## Runtime subpath imports use namespace objects
440
+
441
+ **Migration:** Partially automatic
442
+
443
+ Rewrite `@tailor-platform/sdk/runtime/*` namespace-star and flat value imports to self-named namespace imports, and aggregate `file.deleteFile` calls to `file.delete`. `TailorContextAPI` and `TailorWorkflowAPI` now describe SDK wrappers; direct platform globals use `PlatformContextAPI` and `PlatformWorkflowAPI`.
444
+
445
+ Before:
446
+
447
+ ```ts
448
+ import * as iconv from "@tailor-platform/sdk/runtime/iconv";
449
+ iconv.convert(value, "UTF-8", "Shift_JIS");
450
+ ```
451
+
452
+ After:
453
+
454
+ ```ts
455
+ import { iconv } from "@tailor-platform/sdk/runtime/iconv";
456
+ iconv.convert(value, "UTF-8", "Shift_JIS");
457
+ ```
458
+
459
+ Before:
460
+
461
+ ```ts
462
+ import { get } from "@tailor-platform/sdk/runtime/aigateway";
463
+ const gateway = await get("main");
464
+ ```
465
+
466
+ After:
467
+
468
+ ```ts
469
+ import { aigateway } from "@tailor-platform/sdk/runtime/aigateway";
470
+ const gateway = await aigateway.get("main");
471
+ ```
472
+
473
+ Before:
474
+
475
+ ```ts
476
+ import { file } from "@tailor-platform/sdk/runtime";
477
+ await file.deleteFile("ns", "Doc", "blob", "record-id");
478
+ ```
479
+
480
+ After:
481
+
482
+ ```ts
483
+ import { file } from "@tailor-platform/sdk/runtime";
484
+ await file.delete("ns", "Doc", "blob", "record-id");
485
+ ```
486
+
487
+ <details>
488
+ <summary>Prompt for an AI agent (to finish the cases the codemod could not migrate)</summary>
489
+
490
+ ```text
491
+ In Tailor SDK v2, runtime subpath modules export only a self-named namespace
492
+ object (for example, `iconv` from `@tailor-platform/sdk/runtime/iconv`).
493
+ Default and flat value imports such as
494
+ `import { get } from "@tailor-platform/sdk/runtime/aigateway"` are removed.
495
+ The codemod rewrites straightforward namespace-star imports and flat named value
496
+ imports. It also rewrites direct `file.deleteFile` calls on the aggregate runtime
497
+ namespace to `file.delete`. Destructured aggregate `deleteFile` references require
498
+ manual migration. Review any remaining runtime imports manually, especially when
499
+ a local binding or nested scope shadows an imported value, or when
500
+ type-position namespace member references need explicit top-level type imports.
501
+ For direct platform globals, replace `TailorContextAPI` and `TailorWorkflowAPI`
502
+ type references with `PlatformContextAPI` and `PlatformWorkflowAPI` respectively.
503
+ ```
504
+
505
+ </details>
506
+
439
507
  ## Tailordb → tailordb (lowercase ambient namespace)
440
508
 
441
509
  **Migration:** Partially automatic
@@ -471,6 +539,49 @@ declarations automatically on SDK import.
471
539
 
472
540
  </details>
473
541
 
542
+ ## db.type() → db.table()
543
+
544
+ **Migration:** Partially automatic
545
+
546
+ Rename TailorDB schema builder calls from `db.type()` to `db.table()`. TailorDB schema definitions now use table terminology in SDK projects.
547
+
548
+ Before:
549
+
550
+ ```ts
551
+ import { db } from "@tailor-platform/sdk";
552
+
553
+ export const user = db.type("User", {
554
+ name: db.string(),
555
+ });
556
+ ```
557
+
558
+ After:
559
+
560
+ ```ts
561
+ import { db } from "@tailor-platform/sdk";
562
+
563
+ export const user = db.table("User", {
564
+ name: db.string(),
565
+ });
566
+ ```
567
+
568
+ <details>
569
+ <summary>Prompt for an AI agent (to finish the cases the codemod could not migrate)</summary>
570
+
571
+ ```text
572
+ In Tailor SDK v2, TailorDB schema definitions use db.table(...) instead of
573
+ db.type(...). The codemod rewrites member accesses on db imported from
574
+ @tailor-platform/sdk, including aliases such as `import { db as schema }`.
575
+ It flags destructured builder aliases such as `const { type } = db` and
576
+ local builder aliases such as `const schema = db`, `schema = db`, or
577
+ `function make(schema = db) { ... }` for manual review because the local
578
+ alias may require call-site renaming.
579
+ Review any remaining db.type references and rename SDK TailorDB schema builder
580
+ calls to db.table. Leave unrelated local objects with a .type() method unchanged.
581
+ ```
582
+
583
+ </details>
584
+
474
585
  ## executeScript arg JSON.stringify → value
475
586
 
476
587
  **Migration:** Partially automatic
@@ -93,7 +93,7 @@ interface Plugin<TypeConfig = unknown, PluginConfig = unknown> {
93
93
  onTypeLoaded(context) {
94
94
  const { type, typeConfig, namespace } = context;
95
95
  return {
96
- types: { archive: db.type(`Deleted_${type.name}`, { ... }) },
96
+ types: { archive: db.table(`Deleted_${type.name}`, { ... }) },
97
97
  extends: { fields: { deletedAt: db.datetime({ optional: true }) } },
98
98
  executors: [{ name: `${type.name}-on-delete`, resolve: async () => await import("./on-delete"), context: { sourceType: type, namespace } }],
99
99
  };
@@ -122,7 +122,7 @@ Same as `TypePluginOutput` but without `extends` (namespace plugins cannot exten
122
122
  ```typescript
123
123
  onNamespaceLoaded(context) {
124
124
  return {
125
- types: { auditLog: db.type("AuditLog", { action: db.string(), ... }) },
125
+ types: { auditLog: db.table("AuditLog", { action: db.string(), ... }) },
126
126
  };
127
127
  },
128
128
  ```
@@ -343,7 +343,7 @@ function processSoftDelete(
343
343
 
344
344
  // Generate archive type
345
345
  const archiveType = db
346
- .type(`${prefix}${type.name}`, {
346
+ .table(`${prefix}${type.name}`, {
347
347
  originalId: db.uuid().description("ID of the deleted record"),
348
348
  originalData: db.string().description("JSON snapshot of deleted record"),
349
349
  deletedAt: db.datetime().description("When the record was deleted"),
@@ -450,7 +450,7 @@ export const plugins = definePlugins(
450
450
 
451
451
  // tailordb/customer.ts
452
452
  export const customer = db
453
- .type("Customer", {
453
+ .table("Customer", {
454
454
  name: db.string(),
455
455
  email: db.string(),
456
456
  })
@@ -43,7 +43,7 @@ Use the `.plugin()` method to attach plugins to specific types:
43
43
  import { db } from "@tailor-platform/sdk";
44
44
 
45
45
  export const user = db
46
- .type("User", {
46
+ .table("User", {
47
47
  name: db.string(),
48
48
  email: db.string(),
49
49
  })
@@ -58,7 +58,7 @@ Some plugins accept per-type configuration:
58
58
 
59
59
  ```typescript
60
60
  export const customer = db
61
- .type("Customer", {
61
+ .table("Customer", {
62
62
  name: db.string(),
63
63
  // ...
64
64
  })
package/docs/runtime.md CHANGED
@@ -45,10 +45,12 @@ const { url } = await aigateway.get("my-aigateway");
45
45
  Each namespace can also be imported individually so you only pull what you need:
46
46
 
47
47
  ```ts
48
- import * as iconv from "@tailor-platform/sdk/runtime/iconv";
49
- import type { ListUsersResponse, ClientConfig } from "@tailor-platform/sdk/runtime/idp";
48
+ import { iconv } from "@tailor-platform/sdk/runtime/iconv";
49
+ import { idp, type ListUsersResponse, type ClientConfig } from "@tailor-platform/sdk/runtime/idp";
50
50
  ```
51
51
 
52
+ `TailorContextAPI` and `TailorWorkflowAPI` describe the imported SDK wrapper objects. When typing direct access to the platform-provided globals or a runtime mock, use `PlatformContextAPI` or `PlatformWorkflowAPI` instead.
53
+
52
54
  ## Activating the global types
53
55
 
54
56
  Most users do not need to touch the globals entry — `@tailor-platform/sdk/runtime` (and its subpath modules) cover the same surface without depending on any ambient declaration.
@@ -86,7 +86,7 @@ Example TailorDB type for user profile:
86
86
  // tailordb/user.ts
87
87
  import { db } from "@tailor-platform/sdk";
88
88
 
89
- export const user = db.type("User", {
89
+ export const user = db.table("User", {
90
90
  email: db.string().unique(), // usernameField must have unique constraint
91
91
  role: db.enum(["admin", "user"]),
92
92
  ...db.fields.timestamps(),
@@ -130,7 +130,7 @@ Example TailorDB type with UUID fields for attribute list:
130
130
  // tailordb/user.ts
131
131
  import { db } from "@tailor-platform/sdk";
132
132
 
133
- export const user = db.type("User", {
133
+ export const user = db.table("User", {
134
134
  email: db.string().unique(),
135
135
  role: db.enum(["admin", "user"]),
136
136
  organizationId: db.uuid(), // Can be used in attributeList
@@ -108,7 +108,7 @@ Define input/output schemas using methods of `t` object. Basic usage and support
108
108
  You can reuse fields defined with `db` object, but note that unsupported options will be ignored:
109
109
 
110
110
  ```typescript
111
- const user = db.type("User", {
111
+ const user = db.table("User", {
112
112
  name: db.string().unique(),
113
113
  age: db.int(),
114
114
  });
@@ -69,7 +69,7 @@ A typical change cycle:
69
69
 
70
70
  ```typescript
71
71
  // tailordb/user.ts
72
- export const user = db.type("User", {
72
+ export const user = db.table("User", {
73
73
  name: db.string(),
74
74
  email: db.string(), // ← new required field
75
75
  ...db.fields.timestamps(),
@@ -29,7 +29,7 @@ Define TailorDB Types in files matching glob patterns specified in `tailor.confi
29
29
  import { db } from "@tailor-platform/sdk";
30
30
 
31
31
  // Export both value and type
32
- export const user = db.type("User", {
32
+ export const user = db.table("User", {
33
33
  name: db.string(),
34
34
  email: db.string().unique(),
35
35
  age: db.int(),
@@ -38,7 +38,7 @@ export const user = db.type("User", {
38
38
  export type user = typeof user;
39
39
 
40
40
  // You can define multiple types in the same file
41
- export const role = db.type("Role", {
41
+ export const role = db.table("Role", {
42
42
  name: db.string().unique(),
43
43
  });
44
44
  export type role = typeof role;
@@ -47,7 +47,7 @@ export type role = typeof role;
47
47
  Specify plural form by passing an array as first argument:
48
48
 
49
49
  ```typescript
50
- db.type(["User", "UserList"], {
50
+ db.table(["User", "UserList"], {
51
51
  name: db.string(),
52
52
  });
53
53
  ```
@@ -55,7 +55,7 @@ db.type(["User", "UserList"], {
55
55
  Pass a description as second argument:
56
56
 
57
57
  ```typescript
58
- db.type("User", "User in the system", {
58
+ db.table("User", "User in the system", {
59
59
  name: db.string(),
60
60
  });
61
61
  ```
@@ -174,11 +174,11 @@ db.string().unique();
174
174
  Add a relation to field with automatic index and foreign key constraint:
175
175
 
176
176
  ```typescript
177
- const role = db.type("Role", {
177
+ const role = db.table("Role", {
178
178
  name: db.string(),
179
179
  });
180
180
 
181
- const user = db.type("User", {
181
+ const user = db.table("User", {
182
182
  name: db.string(),
183
183
  roleId: db.uuid().relation({
184
184
  type: "n-1",
@@ -190,7 +190,7 @@ const user = db.type("User", {
190
190
  For one-to-one relations, use `type: "1-1"`:
191
191
 
192
192
  ```typescript
193
- const userProfile = db.type("UserProfile", {
193
+ const userProfile = db.table("UserProfile", {
194
194
  userId: db.uuid().relation({
195
195
  type: "1-1",
196
196
  toward: { type: user },
@@ -202,7 +202,7 @@ const userProfile = db.type("UserProfile", {
202
202
  For foreign key constraint without creating a relation, use `type: "keyOnly"`:
203
203
 
204
204
  ```typescript
205
- const user = db.type("User", {
205
+ const user = db.table("User", {
206
206
  roleId: db.uuid().relation({
207
207
  type: "keyOnly",
208
208
  toward: { type: role },
@@ -213,11 +213,11 @@ const user = db.type("User", {
213
213
  Create relations against different fields using `toward.key`:
214
214
 
215
215
  ```typescript
216
- const user = db.type("User", {
216
+ const user = db.table("User", {
217
217
  email: db.string().unique(),
218
218
  });
219
219
 
220
- const userProfile = db.type("UserProfile", {
220
+ const userProfile = db.table("UserProfile", {
221
221
  userEmail: db.string().relation({
222
222
  type: "1-1",
223
223
  toward: { type: user, key: "email" },
@@ -228,7 +228,7 @@ const userProfile = db.type("UserProfile", {
228
228
  Customize relation names using `toward.as` / `backward` options:
229
229
 
230
230
  ```typescript
231
- const userProfile = db.type("UserProfile", {
231
+ const userProfile = db.table("UserProfile", {
232
232
  userId: db.uuid().relation({
233
233
  type: "1-1",
234
234
  toward: { type: user, as: "base" },
@@ -260,7 +260,7 @@ on the same type point to the same target type, because their default forward na
260
260
  from the target type name:
261
261
 
262
262
  ```typescript
263
- const post = db.type("Post", {
263
+ const post = db.table("Post", {
264
264
  authorID: db.uuid().relation({
265
265
  type: "n-1",
266
266
  toward: { type: user, as: "author" },
@@ -300,11 +300,11 @@ db.string().hooks({
300
300
 
301
301
  #### Type-level Hooks
302
302
 
303
- Set hooks for multiple fields at once using `db.type().hooks()`:
303
+ Set hooks for multiple fields at once using `db.table().hooks()`:
304
304
 
305
305
  ```typescript
306
306
  export const customer = db
307
- .type("Customer", {
307
+ .table("Customer", {
308
308
  firstName: db.string(),
309
309
  lastName: db.string(),
310
310
  fullName: db.string(),
@@ -322,7 +322,7 @@ export const customer = db
322
322
  ```typescript
323
323
  // Compile error - cannot set hooks on the same field twice
324
324
  export const user = db
325
- .type("User", {
325
+ .table("User", {
326
326
  name: db.string().hooks({ create: ({ data }) => data.firstName }), // Field-level
327
327
  })
328
328
  .hooks({
@@ -331,7 +331,7 @@ export const user = db
331
331
 
332
332
  // OK - set hooks on different fields
333
333
  export const user = db
334
- .type("User", {
334
+ .table("User", {
335
335
  firstName: db.string().hooks({ create: () => "John" }), // Field-level on firstName
336
336
  lastName: db.string(),
337
337
  })
@@ -363,11 +363,11 @@ db.string().validate(
363
363
 
364
364
  #### Type-level Validation
365
365
 
366
- Set validators for multiple fields at once using `db.type().validate()`:
366
+ Set validators for multiple fields at once using `db.table().validate()`:
367
367
 
368
368
  ```typescript
369
369
  export const user = db
370
- .type("User", {
370
+ .table("User", {
371
371
  name: db.string(),
372
372
  email: db.string(),
373
373
  })
@@ -385,7 +385,7 @@ export const user = db
385
385
  ```typescript
386
386
  // Compile error - cannot set validation on the same field twice
387
387
  export const user = db
388
- .type("User", {
388
+ .table("User", {
389
389
  name: db.string().validate(({ value }) => value.length > 0), // Field-level
390
390
  })
391
391
  .validate({
@@ -394,7 +394,7 @@ export const user = db
394
394
 
395
395
  // OK - set validation on different fields
396
396
  export const user = db
397
- .type("User", {
397
+ .table("User", {
398
398
  name: db.string().validate(({ value }) => value.length > 0), // Field-level on name
399
399
  email: db.string(),
400
400
  })
@@ -426,7 +426,7 @@ db.string().serial({
426
426
  ### Common Fields
427
427
 
428
428
  ```typescript
429
- export const user = db.type("User", {
429
+ export const user = db.table("User", {
430
430
  name: db.string(),
431
431
  ...db.fields.timestamps(),
432
432
  });
@@ -439,7 +439,7 @@ export const user = db.type("User", {
439
439
  ### Composite Indexes
440
440
 
441
441
  ```typescript
442
- db.type("User", {
442
+ db.table("User", {
443
443
  firstName: db.string(),
444
444
  lastName: db.string(),
445
445
  }).indexes({
@@ -452,7 +452,7 @@ db.type("User", {
452
452
  ### File Fields
453
453
 
454
454
  ```typescript
455
- db.type("User", {
455
+ db.table("User", {
456
456
  name: db.string(),
457
457
  }).files({
458
458
  avatar: "profile image",
@@ -462,7 +462,7 @@ db.type("User", {
462
462
  ### Features
463
463
 
464
464
  ```typescript
465
- db.type("User", {
465
+ db.table("User", {
466
466
  name: db.string(),
467
467
  }).features({
468
468
  aggregation: true,
@@ -475,7 +475,7 @@ db.type("User", {
475
475
  Enable event publishing for a type to trigger executors on record changes:
476
476
 
477
477
  ```typescript
478
- db.type("User", {
478
+ db.table("User", {
479
479
  name: db.string(),
480
480
  }).features({
481
481
  publishEvents: true,
@@ -494,7 +494,7 @@ db.type("User", {
494
494
 
495
495
  ```typescript
496
496
  // publishEvents is automatically enabled because an executor uses this type
497
- export const order = db.type("Order", {
497
+ export const order = db.table("Order", {
498
498
  status: db.string(),
499
499
  });
500
500
 
@@ -508,7 +508,7 @@ db.type("User", {
508
508
  2. **Manual enable**: Enable event publishing for external consumers or debugging
509
509
 
510
510
  ```typescript
511
- db.type("AuditLog", {
511
+ db.table("AuditLog", {
512
512
  action: db.string(),
513
513
  }).features({
514
514
  publishEvents: true, // Enable even without executor triggers
@@ -518,7 +518,7 @@ db.type("User", {
518
518
  3. **Explicit disable**: Disable event publishing for a type that doesn't need it (error if executor uses it)
519
519
 
520
520
  ```typescript
521
- db.type("TempData", {
521
+ db.table("TempData", {
522
522
  data: db.string(),
523
523
  }).features({
524
524
  publishEvents: false, // Explicitly disable
@@ -534,7 +534,7 @@ Extract subsets of fields from a `TailorDBType` for reuse in resolvers, executor
534
534
  Select specific fields and optionally modify their properties:
535
535
 
536
536
  ```typescript
537
- const user = db.type("User", {
537
+ const user = db.table("User", {
538
538
  id: db.uuid(),
539
539
  name: db.string(),
540
540
  email: db.string().unique(),
@@ -604,7 +604,7 @@ Configure Permission and GQLPermission. For details, see the [TailorDB Permissio
604
604
  **Important**: Following the secure-by-default principle, all operations are denied if permissions are not configured. You must explicitly grant permissions for each operation (create, read, update, delete).
605
605
 
606
606
  ```typescript
607
- db.type("User", {
607
+ db.table("User", {
608
608
  name: db.string(),
609
609
  role: db.enum(["admin", "user"]).index(),
610
610
  })
@@ -634,7 +634,7 @@ import {
634
634
  unsafeAllowAllGqlPermission,
635
635
  } from "@tailor-platform/sdk";
636
636
 
637
- db.type("User", {
637
+ db.table("User", {
638
638
  name: db.string(),
639
639
  })
640
640
  .permission(unsafeAllowAllTypePermission)
@@ -351,6 +351,84 @@ export default createWorkflow({
351
351
  });
352
352
  ```
353
353
 
354
+ ## Execution Policies
355
+
356
+ Execution policies apply a per-key concurrency cap to workflow job function dispatches. Declare them at the workspace level and pass a matching key when triggering a job; the platform serializes dispatches that resolve to the same key and suspends any that would exceed the cap until slots free up.
357
+
358
+ ### Declaring Policies
359
+
360
+ Use `defineWorkflowExecutionPolicies` with a builder callback. Property names supply the workspace-unique name and default key prefix verbatim, matching the mental model of `defineWaitPoints`. Override `name` or `key` in the body when the property identifier is not valid execution policy grammar or the key prefix needs to differ. Set `matchType: "prefix"` to register the prefix as a wildcard that matches every dispatch key starting with it (the default, `"exact"`, matches only a dispatch key equal to it).
361
+
362
+ ```typescript
363
+ import { defineWorkflowExecutionPolicies } from "@tailor-platform/sdk";
364
+
365
+ export const executionPolicies = defineWorkflowExecutionPolicies((define) => ({
366
+ /** Shared cap across every "premium" worker dispatch. */
367
+ premium: define({ concurrencyPolicy: { maxConcurrentExecutions: 5 } }),
368
+ /** Per-tenant cap: one pool per resolved tenant key. */
369
+ tenantApi: define({
370
+ name: "tenant-api",
371
+ matchType: "prefix",
372
+ concurrencyPolicy: { maxConcurrentExecutions: 3 },
373
+ }),
374
+ }));
375
+ ```
376
+
377
+ For a single policy, use `defineWorkflowExecutionPolicy(name, def?)`; the key prefix defaults to `name` when `key` is omitted.
378
+
379
+ `concurrencyPolicy` is optional; when omitted, the policy registers the key as valid without a user-defined limit (platform safety nets still apply).
380
+
381
+ Register the policies on your config so the SDK creates them on the workspace during deploy:
382
+
383
+ ```typescript
384
+ // tailor.config.ts
385
+ import { defineConfig } from "@tailor-platform/sdk";
386
+ import { executionPolicies } from "./workflows/policies";
387
+
388
+ export default defineConfig({
389
+ workflow: {
390
+ files: ["workflows/**/*.ts"],
391
+ executionPolicies,
392
+ },
393
+ });
394
+ ```
395
+
396
+ ### Key Grammar
397
+
398
+ `key` accepts `[a-z0-9_:.-]` and must start with `[a-z0-9]`. An exact key must also end with `[a-z0-9]`; a wildcard prefix (`matchType: "prefix"`) may end with any of those characters, since the platform appends a trailing `*` after it. The platform-registered key — including that trailing `*` when wildcarded — is 2 to 64 characters long, so a wildcard prefix must be at most 63 characters. `foo:bar` is a valid exact key; `tenant-api` with `matchType: "prefix"` registers `tenant-api*` as a wildcard prefix.
399
+
400
+ An exact-key policy applies to dispatches whose runtime key equals the policy key. A wildcard policy applies to every dispatch whose runtime key begins with the prefix; each concrete resolved key gets its own independent pool of the declared size (a `cap = 3` wildcard yields three concurrent dispatches per resolved key, not three across every match). The longest matching prefix wins when a dispatch could match more than one wildcard.
401
+
402
+ ### Referencing a Policy from a Workflow
403
+
404
+ Pass the runtime key through the `executionPolicyKey` option on `job.trigger()` or `tailor.workflow.triggerJobFunction()`. For exact-key policies, use `<policy>.key` directly — it's typed so only a value that came from a declared policy can be passed. For wildcard policies (`matchType: "prefix"`), there is no `<policy>.key` — call `<policy>.keyFor(suffix)` to build the concrete key. `keyFor` joins the prefix and suffix with `.` by default; override it with `separator` — the second argument to `defineWorkflowExecutionPolicies` (applies to every policy in the group), or a `def` field on a single `defineWorkflowExecutionPolicy`.
405
+
406
+ ```typescript
407
+ import { createWorkflowJob } from "@tailor-platform/sdk";
408
+ import { executionPolicies } from "./policies";
409
+ import { sendNotification } from "./jobs/send-notification";
410
+ import { fetchTenant } from "./jobs/fetch-tenant";
411
+
412
+ export const mainJob = createWorkflowJob({
413
+ name: "main-job",
414
+ body: async (input: { tenantId: string }) => {
415
+ // Exact key policy: pass .key directly.
416
+ await sendNotification.trigger(
417
+ { message: "Order processed" },
418
+ { executionPolicyKey: executionPolicies.premium.key },
419
+ );
420
+
421
+ // Wildcard policy: build the concrete key with keyFor().
422
+ await fetchTenant.trigger(
423
+ { tenantId: input.tenantId },
424
+ { executionPolicyKey: executionPolicies.tenantApi.keyFor(input.tenantId) },
425
+ );
426
+ },
427
+ });
428
+ ```
429
+
430
+ The same `executionPolicyKey` option is available on `tailor.workflow.triggerJobFunction(name, args, options)` for jobs invoked by name.
431
+
354
432
  ## Triggering a Workflow from a Resolver
355
433
 
356
434
  You can start a workflow execution from a resolver using `workflow.trigger()`.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tailor-platform/sdk",
3
- "version": "2.0.0-next.3",
3
+ "version": "2.0.0-next.4",
4
4
  "description": "Tailor Platform SDK - The SDK to work with Tailor Platform",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -1,15 +0,0 @@
1
- import { t as __exportAll } from "./rolldown-runtime-DXywRVcq.mjs";
2
-
3
- //#region src/runtime/aigateway.ts
4
- var aigateway_exports = /* @__PURE__ */ __exportAll({ get: () => get });
5
- const api = () => globalThis.tailor.aigateway;
6
- /**
7
- * See {@link TailorAigatewayAPI.get}.
8
- * @param args - Forwarded to {@link TailorAigatewayAPI.get}
9
- * @returns The resolved AI Gateway's platform-assigned URL
10
- */
11
- const get = (...args) => api().get(...args);
12
-
13
- //#endregion
14
- export { get as n, aigateway_exports as t };
15
- //# sourceMappingURL=aigateway-B3oZZE6v.mjs.map
@@ -1,3 +0,0 @@
1
- import { n as generatePluginFilesIfNeeded, r as loadApplication, t as defineApplication } from "./application-eHp9jXld.mjs";
2
-
3
- export { defineApplication, generatePluginFilesIfNeeded };