@tailor-platform/sdk 1.76.1 → 1.78.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (301) hide show
  1. package/CHANGELOG.md +60 -0
  2. package/dist/{application-BUfYmf0O.mjs → application-CUxVA7Fs.mjs} +378 -1679
  3. package/dist/application-CUxVA7Fs.mjs.map +1 -0
  4. package/dist/application-Dp_-ioiP.mjs +3 -0
  5. package/dist/cli/cache/bundle-cache.d.mts +2 -1
  6. package/dist/cli/cache/store.d.mts +1 -1
  7. package/dist/cli/commands/api/index.d.mts +1 -0
  8. package/dist/cli/commands/deploy/aigateway.d.mts +5 -1
  9. package/dist/cli/commands/deploy/application.d.mts +7 -1
  10. package/dist/cli/commands/deploy/apply-phases.d.mts +14 -1
  11. package/dist/cli/commands/deploy/auth.d.mts +5 -1
  12. package/dist/cli/commands/deploy/deploy.d.mts +13 -3
  13. package/dist/cli/commands/deploy/executor.d.mts +7 -1
  14. package/dist/cli/commands/deploy/function-registry.d.mts +5 -0
  15. package/dist/cli/commands/deploy/idp.d.mts +5 -1
  16. package/dist/cli/commands/deploy/resolver.d.mts +5 -1
  17. package/dist/cli/commands/deploy/secret-manager.d.mts +5 -1
  18. package/dist/cli/commands/deploy/staticwebsite.d.mts +5 -1
  19. package/dist/cli/commands/deploy/tailordb/index.d.mts +8 -1
  20. package/dist/cli/commands/deploy/types.d.mts +3 -1
  21. package/dist/cli/commands/deploy/workflow-execution-policy.d.mts +3 -1
  22. package/dist/cli/commands/deploy/workflow.d.mts +4 -1
  23. package/dist/cli/commands/executor/get.d.mts +0 -1
  24. package/dist/cli/commands/executor/jobs.d.mts +0 -1
  25. package/dist/cli/commands/executor/list.d.mts +0 -1
  26. package/dist/cli/commands/executor/transform.d.mts +1 -0
  27. package/dist/cli/commands/executor/trigger.d.mts +0 -1
  28. package/dist/cli/commands/executor/webhook.d.mts +0 -1
  29. package/dist/cli/commands/function/get.d.mts +0 -1
  30. package/dist/cli/commands/function/list.d.mts +0 -1
  31. package/dist/cli/commands/function/transform.d.mts +1 -0
  32. package/dist/cli/commands/generate/service.d.mts +5 -1
  33. package/dist/cli/commands/generate/types.d.mts +3 -1
  34. package/dist/cli/commands/machineuser/list.d.mts +0 -1
  35. package/dist/cli/commands/machineuser/token.d.mts +0 -1
  36. package/dist/cli/commands/oauth2client/get.d.mts +0 -1
  37. package/dist/cli/commands/oauth2client/list.d.mts +0 -1
  38. package/dist/cli/commands/oauth2client/transform.d.mts +1 -0
  39. package/dist/cli/commands/organization/folder/create.d.mts +0 -1
  40. package/dist/cli/commands/organization/folder/delete.d.mts +0 -1
  41. package/dist/cli/commands/organization/folder/get.d.mts +0 -1
  42. package/dist/cli/commands/organization/folder/list.d.mts +0 -1
  43. package/dist/cli/commands/organization/folder/update.d.mts +0 -1
  44. package/dist/cli/commands/organization/get.d.mts +0 -1
  45. package/dist/cli/commands/organization/list.d.mts +0 -1
  46. package/dist/cli/commands/organization/transform.d.mts +2 -0
  47. package/dist/cli/commands/organization/tree.d.mts +0 -1
  48. package/dist/cli/commands/organization/update.d.mts +0 -1
  49. package/dist/cli/commands/remove.d.mts +0 -1
  50. package/dist/cli/commands/show.d.mts +9 -4
  51. package/dist/cli/commands/tailordb/migrate/config.d.mts +0 -1
  52. package/dist/cli/commands/tailordb/migrate/diff-calculator.d.mts +0 -1
  53. package/dist/cli/commands/tailordb/migrate/generate.d.mts +0 -1
  54. package/dist/cli/commands/tailordb/migrate/snapshot.d.mts +1 -1
  55. package/dist/cli/commands/tailordb/truncate.d.mts +0 -1
  56. package/dist/cli/commands/workflow/executions.d.mts +0 -1
  57. package/dist/cli/commands/workflow/get.d.mts +2 -1
  58. package/dist/cli/commands/workflow/list.d.mts +0 -1
  59. package/dist/cli/commands/workflow/resume.d.mts +0 -1
  60. package/dist/cli/commands/workflow/start.d.mts +0 -1
  61. package/dist/cli/commands/workflow/status.d.mts +1 -0
  62. package/dist/cli/commands/workflow/transform.d.mts +1 -0
  63. package/dist/cli/commands/workflow/wait.d.mts +0 -1
  64. package/dist/cli/commands/workflow/waiter.d.mts +1 -1
  65. package/dist/cli/commands/workspace/app/health.d.mts +0 -1
  66. package/dist/cli/commands/workspace/app/list.d.mts +0 -1
  67. package/dist/cli/commands/workspace/app/transform.d.mts +2 -0
  68. package/dist/cli/commands/workspace/create.d.mts +3 -1
  69. package/dist/cli/commands/workspace/delete.d.mts +0 -1
  70. package/dist/cli/commands/workspace/get.d.mts +0 -1
  71. package/dist/cli/commands/workspace/list.d.mts +1 -1
  72. package/dist/cli/commands/workspace/restore.d.mts +0 -1
  73. package/dist/cli/commands/workspace/transform.d.mts +4 -0
  74. package/dist/cli/commands/workspace/user/invite.d.mts +0 -1
  75. package/dist/cli/commands/workspace/user/list.d.mts +0 -1
  76. package/dist/cli/commands/workspace/user/remove.d.mts +0 -1
  77. package/dist/cli/commands/workspace/user/transform.d.mts +1 -0
  78. package/dist/cli/commands/workspace/user/update.d.mts +0 -1
  79. package/dist/cli/index.d.mts +3 -1
  80. package/dist/cli/index.mjs +660 -56
  81. package/dist/cli/index.mjs.map +1 -1
  82. package/dist/cli/lib.d.mts +4 -2
  83. package/dist/cli/lib.mjs +3 -3
  84. package/dist/cli/lib.mjs.map +1 -1
  85. package/dist/cli/query/index.d.mts +0 -1
  86. package/dist/cli/services/application.d.mts +12 -1
  87. package/dist/cli/services/auth/service.d.mts +2 -0
  88. package/dist/cli/services/executor/service.d.mts +1 -1
  89. package/dist/cli/services/http-adapter/bundler.d.mts +3 -1
  90. package/dist/cli/services/http-adapter/service.d.mts +2 -1
  91. package/dist/cli/services/resolver/service.d.mts +1 -1
  92. package/dist/cli/services/tailordb/service.d.mts +3 -1
  93. package/dist/cli/services/workflow/bundler.d.mts +2 -1
  94. package/dist/cli/services/workflow/service.d.mts +1 -1
  95. package/dist/cli/shared/args.d.mts +1 -1
  96. package/dist/cli/shared/client.d.mts +1 -1
  97. package/dist/cli/shared/config-loader.d.mts +0 -1
  98. package/dist/cli/shared/context.d.mts +2 -1
  99. package/dist/cli/shared/script-executor.d.mts +0 -1
  100. package/dist/cli/shared/seed-chunker.d.mts +7 -3
  101. package/dist/cli/shared/type-generator.d.mts +0 -1
  102. package/dist/cli/shared/workspace-name.d.mts +1 -0
  103. package/dist/cli/skills.mjs +1 -1
  104. package/dist/completion/zsh-worker.zsh +18 -1
  105. package/dist/configure/config/index.d.mts +0 -1
  106. package/dist/configure/config/types.d.mts +2 -2
  107. package/dist/configure/index.d.mts +2 -1
  108. package/dist/configure/index.mjs +248 -4
  109. package/dist/configure/index.mjs.map +1 -1
  110. package/dist/configure/services/aigateway/index.d.mts +0 -1
  111. package/dist/configure/services/aigateway/types.d.mts +0 -1
  112. package/dist/configure/services/auth/index.d.mts +0 -1
  113. package/dist/configure/services/auth/types.d.mts +14 -13
  114. package/dist/configure/services/executor/executor.d.mts +0 -1
  115. package/dist/configure/services/executor/index.d.mts +1 -0
  116. package/dist/configure/services/executor/operation.d.mts +1 -2
  117. package/dist/configure/services/executor/trigger/event.d.mts +0 -1
  118. package/dist/configure/services/executor/trigger/index.d.mts +0 -1
  119. package/dist/configure/services/executor/trigger/schedule.d.mts +0 -1
  120. package/dist/configure/services/executor/trigger/webhook.d.mts +0 -1
  121. package/dist/configure/services/http-adapter/http-adapter.d.mts +1 -2
  122. package/dist/configure/services/idp/index.d.mts +1 -5
  123. package/dist/configure/services/idp/permission.d.mts +4 -5
  124. package/dist/configure/services/idp/types.d.mts +0 -1
  125. package/dist/configure/services/index.d.mts +5 -0
  126. package/dist/configure/services/resolver/resolver.d.mts +0 -1
  127. package/dist/configure/services/resolver/types.d.mts +0 -1
  128. package/dist/configure/services/secrets/index.d.mts +0 -1
  129. package/dist/configure/services/secrets/types.d.mts +0 -1
  130. package/dist/configure/services/staticwebsite/index.d.mts +0 -1
  131. package/dist/configure/services/staticwebsite/types.d.mts +0 -1
  132. package/dist/configure/services/tailordb/permission.d.mts +4 -5
  133. package/dist/configure/services/tailordb/schema.d.mts +21 -8
  134. package/dist/configure/services/tailordb/types.d.mts +4 -5
  135. package/dist/configure/services/workflow/execution-policy.d.mts +0 -1
  136. package/dist/configure/services/workflow/execution-policy.types.d.mts +0 -1
  137. package/dist/configure/services/workflow/index.d.mts +1 -0
  138. package/dist/configure/services/workflow/job.d.mts +0 -1
  139. package/dist/configure/services/workflow/wait-point.d.mts +0 -1
  140. package/dist/configure/services/workflow/workflow.d.mts +0 -1
  141. package/dist/configure/types/field-runtime.d.mts +1 -1
  142. package/dist/configure/types/field.d.mts +1 -2
  143. package/dist/configure/types/field.types.d.mts +1 -2
  144. package/dist/configure/types/type.d.mts +1 -1
  145. package/dist/configure/user.d.mts +0 -1
  146. package/dist/{crashreport-ayWANEZ6.mjs → crashreport-BNWUM6Kf.mjs} +4 -3
  147. package/dist/{crashreport-ayWANEZ6.mjs.map → crashreport-BNWUM6Kf.mjs.map} +1 -1
  148. package/dist/{crashreport-Dy4ZzSkd.mjs → crashreport-BafWvjjX.mjs} +1 -1
  149. package/dist/errors-DVFS0AZk.mjs +100 -0
  150. package/dist/errors-DVFS0AZk.mjs.map +1 -0
  151. package/dist/{globals-CcU1ONiK.mjs → globals-CvizbGLY.mjs} +2 -2
  152. package/dist/{globals-CcU1ONiK.mjs.map → globals-CvizbGLY.mjs.map} +1 -1
  153. package/dist/kysely/index.d.mts +3 -4
  154. package/dist/{logger-BEiZZ3qT.mjs → logger-BwS4ppwO.mjs} +3 -3
  155. package/dist/logger-BwS4ppwO.mjs.map +1 -0
  156. package/dist/parser/service/auth/index.d.mts +1 -1
  157. package/dist/parser/service/auth/schema.d.mts +1 -0
  158. package/dist/parser/service/http-adapter/index.d.mts +1 -1
  159. package/dist/parser/service/idp/types.d.mts +1 -0
  160. package/dist/parser/service/tailordb/types.d.mts +0 -1
  161. package/dist/plugin/builtin/enum-constants/index.d.mts +0 -1
  162. package/dist/plugin/builtin/file-utils/index.d.mts +0 -1
  163. package/dist/plugin/builtin/kysely-type/index.d.mts +0 -1
  164. package/dist/plugin/builtin/seed/index.d.mts +0 -1
  165. package/dist/plugin/builtin/seed/index.mjs +1 -1
  166. package/dist/plugin/get-generated-type.d.mts +0 -1
  167. package/dist/plugin/manager.d.mts +3 -1
  168. package/dist/plugin/types.d.mts +0 -1
  169. package/dist/plugin/with-context.d.mts +0 -1
  170. package/dist/{registry-NfSW0BRo.mjs → registry-CYBRvfaU.mjs} +4 -49
  171. package/dist/registry-CYBRvfaU.mjs.map +1 -0
  172. package/dist/runtime/aigateway.d.mts +0 -2
  173. package/dist/runtime/authconnection.d.mts +0 -2
  174. package/dist/runtime/globals.d.mts +0 -1
  175. package/dist/runtime/index.d.mts +0 -1
  176. package/dist/runtime/types.d.mts +16 -7
  177. package/dist/{runtime-_vUgjiqT.mjs → runtime-BD2vYJFT.mjs} +2382 -1167
  178. package/dist/runtime-BD2vYJFT.mjs.map +1 -0
  179. package/dist/{schema-DrVyN-LP.mjs → schema-U6DxoZ8D.mjs} +204 -3
  180. package/dist/schema-U6DxoZ8D.mjs.map +1 -0
  181. package/dist/{secret-file-VSVGy1V0.mjs → secret-file-DBqZhjFQ.mjs} +2 -27
  182. package/dist/{secret-file-VSVGy1V0.mjs.map → secret-file-DBqZhjFQ.mjs.map} +1 -1
  183. package/dist/{secretmanager-Bd45j7an.mjs → secretmanager-IY4UvinW.mjs} +42 -9
  184. package/dist/secretmanager-IY4UvinW.mjs.map +1 -0
  185. package/dist/seed/index.d.mts +3 -2
  186. package/dist/{seed-fm0LeYP2.mjs → seed-DFFigL8V.mjs} +3 -13
  187. package/dist/seed-DFFigL8V.mjs.map +1 -0
  188. package/dist/service-CghpdV-9.mjs +3 -0
  189. package/dist/{service-DBFZQloR.mjs → service-Cp0I7ZFe.mjs} +3 -3
  190. package/dist/{service-DBFZQloR.mjs.map → service-Cp0I7ZFe.mjs.map} +1 -1
  191. package/dist/{service-BCRJ-3NV.mjs → service-D12iQGcS.mjs} +2 -2
  192. package/dist/{service-BCRJ-3NV.mjs.map → service-D12iQGcS.mjs.map} +1 -1
  193. package/dist/service_pb-BoLM0X4K.mjs +167 -0
  194. package/dist/service_pb-BoLM0X4K.mjs.map +1 -0
  195. package/dist/{service_pb-B2FF59sP.mjs → service_pb-r1T7kpJc.mjs} +1 -1
  196. package/dist/tailor-proto/src/tailor/v1/aigateway_pb.d.mts +0 -1
  197. package/dist/tailor-proto/src/tailor/v1/aigateway_resource_pb.d.mts +0 -1
  198. package/dist/tailor-proto/src/tailor/v1/application_pb.d.mts +0 -1
  199. package/dist/tailor-proto/src/tailor/v1/application_resource_pb.d.mts +0 -1
  200. package/dist/tailor-proto/src/tailor/v1/auth_pb.d.mts +0 -1
  201. package/dist/tailor-proto/src/tailor/v1/auth_resource_pb.d.mts +0 -1
  202. package/dist/tailor-proto/src/tailor/v1/events_pb.d.mts +0 -1
  203. package/dist/tailor-proto/src/tailor/v1/events_resource_pb.d.mts +0 -1
  204. package/dist/tailor-proto/src/tailor/v1/executor_pb.d.mts +0 -1
  205. package/dist/tailor-proto/src/tailor/v1/executor_resource_pb.d.mts +0 -1
  206. package/dist/tailor-proto/src/tailor/v1/function_pb.d.mts +0 -1
  207. package/dist/tailor-proto/src/tailor/v1/function_registry_pb.d.mts +0 -1
  208. package/dist/tailor-proto/src/tailor/v1/function_resource_pb.d.mts +0 -1
  209. package/dist/tailor-proto/src/tailor/v1/http_adapter_resource_pb.d.mts +0 -1
  210. package/dist/tailor-proto/src/tailor/v1/idp_pb.d.mts +0 -1
  211. package/dist/tailor-proto/src/tailor/v1/idp_resource_pb.d.mts +0 -1
  212. package/dist/tailor-proto/src/tailor/v1/metadata_pb.d.mts +0 -1
  213. package/dist/tailor-proto/src/tailor/v1/metadata_resource_pb.d.mts +0 -1
  214. package/dist/tailor-proto/src/tailor/v1/meter_pb.d.mts +0 -1
  215. package/dist/tailor-proto/src/tailor/v1/pipeline_pb.d.mts +0 -1
  216. package/dist/tailor-proto/src/tailor/v1/pipeline_resource_pb.d.mts +0 -1
  217. package/dist/tailor-proto/src/tailor/v1/resource_pb.d.mts +0 -1
  218. package/dist/tailor-proto/src/tailor/v1/secret_manager_pb.d.mts +0 -1
  219. package/dist/tailor-proto/src/tailor/v1/secret_manager_resource_pb.d.mts +0 -1
  220. package/dist/tailor-proto/src/tailor/v1/service_pb.d.mts +0 -1
  221. package/dist/tailor-proto/src/tailor/v1/stateflow_pb.d.mts +0 -1
  222. package/dist/tailor-proto/src/tailor/v1/stateflow_resource_pb.d.mts +0 -1
  223. package/dist/tailor-proto/src/tailor/v1/staticwebsite_pb.d.mts +0 -1
  224. package/dist/tailor-proto/src/tailor/v1/staticwebsite_resource_pb.d.mts +0 -1
  225. package/dist/tailor-proto/src/tailor/v1/tailordb_pb.d.mts +0 -1
  226. package/dist/tailor-proto/src/tailor/v1/tailordb_resource_pb.d.mts +0 -1
  227. package/dist/tailor-proto/src/tailor/v1/telemetryrouter_pb.d.mts +0 -1
  228. package/dist/tailor-proto/src/tailor/v1/telemetryrouter_resource_pb.d.mts +0 -1
  229. package/dist/tailor-proto/src/tailor/v1/workflow_pb.d.mts +0 -1
  230. package/dist/tailor-proto/src/tailor/v1/workflow_resource_pb.d.mts +0 -1
  231. package/dist/tailor-proto/src/tailor/v1/workspace_pb.d.mts +0 -1
  232. package/dist/tailor-proto/src/tailor/v1/workspace_resource_pb.d.mts +0 -1
  233. package/dist/test-env-key-DuZycyWM.mjs +49 -0
  234. package/dist/test-env-key-DuZycyWM.mjs.map +1 -0
  235. package/dist/type-source-DH_LH20p.mjs +13 -0
  236. package/dist/type-source-DH_LH20p.mjs.map +1 -0
  237. package/dist/types/aigateway.generated.d.mts +5 -2
  238. package/dist/types/auth-connection.generated.d.mts +11 -5
  239. package/dist/types/auth.generated.d.mts +118 -85
  240. package/dist/types/executor.generated.d.mts +76 -84
  241. package/dist/types/helpers.d.mts +5 -5
  242. package/dist/types/http-adapter.generated.d.mts +11 -5
  243. package/dist/types/idp.generated.d.mts +536 -524
  244. package/dist/types/resolver.generated.d.mts +24 -10
  245. package/dist/types/staticwebsite.generated.d.mts +7 -3
  246. package/dist/types/tailordb.generated.d.mts +55 -29
  247. package/dist/types/workflow.generated.d.mts +9 -4
  248. package/dist/user-agent-DX2Jnw0-.mjs +28 -0
  249. package/dist/user-agent-DX2Jnw0-.mjs.map +1 -0
  250. package/dist/utils/test/index.d.mts +0 -1
  251. package/dist/utils/test/index.mjs +1 -1
  252. package/dist/utils/test/mock.d.mts +0 -1
  253. package/dist/vitest/environment.mjs +1 -1
  254. package/dist/vitest/index.d.mts +9 -9
  255. package/dist/vitest/index.mjs +600 -185
  256. package/dist/vitest/index.mjs.map +1 -1
  257. package/dist/vitest/mock-kysely.d.mts +0 -1
  258. package/dist/vitest/mock.d.mts +8 -8
  259. package/dist/vitest/mocks/aigateway.d.mts +16 -6
  260. package/dist/vitest/mocks/authconnection.d.mts +16 -6
  261. package/dist/vitest/mocks/file.d.mts +24 -6
  262. package/dist/vitest/mocks/iconv.d.mts +28 -4
  263. package/dist/vitest/mocks/idp.d.mts +26 -10
  264. package/dist/vitest/mocks/secretmanager.d.mts +16 -5
  265. package/dist/vitest/mocks/tailordb.d.mts +54 -10
  266. package/dist/vitest/mocks/workflow.d.mts +48 -11
  267. package/dist/vitest/setup.mjs +2 -2
  268. package/dist/{service_pb-B5w9rjPY.mjs → workspace_resource_pb-Db3fv68L.mjs} +57 -165
  269. package/dist/workspace_resource_pb-Db3fv68L.mjs.map +1 -0
  270. package/docs/cli/application.md +58 -11
  271. package/docs/cli/setup.md +1 -1
  272. package/docs/cli/workspace.md +6 -4
  273. package/docs/cli-reference.md +12 -8
  274. package/docs/runtime.md +3 -4
  275. package/docs/services/aigateway.md +2 -0
  276. package/docs/services/tailordb.md +52 -1
  277. package/docs/services/workflow.md +1 -1
  278. package/docs/testing.md +103 -89
  279. package/package.json +16 -16
  280. package/dist/application-BUfYmf0O.mjs.map +0 -1
  281. package/dist/application-DbvD5UUz.mjs +0 -3
  282. package/dist/cli/shared/trigger-context.d.mts +0 -1
  283. package/dist/errors-Dtf2WPaW.mjs +0 -42
  284. package/dist/errors-Dtf2WPaW.mjs.map +0 -1
  285. package/dist/field-runtime-9bfXBAOK.mjs +0 -183
  286. package/dist/field-runtime-9bfXBAOK.mjs.map +0 -1
  287. package/dist/job-D-PbD1P3.mjs +0 -55
  288. package/dist/job-D-PbD1P3.mjs.map +0 -1
  289. package/dist/logger-BEiZZ3qT.mjs.map +0 -1
  290. package/dist/registry-NfSW0BRo.mjs.map +0 -1
  291. package/dist/resource_pb-BRv7AMXK.mjs +0 -49
  292. package/dist/resource_pb-BRv7AMXK.mjs.map +0 -1
  293. package/dist/runtime-_vUgjiqT.mjs.map +0 -1
  294. package/dist/schema-DrVyN-LP.mjs.map +0 -1
  295. package/dist/secretmanager-Bd45j7an.mjs.map +0 -1
  296. package/dist/seed-fm0LeYP2.mjs.map +0 -1
  297. package/dist/service-CPMlIg3X.mjs +0 -3
  298. package/dist/service_pb-B5w9rjPY.mjs.map +0 -1
  299. package/dist/types-BwzB2okW.mjs +0 -199
  300. package/dist/types-BwzB2okW.mjs.map +0 -1
  301. package/dist/types-KlawuVKa.mjs +0 -4
