@tailor-platform/sdk 2.0.0-next.1 → 2.0.0-next.10

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 (471) hide show
  1. package/CHANGELOG.md +869 -2
  2. package/README.md +9 -9
  3. package/agent-skills/{tailor-sdk → tailor}/SKILL.md +3 -1
  4. package/dist/aigateway-DR4Kwuik.mjs +9 -0
  5. package/dist/aigateway-DR4Kwuik.mjs.map +1 -0
  6. package/dist/application-DArFTTJ9.mjs +3 -0
  7. package/dist/{application-DqS1yBg3.mjs → application-miwiXtB4.mjs} +1892 -1968
  8. package/dist/application-miwiXtB4.mjs.map +1 -0
  9. package/dist/authconnection-CZvi9ANm.mjs +9 -0
  10. package/dist/authconnection-CZvi9ANm.mjs.map +1 -0
  11. package/dist/brand-Eo4pLXPJ.mjs.map +1 -1
  12. package/dist/cli/cache/bundle-cache.d.mts +2 -0
  13. package/dist/cli/cache/store.d.mts +1 -0
  14. package/dist/cli/cache/types.d.mts +1 -0
  15. package/dist/cli/commands/api/api-call.d.mts +19 -0
  16. package/dist/cli/commands/api/index.d.mts +4 -0
  17. package/dist/cli/commands/deploy/aigateway.d.mts +5 -0
  18. package/dist/cli/commands/deploy/application.d.mts +7 -0
  19. package/dist/cli/commands/deploy/apply-phases.d.mts +14 -0
  20. package/dist/cli/commands/deploy/auth.d.mts +5 -0
  21. package/dist/cli/commands/deploy/deploy.d.mts +34 -0
  22. package/dist/cli/commands/deploy/executor.d.mts +7 -0
  23. package/dist/cli/commands/deploy/function-registry-types.d.mts +12 -0
  24. package/dist/cli/commands/deploy/function-registry.d.mts +7 -0
  25. package/dist/cli/commands/deploy/idp.d.mts +5 -0
  26. package/dist/cli/commands/deploy/resolver.d.mts +5 -0
  27. package/dist/cli/commands/deploy/secret-manager.d.mts +5 -0
  28. package/dist/cli/commands/deploy/staticwebsite.d.mts +5 -0
  29. package/dist/cli/commands/deploy/tailordb/index.d.mts +9 -0
  30. package/dist/cli/commands/deploy/types.d.mts +3 -0
  31. package/dist/cli/commands/deploy/workflow-execution-policy.d.mts +3 -0
  32. package/dist/cli/commands/deploy/workflow.d.mts +4 -0
  33. package/dist/cli/commands/executor/get.d.mts +28 -0
  34. package/dist/cli/commands/executor/jobs.d.mts +122 -0
  35. package/dist/cli/commands/executor/list.d.mts +18 -0
  36. package/dist/cli/commands/executor/transform.d.mts +42 -0
  37. package/dist/cli/commands/executor/trigger.d.mts +40 -0
  38. package/dist/cli/commands/executor/webhook.d.mts +21 -0
  39. package/dist/cli/commands/function/get.d.mts +17 -0
  40. package/dist/cli/commands/function/list.d.mts +21 -0
  41. package/dist/cli/commands/function/transform.d.mts +12 -0
  42. package/dist/cli/commands/generate/options.d.mts +6 -0
  43. package/dist/cli/commands/generate/seed/bundler.d.mts +26 -0
  44. package/dist/cli/commands/generate/service.d.mts +15 -0
  45. package/dist/cli/commands/machineuser/list.d.mts +26 -0
  46. package/dist/cli/commands/machineuser/token.d.mts +21 -0
  47. package/dist/cli/commands/oauth2client/get.d.mts +17 -0
  48. package/dist/cli/commands/oauth2client/list.d.mts +19 -0
  49. package/dist/cli/commands/oauth2client/transform.d.mts +21 -0
  50. package/dist/cli/commands/organization/folder/create.d.mts +17 -0
  51. package/dist/cli/commands/organization/folder/delete.d.mts +15 -0
  52. package/dist/cli/commands/organization/folder/get.d.mts +16 -0
  53. package/dist/cli/commands/organization/folder/list.d.mts +21 -0
  54. package/dist/cli/commands/organization/folder/update.d.mts +17 -0
  55. package/dist/cli/commands/organization/get.d.mts +15 -0
  56. package/dist/cli/commands/organization/list.d.mts +14 -0
  57. package/dist/cli/commands/organization/transform.d.mts +29 -0
  58. package/dist/cli/commands/organization/tree.d.mts +24 -0
  59. package/dist/cli/commands/organization/update.d.mts +16 -0
  60. package/dist/cli/commands/remove.d.mts +15 -0
  61. package/dist/cli/commands/show.d.mts +39 -0
  62. package/dist/cli/commands/staticwebsite/deploy.d.mts +19 -0
  63. package/dist/cli/commands/tailordb/migrate/bundler.d.mts +29 -0
  64. package/dist/cli/commands/tailordb/migrate/config.d.mts +18 -0
  65. package/dist/cli/commands/tailordb/migrate/diff-calculator.d.mts +246 -0
  66. package/dist/cli/commands/tailordb/migrate/generate.d.mts +16 -0
  67. package/dist/cli/commands/tailordb/migrate/snapshot-types.d.mts +208 -0
  68. package/dist/cli/commands/tailordb/migrate/snapshot.d.mts +98 -0
  69. package/dist/cli/commands/tailordb/migrate/types.d.mts +7 -0
  70. package/dist/cli/commands/tailordb/truncate.d.mts +18 -0
  71. package/dist/cli/commands/workflow/executions.d.mts +74 -0
  72. package/dist/cli/commands/workflow/get.d.mts +30 -0
  73. package/dist/cli/commands/workflow/list.d.mts +18 -0
  74. package/dist/cli/commands/workflow/resume.d.mts +22 -0
  75. package/dist/cli/commands/workflow/start.d.mts +60 -0
  76. package/dist/cli/commands/workflow/status.d.mts +6 -0
  77. package/dist/cli/commands/workflow/transform.d.mts +34 -0
  78. package/dist/cli/commands/workflow/wait.d.mts +15 -0
  79. package/dist/cli/commands/workflow/waiter.d.mts +23 -0
  80. package/dist/cli/commands/workspace/app/health.d.mts +17 -0
  81. package/dist/cli/commands/workspace/app/list.d.mts +21 -0
  82. package/dist/cli/commands/workspace/app/transform.d.mts +20 -0
  83. package/dist/cli/commands/workspace/create.d.mts +27 -0
  84. package/dist/cli/commands/workspace/delete.d.mts +14 -0
  85. package/dist/cli/commands/workspace/get.d.mts +16 -0
  86. package/dist/cli/commands/workspace/list.d.mts +17 -0
  87. package/dist/cli/commands/workspace/restore.d.mts +14 -0
  88. package/dist/cli/commands/workspace/transform.d.mts +20 -0
  89. package/dist/cli/commands/workspace/user/invite.d.mts +21 -0
  90. package/dist/cli/commands/workspace/user/list.d.mts +21 -0
  91. package/dist/cli/commands/workspace/user/remove.d.mts +16 -0
  92. package/dist/cli/commands/workspace/user/transform.d.mts +9 -0
  93. package/dist/cli/commands/workspace/user/update.d.mts +21 -0
  94. package/dist/cli/index.mjs +12 -5481
  95. package/dist/cli/lib.d.mts +90 -21048
  96. package/dist/cli/lib.mjs +154 -12
  97. package/dist/cli/lib.mjs.map +1 -1
  98. package/dist/cli/main.d.mts +23 -0
  99. package/dist/cli/main.mjs +6583 -0
  100. package/dist/cli/main.mjs.map +1 -0
  101. package/dist/cli/query/index.d.mts +38 -0
  102. package/dist/cli/services/application.d.mts +12 -0
  103. package/dist/cli/services/auth/service.d.mts +3 -0
  104. package/dist/cli/services/executor/service.d.mts +1 -0
  105. package/dist/cli/services/http-adapter/bundler.d.mts +3 -0
  106. package/dist/cli/services/http-adapter/service.d.mts +2 -0
  107. package/dist/cli/services/resolver/service.d.mts +1 -0
  108. package/dist/cli/services/tailordb/service.d.mts +3 -0
  109. package/dist/cli/services/workflow/bundler.d.mts +2 -0
  110. package/dist/cli/services/workflow/service.d.mts +1 -0
  111. package/dist/cli/shared/args.d.mts +13 -0
  112. package/dist/cli/shared/client.d.mts +1273 -0
  113. package/dist/cli/shared/config-loader.d.mts +25 -0
  114. package/dist/cli/shared/context.d.mts +29 -0
  115. package/dist/cli/shared/error-json.d.mts +23 -0
  116. package/dist/cli/shared/readonly-guard.d.mts +25 -0
  117. package/dist/cli/shared/script-executor.d.mts +77 -0
  118. package/dist/cli/shared/seed-chunker.d.mts +45 -0
  119. package/dist/cli/shared/seed-context.d.mts +49 -0
  120. package/dist/cli/shared/tailordb-namespaces.d.mts +40 -0
  121. package/dist/cli/shared/type-generator.d.mts +19 -0
  122. package/dist/cli/shared/workspace-name.d.mts +1 -0
  123. package/dist/cli/ts-hook.d.mts +4 -0
  124. package/dist/cli/ts-hook.mjs +333 -0
  125. package/dist/completion/zsh-worker.zsh +1433 -1239
  126. package/dist/configure/config/index.d.mts +20 -0
  127. package/dist/configure/config/types.d.mts +111 -0
  128. package/dist/configure/index.d.mts +135 -8
  129. package/dist/configure/index.mjs +390 -36
  130. package/dist/configure/index.mjs.map +1 -1
  131. package/dist/configure/services/aigateway/index.d.mts +16 -0
  132. package/dist/configure/services/aigateway/types.d.mts +10 -0
  133. package/dist/configure/services/auth/index.d.mts +33 -0
  134. package/dist/configure/services/auth/types.d.mts +168 -0
  135. package/dist/configure/services/executor/executor.d.mts +70 -0
  136. package/dist/configure/services/executor/index.d.mts +9 -0
  137. package/dist/configure/services/executor/operation.d.mts +50 -0
  138. package/dist/configure/services/executor/trigger/event.d.mts +271 -0
  139. package/dist/configure/services/executor/trigger/index.d.mts +7 -0
  140. package/dist/configure/services/executor/trigger/schedule.d.mts +24 -0
  141. package/dist/configure/services/executor/trigger/webhook.d.mts +43 -0
  142. package/dist/configure/services/executor/types.d.mts +2 -0
  143. package/dist/configure/services/http-adapter/http-adapter.d.mts +124 -0
  144. package/dist/configure/services/http-adapter/index.d.mts +2 -0
  145. package/dist/configure/services/idp/index.d.mts +60 -0
  146. package/dist/configure/services/idp/permission.d.mts +64 -0
  147. package/dist/configure/services/idp/types.d.mts +23 -0
  148. package/dist/configure/services/index.d.mts +40 -0
  149. package/dist/configure/services/resolver/index.d.mts +6 -0
  150. package/dist/configure/services/resolver/permission.d.mts +64 -0
  151. package/dist/configure/services/resolver/resolver.d.mts +88 -0
  152. package/dist/configure/services/resolver/types.d.mts +5 -0
  153. package/dist/configure/services/secrets/index.d.mts +37 -0
  154. package/dist/configure/services/secrets/types.d.mts +10 -0
  155. package/dist/configure/services/staticwebsite/index.d.mts +18 -0
  156. package/dist/configure/services/staticwebsite/types.d.mts +10 -0
  157. package/dist/configure/services/tailordb/index.d.mts +4 -0
  158. package/dist/configure/services/tailordb/permission.d.mts +103 -0
  159. package/dist/configure/services/tailordb/schema.d.mts +486 -0
  160. package/dist/configure/services/tailordb/types.d.mts +198 -0
  161. package/dist/configure/services/workflow/execution-policy.d.mts +70 -0
  162. package/dist/configure/services/workflow/execution-policy.types.d.mts +103 -0
  163. package/dist/configure/services/workflow/index.d.mts +9 -0
  164. package/dist/configure/services/workflow/job.d.mts +83 -0
  165. package/dist/configure/services/workflow/types.d.mts +2 -0
  166. package/dist/configure/services/workflow/wait-point.d.mts +72 -0
  167. package/dist/configure/services/workflow/workflow.d.mts +56 -0
  168. package/dist/configure/types/aigateway-name.d.mts +12 -0
  169. package/dist/configure/types/connection-name.d.mts +12 -0
  170. package/dist/configure/types/field.d.mts +8 -0
  171. package/dist/configure/types/field.types.d.mts +70 -0
  172. package/dist/configure/types/idp-name.d.mts +12 -0
  173. package/dist/configure/types/index.d.mts +5 -0
  174. package/dist/configure/types/machine-user.d.mts +2 -0
  175. package/dist/configure/types/permission-operand.types.d.mts +20 -0
  176. package/dist/configure/types/type.d.mts +73 -0
  177. package/dist/{context-Bd266-ru.mjs → context-DYQVYWqZ.mjs} +4 -5
  178. package/dist/context-DYQVYWqZ.mjs.map +1 -0
  179. package/dist/{crashreport-BsjAkFWw.mjs → crashreport-B5LqCTfF.mjs} +10 -11
  180. package/dist/{crashreport-BsjAkFWw.mjs.map → crashreport-B5LqCTfF.mjs.map} +1 -1
  181. package/dist/{crashreport-pr6Rhvza.mjs → crashreport-eI7ty7ok.mjs} +1 -1
  182. package/dist/enum-constants-j9QBF0cB.mjs.map +1 -1
  183. package/dist/{errors-Dtf2WPaW.mjs → errors-D7583Zz7.mjs} +18 -2
  184. package/dist/errors-D7583Zz7.mjs.map +1 -0
  185. package/dist/{file-_oUZo76X.mjs → file-BUcmVIH2.mjs} +12 -22
  186. package/dist/file-BUcmVIH2.mjs.map +1 -0
  187. package/dist/{file-utils-DcyIPFQh.mjs → file-utils-yEiIS4nJ.mjs} +6 -6
  188. package/dist/file-utils-yEiIS4nJ.mjs.map +1 -0
  189. package/dist/{globals-Crz8o65k.mjs → globals-DQotNuwK.mjs} +33 -55
  190. package/dist/globals-DQotNuwK.mjs.map +1 -0
  191. package/dist/iconv-QWaZh0TT.mjs +38 -0
  192. package/dist/iconv-QWaZh0TT.mjs.map +1 -0
  193. package/dist/{idp-BDbK5gjm.mjs → idp-RA_swu-h.mjs} +12 -5
  194. package/dist/idp-RA_swu-h.mjs.map +1 -0
  195. package/dist/{interceptor-D-q1rvRl.mjs → interceptor-e33JtsC-.mjs} +2 -2
  196. package/dist/interceptor-e33JtsC-.mjs.map +1 -0
  197. package/dist/kysely/index.d.mts +5 -7
  198. package/dist/{kysely-type-DR8uzZTA.mjs → kysely-type-DqIRgDYR.mjs} +5 -4
  199. package/dist/kysely-type-DqIRgDYR.mjs.map +1 -0
  200. package/dist/logger-BtX0suGY.mjs +48 -0
  201. package/dist/logger-BtX0suGY.mjs.map +1 -0
  202. package/dist/logger-CXQq9YIp.mjs +317 -0
  203. package/dist/logger-CXQq9YIp.mjs.map +1 -0
  204. package/dist/parser/service/auth/index.d.mts +1 -0
  205. package/dist/parser/service/auth/schema.d.mts +3 -0
  206. package/dist/parser/service/http-adapter/index.d.mts +1 -0
  207. package/dist/parser/service/http-adapter/schema.d.mts +1 -0
  208. package/dist/parser/service/idp/types.d.mts +5 -0
  209. package/dist/parser/service/tailordb/type-source.d.mts +10 -0
  210. package/dist/parser/service/tailordb/types.d.mts +131 -0
  211. package/dist/platform-serialize-RoRtBS0v.mjs +46 -0
  212. package/dist/platform-serialize-RoRtBS0v.mjs.map +1 -0
  213. package/dist/plugin/builtin/enum-constants/index.d.mts +15 -1
  214. package/dist/plugin/builtin/file-utils/index.d.mts +15 -1
  215. package/dist/plugin/builtin/file-utils/index.mjs +1 -1
  216. package/dist/plugin/builtin/kysely-type/index.d.mts +15 -1
  217. package/dist/plugin/builtin/kysely-type/index.mjs +1 -1
  218. package/dist/plugin/builtin/seed/index.d.mts +46 -2
  219. package/dist/plugin/builtin/seed/index.mjs +1 -1
  220. package/dist/plugin/builtin/seed/seed-type-processor.d.mts +19 -0
  221. package/dist/plugin/builtin/seed/types.d.mts +2 -0
  222. package/dist/plugin/get-generated-type.d.mts +16 -0
  223. package/dist/plugin/index.d.mts +3 -117
  224. package/dist/plugin/index.mjs +1 -1
  225. package/dist/plugin/index.mjs.map +1 -1
  226. package/dist/plugin/manager.d.mts +2 -0
  227. package/dist/plugin/types.d.mts +242 -0
  228. package/dist/plugin/with-context.d.mts +101 -0
  229. package/dist/{runtime-n9NCkjee.mjs → register-ts-hook-BAHMwxfG.mjs} +7812 -4094
  230. package/dist/register-ts-hook-BAHMwxfG.mjs.map +1 -0
  231. package/dist/{registry-DdsYlL_P.mjs → registry-BIGVUrMB.mjs} +12 -9
  232. package/dist/registry-BIGVUrMB.mjs.map +1 -0
  233. package/dist/{repl-editor-DmGr9zMw.mjs → repl-editor-BCozyiNq.mjs} +6 -5
  234. package/dist/{repl-editor-DmGr9zMw.mjs.map → repl-editor-BCozyiNq.mjs.map} +1 -1
  235. package/dist/runtime/aigateway.d.mts +25 -0
  236. package/dist/runtime/aigateway.mjs +3 -0
  237. package/dist/runtime/authconnection.d.mts +21 -2
  238. package/dist/runtime/authconnection.mjs +2 -2
  239. package/dist/runtime/context.d.mts +54 -2
  240. package/dist/runtime/context.mjs +2 -2
  241. package/dist/runtime/field-parse.d.mts +10 -0
  242. package/dist/runtime/file.d.mts +170 -2
  243. package/dist/runtime/file.mjs +2 -2
  244. package/dist/runtime/globals.d.mts +38 -20
  245. package/dist/runtime/iconv.d.mts +73 -2
  246. package/dist/runtime/iconv.mjs +2 -2
  247. package/dist/runtime/idp.d.mts +129 -2
  248. package/dist/runtime/idp.mjs +2 -2
  249. package/dist/runtime/index.d.mts +48 -9
  250. package/dist/runtime/index.mjs +10 -8
  251. package/dist/runtime/logger.d.mts +98 -0
  252. package/dist/runtime/logger.mjs +3 -0
  253. package/dist/runtime/secretmanager.d.mts +41 -2
  254. package/dist/runtime/secretmanager.mjs +2 -2
  255. package/dist/runtime/types.d.mts +25 -0
  256. package/dist/runtime/workflow.d.mts +124 -2
  257. package/dist/runtime/workflow.mjs +2 -2
  258. package/dist/{schema-BhkpP5Hw.mjs → schema--xYWRGfe.mjs} +288 -229
  259. package/dist/schema--xYWRGfe.mjs.map +1 -0
  260. package/dist/{secret-file-DBqZhjFQ.mjs → secret-file-C3J4Gy8r.mjs} +2 -2
  261. package/dist/{secret-file-DBqZhjFQ.mjs.map → secret-file-C3J4Gy8r.mjs.map} +1 -1
  262. package/dist/secretmanager-CYlpffsz.mjs +13 -0
  263. package/dist/secretmanager-CYlpffsz.mjs.map +1 -0
  264. package/dist/secretmanager-IY4UvinW.mjs +131 -0
  265. package/dist/secretmanager-IY4UvinW.mjs.map +1 -0
  266. package/dist/seed/index.d.mts +4 -4
  267. package/dist/seed-LUVr7jHL.mjs +444 -0
  268. package/dist/seed-LUVr7jHL.mjs.map +1 -0
  269. package/dist/{service-DU1mVzri.mjs → service-B5WynBHQ.mjs} +3 -3
  270. package/dist/{service-DU1mVzri.mjs.map → service-B5WynBHQ.mjs.map} +1 -1
  271. package/dist/service-BNtPsK9Q.mjs +837 -0
  272. package/dist/service-BNtPsK9Q.mjs.map +1 -0
  273. package/dist/service-D5jn05ZI.mjs +3 -0
  274. package/dist/service_pb-BwZRiNug.mjs +167 -0
  275. package/dist/service_pb-BwZRiNug.mjs.map +1 -0
  276. package/dist/service_pb-wRkxUta6.mjs +3 -0
  277. package/dist/tailor-proto/src/tailor/v1/aigateway_pb.d.mts +203 -0
  278. package/dist/tailor-proto/src/tailor/v1/aigateway_resource_pb.d.mts +57 -0
  279. package/dist/tailor-proto/src/tailor/v1/application_pb.d.mts +315 -0
  280. package/dist/tailor-proto/src/tailor/v1/application_resource_pb.d.mts +160 -0
  281. package/dist/tailor-proto/src/tailor/v1/auth_pb.d.mts +2069 -0
  282. package/dist/tailor-proto/src/tailor/v1/auth_resource_pb.d.mts +865 -0
  283. package/dist/tailor-proto/src/tailor/v1/events_pb.d.mts +111 -0
  284. package/dist/tailor-proto/src/tailor/v1/events_resource_pb.d.mts +68 -0
  285. package/dist/tailor-proto/src/tailor/v1/executor_pb.d.mts +438 -0
  286. package/dist/tailor-proto/src/tailor/v1/executor_resource_pb.d.mts +563 -0
  287. package/dist/tailor-proto/src/tailor/v1/function_pb.d.mts +144 -0
  288. package/dist/tailor-proto/src/tailor/v1/function_registry_pb.d.mts +450 -0
  289. package/dist/tailor-proto/src/tailor/v1/function_resource_pb.d.mts +191 -0
  290. package/dist/tailor-proto/src/tailor/v1/http_adapter_resource_pb.d.mts +49 -0
  291. package/dist/tailor-proto/src/tailor/v1/idp_pb.d.mts +406 -0
  292. package/dist/tailor-proto/src/tailor/v1/idp_resource_pb.d.mts +429 -0
  293. package/dist/tailor-proto/src/tailor/v1/metadata_pb.d.mts +72 -0
  294. package/dist/tailor-proto/src/tailor/v1/metadata_resource_pb.d.mts +16 -0
  295. package/dist/tailor-proto/src/tailor/v1/meter_pb.d.mts +308 -0
  296. package/dist/tailor-proto/src/tailor/v1/pipeline_pb.d.mts +590 -0
  297. package/dist/tailor-proto/src/tailor/v1/pipeline_resource_pb.d.mts +329 -0
  298. package/dist/tailor-proto/src/tailor/v1/resource_pb.d.mts +112 -0
  299. package/dist/tailor-proto/src/tailor/v1/secret_manager_pb.d.mts +345 -0
  300. package/dist/tailor-proto/src/tailor/v1/secret_manager_resource_pb.d.mts +53 -0
  301. package/dist/tailor-proto/src/tailor/v1/service_pb.d.mts +3575 -0
  302. package/dist/tailor-proto/src/tailor/v1/stateflow_pb.d.mts +186 -0
  303. package/dist/tailor-proto/src/tailor/v1/stateflow_resource_pb.d.mts +28 -0
  304. package/dist/tailor-proto/src/tailor/v1/staticwebsite_pb.d.mts +428 -0
  305. package/dist/tailor-proto/src/tailor/v1/staticwebsite_resource_pb.d.mts +89 -0
  306. package/dist/tailor-proto/src/tailor/v1/tailordb_pb.d.mts +683 -0
  307. package/dist/tailor-proto/src/tailor/v1/tailordb_resource_pb.d.mts +796 -0
  308. package/dist/tailor-proto/src/tailor/v1/telemetryrouter_pb.d.mts +329 -0
  309. package/dist/tailor-proto/src/tailor/v1/telemetryrouter_resource_pb.d.mts +182 -0
  310. package/dist/tailor-proto/src/tailor/v1/workflow_pb.d.mts +861 -0
  311. package/dist/tailor-proto/src/tailor/v1/workflow_resource_pb.d.mts +309 -0
  312. package/dist/tailor-proto/src/tailor/v1/workspace_pb.d.mts +2014 -0
  313. package/dist/tailor-proto/src/tailor/v1/workspace_resource_pb.d.mts +482 -0
  314. package/dist/{telemetry-CdqJEzkj.mjs → telemetry-BRVdwh14.mjs} +3 -3
  315. package/dist/telemetry-BRVdwh14.mjs.map +1 -0
  316. package/dist/telemetry-CkbkeJxl.mjs +3 -0
  317. package/dist/test-env-key-D7UkZp99.mjs +75 -0
  318. package/dist/test-env-key-D7UkZp99.mjs.map +1 -0
  319. package/dist/types/aigateway.generated.d.mts +12 -0
  320. package/dist/types/app-config.generated.d.mts +4 -0
  321. package/dist/types/auth-connection.generated.d.mts +33 -0
  322. package/dist/types/auth.generated.d.mts +188 -0
  323. package/dist/types/executor.generated.d.mts +209 -0
  324. package/dist/types/helpers.d.mts +40 -0
  325. package/dist/types/http-adapter.generated.d.mts +28 -0
  326. package/dist/types/idp.generated.d.mts +626 -0
  327. package/dist/types/resolver.generated.d.mts +82 -0
  328. package/dist/types/secrets.generated.d.mts +14 -0
  329. package/dist/types/staticwebsite.generated.d.mts +14 -0
  330. package/dist/types/tailordb.generated.d.mts +468 -0
  331. package/dist/types/workflow.generated.d.mts +17 -0
  332. package/dist/user-agent-Bgsszb5I.mjs +28 -0
  333. package/dist/user-agent-Bgsszb5I.mjs.map +1 -0
  334. package/dist/utils/test/index.d.mts +6 -100
  335. package/dist/utils/test/index.mjs +60 -39
  336. package/dist/utils/test/index.mjs.map +1 -1
  337. package/dist/utils/test/mock.d.mts +86 -0
  338. package/dist/vitest/environment.d.mts +1 -2
  339. package/dist/vitest/environment.mjs +2 -2
  340. package/dist/vitest/environment.mjs.map +1 -1
  341. package/dist/vitest/index.d.mts +15 -429
  342. package/dist/vitest/index.mjs +1240 -31
  343. package/dist/vitest/index.mjs.map +1 -1
  344. package/dist/vitest/mock-kysely.d.mts +61 -0
  345. package/dist/vitest/mock.d.mts +10 -0
  346. package/dist/vitest/mocks/aigateway.d.mts +40 -0
  347. package/dist/vitest/mocks/authconnection.d.mts +38 -0
  348. package/dist/vitest/mocks/file.d.mts +58 -0
  349. package/dist/vitest/mocks/iconv.d.mts +51 -0
  350. package/dist/vitest/mocks/idp.d.mts +60 -0
  351. package/dist/vitest/mocks/logger.d.mts +45 -0
  352. package/dist/vitest/mocks/secretmanager.d.mts +44 -0
  353. package/dist/vitest/mocks/tailordb.d.mts +115 -0
  354. package/dist/vitest/mocks/workflow.d.mts +157 -0
  355. package/dist/vitest/setup.d.mts +1 -2
  356. package/dist/vitest/setup.mjs +2 -2
  357. package/dist/vitest/workflow-local.d.mts +41 -0
  358. package/dist/workflow-CsaQ9qK-.mjs +42 -0
  359. package/dist/workflow-CsaQ9qK-.mjs.map +1 -0
  360. package/dist/{client-z_oHGVNy.mjs → workspace_resource_pb-UGK1SSn_.mjs} +55 -619
  361. package/dist/workspace_resource_pb-UGK1SSn_.mjs.map +1 -0
  362. package/docs/cli/application.md +150 -250
  363. package/docs/cli/auth.md +51 -295
  364. package/docs/cli/completion.md +1 -25
  365. package/docs/cli/crashreport.md +3 -61
  366. package/docs/cli/executor.md +72 -183
  367. package/docs/cli/function.md +16 -132
  368. package/docs/cli/organization.md +11 -221
  369. package/docs/cli/plugin.md +29 -0
  370. package/docs/cli/query.md +2 -22
  371. package/docs/cli/secret.md +71 -251
  372. package/docs/cli/setup.md +138 -40
  373. package/docs/cli/skills.md +50 -39
  374. package/docs/cli/staticwebsite.md +32 -180
  375. package/docs/cli/tailordb.md +71 -427
  376. package/docs/cli/upgrade.md +2 -22
  377. package/docs/cli/user.md +78 -247
  378. package/docs/cli/workflow.md +150 -172
  379. package/docs/cli/workspace.md +167 -538
  380. package/docs/cli-reference.md +213 -96
  381. package/docs/configuration.md +40 -6
  382. package/docs/github-actions.md +72 -24
  383. package/docs/migration/v2.md +1316 -0
  384. package/docs/multi-environment.md +29 -7
  385. package/docs/plugin/custom.md +4 -4
  386. package/docs/plugin/index.md +8 -8
  387. package/docs/quickstart.md +8 -7
  388. package/docs/runtime.md +18 -9
  389. package/docs/services/aigateway.md +20 -2
  390. package/docs/services/auth.md +51 -59
  391. package/docs/services/executor.md +8 -3
  392. package/docs/services/http-adapter.md +16 -1
  393. package/docs/services/idp.md +55 -2
  394. package/docs/services/resolver.md +62 -8
  395. package/docs/services/secret.md +11 -11
  396. package/docs/services/staticwebsite.md +8 -2
  397. package/docs/services/tailordb-migration.md +43 -28
  398. package/docs/services/tailordb.md +200 -99
  399. package/docs/services/workflow.md +133 -55
  400. package/docs/testing.md +244 -143
  401. package/package.json +59 -46
  402. package/postinstall.mjs +4 -6
  403. package/dist/application-DB2r36Et.mjs +0 -3
  404. package/dist/application-DqS1yBg3.mjs.map +0 -1
  405. package/dist/authconnection-D2MhtTN5.mjs +0 -15
  406. package/dist/authconnection-D2MhtTN5.mjs.map +0 -1
  407. package/dist/authconnection-DvUQAjQS.d.mts +0 -39
  408. package/dist/cli/erd-viewer-assets/app.js +0 -1181
  409. package/dist/cli/erd-viewer-assets/index.html +0 -73
  410. package/dist/cli/erd-viewer-assets/serve.json +0 -13
  411. package/dist/cli/erd-viewer-assets/styles.css +0 -789
  412. package/dist/cli/index.d.mts +0 -5
  413. package/dist/cli/index.mjs.map +0 -1
  414. package/dist/client-Dbohmtkv.mjs +0 -3
  415. package/dist/client-z_oHGVNy.mjs.map +0 -1
  416. package/dist/context-Bd266-ru.mjs.map +0 -1
  417. package/dist/context-BuuIb8CC.d.mts +0 -68
  418. package/dist/errors-Dtf2WPaW.mjs.map +0 -1
  419. package/dist/field-DOsJCPFa.mjs +0 -22
  420. package/dist/field-DOsJCPFa.mjs.map +0 -1
  421. package/dist/file-BB8Vs9O_.d.mts +0 -250
  422. package/dist/file-_oUZo76X.mjs.map +0 -1
  423. package/dist/file-utils-DcyIPFQh.mjs.map +0 -1
  424. package/dist/globals-Crz8o65k.mjs.map +0 -1
  425. package/dist/http-adapter.generated-WgMnb7Sb.d.mts +0 -580
  426. package/dist/iconv-Co-TOPuH.d.mts +0 -122
  427. package/dist/iconv-D2vi8G36.mjs +0 -63
  428. package/dist/iconv-D2vi8G36.mjs.map +0 -1
  429. package/dist/idp-BDbK5gjm.mjs.map +0 -1
  430. package/dist/idp-DrhVrLmV.d.mts +0 -160
  431. package/dist/index-5vPyRu1y.d.mts +0 -18
  432. package/dist/index-B7AKc18V.d.mts +0 -47
  433. package/dist/index-BlpzXncY.d.mts +0 -1016
  434. package/dist/index-CK7u9isy.d.mts +0 -46
  435. package/dist/index-CNYe5lnW.d.mts +0 -18
  436. package/dist/index-DjUdWlzf.d.mts +0 -18
  437. package/dist/index-ZePLwxw7.d.mts +0 -208
  438. package/dist/interceptor-D-q1rvRl.mjs.map +0 -1
  439. package/dist/job-fuc3j1Ma.mjs +0 -53
  440. package/dist/job-fuc3j1Ma.mjs.map +0 -1
  441. package/dist/kysely-type-DR8uzZTA.mjs.map +0 -1
  442. package/dist/logger-CxF-Ex5d.mjs +0 -220
  443. package/dist/logger-CxF-Ex5d.mjs.map +0 -1
  444. package/dist/mock-BjFj5o1I.mjs +0 -804
  445. package/dist/mock-BjFj5o1I.mjs.map +0 -1
  446. package/dist/registry-DdsYlL_P.mjs.map +0 -1
  447. package/dist/rolldown-runtime-DXywRVcq.mjs +0 -20
  448. package/dist/runtime-n9NCkjee.mjs.map +0 -1
  449. package/dist/schema-BhkpP5Hw.mjs.map +0 -1
  450. package/dist/secretmanager-B3n4KHfm.d.mts +0 -55
  451. package/dist/secretmanager-BVxw3ih_.mjs +0 -24
  452. package/dist/secretmanager-BVxw3ih_.mjs.map +0 -1
  453. package/dist/seed-jf3008-h.mjs +0 -1160
  454. package/dist/seed-jf3008-h.mjs.map +0 -1
  455. package/dist/service-CCL8ruDf.mjs +0 -459
  456. package/dist/service-CCL8ruDf.mjs.map +0 -1
  457. package/dist/service-D6yonf2I.mjs +0 -3
  458. package/dist/telemetry-CdqJEzkj.mjs.map +0 -1
  459. package/dist/telemetry-ClwW5ohF.mjs +0 -3
  460. package/dist/test-env-key-D9kM6ETE.mjs +0 -49
  461. package/dist/test-env-key-D9kM6ETE.mjs.map +0 -1
  462. package/dist/types-B2RpYyA_.mjs +0 -371
  463. package/dist/types-B2RpYyA_.mjs.map +0 -1
  464. package/dist/types-ClhIrW_C.mjs +0 -4
  465. package/dist/types-DCUhgpyI.d.mts +0 -784
  466. package/dist/types-DhO_VEZd.d.mts +0 -574
  467. package/dist/types-DwDgacni.d.mts +0 -338
  468. package/dist/workflow-BbKvGLQg.d.mts +0 -96
  469. package/dist/workflow-DgemCAz3.mjs +0 -38
  470. package/dist/workflow-DgemCAz3.mjs.map +0 -1
  471. package/dist/workflow.generated-DtQwEo-x.d.mts +0 -671
