@signstack/cli 0.1.1

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 (269) hide show
  1. package/README.md +458 -0
  2. package/bin/run.js +12 -0
  3. package/dist/apps/signstack-cli/schemas/asset.schema.json +220 -0
  4. package/dist/apps/signstack-cli/schemas/blueprint.schema.json +485 -0
  5. package/dist/apps/signstack-cli/schemas/jsonata-function.schema.json +185 -0
  6. package/dist/apps/signstack-cli/schemas/schema.schema.json +97 -0
  7. package/dist/apps/signstack-cli/schemas/template.schema.json +295 -0
  8. package/dist/apps/signstack-cli/src/commands/auth/login.d.ts +25 -0
  9. package/dist/apps/signstack-cli/src/commands/auth/login.js +229 -0
  10. package/dist/apps/signstack-cli/src/commands/auth/login.js.map +1 -0
  11. package/dist/apps/signstack-cli/src/commands/auth/logout.d.ts +10 -0
  12. package/dist/apps/signstack-cli/src/commands/auth/logout.js +59 -0
  13. package/dist/apps/signstack-cli/src/commands/auth/logout.js.map +1 -0
  14. package/dist/apps/signstack-cli/src/commands/auth/whoami.d.ts +9 -0
  15. package/dist/apps/signstack-cli/src/commands/auth/whoami.js +85 -0
  16. package/dist/apps/signstack-cli/src/commands/auth/whoami.js.map +1 -0
  17. package/dist/apps/signstack-cli/src/commands/generate.d.ts +51 -0
  18. package/dist/apps/signstack-cli/src/commands/generate.js +479 -0
  19. package/dist/apps/signstack-cli/src/commands/generate.js.map +1 -0
  20. package/dist/apps/signstack-cli/src/commands/preview.d.ts +24 -0
  21. package/dist/apps/signstack-cli/src/commands/preview.js +162 -0
  22. package/dist/apps/signstack-cli/src/commands/preview.js.map +1 -0
  23. package/dist/apps/signstack-cli/src/commands/pull.d.ts +28 -0
  24. package/dist/apps/signstack-cli/src/commands/pull.js +244 -0
  25. package/dist/apps/signstack-cli/src/commands/pull.js.map +1 -0
  26. package/dist/apps/signstack-cli/src/commands/push.d.ts +46 -0
  27. package/dist/apps/signstack-cli/src/commands/push.js +460 -0
  28. package/dist/apps/signstack-cli/src/commands/push.js.map +1 -0
  29. package/dist/apps/signstack-cli/src/commands/run.d.ts +22 -0
  30. package/dist/apps/signstack-cli/src/commands/run.js +126 -0
  31. package/dist/apps/signstack-cli/src/commands/run.js.map +1 -0
  32. package/dist/apps/signstack-cli/src/commands/test.d.ts +6 -0
  33. package/dist/apps/signstack-cli/src/commands/test.js +25 -0
  34. package/dist/apps/signstack-cli/src/commands/test.js.map +1 -0
  35. package/dist/apps/signstack-cli/src/commands/validate.d.ts +59 -0
  36. package/dist/apps/signstack-cli/src/commands/validate.js +558 -0
  37. package/dist/apps/signstack-cli/src/commands/validate.js.map +1 -0
  38. package/dist/apps/signstack-cli/src/index.d.ts +1 -0
  39. package/dist/apps/signstack-cli/src/index.js +2 -0
  40. package/dist/apps/signstack-cli/src/index.js.map +1 -0
  41. package/dist/apps/signstack-cli/src/lib/api-client.d.ts +77 -0
  42. package/dist/apps/signstack-cli/src/lib/api-client.js +269 -0
  43. package/dist/apps/signstack-cli/src/lib/api-client.js.map +1 -0
  44. package/dist/apps/signstack-cli/src/lib/base-command.d.ts +38 -0
  45. package/dist/apps/signstack-cli/src/lib/base-command.js +135 -0
  46. package/dist/apps/signstack-cli/src/lib/base-command.js.map +1 -0
  47. package/dist/apps/signstack-cli/src/lib/config.d.ts +47 -0
  48. package/dist/apps/signstack-cli/src/lib/config.js +106 -0
  49. package/dist/apps/signstack-cli/src/lib/config.js.map +1 -0
  50. package/dist/apps/signstack-cli/src/lib/entity-data-resolver.d.ts +31 -0
  51. package/dist/apps/signstack-cli/src/lib/entity-data-resolver.js +107 -0
  52. package/dist/apps/signstack-cli/src/lib/entity-data-resolver.js.map +1 -0
  53. package/dist/apps/signstack-cli/src/lib/local-resource-loader.d.ts +72 -0
  54. package/dist/apps/signstack-cli/src/lib/local-resource-loader.js +238 -0
  55. package/dist/apps/signstack-cli/src/lib/local-resource-loader.js.map +1 -0
  56. package/dist/apps/signstack-cli/src/lib/path-utils.d.ts +4 -0
  57. package/dist/apps/signstack-cli/src/lib/path-utils.js +7 -0
  58. package/dist/apps/signstack-cli/src/lib/path-utils.js.map +1 -0
  59. package/dist/apps/signstack-cli/src/lib/payload-builder.d.ts +127 -0
  60. package/dist/apps/signstack-cli/src/lib/payload-builder.js +545 -0
  61. package/dist/apps/signstack-cli/src/lib/payload-builder.js.map +1 -0
  62. package/dist/apps/signstack-cli/src/lib/preview-handler.d.ts +95 -0
  63. package/dist/apps/signstack-cli/src/lib/preview-handler.js +611 -0
  64. package/dist/apps/signstack-cli/src/lib/preview-handler.js.map +1 -0
  65. package/dist/apps/signstack-cli/src/lib/preview-output-formatter.d.ts +63 -0
  66. package/dist/apps/signstack-cli/src/lib/preview-output-formatter.js +198 -0
  67. package/dist/apps/signstack-cli/src/lib/preview-output-formatter.js.map +1 -0
  68. package/dist/apps/signstack-cli/src/lib/public-api-client.d.ts +13 -0
  69. package/dist/apps/signstack-cli/src/lib/public-api-client.js +39 -0
  70. package/dist/apps/signstack-cli/src/lib/public-api-client.js.map +1 -0
  71. package/dist/apps/signstack-cli/src/lib/resource-puller.d.ts +131 -0
  72. package/dist/apps/signstack-cli/src/lib/resource-puller.js +800 -0
  73. package/dist/apps/signstack-cli/src/lib/resource-puller.js.map +1 -0
  74. package/dist/apps/signstack-cli/src/lib/resource-pusher.d.ts +87 -0
  75. package/dist/apps/signstack-cli/src/lib/resource-pusher.js +361 -0
  76. package/dist/apps/signstack-cli/src/lib/resource-pusher.js.map +1 -0
  77. package/dist/apps/signstack-cli/src/lib/resource-scanner.d.ts +29 -0
  78. package/dist/apps/signstack-cli/src/lib/resource-scanner.js +101 -0
  79. package/dist/apps/signstack-cli/src/lib/resource-scanner.js.map +1 -0
  80. package/dist/apps/signstack-cli/src/lib/resource-validator.d.ts +44 -0
  81. package/dist/apps/signstack-cli/src/lib/resource-validator.js +158 -0
  82. package/dist/apps/signstack-cli/src/lib/resource-validator.js.map +1 -0
  83. package/dist/apps/signstack-cli/src/lib/run-handler.d.ts +47 -0
  84. package/dist/apps/signstack-cli/src/lib/run-handler.js +266 -0
  85. package/dist/apps/signstack-cli/src/lib/run-handler.js.map +1 -0
  86. package/dist/apps/signstack-cli/src/lib/safe-path.d.ts +28 -0
  87. package/dist/apps/signstack-cli/src/lib/safe-path.js +44 -0
  88. package/dist/apps/signstack-cli/src/lib/safe-path.js.map +1 -0
  89. package/dist/apps/signstack-cli/src/lib/scenario-file.d.ts +35 -0
  90. package/dist/apps/signstack-cli/src/lib/scenario-file.js +80 -0
  91. package/dist/apps/signstack-cli/src/lib/scenario-file.js.map +1 -0
  92. package/dist/apps/signstack-cli/src/lib/schema-validator.d.ts +8 -0
  93. package/dist/apps/signstack-cli/src/lib/schema-validator.js +39 -0
  94. package/dist/apps/signstack-cli/src/lib/schema-validator.js.map +1 -0
  95. package/dist/apps/signstack-cli/src/lib/url-validator.d.ts +17 -0
  96. package/dist/apps/signstack-cli/src/lib/url-validator.js +61 -0
  97. package/dist/apps/signstack-cli/src/lib/url-validator.js.map +1 -0
  98. package/dist/apps/signstack-cli/src/lib/yaml-document-parser.d.ts +25 -0
  99. package/dist/apps/signstack-cli/src/lib/yaml-document-parser.js +133 -0
  100. package/dist/apps/signstack-cli/src/lib/yaml-document-parser.js.map +1 -0
  101. package/dist/apps/signstack-cli/src/lib/yaml-transforms.d.ts +3 -0
  102. package/dist/apps/signstack-cli/src/lib/yaml-transforms.js +32 -0
  103. package/dist/apps/signstack-cli/src/lib/yaml-transforms.js.map +1 -0
  104. package/dist/apps/signstack-cli/src/lib/yaml-writer.d.ts +47 -0
  105. package/dist/apps/signstack-cli/src/lib/yaml-writer.js +160 -0
  106. package/dist/apps/signstack-cli/src/lib/yaml-writer.js.map +1 -0
  107. package/dist/apps/signstack-cli/src/types/auth.types.d.ts +48 -0
  108. package/dist/apps/signstack-cli/src/types/auth.types.js +31 -0
  109. package/dist/apps/signstack-cli/src/types/auth.types.js.map +1 -0
  110. package/dist/apps/signstack-cli/src/types/schema.types.d.ts +14 -0
  111. package/dist/apps/signstack-cli/src/types/schema.types.js +16 -0
  112. package/dist/apps/signstack-cli/src/types/schema.types.js.map +1 -0
  113. package/dist/apps/signstack-cli/src/types/yaml.types.d.ts +144 -0
  114. package/dist/apps/signstack-cli/src/types/yaml.types.js +2 -0
  115. package/dist/apps/signstack-cli/src/types/yaml.types.js.map +1 -0
  116. package/dist/libs/common/base/src/index.d.ts +14 -0
  117. package/dist/libs/common/base/src/index.js +44 -0
  118. package/dist/libs/common/base/src/index.js.map +1 -0
  119. package/dist/libs/common/base/src/lib/address.util.d.ts +12 -0
  120. package/dist/libs/common/base/src/lib/address.util.js +55 -0
  121. package/dist/libs/common/base/src/lib/address.util.js.map +1 -0
  122. package/dist/libs/common/base/src/lib/country-code-data.d.ts +5 -0
  123. package/dist/libs/common/base/src/lib/country-code-data.js +1256 -0
  124. package/dist/libs/common/base/src/lib/country-code-data.js.map +1 -0
  125. package/dist/libs/common/base/src/lib/date.util.d.ts +13 -0
  126. package/dist/libs/common/base/src/lib/date.util.js +135 -0
  127. package/dist/libs/common/base/src/lib/date.util.js.map +1 -0
  128. package/dist/libs/common/base/src/lib/headers.d.ts +1 -0
  129. package/dist/libs/common/base/src/lib/headers.js +5 -0
  130. package/dist/libs/common/base/src/lib/headers.js.map +1 -0
  131. package/dist/libs/common/base/src/lib/jsonata.service.d.ts +32 -0
  132. package/dist/libs/common/base/src/lib/jsonata.service.js +207 -0
  133. package/dist/libs/common/base/src/lib/jsonata.service.js.map +1 -0
  134. package/dist/libs/common/base/src/lib/key-validation.constants.d.ts +37 -0
  135. package/dist/libs/common/base/src/lib/key-validation.constants.js +144 -0
  136. package/dist/libs/common/base/src/lib/key-validation.constants.js.map +1 -0
  137. package/dist/libs/common/base/src/lib/phone-util.d.ts +16 -0
  138. package/dist/libs/common/base/src/lib/phone-util.js +61 -0
  139. package/dist/libs/common/base/src/lib/phone-util.js.map +1 -0
  140. package/dist/libs/common/base/src/lib/schema-validation.util.d.ts +24 -0
  141. package/dist/libs/common/base/src/lib/schema-validation.util.js +155 -0
  142. package/dist/libs/common/base/src/lib/schema-validation.util.js.map +1 -0
  143. package/dist/libs/common/base/src/lib/string-builder.d.ts +48 -0
  144. package/dist/libs/common/base/src/lib/string-builder.js +90 -0
  145. package/dist/libs/common/base/src/lib/string-builder.js.map +1 -0
  146. package/dist/libs/common/base/src/lib/util.d.ts +20 -0
  147. package/dist/libs/common/base/src/lib/util.js +110 -0
  148. package/dist/libs/common/base/src/lib/util.js.map +1 -0
  149. package/dist/libs/signstack/base/schemas/asset.schema.json +220 -0
  150. package/dist/libs/signstack/base/schemas/blueprint.schema.json +485 -0
  151. package/dist/libs/signstack/base/schemas/jsonata-function.schema.json +185 -0
  152. package/dist/libs/signstack/base/schemas/schema.schema.json +97 -0
  153. package/dist/libs/signstack/base/schemas/template.schema.json +295 -0
  154. package/dist/libs/signstack/base/src/index.d.ts +28 -0
  155. package/dist/libs/signstack/base/src/index.js +32 -0
  156. package/dist/libs/signstack/base/src/index.js.map +1 -0
  157. package/dist/libs/signstack/base/src/lib/constants.d.ts +123 -0
  158. package/dist/libs/signstack/base/src/lib/constants.js +131 -0
  159. package/dist/libs/signstack/base/src/lib/constants.js.map +1 -0
  160. package/dist/libs/signstack/base/src/lib/hash.util.d.ts +58 -0
  161. package/dist/libs/signstack/base/src/lib/hash.util.js +90 -0
  162. package/dist/libs/signstack/base/src/lib/hash.util.js.map +1 -0
  163. package/dist/libs/signstack/base/src/lib/is-schema-renderable.util.d.ts +29 -0
  164. package/dist/libs/signstack/base/src/lib/is-schema-renderable.util.js +93 -0
  165. package/dist/libs/signstack/base/src/lib/is-schema-renderable.util.js.map +1 -0
  166. package/dist/libs/signstack/base/src/lib/models/ai-chat.d.ts +41 -0
  167. package/dist/libs/signstack/base/src/lib/models/ai-chat.js +3 -0
  168. package/dist/libs/signstack/base/src/lib/models/ai-chat.js.map +1 -0
  169. package/dist/libs/signstack/base/src/lib/models/api-key.d.ts +54 -0
  170. package/dist/libs/signstack/base/src/lib/models/api-key.js +18 -0
  171. package/dist/libs/signstack/base/src/lib/models/api-key.js.map +1 -0
  172. package/dist/libs/signstack/base/src/lib/models/asset.d.ts +101 -0
  173. package/dist/libs/signstack/base/src/lib/models/asset.js +11 -0
  174. package/dist/libs/signstack/base/src/lib/models/asset.js.map +1 -0
  175. package/dist/libs/signstack/base/src/lib/models/auth.d.ts +142 -0
  176. package/dist/libs/signstack/base/src/lib/models/auth.js +35 -0
  177. package/dist/libs/signstack/base/src/lib/models/auth.js.map +1 -0
  178. package/dist/libs/signstack/base/src/lib/models/base.d.ts +134 -0
  179. package/dist/libs/signstack/base/src/lib/models/base.js +71 -0
  180. package/dist/libs/signstack/base/src/lib/models/base.js.map +1 -0
  181. package/dist/libs/signstack/base/src/lib/models/blueprint.d.ts +311 -0
  182. package/dist/libs/signstack/base/src/lib/models/blueprint.js +9 -0
  183. package/dist/libs/signstack/base/src/lib/models/blueprint.js.map +1 -0
  184. package/dist/libs/signstack/base/src/lib/models/file.d.ts +75 -0
  185. package/dist/libs/signstack/base/src/lib/models/file.js +9 -0
  186. package/dist/libs/signstack/base/src/lib/models/file.js.map +1 -0
  187. package/dist/libs/signstack/base/src/lib/models/jsonata-function.d.ts +111 -0
  188. package/dist/libs/signstack/base/src/lib/models/jsonata-function.js +19 -0
  189. package/dist/libs/signstack/base/src/lib/models/jsonata-function.js.map +1 -0
  190. package/dist/libs/signstack/base/src/lib/models/marketplace-listing.d.ts +132 -0
  191. package/dist/libs/signstack/base/src/lib/models/marketplace-listing.js +22 -0
  192. package/dist/libs/signstack/base/src/lib/models/marketplace-listing.js.map +1 -0
  193. package/dist/libs/signstack/base/src/lib/models/membership.d.ts +127 -0
  194. package/dist/libs/signstack/base/src/lib/models/membership.js +22 -0
  195. package/dist/libs/signstack/base/src/lib/models/membership.js.map +1 -0
  196. package/dist/libs/signstack/base/src/lib/models/namespace.d.ts +87 -0
  197. package/dist/libs/signstack/base/src/lib/models/namespace.js +57 -0
  198. package/dist/libs/signstack/base/src/lib/models/namespace.js.map +1 -0
  199. package/dist/libs/signstack/base/src/lib/models/organization.d.ts +79 -0
  200. package/dist/libs/signstack/base/src/lib/models/organization.js +41 -0
  201. package/dist/libs/signstack/base/src/lib/models/organization.js.map +1 -0
  202. package/dist/libs/signstack/base/src/lib/models/render-job.d.ts +88 -0
  203. package/dist/libs/signstack/base/src/lib/models/render-job.js +3 -0
  204. package/dist/libs/signstack/base/src/lib/models/render-job.js.map +1 -0
  205. package/dist/libs/signstack/base/src/lib/models/resource-edge.d.ts +60 -0
  206. package/dist/libs/signstack/base/src/lib/models/resource-edge.js +202 -0
  207. package/dist/libs/signstack/base/src/lib/models/resource-edge.js.map +1 -0
  208. package/dist/libs/signstack/base/src/lib/models/scenario.d.ts +138 -0
  209. package/dist/libs/signstack/base/src/lib/models/scenario.js +14 -0
  210. package/dist/libs/signstack/base/src/lib/models/scenario.js.map +1 -0
  211. package/dist/libs/signstack/base/src/lib/models/schema.d.ts +131 -0
  212. package/dist/libs/signstack/base/src/lib/models/schema.js +44 -0
  213. package/dist/libs/signstack/base/src/lib/models/schema.js.map +1 -0
  214. package/dist/libs/signstack/base/src/lib/models/shareable-link.d.ts +215 -0
  215. package/dist/libs/signstack/base/src/lib/models/shareable-link.js +27 -0
  216. package/dist/libs/signstack/base/src/lib/models/shareable-link.js.map +1 -0
  217. package/dist/libs/signstack/base/src/lib/models/subscription.d.ts +279 -0
  218. package/dist/libs/signstack/base/src/lib/models/subscription.js +105 -0
  219. package/dist/libs/signstack/base/src/lib/models/subscription.js.map +1 -0
  220. package/dist/libs/signstack/base/src/lib/models/template.d.ts +248 -0
  221. package/dist/libs/signstack/base/src/lib/models/template.js +32 -0
  222. package/dist/libs/signstack/base/src/lib/models/template.js.map +1 -0
  223. package/dist/libs/signstack/base/src/lib/models/user.d.ts +30 -0
  224. package/dist/libs/signstack/base/src/lib/models/user.js +3 -0
  225. package/dist/libs/signstack/base/src/lib/models/user.js.map +1 -0
  226. package/dist/libs/signstack/base/src/lib/models/webhook.d.ts +223 -0
  227. package/dist/libs/signstack/base/src/lib/models/webhook.js +62 -0
  228. package/dist/libs/signstack/base/src/lib/models/webhook.js.map +1 -0
  229. package/dist/libs/signstack/base/src/lib/models/workflow.d.ts +917 -0
  230. package/dist/libs/signstack/base/src/lib/models/workflow.js +152 -0
  231. package/dist/libs/signstack/base/src/lib/models/workflow.js.map +1 -0
  232. package/dist/libs/signstack/base/src/lib/util.d.ts +92 -0
  233. package/dist/libs/signstack/base/src/lib/util.js +406 -0
  234. package/dist/libs/signstack/base/src/lib/util.js.map +1 -0
  235. package/dist/libs/signstack/base/src/lib/validation/dependency-graph.d.ts +94 -0
  236. package/dist/libs/signstack/base/src/lib/validation/dependency-graph.js +446 -0
  237. package/dist/libs/signstack/base/src/lib/validation/dependency-graph.js.map +1 -0
  238. package/dist/libs/signstack/base/src/lib/validation/graph.types.d.ts +57 -0
  239. package/dist/libs/signstack/base/src/lib/validation/graph.types.js +8 -0
  240. package/dist/libs/signstack/base/src/lib/validation/graph.types.js.map +1 -0
  241. package/dist/libs/signstack/base/src/lib/validation/index.d.ts +9 -0
  242. package/dist/libs/signstack/base/src/lib/validation/index.js +23 -0
  243. package/dist/libs/signstack/base/src/lib/validation/index.js.map +1 -0
  244. package/dist/libs/signstack/base/src/lib/validation/resource-schemas.d.ts +3 -0
  245. package/dist/libs/signstack/base/src/lib/validation/resource-schemas.js +27 -0
  246. package/dist/libs/signstack/base/src/lib/validation/resource-schemas.js.map +1 -0
  247. package/dist/libs/signstack/base/src/lib/validation/schema-validation.types.d.ts +57 -0
  248. package/dist/libs/signstack/base/src/lib/validation/schema-validation.types.js +57 -0
  249. package/dist/libs/signstack/base/src/lib/validation/schema-validation.types.js.map +1 -0
  250. package/dist/libs/signstack/base/src/lib/validation/schema-validator.d.ts +38 -0
  251. package/dist/libs/signstack/base/src/lib/validation/schema-validator.js +146 -0
  252. package/dist/libs/signstack/base/src/lib/validation/schema-validator.js.map +1 -0
  253. package/dist/libs/signstack/base/src/lib/validation/validate-dependencies.d.ts +22 -0
  254. package/dist/libs/signstack/base/src/lib/validation/validate-dependencies.js +69 -0
  255. package/dist/libs/signstack/base/src/lib/validation/validate-dependencies.js.map +1 -0
  256. package/dist/libs/signstack/base/src/lib/validation/validate-resource-tree.d.ts +37 -0
  257. package/dist/libs/signstack/base/src/lib/validation/validate-resource-tree.js +250 -0
  258. package/dist/libs/signstack/base/src/lib/validation/validate-resource-tree.js.map +1 -0
  259. package/dist/libs/signstack/base/src/lib/validation/validate-template-inputs.d.ts +24 -0
  260. package/dist/libs/signstack/base/src/lib/validation/validate-template-inputs.js +98 -0
  261. package/dist/libs/signstack/base/src/lib/validation/validate-template-inputs.js.map +1 -0
  262. package/dist/libs/signstack/base/src/lib/validation/yaml-document-utils.d.ts +12 -0
  263. package/dist/libs/signstack/base/src/lib/validation/yaml-document-utils.js +50 -0
  264. package/dist/libs/signstack/base/src/lib/validation/yaml-document-utils.js.map +1 -0
  265. package/dist/libs/signstack/base/src/lib/yaml-spec-converter.d.ts +101 -0
  266. package/dist/libs/signstack/base/src/lib/yaml-spec-converter.js +998 -0
  267. package/dist/libs/signstack/base/src/lib/yaml-spec-converter.js.map +1 -0
  268. package/oclif.manifest.json +822 -0
  269. package/package.json +101 -0
