@tailor-platform/sdk 2.33.0 → 2.34.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 (329) hide show
  1. package/CHANGELOG.md +58 -0
  2. package/dist/ai/index.d.mts +1 -3
  3. package/dist/{application-Bet1K5C4.mjs → application-CwpOIOTt.mjs} +1 -1
  4. package/dist/application-Nce5z46R.mjs +207 -0
  5. package/dist/application-Nce5z46R.mjs.map +1 -0
  6. package/dist/cli/cache/bundle-cache.d.mts +1 -0
  7. package/dist/cli/commands/api/api-call.d.mts +1 -3
  8. package/dist/cli/commands/deploy/aigateway.d.mts +1 -0
  9. package/dist/cli/commands/deploy/app-id-lock.d.mts +1 -3
  10. package/dist/cli/commands/deploy/application.d.mts +1 -0
  11. package/dist/cli/commands/deploy/auth.d.mts +1 -0
  12. package/dist/cli/commands/deploy/config-id-injector.d.mts +1 -3
  13. package/dist/cli/commands/deploy/confirm.d.mts +1 -0
  14. package/dist/cli/commands/deploy/deploy.d.mts +4 -3
  15. package/dist/cli/commands/deploy/executor.d.mts +1 -0
  16. package/dist/cli/commands/deploy/function-registry-types.d.mts +1 -3
  17. package/dist/cli/commands/deploy/function-registry.d.mts +1 -0
  18. package/dist/cli/commands/deploy/idp.d.mts +1 -0
  19. package/dist/cli/commands/deploy/owned-resource.d.mts +3 -0
  20. package/dist/cli/commands/deploy/resolver.d.mts +1 -0
  21. package/dist/cli/commands/deploy/secret-manager.d.mts +1 -0
  22. package/dist/cli/commands/deploy/staticwebsite.d.mts +1 -0
  23. package/dist/cli/commands/deploy/tailordb/plan.d.mts +1 -0
  24. package/dist/cli/commands/deploy/workflow-execution-policy.d.mts +2 -1
  25. package/dist/cli/commands/deploy/workflow.d.mts +1 -0
  26. package/dist/cli/commands/executor/get.d.mts +0 -2
  27. package/dist/cli/commands/executor/jobs.d.mts +0 -2
  28. package/dist/cli/commands/executor/list.d.mts +1 -3
  29. package/dist/cli/commands/executor/transform.d.mts +1 -3
  30. package/dist/cli/commands/executor/trigger.d.mts +0 -2
  31. package/dist/cli/commands/executor/webhook.d.mts +1 -3
  32. package/dist/cli/commands/function/get.d.mts +0 -2
  33. package/dist/cli/commands/function/list.d.mts +0 -2
  34. package/dist/cli/commands/function/transform.d.mts +1 -3
  35. package/dist/cli/commands/generate/options.d.mts +1 -3
  36. package/dist/cli/commands/generate/seed/bundler.d.mts +1 -3
  37. package/dist/cli/commands/generate/service.d.mts +1 -3
  38. package/dist/cli/commands/machineuser/list.d.mts +1 -3
  39. package/dist/cli/commands/machineuser/token.d.mts +1 -3
  40. package/dist/cli/commands/oauth2client/get.d.mts +1 -3
  41. package/dist/cli/commands/oauth2client/list.d.mts +1 -3
  42. package/dist/cli/commands/oauth2client/transform.d.mts +1 -3
  43. package/dist/cli/commands/organization/folder/create.d.mts +0 -2
  44. package/dist/cli/commands/organization/folder/delete.d.mts +0 -2
  45. package/dist/cli/commands/organization/folder/get.d.mts +0 -2
  46. package/dist/cli/commands/organization/folder/list.d.mts +0 -2
  47. package/dist/cli/commands/organization/folder/update.d.mts +0 -2
  48. package/dist/cli/commands/organization/get.d.mts +0 -2
  49. package/dist/cli/commands/organization/list.d.mts +1 -3
  50. package/dist/cli/commands/organization/transform.d.mts +1 -3
  51. package/dist/cli/commands/organization/tree.d.mts +0 -2
  52. package/dist/cli/commands/organization/update.d.mts +0 -2
  53. package/dist/cli/commands/remove.d.mts +1 -3
  54. package/dist/cli/commands/show.d.mts +0 -2
  55. package/dist/cli/commands/staticwebsite/deploy.d.mts +1 -3
  56. package/dist/cli/commands/tailordb/migrate/bundler.d.mts +1 -3
  57. package/dist/cli/commands/tailordb/migrate/config.d.mts +1 -3
  58. package/dist/cli/commands/tailordb/migrate/diff-calculator.d.mts +0 -2
  59. package/dist/cli/commands/tailordb/migrate/generate.d.mts +1 -3
  60. package/dist/cli/commands/tailordb/migrate/rename-detection.d.mts +1 -3
  61. package/dist/cli/commands/tailordb/migrate/snapshot-comparison.d.mts +1 -3
  62. package/dist/cli/commands/tailordb/migrate/snapshot-files.d.mts +1 -3
  63. package/dist/cli/commands/tailordb/migrate/snapshot-local.d.mts +1 -3
  64. package/dist/cli/commands/tailordb/migrate/snapshot-migrations.d.mts +1 -3
  65. package/dist/cli/commands/tailordb/migrate/snapshot-types.d.mts +0 -2
  66. package/dist/cli/commands/tailordb/migrate/types.d.mts +1 -3
  67. package/dist/cli/commands/tailordb/truncate.d.mts +1 -3
  68. package/dist/cli/commands/workflow/executions.d.mts +0 -2
  69. package/dist/cli/commands/workflow/get.d.mts +0 -2
  70. package/dist/cli/commands/workflow/list.d.mts +1 -3
  71. package/dist/cli/commands/workflow/resume.d.mts +1 -3
  72. package/dist/cli/commands/workflow/start.d.mts +0 -2
  73. package/dist/cli/commands/workflow/status.d.mts +1 -3
  74. package/dist/cli/commands/workflow/transform.d.mts +1 -3
  75. package/dist/cli/commands/workflow/wait.d.mts +1 -3
  76. package/dist/cli/commands/workflow/waiter.d.mts +1 -3
  77. package/dist/cli/commands/workspace/app/health.d.mts +0 -2
  78. package/dist/cli/commands/workspace/app/list.d.mts +0 -2
  79. package/dist/cli/commands/workspace/app/transform.d.mts +1 -3
  80. package/dist/cli/commands/workspace/create.d.mts +0 -2
  81. package/dist/cli/commands/workspace/delete.d.mts +0 -2
  82. package/dist/cli/commands/workspace/expiry.d.mts +1 -3
  83. package/dist/cli/commands/workspace/get.d.mts +0 -2
  84. package/dist/cli/commands/workspace/list.d.mts +1 -3
  85. package/dist/cli/commands/workspace/restore.d.mts +0 -2
  86. package/dist/cli/commands/workspace/transform.d.mts +1 -3
  87. package/dist/cli/commands/workspace/user/invite.d.mts +0 -2
  88. package/dist/cli/commands/workspace/user/list.d.mts +0 -2
  89. package/dist/cli/commands/workspace/user/remove.d.mts +0 -2
  90. package/dist/cli/commands/workspace/user/transform.d.mts +1 -3
  91. package/dist/cli/commands/workspace/user/update.d.mts +0 -2
  92. package/dist/cli/lib.d.mts +1 -1
  93. package/dist/cli/lib.mjs +1 -1
  94. package/dist/cli/lib.mjs.map +1 -1
  95. package/dist/cli/main.d.mts +1 -3
  96. package/dist/cli/main.mjs +55 -51
  97. package/dist/cli/main.mjs.map +1 -1
  98. package/dist/cli/query/index.d.mts +0 -2
  99. package/dist/cli/services/application.d.mts +5 -4
  100. package/dist/cli/services/executor/service.d.mts +2 -2
  101. package/dist/cli/services/function-bundle.d.mts +7 -0
  102. package/dist/cli/services/http-adapter/bundler.d.mts +7 -1
  103. package/dist/cli/services/resolver/service.d.mts +2 -2
  104. package/dist/cli/services/workflow/bundler.d.mts +2 -3
  105. package/dist/cli/shared/args.d.mts +0 -2
  106. package/dist/cli/shared/beta.d.mts +1 -3
  107. package/dist/cli/shared/client.d.mts +4 -3
  108. package/dist/cli/shared/command.d.mts +2 -4
  109. package/dist/cli/shared/config-loader.d.mts +2 -4
  110. package/dist/cli/shared/config.d.mts +1 -3
  111. package/dist/cli/shared/context.d.mts +0 -2
  112. package/dist/cli/shared/error-diagnostics.d.mts +1 -3
  113. package/dist/cli/shared/error-json.d.mts +1 -3
  114. package/dist/cli/shared/function-execution.d.mts +1 -3
  115. package/dist/cli/shared/github-actions.d.mts +1 -3
  116. package/dist/cli/shared/logger.d.mts +7 -4
  117. package/dist/cli/shared/platform-bundle-plugin.d.mts +1 -0
  118. package/dist/cli/shared/prompt.d.mts +1 -3
  119. package/dist/cli/shared/readonly-guard.d.mts +0 -2
  120. package/dist/cli/shared/script-executor.d.mts +1 -3
  121. package/dist/cli/shared/seed-chunker.d.mts +1 -3
  122. package/dist/cli/shared/seed-context.d.mts +0 -2
  123. package/dist/cli/shared/sourcemap-sources.d.mts +1 -0
  124. package/dist/cli/shared/tailordb-namespaces.d.mts +1 -3
  125. package/dist/cli/shared/type-generator.d.mts +0 -2
  126. package/dist/cli/shared/workspace-name.d.mts +1 -3
  127. package/dist/completion/zsh-worker.zsh +2 -2
  128. package/dist/configure/config/index.d.mts +2 -4
  129. package/dist/configure/config/types.d.mts +27 -4
  130. package/dist/configure/index.d.mts +7 -9
  131. package/dist/configure/index.mjs +1 -1
  132. package/dist/configure/services/aigateway/index.d.mts +0 -2
  133. package/dist/configure/services/aigateway/types.d.mts +0 -2
  134. package/dist/configure/services/auth/index.d.mts +0 -2
  135. package/dist/configure/services/auth/types.d.mts +0 -2
  136. package/dist/configure/services/executor/executor.d.mts +0 -2
  137. package/dist/configure/services/executor/operation.d.mts +0 -2
  138. package/dist/configure/services/executor/trigger/event.d.mts +0 -2
  139. package/dist/configure/services/executor/trigger/index.d.mts +0 -2
  140. package/dist/configure/services/executor/trigger/schedule.d.mts +0 -2
  141. package/dist/configure/services/executor/trigger/webhook.d.mts +1 -3
  142. package/dist/configure/services/http-adapter/http-adapter.d.mts +0 -2
  143. package/dist/configure/services/idp/index.d.mts +0 -2
  144. package/dist/configure/services/idp/permission.d.mts +0 -2
  145. package/dist/configure/services/idp/types.d.mts +0 -2
  146. package/dist/configure/services/index.d.mts +5 -5
  147. package/dist/configure/services/resolver/index.d.mts +1 -1
  148. package/dist/configure/services/resolver/permission.d.mts +0 -2
  149. package/dist/configure/services/resolver/resolver.d.mts +1 -3
  150. package/dist/configure/services/resolver/types.d.mts +1 -3
  151. package/dist/configure/services/secrets/index.d.mts +0 -2
  152. package/dist/configure/services/secrets/types.d.mts +0 -2
  153. package/dist/configure/services/staticwebsite/index.d.mts +0 -2
  154. package/dist/configure/services/staticwebsite/types.d.mts +0 -2
  155. package/dist/configure/services/tailordb/permission.d.mts +0 -2
  156. package/dist/configure/services/tailordb/schema.d.mts +0 -2
  157. package/dist/configure/services/tailordb/types.d.mts +0 -2
  158. package/dist/configure/services/workflow/execution-policy.d.mts +0 -2
  159. package/dist/configure/services/workflow/execution-policy.types.d.mts +0 -2
  160. package/dist/configure/services/workflow/job.d.mts +0 -2
  161. package/dist/configure/services/workflow/wait-point.d.mts +0 -2
  162. package/dist/configure/services/workflow/workflow.d.mts +0 -2
  163. package/dist/configure/types/aigateway-name.d.mts +1 -3
  164. package/dist/configure/types/auth-namespace-name.d.mts +1 -3
  165. package/dist/configure/types/connection-name.d.mts +1 -3
  166. package/dist/configure/types/field.d.mts +1 -3
  167. package/dist/configure/types/field.types.d.mts +0 -2
  168. package/dist/configure/types/idp-name.d.mts +1 -3
  169. package/dist/configure/types/permission-operand.types.d.mts +0 -2
  170. package/dist/configure/types/secret-vault-name.d.mts +1 -3
  171. package/dist/configure/types/type.d.mts +0 -2
  172. package/dist/{crashreport-BCIy33Cz.mjs → crashreport-DGU6lwiX.mjs} +2 -2
  173. package/dist/{crashreport-BCIy33Cz.mjs.map → crashreport-DGU6lwiX.mjs.map} +1 -1
  174. package/dist/crashreport-WsYAWARW.mjs +1 -0
  175. package/dist/{logger-RgtbhJ83.mjs → errors-BXmGBX-7.mjs} +6 -3
  176. package/dist/errors-BXmGBX-7.mjs.map +1 -0
  177. package/dist/field-parse-BQhUAbpM.mjs +2 -0
  178. package/dist/{field-parse-C41e3UAF.mjs.map → field-parse-BQhUAbpM.mjs.map} +1 -1
  179. package/dist/guards-CiFVxoXR.mjs +2 -0
  180. package/dist/guards-CiFVxoXR.mjs.map +1 -0
  181. package/dist/kysely/index.d.mts +0 -2
  182. package/dist/manager-B813m43t.mjs +2 -0
  183. package/dist/manager-B813m43t.mjs.map +1 -0
  184. package/dist/parser/service/idp/types.d.mts +1 -3
  185. package/dist/parser/service/tailordb/type-source.d.mts +1 -3
  186. package/dist/parser/service/tailordb/types.d.mts +0 -2
  187. package/dist/plugin/builtin/enum-constants/index.d.mts +0 -2
  188. package/dist/plugin/builtin/file-utils/index.d.mts +0 -2
  189. package/dist/plugin/builtin/kysely-type/index.d.mts +0 -2
  190. package/dist/plugin/builtin/seed/index.d.mts +0 -2
  191. package/dist/plugin/builtin/seed/seed-type-processor.d.mts +1 -3
  192. package/dist/plugin/get-generated-table.d.mts +1 -3
  193. package/dist/plugin/index.mjs +1 -1
  194. package/dist/plugin/types.d.mts +0 -2
  195. package/dist/plugin/with-context.d.mts +1 -3
  196. package/dist/register-ts-hook-CtWJL3EO.mjs +1054 -0
  197. package/dist/register-ts-hook-CtWJL3EO.mjs.map +1 -0
  198. package/dist/runtime/aigateway.d.mts +1 -3
  199. package/dist/runtime/authconnection.d.mts +1 -3
  200. package/dist/runtime/context.d.mts +0 -2
  201. package/dist/runtime/date.d.mts +0 -2
  202. package/dist/runtime/field-parse.d.mts +0 -2
  203. package/dist/runtime/file.d.mts +0 -2
  204. package/dist/runtime/globals.d.mts +0 -2
  205. package/dist/runtime/iconv.d.mts +1 -3
  206. package/dist/runtime/idp.d.mts +1 -3
  207. package/dist/runtime/index.d.mts +1 -3
  208. package/dist/runtime/index.mjs +1 -1
  209. package/dist/runtime/logger.d.mts +1 -3
  210. package/dist/runtime/secretmanager.d.mts +1 -3
  211. package/dist/runtime/temporal.d.mts +0 -2
  212. package/dist/runtime/types.d.mts +0 -2
  213. package/dist/runtime/workflow.d.mts +0 -2
  214. package/dist/{schema-B6hJQWp6.mjs → schema-BU1aIQ63.mjs} +2 -2
  215. package/dist/{schema-B6hJQWp6.mjs.map → schema-BU1aIQ63.mjs.map} +1 -1
  216. package/dist/secret-file-BxZ-J_Nz.mjs +2 -0
  217. package/dist/secret-file-BxZ-J_Nz.mjs.map +1 -0
  218. package/dist/seed/idp-user-password.d.mts +0 -2
  219. package/dist/seed/index.d.mts +0 -2
  220. package/dist/service-CaGmqg0r.mjs +2 -0
  221. package/dist/{service-9rwi_I4d.mjs.map → service-CaGmqg0r.mjs.map} +1 -1
  222. package/dist/service-DEq_hdht.mjs +1 -0
  223. package/dist/{service-9SBPNpK8.mjs → service-eeXdVrDK.mjs} +4 -4
  224. package/dist/service-eeXdVrDK.mjs.map +1 -0
  225. package/dist/shared/src/color.d.mts +1 -3
  226. package/dist/tailor-proto/src/tailor/v1/aigateway_pb.d.mts +1 -3
  227. package/dist/tailor-proto/src/tailor/v1/aigateway_resource_pb.d.mts +1 -3
  228. package/dist/tailor-proto/src/tailor/v1/application_pb.d.mts +1 -3
  229. package/dist/tailor-proto/src/tailor/v1/application_resource_pb.d.mts +1 -3
  230. package/dist/tailor-proto/src/tailor/v1/auth_pb.d.mts +1 -3
  231. package/dist/tailor-proto/src/tailor/v1/auth_resource_pb.d.mts +1 -3
  232. package/dist/tailor-proto/src/tailor/v1/events_pb.d.mts +1 -3
  233. package/dist/tailor-proto/src/tailor/v1/events_resource_pb.d.mts +1 -3
  234. package/dist/tailor-proto/src/tailor/v1/executor_pb.d.mts +1 -3
  235. package/dist/tailor-proto/src/tailor/v1/executor_resource_pb.d.mts +1 -3
  236. package/dist/tailor-proto/src/tailor/v1/function_pb.d.mts +1 -3
  237. package/dist/tailor-proto/src/tailor/v1/function_registry_pb.d.mts +1 -3
  238. package/dist/tailor-proto/src/tailor/v1/function_resource_pb.d.mts +1 -3
  239. package/dist/tailor-proto/src/tailor/v1/http_adapter_resource_pb.d.mts +1 -3
  240. package/dist/tailor-proto/src/tailor/v1/idp_pb.d.mts +1 -3
  241. package/dist/tailor-proto/src/tailor/v1/idp_resource_pb.d.mts +1 -3
  242. package/dist/tailor-proto/src/tailor/v1/metadata_pb.d.mts +1 -3
  243. package/dist/tailor-proto/src/tailor/v1/metadata_resource_pb.d.mts +1 -3
  244. package/dist/tailor-proto/src/tailor/v1/meter_pb.d.mts +1 -3
  245. package/dist/tailor-proto/src/tailor/v1/pipeline_pb.d.mts +1 -3
  246. package/dist/tailor-proto/src/tailor/v1/pipeline_resource_pb.d.mts +1 -3
  247. package/dist/tailor-proto/src/tailor/v1/resource_pb.d.mts +1 -3
  248. package/dist/tailor-proto/src/tailor/v1/secret_manager_pb.d.mts +1 -3
  249. package/dist/tailor-proto/src/tailor/v1/secret_manager_resource_pb.d.mts +1 -3
  250. package/dist/tailor-proto/src/tailor/v1/security_pb.d.mts +1 -3
  251. package/dist/tailor-proto/src/tailor/v1/security_resource_pb.d.mts +1 -3
  252. package/dist/tailor-proto/src/tailor/v1/service_pb.d.mts +1 -3
  253. package/dist/tailor-proto/src/tailor/v1/stateflow_pb.d.mts +1 -3
  254. package/dist/tailor-proto/src/tailor/v1/stateflow_resource_pb.d.mts +1 -3
  255. package/dist/tailor-proto/src/tailor/v1/staticwebsite_pb.d.mts +1 -3
  256. package/dist/tailor-proto/src/tailor/v1/staticwebsite_resource_pb.d.mts +1 -3
  257. package/dist/tailor-proto/src/tailor/v1/tailordb_pb.d.mts +1 -3
  258. package/dist/tailor-proto/src/tailor/v1/tailordb_resource_pb.d.mts +1 -3
  259. package/dist/tailor-proto/src/tailor/v1/telemetryrouter_pb.d.mts +1 -3
  260. package/dist/tailor-proto/src/tailor/v1/telemetryrouter_resource_pb.d.mts +1 -3
  261. package/dist/tailor-proto/src/tailor/v1/workflow_pb.d.mts +1 -3
  262. package/dist/tailor-proto/src/tailor/v1/workflow_resource_pb.d.mts +1 -3
  263. package/dist/tailor-proto/src/tailor/v1/workspace_pb.d.mts +1 -3
  264. package/dist/tailor-proto/src/tailor/v1/workspace_resource_pb.d.mts +1 -3
  265. package/dist/types/aigateway.generated.d.mts +1 -3
  266. package/dist/types/app-config.generated.d.mts +1 -3
  267. package/dist/types/auth-connection.generated.d.mts +1 -3
  268. package/dist/types/auth.generated.d.mts +1 -3
  269. package/dist/types/executor.generated.d.mts +1 -3
  270. package/dist/types/field.generated.d.mts +1 -3
  271. package/dist/types/helpers.d.mts +1 -3
  272. package/dist/types/http-adapter.generated.d.mts +1 -3
  273. package/dist/types/idp.generated.d.mts +1 -3
  274. package/dist/types/resolver.generated.d.mts +1 -3
  275. package/dist/types/secrets.generated.d.mts +1 -3
  276. package/dist/types/staticwebsite.generated.d.mts +1 -3
  277. package/dist/types/tailordb.generated.d.mts +1 -3
  278. package/dist/types/workflow.generated.d.mts +1 -3
  279. package/dist/utils/test/index.d.mts +1 -3
  280. package/dist/utils/test/index.mjs +1 -1
  281. package/dist/vitest/date-representation.d.mts +1 -3
  282. package/dist/vitest/environment.d.mts +0 -2
  283. package/dist/vitest/index.d.mts +0 -2
  284. package/dist/vitest/migration-steps.d.mts +1 -3
  285. package/dist/vitest/mock-kysely.d.mts +0 -2
  286. package/dist/vitest/mocks/aigateway.d.mts +0 -2
  287. package/dist/vitest/mocks/authconnection.d.mts +0 -2
  288. package/dist/vitest/mocks/file.d.mts +0 -2
  289. package/dist/vitest/mocks/iconv.d.mts +0 -2
  290. package/dist/vitest/mocks/idp.d.mts +0 -2
  291. package/dist/vitest/mocks/logger.d.mts +0 -2
  292. package/dist/vitest/mocks/secretmanager.d.mts +0 -2
  293. package/dist/vitest/mocks/tailordb-pglite.d.mts +0 -2
  294. package/dist/vitest/mocks/tailordb.d.mts +0 -2
  295. package/dist/vitest/mocks/workflow.d.mts +0 -2
  296. package/dist/vitest/pglite-kysely.d.mts +0 -2
  297. package/dist/vitest/pglite-temporal.d.mts +1 -3
  298. package/dist/vitest/setup.d.mts +0 -2
  299. package/dist/vitest/workflow-local.d.mts +0 -2
  300. package/docs/cli/application.md +2 -1
  301. package/docs/cli/tailordb.md +1 -1
  302. package/docs/cli/user.md +5 -5
  303. package/docs/cli/workspace.md +1 -1
  304. package/docs/cli-reference.md +26 -25
  305. package/docs/configuration.md +13 -2
  306. package/docs/github-actions.md +33 -10
  307. package/docs/services/secret.md +6 -0
  308. package/docs/services/tailordb/index.md +19 -0
  309. package/docs/services/tailordb/migration.md +2 -2
  310. package/docs/testing.md +2 -2
  311. package/package.json +12 -12
  312. package/dist/application-B9_NHiUC.mjs +0 -207
  313. package/dist/application-B9_NHiUC.mjs.map +0 -1
  314. package/dist/crashreport-IN6H7GX3.mjs +0 -1
  315. package/dist/errors-BOF68LJ5.mjs +0 -5
  316. package/dist/errors-BOF68LJ5.mjs.map +0 -1
  317. package/dist/field-parse-C41e3UAF.mjs +0 -2
  318. package/dist/guards-yDXyKC9F.mjs +0 -2
  319. package/dist/guards-yDXyKC9F.mjs.map +0 -1
  320. package/dist/logger-RgtbhJ83.mjs.map +0 -1
  321. package/dist/manager-DTRhIupk.mjs +0 -2
  322. package/dist/manager-DTRhIupk.mjs.map +0 -1
  323. package/dist/register-ts-hook-Dp9reSRG.mjs +0 -1053
  324. package/dist/register-ts-hook-Dp9reSRG.mjs.map +0 -1
  325. package/dist/secret-file-C9wp_FCX.mjs +0 -2
  326. package/dist/secret-file-C9wp_FCX.mjs.map +0 -1
  327. package/dist/service-9SBPNpK8.mjs.map +0 -1
  328. package/dist/service-9rwi_I4d.mjs +0 -2
  329. package/dist/service-Ca1WwyIt.mjs +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"crashreport-BCIy33Cz.mjs","names":["logger","redactSecrets","readPackageJson","userAgentFromVersion","writeSecretFile","ensureSecretDir","path","fs","crypto","os","isCI","localEnabled","remoteEnabled","localDir","xdgConfig","JSON_FOOTER_MARKER","CRASH_LOG_EXTENSION","report","files","dir","f","file","filename","filePath","content","endpoint","response","ua","data","HOME_DIR","UUID_PATTERN","LONG_HEX_PATTERN","EMAIL_PATTERN","ABSOLUTE_PATH_PATTERN","WINDOWS_PATH_PATTERN","URL_QUERY_PATTERN","EMAIL_TEST_PATTERN","WINDOWS_DRIVE_TEST_PATTERN","SDK_PACKAGE_MARKER","separator","firstFrameIndex","stack","result","sdkIndex","match","normalized","message","redactNext","arg","argv","eqIndex","args","commandParts","options","isError","error","rawMessage","rawStack","errorName","currentUser","configPath","raw","parseYAML","email","user","config","sdkVersion","errorType","reason"],"sources":["../src/cli/crashreport/config.ts","../src/cli/crashreport/writer.ts","../src/cli/crashreport/sender.ts","../src/cli/crashreport/sanitize.ts","../src/cli/crashreport/report.ts","../src/cli/crashreport/index.ts"],"sourcesContent":["import * as path from \"pathe\";\nimport { isCI } from \"std-env\";\nimport { xdgConfig } from \"xdg-basedir\";\n\nexport interface CrashReportConfig {\n readonly localEnabled: boolean;\n readonly remoteEnabled: boolean;\n readonly localDir: string;\n}\n\n/**\n * Parse crash report configuration from environment variables.\n * Local crash log writing is enabled by default (opt-out via TAILOR_CRASH_REPORTS_LOCAL=off).\n * Remote sending is disabled by default (opt-in via TAILOR_CRASH_REPORTS_REMOTE=on).\n * Both are auto-disabled in CI environments.\n * @returns Crash report configuration\n */\nexport function parseCrashReportConfig(): CrashReportConfig {\n if (isCI) {\n return {\n localEnabled: false,\n remoteEnabled: false,\n localDir: \"\",\n };\n }\n\n const localEnabled = (process.env.TAILOR_CRASH_REPORTS_LOCAL ?? \"on\").toLowerCase() !== \"off\";\n const remoteEnabled = (process.env.TAILOR_CRASH_REPORTS_REMOTE ?? \"off\").toLowerCase() === \"on\";\n const localDir = xdgConfig ? path.join(xdgConfig, \"tailor-platform\", \"crash-reports\") : \"\";\n\n return {\n localEnabled: localEnabled && localDir !== \"\",\n remoteEnabled,\n localDir,\n };\n}\n","import * as fs from \"node:fs\";\nimport * as path from \"pathe\";\nimport { ensureSecretDir, writeSecretFile } from \"#/cli/shared/secret-file\";\nimport type { CrashReport } from \"./report\";\n\nconst MAX_CRASH_FILES = 10;\n\n/** Marker line that separates human-readable content from the JSON footer. */\nexport const JSON_FOOTER_MARKER = \"--- JSON ---\";\n\n/** File extension for crash log files. */\nexport const CRASH_LOG_EXTENSION = \".crash.log\";\n\n/**\n * Format a CrashReport as human-readable text for local crash log files.\n * @param report - Crash report to format\n * @returns Formatted text content\n */\nexport function formatCrashReport(report: CrashReport): string {\n const lines = [\n `Crash Report: ${report.id}`,\n `Timestamp: ${report.timestamp}`,\n `Error Type: ${report.errorType}`,\n \"\",\n \"--- Environment ---\",\n `SDK Version: ${report.sdkVersion}`,\n `Node Version: ${report.nodeVersion}`,\n `OS: ${report.osPlatform} ${report.osRelease}`,\n `Arch: ${report.arch}`,\n \"\",\n \"--- Command ---\",\n `Command: ${report.command}`,\n `Arguments: ${JSON.stringify(report.argv)}`,\n \"\",\n \"--- Error ---\",\n `Name: ${report.errorName}`,\n `Message: ${report.errorMessage}`,\n \"\",\n \"--- Stack Trace ---\",\n report.stackTrace || \"(no stack trace available)\",\n \"\",\n JSON_FOOTER_MARKER,\n JSON.stringify(report),\n \"\",\n ];\n return lines.join(\"\\n\");\n}\n\n/**\n * Generate a filename for a crash log file.\n * Format: {timestamp}-{shortId}.crash.log\n * @param report - Crash report to generate filename for\n * @returns Filename string\n */\nfunction generateFilename(report: CrashReport): string {\n const safeTimestamp = report.timestamp.replace(/[:.]/g, \"-\");\n const shortId = report.id.slice(0, 8);\n return `${safeTimestamp}-${shortId}${CRASH_LOG_EXTENSION}`;\n}\n\n/**\n * Remove old crash log files, keeping only the most recent ones.\n * @param dir - Crash log directory\n */\nfunction cleanupOldFiles(dir: string): void {\n try {\n const files = fs\n .readdirSync(dir)\n .filter((f) => f.endsWith(CRASH_LOG_EXTENSION))\n .toSorted()\n .toReversed();\n\n for (const file of files.slice(MAX_CRASH_FILES)) {\n fs.unlinkSync(path.join(dir, file));\n }\n } catch {\n // Best-effort cleanup, ignore errors\n }\n}\n\n/**\n * Write a crash report to a local file.\n * Creates the directory if it doesn't exist. Keeps only the last 10 crash files.\n * Never throws - returns the file path on success or undefined on failure.\n * @param report - Crash report to write\n * @param dir - Directory to write the crash log file to\n * @returns File path on success, undefined on failure\n */\nexport function writeCrashReport(report: CrashReport, dir: string): string | undefined {\n try {\n ensureSecretDir(dir);\n\n const filename = generateFilename(report);\n const filePath = path.join(dir, filename);\n const content = formatCrashReport(report);\n\n writeSecretFile(filePath, content);\n cleanupOldFiles(dir);\n\n return filePath;\n } catch {\n return undefined;\n }\n}\n","import type { CrashReport } from \"./report\";\n\nconst SEND_TIMEOUT_MS = 5000;\nconst PRODUCTION_ENDPOINT = \"https://sdk-error-tracking-926vh9t4cl.erp.dev/query\";\n\nconst SUBMIT_MUTATION = `\nmutation SubmitCrashReport(\n $id: String!\n $timestamp: String!\n $sdkVersion: String!\n $nodeVersion: String!\n $osPlatform: String!\n $osRelease: String!\n $arch: String!\n $command: String!\n $argv: [String]\n $errorName: String!\n $errorMessage: String!\n $stackTrace: String\n $errorType: String!\n $userId: String\n $userEmail: String\n) {\n submitCrashReport(\n id: $id\n timestamp: $timestamp\n sdkVersion: $sdkVersion\n nodeVersion: $nodeVersion\n osPlatform: $osPlatform\n osRelease: $osRelease\n arch: $arch\n command: $command\n argv: $argv\n errorName: $errorName\n errorMessage: $errorMessage\n stackTrace: $stackTrace\n errorType: $errorType\n userId: $userId\n userEmail: $userEmail\n ) {\n success\n }\n}`;\n\n/**\n * Send a crash report to the remote endpoint via GraphQL mutation.\n * Best-effort: never throws, returns boolean success.\n * @param report - Crash report to send\n * @param ua - User-Agent header value\n * @returns true if the request succeeded, false otherwise\n */\nexport async function sendCrashReport(report: CrashReport, ua: string): Promise<boolean> {\n try {\n const endpoint = process.env.TAILOR_CRASH_REPORT_ENDPOINT || PRODUCTION_ENDPOINT;\n const response = await fetch(endpoint, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"User-Agent\": ua,\n },\n body: JSON.stringify({\n query: SUBMIT_MUTATION,\n variables: report,\n }),\n signal: AbortSignal.timeout(SEND_TIMEOUT_MS),\n });\n\n if (!response.ok) return false;\n\n const data = (await response.json()) as {\n errors?: unknown[];\n data?: { submitCrashReport: { success: boolean } };\n };\n if (data.errors?.length) return false;\n return data.data?.submitCrashReport.success === true;\n } catch {\n return false;\n }\n}\n","import * as os from \"node:os\";\n\nconst HOME_DIR = os.homedir();\n\n// Patterns for sanitization (global variants for use with .replace())\nconst UUID_PATTERN = /\\b[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\\b/gi;\nconst LONG_HEX_PATTERN = /\\b[0-9a-fA-F]{32,}\\b/g;\nconst EMAIL_PATTERN = /\\b[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}\\b/g;\nconst ABSOLUTE_PATH_PATTERN = /(?:\\/(?:[\\w.@\\- ]+\\/)+[\\w.@\\- ]+)/g;\nconst WINDOWS_PATH_PATTERN = /(?:[A-Za-z]:\\\\(?:[\\w.@\\- ]+\\\\)+[\\w.@\\- ]+)/g;\nconst URL_QUERY_PATTERN = /[?&][^?\\s]*/g;\n\n// Non-global variants for single-match .test() calls (avoids lastIndex state issues)\nconst EMAIL_TEST_PATTERN = /\\b[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}\\b/;\nconst WINDOWS_DRIVE_TEST_PATTERN = /^[A-Za-z]:\\\\/;\n\n// SDK package path marker for relative paths\nconst SDK_PACKAGE_MARKER = \"packages/sdk/\";\n\nfunction lastSegment(filePath: string, separator: string): string {\n return filePath.split(separator).pop() ?? filePath;\n}\n\n/**\n * Sanitize a stack trace by replacing absolute paths with relative SDK paths.\n * External paths are replaced with `<external>/filename.ext`.\n * Home directories are replaced with `~/<redacted>/`.\n * @param stack - Raw stack trace string\n * @returns Sanitized stack trace\n */\nexport function sanitizeStackTrace(stack: string): string {\n // V8 stack traces start with \"ErrorType: message\\n at ...\".\n // The error message may span multiple lines before the first \" at \" frame.\n // Apply message sanitization to all message lines so secrets embedded in\n // multiline error messages are redacted consistently with errorMessage.\n const firstFrameIndex = stack.search(/\\n\\s+at /);\n let result: string;\n if (firstFrameIndex !== -1) {\n result = sanitizeMessage(stack.slice(0, firstFrameIndex)) + stack.slice(firstFrameIndex);\n } else {\n result = sanitizeMessage(stack);\n }\n\n result = result.replace(ABSOLUTE_PATH_PATTERN, (match) => {\n const sdkIndex = match.indexOf(SDK_PACKAGE_MARKER);\n if (sdkIndex !== -1) {\n return match.slice(sdkIndex);\n }\n\n if (match.startsWith(HOME_DIR)) {\n return `~/<redacted>/${lastSegment(match, \"/\")}`;\n }\n\n return `<external>/${lastSegment(match, \"/\")}`;\n });\n result = result.replace(WINDOWS_PATH_PATTERN, (match) => {\n const normalized = match.replace(/\\\\/g, \"/\");\n const sdkIndex = normalized.indexOf(SDK_PACKAGE_MARKER);\n if (sdkIndex !== -1) {\n return normalized.slice(sdkIndex);\n }\n return `<external>/${lastSegment(match, \"\\\\\")}`;\n });\n return result;\n}\n\n/**\n * Sanitize an error message by redacting sensitive information.\n * Redacts: UUIDs, long hex tokens, email addresses, absolute paths, URL query strings.\n * @param message - Raw error message\n * @returns Sanitized error message\n */\nexport function sanitizeMessage(message: string): string {\n let result = message;\n // Strip serialized request/response bodies that may contain secrets\n result = result.replace(/\\nRequest:\\s*[\\s\\S]*$/, \"\\nRequest: <redacted>\");\n result = result.replace(UUID_PATTERN, \"<uuid>\");\n result = result.replace(LONG_HEX_PATTERN, \"<redacted>\");\n result = result.replace(EMAIL_PATTERN, \"<email>\");\n result = result.replace(URL_QUERY_PATTERN, \"?<redacted>\");\n result = result.replace(ABSOLUTE_PATH_PATTERN, (match) => `<path>/${lastSegment(match, \"/\")}`);\n result = result.replace(WINDOWS_PATH_PATTERN, (match) => `<path>/${lastSegment(match, \"\\\\\")}`);\n\n return result;\n}\n\n/**\n * Sanitize process.argv by keeping command/subcommand names and redacting\n * values of sensitive flags.\n * @param argv - Raw process.argv array\n * @returns Sanitized argv array\n */\nexport function sanitizeArgv(argv: string[]): string[] {\n const result: string[] = [];\n let redactNext = false;\n\n for (const arg of argv) {\n if (redactNext) {\n // If the next token is itself a flag, treat it as a new flag rather\n // than consuming it as the previous flag's value. This avoids leaking\n // the *next* flag's value (e.g., `--verbose --workspace-id secret`\n // would otherwise expose `secret`).\n if (!arg.startsWith(\"-\")) {\n result.push(\"<redacted>\");\n redactNext = false;\n continue;\n }\n redactNext = false;\n }\n\n if (arg.startsWith(\"-\")) {\n // --flag=value: keep flag name, redact value\n const eqIndex = arg.indexOf(\"=\");\n if (eqIndex !== -1) {\n result.push(`${arg.slice(0, eqIndex)}=<redacted>`);\n continue;\n }\n\n // --flag / -f: keep flag name, redact next arg as its value\n result.push(arg);\n redactNext = true;\n continue;\n }\n\n // Redact absolute paths\n if (arg.startsWith(\"/\") && arg.includes(\"/\", 1)) {\n result.push(\"<path>\");\n continue;\n }\n\n // Redact Windows-style absolute paths\n if (WINDOWS_DRIVE_TEST_PATTERN.test(arg)) {\n result.push(\"<path>\");\n continue;\n }\n\n // Redact email addresses\n if (EMAIL_TEST_PATTERN.test(arg)) {\n result.push(\"<email>\");\n continue;\n }\n\n result.push(arg);\n }\n\n return result;\n}\n","import * as crypto from \"node:crypto\";\nimport * as fs from \"node:fs\";\nimport * as os from \"node:os\";\nimport { parseYAML } from \"confbox\";\nimport * as path from \"pathe\";\nimport { xdgConfig } from \"xdg-basedir\";\nimport { redactSecrets } from \"#/cli/shared/logger\";\nimport { sanitizeArgv, sanitizeMessage, sanitizeStackTrace } from \"./sanitize\";\n\nexport type ErrorType = \"uncaughtException\" | \"unhandledRejection\" | \"handledError\";\n\nexport interface CrashReport {\n id: string;\n timestamp: string;\n sdkVersion: string;\n nodeVersion: string;\n osPlatform: string;\n osRelease: string;\n arch: string;\n command: string;\n argv: string[];\n errorName: string;\n errorMessage: string;\n stackTrace: string;\n errorType: ErrorType;\n userId: string | null;\n userEmail: string | null;\n}\n\ninterface BuildCrashReportOptions {\n error: unknown;\n sdkVersion: string;\n errorType: ErrorType;\n}\n\n// Maximum subcommand depth to keep (e.g., \"tailordb migrate generate\" = 3 tokens).\n// Positional arguments beyond this are potentially sensitive user input.\n// Accepted trade-off: plain-text positional args that don't match known patterns\n// (UUIDs, hex tokens, emails, paths) pass through to `command` and `argv`.\n// Full redaction would require embedding the CLI command tree here, which is fragile.\nconst MAX_COMMAND_TOKENS = 3;\n\n/**\n * Parse the command name from process.argv.\n * Extracts up to MAX_COMMAND_TOKENS non-flag arguments after the script name.\n * @returns Parsed command string\n */\nfunction parseCommand(): string {\n const args = process.argv.slice(2);\n const commandParts: string[] = [];\n for (const arg of args) {\n if (arg.startsWith(\"-\") || commandParts.length >= MAX_COMMAND_TOKENS) break;\n commandParts.push(arg);\n }\n return commandParts.join(\" \") || \"<unknown>\";\n}\n\n/**\n * Build a CrashReport data structure from an error and context.\n * All sensitive data is sanitized before inclusion: `redactSecrets` masks every registered\n * secret first, then the pattern-based sanitizers below strip known-shape values (UUIDs,\n * long hex, emails, paths) from what's left. `redactSecrets` must run first — the path\n * sanitizer intentionally keeps a path's basename (e.g. `/home/user/.../key.json` becomes\n * `<path>/key.json`), so a registered secret shaped like a path would have that basename\n * survive if the pattern sanitizer ran on it first. This report is written to a local file\n * (and optionally sent remotely) outside the CLI's normal stderr path.\n * @param options - Error, SDK version, and crash type\n * @returns Sanitized crash report\n */\nexport function buildCrashReport(options: BuildCrashReportOptions): CrashReport {\n const { error, sdkVersion, errorType } = options;\n\n const isError = error instanceof Error;\n const rawMessage = isError ? error.message : String(error);\n const rawStack = isError && error.stack ? error.stack : \"\";\n const errorName = isError ? error.name : \"UnknownError\";\n\n const currentUser = readCurrentUser();\n\n return {\n id: crypto.randomUUID(),\n timestamp: new Date().toISOString(),\n sdkVersion,\n nodeVersion: process.version,\n osPlatform: process.platform,\n osRelease: os.release(),\n arch: process.arch,\n command: sanitizeMessage(redactSecrets(parseCommand())),\n argv: sanitizeArgv(process.argv.map(redactSecrets)),\n errorName: redactSecrets(errorName),\n errorMessage: sanitizeMessage(redactSecrets(rawMessage)),\n stackTrace: sanitizeStackTrace(redactSecrets(rawStack)),\n errorType,\n userId: currentUser?.id ? redactSecrets(currentUser.id) : null,\n userEmail: currentUser?.email ? redactSecrets(currentUser.email) : null,\n };\n}\n\ntype CurrentUser = {\n id: string;\n email: string | null;\n};\n\n/**\n * Read current_user from Tailor Platform config without side effects.\n * Unlike readPlatformConfig(), this never triggers migration or logs warnings.\n * @returns The current user ID and email, or null if unavailable\n */\nfunction readCurrentUser(): CurrentUser | null {\n try {\n if (!xdgConfig) return null;\n const configPath = path.join(xdgConfig, \"tailor-platform\", \"config.yaml\");\n if (!fs.existsSync(configPath)) return null;\n const raw = parseYAML(fs.readFileSync(configPath, \"utf-8\")) as {\n current_user?: string | null;\n users?: Record<string, { email?: unknown } | undefined>;\n };\n // parseYAML returns null for empty documents\n // oxlint-disable-next-line typescript/no-unnecessary-condition\n const currentUser = raw?.current_user ?? null;\n if (!currentUser) return null;\n const email = raw.users?.[currentUser]?.email;\n return {\n id: currentUser,\n email: typeof email === \"string\" ? email : legacyEmail(currentUser),\n };\n } catch {\n return null;\n }\n}\n\nfunction legacyEmail(user: string): string | null {\n return user.includes(\"@\") ? user : null;\n}\n","import { logger } from \"#/cli/shared/logger\";\nimport { readPackageJson } from \"#/cli/shared/package-json\";\nimport { userAgentFromVersion } from \"#/cli/shared/user-agent\";\nimport { parseCrashReportConfig } from \"./config\";\nimport { buildCrashReport, type ErrorType } from \"./report\";\nimport { sendCrashReport } from \"./sender\";\nimport { writeCrashReport } from \"./writer\";\n\n/**\n * Report an unexpected crash. Writes a local crash log file and optionally\n * sends the report to a remote endpoint. Displays a user-facing message\n * with the crash log path and a command to submit the report.\n *\n * Never throws - all errors are silently caught.\n * @param error - The error that caused the crash\n * @param errorType - How the error was caught\n */\nexport async function reportCrash(error: unknown, errorType: ErrorType): Promise<void> {\n try {\n const config = parseCrashReportConfig();\n if (!config.localEnabled && !config.remoteEnabled) return;\n\n const packageJson = await readPackageJson();\n const sdkVersion = packageJson.version ?? \"unknown\";\n\n const report = buildCrashReport({ error, sdkVersion, errorType });\n\n if (config.localEnabled) {\n const filePath = writeCrashReport(report, config.localDir);\n if (filePath) {\n logger.log(\n [\n \"\",\n \"An unexpected error occurred. A crash report has been saved to:\",\n ` ${filePath}`,\n \"\",\n \"To submit this report:\",\n ` tailor crashreport send --file \"${filePath}\"`,\n ].join(\"\\n\"),\n );\n }\n }\n\n if (config.remoteEnabled) {\n const ua = userAgentFromVersion(sdkVersion);\n await sendCrashReport(report, ua);\n }\n } catch {\n // Never throw from crash reporting\n }\n}\n\n/**\n * Register global uncaughtException and unhandledRejection handlers.\n * These catch errors outside the normal cleanup flow (e.g., during\n * argument parsing). Should be called once at CLI startup before runMain.\n */\nexport function initCrashReporting(): void {\n const config = parseCrashReportConfig();\n if (!config.localEnabled && !config.remoteEnabled) return;\n\n const handleFatal = (error: unknown, errorType: ErrorType) => {\n const message = error instanceof Error ? error.message : String(error);\n logger.error(message);\n void reportCrash(error, errorType).finally(() => {\n process.exit(1);\n });\n };\n\n process.on(\"uncaughtException\", (error) => handleFatal(error, \"uncaughtException\"));\n process.on(\"unhandledRejection\", (reason) => handleFatal(reason, \"unhandledRejection\"));\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"crashreport-DGU6lwiX.mjs","names":["logger","redactSecrets","readPackageJson","userAgentFromVersion","writeSecretFile","ensureSecretDir","path","fs","crypto","os","isCI","localEnabled","remoteEnabled","localDir","xdgConfig","JSON_FOOTER_MARKER","CRASH_LOG_EXTENSION","report","files","dir","f","file","filename","filePath","content","endpoint","response","ua","data","HOME_DIR","UUID_PATTERN","LONG_HEX_PATTERN","EMAIL_PATTERN","ABSOLUTE_PATH_PATTERN","WINDOWS_PATH_PATTERN","URL_QUERY_PATTERN","EMAIL_TEST_PATTERN","WINDOWS_DRIVE_TEST_PATTERN","SDK_PACKAGE_MARKER","separator","firstFrameIndex","stack","result","sdkIndex","match","normalized","message","redactNext","arg","argv","eqIndex","args","commandParts","options","isError","error","rawMessage","rawStack","errorName","currentUser","configPath","raw","parseYAML","email","user","config","sdkVersion","errorType","reason"],"sources":["../src/cli/crashreport/config.ts","../src/cli/crashreport/writer.ts","../src/cli/crashreport/sender.ts","../src/cli/crashreport/sanitize.ts","../src/cli/crashreport/report.ts","../src/cli/crashreport/index.ts"],"sourcesContent":["import * as path from \"pathe\";\nimport { isCI } from \"std-env\";\nimport { xdgConfig } from \"xdg-basedir\";\n\nexport interface CrashReportConfig {\n readonly localEnabled: boolean;\n readonly remoteEnabled: boolean;\n readonly localDir: string;\n}\n\n/**\n * Parse crash report configuration from environment variables.\n * Local crash log writing is enabled by default (opt-out via TAILOR_CRASH_REPORTS_LOCAL=off).\n * Remote sending is disabled by default (opt-in via TAILOR_CRASH_REPORTS_REMOTE=on).\n * Both are auto-disabled in CI environments.\n * @returns Crash report configuration\n */\nexport function parseCrashReportConfig(): CrashReportConfig {\n if (isCI) {\n return {\n localEnabled: false,\n remoteEnabled: false,\n localDir: \"\",\n };\n }\n\n const localEnabled = (process.env.TAILOR_CRASH_REPORTS_LOCAL ?? \"on\").toLowerCase() !== \"off\";\n const remoteEnabled = (process.env.TAILOR_CRASH_REPORTS_REMOTE ?? \"off\").toLowerCase() === \"on\";\n const localDir = xdgConfig ? path.join(xdgConfig, \"tailor-platform\", \"crash-reports\") : \"\";\n\n return {\n localEnabled: localEnabled && localDir !== \"\",\n remoteEnabled,\n localDir,\n };\n}\n","import * as fs from \"node:fs\";\nimport * as path from \"pathe\";\nimport { ensureSecretDir, writeSecretFile } from \"#/cli/shared/secret-file\";\nimport type { CrashReport } from \"./report\";\n\nconst MAX_CRASH_FILES = 10;\n\n/** Marker line that separates human-readable content from the JSON footer. */\nexport const JSON_FOOTER_MARKER = \"--- JSON ---\";\n\n/** File extension for crash log files. */\nexport const CRASH_LOG_EXTENSION = \".crash.log\";\n\n/**\n * Format a CrashReport as human-readable text for local crash log files.\n * @param report - Crash report to format\n * @returns Formatted text content\n */\nexport function formatCrashReport(report: CrashReport): string {\n const lines = [\n `Crash Report: ${report.id}`,\n `Timestamp: ${report.timestamp}`,\n `Error Type: ${report.errorType}`,\n \"\",\n \"--- Environment ---\",\n `SDK Version: ${report.sdkVersion}`,\n `Node Version: ${report.nodeVersion}`,\n `OS: ${report.osPlatform} ${report.osRelease}`,\n `Arch: ${report.arch}`,\n \"\",\n \"--- Command ---\",\n `Command: ${report.command}`,\n `Arguments: ${JSON.stringify(report.argv)}`,\n \"\",\n \"--- Error ---\",\n `Name: ${report.errorName}`,\n `Message: ${report.errorMessage}`,\n \"\",\n \"--- Stack Trace ---\",\n report.stackTrace || \"(no stack trace available)\",\n \"\",\n JSON_FOOTER_MARKER,\n JSON.stringify(report),\n \"\",\n ];\n return lines.join(\"\\n\");\n}\n\n/**\n * Generate a filename for a crash log file.\n * Format: {timestamp}-{shortId}.crash.log\n * @param report - Crash report to generate filename for\n * @returns Filename string\n */\nfunction generateFilename(report: CrashReport): string {\n const safeTimestamp = report.timestamp.replace(/[:.]/g, \"-\");\n const shortId = report.id.slice(0, 8);\n return `${safeTimestamp}-${shortId}${CRASH_LOG_EXTENSION}`;\n}\n\n/**\n * Remove old crash log files, keeping only the most recent ones.\n * @param dir - Crash log directory\n */\nfunction cleanupOldFiles(dir: string): void {\n try {\n const files = fs\n .readdirSync(dir)\n .filter((f) => f.endsWith(CRASH_LOG_EXTENSION))\n .toSorted()\n .toReversed();\n\n for (const file of files.slice(MAX_CRASH_FILES)) {\n fs.unlinkSync(path.join(dir, file));\n }\n } catch {\n // Best-effort cleanup, ignore errors\n }\n}\n\n/**\n * Write a crash report to a local file.\n * Creates the directory if it doesn't exist. Keeps only the last 10 crash files.\n * Never throws - returns the file path on success or undefined on failure.\n * @param report - Crash report to write\n * @param dir - Directory to write the crash log file to\n * @returns File path on success, undefined on failure\n */\nexport function writeCrashReport(report: CrashReport, dir: string): string | undefined {\n try {\n ensureSecretDir(dir);\n\n const filename = generateFilename(report);\n const filePath = path.join(dir, filename);\n const content = formatCrashReport(report);\n\n writeSecretFile(filePath, content);\n cleanupOldFiles(dir);\n\n return filePath;\n } catch {\n return undefined;\n }\n}\n","import type { CrashReport } from \"./report\";\n\nconst SEND_TIMEOUT_MS = 5000;\nconst PRODUCTION_ENDPOINT = \"https://sdk-error-tracking-926vh9t4cl.erp.dev/query\";\n\nconst SUBMIT_MUTATION = `\nmutation SubmitCrashReport(\n $id: String!\n $timestamp: String!\n $sdkVersion: String!\n $nodeVersion: String!\n $osPlatform: String!\n $osRelease: String!\n $arch: String!\n $command: String!\n $argv: [String]\n $errorName: String!\n $errorMessage: String!\n $stackTrace: String\n $errorType: String!\n $userId: String\n $userEmail: String\n) {\n submitCrashReport(\n id: $id\n timestamp: $timestamp\n sdkVersion: $sdkVersion\n nodeVersion: $nodeVersion\n osPlatform: $osPlatform\n osRelease: $osRelease\n arch: $arch\n command: $command\n argv: $argv\n errorName: $errorName\n errorMessage: $errorMessage\n stackTrace: $stackTrace\n errorType: $errorType\n userId: $userId\n userEmail: $userEmail\n ) {\n success\n }\n}`;\n\n/**\n * Send a crash report to the remote endpoint via GraphQL mutation.\n * Best-effort: never throws, returns boolean success.\n * @param report - Crash report to send\n * @param ua - User-Agent header value\n * @returns true if the request succeeded, false otherwise\n */\nexport async function sendCrashReport(report: CrashReport, ua: string): Promise<boolean> {\n try {\n const endpoint = process.env.TAILOR_CRASH_REPORT_ENDPOINT || PRODUCTION_ENDPOINT;\n const response = await fetch(endpoint, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"User-Agent\": ua,\n },\n body: JSON.stringify({\n query: SUBMIT_MUTATION,\n variables: report,\n }),\n signal: AbortSignal.timeout(SEND_TIMEOUT_MS),\n });\n\n if (!response.ok) return false;\n\n const data = (await response.json()) as {\n errors?: unknown[];\n data?: { submitCrashReport: { success: boolean } };\n };\n if (data.errors?.length) return false;\n return data.data?.submitCrashReport.success === true;\n } catch {\n return false;\n }\n}\n","import * as os from \"node:os\";\n\nconst HOME_DIR = os.homedir();\n\n// Patterns for sanitization (global variants for use with .replace())\nconst UUID_PATTERN = /\\b[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\\b/gi;\nconst LONG_HEX_PATTERN = /\\b[0-9a-fA-F]{32,}\\b/g;\nconst EMAIL_PATTERN = /\\b[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}\\b/g;\nconst ABSOLUTE_PATH_PATTERN = /(?:\\/(?:[\\w.@\\- ]+\\/)+[\\w.@\\- ]+)/g;\nconst WINDOWS_PATH_PATTERN = /(?:[A-Za-z]:\\\\(?:[\\w.@\\- ]+\\\\)+[\\w.@\\- ]+)/g;\nconst URL_QUERY_PATTERN = /[?&][^?\\s]*/g;\n\n// Non-global variants for single-match .test() calls (avoids lastIndex state issues)\nconst EMAIL_TEST_PATTERN = /\\b[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}\\b/;\nconst WINDOWS_DRIVE_TEST_PATTERN = /^[A-Za-z]:\\\\/;\n\n// SDK package path marker for relative paths\nconst SDK_PACKAGE_MARKER = \"packages/sdk/\";\n\nfunction lastSegment(filePath: string, separator: string): string {\n return filePath.split(separator).pop() ?? filePath;\n}\n\n/**\n * Sanitize a stack trace by replacing absolute paths with relative SDK paths.\n * External paths are replaced with `<external>/filename.ext`.\n * Home directories are replaced with `~/<redacted>/`.\n * @param stack - Raw stack trace string\n * @returns Sanitized stack trace\n */\nexport function sanitizeStackTrace(stack: string): string {\n // V8 stack traces start with \"ErrorType: message\\n at ...\".\n // The error message may span multiple lines before the first \" at \" frame.\n // Apply message sanitization to all message lines so secrets embedded in\n // multiline error messages are redacted consistently with errorMessage.\n const firstFrameIndex = stack.search(/\\n\\s+at /);\n let result: string;\n if (firstFrameIndex !== -1) {\n result = sanitizeMessage(stack.slice(0, firstFrameIndex)) + stack.slice(firstFrameIndex);\n } else {\n result = sanitizeMessage(stack);\n }\n\n result = result.replace(ABSOLUTE_PATH_PATTERN, (match) => {\n const sdkIndex = match.indexOf(SDK_PACKAGE_MARKER);\n if (sdkIndex !== -1) {\n return match.slice(sdkIndex);\n }\n\n if (match.startsWith(HOME_DIR)) {\n return `~/<redacted>/${lastSegment(match, \"/\")}`;\n }\n\n return `<external>/${lastSegment(match, \"/\")}`;\n });\n result = result.replace(WINDOWS_PATH_PATTERN, (match) => {\n const normalized = match.replace(/\\\\/g, \"/\");\n const sdkIndex = normalized.indexOf(SDK_PACKAGE_MARKER);\n if (sdkIndex !== -1) {\n return normalized.slice(sdkIndex);\n }\n return `<external>/${lastSegment(match, \"\\\\\")}`;\n });\n return result;\n}\n\n/**\n * Sanitize an error message by redacting sensitive information.\n * Redacts: UUIDs, long hex tokens, email addresses, absolute paths, URL query strings.\n * @param message - Raw error message\n * @returns Sanitized error message\n */\nexport function sanitizeMessage(message: string): string {\n let result = message;\n // Strip serialized request/response bodies that may contain secrets\n result = result.replace(/\\nRequest:\\s*[\\s\\S]*$/, \"\\nRequest: <redacted>\");\n result = result.replace(UUID_PATTERN, \"<uuid>\");\n result = result.replace(LONG_HEX_PATTERN, \"<redacted>\");\n result = result.replace(EMAIL_PATTERN, \"<email>\");\n result = result.replace(URL_QUERY_PATTERN, \"?<redacted>\");\n result = result.replace(ABSOLUTE_PATH_PATTERN, (match) => `<path>/${lastSegment(match, \"/\")}`);\n result = result.replace(WINDOWS_PATH_PATTERN, (match) => `<path>/${lastSegment(match, \"\\\\\")}`);\n\n return result;\n}\n\n/**\n * Sanitize process.argv by keeping command/subcommand names and redacting\n * values of sensitive flags.\n * @param argv - Raw process.argv array\n * @returns Sanitized argv array\n */\nexport function sanitizeArgv(argv: string[]): string[] {\n const result: string[] = [];\n let redactNext = false;\n\n for (const arg of argv) {\n if (redactNext) {\n // If the next token is itself a flag, treat it as a new flag rather\n // than consuming it as the previous flag's value. This avoids leaking\n // the *next* flag's value (e.g., `--verbose --workspace-id secret`\n // would otherwise expose `secret`).\n if (!arg.startsWith(\"-\")) {\n result.push(\"<redacted>\");\n redactNext = false;\n continue;\n }\n redactNext = false;\n }\n\n if (arg.startsWith(\"-\")) {\n // --flag=value: keep flag name, redact value\n const eqIndex = arg.indexOf(\"=\");\n if (eqIndex !== -1) {\n result.push(`${arg.slice(0, eqIndex)}=<redacted>`);\n continue;\n }\n\n // --flag / -f: keep flag name, redact next arg as its value\n result.push(arg);\n redactNext = true;\n continue;\n }\n\n // Redact absolute paths\n if (arg.startsWith(\"/\") && arg.includes(\"/\", 1)) {\n result.push(\"<path>\");\n continue;\n }\n\n // Redact Windows-style absolute paths\n if (WINDOWS_DRIVE_TEST_PATTERN.test(arg)) {\n result.push(\"<path>\");\n continue;\n }\n\n // Redact email addresses\n if (EMAIL_TEST_PATTERN.test(arg)) {\n result.push(\"<email>\");\n continue;\n }\n\n result.push(arg);\n }\n\n return result;\n}\n","import * as crypto from \"node:crypto\";\nimport * as fs from \"node:fs\";\nimport * as os from \"node:os\";\nimport { parseYAML } from \"confbox\";\nimport * as path from \"pathe\";\nimport { xdgConfig } from \"xdg-basedir\";\nimport { redactSecrets } from \"#/cli/shared/logger\";\nimport { sanitizeArgv, sanitizeMessage, sanitizeStackTrace } from \"./sanitize\";\n\nexport type ErrorType = \"uncaughtException\" | \"unhandledRejection\" | \"handledError\";\n\nexport interface CrashReport {\n id: string;\n timestamp: string;\n sdkVersion: string;\n nodeVersion: string;\n osPlatform: string;\n osRelease: string;\n arch: string;\n command: string;\n argv: string[];\n errorName: string;\n errorMessage: string;\n stackTrace: string;\n errorType: ErrorType;\n userId: string | null;\n userEmail: string | null;\n}\n\ninterface BuildCrashReportOptions {\n error: unknown;\n sdkVersion: string;\n errorType: ErrorType;\n}\n\n// Maximum subcommand depth to keep (e.g., \"tailordb migrate generate\" = 3 tokens).\n// Positional arguments beyond this are potentially sensitive user input.\n// Accepted trade-off: plain-text positional args that don't match known patterns\n// (UUIDs, hex tokens, emails, paths) pass through to `command` and `argv`.\n// Full redaction would require embedding the CLI command tree here, which is fragile.\nconst MAX_COMMAND_TOKENS = 3;\n\n/**\n * Parse the command name from process.argv.\n * Extracts up to MAX_COMMAND_TOKENS non-flag arguments after the script name.\n * @returns Parsed command string\n */\nfunction parseCommand(): string {\n const args = process.argv.slice(2);\n const commandParts: string[] = [];\n for (const arg of args) {\n if (arg.startsWith(\"-\") || commandParts.length >= MAX_COMMAND_TOKENS) break;\n commandParts.push(arg);\n }\n return commandParts.join(\" \") || \"<unknown>\";\n}\n\n/**\n * Build a CrashReport data structure from an error and context.\n * All sensitive data is sanitized before inclusion: `redactSecrets` masks every registered\n * secret first, then the pattern-based sanitizers below strip known-shape values (UUIDs,\n * long hex, emails, paths) from what's left. `redactSecrets` must run first — the path\n * sanitizer intentionally keeps a path's basename (e.g. `/home/user/.../key.json` becomes\n * `<path>/key.json`), so a registered secret shaped like a path would have that basename\n * survive if the pattern sanitizer ran on it first. This report is written to a local file\n * (and optionally sent remotely) outside the CLI's normal stderr path.\n * @param options - Error, SDK version, and crash type\n * @returns Sanitized crash report\n */\nexport function buildCrashReport(options: BuildCrashReportOptions): CrashReport {\n const { error, sdkVersion, errorType } = options;\n\n const isError = error instanceof Error;\n const rawMessage = isError ? error.message : String(error);\n const rawStack = isError && error.stack ? error.stack : \"\";\n const errorName = isError ? error.name : \"UnknownError\";\n\n const currentUser = readCurrentUser();\n\n return {\n id: crypto.randomUUID(),\n timestamp: new Date().toISOString(),\n sdkVersion,\n nodeVersion: process.version,\n osPlatform: process.platform,\n osRelease: os.release(),\n arch: process.arch,\n command: sanitizeMessage(redactSecrets(parseCommand())),\n argv: sanitizeArgv(process.argv.map(redactSecrets)),\n errorName: redactSecrets(errorName),\n errorMessage: sanitizeMessage(redactSecrets(rawMessage)),\n stackTrace: sanitizeStackTrace(redactSecrets(rawStack)),\n errorType,\n userId: currentUser?.id ? redactSecrets(currentUser.id) : null,\n userEmail: currentUser?.email ? redactSecrets(currentUser.email) : null,\n };\n}\n\ntype CurrentUser = {\n id: string;\n email: string | null;\n};\n\n/**\n * Read current_user from Tailor Platform config without side effects.\n * Unlike readPlatformConfig(), this never triggers migration or logs warnings.\n * @returns The current user ID and email, or null if unavailable\n */\nfunction readCurrentUser(): CurrentUser | null {\n try {\n if (!xdgConfig) return null;\n const configPath = path.join(xdgConfig, \"tailor-platform\", \"config.yaml\");\n if (!fs.existsSync(configPath)) return null;\n const raw = parseYAML(fs.readFileSync(configPath, \"utf-8\")) as {\n current_user?: string | null;\n users?: Record<string, { email?: unknown } | undefined>;\n };\n // parseYAML returns null for empty documents\n // oxlint-disable-next-line typescript/no-unnecessary-condition\n const currentUser = raw?.current_user ?? null;\n if (!currentUser) return null;\n const email = raw.users?.[currentUser]?.email;\n return {\n id: currentUser,\n email: typeof email === \"string\" ? email : legacyEmail(currentUser),\n };\n } catch {\n return null;\n }\n}\n\nfunction legacyEmail(user: string): string | null {\n return user.includes(\"@\") ? user : null;\n}\n","import { logger } from \"#/cli/shared/logger\";\nimport { readPackageJson } from \"#/cli/shared/package-json\";\nimport { userAgentFromVersion } from \"#/cli/shared/user-agent\";\nimport { parseCrashReportConfig } from \"./config\";\nimport { buildCrashReport, type ErrorType } from \"./report\";\nimport { sendCrashReport } from \"./sender\";\nimport { writeCrashReport } from \"./writer\";\n\n/**\n * Report an unexpected crash. Writes a local crash log file and optionally\n * sends the report to a remote endpoint. Displays a user-facing message\n * with the crash log path and a command to submit the report.\n *\n * Never throws - all errors are silently caught.\n * @param error - The error that caused the crash\n * @param errorType - How the error was caught\n */\nexport async function reportCrash(error: unknown, errorType: ErrorType): Promise<void> {\n try {\n const config = parseCrashReportConfig();\n if (!config.localEnabled && !config.remoteEnabled) return;\n\n const packageJson = await readPackageJson();\n const sdkVersion = packageJson.version ?? \"unknown\";\n\n const report = buildCrashReport({ error, sdkVersion, errorType });\n\n if (config.localEnabled) {\n const filePath = writeCrashReport(report, config.localDir);\n if (filePath) {\n logger.log(\n [\n \"\",\n \"An unexpected error occurred. A crash report has been saved to:\",\n ` ${filePath}`,\n \"\",\n \"To submit this report:\",\n ` tailor crashreport send --file \"${filePath}\"`,\n ].join(\"\\n\"),\n );\n }\n }\n\n if (config.remoteEnabled) {\n const ua = userAgentFromVersion(sdkVersion);\n await sendCrashReport(report, ua);\n }\n } catch {\n // Never throw from crash reporting\n }\n}\n\n/**\n * Register global uncaughtException and unhandledRejection handlers.\n * These catch errors outside the normal cleanup flow (e.g., during\n * argument parsing). Should be called once at CLI startup before runMain.\n */\nexport function initCrashReporting(): void {\n const config = parseCrashReportConfig();\n if (!config.localEnabled && !config.remoteEnabled) return;\n\n const handleFatal = (error: unknown, errorType: ErrorType) => {\n const message = error instanceof Error ? error.message : String(error);\n logger.error(message);\n void reportCrash(error, errorType).finally(() => {\n process.exit(1);\n });\n };\n\n process.on(\"uncaughtException\", (error) => handleFatal(error, \"uncaughtException\"));\n process.on(\"unhandledRejection\", (reason) => handleFatal(reason, \"unhandledRejection\"));\n}\n"],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export{n as reportCrash}from"./crashreport-DGU6lwiX.mjs";