package/docs/testing.md CHANGED
@@ -11,22 +11,22 @@ Lean on unit tests for the day-to-day feedback loop — they run fast and exerci
11
11
 
12
12
  Unit-test entrypoints exposed by the SDK:
13
13
 
14
- - `resolver.body({ input, user, env })` — invoke a resolver
15
- - `workflowJob.body(input, { env })` — invoke a workflow job body directly
16
- - `workflowJob.trigger(input)` — chain a workflow job through the workflow runtime
14
+ - `resolver.body({ input, caller, invoker, env })` — invoke a resolver
15
+ - `workflowJob.body(input, { env, invoker })` — invoke a workflow job body directly
16
+ - `workflowJob.start(input)` — chain a workflow job through the workflow runtime
17
17
  - `runWorkflowLocally(workflow, args)` — run a workflow chain locally with real job bodies
18
- - `executor.operation.body(args)` — invoke a function-kind executor
18
+ - `executor.operation.body({ ...args, invoker })` — invoke a function-kind executor
19
19
 
20
- Helpers under `@tailor-platform/sdk/test`:
20
+ For anonymous direct calls:
21
21
 
22
- - `unauthenticatedTailorUser` default `user` value for resolver contexts
22
+ - Pass `null` for anonymous `caller` / `invoker` context in direct unit tests.
23
23
 