@@ -1,20 +1,21 @@
1
1
  #!/usr/bin/env node
2
+ import { St as AuthInvokerSchema, T as CustomDomainStatus, U as FunctionExecution_Type, kt as PATScope } from "../workspace_resource_pb-Db3fv68L.mjs";
2
3
  import { t as assertDefined } from "../assert-DBxo8jPo.mjs";
3
- import { n as logger, r as styles } from "../logger-BEiZZ3qT.mjs";
4
- import { A as hasAnyUserTokenEntry, B as readPlatformConfig, Ct as toPageDirection, D as loadConfig, F as loadMachineUserName, G as defaultPlatformBaseUrl, H as saveUserTokens, K as fetchAll, L as loadStoredUserTokens, M as loadAccessToken, O as deleteUserTokens, P as loadConsoleBaseUrl, R as loadWorkspaceId, St as resolveMachineUserInputSource, T as hashContent$1, U as writePlatformConfig, V as resolveUserTokenKey, W as closeConnectionPool, X as fetchPlatformMachineUserToken, Y as fetchPaged, Z as fetchUserInfo, _ as platformBundleDefinePlugin, a as resolveInlineSourcemap, b as resolveBundleLogLevel, c as ResolverSchema, ct as configArg, et as getOrNull, it as isDefaultPlatform, j as hasUserTokenEntry, k as fetchLatestToken, lt as confirmationArgs, mt as multiConfigArg, nt as initOAuth2Client, pt as isVerbose, q as fetchAllTolerant, rt as initOperatorClient, s as WorkflowJobSchema, st as commonArgs, t as defineApplication, u as INVOKER_EXPR, ut as deploymentArgs, v as composeFunctionTreeshakeOptions, vt as pagedLogArgs, w as getDistDir, wt as workspaceArgs, y as createLogLevelTreeshakeOptions, yt as paginationArgs, z as platformConfigFromProfile } from "../application-BUfYmf0O.mjs";
5
- import { $t as compareSnapshotWithRemote, A as listCommand$12, An as apiCommand, C as listCommand$13, Cn as hasChanges, Dn as PluginManager, Dt as listCommand$6, E as waitCommand, En as sdkNameLabelKey, F as generateCommand$1, G as removeCommand$1, Gt as deploy, H as extractOwnedNamespaces, Ht as formatKeyValueTable, I as generateMigrationScript, It as getCommand$6, K as updateCommand$3, Kt as ensureConfigId, L as writeDbTypesFile, Mn as assertWritable, N as truncateCommand, Nn as defineAppCommand, O as resumeCommand, On as generateUserTypes, Pt as startCommand, Q as getCommand$5, Qt as parseMigrationLabelNumber, R as getConfiguredEditorCommand, Rt as executionsCommand, Sn as formatMigrationDiff, T as healthCommand, Tn as resourceTrn, Tt as triggerCommand, U as logBetaWarning, Ut as getCommand$1, V as showCommand, Vt as functionExecutionStatusToString, X as listCommand$11, Xt as MIGRATION_LABEL_KEY, Y as treeCommand, Zt as handleOptionalToRequiredError, _n as loadDiff, b as createCommand$4, bn as parseMigrationNumberArg, c as listCommand$14, cn as compareLocalTypesWithSnapshot, ct as createCommand$3, dn as getLatestMigrationNumber, en as generateAllTypeManifestsFromSnapshot, et as updateCommand$2, f as restoreCommand, ft as getCommand$3, g as getCommand$7, gn as isValidMigrationNumber, gt as listCommand$8, ht as tokenCommand, i as updateCommand$4, in as INITIAL_SCHEMA_NUMBER, it as getCommand$4, jt as jobsCommand, kn as prompt, m as listCommand$15, mn as getMigrationFiles, nt as listCommand$10, o as removeCommand, ot as deleteCommand$4, pn as getMigrationFilePath, qt as executeScript, r as queryCommand, sn as assertValidMigrationFiles, t as isNativeTypeScriptRuntime, tn as protoGqlPermission, u as inviteCommand, un as createSnapshotFromLocalTypes, ut as listCommand$9, v as deleteCommand$5, vn as reconstructSnapshotFromMigrations, vt as generate, wn as getNamespacesWithMigrations, wt as webhookCommand, xt as getCommand$2, yn as formatMigrationNumber, yt as listCommand$7, z as openInConfiguredEditor } from "../runtime-_vUgjiqT.mjs";
6
- import { n as ExecutorSchema } from "../service-BCRJ-3NV.mjs";
4
+ import { n as logger, r as styles } from "../logger-BwS4ppwO.mjs";
5
+ import { $n as deploymentArgs, $t as handleOptionalToRequiredError, An as generateUserTypes, At as startCommand, Bn as loadConsoleBaseUrl, Ct as listCommand$7, Dn as resourceTrn, Dt as jobsCommand, E as listCommand$13, En as getNamespacesWithMigrations, F as openInConfiguredEditor, Fn as deleteUserTokens, G as treeCommand, Gn as readPlatformConfig, H as updateCommand$3, Hn as loadStoredUserTokens, Ht as listCommand$16, In as fetchLatestToken, J as getCommand$5, Jn as writePlatformConfig, Jt as ensureConfigId, K as listCommand$12, Kn as resolveUserTokenKey, Kt as formatKeyValueTable, L as showCommand, Ln as hasAnyUserTokenEntry, Lt as functionExecutionStatusToString, M as generateMigrationScript, Mn as apiCall, Mt as getCommand$6, N as writeDbTypesFile, Nn as assertWritable, On as sdkNameLabelKey, P as getConfiguredEditorCommand, Pn as loadConfig, Pt as executionsCommand, Q as listCommand$11, Qn as confirmationArgs, Qt as MIGRATION_LABEL_KEY, R as extractOwnedNamespaces, Rn as hasUserTokenEntry, Rt as getCommand$1, S as waitCommand, Sn as parseMigrationNumberArg, Tn as hasChanges, Un as loadWorkspaceId, V as removeCommand$1, Vn as loadMachineUserName, Vt as deployFromCLI, Wn as platformConfigFromProfile, Wt as createCommand$4, X as updateCommand$2, Xn as commonArgs, Yn as defineAppCommand, Yt as executeScript, Zn as configArg, _t as getCommand$2, ar as toPageDirection, bn as reconstructSnapshotFromMigrations, bt as webhookCommand, c as listCommand$15, ct as getCommand$3, dt as tokenCommand, en as parseMigrationLabelNumber, er as isVerbose, et as getCommand$4, f as restoreCommand, fn as createSnapshotFromLocalTypes, ft as listCommand$9, g as deleteCommand$5, gn as getMigrationFiles, hn as getMigrationFilePath, ht as listCommand$8, i as updateCommand$4, ir as resolveMachineUserInputSource, it as createCommand$3, j as generateCommand$1, jn as prompt, k as truncateCommand, kn as PluginManager, ln as assertValidMigrationFiles, m as getCommand$7, mt as generate, nn as generateAllTypeManifestsFromSnapshot, nr as pagedLogArgs, nt as deleteCommand$4, o as removeCommand, on as INITIAL_SCHEMA_NUMBER, or as workspaceArgs, ot as listCommand$10, pn as getLatestMigrationNumber, qn as saveUserTokens, qt as workspaceNameSchema, r as queryCommand, rn as protoGqlPermission, rr as paginationArgs, t as isNativeTypeScriptRuntime, tn as compareSnapshotWithRemote, tr as multiConfigArg, u as inviteCommand, un as compareLocalTypesWithSnapshot, vn as isValidMigrationNumber, w as resumeCommand, wn as formatMigrationDiff, x as healthCommand, xn as formatMigrationNumber, xt as triggerCommand, y as listCommand$14, yn as loadDiff, z as logBetaWarning, zn as loadAccessToken } from "../runtime-BD2vYJFT.mjs";
6
+ import { A as fetchAllTolerant, B as initOperatorClient, D as closeConnectionPool, L as getOrNull, M as fetchPaged, N as fetchPlatformMachineUserToken, O as defaultPlatformBaseUrl, P as fetchUserInfo, T as hashContent$1, V as isDefaultPlatform, _ as platformBundleDefinePlugin, a as resolveInlineSourcemap, b as resolveBundleLogLevel, c as ResolverSchema, k as fetchAll, s as WorkflowJobSchema, t as defineApplication, u as INVOKER_EXPR, v as composeFunctionTreeshakeOptions, w as getDistDir, y as createLogLevelTreeshakeOptions, z as initOAuth2Client } from "../application-CUxVA7Fs.mjs";
7
+ import { n as ExecutorSchema } from "../service-D12iQGcS.mjs";
7
8
  import { t as multiline } from "../multiline-sfHpTZZK.mjs";
8
- import { r as isPluginGeneratedType } from "../seed-fm0LeYP2.mjs";
9
+ import { t as isPluginGeneratedType } from "../type-source-DH_LH20p.mjs";
9
10
  import { t as readPackageJson } from "../package-json-8b0O9TlX.mjs";
10
- import { i as userAgent } from "../secret-file-VSVGy1V0.mjs";
11
- import { n as isCLIError } from "../errors-Dtf2WPaW.mjs";
12
- import { B as FunctionExecution_Type, Ct as PATScope, T as CustomDomainStatus, gt as AuthInvokerSchema } from "../service_pb-B5w9rjPY.mjs";
13
- import { a as JSON_FOOTER_MARKER, i as CRASH_LOG_EXTENSION, o as parseCrashReportConfig, r as sendCrashReport, t as initCrashReporting } from "../crashreport-ayWANEZ6.mjs";
11
+ import { t as userAgent } from "../user-agent-DX2Jnw0-.mjs";
12
+ import { n as errorToJson, r as isCLIError, t as createCLIError } from "../errors-DVFS0AZk.mjs";
13
+ import { t as OperatorService } from "../service_pb-BoLM0X4K.mjs";
14
+ import { a as JSON_FOOTER_MARKER, i as CRASH_LOG_EXTENSION, o as parseCrashReportConfig, r as sendCrashReport, t as initCrashReporting } from "../crashreport-BNWUM6Kf.mjs";
14
15
  import { arg, defineCommand, runCommand, runMain } from "politty";
15
16
  import { withCompletionCommand } from "politty/completion";
16
17
  import { z } from "zod";
17
- import { create } from "@bufbuild/protobuf";
18
+ import { ScalarType, create } from "@bufbuild/protobuf";
18
19
  import * as fs$1 from "node:fs";
19
20
  import { timestampDate } from "@bufbuild/protobuf/wkt";
20
21
  import * as path from "pathe";
@@ -38,6 +39,561 @@ import { watch } from "chokidar";
38
39
  import * as fs from "fs";
39
40
  import { lookup } from "mime-types";
40
41
 