@@ -2,8 +2,11 @@ import{formatWithOptions as e,stripVTControlCharacters as t,styleText as n}from"
2
2
  `?!1:t<=31||t===127}function normalizeControlCharacters(e){let t=e.match(s)??[];return e.split(s).map(e=>{let t=[];for(let n of e)n===` `?t.push(` `.repeat(8)):isStrippableControlCharacter(n)||t.push(n);return t.join(``)}).reduce((e,n,r)=>e+n+(t[r]??``),``)}function sanitizeCell(e){return normalizeControlCharacters(String(e??``).replace(c,`
3
3
  `))}const u=/^(?:\p{Default_Ignorable_Code_Point}|\p{Control}|\p{Format}|\p{Nonspacing_Mark}|\p{Enclosing_Mark}|\p{Surrogate})+$/v,d=/^\p{RGI_Emoji}$/v;function displayWidth(e){let t=0;for(let{segment:n}of l.segment(e.replace(s,``))){if(u.test(n))continue;if(d.test(n)){t+=2;continue}let e=n.codePointAt(0);t+=e===void 0?0:a(e)}return t}function toCellLines(e){return e.split(`
4
4
  `).map(e=>({text:e,width:displayWidth(e)}))}function padCell(e,t){return e.text+` `.repeat(Math.max(0,t-e.width))}function renderBorder(e,t,n,r){return e+r.map(e=>`─`.repeat(e+2)).join(t)+n}function validateConsistentColumnCount(e){let t=e[0]?.length;t!==void 0&&e.forEach((e,n)=>{if(e.length!==t)throw Error(`renderTable: all rows must have the same number of columns (expected ${t}, row ${n} has ${e.length}).`)})}function renderTable(e,t={}){let n=e.map(e=>e.map(sanitizeCell));validateConsistentColumnCount(n);let r=n.length,i=n[0]?.length??0;if(r===0||i===0)return``;let a=n.map(e=>Array.from({length:i},(t,n)=>toCellLines(e[n]??``))),o=Array.from({length:i},(e,t)=>maxOf(a.map(e=>maxOf((e[t]??[]).map(e=>e.width))))),shouldDrawLine=e=>t.singleLine?e===0||e===r:(t.drawHorizontalLine??(()=>!0))(e,r),s=[];return shouldDrawLine(0)&&s.push(renderBorder(`┌`,`┬`,`┐`,o)),a.forEach((e,t)=>{let n=maxOf(e.map(e=>e.length),1);for(let t=0;t<n;t++){let n=e.map((e,n)=>padCell(e[t]??{text:``,width:0},o[n]??0));s.push(`│ ${n.join(` │ `)} │`)}t<r-1&&shouldDrawLine(t+1)&&s.push(renderBorder(`├`,`┼`,`┤`,o))}),shouldDrawLine(r)&&s.push(renderBorder(`└`,`┴`,`┘`,o)),`${s.join(`
5
- `)}\n`}const f=/* @__PURE__ */ new Set([`true`,`t`,`yes`,`y`,`on`,`1`]),p=/* @__PURE__ */ new Set([`false`,`f`,`no`,`n`,`off`,`0`]);function parseBoolean(e){if(e===void 0)return;let t=e.trim().toLowerCase();if(t!==``){if(f.has(t))return!0;if(p.has(t))return!1}}const m=`TAILOR_JSON_OUTPUT`;function interactiveTerminal(){return!i&&process.stdin.isTTY===!0&&process.stdout.isTTY===!0}function jsonModeRemedy(e){let t=y;switch(e){case`agent`:return` JSON output is enabled because an AI coding agent${t?` (${t})`:``} was detected; pass --json=false or set ${m}=false to restore prompts.`;case`flag`:return t?` JSON output is enabled by --json; pass --json=false instead to restore prompts.`:` JSON output is enabled by --json; drop it to restore prompts.`;case`env`:return t?` JSON output is enabled by ${m}; set it to false to restore prompts.`:` JSON output is enabled by ${m}; unset it to restore prompts.`;case`both`:return t?` JSON output is enabled by --json and ${m}; pass --json=false instead of the flag to restore prompts.`:` JSON output is enabled by --json and ${m}; drop the flag and unset the variable to restore prompts.`}}var CIPromptError=class extends Error{constructor(e){let t=_&&v!==void 0&&interactiveTerminal()?jsonModeRemedy(v):``;super((e??`Interactive prompts are not available in this environment. Provide the required options explicitly.`)+t),this.name=`CIPromptError`}};const h={success:o.green,error:o.red,warning:o.yellow,info:o.cyan,create:o.green,update:o.yellow,delete:o.red,replace:o.magenta,unchanged:o.gray,bold:o.bold,dim:o.gray,highlight:o.cyanBright,successBright:o.greenBright,errorBright:o.redBright,resourceType:o.bold,resourceName:o.cyan,path:o.cyan,value:o.white,placeholder:e=>o.italic(o.gray(e))},g={success:h.success(`✓`),error:h.error(`✖`),warning:h.warning(`⚠`),info:h.info(`i`),create:h.create(`+`),update:h.update(`~`),delete:h.delete(`-`),replace:h.replace(`±`),bullet:h.dim(`•`),arrow:h.dim(`→`)};let _=!1,v,y,b=!1;const x=/* @__PURE__ */ new Set,S=`<redacted>`;function buildAutomaton(e){let t={children:/* @__PURE__ */ new Map,fail:void 0,outputs:[]};t.fail=t;for(let n of e){let e=t;for(let r=0;r<n.length;r++){let i=n[r],a=e.children.get(i);a||(a={children:/* @__PURE__ */ new Map,fail:t,outputs:[]},e.children.set(i,a)),e=a}e.outputs.push(n)}let n=[...t.children.values()];for(let e=0;e<n.length;e++){let r=n[e];for(let[e,i]of r.children){let a=r.fail;for(;a!==t&&!a.children.has(e);)a=a.fail;i.fail=a.children.get(e)??t,i.outputs=i.outputs.concat(i.fail.outputs),n.push(i)}}return t}let C=null;function getAutomaton(){return C??=buildAutomaton(x),C}function findSecretSpans(e){let t=[],n=getAutomaton(),r=n;for(let i=0;i<e.length;i++){let a=e[i];for(;r!==n&&!r.children.has(a);)r=r.fail;r=r.children.get(a)??n;for(let e of r.outputs)t.push([i+1-e.length,i+1])}return t}function redactSecrets(e){if(x.size===0)return e;let t=[];for(let n=0,r;(r=e.indexOf(S,n))!==-1;)t.push([r,r+10]),n=r+10;let n=findSecretSpans(e).filter(([e,n])=>!t.some(([t,r])=>e>=t&&n<=r));if(n.length===0)return e;n.sort(([e],[t])=>e-t);let r=[];for(let e of n){let t=r.at(-1);t&&e[0]<=t[1]?t[1]=Math.max(t[1],e[1]):r.push(e)}let i=``,a=0;for(let[t,n]of r)i+=e.slice(a,t)+S,a=n;return i+e.slice(a)}function renderWithRedaction(e,n){let r=n(redactSecrets(e)),i=t(r),a=redactSecrets(i);return a===i?r:a}function renderRedacted(e,t){return renderWithRedaction(t,t=>renderFor(e,t))}function plainRedacted(e){return renderWithRedaction(e,t)}const w={info:`ℹ`,success:`✔`,warn:`⚠`,error:`✖`,debug:`⚙`,trace:`→`,log:``},T={info:h.info,success:h.success,warn:h.warning,error:h.error,debug:h.dim,trace:h.dim,log:e=>e};function formatLogLine(e){let{mode:t,indent:n,type:r,message:i,timestamp:a}=e,o=n>0?` `.repeat(n):``,s=T[r]||(e=>e);if(t===`plain`)return`${o}${s(i)}\n`;let c=w[r]||``,l=s(`${c?`${c} `:``}${i}`);return`${o}${a??``}${l}\n`}function writeLog(t,n,r){let i=r?.mode??`default`,a=r?.indent??0,o={breakLength:process.stdout.columns||80},s=formatLogLine({mode:i,indent:a,type:t,message:e(o,n),timestamp:i===`stream`?`${(/* @__PURE__ */ new Date()).toLocaleTimeString()} `:``});process.stderr.write(renderRedacted(process.stderr,s))}function setJsonDefaultAgent(e){y=e}function jsonDefaultAgent(){return y}const E={get jsonMode(){return _},set jsonMode(e){_=e,e||(v=void 0)},setJsonMode(e,t){_=e,v=e?t:void 0},get verbose(){return b||parseBoolean(process.env.DEBUG)===!0||process.env.RUNNER_DEBUG===`1`},set verbose(e){b=e},info(e,t){writeLog(`info`,e,t)},success(e,t){writeLog(`success`,e,t)},warn(e,t){writeLog(`warn`,e,t)},error(e,t){writeLog(`error`,e,t)},log(e){writeLog(`log`,e,{mode:`plain`})},newline(){process.stderr.write(`
5
+ `)}\n`}const f=/* @__PURE__ */ new Set([`true`,`t`,`yes`,`y`,`on`,`1`]),p=/* @__PURE__ */ new Set([`false`,`f`,`no`,`n`,`off`,`0`]);function parseBoolean(e){if(e===void 0)return;let t=e.trim().toLowerCase();if(t!==``){if(f.has(t))return!0;if(p.has(t))return!1}}const m=`TAILOR_JSON_OUTPUT`;function interactiveTerminal(){return!i&&process.stdin.isTTY===!0&&process.stdout.isTTY===!0}function jsonModeRemedy(e){let t=y;switch(e){case`agent`:return` JSON output is enabled because an AI coding agent${t?` (${t})`:``} was detected; pass --json=false or set ${m}=false to restore prompts.`;case`flag`:return t?` JSON output is enabled by --json; pass --json=false instead to restore prompts.`:` JSON output is enabled by --json; drop it to restore prompts.`;case`env`:return t?` JSON output is enabled by ${m}; set it to false to restore prompts.`:` JSON output is enabled by ${m}; unset it to restore prompts.`;case`both`:return t?` JSON output is enabled by --json and ${m}; pass --json=false instead of the flag to restore prompts.`:` JSON output is enabled by --json and ${m}; drop the flag and unset the variable to restore prompts.`}}var CIPromptError=class extends Error{constructor(e){let t=_&&v!==void 0&&interactiveTerminal()?jsonModeRemedy(v):``;super((e??`Interactive prompts are not available in this environment. Provide the required options explicitly.`)+t),this.name=`CIPromptError`}};const h={success:o.green,error:o.red,warning:o.yellow,info:o.cyan,create:o.green,update:o.yellow,delete:o.red,replace:o.magenta,unchanged:o.gray,bold:o.bold,dim:o.gray,highlight:o.cyanBright,successBright:o.greenBright,errorBright:o.redBright,resourceType:o.bold,resourceName:o.cyan,path:o.cyan,value:o.white,placeholder:e=>o.italic(o.gray(e))},g={success:h.success(`✓`),error:h.error(`✖`),warning:h.warning(`⚠`),info:h.info(`i`),create:h.create(`+`),update:h.update(`~`),delete:h.delete(`-`),replace:h.replace(`±`),bullet:h.dim(`•`),arrow:h.dim(`→`)};let _=!1,v,y,b;const x=/* @__PURE__ */ new Set,S=`<redacted>`;function buildAutomaton(e){let t={children:/* @__PURE__ */ new Map,fail:void 0,outputs:[]};t.fail=t;for(let n of e){let e=t;for(let r=0;r<n.length;r++){let i=n[r],a=e.children.get(i);a||(a={children:/* @__PURE__ */ new Map,fail:t,outputs:[]},e.children.set(i,a)),e=a}e.outputs.push(n)}let n=[...t.children.values()];for(let e=0;e<n.length;e++){let r=n[e];for(let[e,i]of r.children){let a=r.fail;for(;a!==t&&!a.children.has(e);)a=a.fail;i.fail=a.children.get(e)??t,i.outputs=i.outputs.concat(i.fail.outputs),n.push(i)}}return t}let C=null;function getAutomaton(){return C??=buildAutomaton(x),C}function findSecretSpans(e){let t=[],n=getAutomaton(),r=n;for(let i=0;i<e.length;i++){let a=e[i];for(;r!==n&&!r.children.has(a);)r=r.fail;r=r.children.get(a)??n;for(let e of r.outputs)t.push([i+1-e.length,i+1])}return t}function redactSecrets(e){if(x.size===0)return e;let t=[];for(let n=0,r;(r=e.indexOf(S,n))!==-1;)t.push([r,r+10]),n=r+10;let n=findSecretSpans(e).filter(([e,n])=>!t.some(([t,r])=>e>=t&&n<=r));if(n.length===0)return e;n.sort(([e],[t])=>e-t);let r=[];for(let e of n){let t=r.at(-1);t&&e[0]<=t[1]?t[1]=Math.max(t[1],e[1]):r.push(e)}let i=``,a=0;for(let[t,n]of r)i+=e.slice(a,t)+S,a=n;return i+e.slice(a)}function renderWithRedaction(e,n){let r=n(redactSecrets(e)),i=t(r),a=redactSecrets(i);return a===i?r:a}function renderRedacted(e,t){return renderWithRedaction(t,t=>renderFor(e,t))}function plainRedacted(e){return renderWithRedaction(e,t)}const w={info:`ℹ`,success:`✔`,warn:`⚠`,error:`✖`,debug:`⚙`,trace:`→`,log:``},T={info:h.info,success:h.success,warn:h.warning,error:h.error,debug:h.dim,trace:h.dim,log:e=>e};function formatLogLine(e){let{mode:t,indent:n,type:r,message:i,timestamp:a}=e,o=n>0?` `.repeat(n):``,s=T[r]||(e=>e);if(t===`plain`)return`${o}${s(i)}\n`;let c=w[r]||``,l=s(`${c?`${c} `:``}${i}`);return`${o}${a??``}${l}\n`}function writeLog(t,n,r){let i=r?.mode??`default`,a=r?.indent??0,o={breakLength:process.stdout.columns||80},s=formatLogLine({mode:i,indent:a,type:t,message:e(o,n),timestamp:i===`stream`?`${(/* @__PURE__ */ new Date()).toLocaleTimeString()} `:``});process.stderr.write(renderRedacted(process.stderr,s))}function setJsonDefaultAgent(e){y=e}function jsonDefaultAgent(){return y}const E={get jsonMode(){return _},set jsonMode(e){_=e,e||(v=void 0)},setJsonMode(e,t){_=e,v=e?t:void 0},get verbose(){return b??(parseBoolean(process.env.DEBUG)===!0||process.env.RUNNER_DEBUG===`1`)},set verbose(e){b=e},info(e,t){writeLog(`info`,e,t)},success(e,t){writeLog(`success`,e,t)},warn(e,t){writeLog(`warn`,e,t)},error(e,t){writeLog(`error`,e,t)},log(e){writeLog(`log`,e,{mode:`plain`})},newline(){process.stderr.write(`
6
6
  `)},debug(e){E.verbose&&writeLog(`log`,h.dim(e),{mode:`plain`})},registerSecret(e){if(typeof e!=`string`||[...e].length<4)return;let t=x.size;x.add(e);let n=JSON.stringify(e).slice(1,-1);n!==e&&x.add(n);let r=new URLSearchParams([[`v`,e]]).toString().slice(2);r!==e&&x.add(r),x.size!==t&&(C=null)},out(e,t){if(typeof e==`string`){process.stdout.write(renderFor(process.stdout,e.endsWith(`
7
7
  `)?e:e+`
8
- `));return}if(this.jsonMode){console.log(JSON.stringify(e));return}let n=t?.display,formatValue=(e,n=!1)=>t?.showNull&&e===null?`NULL`:e==null?`N/A`:e instanceof Date?r(e,{addSuffix:!0}):typeof e==`object`?n?JSON.stringify(e,null,2):JSON.stringify(e):String(e),isExcluded=e=>n!==void 0&&e in n&&n[e]===null,transformValue=(e,t,r,i=!1)=>{if(n&&e in n){let i=n[e];if(i)return i(t,r)}return formatValue(t,i)};if(!Array.isArray(e)){let t=renderTable(Object.entries(e).filter(([e])=>!isExcluded(e)).map(([t,n])=>[t,transformValue(t,n,e,!0)]),{singleLine:!1});process.stdout.write(renderFor(process.stdout,t));return}if(e.length===0)return;let i=Array.from(new Set(e.flatMap(e=>Object.keys(e)))).filter(e=>!isExcluded(e));if(i.length===0)return;let a=renderTable([i,...e.map(e=>i.map(t=>transformValue(t,e[t],e)))],{drawHorizontalLine:(e,t)=>e===0||e===1||e===t});process.stdout.write(renderFor(process.stdout,a))}};export{E as a,renderRedacted as c,g as d,parseBoolean as f,jsonDefaultAgent as i,setJsonDefaultAgent as l,m as n,plainRedacted as o,renderTable as p,interactiveTerminal as r,redactSecrets as s,CIPromptError as t,h as u};
9
- //# sourceMappingURL=logger-RgtbhJ83.mjs.map
8
+ `));return}if(this.jsonMode){console.log(JSON.stringify(e));return}let n=t?.display,formatValue=(e,n=!1)=>t?.showNull&&e===null?`NULL`:e==null?`N/A`:e instanceof Date?r(e,{addSuffix:!0}):typeof e==`object`?n?JSON.stringify(e,null,2):JSON.stringify(e):String(e),isExcluded=e=>n!==void 0&&e in n&&n[e]===null,transformValue=(e,t,r,i=!1)=>{if(n&&e in n){let i=n[e];if(i)return i(t,r)}return formatValue(t,i)};if(!Array.isArray(e)){let t=renderTable(Object.entries(e).filter(([e])=>!isExcluded(e)).map(([t,n])=>[t,transformValue(t,n,e,!0)]),{singleLine:!1});process.stdout.write(renderFor(process.stdout,t));return}if(e.length===0)return;let i=Array.from(new Set(e.flatMap(e=>Object.keys(e)))).filter(e=>!isExcluded(e));if(i.length===0)return;let a=renderTable([i,...e.map(e=>i.map(t=>transformValue(t,e[t],e)))],{drawHorizontalLine:(e,t)=>e===0||e===1||e===t});process.stdout.write(renderFor(process.stdout,a))}},D=/^[A-Za-z0-9_./:=@+-]+$/,O=/^[A-Za-z0-9_./:=@+\\-]+$/,k=/[%$"`“”„\p{Cc}]|\\$|^~(?:[\\/]|$)/u,A=/"|\s.*\\$|^~(?:[\\/]|$)/;function quotePosixArg(e){return D.test(e)?e:`'${e.replaceAll(`'`,`'"'"'`)}'`}function isPowerShellBare(e){return O.test(e)&&!/^(@|[+-]?\.?\d)/.test(e)&&e!==`--`&&!/^-[^-].*[.:]/.test(e)}function quotePowerShellArg(e){return isPowerShellBare(e)?e:`'${e.replace(/['‘’‚‛]/g,`$&$&`)}'`}function quoteCmdArg(e){if(O.test(e)&&!e.endsWith(`\\`))return e;let t=`"`,n=0;for(let r of e)r===`\\`?n++:(t+=r===`"`?`${`\\`.repeat(n*2)}""`:`${`\\`.repeat(n)}${r===`%`?`%%cd:~,%`:r}`,n=0);return`${t}${`\\`.repeat(n*2)}"`}function formatWindowsCommandLines(e){if(e.every(e=>isPowerShellBare(e)||e!==``&&!k.test(e)))return{kind:`shared`,commandLine:e.map(e=>isPowerShellBare(e)?e:`"${e}"`).join(` `)};let t=e.map(quoteCmdArg).join(` `);return{kind:`perShell`,powershell:e.some(e=>e===``||A.test(e))?`cmd /d /s /c ${quotePowerShellArg(t)}`:e.map(quotePowerShellArg).join(` `),cmd:t}}function formatShellCommandLines(e){return process.platform===`win32`?formatWindowsCommandLines(e):{kind:`shared`,commandLine:e.map(quotePosixArg).join(` `)}}function formatCommandHint(e){let t=formatShellCommandLines([e.command,...e.args].map(e=>redactSecrets(e)));return t.kind===`shared`?`\`${t.commandLine}\``:`\`${t.powershell}\` in PowerShell or \`${t.cmd}\` in cmd.exe`}function redactAndIndent(e){return redactSecrets(e).split(`
9
+ `).join(`
10
+ `)}function formatError(e){let t=[h.error(`Error${e.code?` [${e.code}]`:``}: ${e.message}`)];return e.details&&t.push(`\n ${h.dim(`Details:`)} ${redactAndIndent(e.details)}`),e.suggestion&&t.push(`\n ${h.info(`Suggestion:`)} ${redactAndIndent(e.suggestion)}`),e.command&&t.push(`\n ${h.dim(`Help:`)} Run \`tailor ${e.command} --help\` for usage information.`),e.next&&t.push(`\n ${h.info(`Next:`)} Run ${formatCommandHint(e.next)}.`),t.join(``)}function CLIError(e){let t=Error(e.message,e.cause===void 0?void 0:{cause:e.cause});return t.name=`CLIError`,t.code=e.code,t.details=e.details,t.suggestion=e.suggestion,t.command=e.command,t.next=e.next,t.context=e.context,t.format=()=>formatError(t),t}function isCLIError(e){return e instanceof Error&&e.name===`CLIError`}function errorSummary(e){return isCLIError(e)?[e.message,e.details,e.suggestion].filter(Boolean).join(`
11
+ `):e instanceof Error?e.message:String(e)}function internalError(e,t){return Error(e,t)}function toError(e){return e instanceof Error?e:Error(String(e),{cause:e})}const j=/does not provide an export named '(?!default')([^']+)'/;function typeOnlyImportHint(e){if(!(e instanceof SyntaxError))return;let t=j.exec(e.message)?.[1];if(t)return`If '${t}' is a type, import it with \`import type\` (or the inline \`type\` modifier). The CLI runs TypeScript by stripping types from each file in isolation, so type-only exports do not exist at runtime. Set "verbatimModuleSyntax": true in tsconfig.json to catch this at typecheck.`}export{h as _,isCLIError as a,renderTable as b,CIPromptError as c,jsonDefaultAgent as d,E as f,setJsonDefaultAgent as g,renderRedacted as h,internalError as i,m as l,redactSecrets as m,errorSummary as n,toError as o,plainRedacted as p,formatCommandHint as r,typeOnlyImportHint as s,CLIError as t,interactiveTerminal as u,g as v,parseBoolean as y};
12
+ //# sourceMappingURL=errors-BXmGBX-7.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors-BXmGBX-7.mjs","names":["styleText","name","text","color","forced","stream","stripVTControlCharacters","ANSI_ESCAPE_PATTERN","CARRIAGE_RETURN_PATTERN","graphemeSegmenter","values","value","max","fallback","codePoint","char","sgrSequences","chars","segment","result","i","cell","ZERO_WIDTH_CLUSTER_PATTERN","RGI_EMOJI_PATTERN","width","eastAsianWidth","cellLine","left","columnWidths","join","right","columnCount","rows","row","index","data","rowCount","rowsCellLines","col","line","config","lineIndex","lines","rowHeight","cellLines","columnLines","cells","rowIndex","TRUTHY_VALUES","FALSY_VALUES","normalized","JSON_OUTPUT_ENV_VAR","isCI","agent","_jsonDefaultAgent","source","reason","_jsonMode","_jsonModeSource","message","styles","symbols","_verbose","_secrets","REDACTED_PLACEHOLDER","root","secret","secrets","node","ch","next","queue","head","parent","child","fail","_automaton","spans","protectedSpans","from","start","end","pStart","pEnd","a","b","merged","span","last","cursor","rendered","render","plain","redactedPlain","styled","TYPE_ICONS","TYPE_COLORS","opts","indentPrefix","indent","colorFn","type","mode","icon","coloredOutput","timestamp","inspectOpts","output","formatWithOptions","logger","sizeBefore","jsonEscaped","formEncoded","display","options","formatDistanceToNowStrict","pretty","key","transformer","item","headers","h","t","header","POSIX_BARE_ARG","CMD_BARE_ARG","WINDOWS_DOUBLE_QUOTE_UNSAFE","POWERSHELL_VERSION_SENSITIVE","quoted","backslashes","argv","cmd","commandLines","action","arg","parts","error","MISSING_NAMED_EXPORT_PATTERN"],"sources":["../../shared/src/color.ts","../src/cli/shared/ascii-table.ts","../src/cli/shared/parse-boolean.ts","../src/cli/shared/logger.ts","../src/cli/shared/shell-quote.ts","../src/cli/shared/errors.ts"],"sourcesContent":["import { stripVTControlCharacters, styleText } from \"node:util\";\n\n/** Applies a style to text */\nexport type StyleFn = (text: string) => string;\n\ntype StyleName = Exclude<Parameters<typeof styleText>[0], readonly unknown[] | unknown[]>;\n\nconst style =\n (name: StyleName): StyleFn =>\n (text) =>\n styleText(name, text, { validateStream: false });\n\n/**\n * Style functions by name, so call sites read `color.bold(text)`. Styling is\n * always applied; `renderFor` drops it again when the destination stream has no\n * color support. Add a name here when a package needs one that is not listed.\n */\nexport const color = {\n bold: style(\"bold\"),\n dim: style(\"dim\"),\n italic: style(\"italic\"),\n gray: style(\"gray\"),\n white: style(\"white\"),\n red: style(\"red\"),\n green: style(\"green\"),\n yellow: style(\"yellow\"),\n cyan: style(\"cyan\"),\n magenta: style(\"magenta\"),\n redBright: style(\"redBright\"),\n greenBright: style(\"greenBright\"),\n cyanBright: style(\"cyanBright\"),\n};\n\n// Node's rules for whether a destination gets colors, applied by hand. Asking\n// styleText instead would be shorter but only correct on Node: Bun ignores both\n// the stream option and NO_COLOR (reproduced on 1.3.14), so it reports every\n// destination as color-capable and escapes end up in redirected output.\n//\n// FORCE_COLOR decides on its own when set, which is how CI keeps colors through\n// a pipe. NO_COLOR counts as set at any non-empty value, \"0\" included.\nconst supportsColor = (stream: NodeJS.WriteStream): boolean => {\n const forced = process.env.FORCE_COLOR;\n if (forced !== undefined) return forced !== \"0\" && forced !== \"false\";\n if (process.env.NODE_DISABLE_COLORS !== undefined) return false;\n if ((process.env.NO_COLOR ?? \"\") !== \"\") return false;\n if (process.env.TERM === \"dumb\") return false;\n return stream.isTTY === true;\n};\n\n/**\n * Prepares styled text for the stream it is written to.\n * @param stream - Stream the text is written to\n * @param text - Styled text\n * @returns Text with styling removed when the stream has no color support\n */\nexport function renderFor(stream: NodeJS.WriteStream, text: string): string {\n return supportsColor(stream) ? text : stripVTControlCharacters(text);\n}\n","import { eastAsianWidth } from \"get-east-asian-width\";\n\n// eslint-disable-next-line no-control-regex\nconst ANSI_ESCAPE_PATTERN = /\\x1b\\[[0-9;]*m/g;\nconst CARRIAGE_RETURN_PATTERN = /\\r\\n?/g;\n\nconst graphemeSegmenter = new Intl.Segmenter(undefined, { granularity: \"grapheme\" });\n\nexport interface AsciiTableConfig {\n /** Suppress horizontal lines between rows, keeping only the outer border. */\n singleLine?: boolean;\n /** Decide whether to draw the horizontal line at `lineIndex` (range `[0, rowCount]` inclusive). */\n drawHorizontalLine?: (lineIndex: number, rowCount: number) => boolean;\n}\n\ninterface CellLine {\n text: string;\n width: number;\n}\n\nfunction maxOf(values: number[], fallback = 0): number {\n return values.reduce((max, value) => (value > max ? value : max), fallback);\n}\n\nconst TAB_WIDTH = 8;\n\nfunction isStrippableControlCharacter(char: string): boolean {\n const codePoint = char.codePointAt(0) ?? 0;\n if (char === \"\\n\") {\n return false;\n }\n return codePoint <= 0x1f || codePoint === 0x7f;\n}\n\n// Only SGR (color/style) escape sequences are meant to survive; a bare ESC\n// that isn't part of a recognized SGR sequence (e.g. a screen-clear CSI\n// sequence, or a BEL-terminated OSC sequence) is treated like any other\n// control character below and stripped, rather than passed through to the\n// terminal or left with its terminator removed.\nfunction normalizeControlCharacters(value: string): string {\n const sgrSequences = value.match(ANSI_ESCAPE_PATTERN) ?? [];\n return value\n .split(ANSI_ESCAPE_PATTERN)\n .map((segment) => {\n const chars: string[] = [];\n for (const char of segment) {\n if (char === \"\\t\") {\n chars.push(\" \".repeat(TAB_WIDTH));\n } else if (!isStrippableControlCharacter(char)) {\n chars.push(char);\n }\n }\n return chars.join(\"\");\n })\n .reduce((result, segment, i) => result + segment + (sgrSequences[i] ?? \"\"), \"\");\n}\n\nfunction sanitizeCell(cell: unknown): string {\n return normalizeControlCharacters(String(cell ?? \"\").replace(CARRIAGE_RETURN_PATTERN, \"\\n\"));\n}\n\n// Clusters made up entirely of non-printing code points (lone joiners,\n// variation selectors, combining marks, etc.) render with no visible glyph.\nconst ZERO_WIDTH_CLUSTER_PATTERN =\n /^(?:\\p{Default_Ignorable_Code_Point}|\\p{Control}|\\p{Format}|\\p{Nonspacing_Mark}|\\p{Enclosing_Mark}|\\p{Surrogate})+$/v;\n// RGI_Emoji covers flags, keycaps, and VS16-forced presentation sequences,\n// which render as 2 columns in terminals even though their first code point\n// alone would measure as narrow/neutral.\nconst RGI_EMOJI_PATTERN = /^\\p{RGI_Emoji}$/v;\n\nfunction displayWidth(value: string): number {\n let width = 0;\n for (const { segment } of graphemeSegmenter.segment(value.replace(ANSI_ESCAPE_PATTERN, \"\"))) {\n if (ZERO_WIDTH_CLUSTER_PATTERN.test(segment)) {\n continue;\n }\n if (RGI_EMOJI_PATTERN.test(segment)) {\n width += 2;\n continue;\n }\n const codePoint = segment.codePointAt(0);\n width += codePoint === undefined ? 0 : eastAsianWidth(codePoint);\n }\n return width;\n}\n\nfunction toCellLines(cell: string): CellLine[] {\n return cell.split(\"\\n\").map((text) => ({ text, width: displayWidth(text) }));\n}\n\nfunction padCell(cellLine: CellLine, width: number): string {\n return cellLine.text + \" \".repeat(Math.max(0, width - cellLine.width));\n}\n\nfunction renderBorder(left: string, join: string, right: string, columnWidths: number[]): string {\n return left + columnWidths.map((width) => \"─\".repeat(width + 2)).join(join) + right;\n}\n\nfunction validateConsistentColumnCount(rows: string[][]): void {\n const columnCount = rows[0]?.length;\n if (columnCount === undefined) {\n return;\n }\n rows.forEach((row, index) => {\n if (row.length !== columnCount) {\n throw new Error(\n `renderTable: all rows must have the same number of columns (expected ${columnCount}, row ${index} has ${row.length}).`,\n );\n }\n });\n}\n\n/**\n * Renders a 2D array of values as a table using single-line Unicode box-drawing borders.\n * Column widths account for East Asian wide characters (measured per grapheme cluster,\n * so combining marks and ZWJ emoji sequences aren't overcounted, non-printing clusters\n * such as a lone joiner or combining mark measure as 0, and flags, keycaps, and\n * VS16-forced emoji presentation are measured as 2 columns) and strip ANSI SGR (color/style)\n * escape codes before measuring. Use this instead of importing a table-rendering package\n * directly.\n * @param data - Table rows; every row must have the same number of columns. Each cell is\n * stringified (`null`/`undefined` become an empty string rather than the literal text\n * \"null\"/\"undefined\"), may contain embedded newlines, has `\\r`/`\\r\\n` normalized to `\\n`,\n * has tabs expanded to spaces, and has other control characters stripped.\n * @param config - Rendering options\n * @returns The rendered table terminated with a trailing newline, or `\"\"` when there are no\n * rows or no columns to display\n */\nexport function renderTable(data: unknown[][], config: AsciiTableConfig = {}): string {\n const rows = data.map((row) => row.map(sanitizeCell));\n validateConsistentColumnCount(rows);\n\n const rowCount = rows.length;\n const columnCount = rows[0]?.length ?? 0;\n if (rowCount === 0 || columnCount === 0) {\n return \"\";\n }\n\n const rowsCellLines = rows.map((row) =>\n Array.from({ length: columnCount }, (_, col) => toCellLines(row[col] ?? \"\")),\n );\n const columnWidths = Array.from({ length: columnCount }, (_, col) =>\n maxOf(rowsCellLines.map((row) => maxOf((row[col] ?? []).map((line) => line.width)))),\n );\n\n const shouldDrawLine = (lineIndex: number): boolean =>\n config.singleLine\n ? lineIndex === 0 || lineIndex === rowCount\n : (config.drawHorizontalLine ?? (() => true))(lineIndex, rowCount);\n\n const lines: string[] = [];\n if (shouldDrawLine(0)) {\n lines.push(renderBorder(\"┌\", \"┬\", \"┐\", columnWidths));\n }\n\n rowsCellLines.forEach((cellLines, rowIndex) => {\n const rowHeight = maxOf(\n cellLines.map((columnLines) => columnLines.length),\n 1,\n );\n for (let line = 0; line < rowHeight; line++) {\n const cells = cellLines.map((columnLines, col) =>\n padCell(columnLines[line] ?? { text: \"\", width: 0 }, columnWidths[col] ?? 0),\n );\n lines.push(`│ ${cells.join(\" │ \")} │`);\n }\n if (rowIndex < rowCount - 1 && shouldDrawLine(rowIndex + 1)) {\n lines.push(renderBorder(\"├\", \"┼\", \"┤\", columnWidths));\n }\n });\n\n if (shouldDrawLine(rowCount)) {\n lines.push(renderBorder(\"└\", \"┴\", \"┘\", columnWidths));\n }\n\n return `${lines.join(\"\\n\")}\\n`;\n}\n","const TRUTHY_VALUES = new Set([\"true\", \"t\", \"yes\", \"y\", \"on\", \"1\"]);\nconst FALSY_VALUES = new Set([\"false\", \"f\", \"no\", \"n\", \"off\", \"0\"]);\n\n/**\n * Parse a string value as a boolean.\n *\n * Recognized values (case-insensitive, trimmed) follow Python's\n * `distutils.util.strtobool` convention:\n * - truthy: `true, t, yes, y, on, 1`\n * - falsy: `false, f, no, n, off, 0`\n *\n * Undefined, empty strings, and unrecognized values return `undefined` so\n * that callers can fall back to their own defaults.\n * @param value - The input string (e.g. an environment variable or CLI flag value)\n * @returns `true`, `false`, or `undefined` when the value is unset or unrecognized\n */\nexport function parseBoolean(value: string | undefined): boolean | undefined {\n if (value === undefined) return undefined;\n const normalized = value.trim().toLowerCase();\n if (normalized === \"\") return undefined;\n if (TRUTHY_VALUES.has(normalized)) return true;\n if (FALSY_VALUES.has(normalized)) return false;\n return undefined;\n}\n","import { formatWithOptions, stripVTControlCharacters, type InspectOptions } from \"node:util\";\nimport { color, renderFor } from \"@tailor-platform/shared/color\";\nimport { formatDistanceToNowStrict } from \"date-fns\";\nimport { isCI } from \"std-env\";\nimport { renderTable } from \"./ascii-table\";\nimport { parseBoolean } from \"./parse-boolean\";\n\n/** Environment variable selecting JSON as the default output for every command. */\nexport const JSON_OUTPUT_ENV_VAR = \"TAILOR_JSON_OUTPUT\";\n\n/**\n * Whether the process is attached to an interactive terminal outside CI.\n * @returns True when both stdin and stdout are TTYs and CI is not detected\n */\nexport function interactiveTerminal(): boolean {\n return !isCI && process.stdin.isTTY === true && process.stdout.isTTY === true;\n}\n\n/**\n * What selected JSON output: an explicit `--json`, the environment, both, or\n * the AI coding agent running the CLI.\n */\nexport type JsonModeSource = \"flag\" | \"env\" | \"both\" | \"agent\";\n\n/**\n * Explain what selected JSON output and how to turn it off. Under an AI coding\n * agent, dropping `--json` or unsetting the variable falls back to JSON again,\n * so the remedy names the explicit `false` values instead.\n * @param source - What selected JSON output\n * @returns Sentence appended to the prompt refusal\n */\nfunction jsonModeRemedy(source: JsonModeSource): string {\n const agent = _jsonDefaultAgent;\n switch (source) {\n case \"agent\":\n return ` JSON output is enabled because an AI coding agent${agent ? ` (${agent})` : \"\"} was detected; pass --json=false or set ${JSON_OUTPUT_ENV_VAR}=false to restore prompts.`;\n case \"flag\":\n return agent\n ? \" JSON output is enabled by --json; pass --json=false instead to restore prompts.\"\n : \" JSON output is enabled by --json; drop it to restore prompts.\";\n case \"env\":\n return agent\n ? ` JSON output is enabled by ${JSON_OUTPUT_ENV_VAR}; set it to false to restore prompts.`\n : ` JSON output is enabled by ${JSON_OUTPUT_ENV_VAR}; unset it to restore prompts.`;\n case \"both\":\n return agent\n ? ` JSON output is enabled by --json and ${JSON_OUTPUT_ENV_VAR}; pass --json=false instead of the flag to restore prompts.`\n : ` JSON output is enabled by --json and ${JSON_OUTPUT_ENV_VAR}; drop the flag and unset the variable to restore prompts.`;\n }\n}\n\n/**\n * Error thrown when a prompt is attempted in a non-interactive environment.\n *\n * JSON mode suppresses prompts, so name whatever selected it: an explicit\n * `--json` stays enabled however the environment is set, while\n * `TAILOR_JSON_OUTPUT` or a detected AI coding agent leaves nothing in the\n * command line to explain the refusal.\n */\nexport class CIPromptError extends Error {\n constructor(message?: string) {\n const reason =\n _jsonMode && _jsonModeSource !== undefined && interactiveTerminal()\n ? jsonModeRemedy(_jsonModeSource)\n : \"\";\n super(\n (message ??\n \"Interactive prompts are not available in this environment. Provide the required options explicitly.\") +\n reason,\n );\n this.name = \"CIPromptError\";\n }\n}\n\n/**\n * Semantic style functions for inline text styling\n */\nexport const styles = {\n // Status colors\n success: color.green,\n error: color.red,\n warning: color.yellow,\n info: color.cyan,\n\n // Action colors (for change sets)\n create: color.green,\n update: color.yellow,\n delete: color.red,\n replace: color.magenta,\n unchanged: color.gray,\n\n // Emphasis\n bold: color.bold,\n dim: color.gray,\n highlight: color.cyanBright,\n successBright: color.greenBright,\n errorBright: color.redBright,\n\n // Resource types\n resourceType: color.bold,\n resourceName: color.cyan,\n\n // File paths\n path: color.cyan,\n\n // Values\n value: color.white,\n placeholder: (text: string) => color.italic(color.gray(text)),\n};\n\n/**\n * Standardized symbols for CLI output\n */\nexport const symbols = {\n success: styles.success(\"\\u2713\"),\n error: styles.error(\"\\u2716\"),\n warning: styles.warning(\"\\u26a0\"),\n info: styles.info(\"i\"),\n create: styles.create(\"+\"),\n update: styles.update(\"~\"),\n delete: styles.delete(\"-\"),\n replace: styles.replace(\"\\u00b1\"),\n bullet: styles.dim(\"\\u2022\"),\n arrow: styles.dim(\"\\u2192\"),\n};\n\n/**\n * Log output modes\n */\nexport type LogMode = \"default\" | \"stream\" | \"plain\";\n\nexport interface LogOptions {\n /** Output mode (default: \"default\") */\n mode?: LogMode;\n /** Number of spaces to indent the entire line (default: 0) */\n indent?: number;\n}\n\n/** Field transformer function. null excludes the field from table output. */\nexport type FieldTransformer = ((value: unknown, item: object) => string) | null;\n\nexport interface OutOptions {\n /** Table display field transform/exclude settings. Only applied in table mode (not JSON). */\n display?: Record<string, FieldTransformer>;\n\n /** Show null values in table output (default: false) */\n showNull?: boolean;\n}\n\n// In JSON mode, all logs go to stderr to keep stdout clean for JSON data\nlet _jsonMode = false;\nlet _jsonModeSource: JsonModeSource | undefined;\nlet _jsonDefaultAgent: string | undefined;\nlet _verbose: boolean | undefined;\n\n// Values registered via `logger.registerSecret()`, redacted from diagnostic log output\nconst _secrets = new Set<string>();\nconst REDACTED_PLACEHOLDER = \"<redacted>\";\n// Below this length, a registered value is too likely to match unrelated text.\nconst MIN_SECRET_LENGTH = 4;\n\n/**\n * Aho-Corasick trie node. Indexed by individual UTF-16 code units (not Unicode code\n * points), matching how `string.indexOf`/`.slice` already index this file's strings — a\n * surrogate-pair character occupies two nodes, same as it occupies two `string` indices.\n */\ninterface TrieNode {\n children: Map<string, TrieNode>;\n fail: TrieNode;\n /** Secrets ending at this node, including those reached via `fail` links (precomputed). */\n outputs: string[];\n}\n\n/**\n * Builds a multi-pattern matcher for every registered secret, so `findSecretSpans` below\n * can find all of their occurrences in one pass over the text (`O(text.length + matches)`)\n * instead of scanning the full text once per registered secret. Rebuilt only when\n * `registerSecret` adds a genuinely new value (see `_automaton` below), so its\n * `O(total secret length)` construction cost is amortized across every log line redacted\n * while the secret set doesn't change.\n * @param secrets - Currently registered secrets\n * @returns Root of the built trie\n */\nfunction buildAutomaton(secrets: ReadonlySet<string>): TrieNode {\n const root: TrieNode = {\n children: new Map(),\n fail: undefined as unknown as TrieNode,\n outputs: [],\n };\n root.fail = root;\n\n for (const secret of secrets) {\n let node = root;\n for (let i = 0; i < secret.length; i++) {\n const ch = secret[i] as string;\n let next = node.children.get(ch);\n if (!next) {\n next = { children: new Map(), fail: root, outputs: [] };\n node.children.set(ch, next);\n }\n node = next;\n }\n node.outputs.push(secret);\n }\n\n // A head index instead of Array#shift(): shift() re-indexes every remaining element on\n // each call, which would make this loop quadratic in the number of trie nodes rather than\n // the linear BFS this is meant to be.\n const queue: TrieNode[] = [...root.children.values()];\n for (let head = 0; head < queue.length; head++) {\n const parent = queue[head] as TrieNode;\n for (const [ch, child] of parent.children) {\n let fail = parent.fail;\n while (fail !== root && !fail.children.has(ch)) fail = fail.fail;\n child.fail = fail.children.get(ch) ?? root;\n child.outputs = child.outputs.concat(child.fail.outputs);\n queue.push(child);\n }\n }\n return root;\n}\n\n// Cached automaton for the current `_secrets` contents; `null` means rebuild on next use.\n// Invalidated only when `registerSecret` actually grows `_secrets` (Set#add on an existing\n// value is a no-op), so re-registering an already-known secret never triggers a rebuild.\nlet _automaton: TrieNode | null = null;\n\nfunction getAutomaton(): TrieNode {\n _automaton ??= buildAutomaton(_secrets);\n return _automaton;\n}\n\n/**\n * Finds every occurrence of every registered secret in `text`, including overlapping ones,\n * in a single pass over `text` via the Aho-Corasick automaton.\n * @param text - Text to search\n * @returns Match spans as `[start, end)` pairs, in the order found\n */\nfunction findSecretSpans(text: string): Array<[start: number, end: number]> {\n const spans: Array<[start: number, end: number]> = [];\n const root = getAutomaton();\n let node = root;\n for (let i = 0; i < text.length; i++) {\n const ch = text[i] as string;\n while (node !== root && !node.children.has(ch)) node = node.fail;\n node = node.children.get(ch) ?? root;\n for (const secret of node.outputs) {\n spans.push([i + 1 - secret.length, i + 1]);\n }\n }\n return spans;\n}\n\n/**\n * Redacts every registered secret from `text` in a single pass over the original text.\n *\n * Matches are found against the original text only - never against text a previous\n * replacement produced - and overlapping/adjacent matches (whether one secret contains\n * another, or two secrets merely cross, e.g. registering \"abcde\" and \"defghi\" against\n * \"abcdefghi\") are merged into one contiguous span before any substitution happens. This\n * avoids two failure modes an iterative \"replace one secret, then the next\" approach has:\n * a later secret re-matching inside a placeholder a previous replacement already inserted,\n * and a crossing (non-nested) overlap leaving a fragment of one secret unredacted.\n *\n * Idempotent: a match that falls inside an occurrence of `<redacted>` already present in\n * `text` is discarded rather than substituted again. Without this, calling this function\n * twice on the same text (which happens whenever something already redacted, such as a\n * `--json` error envelope, is later passed to a diagnostic log call) could corrupt the\n * placeholder itself if a registered secret happens to be one of its substrings (e.g. a\n * secret literally containing \"redact\").\n * @param text - Text to redact\n * @returns `text` with every registered secret occurrence replaced by `<redacted>`\n */\nexport function redactSecrets(text: string): string {\n if (_secrets.size === 0) return text;\n\n const protectedSpans: Array<[start: number, end: number]> = [];\n for (let from = 0, index: number; (index = text.indexOf(REDACTED_PLACEHOLDER, from)) !== -1;) {\n protectedSpans.push([index, index + REDACTED_PLACEHOLDER.length]);\n from = index + REDACTED_PLACEHOLDER.length;\n }\n\n // Only a match wholly inside a protected placeholder is discarded (it can only be the\n // placeholder's own text, e.g. a registered secret that is a substring of \"redacted\").\n // A match that merely overlaps one — extending outside it, e.g. a registered secret that\n // happens to be \"leak<redacted>\" — still has real secret content outside the placeholder\n // and must still be replaced.\n //\n // A registered secret wholly contained in the placeholder (up to and including a secret\n // equal to \"<redacted>\" itself) is indistinguishable from the placeholder in rendered\n // output either way: substituting REDACTED_PLACEHOLDER for text that already reads\n // REDACTED_PLACEHOLDER is a no-op. Discarding the match here (rather than \"fixing\" it to\n // substitute anyway) isn't a redaction gap — it just skips redundant work on text that's\n // already the safe, masked form.\n const spans = findSecretSpans(text).filter(\n ([start, end]) => !protectedSpans.some(([pStart, pEnd]) => start >= pStart && end <= pEnd),\n );\n if (spans.length === 0) return text;\n spans.sort(([a], [b]) => a - b);\n\n const merged: Array<[start: number, end: number]> = [];\n for (const span of spans) {\n const last = merged.at(-1);\n if (last && span[0] <= last[1]) {\n last[1] = Math.max(last[1], span[1]);\n } else {\n merged.push(span);\n }\n }\n\n let result = \"\";\n let cursor = 0;\n for (const [start, end] of merged) {\n result += text.slice(cursor, start) + REDACTED_PLACEHOLDER;\n cursor = end;\n }\n return result + text.slice(cursor);\n}\n\n/**\n * Renders styled text with registered secrets redacted.\n *\n * Redacts the styled text first, so a secret that itself contains a control sequence\n * matches its raw form, then checks the text again without colors, so inline colors\n * cannot split a secret out of a match. When they do, the text is returned without\n * colors, since redacting around the escapes would leave fragments of the secret visible.\n * @param text - Styled text\n * @param render - Removes styling from `text`, or keeps it\n * @returns Rendered text with registered secrets redacted\n */\nfunction renderWithRedaction(text: string, render: (text: string) => string): string {\n const rendered = render(redactSecrets(text));\n const plain = stripVTControlCharacters(rendered);\n const redactedPlain = redactSecrets(plain);\n return redactedPlain === plain ? rendered : redactedPlain;\n}\n\n/**\n * Prepares styled diagnostic text for the stream it is written to, with registered\n * secrets redacted.\n * @param stream - Stream the text is written to\n * @param text - Styled text\n * @returns Text with styling removed when the stream has no color support, and registered secrets redacted\n */\nexport function renderRedacted(stream: NodeJS.WriteStream, text: string): string {\n return renderWithRedaction(text, (styled) => renderFor(stream, styled));\n}\n\n/**\n * Removes styling from text, with registered secrets redacted.\n * @param text - Styled text\n * @returns Plain text with registered secrets redacted\n */\nexport function plainRedacted(text: string): string {\n return renderWithRedaction(text, stripVTControlCharacters);\n}\n\n/**\n * Reset the registered-secret redaction state. Used for testing.\n *\n * `_secrets` is process-lifetime, module-level state with no production unregister API\n * (a real process should never stop hiding a secret it once saw). Test files that call\n * `logger.registerSecret()` and run in a Vitest project with `isolate: false` share this\n * state across files, so a value registered in one file's test can still be redacted in an\n * unrelated later file's assertions unless cleared between tests.\n */\nexport function resetSecretRegistry(): void {\n _secrets.clear();\n _automaton = null;\n}\n\n// Type icons for log output\nconst TYPE_ICONS: Record<string, string> = {\n info: \"ℹ\",\n success: \"✔\",\n warn: \"⚠\",\n error: \"✖\",\n debug: \"⚙\",\n trace: \"→\",\n log: \"\",\n};\n\n// Color functions for icon and message text\nconst TYPE_COLORS: Record<string, (text: string) => string> = {\n info: styles.info,\n success: styles.success,\n warn: styles.warning,\n error: styles.error,\n debug: styles.dim,\n trace: styles.dim,\n log: (text) => text,\n};\n\ninterface FormatLogLineOptions {\n mode: string;\n indent: number;\n type: string;\n message: string;\n timestamp?: string;\n}\n\n/**\n * Formats a log line with the appropriate prefix and indentation\n * @param opts - Formatting options\n * @returns Formatted log line\n */\nexport function formatLogLine(opts: FormatLogLineOptions): string {\n const { mode, indent, type, message, timestamp } = opts;\n const indentPrefix = indent > 0 ? \" \".repeat(indent) : \"\";\n const colorFn = TYPE_COLORS[type] || ((text: string) => text);\n\n // Plain mode: color only, no icon, no timestamp\n if (mode === \"plain\") {\n return `${indentPrefix}${colorFn(message)}\\n`;\n }\n\n // Default/Stream mode: with icon and color\n const icon = TYPE_ICONS[type] || \"\";\n const prefix = icon ? `${icon} ` : \"\";\n const coloredOutput = colorFn(`${prefix}${message}`);\n const timestampPrefix = timestamp ?? \"\";\n\n return `${indentPrefix}${timestampPrefix}${coloredOutput}\\n`;\n}\n\n/**\n * Writes a formatted log line to stderr.\n * @param type - Log type (info, success, warn, error, log)\n * @param message - Log message\n * @param opts - Log options (mode and indent)\n */\nfunction writeLog(type: string, message: string, opts?: LogOptions): void {\n const mode = opts?.mode ?? \"default\";\n const indent = opts?.indent ?? 0;\n const inspectOpts: InspectOptions = {\n breakLength: process.stdout.columns || 80,\n };\n const formattedMessage = formatWithOptions(inspectOpts, message);\n const timestamp = mode === \"stream\" ? `${new Date().toLocaleTimeString()} ` : \"\";\n const output = formatLogLine({ mode, indent, type, message: formattedMessage, timestamp });\n process.stderr.write(renderRedacted(process.stderr, output));\n}\n\n/**\n * Record the AI coding agent running the Tailor CLI, which makes JSON the\n * default output. CLI plugins never record one, so they keep table output.\n * @param agent - Detected agent id (e.g. `\"claude_code\"`), or undefined when none runs the CLI\n */\nexport function setJsonDefaultAgent(agent: string | undefined): void {\n _jsonDefaultAgent = agent;\n}\n\n/**\n * The AI coding agent recorded by {@link setJsonDefaultAgent}.\n * @returns Detected agent id, or undefined when none was recorded\n */\nexport function jsonDefaultAgent(): string | undefined {\n return _jsonDefaultAgent;\n}\n\n/**\n * The CLI logger. Diagnostics go to stderr; `out()` writes primary output to\n * stdout as a table, or as JSON when `jsonMode` is on. `--json` and\n * `--verbose` feed the `jsonMode` / `verbose` state, which CLI plugins share\n * with the SDK code paths they call.\n */\nexport const logger = {\n get jsonMode(): boolean {\n return _jsonMode;\n },\n set jsonMode(value: boolean) {\n _jsonMode = value;\n if (!value) _jsonModeSource = undefined;\n },\n\n /**\n * Enable or disable JSON mode, recording what selected it so a suppressed\n * prompt can name the right remedy.\n * @param value - Whether JSON output is on\n * @param source - What turned it on; omit when turning it off\n */\n setJsonMode(value: boolean, source?: JsonModeSource): void {\n _jsonMode = value;\n _jsonModeSource = value ? source : undefined;\n },\n\n get verbose(): boolean {\n return (\n _verbose ?? (parseBoolean(process.env.DEBUG) === true || process.env.RUNNER_DEBUG === \"1\")\n );\n },\n /**\n * Turn verbose output on or off, overriding `DEBUG` and `RUNNER_DEBUG`.\n * @param value - Whether verbose output is on, or undefined to defer to `DEBUG` and `RUNNER_DEBUG`\n */\n set verbose(value: boolean | undefined) {\n _verbose = value;\n },\n\n info(message: string, opts?: LogOptions): void {\n writeLog(\"info\", message, opts);\n },\n\n success(message: string, opts?: LogOptions): void {\n writeLog(\"success\", message, opts);\n },\n\n warn(message: string, opts?: LogOptions): void {\n writeLog(\"warn\", message, opts);\n },\n\n error(message: string, opts?: LogOptions): void {\n writeLog(\"error\", message, opts);\n },\n\n log(message: string): void {\n writeLog(\"log\", message, { mode: \"plain\" });\n },\n\n newline(): void {\n process.stderr.write(\"\\n\");\n },\n\n debug(message: string): void {\n if (logger.verbose) {\n writeLog(\"log\", styles.dim(message), { mode: \"plain\" });\n }\n },\n\n /**\n * Registers a value to be redacted from diagnostic log output (`info`/`success`/`warn`/\n * `error`/`log`/`debug`). Any occurrence of `value` — or of its JSON-string-escaped form\n * (so a value embedded in `JSON.stringify`d output, e.g. `--json` mode error envelopes, is\n * also caught) or its `application/x-www-form-urlencoded` form (so a value that reached the\n * process via a URL query string, e.g. an OAuth authorization code decoded from a callback\n * URL via `URLSearchParams`, is still caught if that same URL — still encoded — is later\n * echoed into a diagnostic message) — is replaced with `<redacted>` before it reaches\n * stderr. Does not affect `out()`, since some commands intentionally print secret values as\n * their primary result.\n *\n * Values shorter than 4 characters are ignored, since they are too likely to match\n * unrelated text. A non-string value (e.g. `undefined` from an unvalidated external\n * payload cast to a typed shape) is ignored the same way, rather than throwing, since a\n * logging call must never be what crashes the process.\n * @param value - The secret value to redact from future log output\n */\n registerSecret(value: string): void {\n // Counts Unicode code points, not UTF-16 code units, so a value made of surrogate-pair\n // characters (e.g. emoji) isn't undercounted as longer than it actually is.\n if (typeof value !== \"string\" || [...value].length < MIN_SECRET_LENGTH) return;\n const sizeBefore = _secrets.size;\n _secrets.add(value);\n const jsonEscaped = JSON.stringify(value).slice(1, -1);\n if (jsonEscaped !== value) _secrets.add(jsonEscaped);\n // Uses URLSearchParams rather than encodeURIComponent: form-urlencoding (what\n // URLSearchParams produces, and what a URL query string actually contains) encodes a\n // space as \"+\", not \"%20\", and unlike encodeURIComponent it never throws on a lone\n // surrogate (invalid UTF-16) — it substitutes U+FFFD instead, matching how the URL\n // itself would already have encoded that same malformed input.\n const formEncoded = new URLSearchParams([[\"v\", value]]).toString().slice(2);\n if (formEncoded !== value) _secrets.add(formEncoded);\n // Set#add on an already-registered value is a no-op, so this only invalidates the\n // cached automaton (see findSecretSpans) when a genuinely new secret was added.\n if (_secrets.size !== sizeBefore) _automaton = null;\n },\n\n out(data: string | object | object[], options?: OutOptions): void {\n if (typeof data === \"string\") {\n process.stdout.write(renderFor(process.stdout, data.endsWith(\"\\n\") ? data : data + \"\\n\"));\n return;\n }\n\n if (this.jsonMode) {\n // eslint-disable-next-line no-restricted-syntax\n console.log(JSON.stringify(data));\n return;\n }\n\n const display = options?.display;\n\n // Helper to format a value for table display\n const formatValue = (value: unknown, pretty = false): string => {\n if (options?.showNull && value === null) return \"NULL\";\n if (value === null || value === undefined) return \"N/A\";\n if (value instanceof Date) {\n return formatDistanceToNowStrict(value, { addSuffix: true });\n }\n if (typeof value === \"object\") {\n return pretty ? JSON.stringify(value, null, 2) : JSON.stringify(value);\n }\n return String(value);\n };\n\n // Helper to check if field should be excluded\n const isExcluded = (key: string): boolean => {\n return display !== undefined && key in display && display[key] === null;\n };\n\n // Helper to apply transformer or default formatting\n const transformValue = (key: string, value: unknown, item: object, pretty = false): string => {\n if (display && key in display) {\n const transformer = display[key];\n if (transformer) {\n return transformer(value, item);\n }\n }\n return formatValue(value, pretty);\n };\n\n if (!Array.isArray(data)) {\n const entries = Object.entries(data).filter(([key]) => !isExcluded(key));\n const formattedEntries = entries.map(([key, value]) => [\n key,\n transformValue(key, value, data, true),\n ]);\n const t = renderTable(formattedEntries, { singleLine: false });\n process.stdout.write(renderFor(process.stdout, t));\n return;\n }\n\n if (data.length === 0) {\n return;\n }\n\n const allHeaders = Array.from(new Set(data.flatMap((item) => Object.keys(item))));\n const headers = allHeaders.filter((h) => !isExcluded(h));\n if (headers.length === 0) {\n return;\n }\n const rows = data.map((item) =>\n headers.map((header) =>\n transformValue(header, (item as Record<string, unknown>)[header], item),\n ),\n );\n\n const t = renderTable([headers, ...rows], {\n drawHorizontalLine: (lineIndex, rowCount) => {\n return lineIndex === 0 || lineIndex === 1 || lineIndex === rowCount;\n },\n });\n process.stdout.write(renderFor(process.stdout, t));\n },\n};\n","/**\n * Command lines for a suggested command: one line when every supported shell reads it the same\n * way, otherwise one line per Windows shell.\n */\nexport type ShellCommandLines =\n | { kind: \"shared\"; commandLine: string }\n | { kind: \"perShell\"; powershell: string; cmd: string };\n\nconst POSIX_BARE_ARG = /^[A-Za-z0-9_./:=@+-]+$/;\nconst CMD_BARE_ARG = /^[A-Za-z0-9_./:=@+\\\\-]+$/;\n// PowerShell expands `$` and backtick escapes inside double quotes and reads `“ ” „` as `\"`,\n// cmd.exe expands `%` even inside quotes, a `\"` or a trailing backslash changes where the\n// quoted argument ends, and a leading `~` is version-sensitive (below).\nconst WINDOWS_DOUBLE_QUOTE_UNSAFE = /[%$\"`“”„\\p{Cc}]|\\\\$|^~(?:[\\\\/]|$)/u;\n// PowerShell versions pass these to programs differently: Windows PowerShell 5.1 and 7.3+\n// disagree on quotes and trailing backslashes, and 7.6+ expands a leading `~` inside the `.ps1`\n// shim however it was quoted.\nconst POWERSHELL_VERSION_SENSITIVE = /\"|\\s.*\\\\$|^~(?:[\\\\/]|$)/;\n\nfunction quotePosixArg(value: string): string {\n if (POSIX_BARE_ARG.test(value)) return value;\n return `'${value.replaceAll(\"'\", `'\"'\"'`)}'`;\n}\n\nfunction isPowerShellBare(value: string): boolean {\n // A leading `@` splats, a lone `--` ends parameters, a leading digit reads as a number, and a\n // single-dash token with `.` or `:` reads as parameter syntax.\n return (\n CMD_BARE_ARG.test(value) &&\n !/^(@|[+-]?\\.?\\d)/.test(value) &&\n value !== \"--\" &&\n !/^-[^-].*[.:]/.test(value)\n );\n}\n\nfunction quotePowerShellArg(value: string): string {\n if (isPowerShellBare(value)) return value;\n return `'${value.replace(/['‘’‚‛]/g, \"$&$&\")}'`;\n}\n\nfunction quoteCmdArg(value: string): string {\n // Quoting a trailing backslash keeps a command routed through `cmd /c` from ending in one,\n // which PowerShell 7 doubles when it quotes the line.\n if (CMD_BARE_ARG.test(value) && !value.endsWith(\"\\\\\")) return value;\n let quoted = '\"';\n let backslashes = 0;\n for (const char of value) {\n if (char === \"\\\\\") {\n backslashes++;\n continue;\n }\n if (char === '\"') {\n quoted += `${\"\\\\\".repeat(backslashes * 2)}\"\"`;\n } else {\n // `%%cd:~,%` reads back as a literal `%` without cmd.exe expanding a `%NAME%` around it.\n quoted += `${\"\\\\\".repeat(backslashes)}${char === \"%\" ? \"%%cd:~,%\" : char}`;\n }\n backslashes = 0;\n }\n return `${quoted}${\"\\\\\".repeat(backslashes * 2)}\"`;\n}\n\nfunction formatWindowsCommandLines(argv: readonly string[]): ShellCommandLines {\n if (\n argv.every(\n (value) =>\n isPowerShellBare(value) || (value !== \"\" && !WINDOWS_DOUBLE_QUOTE_UNSAFE.test(value)),\n )\n ) {\n return {\n kind: \"shared\",\n commandLine: argv.map((value) => (isPowerShellBare(value) ? value : `\"${value}\"`)).join(\" \"),\n };\n }\n const cmd = argv.map(quoteCmdArg).join(\" \");\n // Both PowerShell versions pass a `cmd` argument the same legacy way, so routing the cmd.exe\n // line through `cmd /c` keeps the arguments identical where their native quoting differs.\n const powershell = argv.some((value) => value === \"\" || POWERSHELL_VERSION_SENSITIVE.test(value))\n ? `cmd /d /s /c ${quotePowerShellArg(cmd)}`\n : argv.map(quotePowerShellArg).join(\" \");\n return { kind: \"perShell\", powershell, cmd };\n}\n\n/**\n * Render an argv array as command lines that the current platform's shells run with every\n * argument delivered unchanged\n * @param {readonly string[]} argv - Executable name followed by its arguments\n * @returns {ShellCommandLines} One shared command line, or one per Windows shell\n */\nexport function formatShellCommandLines(argv: readonly string[]): ShellCommandLines {\n if (process.platform === \"win32\") return formatWindowsCommandLines(argv);\n return { kind: \"shared\", commandLine: argv.map(quotePosixArg).join(\" \") };\n}\n","import { redactSecrets, styles } from \"./logger\";\nimport { formatShellCommandLines } from \"./shell-quote\";\nimport type { Jsonifiable } from \"type-fest\";\n\n/**\n * Options for creating a CLI error\n */\ninterface CLIErrorOptions {\n /** Stable machine-readable failure code, such as `WORKSPACE_NOT_FOUND`. */\n code: string;\n message: string;\n details?: string;\n suggestion?: string;\n command?: string;\n next?: CLIErrorNextAction;\n context?: Readonly<Record<string, Jsonifiable | undefined>>;\n cause?: unknown;\n}\n\nexport type CLIErrorNextAction = {\n /** Executable name, such as `tailor`. */\n command: string;\n /** Arguments passed directly to the executable. */\n args: readonly string[];\n};\n\n/**\n * CLI error interface with formatted output\n */\nexport interface CLIError extends Error {\n readonly code: string;\n readonly details?: string;\n readonly suggestion?: string;\n readonly command?: string;\n readonly next?: CLIErrorNextAction;\n readonly context?: Readonly<Record<string, Jsonifiable | undefined>>;\n format(): string;\n}\n\ntype CLIErrorInternal = Error & {\n code: string;\n details?: string;\n suggestion?: string;\n command?: string;\n next?: CLIErrorNextAction;\n context?: Readonly<Record<string, Jsonifiable | undefined>>;\n format(): string;\n};\n\n/**\n * Render a command as a user-facing hint that can be copied into the current platform's shells:\n * one backticked command line, or on Windows, when no single quoting suits both shells, a\n * PowerShell and a cmd.exe line (`` `…` in PowerShell or `…` in cmd.exe ``).\n * Registered secrets are redacted before quoting, which could otherwise split them.\n * @param {CLIErrorNextAction} action - Executable and arguments to suggest\n * @returns {string} The command part of the hint, to follow a verb such as \"Run\"\n */\nexport function formatCommandHint(action: CLIErrorNextAction): string {\n const commandLines = formatShellCommandLines(\n [action.command, ...action.args].map((arg) => redactSecrets(arg)),\n );\n if (commandLines.kind === \"shared\") {\n return `\\`${commandLines.commandLine}\\``;\n }\n return `\\`${commandLines.powershell}\\` in PowerShell or \\`${commandLines.cmd}\\` in cmd.exe`;\n}\n\n/**\n * Redact registered secrets, then indent every line after the first.\n * Redacting first keeps the indent from splitting a multi-line secret.\n * @param text - Details or suggestion text\n * @returns Redacted text with its continuation lines indented\n */\nfunction redactAndIndent(text: string): string {\n return redactSecrets(text).split(\"\\n\").join(\"\\n \");\n}\n\n/**\n * Format CLI error for output\n * @param error - CLIError instance to format\n * @returns Formatted error message\n */\nfunction formatError(error: CLIError): string {\n const parts: string[] = [\n styles.error(`Error${error.code ? ` [${error.code}]` : \"\"}: ${error.message}`),\n ];\n\n if (error.details) {\n parts.push(`\\n ${styles.dim(\"Details:\")} ${redactAndIndent(error.details)}`);\n }\n\n if (error.suggestion) {\n parts.push(`\\n ${styles.info(\"Suggestion:\")} ${redactAndIndent(error.suggestion)}`);\n }\n\n if (error.command) {\n parts.push(\n `\\n ${styles.dim(\"Help:\")} Run \\`tailor ${error.command} --help\\` for usage information.`,\n );\n }\n\n if (error.next) {\n parts.push(`\\n ${styles.info(\"Next:\")} Run ${formatCommandHint(error.next)}.`);\n }\n\n return parts.join(\"\");\n}\n\n/**\n * Create a CLI error with formatted output\n * @param options - Options to construct a CLIError\n * @returns Constructed CLIError instance\n */\nexport function CLIError(options: CLIErrorOptions): CLIError {\n const error = new Error(\n options.message,\n options.cause === undefined ? undefined : { cause: options.cause },\n ) as CLIErrorInternal;\n error.name = \"CLIError\";\n error.code = options.code;\n error.details = options.details;\n error.suggestion = options.suggestion;\n error.command = options.command;\n error.next = options.next;\n error.context = options.context;\n error.format = () => formatError(error);\n return error;\n}\n\n/**\n * Type guard to check if an error is a CLIError\n * @param error - Error to check\n * @returns True if the error is a CLIError\n */\nexport function isCLIError(error: unknown): error is CLIError {\n return error instanceof Error && error.name === \"CLIError\";\n}\n\n/**\n * Summarize a failure as plain text for reports that carry a single error string.\n * CLI errors contribute their details and suggestion so the remediation survives.\n * @param error - Failure to summarize\n * @returns Message followed by any details and suggestion, one per line\n */\nexport function errorSummary(error: unknown): string {\n if (isCLIError(error)) {\n return [error.message, error.details, error.suggestion].filter(Boolean).join(\"\\n\");\n }\n return error instanceof Error ? error.message : String(error);\n}\n\n/**\n * Create an error for an SDK invariant violation that no user action can fix.\n * The result is a plain Error, so JSON output reports it as `UNEXPECTED_ERROR`\n * and crash reporting treats it like any other unexpected failure.\n * @param message - Description of the violated invariant\n * @param options - Standard Error options, such as `cause`\n * @returns Plain Error instance\n */\nexport function internalError(message: string, options?: ErrorOptions): Error {\n return new Error(message, options);\n}\n\n/**\n * Convert a caught value into an Error, keeping Error instances as-is\n * @param value - Caught value\n * @returns The value itself when it is an Error, otherwise an Error of its string form with the value as `cause`\n */\nexport function toError(value: unknown): Error {\n return value instanceof Error ? value : new Error(String(value), { cause: value });\n}\n\nconst MISSING_NAMED_EXPORT_PATTERN = /does not provide an export named '(?!default')([^']+)'/;\n\n/**\n * Suggest `import type` when importing user code fails on a missing named\n * export. The CLI strips types from each file in isolation, so a type-only\n * export does not exist at runtime and a plain import of it fails to link.\n * @param error - Error thrown while importing user modules\n * @returns Suggestion text, or undefined when the error is not that failure\n */\nexport function typeOnlyImportHint(error: unknown): string | undefined {\n if (!(error instanceof SyntaxError)) return undefined;\n const name = MISSING_NAMED_EXPORT_PATTERN.exec(error.message)?.[1];\n if (!name) return undefined;\n return (\n `If '${name}' is a type, import it with \\`import type\\` (or the inline \\`type\\` modifier). ` +\n \"The CLI runs TypeScript by stripping types from each file in isolation, so type-only exports do not exist at runtime. \" +\n 'Set \"verbatimModuleSyntax\": true in tsconfig.json to catch this at typecheck.'\n );\n}\n"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import{n as e,o as t,t as n}from"./date-CgP7gMG_.mjs";const r={uuid:/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i,date:/^(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})$/,time:/^(?<hour>[01]\d|2[0-3]):(?<minute>[0-5]\d)$/,datetime:/^(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})[Tt](?<hour>[01]\d|2[0-3]):(?<minute>[0-5]\d):(?<second>[0-5]\d|60)(\.(?<fraction>\d+))?(?<offset>[Zz]|[+-](?:[01]\d|2[0-3]):[0-5]\d)$/,decimal:/^-?(\d+\.?\d*|\.\d+)([eE][+-]?\d+)?$/};function isNestedObject(e){return typeof e==`object`&&!!e&&!Array.isArray(e)&&!(e instanceof Date)}function validateBaseValue(e){let{field:t,value:n,pathArray:i,issues:a}=e,o=i.length>0?i:void 0,s=a.length;switch(t.type){case`string`:typeof n!=`string`&&a.push({message:`Expected a string: received ${String(n)}`,path:o});break;case`integer`:typeof n==`number`&&Number.isInteger(n)||a.push({message:`Expected an integer: received ${String(n)}`,path:o});break;case`float`:typeof n==`number`&&Number.isFinite(n)||a.push({message:`Expected a number: received ${String(n)}`,path:o});break;case`boolean`:typeof n!=`boolean`&&a.push({message:`Expected a boolean: received ${String(n)}`,path:o});break;case`uuid`:typeof n==`string`&&r.uuid.test(n)||a.push({message:`Expected a valid UUID: received ${String(n)}`,path:o});break;case`date`:typeof n==`string`&&r.date.test(n)||a.push({message:`Expected to match "yyyy-MM-dd" format: received ${String(n)}`,path:o});break;case`datetime`:typeof n==`string`&&r.datetime.test(n)||a.push({message:`Expected to match ISO format: received ${String(n)}`,path:o});break;case`time`:typeof n==`string`&&r.time.test(n)||a.push({message:`Expected to match "HH:mm" format: received ${String(n)}`,path:o});break;case`decimal`:typeof n==`string`&&r.decimal.test(n)||a.push({message:`Expected a decimal string: received ${String(n)}`,path:o});break;case`enum`:if(t._metadata.allowedValues){let e=t._metadata.allowedValues.map(e=>e.value);typeof n==`string`&&e.includes(n)||a.push({message:`Must be one of [${e.join(`, `)}]: received ${String(n)}`,path:o})}break;case`nested`:{if(!isNestedObject(n))return a.push({message:`Expected an object: received ${String(n)}`,path:o}),!1;let r=!0;for(let[a,o]of Object.entries(t.fields)){let t=n[a];validateBaseField({...e,field:o,value:t,pathArray:i.concat(a)})||(r=!1)}return r}}return a.length===s}function validateCustomValue(e,t){let{value:n,pathArray:r,issues:i}=e,a=r.length>0?r:void 0;for(let e of t){let t=e({value:n});typeof t==`string`&&i.push({message:t,path:a})}}function validateBaseField(e){let{field:t,value:n,pathArray:r,issues:i}=e,a=r.length>0?r:void 0,o=n==null;if(t._metadata.required&&o)return i.push({message:`Required field is missing`,path:a}),!1;if(!t._metadata.required&&o)return!0;let s=!0;if(t._metadata.array){if(!Array.isArray(n))return i.push({message:`Expected an array`,path:a}),!1;for(let t=0;t<n.length;t++)validateBaseValue({...e,value:n[t],pathArray:r.concat(`[${t}]`)})||(s=!1)}else s=validateBaseValue(e);return s}function validateCustomField(e){let{field:t,value:n,pathArray:r}=e;if(n==null)return;if(t.type===`nested`){let i=t._metadata.array?n:[n];for(let n=0;n<i.length;n++){let a=i[n],o=t._metadata.array?r.concat(`[${n}]`):r;for(let[n,r]of Object.entries(t.fields))validateCustomField({...e,field:r,value:a[n],pathArray:o.concat(n)})}}let i=t._metadata.validate;i?.length&&validateCustomValue(e,i)}function parseInternal(e,t=a){let{value:n}=e,r=[],i={...e,issues:r};return validateBaseField(i)&&(n=deserializeDates(i,t),r.length===0&&validateCustomField({...i,value:n})),r.length>0?{issues:r}:{value:n??null}}function rejectLeapSecond(e,t){if(e===`datetime`&&t.slice(17,19)===`60`)throw RangeError(`Leap seconds are not supported`)}function parseAsDate(t,n){rejectLeapSecond(t,n);let r=new Date(t===`date`?`${n}T00:00:00.000Z`:t===`time`?`1970-01-01T${n}:00.000Z`:n);if(!Number.isFinite(r.getTime()))throw RangeError(`Invalid Date`);if(t!==`time`){let t=n.slice(0,10);if(e(/* @__PURE__ */ new Date(`${t}T00:00:00.000Z`))!==t)throw RangeError(`Invalid calendar date`)}return r}function parseAsTemporal(e,n){rejectLeapSecond(e,n);let r=t();return e===`date`?r.PlainDate.from(n):e===`datetime`?r.Instant.from(n):r.PlainTime.from(n)}const i={date:parseAsDate,temporal:parseAsTemporal},a={date:globalThis.process?.env.__TAILOR_PLATFORM_BUNDLE_WITHOUT_DATE?void 0:parseAsDate,temporal:globalThis.process?.env.__TAILOR_PLATFORM_BUNDLE_WITHOUT_TEMPORAL?void 0:parseAsTemporal};function deserializeDates(e,t){let{field:r,value:i,issues:a,pathArray:o}=e;if(i==null)return i;let convert=(i,o)=>{let{type:s}=r,c=n(s,r._metadata.as);if(c){let e=t[c];if(!e)throw Error(`Parsing fields declared with as: "${c}" is not included in this bundle. Parse them with parseDateFields, exported by "@tailor-platform/sdk/runtime".`);try{return e(s,String(i))}catch(e){if(!(e instanceof RangeError))throw e;return a.push({message:`Expected a valid ${s===`date`?`calendar date`:s}: received ${i}`,path:o.length>0?o:void 0}),i}}if(r.type!==`nested`)return i;let l=i,u=l;for(let[n,i]of Object.entries(r.fields)){let r=deserializeDates({...e,field:i,value:l[n],pathArray:o.concat(n)},t);r!==l[n]&&(u===l&&(u={...l}),Object.defineProperty(u,n,{value:r,enumerable:!0,configurable:!0,writable:!0}))}return u};if(!r._metadata.array)return convert(i,o);let s=i,c=s.map((e,t)=>convert(e,o.concat(`[${t}]`)));return c.every((e,t)=>e===s[t])?i:c}function parseInputFields(e){let{fields:t,...n}=e;return parseInternal({...n,field:{type:`nested`,fields:t,_metadata:{required:!0}},pathArray:[]})}function parseDateFields(e,t){return parseInternal({...t,field:e,pathArray:[]},i)}export{parseInternal as i,parseDateFields as n,parseInputFields as r,isNestedObject as t};
2
+ //# sourceMappingURL=field-parse-BQhUAbpM.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"field-parse-C41e3UAF.mjs","names":["formatDate","getTemporal","dateRepresentationOf","regex","value","args","path","pathArray","initialIssueCount","issues","field","allowedValues","v","nestedBaseValid","fieldName","nestedField","fieldValue","fn","validateFns","result","isNullOrUndefined","baseValid","i","records","record","recordPath","bundledDateParsers","validationArgs","dateParsers","type","text","date","calendarDate","Temporal","allDateParsers","as","parse","item","error","itemPath","key","child","converted","values","index","parseArgs"],"sources":["../src/runtime/field-parse.ts"],"sourcesContent":["import { dateRepresentationOf, formatDate } from \"./date\";\nimport { getTemporal } from \"./temporal\";\nimport type { FieldMetadata, TailorFieldType } from \"#/configure/types/field.types\";\nimport type { TailorPrincipal } from \"#/runtime/types\";\nimport type { StandardSchemaV1 } from \"@standard-schema/spec\";\n\nconst regex = {\n uuid: /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i,\n date: /^(?<year>\\d{4})-(?<month>\\d{2})-(?<day>\\d{2})$/,\n time: /^(?<hour>[01]\\d|2[0-3]):(?<minute>[0-5]\\d)$/,\n datetime:\n /^(?<year>\\d{4})-(?<month>\\d{2})-(?<day>\\d{2})[Tt](?<hour>[01]\\d|2[0-3]):(?<minute>[0-5]\\d):(?<second>[0-5]\\d|60)(\\.(?<fraction>\\d+))?(?<offset>[Zz]|[+-](?:[01]\\d|2[0-3]):[0-5]\\d)$/,\n decimal: /^-?(\\d+\\.?\\d*|\\.\\d+)([eE][+-]?\\d+)?$/,\n} as const;\n\n/**\n * Whether a value is an acceptable shape for a nested field. Runtime input may\n * not match the declared field type, so anything this rejects is reported\n * against the field rather than recursed into.\n * @param value - The value to check\n * @returns `true` when the value is a plain object the parser recurses into\n */\nexport function isNestedObject(value: unknown): value is Record<string, unknown> {\n return (\n typeof value === \"object\" && value !== null && !Array.isArray(value) && !(value instanceof Date)\n );\n}\n\nexport type FieldParseArgs = {\n value: unknown;\n data: unknown;\n invoker: TailorPrincipal | null;\n};\n\nexport type FieldParseInternalArgs = {\n value: unknown;\n data: unknown;\n invoker: TailorPrincipal | null;\n pathArray: string[];\n};\n\nexport type FieldRuntime<T extends TailorFieldType = TailorFieldType> = {\n readonly type: T;\n readonly fields: Record<string, FieldRuntime>;\n _metadata: FieldMetadata;\n};\n\ntype FieldParseRuntimeArgs<T extends TailorFieldType> = FieldParseInternalArgs & {\n field: FieldRuntime<T>;\n};\n\ntype FieldValidationArgs<T extends TailorFieldType> = FieldParseRuntimeArgs<T> & {\n issues: StandardSchemaV1.Issue[];\n};\n\nfunction validateBaseValue<T extends TailorFieldType>(args: FieldValidationArgs<T>): boolean {\n const { field, value, pathArray, issues } = args;\n const path = pathArray.length > 0 ? pathArray : undefined;\n const initialIssueCount = issues.length;\n\n switch (field.type) {\n case \"string\":\n if (typeof value !== \"string\") {\n issues.push({\n message: `Expected a string: received ${String(value)}`,\n path,\n });\n }\n break;\n\n case \"integer\":\n if (typeof value !== \"number\" || !Number.isInteger(value)) {\n issues.push({\n message: `Expected an integer: received ${String(value)}`,\n path,\n });\n }\n break;\n\n case \"float\":\n if (typeof value !== \"number\" || !Number.isFinite(value)) {\n issues.push({\n message: `Expected a number: received ${String(value)}`,\n path,\n });\n }\n break;\n\n case \"boolean\":\n if (typeof value !== \"boolean\") {\n issues.push({\n message: `Expected a boolean: received ${String(value)}`,\n path,\n });\n }\n break;\n\n case \"uuid\":\n if (typeof value !== \"string\" || !regex.uuid.test(value)) {\n issues.push({\n message: `Expected a valid UUID: received ${String(value)}`,\n path,\n });\n }\n break;\n case \"date\":\n if (typeof value !== \"string\" || !regex.date.test(value)) {\n issues.push({\n message: `Expected to match \"yyyy-MM-dd\" format: received ${String(value)}`,\n path,\n });\n }\n break;\n case \"datetime\":\n if (typeof value !== \"string\" || !regex.datetime.test(value)) {\n issues.push({\n message: `Expected to match ISO format: received ${String(value)}`,\n path,\n });\n }\n break;\n case \"time\":\n if (typeof value !== \"string\" || !regex.time.test(value)) {\n issues.push({\n message: `Expected to match \"HH:mm\" format: received ${String(value)}`,\n path,\n });\n }\n break;\n case \"decimal\":\n if (typeof value !== \"string\" || !regex.decimal.test(value)) {\n issues.push({\n message: `Expected a decimal string: received ${String(value)}`,\n path,\n });\n }\n break;\n\n case \"enum\":\n if (field._metadata.allowedValues) {\n const allowedValues = field._metadata.allowedValues.map((v) => v.value);\n if (typeof value !== \"string\" || !allowedValues.includes(value)) {\n issues.push({\n message: `Must be one of [${allowedValues.join(\", \")}]: received ${String(value)}`,\n path,\n });\n }\n }\n break;\n\n case \"nested\": {\n if (!isNestedObject(value)) {\n issues.push({\n message: `Expected an object: received ${String(value)}`,\n path,\n });\n return false;\n }\n\n let nestedBaseValid = true;\n for (const [fieldName, nestedField] of Object.entries(field.fields)) {\n const fieldValue = value[fieldName];\n if (\n !validateBaseField({\n ...args,\n field: nestedField,\n value: fieldValue,\n pathArray: pathArray.concat(fieldName),\n })\n ) {\n nestedBaseValid = false;\n }\n }\n return nestedBaseValid;\n }\n }\n\n return issues.length === initialIssueCount;\n}\n\nfunction validateCustomValue<T extends TailorFieldType>(\n args: FieldValidationArgs<T>,\n validateFns: NonNullable<FieldMetadata[\"validate\"]>,\n): void {\n const { value, pathArray, issues } = args;\n const path = pathArray.length > 0 ? pathArray : undefined;\n\n for (const fn of validateFns) {\n const result = fn({ value });\n if (typeof result === \"string\") {\n issues.push({\n message: result,\n path,\n });\n }\n }\n}\n\nfunction validateBaseField<T extends TailorFieldType>(args: FieldValidationArgs<T>): boolean {\n const { field, value, pathArray, issues } = args;\n const path = pathArray.length > 0 ? pathArray : undefined;\n\n const isNullOrUndefined = value === null || value === undefined;\n if (field._metadata.required && isNullOrUndefined) {\n issues.push({\n message: \"Required field is missing\",\n path,\n });\n return false;\n }\n\n if (!field._metadata.required && isNullOrUndefined) {\n return true;\n }\n\n let baseValid = true;\n if (field._metadata.array) {\n if (!Array.isArray(value)) {\n issues.push({\n message: \"Expected an array\",\n path,\n });\n return false;\n }\n\n for (let i = 0; i < value.length; i++) {\n if (\n !validateBaseValue({\n ...args,\n value: value[i],\n pathArray: pathArray.concat(`[${i}]`),\n })\n ) {\n baseValid = false;\n }\n }\n } else {\n baseValid = validateBaseValue(args);\n }\n\n return baseValid;\n}\n\nfunction validateCustomField<T extends TailorFieldType>(args: FieldValidationArgs<T>): void {\n const { field, value, pathArray } = args;\n if (value === null || value === undefined) {\n return;\n }\n\n if (field.type === \"nested\") {\n const records = field._metadata.array\n ? (value as Record<string, unknown>[])\n : [value as Record<string, unknown>];\n\n for (let i = 0; i < records.length; i++) {\n const record = records[i] as Record<string, unknown>;\n const recordPath = field._metadata.array ? pathArray.concat(`[${i}]`) : pathArray;\n for (const [fieldName, nestedField] of Object.entries(field.fields)) {\n validateCustomField({\n ...args,\n field: nestedField,\n value: record[fieldName],\n pathArray: recordPath.concat(fieldName),\n });\n }\n }\n }\n\n const validateFns = field._metadata.validate;\n if (validateFns?.length) {\n validateCustomValue(args, validateFns);\n }\n}\n\nexport function parseInternal<T extends TailorFieldType, Output>(\n args: FieldParseRuntimeArgs<T>,\n dateParsers: DateParsers = bundledDateParsers,\n): StandardSchemaV1.Result<Output> {\n let { value } = args;\n const issues: StandardSchemaV1.Issue[] = [];\n const validationArgs = { ...args, issues };\n const baseValid = validateBaseField(validationArgs);\n if (baseValid) {\n value = deserializeDates(validationArgs, dateParsers);\n if (issues.length === 0) {\n validateCustomField({ ...validationArgs, value });\n }\n }\n if (issues.length > 0) {\n return { issues };\n }\n\n return { value: (value ?? null) as Output };\n}\n\ntype DateParser = (type: TailorFieldType, text: string) => unknown;\n\ntype DateParsers = {\n readonly date: DateParser | undefined;\n readonly temporal: DateParser | undefined;\n};\n\nfunction rejectLeapSecond(type: TailorFieldType, text: string): void {\n if (type === \"datetime\" && text.slice(17, 19) === \"60\") {\n throw new RangeError(\"Leap seconds are not supported\");\n }\n}\n\nfunction parseAsDate(type: TailorFieldType, text: string): Date {\n rejectLeapSecond(type, text);\n const date = new Date(\n type === \"date\"\n ? `${text}T00:00:00.000Z`\n : type === \"time\"\n ? `1970-01-01T${text}:00.000Z`\n : text,\n );\n if (!Number.isFinite(date.getTime())) throw new RangeError(\"Invalid Date\");\n if (type !== \"time\") {\n const calendarDate = text.slice(0, 10);\n if (formatDate(new Date(`${calendarDate}T00:00:00.000Z`)) !== calendarDate) {\n throw new RangeError(\"Invalid calendar date\");\n }\n }\n return date;\n}\n\nfunction parseAsTemporal(type: TailorFieldType, text: string): unknown {\n rejectLeapSecond(type, text);\n const Temporal = getTemporal();\n if (type === \"date\") return Temporal.PlainDate.from(text);\n if (type === \"datetime\") return Temporal.Instant.from(text);\n return Temporal.PlainTime.from(text);\n}\n\nconst allDateParsers: DateParsers = { date: parseAsDate, temporal: parseAsTemporal };\n\ntype MaybeProcessGlobal = { process?: { env: Record<string, string | undefined> } };\n\nconst bundledDateParsers: DateParsers = {\n date: (globalThis as MaybeProcessGlobal).process?.env.__TAILOR_PLATFORM_BUNDLE_WITHOUT_DATE\n ? undefined\n : parseAsDate,\n temporal: (globalThis as MaybeProcessGlobal).process?.env\n .__TAILOR_PLATFORM_BUNDLE_WITHOUT_TEMPORAL\n ? undefined\n : parseAsTemporal,\n};\n\nfunction deserializeDates(\n args: FieldValidationArgs<TailorFieldType>,\n dateParsers: DateParsers,\n): unknown {\n const { field, value, issues, pathArray } = args;\n if (value === null || value === undefined) return value;\n const convert = (item: unknown, itemPath: string[]): unknown => {\n const { type } = field;\n const as = dateRepresentationOf(type, field._metadata.as);\n if (as) {\n const parse = dateParsers[as];\n if (!parse) {\n throw new Error(\n `Parsing fields declared with as: \"${as}\" is not included in this bundle. Parse them with parseDateFields, exported by \"@tailor-platform/sdk/runtime\".`,\n );\n }\n try {\n return parse(type, String(item));\n } catch (error) {\n if (!(error instanceof RangeError)) throw error;\n issues.push({\n message: `Expected a valid ${type === \"date\" ? \"calendar date\" : type}: received ${item}`,\n path: itemPath.length > 0 ? itemPath : undefined,\n });\n return item;\n }\n }\n if (field.type !== \"nested\") return item;\n const record = item as Record<string, unknown>;\n let result = record;\n for (const [key, child] of Object.entries(field.fields)) {\n const converted = deserializeDates(\n {\n ...args,\n field: child,\n value: record[key],\n pathArray: itemPath.concat(key),\n },\n dateParsers,\n );\n if (converted !== record[key]) {\n if (result === record) result = { ...record };\n Object.defineProperty(result, key, {\n value: converted,\n enumerable: true,\n configurable: true,\n writable: true,\n });\n }\n }\n return result;\n };\n if (!field._metadata.array) return convert(value, pathArray);\n const values = value as unknown[];\n const converted = values.map((item, index) => convert(item, pathArray.concat(`[${index}]`)));\n return converted.every((item, index) => item === values[index]) ? value : converted;\n}\n\ntype ParseInputFieldsArgs = FieldParseArgs & {\n fields: Record<string, FieldRuntime>;\n};\n\n/**\n * Validate a value against a record of input fields, treating the record as a\n * single required object — the same code path deployed functions run via\n * `t.object(fields).parse(...)`, so local validation matches platform behavior.\n * @param args - Input field definitions plus the value, context data, and user\n * @returns Validation result\n */\nexport function parseInputFields(args: ParseInputFieldsArgs): StandardSchemaV1.Result<unknown> {\n const { fields, ...parseArgs } = args;\n return parseInternal({\n ...parseArgs,\n field: { type: \"nested\", fields, _metadata: { required: true } },\n pathArray: [],\n });\n}\n\ntype ParsableField<Output> = FieldRuntime & {\n parse(args: FieldParseArgs): StandardSchemaV1.Result<Output>;\n};\n\n/**\n * Parse a value like `field.parse`, converting fields declared with `as: \"date\"` or\n * `as: \"temporal\"` even in bundles that leave that conversion out of `field.parse`.\n * @param field - Field defining the value's shape\n * @param args - Value to parse, with the context data and invoker passed to validators\n * @returns Validation result with Date and Temporal fields converted\n */\nexport function parseDateFields<Output>(\n field: ParsableField<Output>,\n args: FieldParseArgs,\n): StandardSchemaV1.Result<Output> {\n return parseInternal({ ...args, field, pathArray: [] }, allDateParsers);\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"field-parse-BQhUAbpM.mjs","names":["formatDate","getTemporal","dateRepresentationOf","regex","value","args","path","pathArray","initialIssueCount","issues","field","allowedValues","v","nestedBaseValid","fieldName","nestedField","fieldValue","fn","validateFns","result","isNullOrUndefined","baseValid","i","records","record","recordPath","bundledDateParsers","validationArgs","dateParsers","type","text","date","calendarDate","Temporal","allDateParsers","as","parse","item","error","itemPath","key","child","converted","values","index","parseArgs"],"sources":["../src/runtime/field-parse.ts"],"sourcesContent":["import { dateRepresentationOf, formatDate } from \"./date\";\nimport { getTemporal } from \"./temporal\";\nimport type { FieldMetadata, TailorFieldType } from \"#/configure/types/field.types\";\nimport type { TailorPrincipal } from \"#/runtime/types\";\nimport type { StandardSchemaV1 } from \"@standard-schema/spec\";\n\nconst regex = {\n uuid: /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i,\n date: /^(?<year>\\d{4})-(?<month>\\d{2})-(?<day>\\d{2})$/,\n time: /^(?<hour>[01]\\d|2[0-3]):(?<minute>[0-5]\\d)$/,\n datetime:\n /^(?<year>\\d{4})-(?<month>\\d{2})-(?<day>\\d{2})[Tt](?<hour>[01]\\d|2[0-3]):(?<minute>[0-5]\\d):(?<second>[0-5]\\d|60)(\\.(?<fraction>\\d+))?(?<offset>[Zz]|[+-](?:[01]\\d|2[0-3]):[0-5]\\d)$/,\n decimal: /^-?(\\d+\\.?\\d*|\\.\\d+)([eE][+-]?\\d+)?$/,\n} as const;\n\n/**\n * Whether a value is an acceptable shape for a nested field. Runtime input may\n * not match the declared field type, so anything this rejects is reported\n * against the field rather than recursed into.\n * @param value - The value to check\n * @returns `true` when the value is a plain object the parser recurses into\n */\nexport function isNestedObject(value: unknown): value is Record<string, unknown> {\n return (\n typeof value === \"object\" && value !== null && !Array.isArray(value) && !(value instanceof Date)\n );\n}\n\nexport type FieldParseArgs = {\n value: unknown;\n data: unknown;\n invoker: TailorPrincipal | null;\n};\n\nexport type FieldParseInternalArgs = {\n value: unknown;\n data: unknown;\n invoker: TailorPrincipal | null;\n pathArray: string[];\n};\n\nexport type FieldRuntime<T extends TailorFieldType = TailorFieldType> = {\n readonly type: T;\n readonly fields: Record<string, FieldRuntime>;\n _metadata: FieldMetadata;\n};\n\ntype FieldParseRuntimeArgs<T extends TailorFieldType> = FieldParseInternalArgs & {\n field: FieldRuntime<T>;\n};\n\ntype FieldValidationArgs<T extends TailorFieldType> = FieldParseRuntimeArgs<T> & {\n issues: StandardSchemaV1.Issue[];\n};\n\nfunction validateBaseValue<T extends TailorFieldType>(args: FieldValidationArgs<T>): boolean {\n const { field, value, pathArray, issues } = args;\n const path = pathArray.length > 0 ? pathArray : undefined;\n const initialIssueCount = issues.length;\n\n switch (field.type) {\n case \"string\":\n if (typeof value !== \"string\") {\n issues.push({\n message: `Expected a string: received ${String(value)}`,\n path,\n });\n }\n break;\n\n case \"integer\":\n if (typeof value !== \"number\" || !Number.isInteger(value)) {\n issues.push({\n message: `Expected an integer: received ${String(value)}`,\n path,\n });\n }\n break;\n\n case \"float\":\n if (typeof value !== \"number\" || !Number.isFinite(value)) {\n issues.push({\n message: `Expected a number: received ${String(value)}`,\n path,\n });\n }\n break;\n\n case \"boolean\":\n if (typeof value !== \"boolean\") {\n issues.push({\n message: `Expected a boolean: received ${String(value)}`,\n path,\n });\n }\n break;\n\n case \"uuid\":\n if (typeof value !== \"string\" || !regex.uuid.test(value)) {\n issues.push({\n message: `Expected a valid UUID: received ${String(value)}`,\n path,\n });\n }\n break;\n case \"date\":\n if (typeof value !== \"string\" || !regex.date.test(value)) {\n issues.push({\n message: `Expected to match \"yyyy-MM-dd\" format: received ${String(value)}`,\n path,\n });\n }\n break;\n case \"datetime\":\n if (typeof value !== \"string\" || !regex.datetime.test(value)) {\n issues.push({\n message: `Expected to match ISO format: received ${String(value)}`,\n path,\n });\n }\n break;\n case \"time\":\n if (typeof value !== \"string\" || !regex.time.test(value)) {\n issues.push({\n message: `Expected to match \"HH:mm\" format: received ${String(value)}`,\n path,\n });\n }\n break;\n case \"decimal\":\n if (typeof value !== \"string\" || !regex.decimal.test(value)) {\n issues.push({\n message: `Expected a decimal string: received ${String(value)}`,\n path,\n });\n }\n break;\n\n case \"enum\":\n if (field._metadata.allowedValues) {\n const allowedValues = field._metadata.allowedValues.map((v) => v.value);\n if (typeof value !== \"string\" || !allowedValues.includes(value)) {\n issues.push({\n message: `Must be one of [${allowedValues.join(\", \")}]: received ${String(value)}`,\n path,\n });\n }\n }\n break;\n\n case \"nested\": {\n if (!isNestedObject(value)) {\n issues.push({\n message: `Expected an object: received ${String(value)}`,\n path,\n });\n return false;\n }\n\n let nestedBaseValid = true;\n for (const [fieldName, nestedField] of Object.entries(field.fields)) {\n const fieldValue = value[fieldName];\n if (\n !validateBaseField({\n ...args,\n field: nestedField,\n value: fieldValue,\n pathArray: pathArray.concat(fieldName),\n })\n ) {\n nestedBaseValid = false;\n }\n }\n return nestedBaseValid;\n }\n }\n\n return issues.length === initialIssueCount;\n}\n\nfunction validateCustomValue<T extends TailorFieldType>(\n args: FieldValidationArgs<T>,\n validateFns: NonNullable<FieldMetadata[\"validate\"]>,\n): void {\n const { value, pathArray, issues } = args;\n const path = pathArray.length > 0 ? pathArray : undefined;\n\n for (const fn of validateFns) {\n const result = fn({ value });\n if (typeof result === \"string\") {\n issues.push({\n message: result,\n path,\n });\n }\n }\n}\n\nfunction validateBaseField<T extends TailorFieldType>(args: FieldValidationArgs<T>): boolean {\n const { field, value, pathArray, issues } = args;\n const path = pathArray.length > 0 ? pathArray : undefined;\n\n const isNullOrUndefined = value === null || value === undefined;\n if (field._metadata.required && isNullOrUndefined) {\n issues.push({\n message: \"Required field is missing\",\n path,\n });\n return false;\n }\n\n if (!field._metadata.required && isNullOrUndefined) {\n return true;\n }\n\n let baseValid = true;\n if (field._metadata.array) {\n if (!Array.isArray(value)) {\n issues.push({\n message: \"Expected an array\",\n path,\n });\n return false;\n }\n\n for (let i = 0; i < value.length; i++) {\n if (\n !validateBaseValue({\n ...args,\n value: value[i],\n pathArray: pathArray.concat(`[${i}]`),\n })\n ) {\n baseValid = false;\n }\n }\n } else {\n baseValid = validateBaseValue(args);\n }\n\n return baseValid;\n}\n\nfunction validateCustomField<T extends TailorFieldType>(args: FieldValidationArgs<T>): void {\n const { field, value, pathArray } = args;\n if (value === null || value === undefined) {\n return;\n }\n\n if (field.type === \"nested\") {\n const records = field._metadata.array\n ? (value as Record<string, unknown>[])\n : [value as Record<string, unknown>];\n\n for (let i = 0; i < records.length; i++) {\n const record = records[i] as Record<string, unknown>;\n const recordPath = field._metadata.array ? pathArray.concat(`[${i}]`) : pathArray;\n for (const [fieldName, nestedField] of Object.entries(field.fields)) {\n validateCustomField({\n ...args,\n field: nestedField,\n value: record[fieldName],\n pathArray: recordPath.concat(fieldName),\n });\n }\n }\n }\n\n const validateFns = field._metadata.validate;\n if (validateFns?.length) {\n validateCustomValue(args, validateFns);\n }\n}\n\nexport function parseInternal<T extends TailorFieldType, Output>(\n args: FieldParseRuntimeArgs<T>,\n dateParsers: DateParsers = bundledDateParsers,\n): StandardSchemaV1.Result<Output> {\n let { value } = args;\n const issues: StandardSchemaV1.Issue[] = [];\n const validationArgs = { ...args, issues };\n const baseValid = validateBaseField(validationArgs);\n if (baseValid) {\n value = deserializeDates(validationArgs, dateParsers);\n if (issues.length === 0) {\n validateCustomField({ ...validationArgs, value });\n }\n }\n if (issues.length > 0) {\n return { issues };\n }\n\n return { value: (value ?? null) as Output };\n}\n\ntype DateParser = (type: TailorFieldType, text: string) => unknown;\n\ntype DateParsers = {\n readonly date: DateParser | undefined;\n readonly temporal: DateParser | undefined;\n};\n\nfunction rejectLeapSecond(type: TailorFieldType, text: string): void {\n if (type === \"datetime\" && text.slice(17, 19) === \"60\") {\n throw new RangeError(\"Leap seconds are not supported\");\n }\n}\n\nfunction parseAsDate(type: TailorFieldType, text: string): Date {\n rejectLeapSecond(type, text);\n const date = new Date(\n type === \"date\"\n ? `${text}T00:00:00.000Z`\n : type === \"time\"\n ? `1970-01-01T${text}:00.000Z`\n : text,\n );\n if (!Number.isFinite(date.getTime())) throw new RangeError(\"Invalid Date\");\n if (type !== \"time\") {\n const calendarDate = text.slice(0, 10);\n if (formatDate(new Date(`${calendarDate}T00:00:00.000Z`)) !== calendarDate) {\n throw new RangeError(\"Invalid calendar date\");\n }\n }\n return date;\n}\n\nfunction parseAsTemporal(type: TailorFieldType, text: string): unknown {\n rejectLeapSecond(type, text);\n const Temporal = getTemporal();\n if (type === \"date\") return Temporal.PlainDate.from(text);\n if (type === \"datetime\") return Temporal.Instant.from(text);\n return Temporal.PlainTime.from(text);\n}\n\nconst allDateParsers: DateParsers = { date: parseAsDate, temporal: parseAsTemporal };\n\ntype MaybeProcessGlobal = { process?: { env: Record<string, string | undefined> } };\n\nconst bundledDateParsers: DateParsers = {\n date: (globalThis as MaybeProcessGlobal).process?.env.__TAILOR_PLATFORM_BUNDLE_WITHOUT_DATE\n ? undefined\n : parseAsDate,\n temporal: (globalThis as MaybeProcessGlobal).process?.env\n .__TAILOR_PLATFORM_BUNDLE_WITHOUT_TEMPORAL\n ? undefined\n : parseAsTemporal,\n};\n\nfunction deserializeDates(\n args: FieldValidationArgs<TailorFieldType>,\n dateParsers: DateParsers,\n): unknown {\n const { field, value, issues, pathArray } = args;\n if (value === null || value === undefined) return value;\n const convert = (item: unknown, itemPath: string[]): unknown => {\n const { type } = field;\n const as = dateRepresentationOf(type, field._metadata.as);\n if (as) {\n const parse = dateParsers[as];\n if (!parse) {\n throw new Error(\n `Parsing fields declared with as: \"${as}\" is not included in this bundle. Parse them with parseDateFields, exported by \"@tailor-platform/sdk/runtime\".`,\n );\n }\n try {\n return parse(type, String(item));\n } catch (error) {\n if (!(error instanceof RangeError)) throw error;\n issues.push({\n message: `Expected a valid ${type === \"date\" ? \"calendar date\" : type}: received ${item}`,\n path: itemPath.length > 0 ? itemPath : undefined,\n });\n return item;\n }\n }\n if (field.type !== \"nested\") return item;\n const record = item as Record<string, unknown>;\n let result = record;\n for (const [key, child] of Object.entries(field.fields)) {\n const converted = deserializeDates(\n {\n ...args,\n field: child,\n value: record[key],\n pathArray: itemPath.concat(key),\n },\n dateParsers,\n );\n if (converted !== record[key]) {\n if (result === record) result = { ...record };\n Object.defineProperty(result, key, {\n value: converted,\n enumerable: true,\n configurable: true,\n writable: true,\n });\n }\n }\n return result;\n };\n if (!field._metadata.array) return convert(value, pathArray);\n const values = value as unknown[];\n const converted = values.map((item, index) => convert(item, pathArray.concat(`[${index}]`)));\n return converted.every((item, index) => item === values[index]) ? value : converted;\n}\n\ntype ParseInputFieldsArgs = FieldParseArgs & {\n fields: Record<string, FieldRuntime>;\n};\n\n/**\n * Validate a value against a record of input fields, treating the record as a\n * single required object — the same code path deployed functions run via\n * `t.object(fields).parse(...)`, so local validation matches platform behavior.\n * @param args - Input field definitions plus the value, context data, and user\n * @returns Validation result\n */\nexport function parseInputFields(args: ParseInputFieldsArgs): StandardSchemaV1.Result<unknown> {\n const { fields, ...parseArgs } = args;\n return parseInternal({\n ...parseArgs,\n field: { type: \"nested\", fields, _metadata: { required: true } },\n pathArray: [],\n });\n}\n\ntype ParsableField<Output> = FieldRuntime & {\n parse(args: FieldParseArgs): StandardSchemaV1.Result<Output>;\n};\n\n/**\n * Parse a value like `field.parse`, converting fields declared with `as: \"date\"` or\n * `as: \"temporal\"` even in bundles that leave that conversion out of `field.parse`.\n * @param field - Field defining the value's shape\n * @param args - Value to parse, with the context data and invoker passed to validators\n * @returns Validation result with Date and Temporal fields converted\n */\nexport function parseDateFields<Output>(\n field: ParsableField<Output>,\n args: FieldParseArgs,\n): StandardSchemaV1.Result<Output> {\n return parseInternal({ ...args, field, pathArray: [] }, allDateParsers);\n}\n"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ function getRawPluginTableName(e){let t=typeof e==`object`&&e&&`name`in e?e.name:void 0;return typeof t==`string`?t:void 0}function hasGenerationHooks(e){return!!(e.onTailorDBReady||e.onResolverReady||e.onExecutorReady)}function isPluginExecutorWithFile(e){return`resolve`in e&&`context`in e}export{hasGenerationHooks as n,isPluginExecutorWithFile as r,getRawPluginTableName as t};
2
+ //# sourceMappingURL=guards-CiFVxoXR.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"guards-CiFVxoXR.mjs","names":["name","table","plugin","executor"],"sources":["../src/plugin/guards.ts"],"sourcesContent":["// Runtime guards and helpers for plugin authoring types.\n//\n// These live outside plugin/types.ts (a pure type module) because they are\n// runtime functions. The types they operate on are imported type-only.\nimport type { PluginGeneratedExecutor, PluginGeneratedExecutorWithFile } from \"./types\";\n\n/**\n * Reads a table name without assuming plugin output is a valid table object.\n * @param table - Raw table value returned by a plugin hook.\n * @returns The table name when it is a string; otherwise, undefined.\n */\nexport function getRawPluginTableName(table: unknown): string | undefined {\n const name =\n typeof table === \"object\" && table !== null && \"name\" in table ? table.name : undefined;\n return typeof name === \"string\" ? name : undefined;\n}\n\n/**\n * Checks if a plugin has any generation-time hooks.\n * @param plugin - The plugin object to inspect.\n * @param plugin.onTailorDBReady - Hook for TailorDB readiness.\n * @param plugin.onResolverReady - Hook for resolver readiness.\n * @param plugin.onExecutorReady - Hook for executor readiness.\n * @returns True if the plugin has at least one generation hook.\n */\nexport function hasGenerationHooks(plugin: {\n onTailorDBReady?: unknown;\n onResolverReady?: unknown;\n onExecutorReady?: unknown;\n}): boolean {\n return !!(plugin.onTailorDBReady || plugin.onResolverReady || plugin.onExecutorReady);\n}\n\n/**\n * Checks if a plugin executor uses file-based resolution.\n * @param executor - The plugin executor to check.\n * @returns True if the executor uses file-based resolution.\n */\nexport function isPluginExecutorWithFile(\n executor: PluginGeneratedExecutor,\n): executor is PluginGeneratedExecutorWithFile {\n return \"resolve\" in executor && \"context\" in executor;\n}\n"],"mappings":"AAWA,SAAgB,sBAAsB,EAAoC,CACxE,IAAMA,EACJ,OAAOC,GAAU,UAAYA,GAAkB,SAAUA,EAAQA,EAAM,KAAO,IAAA,GAChF,OAAO,OAAOD,GAAS,SAAWA,EAAO,IAAA,EAC3C,CAUA,SAAgB,mBAAmB,EAIvB,CACV,MAAO,CAAC,EAAEE,EAAO,iBAAmBA,EAAO,iBAAmBA,EAAO,gBACvE,CAOA,SAAgB,yBACd,EAC6C,CAC7C,MAAO,YAAaC,GAAY,YAAaA,CAC/C,C"}
@@ -3,7 +3,6 @@ import { IsAutoFilledDBField, IsReadOnlyDBField, TailorAnyDBField, TailorAnyDBTy
3
3
  import { Temporal, Temporal as Temporal$1 } from "temporal-spec";
4
4
  import { ColumnType, ColumnType as ColumnType$1, Insertable, Insertable as Insertable$1, Kysely, Kysely as Kysely$1, KyselyConfig, KyselyConfig as KyselyConfig$1, Selectable, Selectable as Selectable$1, Transaction, Transaction as Transaction$1, Updateable, Updateable as Updateable$1, sql } from "kysely";
5
5
  import { TailordbDialect } from "@tailor-platform/function-kysely-tailordb";
6
- //#region src/kysely/index.d.ts
7
6
  export type Timestamp = ColumnType$1<Date, Date | string, Date | string>;
8
7
  /** Column type for a `date` field read back as `Temporal.PlainDate` (`createGetDB`'s `temporal` option). */
9
8
  export type TemporalDate = ColumnType$1<Temporal$1.PlainDate, Temporal$1.PlainDate | string, Temporal$1.PlainDate | string>;
@@ -102,5 +101,4 @@ export type TailorDBInsertable<T extends TailorDBColumnsSource, IsTemporal exten
102
101
  export type TailorDBSelectable<T extends TailorDBColumnsSource, IsTemporal extends boolean = false> = FlattenColumns<Selectable$1<TailorDBColumns<T, IsTemporal>>>;
103
102
  /** Update input for a TailorDB table or field collection. See {@link TailorDBInsertable}. */
104
103
  export type TailorDBUpdateable<T extends TailorDBColumnsSource, IsTemporal extends boolean = false> = FlattenColumns<Updateable$1<TailorDBColumns<T, IsTemporal>>>;
105
- //#endregion
106
104
  export { type ColumnType, type Insertable, Kysely, type KyselyConfig, type Selectable, TailordbDialect, type Temporal, type Transaction, type Updateable, sql };
@@ -0,0 +1,2 @@
1
+ import{t as e}from"./schema-BU1aIQ63.mjs";import{t}from"./assert-WeXvmG4j.mjs";import{n,t as r}from"./guards-CiFVxoXR.mjs";var PluginManager=class{plugins=/* @__PURE__ */ new Map;generatedExecutors=[];generatedTables=[];generatedResolvers=[];processedResolverNamespaces=/* @__PURE__ */ new Set;namespaceGeneratedTableKeys=/* @__PURE__ */ new Set;namespaceGeneratedExecutorKeys=/* @__PURE__ */ new Set;constructor(e=[]){for(let t of e){if(this.plugins.has(t.id))throw Error(`Duplicate plugin ID "${t.id}" detected. Each plugin must have a unique ID.`);this.plugins.set(t.id,t)}}async processAttachment(e){let n=this.plugins.get(e.pluginId);if(!n)return{success:!1,error:`Plugin "${e.pluginId}" not found`};let r=n.tableConfigRequired;if((typeof r==`function`?r(n.pluginConfig):r===!0)&&(e.tableConfig===void 0||e.tableConfig===null))return{success:!1,error:`Plugin "${n.id}" requires tableConfig, but none was provided for table "${e.table.name}".`};if(!n.onTableLoaded)return{success:!1,error:`Plugin "${n.id}" does not support table-attached processing (missing onTableLoaded method). Use onNamespaceLoaded via definePlugins() instead.`};let i;try{i=await n.onTableLoaded({table:e.table,tableConfig:e.tableConfig,pluginConfig:n.pluginConfig,namespace:e.namespace})}catch(t){let r=t instanceof Error?t.message:String(t);return{success:!1,error:`Plugin "${n.id}" threw an error while processing table "${e.table.name}": ${r}`}}for(let t of i.resolvers??[])this.generatedResolvers.push({resolver:t,pluginId:n.id,namespace:e.namespace,sourceTableName:e.table.name});if(i.tables&&Object.keys(i.tables).length>0){let r=t(n.importPath,`plugin "${n.id}" missing importPath`);for(let[t,a]of Object.entries(i.tables))this.generatedTables.push({pluginId:e.pluginId,pluginImportPath:r,sourceTableName:e.table.name,kind:t,table:a,namespace:e.namespace,pluginConfig:n.pluginConfig})}if(i.executors&&i.executors.length>0)for(let t of i.executors)this.generatedExecutors.push({executor:t,pluginId:e.pluginId,namespace:e.namespace,sourceTableName:e.table.name});return{success:!0,output:i}}async processNamespacePlugins(e){let n=[];for(let[i,a]of this.plugins){if(!a.onNamespaceLoaded)continue;let o=a.pluginConfig,s={pluginConfig:o,namespace:e},c;try{c=await a.onNamespaceLoaded(s)}catch(t){let r=t instanceof Error?t.message:String(t);n.push({pluginId:i,config:o,result:{success:!1,error:`Plugin "${a.id}" threw an error during namespace processing for "${e}": ${r}`}});continue}let l=JSON.stringify([i,e]);if(!this.processedResolverNamespaces.has(l)){for(let t of c.resolvers??[])this.generatedResolvers.push({resolver:t,pluginId:i,namespace:e});this.processedResolverNamespaces.add(l)}if(c.executors&&c.executors.length>0)for(let t of c.executors){let n=`${i}:${t.name}`;this.namespaceGeneratedExecutorKeys.has(n)||(this.namespaceGeneratedExecutorKeys.add(n),this.generatedExecutors.push({executor:t,pluginId:i,namespace:e}))}if(c.tables&&Object.keys(c.tables).length>0){let n=t(a.importPath,`plugin "${a.id}" missing importPath`);for(let[t,o]of Object.entries(c.tables)){let s=`${i}:${t}:${r(o)??``}`;this.namespaceGeneratedTableKeys.has(s)||(this.namespaceGeneratedTableKeys.add(s),this.generatedTables.push({pluginId:i,pluginImportPath:n,sourceTableName:`(namespace)`,kind:t,table:o,namespace:e,pluginConfig:a.pluginConfig}))}}n.push({pluginId:i,config:o,result:{success:!0,output:c}})}return n}async processAttachmentsForTable(e){let{rawTable:t,attachments:n,namespace:i}=e,a=t,o,s=[],c=[];for(let e of n){let t=await this.processAttachment({table:a,tableConfig:e.config,namespace:i,pluginId:e.pluginId});if(!t.success)throw Error(t.error);let n=t.output,l=n.extends?.fields;l&&Object.keys(l).length>0&&(a=this.extendTable({originalTable:a,extendFields:l,pluginId:e.pluginId}),o=a,c.push({kind:`extended`,tableName:a.name,fieldCount:Object.keys(l).length,pluginId:e.pluginId}));let u=this.getPlugin(e.pluginId);for(let[t,i]of Object.entries(n.tables??{})){let n=r(i)??``;s.push({tableName:n,table:i,kind:t,pluginId:e.pluginId,pluginImportPath:this.getPluginImportPath(e.pluginId)??``,pluginConfig:u?.pluginConfig}),c.push({kind:`generated`,tableName:n,pluginId:e.pluginId})}}return{extendedTable:o,generatedTables:s,events:c}}getPlugin(e){return this.plugins.get(e)}getPluginImportPath(e){return this.plugins.get(e)?.importPath}getPluginGeneratedResolvers(){return this.generatedResolvers}getPluginGeneratedExecutorsWithImportPath(){return this.generatedExecutors.map(e=>({...e,pluginImportPath:this.getPluginImportPath(e.pluginId)??``}))}getPluginGeneratedTables(){return this.generatedTables}getPluginsWithGenerationHooks(){return Array.from(this.plugins.values()).filter(e=>n(e))}generatePluginFiles(e){let{outputDir:t,sourceTableInfoMap:n,configPath:r,tableGenerator:i,executorGenerator:a}=e,o=i(this.generatedTables,t);return a(this.getPluginGeneratedExecutorsWithImportPath(),t,o,n,r)}extendTable(t){let{originalTable:n,extendFields:r,pluginId:i}=t,a=Object.keys(n.fields),o=Object.keys(n.metadata.files),s=Object.keys(r),c=s.filter(e=>a.includes(e)),l=s.filter(e=>o.includes(e));if(c.length>0)throw Error(`Plugin "${i}" attempted to add fields that already exist in table "${n.name}": ${c.join(`, `)}. extendFields cannot overwrite existing fields.`);if(l.length>0)throw Error(`Plugin "${i}" attempted to add fields that collide with file keys already declared via .files() on table "${n.name}": ${l.join(`, `)}.`);let{id:u,...d}={...n.fields,...r},f=n.metadata.settings?.pluralForm,p=f?[n.name,f]:n.name;return copyMetadataToExtendedTable(n,e.table(p,d))}};function copyMetadataToExtendedTable(e,t){let n=t;e._description&&(n=n.description(e._description));let r=e.metadata;if(Object.keys(r.files).length>0&&(n=n.files(r.files)),r.settings){let{pluralForm:e,...t}=r.settings;Object.keys(t).length>0&&(n=n.features(t))}if(r.permissions.record&&(n=n.permission(r.permissions.record)),r.permissions.gql&&(n=n.gqlPermission(r.permissions.gql)),r.indexes&&Object.keys(r.indexes).length>0){let e=Object.entries(r.indexes).map(([e,t])=>({name:e,fields:t.fields,unique:t.unique}));n=n.indexes(...e)}if(r.typeHook&&(n=n.hooks(r.typeHook)),r.typeValidate&&(n=n.validate(r.typeValidate)),e.plugins.length>0)for(let t of e.plugins)n=n.plugin({[t.pluginId]:t.config});return n}export{PluginManager as t};
2
+ //# sourceMappingURL=manager-B813m43t.mjs.map