24
24
  Platform API mocks under `@tailor-platform/sdk/vitest` (for use with the [`tailor-runtime` Vitest environment](#runtime-environment-emulation-beta) below):
25
25
 
26
26
  - `mockTailordb` — TailorDB query stubs and call recording
27
27
  - `mockWorkflow` — `tailor.workflow` job / wait / resolve mocks
28
28
  - `runWorkflowLocally` — local full-chain workflow runner
29
- - `mockSecretmanager`, `mockAuthconnection`, `mockIdp`, `mockFile`, `mockIconv` — corresponding platform API mocks
29
+ - `mockSecretmanager`, `mockAuthconnection`, `mockIdp`, `mockFile`, `mockIconv`, `mockAigateway`, `mockLogger` — corresponding platform API mocks
30
30
 
31
31
  For tighter alignment with the production runtime — Node.js module blocking, Web-only globals, and platform API mocks — pair the resolver helpers with the [`tailor-runtime` Vitest environment](#runtime-environment-emulation-beta) below.
32
32
 
@@ -63,25 +63,30 @@ export default defineConfig({
63
63
 
64
64
  ### Acquiring mocks with `using`
65
65
 
66
- Each mock controller (`mockTailordb`, `mockWorkflow`, `mockSecretmanager`, `mockAuthconnection`, `mockIdp`, `mockFile`, `mockIconv`) is a **factory function**. Acquire it inside a test with a [`using` declaration](https://github.com/tc39/proposal-explicit-resource-management) — its state is reset automatically when the test scope exits, so you no longer need `beforeEach(() => mock.reset())`:
66
+ Each mock controller (`mockTailordb`, `mockWorkflow`, `mockSecretmanager`, `mockAuthconnection`, `mockIdp`, `mockFile`, `mockIconv`, `mockAigateway`, `mockLogger`) is a **factory function**. Acquire it inside a test with a [`using` declaration](https://github.com/tc39/proposal-explicit-resource-management) — its state is reset automatically when the test scope exits, so you no longer need `beforeEach(() => mock.reset())`:
67
67
 
68
68
  ```typescript
69
69
  import { mockTailordb } from "@tailor-platform/sdk/vitest";
70
70
 
71
71
  test("...", () => {
72
72
  using db = mockTailordb();
73
- db.enqueueResult({ age: 30 });
73
+ db.onQuery(/SELECT age/).returnsRows([{ age: 30 }]);
74
74
  // …
75
75
  }); // reset automatically here
76
76
  ```
77
77
 
78
- The mock functions are also exposed directly (e.g. `db.queryObject`, `wf.triggerJobFunction`) so you can assert on them with `expect(...).toHaveBeenCalledWith(...)`.
78
+ Runtime operations are exposed as typed Vitest mocks wherever the platform API has a stable operation shape. For example, use `file.download.mockResolvedValue(...)`, `iconv.decode.mockReturnValue(...)`, or `wf.job(myJob).mockResolvedValue(...)`, then assert with native Vitest matchers. Service-specific helpers cover stateful fixtures and query matching.
79
+
80
+ Every controller provides two lifecycle methods when manual reuse is useful:
81
+
82
+ - `clear()` removes call history but preserves configured behavior.
83
+ - `reset()` removes call history and configured behavior, restoring the controller's default behavior.
79
84
 
80
85
  > **Requirements:** `using` requires TypeScript ≥ 5.2 and a runtime that provides `Symbol.dispose` (Node ≥ 20.4 — the SDK already targets Node ≥ 22, and Vitest's transformer downlevels the syntax for you).
81
86
  >
82
87
  > **Acquire what you use:** a namespace is only mocked while you hold it with `using`, so code under test that calls a platform API (e.g. `tailor.workflow`, `tailordb.Client`) must run inside a test that has acquired the matching `mockX()`. The error classes and `tailor.context` are always present.
83
88
  >
84
- > **Seeded secrets survive:** secrets seeded from `tailor.config.ts` stay available across tests; a per-test `mockSecretmanager().setSecrets(...)` override applies only within that test.
89
+ > **Seeded secrets survive:** secrets seeded from `tailor.config.ts` stay available across tests; per-test fixtures passed to `mockSecretmanager({ secrets: ... })` apply only within that test.
85
90
 
86
91
  ### TailorDB Mock
87
92
 
@@ -92,14 +97,19 @@ import { mockTailordb } from "@tailor-platform/sdk/vitest";
92
97
 
93
98
  test("resolver queries the database", async () => {
94
99
  using db = mockTailordb();
95
- // Order-based: stage rows for each upcoming query in one call
96
- db.enqueueResults(
100
+ // Use an explicit queue when transaction order is part of the test.
101
+ db.enqueueRows(
97
102
  [], // BEGIN (empty result)
98
103
  [{ age: 30 }], // SELECT (one row)
99
104
  [], // COMMIT
100
105
  );
101
106
 
102
- const result = await resolver.body({ input: { email: "test@example.com" } });
107
+ const result = await resolver.body({
108
+ input: { email: "test@example.com" },
109
+ caller: null,
110
+ invoker: null,
111
+ env: {},
112
+ });
103
113
 
104
114
  expect(result).toEqual({ oldAge: 30, newAge: 31 });
105
115
  expect(db.executedQueries).toHaveLength(3);
@@ -107,75 +117,85 @@ test("resolver queries the database", async () => {
107
117
  });
108
118
  ```
109
119
 
110
- Three response modes:
111
-
112
- - **`enqueueResult(...rows)`** — Order-based, single query. Arguments are the row objects returned by the next `queryObject` call (`enqueueResult()` for empty, `enqueueResult({ id: "1" })` for one row, `enqueueResult({ a: 1 }, { a: 2 })` for multiple rows). Consumed in FIFO order.
113
- - **`enqueueResults(...rowsArrays)`** — Order-based, multiple queries. Each argument is a rows array for one upcoming query. Equivalent to calling `enqueueResult` for each entry but easier to read for transactional sequences.
114
- - **`setQueryResolver((query, params) => rows)`** — Content-based fallback. Called when the queue is empty.
120
+ Match queries by SQL text, a regular expression, SQL plus parameters, or a predicate. The most recently registered matcher wins:
115
121
 
116
122
  ```typescript
117
123
  test("content-based mock", async () => {
118
124
  using db = mockTailordb();
119
- db.setQueryResolver((query) => {
120
- if (query.includes("SELECT")) return [{ id: "1", name: "test" }];
121
- return [];
125
+ db.onQuery({ sql: /FROM users/i, params: ["1"] }).returnsRows([{ id: "1", name: "test" }]);
126
+ db.onQuery(/FROM audit_logs/i)
127
+ .returnsRowsOnce([{ id: "first" }])
128
+ .returnsRows([{ id: "later" }]);
129
+
130
+ const result = await resolver.body({
131
+ input: { userId: "1" },
132
+ caller: null,
133
+ invoker: null,
134
+ env: {},
122
135
  });
123
136
 
124
- const result = await resolver.body({ input: { userId: "1" } });
125
-
126
137
  expect(db.executedQueries[0].query).toContain("SELECT");
127
138
  });
128
139
  ```
129
140
 
141
+ Within one `mockTailordb()` instance, use either `onQuery()` matchers or a direct `queryObject.mockImplementation()` override. A direct override replaces matcher-based behavior, so do not combine the two styles.
142
+
143
+ `returnsRowsOnce` and `rejectsOnce` configure one-time responses before the persistent `returnsRows` or `rejects` response. `enqueueRows(...rowArrays)` remains available for transaction sequences whose exact call order is under test. The existing `enqueueResult`, `enqueueResults`, and `setQueryResolver` helpers remain supported for compatibility.
144
+
145
+ Pass `{ onUnhandled: "error" }` to make an unmatched query fail instead of returning an empty result.
146
+
130
147
  ### Workflow Mock
131
148
 
132
- Workflow job `.trigger()` calls use the platform workflow runtime. Acquire `mockWorkflow()` when you want to provide trigger responses with `setJobHandler` / `enqueueResult` or assert on `triggeredJobs`. If no response is configured, the mock throws so missing job mocks fail loudly:
149
+ Workflow job `.start()` calls use the platform workflow runtime. Acquire `mockWorkflow()` when you want to provide start responses with `setJobHandler` / `enqueueResult` or assert on `startedJobs`. If no response is configured, the mock throws so missing job mocks fail loudly. Use `job(definition)` or `workflow(definition)` to get a stable, fully typed Vitest mock for one definition:
133
150
 
134
151
  ```typescript
135
152
  import { mockWorkflow } from "@tailor-platform/sdk/vitest";
153
+ import { processPayment, validateOrder } from "./jobs";
136
154
 
137
- test("workflow triggers jobs", async () => {
155
+ test("workflow starts jobs", async () => {
138
156
  using wf = mockWorkflow();
139
- wf.setJobHandler((jobName, args) => {
140
- if (jobName === "validate-order") return { valid: true };
141
- if (jobName === "process-payment") return { txnId: "txn-1" };
142
- return null;
143
- });
157
+ const validate = wf.job(validateOrder);
158
+ const payment = wf.job(processPayment);
159
+ validate.mockResolvedValue({ valid: true });
160
+ payment.mockResolvedValue({ txnId: "txn-1" });
144
161
 
145
162
  const result = await main({ input: { orderId: "o-1" } });
146
163
 
147
- expect(wf.triggeredJobs).toEqual([
148
- { jobName: "validate-order", args: { orderId: "o-1" } },
149
- { jobName: "process-payment", args: { orderId: "o-1" } },
150
- ]);
164
+ expect(validate).toHaveBeenCalledWith({ orderId: "o-1" });
165
+ expect(payment).toHaveBeenCalledWith({ orderId: "o-1" });
151
166
  });
152
167
  ```
153
168
 
154
- `mockWorkflow()` also supports order-based responses:
169
+ Unconfigured definition mocks continue to run their real implementations. The lower-level `execJobFunction`, `startWorkflow`, `resumeWorkflowExecution`, `wait`, and `resolve` mocks and the existing `setJobHandler`, `enqueueResult`, `enqueueResults`, and call-record helpers remain available.
170
+
171
+ Use `waitPoint(definition)` for typed wait-point control:
155
172
 
156
173
  ```typescript
157
174
  using wf = mockWorkflow();
175
+ const approvalMock = wf.waitPoint(approvalWaitPoint);
158
176
 
159
- // Single response for the next triggerJobFunction call
160
- wf.enqueueResult({ valid: true });
177
+ approvalMock.wait.mockResolvedValue({ approved: true });
178
+ await approvalWaitPoint.wait({ message: "Please approve" });
161
179
 
162
- // Multiple responses for subsequent calls (FIFO)
163
- wf.enqueueResults({ valid: true }, { txnId: "txn-1" });
180
+ expect(approvalMock.wait).toHaveBeenCalledWith({ message: "Please approve" });
164
181
  ```
165
182
 
183
+ Use `wf.setEnv(...)` when locally-run workflow job bodies need configuration values. Per-run `runWorkflowLocally(..., { env })` options take precedence over the mock's env.
184
+
166
185
  ### SecretManager Mock
167
186
 
168
187
  ```typescript
169
188
  import { mockSecretmanager } from "@tailor-platform/sdk/vitest";
170
189
 
171
190
  test("reads secrets from vault", async () => {
172
- using sm = mockSecretmanager();
173
- sm.setSecrets({
174
- "my-vault": { API_KEY: "sk-123", DB_PASS: "secret" },
191
+ using sm = mockSecretmanager({
192
+ secrets: { "my-vault": { API_KEY: "sk-123" } },
175
193
  });
194
+ sm.setSecret("my-vault", "API_KEY", "override");
195
+ sm.mergeSecrets("my-vault", { DB_PASS: "secret" });
176
196
 
177
197
  const key = await tailor.secretmanager.getSecret("my-vault", "API_KEY");
178
- expect(key).toBe("sk-123");
198
+ expect(key).toBe("override");
179
199
  expect(sm.calls).toEqual([{ method: "getSecret", vault: "my-vault", name: "API_KEY" }]);
180
200
  });
181
201
  ```
@@ -186,65 +206,65 @@ test("reads secrets from vault", async () => {
186
206
  import { mockAuthconnection } from "@tailor-platform/sdk/vitest";
187
207
 
188
208
  test("returns configured token", async () => {
189
- using ac = mockAuthconnection();
190
- ac.setTokens({
191
- google: { access_token: "ya29.xxx", expires_in: 3600 },
209
+ using ac = mockAuthconnection({
210
+ tokens: { google: { access_token: "ya29.xxx" } },
211
+ onUnhandled: "error",
192
212
  });
213
+ ac.setToken("google", { access_token: "replacement" });
193
214
 
194
215
  const token = await tailor.authconnection.getConnectionToken("google");
195
- expect(token.access_token).toBe("ya29.xxx");
216
+ expect(token.access_token).toBe("replacement");
196
217
  });
197
218
  ```
198
219
 
199
- When no token is configured for a connection, it returns `{ access_token: "mock-token" }`.
220
+ By default, an unconfigured connection returns `{ access_token: "mock-token" }`. Pass `onUnhandled: "error"` to fail instead.
200
221
 
201
222
  ### IDP Mock
202
223
 
203
224
  ```typescript
204
225
  import { mockIdp } from "@tailor-platform/sdk/vitest";
205
226
 
206
- test("resolver-based", async () => {
207
- using idp = mockIdp();
208
- idp.setResolver((method, args) => {
209
- if (method === "user") return { id: "u-1", name: "alice", disabled: false };
210
- return null; // falls back to defaults
227
+ test("namespace-specific mock", async () => {
228
+ using idp = mockIdp({ onUnhandled: "error" });
229
+ const customerIdp = idp.namespace("my-ns");
230
+ customerIdp.user.mockResolvedValue({
231
+ id: "u-1",
232
+ name: "alice",
233
+ disabled: false,
234
+ mfaEnrolled: false,
235
+ mfaFactorIds: [],
211
236
  });
212
237
 
213
238
  const client = new tailor.idp.Client({ namespace: "my-ns" });
214
239
  const user = await client.user("u-1");
215
240
  expect(user.name).toBe("alice");
216
- });
217
-
218
- test("queue-based", async () => {
219
- using idp = mockIdp();
220
- idp.enqueueResult({ id: "u-1", name: "alice", disabled: false });
221
-
222
- const client = new tailor.idp.Client({ namespace: "my-ns" });
223
- const user = await client.user("u-1");
224
- expect(user.name).toBe("alice");
225
- expect(idp.calls).toMatchObject([{ method: "user", namespace: "my-ns" }]);
241
+ expect(customerIdp.user).toHaveBeenCalledWith("u-1");
226
242
  });
227
243
  ```
228
244
 
245
+ Each namespace exposes typed mocks for `users`, `user`, `userByName`, `createUser`, `updateUser`, `deleteUser`, `sendPasswordResetEmail`, and `unenrollMfa`. The existing resolver, queue, and aggregate `calls` APIs remain supported.
246
+
229
247
  ### File Mock
230
248
 
231
249
  ```typescript
232
250
  import { mockFile } from "@tailor-platform/sdk/vitest";
233
251
 
234
252
  test("mock file download", async () => {
235
- using file = mockFile();
236
- file.enqueueResult({
253
+ using file = mockFile({ onUnhandled: "error" });
254
+ file.download.mockResolvedValue({
237
255
  data: new Uint8Array([1, 2, 3]),
238
256
  metadata: { contentType: "image/png", fileSize: 3, sha256sum: "abc", lastUploadedAt: "" },
239
257
  });
240
258
 
241
259
  const result = await tailordb.file.download("ns", "Doc", "attachment", "r-1");
242
260
  expect(result.data).toEqual(new Uint8Array([1, 2, 3]));
243
- expect(file.calls).toMatchObject([{ method: "download", recordId: "r-1" }]);
261
+ expect(file.download).toHaveBeenCalledWith("ns", "Doc", "attachment", "r-1");
244
262
  });
245
263
  ```
246
264
 
247
- For `downloadStream`, enqueue a `FileDownloadStreamResponse` object with a `ReadableStream` body and metadata:
265
+ All File operations are typed Vitest mocks: `upload`, `download`, `downloadAsBase64`, `delete`, `getMetadata`, `downloadStream`, and `uploadStream`. Use native methods such as `mockResolvedValueOnce` and `mockRejectedValueOnce` to model success and failure. The existing resolver, queue, and aggregate `calls` APIs remain supported.
266
+
267
+ For `downloadStream`, configure a `FileDownloadStreamResponse` object with a `ReadableStream` body and metadata:
248
268
 
249
269
  ```typescript
250
270
  test("mock file download stream", async () => {
@@ -255,7 +275,7 @@ test("mock file download stream", async () => {
255
275
  controller.close();
256
276
  },
257
277
  });
258
- file.enqueueResult({
278
+ file.downloadStream.mockResolvedValue({
259
279
  body,
260
280
  metadata: { contentType: "image/png", fileSize: 3, sha256sum: "abc", lastUploadedAt: "" },
261
281
  });
@@ -265,28 +285,6 @@ test("mock file download stream", async () => {
265
285
  });
266
286
  ```
267
287
 
268
- For the deprecated `openDownloadStream`, enqueue an iterable of `StreamValue` items — `metadata`, one or more `chunk` items, and a terminal `complete`. Raw `Uint8Array` / `ArrayBuffer` chunks are rejected so tests stay aligned with the platform's structured stream contract.
269
-
270
- ```typescript
271
- test("mock file download stream (deprecated openDownloadStream)", async () => {
272
- using file = mockFile();
273
- file.enqueueResult([
274
- {
275
- type: "metadata",
276
- metadata: { contentType: "image/png", fileSize: 3, sha256sum: "abc" },
277
- },
278
- { type: "chunk", data: new Uint8Array([1, 2]), position: 0 },
279
- { type: "chunk", data: new Uint8Array([3]), position: 2 },
280
- { type: "complete" },
281
- ]);
282
-
283
- const stream = await tailordb.file.openDownloadStream("ns", "Doc", "attachment", "r-1");
284
- const items = [];
285
- for await (const item of stream) items.push(item);
286
- expect(items).toHaveLength(4);
287
- });
288
- ```
289
-
290
288
  ### Iconv Mock
291
289
 
292
290
  ```typescript
@@ -294,10 +292,7 @@ import { mockIconv } from "@tailor-platform/sdk/vitest";
294
292
 
295
293
  test("mock encoding conversion", () => {
296
294
  using iconv = mockIconv();
297
- iconv.setResolver((method, args) => {
298
- if (method === "decode") return "decoded-text";
299
- return null; // falls back to default empty string
300
- });
295
+ iconv.decode.mockReturnValue("decoded-text");
301
296
 
302
297
  const result = tailor.iconv.decode(new Uint8Array([0x48, 0x69]), "UTF-8");
303
298
  expect(result).toBe("decoded-text");
@@ -305,6 +300,48 @@ test("mock encoding conversion", () => {
305
300
  });
306
301
  ```
307
302
 
303
+ `convert`, `convertBuffer`, `decode`, `encode`, and `encodings` are all typed Vitest mocks. Pass `{ onUnhandled: "error" }` to fail calls without a configured implementation. The existing resolver and aggregate `calls` APIs remain supported.
304
+
305
+ ### AI Gateway Mock
306
+
307
+ ```typescript
308
+ import { mockAigateway } from "@tailor-platform/sdk/vitest";
309
+
310
+ test("resolves an AI Gateway URL", async () => {
311
+ using aigateway = mockAigateway({
312
+ urls: { "my-aigateway": "https://my-aigateway.example.com" },
313
+ });
314
+ aigateway.setUrl("my-aigateway", "https://replacement.example.com");
315
+
316
+ const { url } = await tailor.aigateway.get("my-aigateway");
317
+ expect(url).toBe("https://replacement.example.com");
318
+ expect(aigateway.calls).toEqual([{ name: "my-aigateway" }]);
319
+ });
320
+ ```
321
+
322
+ Calling `get` for a name that has not been registered throws. `setUrls` remains available when replacing the complete URL fixture.
323
+
324
+ ### Logger Mock
325
+
326
+ Each method is a `vi.fn`, so assert on it directly. `calls` returns the emitted `debug`/`info`/`warn`/`error` entries in order.
327
+
328
+ ```typescript
329
+ import { mockLogger } from "@tailor-platform/sdk/vitest";
330
+
331
+ test("logs the processed order", () => {
332
+ using logger = mockLogger();
333
+
334
+ tailor.logger.info("order processed", { orderId: "o-1" });
335
+
336
+ expect(logger.info).toHaveBeenCalledWith("order processed", { orderId: "o-1" });
337
+ expect(logger.calls).toEqual([
338
+ { severity: "info", message: "order processed", attributes: { orderId: "o-1" } },
339
+ ]);
340
+ });
341
+ ```
342
+
343
+ Without an explicit `mockLogger()`, `tailor.logger.*` calls are no-ops in the `tailor-runtime` environment (they neither throw nor record).
344
+
308
345
  ### Loading Secrets from Config
309
346
 
310
347
  Pass a config path to load `defineSecretManager()` values into the mock:
@@ -316,7 +353,7 @@ export default defineConfig({
316
353
  });
317
354
  ```
318
355
 
319
- This makes `tailor.secretmanager.getSecret("vault", "key")` return the values defined in your config. You can still override with `using sm = mockSecretmanager(); sm.setSecrets(...)` in individual tests: a per-test override applies only within that test, and the config-loaded secrets remain available to every other test.
356
+ This makes `tailor.secretmanager.getSecret("vault", "key")` return the values defined in your config. You can still override with `mockSecretmanager({ secrets: ... })` in individual tests: a per-test overlay applies only within that test, and the config-loaded secrets remain available to every other test.
320
357
 
321
358
  ### Per-Project Configuration
322
359
 
@@ -358,7 +395,7 @@ export default defineConfig({
358
395
 
359
396
  ## Unit Tests
360
397
 
361
- Unit tests call `.body()` (or `.trigger()`) directly on a resolver, workflow job, or executor and stub any platform-provided globals they touch.
398
+ Unit tests call `.body()` (or `.start()`) directly on a resolver, workflow job, or executor and stub any platform-provided globals they touch.
362
399
 
363
400
  ### Testing Resolvers
364
401
 
@@ -367,7 +404,6 @@ Unit tests call `.body()` (or `.trigger()`) directly on a resolver, workflow job
367
404
  For pure logic with no external dependencies, invoke `.body()` directly:
368
405
 
369
406
  ```typescript
370
- import { unauthenticatedTailorUser } from "@tailor-platform/sdk/test";
371
407
  import { describe, expect, test } from "vitest";
372
408
  import resolver from "../src/resolver/add";
373
409
 
@@ -375,7 +411,8 @@ describe("add resolver", () => {
375
411
  test("adds two numbers", async () => {
376
412
  const result = await resolver.body({
377
413
  input: { left: 1, right: 2 },
378
- user: unauthenticatedTailorUser,
414
+ caller: null,
415
+ invoker: null,
379
416
  env: {},
380
417
  });
381
418
  expect(result).toBe(3);
@@ -391,15 +428,16 @@ Stub the global `tailordb.Client` and queue raw query results in order. Best for
391
428
 
392
429
  > If you are running with the [`tailor-runtime` Vitest environment](#runtime-environment-emulation-beta), acquire `using db = mockTailordb()` to install and drive the mock `tailordb.Client` instead of `vi.stubGlobal()`.
393
430
 
431
+ > The example below uses `aroundAll` / `aroundEach`, which require Vitest ≥ 4.1.
432
+
394
433
  ```typescript
395
- import { unauthenticatedTailorUser } from "@tailor-platform/sdk/test";
396
- import { afterAll, afterEach, beforeAll, describe, expect, test, vi } from "vitest";
434
+ import { aroundAll, aroundEach, describe, expect, test, vi } from "vitest";
397
435
  import resolver from "../src/resolver/incrementUserAge";
398
436
 
399
437
  describe("incrementUserAge resolver", () => {
400
438
  const mockQueryObject = vi.fn();
401
439
 
402
- beforeAll(() => {
440
+ aroundAll(async (runSuite) => {
403
441
  vi.stubGlobal("tailordb", {
404
442
  Client: vi.fn(
405
443
  class {
@@ -409,9 +447,13 @@ describe("incrementUserAge resolver", () => {
409
447
  },
410
448
  ),
411
449
  });
450
+ await runSuite();
451
+ vi.unstubAllGlobals();
452
+ });
453
+ aroundEach(async (runTest) => {
454
+ await runTest();
455
+ mockQueryObject.mockReset();
412
456
  });
413
- afterAll(() => vi.unstubAllGlobals());
414
- afterEach(() => mockQueryObject.mockReset());
415
457
 
416
458
  test("increments age inside a transaction", async () => {
417
459
  // BEGIN → SELECT → UPDATE → COMMIT
@@ -422,7 +464,8 @@ describe("incrementUserAge resolver", () => {
422
464
 
423
465
  const result = await resolver.body({
424
466
  input: { email: "test@example.com" },
425
- user: unauthenticatedTailorUser,
467
+ caller: null,
468
+ invoker: null,
426
469
  env: {},
427
470
  });
428
471
 
@@ -493,7 +536,6 @@ describe("decrementUserAge", () => {
493
536
  Pass `mock.db` to functions that take a Kysely instance. When a resolver or executor calls `getDB()` internally there is no such seam, so spy the generated `getDB` and point it at the mock:
494
537
 
495
538
  ```typescript
496
- import { unauthenticatedTailorUser } from "@tailor-platform/sdk/test";
497
539
  import { createKyselyMock } from "@tailor-platform/sdk/vitest";
498
540
  import { describe, expect, test, vi } from "vitest";
499
541
  import { getDB, type Namespace } from "../generated/db";
@@ -525,7 +567,8 @@ describe("upsertUsers resolver", () => {
525
567
  { name: "Existing", email: "exists@example.com", age: 41 },
526
568
  ],
527
569
  },
528
- user: unauthenticatedTailorUser,
570
+ caller: null,
571
+ invoker: null,
529
572
  env: { appName: "Resolver Template", version: 1 },
530
573
  });
531
574
 
@@ -541,39 +584,70 @@ Reach for [`mockTailordb`](#mocking-the-tailordb-client) instead when you want t
541
584
 
542
585
  #### Resolvers that resume a workflow
543
586
 
544
- Resolvers that call `waitPoint.resolve(...)` delegate to `tailor.workflow.resolve` at runtime. With the `tailor-runtime` environment active, use `mockWorkflow().setResolveHandler` to drive the user-supplied callback and inspect `resolveCalls`:
587
+ Resolvers that call `waitPoint.resolve(...)` delegate to `tailor.workflow.resolve` at runtime. With the `tailor-runtime` environment active, use `mockWorkflow().waitPoint(definition)` to invoke the callback with the payload that originally suspended the job:
545
588
 
546
589
  ```typescript
547
- import { unauthenticatedTailorUser } from "@tailor-platform/sdk/test";
548
590
  import { mockWorkflow } from "@tailor-platform/sdk/vitest";
549
591
  import { describe, expect, test } from "vitest";
592
+ import { approval } from "../workflow/approval";
550
593
  import resolver from "./resolveApproval";
551
594
 
552
595
  describe("resolveApproval resolver", () => {
553
596
  test("resolves approval with approved=true", async () => {
554
597
  using wf = mockWorkflow();
555
- wf.setResolveHandler((_executionId, _key, callback) => {
556
- const result = callback({ message: "Please approve order order-1", orderId: "order-1" });
557
- expect(result).toEqual({ approved: true });
598
+ const approvalMock = wf.waitPoint(approval);
599
+ approvalMock.setResolvePayload({
600
+ message: "Please approve order order-1",
601
+ orderId: "order-1",
558
602
  });
559
603
 
560
604
  const result = await resolver.body({
561
605
  input: { executionId: "exec-1", approved: true },
562
- user: unauthenticatedTailorUser,
606
+ caller: null,
607
+ invoker: null,
563
608
  env: {},
564
609
  });
565
610
 
566
611
  expect(result).toEqual({ resolved: true });
567
- expect(wf.resolveCalls).toEqual([{ executionId: "exec-1", key: "approval" }]);
612
+ expect(approvalMock.resolve).toHaveBeenCalledWith("exec-1", expect.any(Function));
568
613
  });
569
614
  });
570
615
  ```
571
616
 
572
- `setResolveHandler` receives `(executionId, key, callback)` and decides whether to invoke the callback that's how you assert the value returned to the suspended job.
617
+ `setResolvePayload` is typed from the wait-point definition. The lower-level `setResolveHandler` and `resolveCalls` APIs remain available when a test must control several wait points together.
618
+
619
+ #### Resolvers that resume failed workflows
620
+
621
+ Resolvers or executors that call `workflow.resumeWorkflowExecution(executionId)` delegate to `tailor.workflow.resumeWorkflowExecution` at runtime. With the `tailor-runtime` environment active, use `mockWorkflow().setResumeHandler` to control the returned execution ID and inspect `resumeWorkflowExecution.mock.calls`:
622
+
623
+ ```typescript
624
+ import { unauthenticatedTailorUser } from "@tailor-platform/sdk/test";
625
+ import { mockWorkflow } from "@tailor-platform/sdk/vitest";
626
+ import { describe, expect, test } from "vitest";
627
+ import resolver from "./retryFailedWorkflow";
628
+
629
+ describe("retryFailedWorkflow resolver", () => {
630
+ test("resumes a failed workflow execution", async () => {
631
+ using wf = mockWorkflow();
632
+ wf.setResumeHandler("exec-resumed-123");
633
+
634
+ const result = await resolver.body({
635
+ input: { executionId: "exec-failed-456" },
636
+ user: unauthenticatedTailorUser,
637
+ env: {},
638
+ });
639
+
640
+ expect(result).toEqual({ resumedExecutionId: "exec-resumed-123" });
641
+ expect(wf.resumeWorkflowExecution.mock.calls).toEqual([["exec-failed-456"]]);
642
+ });
643
+ });
644
+ ```
645
+
646
+ `setResumeHandler` accepts a static string (same execution ID for every call) or a function `(executionId) => string` that computes one per call. By default the mock echoes the input `executionId`.
573
647
 
574
648
  ### Testing Executors
575
649
 
576
- Function-kind executors expose their handler as `executor.operation.body(args)`. The shape of `args` is determined by the trigger — for example, `recordCreatedTrigger({ type: user })` produces `{ newRecord }` typed against the type's output. GraphQL, webhook, and workflow operation kinds are declarative and don't expose a user-authored body to test.
650
+ Function-kind executors expose their handler as `executor.operation.body(args)`. The shape of `args` is determined by the trigger — for example, `recordCreatedTrigger({ type: user })` produces `{ newRecord }` typed against the type's output, plus runtime fields such as `env`, `actor`, and `invoker`. GraphQL, webhook, and workflow operation kinds are declarative and don't expose a user-authored body to test.
577
651
 
578
652
  The `executor` template extracts shared DB access into a helper (`shared.ts`) and tests the helper directly against a mocked `tailordb.Client` (same TailorDB-mocking pattern as the resolver section). Executor handlers themselves stay thin and can be tested by spying on the helper:
579
653
 
@@ -590,6 +664,14 @@ describe("onUserCreated executor", () => {
590
664
  throw new Error("expected function operation");
591
665
  }
592
666
  await onUserCreated.operation.body({
667
+ workspaceId: "workspace-1",
668
+ appNamespace: "app",
669
+ env: {},
670
+ actor: null,
671
+ invoker: null,
672
+ event: "created",
673
+ rawEvent: "tailordb.type_record.created",
674
+ typeName: "User",
593
675
  newRecord: {
594
676
  id: "user-1",
595
677
  name: "Alice",
@@ -614,11 +696,11 @@ To exercise the full chain (executor → helper → TailorDB), drop the spy and
614
696
 
615
697
  ### Testing Workflow Jobs
616
698
 
617
- Workflow jobs expose the same `.body()` entrypoint as resolvers, plus `.trigger()` for calling them from another job or a test.
699
+ Workflow jobs expose the same `.body()` entrypoint as resolvers, plus `.start()` for calling them from another job or a test.
618
700
 
619
701
  #### Simple job
620
702
 
621
- Call `.body()` with the input and a stub `{ env: {} }`:
703
+ Call `.body()` with the input and a stub `{ env: {}, invoker: null }`:
622
704
 
623
705
  ```typescript
624
706
  import { describe, expect, test } from "vitest";
@@ -626,46 +708,54 @@ import { validateOrder } from "./order-fulfillment";
626
708
 
627
709
  describe("validateOrder", () => {
628
710
  test("accepts a valid order", () => {
629
- const result = validateOrder.body({ orderId: "order-1", amount: 100 }, { env: {} });
711
+ const result = validateOrder.body(
712
+ { orderId: "order-1", amount: 100 },
713
+ { env: {}, invoker: null },
714
+ );
630
715
  expect(result).toEqual({ valid: true, orderId: "order-1" });
631
716
  });
632
717
 
633
718
  test("rejects a non-positive amount", () => {
634
- expect(() => validateOrder.body({ orderId: "order-1", amount: 0 }, { env: {} })).toThrow(
635
- "Order amount must be positive",
636
- );
719
+ expect(() =>
720
+ validateOrder.body({ orderId: "order-1", amount: 0 }, { env: {}, invoker: null }),
721
+ ).toThrow("Order amount must be positive");
637
722
  });
638
723
  });
639
724
  ```
640
725
 
641
- #### Jobs that trigger other jobs
726
+ #### Jobs that start other jobs
642
727
 
643
- Spy on each dependent job's `.trigger()` to replace it with a deterministic result:
728
+ Use `mockWorkflow().job(definition)` to replace dependent jobs with deterministic results:
644
729
 
645
730
  ```typescript
646
- import { describe, expect, test, vi } from "vitest";
731
+ import { mockWorkflow } from "@tailor-platform/sdk/vitest";
732
+ import { describe, expect, test } from "vitest";
647
733
  import { fulfillOrder, processPayment, sendConfirmation, validateOrder } from "./order-fulfillment";
648
734
 
649
735
  describe("fulfillOrder", () => {
650
736
  test("chains validate → pay → confirm", async () => {
651
- using _validateSpy = vi.spyOn(validateOrder, "trigger").mockReturnValue({
737
+ using wf = mockWorkflow();
738
+ const validate = wf.job(validateOrder).mockResolvedValue({
652
739
  valid: true,
653
740
  orderId: "order-1",
654
741
  });
655
- using _paymentSpy = vi.spyOn(processPayment, "trigger").mockReturnValue({
742
+ wf.job(processPayment).mockResolvedValue({
656
743
  transactionId: "txn-order-1",
657
744
  amount: 100,
658
745
  status: "completed",
659
746
  });
660
- using _confirmSpy = vi.spyOn(sendConfirmation, "trigger").mockReturnValue({
747
+ wf.job(sendConfirmation).mockResolvedValue({
661
748
  orderId: "order-1",
662
749
  transactionId: "txn-order-1",
663
750
  confirmed: true,
664
751
  });
665
752
 
666
- const result = await fulfillOrder.body({ orderId: "order-1", amount: 100 }, { env: {} });
753
+ const result = await fulfillOrder.body(
754
+ { orderId: "order-1", amount: 100 },
755
+ { env: {}, invoker: null },
756
+ );
667
757
 
668
- expect(validateOrder.trigger).toHaveBeenCalledWith({ orderId: "order-1", amount: 100 });
758
+ expect(validate).toHaveBeenCalledWith({ orderId: "order-1", amount: 100 });
669
759
  expect(result).toMatchObject({ confirmed: true, paymentStatus: "completed" });
670
760
  });
671
761
  });
@@ -675,43 +765,50 @@ describe("fulfillOrder", () => {
675
765
 
676
766
  #### Jobs that wait on approval
677
767
 
678
- `.wait()` calls delegate to `tailor.workflow.wait`. With the `tailor-runtime` environment active, use `mockWorkflow().setWaitHandler` to drive each branch and inspect `waitCalls`:
768
+ `.wait()` calls delegate to `tailor.workflow.wait`. With the `tailor-runtime` environment active, use `mockWorkflow().waitPoint(definition)` to drive each branch with a typed mock:
679
769
 
680
770
  ```typescript
681
771
  import { mockWorkflow } from "@tailor-platform/sdk/vitest";
682
772
  import { describe, expect, test } from "vitest";
683
- import { processWithApproval } from "./approval";
773
+ import { approval, processWithApproval } from "./approval";
684
774
 
685
775
  describe("processWithApproval", () => {
686
776
  test("returns approved status when .wait() resolves positively", async () => {
687
777
  using wf = mockWorkflow();
688
- wf.setWaitHandler({ approved: true });
778
+ const approvalMock = wf.waitPoint(approval);
779
+ approvalMock.wait.mockResolvedValue({ approved: true });
689
780
 
690
- const result = await processWithApproval.body({ orderId: "order-1" }, { env: {} });
781
+ const result = await processWithApproval.body(
782
+ { orderId: "order-1" },
783
+ { env: {}, invoker: null },
784
+ );
691
785
 
692
786
  expect(result).toEqual({ orderId: "order-1", status: "approved" });
693
- expect(wf.waitCalls[0]).toEqual({
694
- key: "approval",
695
- payload: { message: "Please approve order order-1", orderId: "order-1" },
787
+ expect(approvalMock.wait).toHaveBeenCalledWith({
788
+ message: "Please approve order order-1",
789
+ orderId: "order-1",
696
790
  });
697
791
  });
698
792
 
699
793
  test("returns rejected status when .wait() resolves negatively", async () => {
700
794
  using wf = mockWorkflow();
701
- wf.setWaitHandler({ approved: false });
795
+ wf.waitPoint(approval).wait.mockResolvedValue({ approved: false });
702
796
 
703
- const result = await processWithApproval.body({ orderId: "order-2" }, { env: {} });
797
+ const result = await processWithApproval.body(
798
+ { orderId: "order-2" },
799
+ { env: {}, invoker: null },
800
+ );
704
801
 
705
802
  expect(result.status).toBe("rejected");
706
803
  });
707
804
  });
708
805
  ```
709
806
 
710
- `setWaitHandler` accepts a static value (returned from every `.wait()` call) or a function `(key, payload) => unknown` to compute one per call. `waitCalls` captures the `key` and `payload` passed in.
807
+ The lower-level `setWaitHandler` and `waitCalls` APIs remain available when one handler must cover several wait points.
711
808
 
712
809
  #### Running a full workflow locally
713
810
 
714
- To exercise the full chain with real job bodies, call `runWorkflowLocally(workflow, args)`. Dependent jobs run their real `.body()` functions, and trigger args/results cross the same JSON boundary as the platform, so a non-serializable payload fails the test exactly as it would in production:
811
+ To exercise the full chain with real job bodies, call `runWorkflowLocally(workflow, args)`. Dependent jobs run their real `.body()` functions, and start args/results cross the same JSON boundary as the platform, so a non-serializable payload fails the test exactly as it would in production:
715
812
 
716
813
  ```typescript
717
814
  import { runWorkflowLocally } from "@tailor-platform/sdk/vitest";
@@ -727,9 +824,13 @@ describe("order-fulfillment workflow", () => {
727
824
  });
728
825
  ```
729
826
 
827
+ Acquire `mockWorkflow()` only when you need to override a dependent definition with `wf.job(...)` / `wf.workflow(...)` (the rest still run their real bodies), control the env via `wf.setEnv(...)`, or assert on calls.
828
+
730
829
  Pass `{ env }` as the third argument when job bodies need configuration values during the local run.
731
830
 
732
- Like the platform runtime, the local runner re-runs the orchestrator body once per `.trigger()` call (N triggers means N+1 passes), so any side effects outside the trigger results fire on every pass. Keep the body deterministic and move repeatable side effects into the triggered jobs.
831
+ If you already acquired `mockWorkflow()`, you can also call `wf.setEnv(...)` to reuse the same env across local workflow runs.
832
+
833
+ Like the platform runtime, the local runner re-runs the orchestrator body once per `.start()` call (N starts means N+1 passes), so any side effects outside the start results fire on every pass. Keep the body deterministic and move repeatable side effects into the started jobs.
733
834
 
734
835
  This helper is still a local runner. Use E2E tests when you need to verify deployed workflow scheduling, suspension, or replay behavior.
735
836
 
@@ -837,7 +938,7 @@ describe("user-profile-sync workflow", () => {
837
938
  test("executes end to end", { timeout: 180_000 }, async () => {
838
939
  const { executionId, wait } = await startWorkflow({
839
940
  workflow: userProfileSync,
840
- authInvoker: "admin",
941
+ invoker: "admin",
841
942
  arg: {
842
943
  name: "workflow-test",
843
944
  email: `wf-${randomUUID()}@example.com`,