@@ -0,0 +1,800 @@
1
+ import { AssetType, parseResourceId, ResourceKind, } from '@signstack/base';
2
+ import { SchemaKind } from '../types/schema.types.js';
3
+ import { YamlWriter } from './yaml-writer.js';
4
+ /** Org-scoped pull source — uses authenticated org/namespace endpoints. */
5
+ export class OrgPullSource {
6
+ orgId;
7
+ nsKey;
8
+ constructor(orgId, nsKey) {
9
+ this.orgId = orgId;
10
+ this.nsKey = nsKey;
11
+ }
12
+ buildDependencyTreeUrl(kind, key, version) {
13
+ return `/v1/orgs/${this.orgId}/namespaces/${this.nsKey}/resource-edges/${encodeURIComponent(kind)}/${encodeURIComponent(key)}/${encodeURIComponent(version)}/depends-on?transitive=true`;
14
+ }
15
+ buildResourceUrl(kind, key, version) {
16
+ const endpoint = KIND_TO_ENDPOINT[kind];
17
+ return `/v1/orgs/${this.orgId}/namespaces/${this.nsKey}/${endpoint}/${key}?version=${version}`;
18
+ }
19
+ async fetchFileDownloadUrl(client, fileId) {
20
+ const file = await client.get(`/v1/orgs/${this.orgId}/files/${fileId}`);
21
+ return file.downloadUrl;
22
+ }
23
+ }
24
+ /**
25
+ * Public library pull source — scoped by the listing that's being pulled. All
26
+ * URLs are keyed by the listing (`listingKey@listingVersion`), not the
27
+ * underlying resource. Sub-resources are fetched through the listing so the
28
+ * backend can authorize access once at the listing level. No auth required.
29
+ */
30
+ export class LibraryPullSource {
31
+ listingKey;
32
+ listingVersion;
33
+ constructor(listingKey, listingVersion) {
34
+ this.listingKey = listingKey;
35
+ this.listingVersion = listingVersion;
36
+ }
37
+ get _prefix() {
38
+ return `/v1/library/listings/by-key/${encodeURIComponent(this.listingKey)}/${encodeURIComponent(this.listingVersion)}`;
39
+ }
40
+ // The dependency tree is per-listing (the listing knows its root resource
41
+ // and transitive deps), so the `kind`/`key`/`version` args are ignored.
42
+ buildDependencyTreeUrl() {
43
+ return `${this._prefix}/dependencies`;
44
+ }
45
+ buildResourceUrl(kind, key, version) {
46
+ const endpoint = KIND_TO_ENDPOINT[kind];
47
+ return `${this._prefix}/${endpoint}/${encodeURIComponent(key)}?resourceVersion=${encodeURIComponent(version)}`;
48
+ }
49
+ async fetchFileDownloadUrl(client, fileId) {
50
+ const resp = await client.get(`${this._prefix}/files/${encodeURIComponent(fileId)}/signed-url`);
51
+ return resp.url;
52
+ }
53
+ }
54
+ /** Map backend ResourceKind to CLI SchemaKind */
55
+ const BACKEND_TO_SCHEMA_KIND = {
56
+ [ResourceKind.Blueprint]: SchemaKind.Blueprint,
57
+ [ResourceKind.Template]: SchemaKind.Template,
58
+ [ResourceKind.Schema]: SchemaKind.Schema,
59
+ [ResourceKind.Asset]: SchemaKind.Asset,
60
+ [ResourceKind.JsonataFunction]: SchemaKind.JsonataFunction,
61
+ };
62
+ /** Map CLI SchemaKind to backend ResourceKind */
63
+ export const SCHEMA_KIND_TO_BACKEND = {
64
+ [SchemaKind.Blueprint]: ResourceKind.Blueprint,
65
+ [SchemaKind.Template]: ResourceKind.Template,
66
+ [SchemaKind.Schema]: ResourceKind.Schema,
67
+ [SchemaKind.Asset]: ResourceKind.Asset,
68
+ [SchemaKind.JsonataFunction]: ResourceKind.JsonataFunction,
69
+ };
70
+ /** Map backend ResourceKind to API endpoint path segment */
71
+ export const KIND_TO_ENDPOINT = {
72
+ [ResourceKind.Blueprint]: 'blueprints',
73
+ [ResourceKind.Template]: 'templates',
74
+ [ResourceKind.Schema]: 'schemas',
75
+ [ResourceKind.Asset]: 'assets',
76
+ [ResourceKind.JsonataFunction]: 'jsonata-functions',
77
+ };
78
+ /** Default file extensions by asset type */
79
+ const ASSET_TYPE_EXT = {
80
+ [AssetType.Pdf]: '.pdf',
81
+ [AssetType.Image]: '.png',
82
+ [AssetType.Html]: '.hbs',
83
+ [AssetType.Css]: '.css',
84
+ };
85
+ /** Content-Type to file extension reverse map */
86
+ const CONTENT_TYPE_TO_EXT = {
87
+ 'image/png': '.png',
88
+ 'image/jpeg': '.jpg',
89
+ 'image/gif': '.gif',
90
+ 'image/svg+xml': '.svg',
91
+ 'image/webp': '.webp',
92
+ 'application/pdf': '.pdf',
93
+ };
94
+ const CONCURRENCY_LIMIT = 5;
95
+ const API_VERSION = 'signstack/v1beta2';
96
+ /**
97
+ * ResourcePuller — Fetches SignStack resources from the API and converts them to YAML files.
98
+ *
99
+ * This is the inverse of ResourcePusher. It:
100
+ * 1. Fetches the dependency tree for a resource
101
+ * 2. Downloads each dependent resource
102
+ * 3. Converts API responses to YAML format
103
+ * 4. Downloads binary files for assets with fileIds
104
+ * 5. Writes everything to a local folder structure
105
+ */
106
+ export class ResourcePuller {
107
+ client;
108
+ source;
109
+ log;
110
+ constructor(client, source, log) {
111
+ this.client = client;
112
+ this.source = source;
113
+ this.log = log;
114
+ }
115
+ /**
116
+ * Pull a resource and all its dependencies from the API.
117
+ */
118
+ async pull(params) {
119
+ const { kind, key, version, outputDir, verbose } = params;
120
+ // Step 1: Fetch dependency tree
121
+ if (verbose) {
122
+ this.log(`Fetching dependency tree for ${kind}:${key}@${version}...`);
123
+ }
124
+ const resourceIds = await this.fetchAllDependencyIds(kind, key, version);
125
+ this.log(`Found ${resourceIds.size} dependencies (including root)`);
126
+ // Build a lookup map from "kind:key" -> version, so converters can resolve
127
+ // missing schemaVersion fields that the API sometimes omits.
128
+ const versionByKindAndKey = new Map();
129
+ for (const id of resourceIds) {
130
+ const { kind: k, key: rk, version: rv } = parseResourceId(id);
131
+ versionByKindAndKey.set(`${k}:${rk}`, rv);
132
+ }
133
+ // Step 2: Create output directory structure
134
+ const writer = new YamlWriter(outputDir);
135
+ writer.ensureDirectories();
136
+ // Step 3: Fetch and convert each resource
137
+ const results = [];
138
+ const byKind = {};
139
+ const resourceIdArray = Array.from(resourceIds);
140
+ // Process in batches for concurrency
141
+ for (let i = 0; i < resourceIdArray.length; i += CONCURRENCY_LIMIT) {
142
+ const batch = resourceIdArray.slice(i, i + CONCURRENCY_LIMIT);
143
+ const batchResults = await Promise.all(batch.map((id) => this.pullSingleResource(id, writer, verbose, versionByKindAndKey)));
144
+ for (const result of batchResults) {
145
+ results.push(result);
146
+ if (result.success) {
147
+ byKind[result.kind] = (byKind[result.kind] ?? 0) + 1;
148
+ }
149
+ }
150
+ }
151
+ const succeeded = results.filter((r) => r.success).length;
152
+ const failed = results.filter((r) => !r.success).length;
153
+ return {
154
+ outputDir,
155
+ total: results.length,
156
+ succeeded,
157
+ failed,
158
+ results,
159
+ byKind,
160
+ };
161
+ }
162
+ /**
163
+ * Fetch the transitive dependency tree and collect all unique resource IDs.
164
+ * Also includes the root resource itself.
165
+ */
166
+ async fetchAllDependencyIds(kind, key, version) {
167
+ const rootId = `${kind}:${key}@${version}`;
168
+ const ids = new Set();
169
+ ids.add(rootId);
170
+ try {
171
+ const url = this.source.buildDependencyTreeUrl(kind, key, version);
172
+ const resp = await this.client.get(url);
173
+ if (resp.tree) {
174
+ this.flattenTree(resp.tree, ids);
175
+ }
176
+ }
177
+ catch (error) {
178
+ this.log(`Warning: Could not fetch dependency tree for ${rootId}: ${error.message}`);
179
+ }
180
+ return ids;
181
+ }
182
+ /**
183
+ * Recursively flatten a dependency tree into a set of resource IDs.
184
+ * Handles both org format ({ resourceId }) and library format ({ kind, key, version }).
185
+ */
186
+ flattenTree(node, ids) {
187
+ if ('resourceId' in node) {
188
+ ids.add(node.resourceId);
189
+ }
190
+ else {
191
+ ids.add(`${node.kind}:${node.key}@${node.version}`);
192
+ }
193
+ for (const child of node.children ?? []) {
194
+ this.flattenTree(child, ids);
195
+ }
196
+ }
197
+ /**
198
+ * Pull a single resource: fetch from API, convert to YAML, write files.
199
+ */
200
+ async pullSingleResource(resourceId, writer, verbose, versionByKindAndKey) {
201
+ const { kind: backendKind, key, version } = parseResourceId(resourceId);
202
+ const schemaKind = BACKEND_TO_SCHEMA_KIND[backendKind];
203
+ if (!schemaKind) {
204
+ return {
205
+ resourceId,
206
+ kind: SchemaKind.Schema, // fallback
207
+ key,
208
+ version,
209
+ success: false,
210
+ error: `Unknown resource kind: ${backendKind}`,
211
+ };
212
+ }
213
+ const baseResult = {
214
+ resourceId,
215
+ kind: schemaKind,
216
+ key,
217
+ version,
218
+ success: false,
219
+ };
220
+ try {
221
+ const path = this.source.buildResourceUrl(backendKind, key, version);
222
+ const resp = await this.client.get(path);
223
+ const { yamlDoc, additionalFiles } = await this.convertResource(schemaKind, key, version, resp, writer, versionByKindAndKey);
224
+ const yamlPath = writer.writeYaml(schemaKind, key, yamlDoc);
225
+ if (verbose) {
226
+ this.log(` ${schemaKind}:${key}@${version} -> ${yamlPath}`);
227
+ }
228
+ return {
229
+ ...baseResult,
230
+ success: true,
231
+ yamlPath,
232
+ additionalFiles,
233
+ };
234
+ }
235
+ catch (error) {
236
+ const errMsg = error.message;
237
+ if (verbose) {
238
+ this.log(` Failed: ${schemaKind}:${key}@${version} - ${errMsg}`);
239
+ }
240
+ return { ...baseResult, error: errMsg };
241
+ }
242
+ }
243
+ /**
244
+ * Convert an API response to a YAML document object.
245
+ * Also writes any additional files (JSON definitions, HTML/CSS content, binary files).
246
+ */
247
+ async convertResource(kind, key, version, resp, writer, versionByKindAndKey) {
248
+ switch (kind) {
249
+ case SchemaKind.Schema:
250
+ return this.convertSchema(key, resp, writer);
251
+ case SchemaKind.Asset:
252
+ return this.convertAsset(key, resp, writer);
253
+ case SchemaKind.Template:
254
+ return this.convertTemplateWithAssetStub(key, version, resp, writer, versionByKindAndKey);
255
+ case SchemaKind.Blueprint:
256
+ return {
257
+ yamlDoc: this.convertBlueprint(resp, versionByKindAndKey),
258
+ additionalFiles: [],
259
+ };
260
+ case SchemaKind.JsonataFunction:
261
+ return {
262
+ yamlDoc: this.convertJsonataFunction(resp, versionByKindAndKey),
263
+ additionalFiles: [],
264
+ };
265
+ default:
266
+ throw new Error(`Unknown resource kind: ${kind}`);
267
+ }
268
+ }
269
+ // ─── Schema Conversion ────────────────────────────────────────
270
+ convertSchema(key, resp, writer) {
271
+ const additionalFiles = [];
272
+ // Write JSON schema definition to file
273
+ const filePath = writer.writeJsonDefinition(key, resp.spec.schemaDefinition);
274
+ additionalFiles.push(filePath);
275
+ const yamlDoc = {
276
+ apiVersion: API_VERSION,
277
+ kind: 'Schema',
278
+ metadata: buildMetadata(resp.metadata),
279
+ spec: {
280
+ jsonSchemaDraft: resp.spec.jsonSchemaDraft,
281
+ file: filePath,
282
+ },
283
+ };
284
+ return { yamlDoc, additionalFiles };
285
+ }
286
+ // ─── Asset Conversion ─────────────────────────────────────────
287
+ async convertAsset(key, resp, writer) {
288
+ const additionalFiles = [];
289
+ const spec = {
290
+ type: resp.spec.type,
291
+ };
292
+ // Handle file content based on asset type
293
+ if (resp.spec.type === AssetType.Html || resp.spec.type === AssetType.Css) {
294
+ // Text assets: write content to file
295
+ if (resp.spec.content) {
296
+ const subdir = resp.spec.type === AssetType.Html ? 'html' : 'css';
297
+ const ext = ASSET_TYPE_EXT[resp.spec.type] ?? '.txt';
298
+ const filename = `${key}${ext}`;
299
+ const filePath = writer.writeTextContent(subdir, filename, resp.spec.content);
300
+ spec.file = filePath;
301
+ additionalFiles.push(filePath);
302
+ }
303
+ }
304
+ else if (resp.spec.type === AssetType.Pdf ||
305
+ resp.spec.type === AssetType.Image) {
306
+ // Binary assets: download via signed URL
307
+ if (resp.spec.fileId) {
308
+ try {
309
+ const signedUrl = await this.getSignedUrl(resp.spec.fileId);
310
+ const ext = await this.getFileExtension(resp.spec.type, signedUrl);
311
+ const filePath = await writer.downloadBinaryFile(key, ext, signedUrl);
312
+ spec.file = filePath;
313
+ additionalFiles.push(filePath);
314
+ }
315
+ catch (error) {
316
+ // Log but don't fail the entire resource
317
+ this.log(` Warning: Could not download file for asset ${key} (fileId: ${resp.spec.fileId}): ${error.message}`);
318
+ }
319
+ }
320
+ }
321
+ // Handle HTML config references
322
+ if (resp.spec.htmlConfig) {
323
+ this.convertHtmlConfig(resp.spec.htmlConfig, spec);
324
+ }
325
+ const yamlDoc = {
326
+ apiVersion: API_VERSION,
327
+ kind: 'Asset',
328
+ metadata: buildMetadata(resp.metadata),
329
+ spec,
330
+ };
331
+ return { yamlDoc, additionalFiles };
332
+ }
333
+ /**
334
+ * Convert API htmlConfig refs back to YAML format.
335
+ */
336
+ convertHtmlConfig(config, spec) {
337
+ // Partials: [{key, version, alias}] -> { alias: "key@version" }
338
+ if (config.partials && config.partials.length > 0) {
339
+ const partials = {};
340
+ for (const p of config.partials) {
341
+ partials[p.alias] = `${p.key}@${p.version}`;
342
+ }
343
+ spec.partials = partials;
344
+ }
345
+ // Styles: [{key, version}] -> ["key@version"]
346
+ if (config.styles && config.styles.length > 0) {
347
+ spec.styles = config.styles.map((s) => `${s.key}@${s.version}`);
348
+ }
349
+ // Images: [{key, version, alias}] -> { alias: "key@version" }
350
+ if (config.images && config.images.length > 0) {
351
+ const images = {};
352
+ for (const img of config.images) {
353
+ images[img.alias] = `${img.key}@${img.version}`;
354
+ }
355
+ spec.images = images;
356
+ }
357
+ // ViewModel schema
358
+ if (config.data?.schemaKey) {
359
+ spec.data = {
360
+ schema: toRef(config.data.schemaKey, config.data.schemaVersion),
361
+ };
362
+ }
363
+ // PDF settings
364
+ if (config.pdfSettings) {
365
+ spec.pdfSettings = config.pdfSettings;
366
+ }
367
+ }
368
+ // ─── Template Conversion ──────────────────────────────────────
369
+ /**
370
+ * Convert a template and, when contentKey was absent from the API response
371
+ * (supplement templates like exhibit_a_nwmls), also write a stub asset YAML
372
+ * so that --resolve local preview can find the content dependency.
373
+ */
374
+ convertTemplateWithAssetStub(key, version, resp, writer, versionByKindAndKey) {
375
+ const additionalFiles = [];
376
+ const yamlDoc = this.convertTemplate(resp, versionByKindAndKey);
377
+ // When contentKey was absent from the API, write a stub asset so that
378
+ // --resolve local preview can resolve the content reference.
379
+ if (!resp.spec.contentKey && resp.spec.type === 'pdf') {
380
+ const assetVersion = resp.metadata.version;
381
+ const stubAsset = {
382
+ apiVersion: API_VERSION,
383
+ kind: 'Asset',
384
+ metadata: {
385
+ key,
386
+ version: assetVersion,
387
+ name: key,
388
+ },
389
+ spec: {
390
+ type: 'pdf',
391
+ file: `./${key}.pdf`,
392
+ },
393
+ };
394
+ const assetPath = writer.writeYaml(SchemaKind.Asset, key, stubAsset);
395
+ writer.writePlaceholderPdf(key);
396
+ this.log(` Warning: template ${key}@${version} had no contentKey — wrote stub asset at ${assetPath}`);
397
+ additionalFiles.push(assetPath);
398
+ }
399
+ return { yamlDoc, additionalFiles };
400
+ }
401
+ convertTemplate(resp, versionByKindAndKey) {
402
+ const spec = {
403
+ type: resp.spec.type,
404
+ };
405
+ // Content reference — required for pdf templates.
406
+ // Fall back to the template's own key/version when the API omits contentKey
407
+ // or contentVersion (observed for supplement templates like exhibit_a_nwmls).
408
+ const contentKey = resp.spec.contentKey ||
409
+ (resp.spec.type === 'pdf' ? resp.metadata.key : undefined);
410
+ const contentVersion = resp.spec.contentVersion || resp.metadata.version;
411
+ if (contentKey) {
412
+ spec.content = toRef(contentKey, contentVersion);
413
+ }
414
+ // Inputs
415
+ if (resp.spec.inputs && resp.spec.inputs.length > 0) {
416
+ spec.inputs = resp.spec.inputs.map((i) => convertInputToYaml(i, versionByKindAndKey));
417
+ }
418
+ // Roles
419
+ if (resp.spec.roles && resp.spec.roles.length > 0) {
420
+ spec.roles = resp.spec.roles.map(convertRoleToYaml);
421
+ }
422
+ // Fields
423
+ if (resp.spec.fields && resp.spec.fields.length > 0) {
424
+ spec.fields = resp.spec.fields.map(convertFieldToYaml);
425
+ }
426
+ // Data transform
427
+ if (resp.spec.data?.transform) {
428
+ spec.data = { transform: resp.spec.data.transform };
429
+ }
430
+ if (resp.spec.functions && resp.spec.functions.length > 0) {
431
+ spec.functions = convertFunctionsToYaml(resp.spec.functions);
432
+ }
433
+ return {
434
+ apiVersion: API_VERSION,
435
+ kind: 'Template',
436
+ metadata: buildMetadata(resp.metadata),
437
+ spec,
438
+ };
439
+ }
440
+ // ─── Blueprint Conversion ─────────────────────────────────────
441
+ convertBlueprint(resp, versionByKindAndKey) {
442
+ const spec = {};
443
+ // Inputs
444
+ if (resp.spec.inputs && resp.spec.inputs.length > 0) {
445
+ spec.inputs = resp.spec.inputs.map((i) => convertInputToYaml(i, versionByKindAndKey));
446
+ }
447
+ // Participants
448
+ if (resp.spec.participants && resp.spec.participants.length > 0) {
449
+ spec.participants = resp.spec.participants.map(convertParticipantToYaml);
450
+ }
451
+ // Envelopes
452
+ if (resp.spec.envelopes && resp.spec.envelopes.length > 0) {
453
+ spec.envelopes = resp.spec.envelopes.map(convertEnvelopeToYaml);
454
+ }
455
+ if (resp.spec.functions && resp.spec.functions.length > 0) {
456
+ spec.functions = convertFunctionsToYaml(resp.spec.functions);
457
+ }
458
+ // Orchestration
459
+ if (resp.spec.orchestration) {
460
+ spec.orchestration = convertOrchestrationToYaml(resp.spec.orchestration);
461
+ }
462
+ return {
463
+ apiVersion: API_VERSION,
464
+ kind: 'Blueprint',
465
+ metadata: buildMetadata(resp.metadata),
466
+ spec,
467
+ };
468
+ }
469
+ // ─── JsonataFunction Conversion ───────────────────────────────
470
+ convertJsonataFunction(resp, versionByKindAndKey) {
471
+ const spec = {};
472
+ if (resp.spec.params && resp.spec.params.length > 0) {
473
+ spec.params = resp.spec.params.map((p) => {
474
+ const param = {
475
+ name: p.name,
476
+ type: p.type,
477
+ };
478
+ if (p.schemaKey) {
479
+ param.schema = toRef(p.schemaKey, resolveVersion(ResourceKind.Schema, p.schemaKey, p.schemaVersion, versionByKindAndKey));
480
+ }
481
+ return param;
482
+ });
483
+ }
484
+ if (resp.spec.returnType) {
485
+ const rt = {
486
+ type: resp.spec.returnType.type,
487
+ };
488
+ if (resp.spec.returnType.schemaKey) {
489
+ rt.schema = toRef(resp.spec.returnType.schemaKey, resolveVersion(ResourceKind.Schema, resp.spec.returnType.schemaKey, resp.spec.returnType.schemaVersion, versionByKindAndKey));
490
+ }
491
+ spec.returnType = rt;
492
+ }
493
+ if (resp.spec.body) {
494
+ spec.body = resp.spec.body;
495
+ }
496
+ return {
497
+ apiVersion: API_VERSION,
498
+ kind: 'JsonataFunction',
499
+ metadata: buildMetadata(resp.metadata),
500
+ spec,
501
+ };
502
+ }
503
+ // ─── File Download Helpers ────────────────────────────────────
504
+ /**
505
+ * Get a signed download URL for a file.
506
+ */
507
+ async getSignedUrl(fileId) {
508
+ return this.source.fetchFileDownloadUrl(this.client, fileId);
509
+ }
510
+ /**
511
+ * Determine file extension by making a HEAD request to the signed URL.
512
+ * Falls back to the default extension for the asset type if the Content-Type
513
+ * is unrecognized or the request fails.
514
+ */
515
+ async getFileExtension(assetType, signedUrl) {
516
+ try {
517
+ const response = await fetch(signedUrl, { method: 'HEAD' });
518
+ if (response.ok) {
519
+ const contentType = response.headers.get('content-type');
520
+ // Strip parameters like "; charset=utf-8" before lookup
521
+ const mimeType = contentType?.split(';')[0].trim();
522
+ if (mimeType && CONTENT_TYPE_TO_EXT[mimeType]) {
523
+ return CONTENT_TYPE_TO_EXT[mimeType];
524
+ }
525
+ }
526
+ }
527
+ catch {
528
+ // Fall through to default
529
+ }
530
+ return ASSET_TYPE_EXT[assetType] ?? '.bin';
531
+ }
532
+ }
533
+ // ─── Shared Conversion Helpers ────────────────────────────────
534
+ /**
535
+ * Resolve a version for a resource, falling back to the dependency map when
536
+ * the API omits schemaVersion (it's an optional field on Input).
537
+ */
538
+ function resolveVersion(kind, key, version, versionByKindAndKey) {
539
+ return version || versionByKindAndKey.get(`${kind}:${key}`);
540
+ }
541
+ /** Combine key and version into "key@version" reference */
542
+ function toRef(key, version) {
543
+ if (!key)
544
+ return undefined;
545
+ if (!version)
546
+ return key;
547
+ return `${key}@${version}`;
548
+ }
549
+ /** Build the YAML metadata block, omitting undefined fields */
550
+ function buildMetadata(metadata) {
551
+ const result = {
552
+ key: metadata.key,
553
+ version: metadata.version,
554
+ };
555
+ if (metadata.name)
556
+ result.name = metadata.name;
557
+ if (metadata.description)
558
+ result.description = metadata.description;
559
+ if (metadata.labels && Object.keys(metadata.labels).length > 0) {
560
+ // Label keys must match ^[a-z][a-z0-9]*(_[a-z0-9]+)*$ — sanitize by
561
+ // converting camelCase and any invalid chars to snake_case.
562
+ const sanitized = {};
563
+ for (const [k, v] of Object.entries(metadata.labels)) {
564
+ const safe = k
565
+ .replace(/([A-Z])/g, '_$1')
566
+ .toLowerCase()
567
+ .replace(/[^a-z0-9_]/g, '_')
568
+ .replace(/^[^a-z]+/, '')
569
+ .replace(/_+/g, '_')
570
+ .replace(/_$/, '');
571
+ if (safe)
572
+ sanitized[safe] = v;
573
+ }
574
+ if (Object.keys(sanitized).length > 0)
575
+ result.labels = sanitized;
576
+ }
577
+ return result;
578
+ }
579
+ /**
580
+ * Converts a spec.functions array to YAML form.
581
+ * Emits object-map when any entry has a distinct alias, otherwise a plain array.
582
+ */
583
+ function convertFunctionsToYaml(functions) {
584
+ const hasDistinctAlias = functions.some((f) => f.alias);
585
+ if (hasDistinctAlias) {
586
+ return functions.reduce((acc, f) => {
587
+ acc[f.alias ?? f.functionKey] = `${f.functionKey}@${f.functionVersion}`;
588
+ return acc;
589
+ }, {});
590
+ }
591
+ return functions.map((f) => `${f.functionKey}@${f.functionVersion}`);
592
+ }
593
+ /**
594
+ * Convert API LiteralOrExpression to YAML expression format.
595
+ * Both sides use { expression: "..." }, so this is effectively a passthrough
596
+ * that strips undefined/null.
597
+ */
598
+ function passthroughExpression(value) {
599
+ if (value === undefined || value === null)
600
+ return undefined;
601
+ return value;
602
+ }
603
+ /** Convert API Input to YAML input format */
604
+ function convertInputToYaml(input, versionByKindAndKey) {
605
+ const result = {
606
+ key: input.key,
607
+ };
608
+ if (input.name)
609
+ result.name = input.name;
610
+ if (input.description)
611
+ result.description = input.description;
612
+ if (input.schemaKey) {
613
+ result.schema = toRef(input.schemaKey, resolveVersion(ResourceKind.Schema, input.schemaKey, input.schemaVersion, versionByKindAndKey));
614
+ }
615
+ if (typeof input.required === 'boolean') {
616
+ result.required = input.required;
617
+ }
618
+ else if (input.required &&
619
+ typeof input.required === 'object' &&
620
+ 'expression' in input.required) {
621
+ result.required = input.required.expression;
622
+ }
623
+ return result;
624
+ }
625
+ /** Convert API TemplateRole to YAML role format */
626
+ function convertRoleToYaml(role) {
627
+ const result = {
628
+ key: role.key,
629
+ };
630
+ if (role.name)
631
+ result.name = role.name;
632
+ if (role.roleCategory)
633
+ result.roleCategory = role.roleCategory;
634
+ if (role.output) {
635
+ result.output = {
636
+ schema: toRef(role.output.schemaKey, role.output.schemaVersion),
637
+ transform: role.output.transform,
638
+ };
639
+ }
640
+ return result;
641
+ }
642
+ /** Convert API TemplateFieldInfo to YAML field format */
643
+ function convertFieldToYaml(field) {
644
+ const result = {
645
+ key: field.key,
646
+ type: field.type,
647
+ };
648
+ // Value (LiteralOrExpression)
649
+ const yamlValue = passthroughExpression(field.value);
650
+ if (yamlValue !== undefined)
651
+ result.value = yamlValue;
652
+ // Role
653
+ if (field.role)
654
+ result.role = field.role;
655
+ // includeIf
656
+ if (field.includeIf)
657
+ result.includeIf = field.includeIf;
658
+ // Widget (flatten from widgets[0])
659
+ if (field.widgets && field.widgets.length > 0) {
660
+ const w = field.widgets[0];
661
+ const widget = {};
662
+ if (w.position) {
663
+ widget.page = w.position.pageNumber;
664
+ widget.x = w.position.x;
665
+ widget.y = w.position.y;
666
+ }
667
+ if (w.dimensions) {
668
+ widget.width = w.dimensions.width;
669
+ widget.height = w.dimensions.height;
670
+ }
671
+ if (w.style) {
672
+ const style = {};
673
+ if (w.style.fontSizePx !== undefined)
674
+ style.fontSize = w.style.fontSizePx;
675
+ if (w.style.fontColor)
676
+ style.fontColor = w.style.fontColor;
677
+ if (w.style.fontFamily)
678
+ style.fontFamily = w.style.fontFamily;
679
+ if (w.style.strokeWidth !== undefined)
680
+ style.strokeWidth = w.style.strokeWidth;
681
+ if (w.style.strokeColor)
682
+ style.strokeColor = w.style.strokeColor;
683
+ if (Object.keys(style).length > 0)
684
+ widget.style = style;
685
+ }
686
+ if (Object.keys(widget).length > 0)
687
+ result.widget = widget;
688
+ }
689
+ return result;
690
+ }
691
+ /** Convert API BlueprintParticipant to YAML format */
692
+ function convertParticipantToYaml(participant) {
693
+ // Schema requires `name` and `email`; fall back to key-derived placeholders
694
+ // if the API didn't store LiteralOrExpression values for them.
695
+ const name = passthroughExpression(participant.participantName) ??
696
+ participant.name ??
697
+ participant.key;
698
+ // email must be a valid address or an { expression } object — never a freeform
699
+ // string. Use an expression placeholder when no expression was stored on the API.
700
+ const email = passthroughExpression(participant.participantEmail) ?? {
701
+ expression: `$.${participant.key}.email`,
702
+ };
703
+ const result = {
704
+ key: participant.key,
705
+ name,
706
+ email,
707
+ };
708
+ if (participant.roleCategory)
709
+ result.roleCategory = participant.roleCategory;
710
+ return result;
711
+ }
712
+ /** Convert API BlueprintEnvelope to YAML format */
713
+ function convertEnvelopeToYaml(envelope) {
714
+ const result = {
715
+ key: envelope.key,
716
+ };
717
+ if (envelope.subject && envelope.subject !== envelope.key) {
718
+ result.name = envelope.subject;
719
+ }
720
+ if (envelope.documents && envelope.documents.length > 0) {
721
+ result.documents = envelope.documents.map((doc) => {
722
+ const d = {
723
+ key: doc.key,
724
+ };
725
+ if (doc.templateKey) {
726
+ d.template = toRef(doc.templateKey, doc.templateVersion);
727
+ }
728
+ if (doc.inputMap && doc.inputMap.length > 0) {
729
+ const inputMap = {};
730
+ for (const m of doc.inputMap) {
731
+ inputMap[m.templateInputKey] = m.blueprintInputKey
732
+ ? `$.${m.blueprintInputKey}`
733
+ : m.blueprintInputKey;
734
+ }
735
+ d.inputMap = inputMap;
736
+ }
737
+ if (doc.includeIf)
738
+ d.includeIf = doc.includeIf;
739
+ if (doc.iterator)
740
+ d.iterator = doc.iterator;
741
+ const fileIdYaml = passthroughExpression(doc.fileId);
742
+ if (fileIdYaml !== undefined)
743
+ d.fileId = fileIdYaml;
744
+ return d;
745
+ });
746
+ }
747
+ return result;
748
+ }
749
+ /** Recursively convert API BlueprintStep to YAML orchestration format */
750
+ function convertOrchestrationToYaml(step) {
751
+ const result = {
752
+ key: step.key,
753
+ type: step.type,
754
+ };
755
+ if (step.name)
756
+ result.name = step.name;
757
+ if (step.includeIf)
758
+ result.includeIf = step.includeIf;
759
+ if (step.onComplete)
760
+ result.onComplete = step.onComplete;
761
+ if (step.type === 'group') {
762
+ const group = step;
763
+ if (group.execution)
764
+ result.execution = group.execution;
765
+ if (group.completion)
766
+ result.completion = group.completion;
767
+ if (group.quorum)
768
+ result.quorum = group.quorum;
769
+ if (group.children && group.children.length > 0) {
770
+ // Filter out participant steps whose action has no assignments — they
771
+ // are unrepresentable in the YAML schema (sign action requires minItems:1).
772
+ result.children = group.children
773
+ .filter((child) => {
774
+ if (child.type !== 'participant')
775
+ return true;
776
+ const p = child;
777
+ return !p.action || p.action.assignments?.length > 0;
778
+ })
779
+ .map(convertOrchestrationToYaml);
780
+ }
781
+ }
782
+ else {
783
+ const participant = step;
784
+ if (participant.participantKey) {
785
+ result.participant = participant.participantKey;
786
+ }
787
+ if (participant.action && participant.action.assignments?.length > 0) {
788
+ result.action = {
789
+ type: participant.action.type,
790
+ envelope: participant.action.envelopeKey,
791
+ assignments: participant.action.assignments.map((a) => ({
792
+ document: a.documentKey,
793
+ role: a.roleKey,
794
+ })),
795
+ };
796
+ }
797
+ }
798
+ return result;
799
+ }
800
+ //# sourceMappingURL=resource-puller.js.map