42
+ //#region src/cli/commands/api/proto-reflect.ts
43
+ const UNARY_METHODS = OperatorService.methods.filter((m) => m.methodKind === "unary");
44
+ function listMethodNames() {
45
+ return UNARY_METHODS.map((m) => m.name).toSorted();
46
+ }
47
+ /**
48
+ * Returns every accepted form of the `endpoint` positional — bare method name
49
+ * and fully-qualified `service/Method`. politty's expand completion keys its
50
+ * static table by the literal endpoint string, so both forms must appear in
51
+ * `choices` or the user typing the fully-qualified name gets no `--field`
52
+ * completion candidates back at TAB time.
53
+ * @returns Sorted list of accepted endpoint values
54
+ */
55
+ function listMethodChoices() {
56
+ return UNARY_METHODS.flatMap((m) => [m.name, `${OperatorService.typeName}/${m.name}`]).toSorted();
57
+ }
58
+ function getMethodDescriptor(methodName) {
59
+ return UNARY_METHODS.find((m) => m.name === methodName);
60
+ }
61
+ function extractMethodName(endpoint) {
62
+ if (!endpoint.includes("/")) return endpoint;
63
+ return endpoint.split("/").pop() ?? endpoint;
64
+ }
65
+ /**
66
+ * Returns the nested message descriptor when the field is a message, a list of
67
+ * messages, or a map with message values. Otherwise returns undefined.
68
+ * @param field - The proto field descriptor to inspect
69
+ * @returns The nested message descriptor, or undefined when the field isn't message-shaped
70
+ */
71
+ function nestedMessage(field) {
72
+ if (field.fieldKind === "message") return field.message;
73
+ if (field.fieldKind === "list" && field.listKind === "message") return field.message;
74
+ if (field.fieldKind === "map" && field.mapKind === "message") return field.message;
75
+ }
76
+ /**
77
+ * Most `google.protobuf.*` well-known types serialize as scalars in proto JSON
78
+ * (Timestamp/Duration → RFC3339/duration string, FieldMask → comma-joined
79
+ * string, *Value wrappers → underlying primitive, etc.), so we must not let
80
+ * `--field` drill into their internal fields. Treating them as leaves keeps
81
+ * the completion and the body shape consistent with what the server expects.
82
+ * @param message - The proto message descriptor to inspect
83
+ * @returns True when the message is a well-known type
84
+ */
85
+ function isWellKnownType(message) {
86
+ return message.typeName.startsWith("google.protobuf.");
87
+ }
88
+ const UNREPRESENTABLE_WELL_KNOWN_TYPES = /* @__PURE__ */ new Set([
89
+ "google.protobuf.Struct",
90
+ "google.protobuf.Value",
91
+ "google.protobuf.ListValue",
92
+ "google.protobuf.NullValue",
93
+ "google.protobuf.Any",
94
+ "google.protobuf.Empty"
95
+ ]);
96
+ /**
97
+ * @param message - The proto message descriptor to inspect
98
+ * @returns True when the message is a well-known type that `--field` cannot represent
99
+ */
100
+ function isUnrepresentableWellKnownType(message) {
101
+ return UNREPRESENTABLE_WELL_KNOWN_TYPES.has(message.typeName);
102
+ }
103
+ /**
104
+ * Pre-enumerates every `--field` completion candidate for `methodName`,
105
+ * walking the input message tree to produce a flat list that the shell can
106
+ * prefix-filter at TAB time. Used by the `expand` completion variant so no
107
+ * Node process is spawned per keystroke.
108
+ *
109
+ * For each leaf field, emits `key=` (key completion). Enum leaves additionally
110
+ * emit `key=ENUM_VALUE` per value, bool leaves emit `key=true` and
111
+ * `key=false`. For nested messages, emits `key.` (drill-down) and recurses.
112
+ *
113
+ * Returns an empty array when `methodName` is unknown so the `expand`
114
+ * generator stays exception-free at script-generation time.
115
+ * @param methodName - Name of the unary RPC whose input message is being walked
116
+ * @returns Flat list of `{ value, description }` candidates
117
+ */
118
+ function enumerateAllFieldCompletions(methodName) {
119
+ const method = getMethodDescriptor(methodName);
120
+ if (!method) return [];
121
+ const candidates = [];
122
+ const visited = /* @__PURE__ */ new Set();
123
+ function walk(message, prefix) {
124
+ visited.add(message);
125
+ for (const field of message.fields) {
126
+ if (field.fieldKind === "list" || field.fieldKind === "map") continue;
127
+ const fullKey = prefix + field.localName;
128
+ if (field.fieldKind === "message") {
129
+ if (isUnrepresentableWellKnownType(field.message)) continue;
130
+ if (!isWellKnownType(field.message)) {
131
+ const nested = field.message;
132
+ candidates.push({
133
+ value: `${fullKey}.`,
134
+ description: `${fullKey} (message)`
135
+ });
136
+ if (!visited.has(nested)) walk(nested, `${fullKey}.`);
137
+ continue;
138
+ }
139
+ }
140
+ candidates.push({
141
+ value: `${fullKey}=`,
142
+ description: `Set ${fullKey}`
143
+ });
144
+ if (field.fieldKind === "enum") for (const v of field.enum.values) candidates.push({
145
+ value: `${fullKey}=${v.name}`,
146
+ description: v.name
147
+ });
148
+ else if (field.fieldKind === "scalar" && field.scalar === ScalarType.BOOL) {
149
+ candidates.push({
150
+ value: `${fullKey}=true`,
151
+ description: "true"
152
+ });
153
+ candidates.push({
154
+ value: `${fullKey}=false`,
155
+ description: "false"
156
+ });
157
+ }
158
+ }
159
+ visited.delete(message);
160
+ }
161
+ walk(method.input, "");
162
+ return candidates;
163
+ }
164
+ /**
165
+ * Resolves the leaf `DescField` at a dotted `--field` path within an input
166
+ * message tree. Returns undefined when any segment is missing or when a
167
+ * non-leaf segment isn't a singular message — callers fall back to treating
168
+ * the value as a string in that case.
169
+ * @param input - The RPC input message descriptor
170
+ * @param path - Dot-split path segments to follow (e.g. ["application", "name"])
171
+ * @returns The leaf field descriptor, or undefined when the path doesn't resolve
172
+ */
173
+ function resolveLeafField(input, path) {
174
+ let message = input;
175
+ for (let i = 0; i < path.length; i++) {
176
+ const field = message.fields.find((f) => f.localName === path[i]);
177
+ if (!field) return void 0;
178
+ if (i === path.length - 1) {
179
+ if (field.fieldKind === "message" && isUnrepresentableWellKnownType(field.message)) return;
180
+ return field;
181
+ }
182
+ if (field.fieldKind !== "message") return void 0;
183
+ if (isWellKnownType(field.message)) return void 0;
184
+ message = field.message;
185
+ }
186
+ }
187
+
188
+ //#endregion
189
+ //#region src/cli/commands/api/render.ts
190
+ const SCALAR_LABEL = {
191
+ [ScalarType.DOUBLE]: "double",
192
+ [ScalarType.FLOAT]: "float",
193
+ [ScalarType.INT64]: "int64",
194
+ [ScalarType.UINT64]: "uint64",
195
+ [ScalarType.INT32]: "int32",
196
+ [ScalarType.FIXED64]: "fixed64",
197
+ [ScalarType.FIXED32]: "fixed32",
198
+ [ScalarType.BOOL]: "bool",
199
+ [ScalarType.STRING]: "string",
200
+ [ScalarType.BYTES]: "bytes",
201
+ [ScalarType.UINT32]: "uint32",
202
+ [ScalarType.SFIXED32]: "sfixed32",
203
+ [ScalarType.SFIXED64]: "sfixed64",
204
+ [ScalarType.SINT32]: "sint32",
205
+ [ScalarType.SINT64]: "sint64"
206
+ };
207
+ function shortName(typeName) {
208
+ const dot = typeName.lastIndexOf(".");
209
+ return dot < 0 ? typeName : typeName.slice(dot + 1);
210
+ }
211
+ function scalarLabel(scalar) {
212
+ return SCALAR_LABEL[scalar] ?? `scalar(${scalar})`;
213
+ }
214
+ function enumLabel(enumDesc) {
215
+ return `enum ${shortName(enumDesc.typeName)}`;
216
+ }
217
+ function enumOf(field) {
218
+ if (field.fieldKind === "enum") return field.enum;
219
+ if (field.fieldKind === "list" && field.listKind === "enum") return field.enum;
220
+ }
221
+ function describeFieldType(field) {
222
+ switch (field.fieldKind) {
223
+ case "scalar": return scalarLabel(field.scalar);
224
+ case "enum": return enumLabel(field.enum);
225
+ case "message": return shortName(field.message.typeName);
226
+ case "list": {
227
+ let inner;
228
+ if (field.listKind === "scalar") inner = scalarLabel(field.scalar);
229
+ else if (field.listKind === "enum") inner = enumLabel(field.enum);
230
+ else inner = shortName(field.message.typeName);
231
+ return `repeated ${inner}`;
232
+ }
233
+ case "map": {
234
+ const keyType = scalarLabel(field.mapKey);
235
+ let valType;
236
+ if (field.mapKind === "scalar") valType = scalarLabel(field.scalar);
237
+ else if (field.mapKind === "enum") valType = enumLabel(field.enum);
238
+ else valType = shortName(field.message.typeName);
239
+ return `map<${keyType}, ${valType}>`;
240
+ }
241
+ default: return "<unknown>";
242
+ }
243
+ }
244
+ function fieldToJson(field, visited) {
245
+ const json = {
246
+ name: field.localName,
247
+ protoName: field.name,
248
+ type: describeFieldType(field),
249
+ fieldKind: field.fieldKind,
250
+ repeated: field.fieldKind === "list"
251
+ };
252
+ if (field.oneof) json.oneof = field.oneof.name;
253
+ const fieldEnum = enumOf(field);
254
+ if (fieldEnum) json.enumValues = fieldEnum.values.map((v) => v.name);
255
+ const nested = nestedMessage(field);
256
+ if (nested && !visited.has(nested)) {
257
+ visited.add(nested);
258
+ json.message = {
259
+ typeName: nested.typeName,
260
+ fields: nested.fields.map((f) => fieldToJson(f, visited))
261
+ };
262
+ visited.delete(nested);
263
+ } else if (nested) json.message = {
264
+ typeName: nested.typeName,
265
+ fields: [],
266
+ recursive: true
267
+ };
268
+ return json;
269
+ }
270
+ function renderInspectJson(method) {
271
+ const visited = /* @__PURE__ */ new Set([method.input]);
272
+ return {
273
+ method: method.name,
274
+ input: {
275
+ typeName: method.input.typeName,
276
+ fields: method.input.fields.map((f) => fieldToJson(f, visited))
277
+ },
278
+ output: { typeName: method.output.typeName }
279
+ };
280
+ }
281
+ function renderFieldText(field, indent, visited) {
282
+ const lines = [];
283
+ const oneofTag = field.oneof ? ` (oneof ${field.oneof.name})` : "";
284
+ lines.push(`${indent}${field.localName}: ${describeFieldType(field)}${oneofTag}`);
285
+ const fieldEnum = enumOf(field);
286
+ if (fieldEnum) {
287
+ const values = fieldEnum.values.map((v) => v.name).join(", ");
288
+ lines.push(`${indent} values: ${values}`);
289
+ }
290
+ const nested = nestedMessage(field);
291
+ if (nested && !visited.has(nested)) {
292
+ visited.add(nested);
293
+ for (const sub of nested.fields) lines.push(...renderFieldText(sub, `${indent} `, visited));
294
+ visited.delete(nested);
295
+ } else if (nested) lines.push(`${indent} …(recursive ${nested.typeName})`);
296
+ return lines;
297
+ }
298
+ function renderInspectText(method) {
299
+ const lines = [];
300
+ lines.push(`${method.name}`);
301
+ lines.push(` request: ${method.input.typeName}`);
302
+ const visited = /* @__PURE__ */ new Set([method.input]);
303
+ for (const f of method.input.fields) lines.push(...renderFieldText(f, " ", visited));
304
+ lines.push(` response: ${method.output.typeName}`);
305
+ return lines.join("\n");
306
+ }
307
+
308
+ //#endregion
309
+ //#region src/cli/commands/api/inspect.ts
310
+ const inspectCommand = defineAppCommand({
311
+ name: "inspect",
312
+ description: "Print the input message tree of an OperatorService endpoint.",
313
+ notes: "Combine with the global `--json` flag for a machine-readable descriptor. Recursive type references and `oneof` membership are annotated. Use `tailor-sdk api list` to discover endpoint names.",
314
+ examples: [{
315
+ cmd: "GetApplication",
316
+ desc: "Show fields of GetApplicationRequest."
317
+ }, {
318
+ cmd: "CreateExecutorExecutor",
319
+ desc: "Inspect a deeply nested input with `(oneof config)` annotations."
320
+ }],
321
+ args: z.object({ endpoint: arg(z.string(), {
322
+ positional: true,
323
+ description: "API endpoint to inspect (e.g., 'GetApplication' or 'tailor.v1.OperatorService/GetApplication').",
324
+ completion: { custom: { choices: listMethodNames() } }
325
+ }) }).strict(),
326
+ run: (args) => {
327
+ const methodName = extractMethodName(args.endpoint);
328
+ const method = getMethodDescriptor(methodName);
329
+ if (!method) throw createCLIError({
330
+ message: `unknown method: ${methodName}`,
331
+ suggestion: "Run `tailor-sdk api list` to see available methods.",
332
+ command: "api inspect"
333
+ });
334
+ if (logger.jsonMode) logger.out(renderInspectJson(method));
335
+ else logger.out(renderInspectText(method));
336
+ }
337
+ });
338
+
339
+ //#endregion
340
+ //#region src/cli/commands/api/list.ts
341
+ const listCommand$6 = defineAppCommand({
342
+ name: "list",
343
+ description: "List all invocable OperatorService methods.",
344
+ notes: "Only single-request (non-streaming) methods are listed, because the CLI issues a single JSON request and reads one JSON response.",
345
+ args: z.object({}).strict(),
346
+ run: () => {
347
+ const names = listMethodNames();
348
+ if (logger.jsonMode) logger.out(names);
349
+ else for (const name of names) logger.out(name);
350
+ }
351
+ });
352
+
353
+ //#endregion
354
+ //#region src/cli/commands/api/index.ts
355
+ function resolveNamespaceName(methodName, config) {
356
+ if (/Auth|Tenant|UserProfile/.test(methodName)) return config.auth?.name;
357
+ if (/IdP/.test(methodName)) {
358
+ if (config.idp?.length === 1) return assertDefined(config.idp[0], "idp config missing").name;
359
+ return;
360
+ }
361
+ if (/TailorDB/.test(methodName)) {
362
+ const keys = Object.keys(config.db ?? {});
363
+ if (keys.length === 1) return keys[0];
364
+ return;
365
+ }
366
+ if (/Pipeline/.test(methodName)) {
367
+ const keys = Object.keys(config.resolver ?? {});
368
+ if (keys.length === 1) return keys[0];
369
+ return;
370
+ }
371
+ }
372
+ /**
373
+ * Parse a JSON body string as a plain object for field injection.
374
+ * Returns undefined for invalid JSON or non-object values (null, arrays, primitives),
375
+ * so callers can fall back to sending the raw string unchanged.
376
+ * @param body - Raw body string
377
+ * @returns Parsed object or undefined
378
+ */
379
+ function parseBodyAsObject(body) {
380
+ let parsed;
381
+ try {
382
+ parsed = JSON.parse(body);
383
+ } catch {
384
+ return;
385
+ }
386
+ if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) return;
387
+ return parsed;
388
+ }
389
+ /**
390
+ * Set a dotted path on a body object, replacing non-object intermediates as
391
+ * needed. `--field` takes precedence over `--body`, so collisions overwrite.
392
+ * @param obj - The body object to mutate
393
+ * @param path - Dot-split path segments (e.g. ["application", "name"])
394
+ * @param value - Value to assign at the leaf
395
+ */
396
+ function setNestedPath(obj, path, value) {
397
+ let cursor = obj;
398
+ for (let i = 0; i < path.length - 1; i++) {
399
+ const key = assertDefined(path[i], "path segment missing");
400
+ const next = cursor[key];
401
+ if (typeof next !== "object" || next === null || Array.isArray(next)) cursor[key] = {};
402
+ cursor = cursor[key];
403
+ }
404
+ cursor[assertDefined(path[path.length - 1], "path last segment missing")] = value;
405
+ }
406
+ /**
407
+ * Coerces a raw `--field` string value to match the leaf proto type so the
408
+ * JSON body sends a properly typed value. Today we only coerce bool — the
409
+ * completion candidates explicitly suggest `=true`/`=false`, so sending the
410
+ * literal string "true" would be a visible mismatch. Other scalars are left
411
+ * as strings: proto JSON accepts string forms for ints/floats/int64/etc.,
412
+ * and we'd rather pass through what the user typed than silently coerce.
413
+ * @param field - The resolved leaf field descriptor, or undefined when the path didn't resolve
414
+ * @param raw - The raw string value after `=`
415
+ * @returns The value to write into the body object
416
+ */
417
+ function coerceFieldValue(field, raw) {
418
+ if (field && field.fieldKind === "scalar" && field.scalar === ScalarType.BOOL) {
419
+ if (raw === "true") return true;
420
+ if (raw === "false") return false;
421
+ throw new Error(`Invalid value for bool field: '${raw}'. Expected 'true' or 'false'.`);
422
+ }
423
+ return raw;
424
+ }
425
+ /**
426
+ * Collapse top-level body keys that address a known input field by its
427
+ * protobuf name (snake_case) or JSON name to the field's `localName`. protojson
428
+ * accepts every alias, so converging them here lets the presence checks below
429
+ * reason in a single namespace — otherwise a `--body` written as
430
+ * `{"workspace_id": ...}` slips past the camelCase check and we inject a second
431
+ * `workspaceId`, which the server rejects as a duplicate field. When both forms
432
+ * are present the canonical key wins and the alias is dropped.
433
+ * @param body - The parsed body object to mutate
434
+ * @param fields - The target endpoint's input fields
435
+ * @returns Whether any key was rewritten
436
+ */
437
+ function normalizeBodyFieldKeys(body, fields) {
438
+ const aliasToLocal = /* @__PURE__ */ new Map();
439
+ for (const f of fields) {
440
+ aliasToLocal.set(f.name, f.localName);
441
+ aliasToLocal.set(f.jsonName, f.localName);
442
+ }
443
+ let changed = false;
444
+ for (const key of Object.keys(body)) {
445
+ const local = aliasToLocal.get(key);
446
+ if (!local || local === key) continue;
447
+ if (!Object.hasOwn(body, local)) body[local] = body[key];
448
+ delete body[key];
449
+ changed = true;
450
+ }
451
+ return changed;
452
+ }
453
+ const FORBIDDEN_SEGMENTS = /* @__PURE__ */ new Set([
454
+ "__proto__",
455
+ "constructor",
456
+ "prototype"
457
+ ]);
458
+ const fieldArg = z.string().transform((val, ctx) => {
459
+ const eq = val.indexOf("=");
460
+ if (eq < 0) {
461
+ ctx.addIssue({
462
+ code: z.ZodIssueCode.custom,
463
+ message: `Invalid field format: '${val}'. Expected format: 'key=value' or 'a.b.c=value'`
464
+ });
465
+ return z.NEVER;
466
+ }
467
+ const key = val.slice(0, eq);
468
+ if (key.length === 0) {
469
+ ctx.addIssue({
470
+ code: z.ZodIssueCode.custom,
471
+ message: "Field key cannot be empty"
472
+ });
473
+ return z.NEVER;
474
+ }
475
+ const segments = key.split(".");
476
+ if (segments.some((seg) => seg.length === 0)) {
477
+ ctx.addIssue({
478
+ code: z.ZodIssueCode.custom,
479
+ message: `Invalid field key: '${key}'. Dotted segments cannot be empty`
480
+ });
481
+ return z.NEVER;
482
+ }
483
+ const forbidden = segments.find((seg) => FORBIDDEN_SEGMENTS.has(seg));
484
+ if (forbidden) {
485
+ ctx.addIssue({
486
+ code: z.ZodIssueCode.custom,
487
+ message: `Invalid field key: '${key}'. Segment '${forbidden}' is not allowed.`
488
+ });
489
+ return z.NEVER;
490
+ }
491
+ return {
492
+ path: segments,
493
+ value: val.slice(eq + 1)
494
+ };
495
+ });
496
+ const apiCommand = defineAppCommand({
497
+ name: "api",
498
+ description: "Call Tailor Platform API endpoints directly.",
499
+ notes: `Use \`tailor-sdk api list\` to enumerate invocable methods and \`tailor-sdk api inspect <endpoint>\` to print an endpoint's input message tree (combine with \`--json\` for machine-readable output).
500
+
501
+ The request body is inferred from the target endpoint's request schema, and commonly required fields are auto-injected so they can be omitted from \`--body\`:
502
+
503
+ - \`workspaceId\` — resolved from \`-w\` / \`TAILOR_PLATFORM_WORKSPACE_ID\` / the selected profile.
504
+ - \`namespaceName\` — resolved from \`tailor.config.ts\` based on the endpoint's service:
505
+ - Auth / Tenant / UserProfile endpoints use \`auth.name\`.
506
+ - IdP / TailorDB / Pipeline endpoints use the sole configured namespace when exactly one is defined.
507
+
508
+ Values already present in \`--body\` are never overridden. If a value cannot be resolved (e.g. no config found), injection is silently skipped and the server-side validation error takes precedence.
509
+
510
+ Use \`--field key=value\` (repeatable) to set request body fields without writing JSON. Dotted keys (e.g. \`application.name=foo\`) build nested objects. \`--field\` overrides matching fields in \`--body\` and tab-completes from the endpoint's request schema.`,
511
+ examples: [
512
+ {
513
+ cmd: "GetApplication -b '{\"applicationName\":\"app-1\"}'",
514
+ desc: "Call an endpoint; workspaceId is auto-injected."
515
+ },
516
+ {
517
+ cmd: "GetApplication -f applicationName=app-1",
518
+ desc: "Same as above, using --field instead of --body."
519
+ },
520
+ {
521
+ cmd: "list",
522
+ desc: "List all invocable OperatorService methods."
523
+ },
524
+ {
525
+ cmd: "inspect GetApplication",
526
+ desc: "Show the input message tree for an endpoint."
527
+ }
528
+ ],
529
+ subCommands: {
530
+ list: listCommand$6,
531
+ inspect: inspectCommand
532
+ },
533
+ args: z.object({
534
+ ...workspaceArgs,
535
+ ...configArg,
536
+ body: arg(z.string().default("{}"), {
537
+ alias: "b",
538
+ description: "Request body as JSON."
539
+ }),
540
+ field: arg(fieldArg.array().optional(), {
541
+ alias: "f",
542
+ description: "Set a body field as `key=value` (repeatable; dotted keys nest). Overrides --body.",
543
+ completion: { custom: { expand: {
544
+ dependsOn: ["endpoint"],
545
+ enumerate: ({ endpoint }) => enumerateAllFieldCompletions(extractMethodName(endpoint ?? ""))
546
+ } } }
547
+ }),
548
+ endpoint: arg(z.string(), {
549
+ positional: true,
550
+ description: "API endpoint to call (e.g., 'GetApplication' or 'tailor.v1.OperatorService/GetApplication').",
551
+ completion: { custom: { choices: listMethodChoices() } }
552
+ })
553
+ }).strict(),
554
+ run: async (args) => {
555
+ await assertWritable({ profile: args.profile });
556
+ const methodName = extractMethodName(args.endpoint);
557
+ const method = getMethodDescriptor(methodName);
558
+ const parsedBody = parseBodyAsObject(args.body);
559
+ let mutated = false;
560
+ if (args.field && args.field.length > 0) {
561
+ if (!parsedBody) throw new Error("--field requires --body to be a JSON object (or omitted).");
562
+ for (const f of args.field) {
563
+ const leaf = method ? resolveLeafField(method.input, f.path) : void 0;
564
+ setNestedPath(parsedBody, f.path, coerceFieldValue(leaf, f.value));
565
+ }
566
+ mutated = true;
567
+ }
568
+ if (parsedBody && method) {
569
+ if (normalizeBodyFieldKeys(parsedBody, method.input.fields)) mutated = true;
570
+ const fieldNames = method.input.fields.map((f) => f.localName);
571
+ if (fieldNames.includes("workspaceId") && !Object.hasOwn(parsedBody, "workspaceId")) try {
572
+ parsedBody.workspaceId = await loadWorkspaceId({
573
+ workspaceId: args["workspace-id"],
574
+ profile: args.profile
575
+ });
576
+ mutated = true;
577
+ } catch {}
578
+ if (fieldNames.includes("namespaceName") && !Object.hasOwn(parsedBody, "namespaceName")) try {
579
+ const { config } = await loadConfig(args.config);
580
+ const ns = resolveNamespaceName(methodName, config);
581
+ if (ns) {
582
+ parsedBody.namespaceName = ns;
583
+ mutated = true;
584
+ }
585
+ } catch {}
586
+ }
587
+ const result = await apiCall({
588
+ profile: args.profile,
589
+ endpoint: args.endpoint,
590
+ body: mutated && parsedBody ? JSON.stringify(parsedBody) : args.body
591
+ });
592
+ logger.out(JSON.stringify(result.data, null, 2));
593
+ }
594
+ });
595
+
596
+ //#endregion
41
597
  //#region src/cli/commands/authconnection/args.ts
42
598
  /**
43
599
  * Arguments for identifying an auth connection
@@ -467,6 +1023,35 @@ const crashReportCommand = defineCommand({
467
1023
  }
468
1024
  });
469
1025
 
1026
+ //#endregion
1027
+ //#region src/parser/service/resolver/local-input-parser.ts
1028
+ /**
1029
+ * Build a local, in-process validator for a resolver's declared input fields.
1030
+ * Each field already carries its own bound `_parseInternal` (attached when the
1031
+ * user's resolver module was loaded via dynamic import), so this only needs to
1032
+ * orchestrate calling every field and collecting issues.
1033
+ * @param fields - Resolver's raw input field definitions (already-built TailorField instances)
1034
+ * @returns An object exposing a `.parse()` method for local format detection
1035
+ */
1036
+ function buildLocalInputParser(fields) {
1037
+ return { parse(args) {
1038
+ const { value, data, user } = args;
1039
+ if (typeof value !== "object" || value === null || Array.isArray(value) || value instanceof Date) return { issues: [{ message: `Expected an object: received ${String(value)}` }] };
1040
+ const record = value;
1041
+ const issues = [];
1042
+ for (const [name, field] of Object.entries(fields)) {
1043
+ const result = field._parseInternal({
1044
+ value: record[name],
1045
+ data,
1046
+ user,
1047
+ pathArray: [name]
1048
+ });
1049
+ if (result.issues) issues.push(...result.issues);
1050
+ }
1051
+ return issues.length > 0 ? { issues } : {};
1052
+ } };
1053
+ }
1054
+
470
1055
  //#endregion
471
1056
  //#region src/cli/commands/deploy/index.ts
472
1057
  const deployCommand$1 = defineAppCommand({
@@ -477,6 +1062,17 @@ const deployCommand$1 = defineAppCommand({
477
1062
  ...workspaceArgs,
478
1063
  ...multiConfigArg,
479
1064
  ...confirmationArgs,
1065
+ "create-workspace": arg(z.boolean().optional(), { description: "Create a workspace when the account has none" }),
1066
+ "workspace-name": arg(z.string().optional(), { description: "Name for a workspace created during deploy" }),
1067
+ "workspace-region": arg(z.string().optional(), { description: "Region for a workspace created during deploy" }),
1068
+ "organization-id": arg(z.string().optional(), {
1069
+ description: "Organization ID for a workspace created during deploy",
1070
+ env: "TAILOR_PLATFORM_ORGANIZATION_ID"
1071
+ }),
1072
+ "folder-id": arg(z.string().optional(), {
1073
+ description: "Folder ID for a workspace created during deploy",
1074
+ env: "TAILOR_PLATFORM_FOLDER_ID"
1075
+ }),
480
1076
  "dry-run": arg(z.boolean().optional(), {
481
1077
  alias: "d",
482
1078
  description: "Run the command without making any changes"
@@ -490,16 +1086,26 @@ const deployCommand$1 = defineAppCommand({
490
1086
  await assertWritable({ profile: args.profile });
491
1087
  const { initTelemetry } = await import("../telemetry-ClwW5ohF.mjs");
492
1088
  await initTelemetry();
493
- await deploy({
1089
+ await deployFromCLI({
494
1090
  workspaceId: args["workspace-id"],
495
1091
  profile: args.profile,
496
1092
  configPath: args.config,
497
1093
  dryRun: args["dry-run"],
498
1094
  yes: args.yes,
1095
+ createWorkspace: args["create-workspace"],
1096
+ workspaceName: args["workspace-name"],
1097
+ workspaceRegion: args["workspace-region"],
1098
+ organizationId: args["organization-id"],
1099
+ folderId: args["folder-id"],
499
1100
  noSchemaCheck: args["no-schema-check"],
500
1101
  noValidate: args["no-validate"],
501
1102
  noCache: args["no-cache"],
502
1103
  cleanCache: args["clean-cache"]
1104
+ }, {
1105
+ envFile: args["env-file"],
1106
+ envFileIfExists: args["env-file-if-exists"],
1107
+ verbose: args.verbose,
1108
+ json: args.json
503
1109
  });
504
1110
  }
505
1111
  });
@@ -512,12 +1118,12 @@ const executorCommand = defineCommand({
512
1118
  subCommands: {
513
1119
  trigger: triggerCommand,
514
1120
  jobs: jobsCommand,
515
- list: listCommand$6,
1121
+ list: listCommand$7,
516
1122
  get: getCommand$1,
517
1123
  webhook: webhookCommand
518
1124
  },
519
1125
  async run() {
520
- await runCommand(listCommand$6, []);
1126
+ await runCommand(listCommand$7, []);
521
1127
  }
522
1128
  });
523
1129
 
@@ -1287,10 +1893,7 @@ async function detectFunctionType(options) {
1287
1893
  if (resolverResult.success) {
1288
1894
  const rawInput = module.default.input;
1289
1895
  let inputSchema;
1290
- if (rawInput) {
1291
- const { t } = await import("../types-KlawuVKa.mjs");
1292
- inputSchema = t.object(rawInput);
1293
- }
1896
+ if (rawInput) inputSchema = buildLocalInputParser(rawInput);
1294
1897
  return {
1295
1898
  type: "resolver",
1296
1899
  name: resolverResult.data.name,
@@ -1650,12 +2253,12 @@ const functionCommand = defineCommand({
1650
2253
  description: "Manage functions",
1651
2254
  subCommands: {
1652
2255
  get: getCommand$2,
1653
- list: listCommand$7,
2256
+ list: listCommand$8,
1654
2257
  logs: logsCommand,
1655
2258
  "test-run": testRunCommand
1656
2259
  },
1657
2260
  async run() {
1658
- await runCommand(listCommand$7, []);
2261
+ await runCommand(listCommand$8, []);
1659
2262
  }
1660
2263
  });
1661
2264
 
@@ -1988,11 +2591,11 @@ const machineuserCommand = defineCommand({
1988
2591
  name: "machineuser",
1989
2592
  description: "Manage machine users in your Tailor Platform application.",
1990
2593
  subCommands: {
1991
- list: listCommand$8,
2594
+ list: listCommand$9,
1992
2595
  token: tokenCommand
1993
2596
  },
1994
2597
  async run() {
1995
- await runCommand(listCommand$8, []);
2598
+ await runCommand(listCommand$9, []);
1996
2599
  }
1997
2600
  });
1998
2601
 
@@ -2002,11 +2605,11 @@ const oauth2clientCommand = defineCommand({
2002
2605
  name: "oauth2client",
2003
2606
  description: "Manage OAuth2 clients in your Tailor Platform application.",
2004
2607
  subCommands: {
2005
- list: listCommand$9,
2608
+ list: listCommand$10,
2006
2609
  get: getCommand$3
2007
2610
  },
2008
2611
  async run() {
2009
- await runCommand(listCommand$9, []);
2612
+ await runCommand(listCommand$10, []);
2010
2613
  }
2011
2614
  });
2012
2615
 
@@ -2063,7 +2666,7 @@ const folderCommand = defineCommand({
2063
2666
  create: createCommand$3,
2064
2667
  delete: deleteCommand$4,
2065
2668
  get: getCommand$4,
2066
- list: listCommand$10,
2669
+ list: listCommand$11,
2067
2670
  update: updateCommand$2
2068
2671
  }
2069
2672
  });
@@ -2076,12 +2679,12 @@ const organizationCommand = defineCommand({
2076
2679
  subCommands: {
2077
2680
  folder: folderCommand,
2078
2681
  get: getCommand$5,
2079
- list: listCommand$11,
2682
+ list: listCommand$12,
2080
2683
  tree: treeCommand,
2081
2684
  update: updateCommand$3
2082
2685
  },
2083
2686
  async run() {
2084
- await runCommand(listCommand$11, []);
2687
+ await runCommand(listCommand$12, []);
2085
2688
  }
2086
2689
  });
2087
2690
 
@@ -2876,23 +3479,23 @@ function findTarget(lock, kind, workspaceName) {
2876
3479
 
2877
3480
  //#endregion
2878
3481
  //#region src/cli/commands/setup/action.yml
2879
- var action_default = "# __HEADER__\nname: __WORKSPACE_NAME__\ndescription: >-\n Deploy __WORKSPACE_NAME__ to Tailor Platform.\n Checkout and dependency installation are expected to be handled by the caller.\n\ninputs:\n workspace-id:\n description: Tailor Platform workspace id\n required: true\n name:\n description: Workspace name (used in Slack notifications)\n required: true\n working-directory:\n description: App directory relative to the repository root\n required: false\n default: \".\"\n config:\n description: SDK config path, or comma-separated config paths for multi-config deploys\n required: false\n default: \"tailor.config.ts\"\n deploy:\n description: Whether to run the Tailor deploy step after build steps\n required: false\n default: \"true\"\n build-site:\n description: Whether to run the static website build slot when present\n required: false\n default: \"true\"\n platform-client-id:\n description: Machine-user client id\n required: true\n platform-client-secret:\n description: Machine-user client secret\n required: true\n slack-token:\n description: Slack bot token\n required: false\n slack-channel-id:\n description: Slack channel id\n required: false\n user-mapping:\n description: JSON string mapping GitHub usernames to Slack user IDs\n required: false\n package-manager:\n description: Package manager used for dependency installation (pnpm, npm, yarn, bun)\n required: false\n default: pnpm\n\noutputs:\n app-url:\n description: Deployed application URL\n value: ${{ steps.tailor-apply.outputs.app-url }}\n\nruns:\n using: composite\n steps:\n # __STATIC_WEBSITE_BUILD_START__\n - id: build-site\n if: inputs.build-site == 'true'\n shell: bash\n run: |\n # Replace with your static website build command.\n # Example: pnpm --filter <package-name> run build:static\n # Note: this run: command is user-editable. Custom build commands are preserved across\n # reruns and are not treated as drift by setup check. Other edits to this file are flagged\n # as drift and will be overwritten if you re-run setup action with --force.\n true\n # __STATIC_WEBSITE_BUILD_END__\n - id: tailor-apply\n if: inputs.deploy == 'true'\n uses: tailor-platform/actions/deploy@e74173d4bdd931d036ad359cf5f7729fc6aa7067 # v1.5.1\n env:\n TAILOR_PLATFORM_SDK_CONFIG_PATH: ${{ inputs.config }}\n with:\n workspace-id: ${{ inputs.workspace-id }}\n working-directory: ${{ inputs.working-directory }}\n package-manager: ${{ inputs.package-manager }}\n platform-client-id: ${{ inputs.platform-client-id }}\n platform-client-secret: ${{ inputs.platform-client-secret }}\n - id: tailor-notify\n if: failure() && inputs.slack-token != '' && inputs.slack-channel-id != ''\n uses: tailor-platform/actions/notify@e74173d4bdd931d036ad359cf5f7729fc6aa7067 # v1.5.1\n with:\n provider: slack\n status: failure\n workspace-name: ${{ inputs.name }}\n slack-token: ${{ inputs.slack-token }}\n slack-channel-id: ${{ inputs.slack-channel-id }}\n user-mapping: ${{ inputs.user-mapping }}\n";
3482
+ var action_default = "# __HEADER__\nname: __WORKSPACE_NAME__\ndescription: >-\n Deploy __WORKSPACE_NAME__ to Tailor Platform.\n Checkout and dependency installation are expected to be handled by the caller.\n\ninputs:\n workspace-id:\n description: Tailor Platform workspace id\n required: true\n name:\n description: Workspace name (used in Slack notifications)\n required: true\n working-directory:\n description: App directory relative to the repository root\n required: false\n default: \".\"\n config:\n description: SDK config path, or comma-separated config paths for multi-config deploys\n required: false\n default: \"tailor.config.ts\"\n deploy:\n description: Whether to run the Tailor deploy step after build steps\n required: false\n default: \"true\"\n build-site:\n description: Whether to run the static website build slot when present\n required: false\n default: \"true\"\n platform-client-id:\n description: Machine-user client id\n required: true\n platform-client-secret:\n description: Machine-user client secret\n required: true\n slack-token:\n description: Slack bot token\n required: false\n slack-channel-id:\n description: Slack channel id\n required: false\n user-mapping:\n description: JSON string mapping GitHub usernames to Slack user IDs\n required: false\n package-manager:\n description: Package manager used for dependency installation (pnpm, npm, yarn, bun)\n required: false\n default: pnpm\n\noutputs:\n app-url:\n description: Deployed application URL\n value: ${{ steps.tailor-apply.outputs.app-url }}\n\nruns:\n using: composite\n steps:\n # __STATIC_WEBSITE_BUILD_START__\n - id: build-site\n if: inputs.build-site == 'true'\n shell: bash\n run: |\n # Replace with your static website build command.\n # Example: pnpm --filter <package-name> run build:static\n # Note: this run: command is user-editable. Custom build commands are preserved across\n # reruns and are not treated as drift by setup check. Other edits to this file are flagged\n # as drift and will be overwritten if you re-run setup action with --force.\n true\n # __STATIC_WEBSITE_BUILD_END__\n - id: tailor-apply\n if: inputs.deploy == 'true'\n uses: tailor-platform/actions/deploy@a3c3032e14277e81039eb26ae1a425adb22eb532 # v1.7.0\n env:\n TAILOR_PLATFORM_SDK_CONFIG_PATH: ${{ inputs.config }}\n with:\n workspace-id: ${{ inputs.workspace-id }}\n working-directory: ${{ inputs.working-directory }}\n package-manager: ${{ inputs.package-manager }}\n platform-client-id: ${{ inputs.platform-client-id }}\n platform-client-secret: ${{ inputs.platform-client-secret }}\n - id: tailor-notify\n if: failure() && inputs.slack-token != '' && inputs.slack-channel-id != ''\n uses: tailor-platform/actions/notify@a3c3032e14277e81039eb26ae1a425adb22eb532 # v1.7.0\n with:\n provider: slack\n status: failure\n workspace-name: ${{ inputs.name }}\n slack-token: ${{ inputs.slack-token }}\n slack-channel-id: ${{ inputs.slack-channel-id }}\n user-mapping: ${{ inputs.user-mapping }}\n";
2880
3483
 
2881
3484
  //#endregion
2882
3485
  //#region src/cli/commands/setup/branch.workflow.yml
2883
- var branch_workflow_default = "# __HEADER__\nname: Tailor (__WORKSPACE_NAME__)\n\non:\n # __PULL_REQUEST_START__\n pull_request:\n branches: [\"__BRANCH__\"]\n # __PATHS__\n # __PULL_REQUEST_END__\n push:\n branches: [\"__BRANCH__\"]\n # __PATHS__\n workflow_dispatch:\n # __DISPATCH_INPUTS_START__\n inputs:\n dry-run:\n description: Preview changes without deploying\n type: boolean\n default: false\n # __DISPATCH_INPUTS_END__\n\npermissions:\n contents: read\n\njobs:\n # __PLAN_JOB_START__\n tailor-plan:\n if: >-\n github.event_name == 'pull_request' ||\n (github.event_name == 'workflow_dispatch' && inputs['dry-run'])\n runs-on: ubuntu-latest\n timeout-minutes: 30\n environment: __ENVIRONMENT__\n permissions:\n contents: read\n pull-requests: write\n concurrency:\n group: tailor-plan-__WORKSPACE_NAME__-${{ github.event.pull_request.number || github.run_id }}\n cancel-in-progress: true\n steps:\n - id: tailor-checkout\n uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0\n - id: tailor-setup\n uses: tailor-platform/actions/setup@e74173d4bdd931d036ad359cf5f7729fc6aa7067 # v1.5.1\n with:\n package-manager: __PACKAGE_MANAGER__\n - id: tailor-install\n uses: tailor-platform/actions/install@e74173d4bdd931d036ad359cf5f7729fc6aa7067 # v1.5.1\n with:\n package-manager: __PACKAGE_MANAGER__\n - id: tailor-generate-check\n uses: tailor-platform/actions/generate-check@e74173d4bdd931d036ad359cf5f7729fc6aa7067 # v1.5.1\n with:\n package-manager: __PACKAGE_MANAGER__\n # __WORKING_DIRECTORY__\n # __SEED_VALIDATE_START__\n - id: tailor-seed-validate\n uses: tailor-platform/actions/seed-validate@e74173d4bdd931d036ad359cf5f7729fc6aa7067 # v1.5.1\n with:\n package-manager: __PACKAGE_MANAGER__\n # __WORKING_DIRECTORY__\n # __SEED_VALIDATE_END__\n - id: tailor-drift-check\n uses: tailor-platform/actions/drift-check@e74173d4bdd931d036ad359cf5f7729fc6aa7067 # v1.5.1\n with:\n package-manager: __PACKAGE_MANAGER__\n # __MIGRATION_DRIFT_CHECK_START__\n - id: tailor-migration-drift-check\n uses: tailor-platform/actions/migration-drift-check@e74173d4bdd931d036ad359cf5f7729fc6aa7067 # v1.5.1\n with:\n package-manager: __PACKAGE_MANAGER__\n # __WORKING_DIRECTORY__\n # __MIGRATION_DRIFT_CHECK_END__\n - id: tailor-plan\n # Fork PRs cannot read secrets; the checks above still run for them.\n if: github.event_name != 'pull_request' || !github.event.pull_request.head.repo.fork\n uses: tailor-platform/actions/plan@e74173d4bdd931d036ad359cf5f7729fc6aa7067 # v1.5.1\n with:\n workspace-id: ${{ vars.TAILOR_PLATFORM_WORKSPACE_ID }}\n package-manager: __PACKAGE_MANAGER__\n label: __WORKSPACE_NAME__\n # __WORKING_DIRECTORY__\n platform-client-id: ${{ secrets.TAILOR_PLATFORM_MACHINE_USER_CLIENT_ID }}\n platform-client-secret: ${{ secrets.TAILOR_PLATFORM_MACHINE_USER_CLIENT_SECRET }}\n github-token: ${{ secrets.GITHUB_TOKEN }}\n # __PLAN_JOB_END__\n # __ERD_PREVIEW_JOB_START__\n tailor-erd-preview-matrix:\n if: github.event_name == 'pull_request'\n runs-on: ubuntu-latest\n timeout-minutes: 5\n permissions:\n contents: read\n outputs:\n namespaces: ${{ steps.tailor-erd-preview-matrix.outputs.namespaces }}\n base-app-dir: ${{ steps.tailor-erd-preview-matrix.outputs['base-app-dir'] }}\n steps:\n - id: tailor-checkout\n uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0\n with:\n persist-credentials: false\n - id: tailor-checkout-base\n uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0\n with:\n repository: ${{ github.event.pull_request.base.repo.full_name }}\n ref: ${{ github.event.pull_request.base.sha }}\n path: .tailor-erd-base\n persist-credentials: false\n - id: tailor-erd-preview-matrix\n shell: bash\n env:\n APP_DIR: \"__APP_DIR__\"\n WORKSPACE_NAME: \"__WORKSPACE_NAME__\"\n run: |\n set -euo pipefail\n node <<'NODE'\n const fs = require(\"node:fs\");\n\n const appDir = process.env.APP_DIR || \".\";\n const workspaceName = process.env.WORKSPACE_NAME;\n const output = process.env.GITHUB_OUTPUT;\n const dirPattern = /^[A-Za-z0-9._/-]+$/;\n const namespacePattern = /^[A-Za-z0-9][A-Za-z0-9._-]*$/;\n\n function lockTarget(file) {\n try {\n const lock = JSON.parse(fs.readFileSync(file, \"utf8\"));\n return lock.targets?.find(\n (candidate) =>\n candidate.kind === \"branch\" &&\n candidate.workspaceName === workspaceName,\n );\n } catch (error) {\n if (error && error.code === \"ENOENT\") return undefined;\n throw error;\n }\n }\n\n function namespacesFromTarget(target, label) {\n const namespaces =\n target?.inputs?.erdPreview === true && Array.isArray(target.inputs?.erdNamespaces)\n ? target.inputs.erdNamespaces\n : [];\n for (const namespace of namespaces) {\n if (typeof namespace !== \"string\" || !namespacePattern.test(namespace)) {\n throw new Error(`Invalid ERD namespace in ${label}: ${String(namespace)}`);\n }\n }\n return namespaces;\n }\n\n function normalizeDir(value, label) {\n const raw = typeof value === \"string\" && value.length > 0 ? value : appDir;\n const normalized =\n raw.replaceAll(\"\\\\\", \"/\").replace(/\\/{2,}/g, \"/\").replace(/^\\.\\//, \"\").replace(/\\/$/, \"\") ||\n \".\";\n if (\n !dirPattern.test(normalized) ||\n normalized.startsWith(\"/\") ||\n normalized.split(\"/\").includes(\"..\")\n ) {\n throw new Error(`Invalid ERD app dir in ${label}: ${raw}`);\n }\n return normalized;\n }\n\n const headTarget = lockTarget(\".github/tailor-sdk.lock\");\n const baseTarget = lockTarget(\".tailor-erd-base/.github/tailor-sdk.lock\");\n const baseAppDir = normalizeDir(baseTarget?.inputs?.dir, \"base setup lock\");\n const namespaces = [\n ...new Set([\n ...namespacesFromTarget(headTarget, \"head setup lock\"),\n ...namespacesFromTarget(baseTarget, \"base setup lock\"),\n ]),\n ].sort((a, b) => a.localeCompare(b));\n\n if (namespaces.length === 0) {\n console.error(\"No ERD preview namespaces found in the head or base setup lock.\");\n process.exit(1);\n }\n\n fs.appendFileSync(output, `namespaces=${JSON.stringify(namespaces)}\\n`);\n fs.appendFileSync(output, `base-app-dir=${baseAppDir}\\n`);\n NODE\n\n tailor-erd-preview:\n needs: tailor-erd-preview-matrix\n if: github.event_name == 'pull_request'\n runs-on: ubuntu-latest\n timeout-minutes: 15\n permissions:\n contents: read\n strategy:\n fail-fast: false\n matrix:\n namespace: ${{ fromJSON(needs.tailor-erd-preview-matrix.outputs.namespaces) }}\n steps:\n - id: tailor-checkout\n uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0\n with:\n persist-credentials: false\n - id: tailor-setup\n uses: tailor-platform/actions/setup@7817f37adf2891fbb2ebbe0a3b222a5fa2ed0c1f # v1.3.0\n with:\n package-manager: __PACKAGE_MANAGER__\n - id: tailor-checkout-base\n uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0\n with:\n repository: ${{ github.event.pull_request.base.repo.full_name }}\n ref: ${{ github.event.pull_request.base.sha }}\n path: .tailor-erd-base\n persist-credentials: false\n - id: tailor-detect-base-package-manager\n shell: bash\n run: |\n set -euo pipefail\n cd .tailor-erd-base\n base_package_manager=\"$(\n if [ -f pnpm-lock.yaml ]; then\n echo pnpm\n elif [ -f yarn.lock ]; then\n echo yarn\n elif [ -f bun.lockb ] || [ -f bun.lock ]; then\n echo bun\n elif [ -f package-lock.json ]; then\n echo npm\n else\n echo \"__PACKAGE_MANAGER__\"\n fi\n )\"\n echo \"package-manager=$base_package_manager\" >> \"$GITHUB_OUTPUT\"\n if [ \"$base_package_manager\" = \"pnpm\" ]; then\n base_pnpm_version=\"$(node <<'NODE'\n const fs = require(\"node:fs\");\n\n const fallback = \"10\";\n\n function readManifest(file) {\n try {\n return JSON.parse(fs.readFileSync(file, \"utf8\"));\n } catch {\n return {};\n }\n }\n\n function pnpmVersion(manifest) {\n const packageManager = manifest.packageManager;\n if (typeof packageManager === \"string\" && packageManager.startsWith(\"pnpm@\")) {\n return packageManager.slice(\"pnpm@\".length).split(\"+\")[0];\n }\n\n const devPackageManager = manifest.devEngines?.packageManager;\n if (devPackageManager?.name === \"pnpm\" && devPackageManager.version) {\n return devPackageManager.version;\n }\n\n return undefined;\n }\n\n process.stdout.write(\n pnpmVersion(readManifest(\"package.json\")) ?? fallback,\n );\n NODE\n )\"\n echo \"pnpm-version=$base_pnpm_version\" >> \"$GITHUB_OUTPUT\"\n fi\n - id: tailor-setup-base-pnpm\n if: steps.tailor-detect-base-package-manager.outputs['package-manager'] == 'pnpm'\n uses: pnpm/action-setup@0ebf47130e4866e96fce0953f49152a61190b271 # v6.0.9\n with:\n version: ${{ steps.tailor-detect-base-package-manager.outputs['pnpm-version'] }}\n package_json_file: .tailor-erd-base/package.json\n run_install: false\n - id: tailor-setup-base-node\n if: steps.tailor-detect-base-package-manager.outputs['package-manager'] != 'bun'\n uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0\n with:\n node-version-file: .tailor-erd-base/package.json\n - id: tailor-setup-base-yarn\n if: steps.tailor-detect-base-package-manager.outputs['package-manager'] == 'yarn'\n shell: bash\n working-directory: .tailor-erd-base\n run: |\n set -euo pipefail\n corepack enable\n - id: tailor-setup-base-bun\n if: steps.tailor-detect-base-package-manager.outputs['package-manager'] == 'bun'\n uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0\n - id: tailor-install-base\n shell: bash\n working-directory: .tailor-erd-base\n env:\n BASE_PACKAGE_MANAGER: ${{ steps.tailor-detect-base-package-manager.outputs['package-manager'] }}\n run: |\n set -euo pipefail\n case \"$BASE_PACKAGE_MANAGER\" in\n pnpm) pnpm install --frozen-lockfile ;;\n npm) npm ci ;;\n yarn)\n if grep -q '^__metadata:' yarn.lock; then\n yarn install --immutable\n else\n yarn install --frozen-lockfile\n fi\n ;;\n bun) bun install --frozen-lockfile ;;\n *)\n echo \"::error::Unsupported base package-manager '$BASE_PACKAGE_MANAGER' (expected pnpm, npm, yarn, or bun)\"\n exit 1\n ;;\n esac\n - id: tailor-restore-head-setup\n uses: tailor-platform/actions/setup@7817f37adf2891fbb2ebbe0a3b222a5fa2ed0c1f # v1.3.0\n with:\n package-manager: __PACKAGE_MANAGER__\n - id: tailor-build-erd-preview\n shell: bash\n env:\n APP_DIR: \"__APP_DIR__\"\n BASE_APP_DIR: ${{ needs.tailor-erd-preview-matrix.outputs['base-app-dir'] }}\n BASE_PACKAGE_MANAGER: ${{ steps.tailor-detect-base-package-manager.outputs['package-manager'] }}\n NAMESPACE: ${{ matrix.namespace }}\n run: |\n set -euo pipefail\n\n run_tailor_sdk() {\n case \"__PACKAGE_MANAGER__\" in\n pnpm) pnpm exec tailor-sdk \"$@\" ;;\n npm) npx tailor-sdk \"$@\" ;;\n yarn) yarn tailor-sdk \"$@\" ;;\n bun) bunx tailor-sdk \"$@\" ;;\n *)\n echo \"::error::Unsupported package-manager '__PACKAGE_MANAGER__' (expected pnpm, npm, yarn, or bun)\"\n exit 1\n ;;\n esac\n }\n\n run_head_node() {\n case \"__PACKAGE_MANAGER__\" in\n pnpm) pnpm exec node \"$@\" ;;\n npm) node \"$@\" ;;\n yarn) yarn node \"$@\" ;;\n bun) node \"$@\" ;;\n *)\n echo \"::error::Unsupported package-manager '__PACKAGE_MANAGER__' (expected pnpm, npm, yarn, or bun)\"\n exit 1\n ;;\n esac\n }\n\n tailor_sdk_bin=\"$(\n run_head_node - <<'NODE'\n const path = require(\"node:path\");\n const { createRequire } = require(\"node:module\");\n const appDir = process.env.APP_DIR || \".\";\n const githubWorkspace = process.env.GITHUB_WORKSPACE;\n if (!githubWorkspace) {\n throw new Error(\"GITHUB_WORKSPACE is required.\");\n }\n\n let lastError;\n for (const manifestPath of [\n path.join(githubWorkspace, appDir, \"package.json\"),\n path.join(githubWorkspace, \"package.json\"),\n ]) {\n try {\n const requireFromManifest = createRequire(manifestPath);\n process.stdout.write(\n path.join(\n path.dirname(requireFromManifest.resolve(\"@tailor-platform/sdk/cli\")),\n \"index.mjs\",\n ),\n );\n process.exit(0);\n } catch (error) {\n lastError = error;\n }\n }\n throw lastError || new Error(\"Failed to resolve @tailor-platform/sdk/cli.\");\n NODE\n )\"\n\n run_head_tailor_sdk_bin() {\n local command_cwd=\"$1\"\n shift\n\n run_head_cli_env() {\n env TAILOR_SDK_BIN=\"$tailor_sdk_bin\" TAILOR_SDK_CWD=\"$command_cwd\" \"$@\"\n }\n\n (\n cd \"$GITHUB_WORKSPACE\" || exit 1\n case \"__PACKAGE_MANAGER__\" in\n pnpm) run_head_cli_env pnpm exec node \"$head_cli_runner\" \"$@\" ;;\n npm) run_head_cli_env node \"$head_cli_runner\" \"$@\" ;;\n yarn) run_head_cli_env yarn node \"$head_cli_runner\" \"$@\" ;;\n bun) run_head_cli_env bun \"$head_cli_runner\" \"$@\" ;;\n *)\n echo \"::error::Unsupported package-manager '__PACKAGE_MANAGER__' (expected pnpm, npm, yarn, or bun)\"\n exit 1\n ;;\n esac\n )\n }\n\n run_base_tailor_sdk_bin() {\n local command_cwd=\"$1\"\n shift\n\n run_head_cli_env() {\n env TAILOR_SDK_BIN=\"$tailor_sdk_bin\" TAILOR_SDK_CWD=\"$command_cwd\" \"$@\"\n }\n\n (\n cd \"$command_cwd\" || exit 1\n case \"$BASE_PACKAGE_MANAGER\" in\n pnpm) run_head_cli_env pnpm exec node \"$head_cli_runner\" \"$@\" ;;\n npm) run_head_cli_env node \"$head_cli_runner\" \"$@\" ;;\n yarn) run_head_cli_env yarn node \"$head_cli_runner\" \"$@\" ;;\n bun) run_head_cli_env bun \"$head_cli_runner\" \"$@\" ;;\n *)\n echo \"::error::Unsupported base package-manager '$BASE_PACKAGE_MANAGER' (expected pnpm, npm, yarn, or bun)\"\n exit 1\n ;;\n esac\n )\n }\n\n head_output=\"$RUNNER_TEMP/tailor-erd/head\"\n base_output=\"$RUNNER_TEMP/tailor-erd/base\"\n preview_output=\"$RUNNER_TEMP/tailor-erd/preview\"\n dts_output=\"$RUNNER_TEMP/tailor-erd/dts\"\n head_cli_runner=\"$RUNNER_TEMP/tailor-erd/run-head-tailor-sdk.mjs\"\n head_log=\"$RUNNER_TEMP/tailor-erd/head-$NAMESPACE.log\"\n base_log=\"$RUNNER_TEMP/tailor-erd/base-$NAMESPACE.log\"\n rm -rf \"$head_output\" \"$base_output\" \"$preview_output\" \"$dts_output\"\n mkdir -p \"$head_output\" \"$base_output\" \"$preview_output\" \"$dts_output\"\n cat > \"$head_cli_runner\" <<'NODE'\n import { pathToFileURL } from \"node:url\";\n\n const cliBin = process.env.TAILOR_SDK_BIN;\n const commandCwd = process.env.TAILOR_SDK_CWD;\n if (!cliBin || !commandCwd) {\n throw new Error(\"TAILOR_SDK_BIN and TAILOR_SDK_CWD are required.\");\n }\n\n process.chdir(commandCwd);\n process.argv = [process.argv[0], cliBin, ...process.argv.slice(2)];\n await import(pathToFileURL(cliBin).href);\n NODE\n\n head_config=\"$GITHUB_WORKSPACE/$APP_DIR/tailor.config.ts\"\n base_config=\"$GITHUB_WORKSPACE/.tailor-erd-base/$BASE_APP_DIR/tailor.config.ts\"\n head_html=\"$head_output/$NAMESPACE/dist/index.html\"\n base_html=\"$base_output/$NAMESPACE/dist/index.html\"\n preview_html=\"$preview_output/$NAMESPACE-viewer.html\"\n\n head_missing=\"false\"\n if [ ! -f \"$head_config\" ]; then\n echo \"Head ERD config not found; rendering base objects as removed.\"\n head_missing=\"true\"\n elif ! (\n cd \"$GITHUB_WORKSPACE/$APP_DIR\" || exit 1\n TAILOR_PLATFORM_SDK_DTS_PATH=\"$dts_output/head-$NAMESPACE.d.ts\" \\\n run_tailor_sdk tailordb erd export --config \"$head_config\" --namespace \"$NAMESPACE\" --output \"$head_output\"\n ) >\"$head_log\" 2>&1; then\n if grep -q 'not found in local config.db' \"$head_log\"; then\n cat \"$head_log\"\n echo \"Head ERD namespace '$NAMESPACE' not found; rendering base objects as removed.\"\n head_missing=\"true\"\n else\n cat \"$head_log\"\n exit 1\n fi\n elif [ -s \"$head_log\" ]; then\n cat \"$head_log\"\n fi\n\n base_missing=\"false\"\n if [ ! -f \"$base_config\" ]; then\n echo \"Base ERD config not found; rendering current objects as added.\"\n base_missing=\"true\"\n elif ! (\n TAILOR_PLATFORM_SDK_DTS_PATH=\"$dts_output/base-$NAMESPACE.d.ts\" \\\n run_base_tailor_sdk_bin \"$GITHUB_WORKSPACE/.tailor-erd-base/$BASE_APP_DIR\" tailordb erd export --config \"$base_config\" --namespace \"$NAMESPACE\" --output \"$base_output\"\n ) >\"$base_log\" 2>&1; then\n if grep -q 'not found in local config.db' \"$base_log\"; then\n cat \"$base_log\"\n echo \"Base ERD namespace '$NAMESPACE' not found; rendering current objects as added.\"\n base_missing=\"true\"\n else\n cat \"$base_log\"\n exit 1\n fi\n elif [ -s \"$base_log\" ]; then\n cat \"$base_log\"\n fi\n\n if [ \"$head_missing\" = \"true\" ] && [ \"$base_missing\" = \"true\" ]; then\n echo \"::error::ERD namespace '$NAMESPACE' was not found in head or base.\"\n exit 1\n fi\n if [ \"$head_missing\" = \"false\" ] && [ ! -f \"$head_html\" ]; then\n echo \"::error::Head ERD viewer was not generated at $head_html\"\n exit 1\n fi\n if [ \"$base_missing\" = \"false\" ] && [ ! -f \"$base_html\" ]; then\n echo \"::error::Base ERD viewer was not generated at $base_html\"\n exit 1\n fi\n\n diff_args=(--namespace \"$NAMESPACE\" --output \"$preview_html\")\n if [ \"$head_missing\" = \"false\" ]; then\n diff_args+=(--head-html \"$head_html\")\n fi\n if [ \"$base_missing\" = \"false\" ]; then\n diff_args+=(--base-html \"$base_html\")\n fi\n run_head_tailor_sdk_bin \"$GITHUB_WORKSPACE\" tailordb erd diff \"${diff_args[@]}\"\n - id: tailor-upload-erd-viewer\n uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1\n with:\n name: ${{ matrix.namespace }}-viewer.html\n path: ${{ runner.temp }}/tailor-erd/preview/${{ matrix.namespace }}-viewer.html\n if-no-files-found: error\n archive: false\n retention-days: 7\n\n # __ERD_PREVIEW_JOB_END__\n # __ERD_PREVIEW_COMMENT_JOB_START__\n tailor-erd-preview-comment:\n needs: tailor-erd-preview\n if: github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository\n runs-on: ubuntu-latest\n timeout-minutes: 5\n permissions:\n actions: read\n pull-requests: write\n steps:\n - id: tailor-comment-erd-preview\n env:\n GH_TOKEN: ${{ github.token }}\n REPO: ${{ github.repository }}\n RUN_ID: ${{ github.run_id }}\n SERVER: ${{ github.server_url }}\n PR_NUMBER: ${{ github.event.pull_request.number }}\n BASE_REF: ${{ github.event.pull_request.base.ref }}\n HEAD_SHA: ${{ github.event.pull_request.head.sha }}\n MARKER: \"<!-- tailor-erd-preview: __WORKSPACE_NAME__ -->\"\n run: |\n set -euo pipefail\n\n current_head=$(gh api \"repos/$REPO/pulls/$PR_NUMBER\" --jq '.head.sha')\n if [ \"$current_head\" != \"$HEAD_SHA\" ]; then\n echo \"Skipping stale ERD preview comment for $HEAD_SHA; current head is $current_head.\"\n exit 0\n fi\n\n body=\"$MARKER\"$'\\n'\"### TailorDB ERD preview (__WORKSPACE_NAME__)\"$'\\n\\n'\n body+=\"Self-contained ERD viewer HTML artifacts for this pull request. Each viewer can switch between the current schema and a diff against base branch \\`$BASE_REF\\`.\"$'\\n'\n\n while IFS=$'\\t' read -r name id; do\n [ -z \"$name\" ] && continue\n if [[ \"$name\" != *-viewer.html ]]; then\n continue\n fi\n ns=${name%-viewer.html}\n label=\"$ns viewer\"\n body+=$'\\n'\"- **$label**: [$name]($SERVER/$REPO/actions/runs/$RUN_ID/artifacts/$id)\"\n done < <(gh api \"repos/$REPO/actions/runs/$RUN_ID/artifacts\" --paginate \\\n --jq '.artifacts[] | select(.name | endswith(\"-viewer.html\")) | [.name, (.id|tostring)] | @tsv' | sort)\n\n existing=$(gh api \"repos/$REPO/issues/$PR_NUMBER/comments\" --paginate \\\n --jq 'map(select(.body | contains(env.MARKER))) | .[0].id // empty')\n if [ -n \"$existing\" ]; then\n gh api --method PATCH \"repos/$REPO/issues/comments/$existing\" -f body=\"$body\" >/dev/null\n else\n gh api --method POST \"repos/$REPO/issues/$PR_NUMBER/comments\" -f body=\"$body\" >/dev/null\n fi\n\n # __ERD_PREVIEW_COMMENT_JOB_END__\n tailor-deploy:\n # __DEPLOY_IF__\n runs-on: ubuntu-latest\n timeout-minutes: 30\n permissions:\n contents: read\n environment: __ENVIRONMENT__\n concurrency:\n group: tailor-deploy-__WORKSPACE_NAME__\n cancel-in-progress: false\n steps:\n - id: tailor-checkout\n uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0\n - id: tailor-setup\n uses: tailor-platform/actions/setup@e74173d4bdd931d036ad359cf5f7729fc6aa7067 # v1.5.1\n with:\n package-manager: __PACKAGE_MANAGER__\n - id: tailor-install\n uses: tailor-platform/actions/install@e74173d4bdd931d036ad359cf5f7729fc6aa7067 # v1.5.1\n with:\n package-manager: __PACKAGE_MANAGER__\n - id: tailor-apply\n uses: tailor-platform/actions/deploy@e74173d4bdd931d036ad359cf5f7729fc6aa7067 # v1.5.1\n with:\n workspace-id: ${{ vars.TAILOR_PLATFORM_WORKSPACE_ID }}\n package-manager: __PACKAGE_MANAGER__\n # __WORKING_DIRECTORY__\n platform-client-id: ${{ secrets.TAILOR_PLATFORM_MACHINE_USER_CLIENT_ID }}\n platform-client-secret: ${{ secrets.TAILOR_PLATFORM_MACHINE_USER_CLIENT_SECRET }}\n # __SEED_DATA_START__\n - id: seed-data\n if: false\n shell: bash\n # __WORKING_DIRECTORY__\n run: |\n # Uncomment and implement to seed data on deploy.\n # Run after apply so the schema is ready.\n # Example: node scripts/seed.mjs\n true\n # __SEED_DATA_END__\n - id: slack-prereq\n if: always()\n shell: bash\n env:\n SLACK_TOKEN: ${{ secrets.TAILOR_SLACK_BOT_TOKEN }}\n SLACK_CHANNEL_ID: ${{ vars.TAILOR_SLACK_CHANNEL_ID }}\n run: |\n if [[ -n \"$SLACK_TOKEN\" && -n \"$SLACK_CHANNEL_ID\" ]]; then\n echo \"ready=true\" >> \"$GITHUB_OUTPUT\"\n fi\n - id: tailor-notify\n if: always() && steps.slack-prereq.outputs.ready == 'true'\n uses: tailor-platform/actions/notify@e74173d4bdd931d036ad359cf5f7729fc6aa7067 # v1.5.1\n with:\n provider: slack\n status: ${{ job.status }}\n workspace-name: __WORKSPACE_NAME__\n slack-token: ${{ secrets.TAILOR_SLACK_BOT_TOKEN }}\n slack-channel-id: ${{ vars.TAILOR_SLACK_CHANNEL_ID }}\n # user-mapping: ${{ vars.TAILOR_SLACK_USER_MAPPING }}\n";
3486
+ var branch_workflow_default = "# __HEADER__\nname: Tailor (__WORKSPACE_NAME__)\n\non:\n # __PULL_REQUEST_START__\n pull_request:\n branches: [\"__BRANCH__\"]\n # __PATHS__\n # __PULL_REQUEST_END__\n push:\n branches: [\"__BRANCH__\"]\n # __PATHS__\n workflow_dispatch:\n # __DISPATCH_INPUTS_START__\n inputs:\n dry-run:\n description: Preview changes without deploying\n type: boolean\n default: false\n # __DISPATCH_INPUTS_END__\n\npermissions:\n contents: read\n\njobs:\n # __PLAN_JOB_START__\n tailor-plan:\n if: >-\n github.event_name == 'pull_request' ||\n (github.event_name == 'workflow_dispatch' && inputs['dry-run'])\n runs-on: ubuntu-latest\n timeout-minutes: 30\n environment: __ENVIRONMENT__\n permissions:\n contents: read\n pull-requests: write\n concurrency:\n group: tailor-plan-__WORKSPACE_NAME__-${{ github.event.pull_request.number || github.run_id }}\n cancel-in-progress: true\n steps:\n - id: tailor-checkout\n uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0\n - id: tailor-setup\n uses: tailor-platform/actions/setup@a3c3032e14277e81039eb26ae1a425adb22eb532 # v1.7.0\n with:\n package-manager: __PACKAGE_MANAGER__\n - id: tailor-install\n uses: tailor-platform/actions/install@a3c3032e14277e81039eb26ae1a425adb22eb532 # v1.7.0\n with:\n package-manager: __PACKAGE_MANAGER__\n - id: tailor-generate-check\n uses: tailor-platform/actions/generate-check@a3c3032e14277e81039eb26ae1a425adb22eb532 # v1.7.0\n with:\n package-manager: __PACKAGE_MANAGER__\n # __WORKING_DIRECTORY__\n # __SEED_VALIDATE_START__\n - id: tailor-seed-validate\n uses: tailor-platform/actions/seed-validate@a3c3032e14277e81039eb26ae1a425adb22eb532 # v1.7.0\n with:\n package-manager: __PACKAGE_MANAGER__\n # __WORKING_DIRECTORY__\n # __SEED_VALIDATE_END__\n - id: tailor-drift-check\n uses: tailor-platform/actions/drift-check@a3c3032e14277e81039eb26ae1a425adb22eb532 # v1.7.0\n with:\n package-manager: __PACKAGE_MANAGER__\n # __MIGRATION_DRIFT_CHECK_START__\n - id: tailor-migration-drift-check\n uses: tailor-platform/actions/migration-drift-check@a3c3032e14277e81039eb26ae1a425adb22eb532 # v1.7.0\n with:\n package-manager: __PACKAGE_MANAGER__\n # __WORKING_DIRECTORY__\n # __MIGRATION_DRIFT_CHECK_END__\n - id: tailor-plan\n # Fork PRs cannot read secrets; the checks above still run for them.\n if: github.event_name != 'pull_request' || !github.event.pull_request.head.repo.fork\n uses: tailor-platform/actions/plan@a3c3032e14277e81039eb26ae1a425adb22eb532 # v1.7.0\n with:\n workspace-id: ${{ vars.TAILOR_PLATFORM_WORKSPACE_ID }}\n package-manager: __PACKAGE_MANAGER__\n label: __WORKSPACE_NAME__\n # __WORKING_DIRECTORY__\n platform-client-id: ${{ secrets.TAILOR_PLATFORM_MACHINE_USER_CLIENT_ID }}\n platform-client-secret: ${{ secrets.TAILOR_PLATFORM_MACHINE_USER_CLIENT_SECRET }}\n github-token: ${{ secrets.GITHUB_TOKEN }}\n # __PLAN_JOB_END__\n # __ERD_PREVIEW_JOB_START__\n tailor-erd-preview-matrix:\n if: github.event_name == 'pull_request'\n runs-on: ubuntu-latest\n timeout-minutes: 5\n permissions:\n contents: read\n outputs:\n namespaces: ${{ steps.tailor-erd-preview-matrix.outputs.namespaces }}\n base-app-dir: ${{ steps.tailor-erd-preview-matrix.outputs['base-app-dir'] }}\n steps:\n - id: tailor-checkout\n uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0\n with:\n persist-credentials: false\n - id: tailor-checkout-base\n uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0\n with:\n repository: ${{ github.event.pull_request.base.repo.full_name }}\n ref: ${{ github.event.pull_request.base.sha }}\n path: .tailor-erd-base\n persist-credentials: false\n - id: tailor-erd-preview-matrix\n shell: bash\n env:\n APP_DIR: \"__APP_DIR__\"\n WORKSPACE_NAME: \"__WORKSPACE_NAME__\"\n run: |\n set -euo pipefail\n node <<'NODE'\n const fs = require(\"node:fs\");\n\n const appDir = process.env.APP_DIR || \".\";\n const workspaceName = process.env.WORKSPACE_NAME;\n const output = process.env.GITHUB_OUTPUT;\n const dirPattern = /^[A-Za-z0-9._/-]+$/;\n const namespacePattern = /^[A-Za-z0-9][A-Za-z0-9._-]*$/;\n\n function lockTarget(file) {\n try {\n const lock = JSON.parse(fs.readFileSync(file, \"utf8\"));\n return lock.targets?.find(\n (candidate) =>\n candidate.kind === \"branch\" &&\n candidate.workspaceName === workspaceName,\n );\n } catch (error) {\n if (error && error.code === \"ENOENT\") return undefined;\n throw error;\n }\n }\n\n function namespacesFromTarget(target, label) {\n const namespaces =\n target?.inputs?.erdPreview === true && Array.isArray(target.inputs?.erdNamespaces)\n ? target.inputs.erdNamespaces\n : [];\n for (const namespace of namespaces) {\n if (typeof namespace !== \"string\" || !namespacePattern.test(namespace)) {\n throw new Error(`Invalid ERD namespace in ${label}: ${String(namespace)}`);\n }\n }\n return namespaces;\n }\n\n function normalizeDir(value, label) {\n const raw = typeof value === \"string\" && value.length > 0 ? value : appDir;\n const normalized =\n raw.replaceAll(\"\\\\\", \"/\").replace(/\\/{2,}/g, \"/\").replace(/^\\.\\//, \"\").replace(/\\/$/, \"\") ||\n \".\";\n if (\n !dirPattern.test(normalized) ||\n normalized.startsWith(\"/\") ||\n normalized.split(\"/\").includes(\"..\")\n ) {\n throw new Error(`Invalid ERD app dir in ${label}: ${raw}`);\n }\n return normalized;\n }\n\n const headTarget = lockTarget(\".github/tailor-sdk.lock\");\n const baseTarget = lockTarget(\".tailor-erd-base/.github/tailor-sdk.lock\");\n const baseAppDir = normalizeDir(baseTarget?.inputs?.dir, \"base setup lock\");\n const namespaces = [\n ...new Set([\n ...namespacesFromTarget(headTarget, \"head setup lock\"),\n ...namespacesFromTarget(baseTarget, \"base setup lock\"),\n ]),\n ].sort((a, b) => a.localeCompare(b));\n\n if (namespaces.length === 0) {\n console.error(\"No ERD preview namespaces found in the head or base setup lock.\");\n process.exit(1);\n }\n\n fs.appendFileSync(output, `namespaces=${JSON.stringify(namespaces)}\\n`);\n fs.appendFileSync(output, `base-app-dir=${baseAppDir}\\n`);\n NODE\n\n tailor-erd-preview:\n needs: tailor-erd-preview-matrix\n if: github.event_name == 'pull_request'\n runs-on: ubuntu-latest\n timeout-minutes: 15\n permissions:\n contents: read\n strategy:\n fail-fast: false\n matrix:\n namespace: ${{ fromJSON(needs.tailor-erd-preview-matrix.outputs.namespaces) }}\n steps:\n - id: tailor-checkout\n uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0\n with:\n persist-credentials: false\n - id: tailor-setup\n uses: tailor-platform/actions/setup@a3c3032e14277e81039eb26ae1a425adb22eb532 # v1.7.0\n with:\n package-manager: __PACKAGE_MANAGER__\n - id: tailor-checkout-base\n uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0\n with:\n repository: ${{ github.event.pull_request.base.repo.full_name }}\n ref: ${{ github.event.pull_request.base.sha }}\n path: .tailor-erd-base\n persist-credentials: false\n - id: tailor-detect-base-package-manager\n shell: bash\n run: |\n set -euo pipefail\n cd .tailor-erd-base\n base_package_manager=\"$(\n if [ -f pnpm-lock.yaml ]; then\n echo pnpm\n elif [ -f yarn.lock ]; then\n echo yarn\n elif [ -f bun.lockb ] || [ -f bun.lock ]; then\n echo bun\n elif [ -f package-lock.json ]; then\n echo npm\n else\n echo \"__PACKAGE_MANAGER__\"\n fi\n )\"\n echo \"package-manager=$base_package_manager\" >> \"$GITHUB_OUTPUT\"\n if [ \"$base_package_manager\" = \"pnpm\" ]; then\n base_pnpm_version=\"$(node <<'NODE'\n const fs = require(\"node:fs\");\n\n const fallback = \"10\";\n\n function readManifest(file) {\n try {\n return JSON.parse(fs.readFileSync(file, \"utf8\"));\n } catch {\n return {};\n }\n }\n\n function pnpmVersion(manifest) {\n const packageManager = manifest.packageManager;\n if (typeof packageManager === \"string\" && packageManager.startsWith(\"pnpm@\")) {\n return packageManager.slice(\"pnpm@\".length).split(\"+\")[0];\n }\n\n const devPackageManager = manifest.devEngines?.packageManager;\n if (devPackageManager?.name === \"pnpm\" && devPackageManager.version) {\n return devPackageManager.version;\n }\n\n return undefined;\n }\n\n process.stdout.write(\n pnpmVersion(readManifest(\"package.json\")) ?? fallback,\n );\n NODE\n )\"\n echo \"pnpm-version=$base_pnpm_version\" >> \"$GITHUB_OUTPUT\"\n fi\n - id: tailor-setup-base-pnpm\n if: steps.tailor-detect-base-package-manager.outputs['package-manager'] == 'pnpm'\n uses: pnpm/action-setup@0ebf47130e4866e96fce0953f49152a61190b271 # v6.0.9\n with:\n version: ${{ steps.tailor-detect-base-package-manager.outputs['pnpm-version'] }}\n package_json_file: .tailor-erd-base/package.json\n run_install: false\n - id: tailor-setup-base-node\n if: steps.tailor-detect-base-package-manager.outputs['package-manager'] != 'bun'\n uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7\n with:\n node-version-file: .tailor-erd-base/package.json\n - id: tailor-setup-base-yarn\n if: steps.tailor-detect-base-package-manager.outputs['package-manager'] == 'yarn'\n shell: bash\n working-directory: .tailor-erd-base\n run: |\n set -euo pipefail\n corepack enable\n - id: tailor-setup-base-bun\n if: steps.tailor-detect-base-package-manager.outputs['package-manager'] == 'bun'\n uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0\n - id: tailor-install-base\n shell: bash\n working-directory: .tailor-erd-base\n env:\n BASE_PACKAGE_MANAGER: ${{ steps.tailor-detect-base-package-manager.outputs['package-manager'] }}\n run: |\n set -euo pipefail\n case \"$BASE_PACKAGE_MANAGER\" in\n pnpm) pnpm install --frozen-lockfile ;;\n npm) npm ci ;;\n yarn)\n if grep -q '^__metadata:' yarn.lock; then\n yarn install --immutable\n else\n yarn install --frozen-lockfile\n fi\n ;;\n bun) bun install --frozen-lockfile ;;\n *)\n echo \"::error::Unsupported base package-manager '$BASE_PACKAGE_MANAGER' (expected pnpm, npm, yarn, or bun)\"\n exit 1\n ;;\n esac\n - id: tailor-restore-head-setup\n uses: tailor-platform/actions/setup@a3c3032e14277e81039eb26ae1a425adb22eb532 # v1.7.0\n with:\n package-manager: __PACKAGE_MANAGER__\n - id: tailor-build-erd-preview\n shell: bash\n env:\n APP_DIR: \"__APP_DIR__\"\n BASE_APP_DIR: ${{ needs.tailor-erd-preview-matrix.outputs['base-app-dir'] }}\n BASE_PACKAGE_MANAGER: ${{ steps.tailor-detect-base-package-manager.outputs['package-manager'] }}\n NAMESPACE: ${{ matrix.namespace }}\n run: |\n set -euo pipefail\n\n run_tailor_sdk() {\n case \"__PACKAGE_MANAGER__\" in\n pnpm) pnpm exec tailor-sdk \"$@\" ;;\n npm) npx tailor-sdk \"$@\" ;;\n yarn) yarn tailor-sdk \"$@\" ;;\n bun) bunx tailor-sdk \"$@\" ;;\n *)\n echo \"::error::Unsupported package-manager '__PACKAGE_MANAGER__' (expected pnpm, npm, yarn, or bun)\"\n exit 1\n ;;\n esac\n }\n\n run_head_node() {\n case \"__PACKAGE_MANAGER__\" in\n pnpm) pnpm exec node \"$@\" ;;\n npm) node \"$@\" ;;\n yarn) yarn node \"$@\" ;;\n bun) node \"$@\" ;;\n *)\n echo \"::error::Unsupported package-manager '__PACKAGE_MANAGER__' (expected pnpm, npm, yarn, or bun)\"\n exit 1\n ;;\n esac\n }\n\n tailor_sdk_bin=\"$(\n run_head_node - <<'NODE'\n const path = require(\"node:path\");\n const { createRequire } = require(\"node:module\");\n const appDir = process.env.APP_DIR || \".\";\n const githubWorkspace = process.env.GITHUB_WORKSPACE;\n if (!githubWorkspace) {\n throw new Error(\"GITHUB_WORKSPACE is required.\");\n }\n\n let lastError;\n for (const manifestPath of [\n path.join(githubWorkspace, appDir, \"package.json\"),\n path.join(githubWorkspace, \"package.json\"),\n ]) {\n try {\n const requireFromManifest = createRequire(manifestPath);\n process.stdout.write(\n path.join(\n path.dirname(requireFromManifest.resolve(\"@tailor-platform/sdk/cli\")),\n \"index.mjs\",\n ),\n );\n process.exit(0);\n } catch (error) {\n lastError = error;\n }\n }\n throw lastError || new Error(\"Failed to resolve @tailor-platform/sdk/cli.\");\n NODE\n )\"\n\n run_head_tailor_sdk_bin() {\n local command_cwd=\"$1\"\n shift\n\n run_head_cli_env() {\n env TAILOR_SDK_BIN=\"$tailor_sdk_bin\" TAILOR_SDK_CWD=\"$command_cwd\" \"$@\"\n }\n\n (\n cd \"$GITHUB_WORKSPACE\" || exit 1\n case \"__PACKAGE_MANAGER__\" in\n pnpm) run_head_cli_env pnpm exec node \"$head_cli_runner\" \"$@\" ;;\n npm) run_head_cli_env node \"$head_cli_runner\" \"$@\" ;;\n yarn) run_head_cli_env yarn node \"$head_cli_runner\" \"$@\" ;;\n bun) run_head_cli_env bun \"$head_cli_runner\" \"$@\" ;;\n *)\n echo \"::error::Unsupported package-manager '__PACKAGE_MANAGER__' (expected pnpm, npm, yarn, or bun)\"\n exit 1\n ;;\n esac\n )\n }\n\n run_base_tailor_sdk_bin() {\n local command_cwd=\"$1\"\n shift\n\n run_head_cli_env() {\n env TAILOR_SDK_BIN=\"$tailor_sdk_bin\" TAILOR_SDK_CWD=\"$command_cwd\" \"$@\"\n }\n\n (\n cd \"$command_cwd\" || exit 1\n case \"$BASE_PACKAGE_MANAGER\" in\n pnpm) run_head_cli_env pnpm exec node \"$head_cli_runner\" \"$@\" ;;\n npm) run_head_cli_env node \"$head_cli_runner\" \"$@\" ;;\n yarn) run_head_cli_env yarn node \"$head_cli_runner\" \"$@\" ;;\n bun) run_head_cli_env bun \"$head_cli_runner\" \"$@\" ;;\n *)\n echo \"::error::Unsupported base package-manager '$BASE_PACKAGE_MANAGER' (expected pnpm, npm, yarn, or bun)\"\n exit 1\n ;;\n esac\n )\n }\n\n head_output=\"$RUNNER_TEMP/tailor-erd/head\"\n base_output=\"$RUNNER_TEMP/tailor-erd/base\"\n preview_output=\"$RUNNER_TEMP/tailor-erd/preview\"\n dts_output=\"$RUNNER_TEMP/tailor-erd/dts\"\n head_cli_runner=\"$RUNNER_TEMP/tailor-erd/run-head-tailor-sdk.mjs\"\n head_log=\"$RUNNER_TEMP/tailor-erd/head-$NAMESPACE.log\"\n base_log=\"$RUNNER_TEMP/tailor-erd/base-$NAMESPACE.log\"\n rm -rf \"$head_output\" \"$base_output\" \"$preview_output\" \"$dts_output\"\n mkdir -p \"$head_output\" \"$base_output\" \"$preview_output\" \"$dts_output\"\n cat > \"$head_cli_runner\" <<'NODE'\n import { pathToFileURL } from \"node:url\";\n\n const cliBin = process.env.TAILOR_SDK_BIN;\n const commandCwd = process.env.TAILOR_SDK_CWD;\n if (!cliBin || !commandCwd) {\n throw new Error(\"TAILOR_SDK_BIN and TAILOR_SDK_CWD are required.\");\n }\n\n process.chdir(commandCwd);\n process.argv = [process.argv[0], cliBin, ...process.argv.slice(2)];\n await import(pathToFileURL(cliBin).href);\n NODE\n\n head_config=\"$GITHUB_WORKSPACE/$APP_DIR/tailor.config.ts\"\n base_config=\"$GITHUB_WORKSPACE/.tailor-erd-base/$BASE_APP_DIR/tailor.config.ts\"\n head_html=\"$head_output/$NAMESPACE/dist/index.html\"\n base_html=\"$base_output/$NAMESPACE/dist/index.html\"\n preview_html=\"$preview_output/$NAMESPACE-viewer.html\"\n\n head_missing=\"false\"\n if [ ! -f \"$head_config\" ]; then\n echo \"Head ERD config not found; rendering base objects as removed.\"\n head_missing=\"true\"\n elif ! (\n cd \"$GITHUB_WORKSPACE/$APP_DIR\" || exit 1\n TAILOR_PLATFORM_SDK_DTS_PATH=\"$dts_output/head-$NAMESPACE.d.ts\" \\\n run_tailor_sdk tailordb erd export --config \"$head_config\" --namespace \"$NAMESPACE\" --output \"$head_output\"\n ) >\"$head_log\" 2>&1; then\n if grep -q 'not found in local config.db' \"$head_log\"; then\n cat \"$head_log\"\n echo \"Head ERD namespace '$NAMESPACE' not found; rendering base objects as removed.\"\n head_missing=\"true\"\n else\n cat \"$head_log\"\n exit 1\n fi\n elif [ -s \"$head_log\" ]; then\n cat \"$head_log\"\n fi\n\n base_missing=\"false\"\n if [ ! -f \"$base_config\" ]; then\n echo \"Base ERD config not found; rendering current objects as added.\"\n base_missing=\"true\"\n elif ! (\n TAILOR_PLATFORM_SDK_DTS_PATH=\"$dts_output/base-$NAMESPACE.d.ts\" \\\n run_base_tailor_sdk_bin \"$GITHUB_WORKSPACE/.tailor-erd-base/$BASE_APP_DIR\" tailordb erd export --config \"$base_config\" --namespace \"$NAMESPACE\" --output \"$base_output\"\n ) >\"$base_log\" 2>&1; then\n if grep -q 'not found in local config.db' \"$base_log\"; then\n cat \"$base_log\"\n echo \"Base ERD namespace '$NAMESPACE' not found; rendering current objects as added.\"\n base_missing=\"true\"\n else\n cat \"$base_log\"\n exit 1\n fi\n elif [ -s \"$base_log\" ]; then\n cat \"$base_log\"\n fi\n\n if [ \"$head_missing\" = \"true\" ] && [ \"$base_missing\" = \"true\" ]; then\n echo \"::error::ERD namespace '$NAMESPACE' was not found in head or base.\"\n exit 1\n fi\n if [ \"$head_missing\" = \"false\" ] && [ ! -f \"$head_html\" ]; then\n echo \"::error::Head ERD viewer was not generated at $head_html\"\n exit 1\n fi\n if [ \"$base_missing\" = \"false\" ] && [ ! -f \"$base_html\" ]; then\n echo \"::error::Base ERD viewer was not generated at $base_html\"\n exit 1\n fi\n\n diff_args=(--namespace \"$NAMESPACE\" --output \"$preview_html\")\n if [ \"$head_missing\" = \"false\" ]; then\n diff_args+=(--head-html \"$head_html\")\n fi\n if [ \"$base_missing\" = \"false\" ]; then\n diff_args+=(--base-html \"$base_html\")\n fi\n run_head_tailor_sdk_bin \"$GITHUB_WORKSPACE\" tailordb erd diff \"${diff_args[@]}\"\n - id: tailor-upload-erd-viewer\n uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1\n with:\n name: ${{ matrix.namespace }}-viewer.html\n path: ${{ runner.temp }}/tailor-erd/preview/${{ matrix.namespace }}-viewer.html\n if-no-files-found: error\n archive: false\n retention-days: 7\n\n # __ERD_PREVIEW_JOB_END__\n # __ERD_PREVIEW_COMMENT_JOB_START__\n tailor-erd-preview-comment:\n needs: tailor-erd-preview\n if: github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository\n runs-on: ubuntu-latest\n timeout-minutes: 5\n permissions:\n actions: read\n pull-requests: write\n steps:\n - id: tailor-comment-erd-preview\n env:\n GH_TOKEN: ${{ github.token }}\n REPO: ${{ github.repository }}\n RUN_ID: ${{ github.run_id }}\n SERVER: ${{ github.server_url }}\n PR_NUMBER: ${{ github.event.pull_request.number }}\n BASE_REF: ${{ github.event.pull_request.base.ref }}\n HEAD_SHA: ${{ github.event.pull_request.head.sha }}\n MARKER: \"<!-- tailor-erd-preview: __WORKSPACE_NAME__ -->\"\n run: |\n set -euo pipefail\n\n current_head=$(gh api \"repos/$REPO/pulls/$PR_NUMBER\" --jq '.head.sha')\n if [ \"$current_head\" != \"$HEAD_SHA\" ]; then\n echo \"Skipping stale ERD preview comment for $HEAD_SHA; current head is $current_head.\"\n exit 0\n fi\n\n body=\"$MARKER\"$'\\n'\"### TailorDB ERD preview (__WORKSPACE_NAME__)\"$'\\n\\n'\n body+=\"Self-contained ERD viewer HTML artifacts for this pull request. Each viewer can switch between the current schema and a diff against base branch \\`$BASE_REF\\`.\"$'\\n'\n\n while IFS=$'\\t' read -r name id; do\n [ -z \"$name\" ] && continue\n if [[ \"$name\" != *-viewer.html ]]; then\n continue\n fi\n ns=${name%-viewer.html}\n label=\"$ns viewer\"\n body+=$'\\n'\"- **$label**: [$name]($SERVER/$REPO/actions/runs/$RUN_ID/artifacts/$id)\"\n done < <(gh api \"repos/$REPO/actions/runs/$RUN_ID/artifacts\" --paginate \\\n --jq '.artifacts[] | select(.name | endswith(\"-viewer.html\")) | [.name, (.id|tostring)] | @tsv' | sort)\n\n existing=$(gh api \"repos/$REPO/issues/$PR_NUMBER/comments\" --paginate \\\n --jq 'map(select(.body | contains(env.MARKER))) | .[0].id // empty')\n if [ -n \"$existing\" ]; then\n gh api --method PATCH \"repos/$REPO/issues/comments/$existing\" -f body=\"$body\" >/dev/null\n else\n gh api --method POST \"repos/$REPO/issues/$PR_NUMBER/comments\" -f body=\"$body\" >/dev/null\n fi\n\n # __ERD_PREVIEW_COMMENT_JOB_END__\n tailor-deploy:\n # __DEPLOY_IF__\n runs-on: ubuntu-latest\n timeout-minutes: 30\n permissions:\n contents: read\n environment: __ENVIRONMENT__\n concurrency:\n group: tailor-deploy-__WORKSPACE_NAME__\n cancel-in-progress: false\n steps:\n - id: tailor-checkout\n uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0\n - id: tailor-setup\n uses: tailor-platform/actions/setup@a3c3032e14277e81039eb26ae1a425adb22eb532 # v1.7.0\n with:\n package-manager: __PACKAGE_MANAGER__\n - id: tailor-install\n uses: tailor-platform/actions/install@a3c3032e14277e81039eb26ae1a425adb22eb532 # v1.7.0\n with:\n package-manager: __PACKAGE_MANAGER__\n - id: tailor-apply\n uses: tailor-platform/actions/deploy@a3c3032e14277e81039eb26ae1a425adb22eb532 # v1.7.0\n with:\n workspace-id: ${{ vars.TAILOR_PLATFORM_WORKSPACE_ID }}\n package-manager: __PACKAGE_MANAGER__\n # __WORKING_DIRECTORY__\n platform-client-id: ${{ secrets.TAILOR_PLATFORM_MACHINE_USER_CLIENT_ID }}\n platform-client-secret: ${{ secrets.TAILOR_PLATFORM_MACHINE_USER_CLIENT_SECRET }}\n # __SEED_DATA_START__\n - id: seed-data\n if: false\n shell: bash\n # __WORKING_DIRECTORY__\n run: |\n # Uncomment and implement to seed data on deploy.\n # Run after apply so the schema is ready.\n # Example: node scripts/seed.mjs\n true\n # __SEED_DATA_END__\n - id: slack-prereq\n if: always()\n shell: bash\n env:\n SLACK_TOKEN: ${{ secrets.TAILOR_SLACK_BOT_TOKEN }}\n SLACK_CHANNEL_ID: ${{ vars.TAILOR_SLACK_CHANNEL_ID }}\n run: |\n if [[ -n \"$SLACK_TOKEN\" && -n \"$SLACK_CHANNEL_ID\" ]]; then\n echo \"ready=true\" >> \"$GITHUB_OUTPUT\"\n fi\n - id: tailor-notify\n if: always() && steps.slack-prereq.outputs.ready == 'true'\n uses: tailor-platform/actions/notify@a3c3032e14277e81039eb26ae1a425adb22eb532 # v1.7.0\n with:\n provider: slack\n status: ${{ job.status }}\n workspace-name: __WORKSPACE_NAME__\n slack-token: ${{ secrets.TAILOR_SLACK_BOT_TOKEN }}\n slack-channel-id: ${{ vars.TAILOR_SLACK_CHANNEL_ID }}\n # user-mapping: ${{ vars.TAILOR_SLACK_USER_MAPPING }}\n";
2884
3487
 
2885
3488
  //#endregion
2886
3489
  //#region src/cli/commands/setup/coordinate.workflow.yml
2887
- var coordinate_workflow_default = "# __HEADER__\nname: Tailor Coordinator (__WORKSPACE_NAME__)\n\non:\n # __PULL_REQUEST_START__\n pull_request:\n branches: [\"__BRANCH__\"]\n # __PULL_REQUEST_END__\n push:\n # __PUSH_BRANCHES_START__\n branches: [\"__BRANCH__\"]\n # __PUSH_BRANCHES_END__\n # __PUSH_TAGS_START__\n tags: [__TAG_PATTERN__]\n # __PUSH_TAGS_END__\n workflow_dispatch:\n inputs:\n dry-run:\n description: Preview changes without deploying\n type: boolean\n default: false\n\npermissions:\n contents: read\n\njobs:\n # __TAG_GUARD_JOB_START__\n tailor-tag-guard:\n runs-on: ubuntu-latest\n timeout-minutes: 5\n permissions:\n contents: read\n outputs:\n on-branch: ${{ steps.tailor-tag-guard.outputs.on-branch }}\n steps:\n - id: tailor-checkout\n uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0\n with:\n fetch-depth: 0\n - id: tailor-tag-guard\n uses: tailor-platform/actions/tag-guard@e74173d4bdd931d036ad359cf5f7729fc6aa7067 # v1.5.1\n with:\n target-branch: __BRANCH__\n # __TAG_GUARD_JOB_END__\n\n tailor-plan:\n # __PLAN_NEEDS__\n # __PLAN_IF__\n runs-on: ubuntu-latest\n timeout-minutes: 60\n environment: __ENVIRONMENT__\n permissions:\n contents: read\n pull-requests: write\n concurrency:\n group: tailor-plan-__WORKSPACE_NAME__-${{ github.event.pull_request.number || github.run_id }}\n cancel-in-progress: true\n steps:\n - id: tailor-checkout\n uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0\n - id: tailor-setup\n uses: ./.github/actions/tailor-setup\n # __PER_APP_PLAN_STEPS__\n\n tailor-deploy:\n # __DEPLOY_NEEDS__\n # __DEPLOY_IF__\n # __DEPLOY_ENVIRONMENT__\n runs-on: ubuntu-latest\n timeout-minutes: 60\n permissions:\n contents: read\n concurrency:\n group: tailor-deploy-__WORKSPACE_NAME__\n cancel-in-progress: false\n steps:\n - id: tailor-checkout\n uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0\n - id: tailor-setup\n uses: ./.github/actions/tailor-setup\n # __PER_APP_DEPLOY_STEPS__\n";
3490
+ var coordinate_workflow_default = "# __HEADER__\nname: Tailor Coordinator (__WORKSPACE_NAME__)\n\non:\n # __PULL_REQUEST_START__\n pull_request:\n branches: [\"__BRANCH__\"]\n # __PULL_REQUEST_END__\n push:\n # __PUSH_BRANCHES_START__\n branches: [\"__BRANCH__\"]\n # __PUSH_BRANCHES_END__\n # __PUSH_TAGS_START__\n tags: [__TAG_PATTERN__]\n # __PUSH_TAGS_END__\n workflow_dispatch:\n inputs:\n dry-run:\n description: Preview changes without deploying\n type: boolean\n default: false\n\npermissions:\n contents: read\n\njobs:\n # __TAG_GUARD_JOB_START__\n tailor-tag-guard:\n runs-on: ubuntu-latest\n timeout-minutes: 5\n permissions:\n contents: read\n outputs:\n on-branch: ${{ steps.tailor-tag-guard.outputs.on-branch }}\n steps:\n - id: tailor-checkout\n uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0\n with:\n fetch-depth: 0\n - id: tailor-tag-guard\n uses: tailor-platform/actions/tag-guard@a3c3032e14277e81039eb26ae1a425adb22eb532 # v1.7.0\n with:\n target-branch: __BRANCH__\n # __TAG_GUARD_JOB_END__\n\n tailor-plan:\n # __PLAN_NEEDS__\n # __PLAN_IF__\n runs-on: ubuntu-latest\n timeout-minutes: 60\n environment: __ENVIRONMENT__\n permissions:\n contents: read\n pull-requests: write\n concurrency:\n group: tailor-plan-__WORKSPACE_NAME__-${{ github.event.pull_request.number || github.run_id }}\n cancel-in-progress: true\n steps:\n - id: tailor-checkout\n uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0\n - id: tailor-setup\n uses: ./.github/actions/tailor-setup\n # __PER_APP_PLAN_STEPS__\n\n tailor-deploy:\n # __DEPLOY_NEEDS__\n # __DEPLOY_IF__\n # __DEPLOY_ENVIRONMENT__\n runs-on: ubuntu-latest\n timeout-minutes: 60\n permissions:\n contents: read\n concurrency:\n group: tailor-deploy-__WORKSPACE_NAME__\n cancel-in-progress: false\n steps:\n - id: tailor-checkout\n uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0\n - id: tailor-setup\n uses: ./.github/actions/tailor-setup\n # __PER_APP_DEPLOY_STEPS__\n";
2888
3491
 
2889
3492
  //#endregion
2890
3493
  //#region src/cli/commands/setup/preview.workflow.yml
2891
- var preview_workflow_default = "# __HEADER__\nname: Tailor Preview (__WORKSPACE_NAME__)\n\non:\n pull_request:\n branches: [\"__BRANCH__\"]\n # __PR_TYPES__\n # To deploy only for PRs that carry the `tailor:preview` label instead of all PRs,\n # re-run: tailor-sdk setup --require-preview-label\n # __PATHS__\n\npermissions:\n contents: read\n pull-requests: write\n\njobs:\n tailor-preview-deploy:\n # __DEPLOY_IF__\n runs-on: ubuntu-latest\n timeout-minutes: 30\n environment: __ENVIRONMENT__\n permissions:\n contents: read\n pull-requests: write\n concurrency:\n group: tailor-preview-__WORKSPACE_NAME__-${{ github.event.pull_request.number }}\n cancel-in-progress: true\n steps:\n - id: tailor-checkout\n uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0\n - id: tailor-setup\n uses: tailor-platform/actions/setup@e74173d4bdd931d036ad359cf5f7729fc6aa7067 # v1.5.1\n with:\n package-manager: __PACKAGE_MANAGER__\n - id: tailor-install\n uses: tailor-platform/actions/install@e74173d4bdd931d036ad359cf5f7729fc6aa7067 # v1.5.1\n with:\n package-manager: __PACKAGE_MANAGER__\n - id: tailor-generate-check\n uses: tailor-platform/actions/generate-check@e74173d4bdd931d036ad359cf5f7729fc6aa7067 # v1.5.1\n with:\n package-manager: __PACKAGE_MANAGER__\n # __WORKING_DIRECTORY__\n - id: tailor-preview-deploy\n uses: tailor-platform/actions/preview-deploy@e74173d4bdd931d036ad359cf5f7729fc6aa7067 # v1.5.1\n with:\n workspace-name-prefix: __WORKSPACE_NAME__\n region: \"__REGION__\"\n organization-id: ${{ vars.TAILOR_PLATFORM_ORGANIZATION_ID }}\n folder-id: ${{ vars.TAILOR_PLATFORM_FOLDER_ID }}\n package-manager: __PACKAGE_MANAGER__\n # __WORKING_DIRECTORY__\n platform-client-id: ${{ secrets.TAILOR_PLATFORM_MACHINE_USER_CLIENT_ID }}\n platform-client-secret: ${{ secrets.TAILOR_PLATFORM_MACHINE_USER_CLIENT_SECRET }}\n github-token: ${{ secrets.GITHUB_TOKEN }}\n - id: tailor-preview-comment\n if: always()\n uses: tailor-platform/actions/preview-comment@e74173d4bdd931d036ad359cf5f7729fc6aa7067 # v1.5.1\n with:\n workspace-id: ${{ steps.tailor-preview-deploy.outputs.workspace-id }}\n workspace-name: ${{ steps.tailor-preview-deploy.outputs.workspace-name }}\n status: ${{ job.status == 'success' && 'success' || 'failure' }}\n app-url: ${{ steps.tailor-preview-deploy.outputs.app-url }}\n github-token: ${{ secrets.GITHUB_TOKEN }}\n\n tailor-preview-cleanup:\n # __CLEANUP_IF__\n runs-on: ubuntu-latest\n timeout-minutes: 15\n environment: __ENVIRONMENT__\n permissions:\n contents: read\n pull-requests: write\n steps:\n - id: tailor-checkout\n uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0\n - id: tailor-setup\n uses: tailor-platform/actions/setup@e74173d4bdd931d036ad359cf5f7729fc6aa7067 # v1.5.1\n with:\n package-manager: __PACKAGE_MANAGER__\n - id: tailor-install\n uses: tailor-platform/actions/install@e74173d4bdd931d036ad359cf5f7729fc6aa7067 # v1.5.1\n with:\n package-manager: __PACKAGE_MANAGER__\n - id: tailor-preview-cleanup\n uses: tailor-platform/actions/preview-cleanup@e74173d4bdd931d036ad359cf5f7729fc6aa7067 # v1.5.1\n with:\n workspace-name-prefix: __WORKSPACE_NAME__\n package-manager: __PACKAGE_MANAGER__\n # __WORKING_DIRECTORY__\n platform-client-id: ${{ secrets.TAILOR_PLATFORM_MACHINE_USER_CLIENT_ID }}\n platform-client-secret: ${{ secrets.TAILOR_PLATFORM_MACHINE_USER_CLIENT_SECRET }}\n github-token: ${{ secrets.GITHUB_TOKEN }}\n";
3494
+ var preview_workflow_default = "# __HEADER__\nname: Tailor Preview (__WORKSPACE_NAME__)\n\non:\n pull_request:\n branches: [\"__BRANCH__\"]\n # __PR_TYPES__\n # To deploy only for PRs that carry the `tailor:preview` label instead of all PRs,\n # re-run: tailor-sdk setup --require-preview-label\n # __PATHS__\n\npermissions:\n contents: read\n pull-requests: write\n\njobs:\n tailor-preview-deploy:\n # __DEPLOY_IF__\n runs-on: ubuntu-latest\n timeout-minutes: 30\n environment: __ENVIRONMENT__\n permissions:\n contents: read\n pull-requests: write\n concurrency:\n group: tailor-preview-__WORKSPACE_NAME__-${{ github.event.pull_request.number }}\n cancel-in-progress: true\n steps:\n - id: tailor-checkout\n uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0\n - id: tailor-setup\n uses: tailor-platform/actions/setup@a3c3032e14277e81039eb26ae1a425adb22eb532 # v1.7.0\n with:\n package-manager: __PACKAGE_MANAGER__\n - id: tailor-install\n uses: tailor-platform/actions/install@a3c3032e14277e81039eb26ae1a425adb22eb532 # v1.7.0\n with:\n package-manager: __PACKAGE_MANAGER__\n - id: tailor-generate-check\n uses: tailor-platform/actions/generate-check@a3c3032e14277e81039eb26ae1a425adb22eb532 # v1.7.0\n with:\n package-manager: __PACKAGE_MANAGER__\n # __WORKING_DIRECTORY__\n - id: tailor-preview-deploy\n uses: tailor-platform/actions/preview-deploy@a3c3032e14277e81039eb26ae1a425adb22eb532 # v1.7.0\n with:\n workspace-name-prefix: __WORKSPACE_NAME__\n region: \"__REGION__\"\n organization-id: ${{ vars.TAILOR_PLATFORM_ORGANIZATION_ID }}\n folder-id: ${{ vars.TAILOR_PLATFORM_FOLDER_ID }}\n package-manager: __PACKAGE_MANAGER__\n # __WORKING_DIRECTORY__\n platform-client-id: ${{ secrets.TAILOR_PLATFORM_MACHINE_USER_CLIENT_ID }}\n platform-client-secret: ${{ secrets.TAILOR_PLATFORM_MACHINE_USER_CLIENT_SECRET }}\n github-token: ${{ secrets.GITHUB_TOKEN }}\n - id: tailor-preview-comment\n if: always()\n uses: tailor-platform/actions/preview-comment@a3c3032e14277e81039eb26ae1a425adb22eb532 # v1.7.0\n with:\n workspace-id: ${{ steps.tailor-preview-deploy.outputs.workspace-id }}\n workspace-name: ${{ steps.tailor-preview-deploy.outputs.workspace-name }}\n status: ${{ job.status == 'success' && 'success' || 'failure' }}\n app-url: ${{ steps.tailor-preview-deploy.outputs.app-url }}\n github-token: ${{ secrets.GITHUB_TOKEN }}\n\n tailor-preview-cleanup:\n # __CLEANUP_IF__\n runs-on: ubuntu-latest\n timeout-minutes: 15\n environment: __ENVIRONMENT__\n permissions:\n contents: read\n pull-requests: write\n steps:\n - id: tailor-checkout\n uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0\n - id: tailor-setup\n uses: tailor-platform/actions/setup@a3c3032e14277e81039eb26ae1a425adb22eb532 # v1.7.0\n with:\n package-manager: __PACKAGE_MANAGER__\n - id: tailor-install\n uses: tailor-platform/actions/install@a3c3032e14277e81039eb26ae1a425adb22eb532 # v1.7.0\n with:\n package-manager: __PACKAGE_MANAGER__\n - id: tailor-preview-cleanup\n uses: tailor-platform/actions/preview-cleanup@a3c3032e14277e81039eb26ae1a425adb22eb532 # v1.7.0\n with:\n workspace-name-prefix: __WORKSPACE_NAME__\n package-manager: __PACKAGE_MANAGER__\n # __WORKING_DIRECTORY__\n platform-client-id: ${{ secrets.TAILOR_PLATFORM_MACHINE_USER_CLIENT_ID }}\n platform-client-secret: ${{ secrets.TAILOR_PLATFORM_MACHINE_USER_CLIENT_SECRET }}\n github-token: ${{ secrets.GITHUB_TOKEN }}\n";
2892
3495
 
2893
3496
  //#endregion
2894
3497
  //#region src/cli/commands/setup/tag.workflow.yml
2895
- var tag_workflow_default = "# __HEADER__\nname: Tailor (__WORKSPACE_NAME__)\n\non:\n push:\n tags: [\"__TAG_PATTERN__\"]\n workflow_dispatch:\n inputs:\n dry-run:\n description: Preview changes without deploying\n type: boolean\n default: false\n\npermissions:\n contents: read\n\njobs:\n # __TAG_GUARD_JOB_START__\n tailor-tag-guard:\n runs-on: ubuntu-latest\n timeout-minutes: 10\n permissions:\n contents: read\n outputs:\n on-branch: ${{ steps.tailor-tag-guard.outputs.on-branch }}\n steps:\n - id: tailor-checkout\n uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0\n with:\n fetch-depth: 0\n - id: tailor-tag-guard\n uses: tailor-platform/actions/tag-guard@e74173d4bdd931d036ad359cf5f7729fc6aa7067 # v1.5.1\n with:\n target-branch: \"__BRANCH__\"\n # __TAG_GUARD_JOB_END__\n tailor-plan:\n # __PLAN_NEEDS__\n # __PLAN_IF__\n runs-on: ubuntu-latest\n timeout-minutes: 30\n environment: __ENVIRONMENT__\n permissions:\n contents: read\n steps:\n - id: tailor-checkout\n uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0\n - id: tailor-setup\n uses: tailor-platform/actions/setup@e74173d4bdd931d036ad359cf5f7729fc6aa7067 # v1.5.1\n with:\n package-manager: __PACKAGE_MANAGER__\n - id: tailor-install\n uses: tailor-platform/actions/install@e74173d4bdd931d036ad359cf5f7729fc6aa7067 # v1.5.1\n with:\n package-manager: __PACKAGE_MANAGER__\n - id: tailor-generate-check\n uses: tailor-platform/actions/generate-check@e74173d4bdd931d036ad359cf5f7729fc6aa7067 # v1.5.1\n with:\n package-manager: __PACKAGE_MANAGER__\n # __WORKING_DIRECTORY__\n # __SEED_VALIDATE_START__\n - id: tailor-seed-validate\n uses: tailor-platform/actions/seed-validate@e74173d4bdd931d036ad359cf5f7729fc6aa7067 # v1.5.1\n with:\n package-manager: __PACKAGE_MANAGER__\n # __WORKING_DIRECTORY__\n # __SEED_VALIDATE_END__\n - id: tailor-drift-check\n uses: tailor-platform/actions/drift-check@e74173d4bdd931d036ad359cf5f7729fc6aa7067 # v1.5.1\n with:\n package-manager: __PACKAGE_MANAGER__\n # __MIGRATION_DRIFT_CHECK_START__\n - id: tailor-migration-drift-check\n uses: tailor-platform/actions/migration-drift-check@e74173d4bdd931d036ad359cf5f7729fc6aa7067 # v1.5.1\n with:\n package-manager: __PACKAGE_MANAGER__\n # __WORKING_DIRECTORY__\n # __MIGRATION_DRIFT_CHECK_END__\n - id: tailor-plan\n uses: tailor-platform/actions/plan@e74173d4bdd931d036ad359cf5f7729fc6aa7067 # v1.5.1\n with:\n workspace-id: ${{ vars.TAILOR_PLATFORM_WORKSPACE_ID }}\n package-manager: __PACKAGE_MANAGER__\n label: __WORKSPACE_NAME__\n # __WORKING_DIRECTORY__\n platform-client-id: ${{ secrets.TAILOR_PLATFORM_MACHINE_USER_CLIENT_ID }}\n platform-client-secret: ${{ secrets.TAILOR_PLATFORM_MACHINE_USER_CLIENT_SECRET }}\n\n tailor-deploy:\n needs: tailor-plan\n if: ${{ !(github.event_name == 'workflow_dispatch' && inputs['dry-run']) }}\n environment: __ENVIRONMENT__\n runs-on: ubuntu-latest\n timeout-minutes: 30\n permissions:\n contents: read\n concurrency:\n group: tailor-deploy-__WORKSPACE_NAME__\n cancel-in-progress: false\n steps:\n - id: tailor-checkout\n uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0\n - id: tailor-setup\n uses: tailor-platform/actions/setup@e74173d4bdd931d036ad359cf5f7729fc6aa7067 # v1.5.1\n with:\n package-manager: __PACKAGE_MANAGER__\n - id: tailor-install\n uses: tailor-platform/actions/install@e74173d4bdd931d036ad359cf5f7729fc6aa7067 # v1.5.1\n with:\n package-manager: __PACKAGE_MANAGER__\n - id: tailor-apply\n uses: tailor-platform/actions/deploy@e74173d4bdd931d036ad359cf5f7729fc6aa7067 # v1.5.1\n with:\n workspace-id: ${{ vars.TAILOR_PLATFORM_WORKSPACE_ID }}\n package-manager: __PACKAGE_MANAGER__\n # __WORKING_DIRECTORY__\n platform-client-id: ${{ secrets.TAILOR_PLATFORM_MACHINE_USER_CLIENT_ID }}\n platform-client-secret: ${{ secrets.TAILOR_PLATFORM_MACHINE_USER_CLIENT_SECRET }}\n # __SEED_DATA_START__\n - id: seed-data\n if: false\n shell: bash\n # __WORKING_DIRECTORY__\n run: |\n # Uncomment and implement to seed data on deploy.\n # Run after apply so the schema is ready.\n # Example: node scripts/seed.mjs\n true\n # __SEED_DATA_END__\n - id: slack-prereq\n if: always()\n shell: bash\n env:\n SLACK_TOKEN: ${{ secrets.TAILOR_SLACK_BOT_TOKEN }}\n SLACK_CHANNEL_ID: ${{ vars.TAILOR_SLACK_CHANNEL_ID }}\n run: |\n if [[ -n \"$SLACK_TOKEN\" && -n \"$SLACK_CHANNEL_ID\" ]]; then\n echo \"ready=true\" >> \"$GITHUB_OUTPUT\"\n fi\n - id: tailor-notify\n if: always() && steps.slack-prereq.outputs.ready == 'true'\n uses: tailor-platform/actions/notify@e74173d4bdd931d036ad359cf5f7729fc6aa7067 # v1.5.1\n with:\n provider: slack\n status: ${{ job.status }}\n workspace-name: __WORKSPACE_NAME__\n slack-token: ${{ secrets.TAILOR_SLACK_BOT_TOKEN }}\n slack-channel-id: ${{ vars.TAILOR_SLACK_CHANNEL_ID }}\n # user-mapping: ${{ vars.TAILOR_SLACK_USER_MAPPING }}\n";
3498
+ var tag_workflow_default = "# __HEADER__\nname: Tailor (__WORKSPACE_NAME__)\n\non:\n push:\n tags: [\"__TAG_PATTERN__\"]\n workflow_dispatch:\n inputs:\n dry-run:\n description: Preview changes without deploying\n type: boolean\n default: false\n\npermissions:\n contents: read\n\njobs:\n # __TAG_GUARD_JOB_START__\n tailor-tag-guard:\n runs-on: ubuntu-latest\n timeout-minutes: 10\n permissions:\n contents: read\n outputs:\n on-branch: ${{ steps.tailor-tag-guard.outputs.on-branch }}\n steps:\n - id: tailor-checkout\n uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0\n with:\n fetch-depth: 0\n - id: tailor-tag-guard\n uses: tailor-platform/actions/tag-guard@a3c3032e14277e81039eb26ae1a425adb22eb532 # v1.7.0\n with:\n target-branch: \"__BRANCH__\"\n # __TAG_GUARD_JOB_END__\n tailor-plan:\n # __PLAN_NEEDS__\n # __PLAN_IF__\n runs-on: ubuntu-latest\n timeout-minutes: 30\n environment: __ENVIRONMENT__\n permissions:\n contents: read\n steps:\n - id: tailor-checkout\n uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0\n - id: tailor-setup\n uses: tailor-platform/actions/setup@a3c3032e14277e81039eb26ae1a425adb22eb532 # v1.7.0\n with:\n package-manager: __PACKAGE_MANAGER__\n - id: tailor-install\n uses: tailor-platform/actions/install@a3c3032e14277e81039eb26ae1a425adb22eb532 # v1.7.0\n with:\n package-manager: __PACKAGE_MANAGER__\n - id: tailor-generate-check\n uses: tailor-platform/actions/generate-check@a3c3032e14277e81039eb26ae1a425adb22eb532 # v1.7.0\n with:\n package-manager: __PACKAGE_MANAGER__\n # __WORKING_DIRECTORY__\n # __SEED_VALIDATE_START__\n - id: tailor-seed-validate\n uses: tailor-platform/actions/seed-validate@a3c3032e14277e81039eb26ae1a425adb22eb532 # v1.7.0\n with:\n package-manager: __PACKAGE_MANAGER__\n # __WORKING_DIRECTORY__\n # __SEED_VALIDATE_END__\n - id: tailor-drift-check\n uses: tailor-platform/actions/drift-check@a3c3032e14277e81039eb26ae1a425adb22eb532 # v1.7.0\n with:\n package-manager: __PACKAGE_MANAGER__\n # __MIGRATION_DRIFT_CHECK_START__\n - id: tailor-migration-drift-check\n uses: tailor-platform/actions/migration-drift-check@a3c3032e14277e81039eb26ae1a425adb22eb532 # v1.7.0\n with:\n package-manager: __PACKAGE_MANAGER__\n # __WORKING_DIRECTORY__\n # __MIGRATION_DRIFT_CHECK_END__\n - id: tailor-plan\n uses: tailor-platform/actions/plan@a3c3032e14277e81039eb26ae1a425adb22eb532 # v1.7.0\n with:\n workspace-id: ${{ vars.TAILOR_PLATFORM_WORKSPACE_ID }}\n package-manager: __PACKAGE_MANAGER__\n label: __WORKSPACE_NAME__\n # __WORKING_DIRECTORY__\n platform-client-id: ${{ secrets.TAILOR_PLATFORM_MACHINE_USER_CLIENT_ID }}\n platform-client-secret: ${{ secrets.TAILOR_PLATFORM_MACHINE_USER_CLIENT_SECRET }}\n\n tailor-deploy:\n needs: tailor-plan\n if: ${{ !(github.event_name == 'workflow_dispatch' && inputs['dry-run']) }}\n environment: __ENVIRONMENT__\n runs-on: ubuntu-latest\n timeout-minutes: 30\n permissions:\n contents: read\n concurrency:\n group: tailor-deploy-__WORKSPACE_NAME__\n cancel-in-progress: false\n steps:\n - id: tailor-checkout\n uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0\n - id: tailor-setup\n uses: tailor-platform/actions/setup@a3c3032e14277e81039eb26ae1a425adb22eb532 # v1.7.0\n with:\n package-manager: __PACKAGE_MANAGER__\n - id: tailor-install\n uses: tailor-platform/actions/install@a3c3032e14277e81039eb26ae1a425adb22eb532 # v1.7.0\n with:\n package-manager: __PACKAGE_MANAGER__\n - id: tailor-apply\n uses: tailor-platform/actions/deploy@a3c3032e14277e81039eb26ae1a425adb22eb532 # v1.7.0\n with:\n workspace-id: ${{ vars.TAILOR_PLATFORM_WORKSPACE_ID }}\n package-manager: __PACKAGE_MANAGER__\n # __WORKING_DIRECTORY__\n platform-client-id: ${{ secrets.TAILOR_PLATFORM_MACHINE_USER_CLIENT_ID }}\n platform-client-secret: ${{ secrets.TAILOR_PLATFORM_MACHINE_USER_CLIENT_SECRET }}\n # __SEED_DATA_START__\n - id: seed-data\n if: false\n shell: bash\n # __WORKING_DIRECTORY__\n run: |\n # Uncomment and implement to seed data on deploy.\n # Run after apply so the schema is ready.\n # Example: node scripts/seed.mjs\n true\n # __SEED_DATA_END__\n - id: slack-prereq\n if: always()\n shell: bash\n env:\n SLACK_TOKEN: ${{ secrets.TAILOR_SLACK_BOT_TOKEN }}\n SLACK_CHANNEL_ID: ${{ vars.TAILOR_SLACK_CHANNEL_ID }}\n run: |\n if [[ -n \"$SLACK_TOKEN\" && -n \"$SLACK_CHANNEL_ID\" ]]; then\n echo \"ready=true\" >> \"$GITHUB_OUTPUT\"\n fi\n - id: tailor-notify\n if: always() && steps.slack-prereq.outputs.ready == 'true'\n uses: tailor-platform/actions/notify@a3c3032e14277e81039eb26ae1a425adb22eb532 # v1.7.0\n with:\n provider: slack\n status: ${{ job.status }}\n workspace-name: __WORKSPACE_NAME__\n slack-token: ${{ secrets.TAILOR_SLACK_BOT_TOKEN }}\n slack-channel-id: ${{ vars.TAILOR_SLACK_CHANNEL_ID }}\n # user-mapping: ${{ vars.TAILOR_SLACK_USER_MAPPING }}\n";
2896
3499
 
2897
3500
  //#endregion
2898
3501
  //#region src/cli/commands/setup/templates.ts
@@ -3062,7 +3665,8 @@ function renderActionWorkflow(params) {
3062
3665
  generatedIds: ["tailor-apply", "tailor-notify"]
3063
3666
  };
3064
3667
  }
3065
- const ACTIONS_SHA = "e74173d4bdd931d036ad359cf5f7729fc6aa7067";
3668
+ const ACTIONS_SHA = "a3c3032e14277e81039eb26ae1a425adb22eb532";
3669
+ const ACTIONS_VERSION = "v1.7.0";
3066
3670
  /**
3067
3671
  * Render the coordinator workflow that orchestrates per-app composite actions.
3068
3672
  *
@@ -3104,7 +3708,7 @@ function renderCoordinateWorkflow(params) {
3104
3708
  }
3105
3709
  const driftCheckStep = [
3106
3710
  `- id: tailor-drift-check`,
3107
- ` uses: tailor-platform/actions/drift-check@${ACTIONS_SHA} # v1.5.1`,
3711
+ ` uses: tailor-platform/actions/drift-check@${ACTIONS_SHA} # ${ACTIONS_VERSION}`,
3108
3712
  ` with:`,
3109
3713
  ` package-manager: ${packageManager}`
3110
3714
  ].join("\n");
@@ -3121,7 +3725,7 @@ function renderCoordinateWorkflow(params) {
3121
3725
  return [
3122
3726
  `- id: tailor-plan-${group.id}`,
3123
3727
  ` if: github.event_name != 'pull_request' || !github.event.pull_request.head.repo.fork`,
3124
- ` uses: tailor-platform/actions/plan@${ACTIONS_SHA} # v1.5.1`,
3728
+ ` uses: tailor-platform/actions/plan@${ACTIONS_SHA} # ${ACTIONS_VERSION}`,
3125
3729
  ` with:`,
3126
3730
  ` workspace-id: \${{ vars.TAILOR_PLATFORM_WORKSPACE_ID }}`,
3127
3731
  ` package-manager: ${packageManager}${wdLine}`,
@@ -3134,7 +3738,7 @@ function renderCoordinateWorkflow(params) {
3134
3738
  const multiConfigPlanStep = (group) => [
3135
3739
  `- id: tailor-plan-${group.id}`,
3136
3740
  ` if: github.event_name != 'pull_request' || !github.event.pull_request.head.repo.fork`,
3137
- ` uses: tailor-platform/actions/plan@${ACTIONS_SHA} # v1.5.1`,
3741
+ ` uses: tailor-platform/actions/plan@${ACTIONS_SHA} # ${ACTIONS_VERSION}`,
3138
3742
  ` env:`,
3139
3743
  ` TAILOR_PLATFORM_SDK_CONFIG_PATH: ${groupConfigPath(group)}`,
3140
3744
  ` with:`,
@@ -3151,7 +3755,7 @@ function renderCoordinateWorkflow(params) {
3151
3755
  const wdLine = wd ? `\n working-directory: ${wd}` : "";
3152
3756
  return [
3153
3757
  `- id: tailor-generate-check-${app.name}`,
3154
- ` uses: tailor-platform/actions/generate-check@${ACTIONS_SHA} # v1.5.1`,
3758
+ ` uses: tailor-platform/actions/generate-check@${ACTIONS_SHA} # ${ACTIONS_VERSION}`,
3155
3759
  ` with:`,
3156
3760
  ` package-manager: ${packageManager}${wdLine}`
3157
3761
  ];
@@ -3246,11 +3850,11 @@ function renderTailorSetupAction(params) {
3246
3850
  `runs:`,
3247
3851
  ` using: composite`,
3248
3852
  ` steps:`,
3249
- ` - uses: tailor-platform/actions/setup@${ACTIONS_SHA} # v1.5.1`,
3853
+ ` - uses: tailor-platform/actions/setup@${ACTIONS_SHA} # ${ACTIONS_VERSION}`,
3250
3854
  ` with:`,
3251
3855
  ` package-manager: ${packageManager}`,
3252
3856
  ` # Add custom steps here (e.g. private registry authentication)`,
3253
- ` - uses: tailor-platform/actions/install@${ACTIONS_SHA} # v1.5.1`,
3857
+ ` - uses: tailor-platform/actions/install@${ACTIONS_SHA} # ${ACTIONS_VERSION}`,
3254
3858
  ` with:`,
3255
3859
  ` package-manager: ${packageManager}`,
3256
3860
  ` # editable: install-command:`,
@@ -3299,9 +3903,8 @@ async function defaultLoadHasStaticWebsites$1(configPath) {
3299
3903
  const { config } = await loadConfig(configPath);
3300
3904
  return (config.staticWebsites?.length ?? 0) > 0;
3301
3905
  }
3302
- const WORKSPACE_NAME_RE = /^[a-z0-9-]+$/;
3303
3906
  function validateWorkspaceName(name) {
3304
- if (name.length < 3 || name.length > 63 || !WORKSPACE_NAME_RE.test(name) || name.startsWith("-") || name.endsWith("-")) throw new Error(`Invalid workspace name "${name}". Names must be 3-63 characters of lowercase letters, numbers, and hyphens, and cannot start or end with a hyphen. Pass a valid name with --name.`);
3907
+ if (!workspaceNameSchema.safeParse(name).success) throw new Error(`Invalid workspace name "${name}". Names must be 3-63 characters of lowercase letters, numbers, and hyphens, and cannot start or end with a hyphen. Pass a valid name with --name.`);
3305
3908
  }
3306
3909
  const BRANCH_RE = /^[A-Za-z0-9._/-]+$/;
3307
3910
  const TAG_PATTERN_RE = /^[A-Za-z0-9._/*?![\]-]+$/;
@@ -5431,7 +6034,7 @@ function resolveNamespace(options) {
5431
6034
  if (options.head && options.head.namespace !== namespace) throw new Error(`Head ERD namespace "${options.head.namespace}" does not match "${namespace}".`);
5432
6035
  return namespace;
5433
6036
  }
5434
- function writeFile(filePath, content) {
6037
+ function writeFile$1(filePath, content) {
5435
6038
  fs$1.mkdirSync(path.dirname(filePath), { recursive: true });
5436
6039
  fs$1.writeFileSync(filePath, content, "utf8");
5437
6040
  }
@@ -5460,12 +6063,12 @@ function writeErdDiff(options) {
5460
6063
  base: baseSchema,
5461
6064
  head: headSchema
5462
6065
  });
5463
- writeFile(options.outputHtml, renderErdDiffHtml({
6066
+ writeFile$1(options.outputHtml, renderErdDiffHtml({
5464
6067
  schema: viewerSchema,
5465
6068
  currentSchema: headSchema,
5466
6069
  diff
5467
6070
  }));
5468
- if (options.outputJson) writeFile(options.outputJson, `${JSON.stringify(diff, null, 2)}\n`);
6071
+ if (options.outputJson) writeFile$1(options.outputJson, `${JSON.stringify(diff, null, 2)}\n`);
5469
6072
  return {
5470
6073
  namespace,
5471
6074
  outputHtml: options.outputHtml,
@@ -6222,7 +6825,7 @@ async function fetchRemoteTypes(client, workspaceId, namespace) {
6222
6825
  async function assertMigrationsReproduceLocalTypes(loaded, target) {
6223
6826
  const { config, plugins } = loaded;
6224
6827
  const pluginManager = plugins.length > 0 ? new PluginManager(plugins) : void 0;
6225
- const { defineApplication, generatePluginFilesIfNeeded } = await import("../application-DbvD5UUz.mjs");
6828
+ const { defineApplication, generatePluginFilesIfNeeded } = await import("../application-Dp_-ioiP.mjs");
6226
6829
  const application = defineApplication({
6227
6830
  config,
6228
6831
  pluginManager
@@ -6234,7 +6837,7 @@ async function assertMigrationsReproduceLocalTypes(loaded, target) {
6234
6837
  await service.processNamespacePlugins();
6235
6838
  }
6236
6839
  const pluginExecutorFiles = generatePluginFilesIfNeeded(pluginManager, application.tailorDBServices, config.path);
6237
- const executorService = application.executorService ?? (pluginExecutorFiles.length > 0 ? (await import("../service-CPMlIg3X.mjs")).createExecutorService({ config: { files: [] } }) : void 0);
6840
+ const executorService = application.executorService ?? (pluginExecutorFiles.length > 0 ? (await import("../service-CghpdV-9.mjs")).createExecutorService({ config: { files: [] } }) : void 0);
6238
6841
  await executorService?.loadExecutors();
6239
6842
  if (pluginExecutorFiles.length > 0) await executorService?.loadPluginExecutorFiles([...pluginExecutorFiles]);
6240
6843
  const executorUsedTypes = /* @__PURE__ */ new Set();
@@ -6505,7 +7108,7 @@ const upgradeCommand = defineAppCommand({
6505
7108
  run: async (args) => {
6506
7109
  const { initTelemetry } = await import("../telemetry-ClwW5ohF.mjs");
6507
7110
  await initTelemetry();
6508
- const { upgrade } = await import("../service-DBFZQloR.mjs");
7111
+ const { upgrade } = await import("../service-Cp0I7ZFe.mjs");
6509
7112
  await upgrade({
6510
7113
  from: args.from,
6511
7114
  dryRun: args["dry-run"],
@@ -6848,7 +7451,7 @@ const workflowCommand = defineCommand({
6848
7451
  name: "workflow",
6849
7452
  description: "Manage workflows and workflow executions.",
6850
7453
  subCommands: {
6851
- list: listCommand$12,
7454
+ list: listCommand$13,
6852
7455
  get: getCommand$6,
6853
7456
  start: startCommand,
6854
7457
  wait: waitCommand,
@@ -6856,7 +7459,7 @@ const workflowCommand = defineCommand({
6856
7459
  resume: resumeCommand
6857
7460
  },
6858
7461
  async run() {
6859
- await runCommand(listCommand$12, []);
7462
+ await runCommand(listCommand$13, []);
6860
7463
  }
6861
7464
  });
6862
7465
 
@@ -6867,10 +7470,10 @@ const appCommand = defineCommand({
6867
7470
  description: "Manage workspace applications",
6868
7471
  subCommands: {
6869
7472
  health: healthCommand,
6870
- list: listCommand$13
7473
+ list: listCommand$14
6871
7474
  },
6872
7475
  async run() {
6873
- await runCommand(listCommand$13, []);
7476
+ await runCommand(listCommand$14, []);
6874
7477
  }
6875
7478
  });
6876
7479
 
@@ -6881,12 +7484,12 @@ const userCommand = defineCommand({
6881
7484
  description: "Manage workspace users",
6882
7485
  subCommands: {
6883
7486
  invite: inviteCommand,
6884
- list: listCommand$14,
7487
+ list: listCommand$15,
6885
7488
  remove: removeCommand,
6886
7489
  update: updateCommand$4
6887
7490
  },
6888
7491
  async run() {
6889
- await runCommand(listCommand$14, []);
7492
+ await runCommand(listCommand$15, []);
6890
7493
  }
6891
7494
  });
6892
7495
 
@@ -6900,12 +7503,12 @@ const workspaceCommand = defineCommand({
6900
7503
  create: createCommand$4,
6901
7504
  delete: deleteCommand$5,
6902
7505
  get: getCommand$7,
6903
- list: listCommand$15,
7506
+ list: listCommand$16,
6904
7507
  restore: restoreCommand,
6905
7508
  user: userCommand
6906
7509
  },
6907
7510
  async run() {
6908
- await runCommand(listCommand$15, []);
7511
+ await runCommand(listCommand$16, []);
6909
7512
  }
6910
7513
  });
6911
7514
 
@@ -6957,7 +7560,8 @@ runMain(mainCommand, {
6957
7560
  displayErrors: false,
6958
7561
  cleanup: async ({ error }) => {
6959
7562
  if (error) {
6960
- if (isCLIError(error)) {
7563
+ if (logger.jsonMode) logger.log(JSON.stringify(errorToJson(error, { includeStack: isVerbose() })));
7564
+ else if (isCLIError(error)) {
6961
7565
  logger.log(error.format());
6962
7566
  if (isVerbose() && error.stack) logger.debug(`\nStack trace:\n${error.stack}`);
6963
7567
  } else if (error instanceof Error) {
@@ -6965,7 +7569,7 @@ runMain(mainCommand, {
6965
7569
  if (isVerbose() && error.stack) logger.debug(`\nStack trace:\n${error.stack}`);
6966
7570
  } else logger.error(`Unknown error: ${error}`);
6967
7571
  if (!isCLIError(error) && (!(error instanceof Error) || error instanceof TypeError || error instanceof RangeError)) {
6968
- const { reportCrash } = await import("../crashreport-Dy4ZzSkd.mjs");
7572
+ const { reportCrash } = await import("../crashreport-BafWvjjX.mjs");
6969
7573
  await reportCrash(error, "handledError");
6970
7574
  }
6971
7575
  }