@trayai/tray-sync-cli 0.0.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 (297) hide show
  1. package/LICENSE.md +182 -0
  2. package/README.md +167 -0
  3. package/dist/api/errors.js +29 -0
  4. package/dist/api/trayClient.js +69 -0
  5. package/dist/cli.js +32 -0
  6. package/dist/commands/auth.js +103 -0
  7. package/dist/commands/env.js +534 -0
  8. package/dist/commands/init.js +115 -0
  9. package/dist/commands/project.js +175 -0
  10. package/dist/commands/promote.js +289 -0
  11. package/dist/commands/pull.js +379 -0
  12. package/dist/commands/status.js +126 -0
  13. package/dist/config/credentials.js +10 -0
  14. package/dist/config/environments.js +10 -0
  15. package/dist/config/io.js +36 -0
  16. package/dist/config/mappings.js +9 -0
  17. package/dist/config/paths.js +33 -0
  18. package/dist/config/projectConfig.js +16 -0
  19. package/dist/config/pullProgress.js +9 -0
  20. package/dist/config/state.js +9 -0
  21. package/dist/config/trayYaml.js +9 -0
  22. package/dist/config/types.js +21 -0
  23. package/dist/config/yaml.js +22 -0
  24. package/dist/lib/authDiscovery.js +76 -0
  25. package/dist/lib/checksum.js +5 -0
  26. package/dist/lib/exportStructure.js +23 -0
  27. package/dist/lib/outputFormat.js +12 -0
  28. package/dist/lib/pathContainment.js +37 -0
  29. package/dist/lib/promoteExecute.js +8 -0
  30. package/dist/lib/promoteReconstruct.js +35 -0
  31. package/dist/lib/promoteReport.js +44 -0
  32. package/dist/lib/promoteTarget.js +129 -0
  33. package/dist/lib/region.js +26 -0
  34. package/dist/lib/regionDisplay.js +11 -0
  35. package/dist/lib/regionParsing.js +12 -0
  36. package/dist/lib/scriptExtraction.js +46 -0
  37. package/dist/lib/slug.js +14 -0
  38. package/dist/lib/tokenResolution.js +19 -0
  39. package/dist/lib/uuid.js +5 -0
  40. package/dist/views/env/env.js +89 -0
  41. package/dist/views/env/shared.js +7 -0
  42. package/dist/views/init/init.js +17 -0
  43. package/dist/views/project/project.js +35 -0
  44. package/dist/views/project/shared.js +4 -0
  45. package/dist/views/promote/promote.js +44 -0
  46. package/dist/views/promote/shared.js +4 -0
  47. package/dist/views/pull/pull.js +31 -0
  48. package/dist/views/pull/shared.js +4 -0
  49. package/dist/views/shared.js +8 -0
  50. package/dist/views/status/shared.js +20 -0
  51. package/dist/views/status/status.js +23 -0
  52. package/node_modules/commander/LICENSE +22 -0
  53. package/node_modules/commander/Readme.md +1172 -0
  54. package/node_modules/commander/index.js +21 -0
  55. package/node_modules/commander/lib/argument.js +147 -0
  56. package/node_modules/commander/lib/command.js +2790 -0
  57. package/node_modules/commander/lib/error.js +36 -0
  58. package/node_modules/commander/lib/help.js +731 -0
  59. package/node_modules/commander/lib/option.js +377 -0
  60. package/node_modules/commander/lib/suggestSimilar.js +99 -0
  61. package/node_modules/commander/package-support.json +19 -0
  62. package/node_modules/commander/package.json +64 -0
  63. package/node_modules/commander/typings/index.d.ts +1113 -0
  64. package/node_modules/yaml/LICENSE +13 -0
  65. package/node_modules/yaml/README.md +172 -0
  66. package/node_modules/yaml/bin.mjs +11 -0
  67. package/node_modules/yaml/browser/dist/compose/compose-collection.js +88 -0
  68. package/node_modules/yaml/browser/dist/compose/compose-doc.js +43 -0
  69. package/node_modules/yaml/browser/dist/compose/compose-node.js +109 -0
  70. package/node_modules/yaml/browser/dist/compose/compose-scalar.js +86 -0
  71. package/node_modules/yaml/browser/dist/compose/composer.js +219 -0
  72. package/node_modules/yaml/browser/dist/compose/resolve-block-map.js +115 -0
  73. package/node_modules/yaml/browser/dist/compose/resolve-block-scalar.js +198 -0
  74. package/node_modules/yaml/browser/dist/compose/resolve-block-seq.js +49 -0
  75. package/node_modules/yaml/browser/dist/compose/resolve-end.js +37 -0
  76. package/node_modules/yaml/browser/dist/compose/resolve-flow-collection.js +207 -0
  77. package/node_modules/yaml/browser/dist/compose/resolve-flow-scalar.js +225 -0
  78. package/node_modules/yaml/browser/dist/compose/resolve-props.js +146 -0
  79. package/node_modules/yaml/browser/dist/compose/util-contains-newline.js +34 -0
  80. package/node_modules/yaml/browser/dist/compose/util-empty-scalar-position.js +26 -0
  81. package/node_modules/yaml/browser/dist/compose/util-flow-indent-check.js +15 -0
  82. package/node_modules/yaml/browser/dist/compose/util-map-includes.js +13 -0
  83. package/node_modules/yaml/browser/dist/doc/Document.js +335 -0
  84. package/node_modules/yaml/browser/dist/doc/anchors.js +71 -0
  85. package/node_modules/yaml/browser/dist/doc/applyReviver.js +55 -0
  86. package/node_modules/yaml/browser/dist/doc/createNode.js +88 -0
  87. package/node_modules/yaml/browser/dist/doc/directives.js +176 -0
  88. package/node_modules/yaml/browser/dist/errors.js +57 -0
  89. package/node_modules/yaml/browser/dist/index.js +17 -0
  90. package/node_modules/yaml/browser/dist/log.js +11 -0
  91. package/node_modules/yaml/browser/dist/nodes/Alias.js +116 -0
  92. package/node_modules/yaml/browser/dist/nodes/Collection.js +147 -0
  93. package/node_modules/yaml/browser/dist/nodes/Node.js +38 -0
  94. package/node_modules/yaml/browser/dist/nodes/Pair.js +36 -0
  95. package/node_modules/yaml/browser/dist/nodes/Scalar.js +24 -0
  96. package/node_modules/yaml/browser/dist/nodes/YAMLMap.js +144 -0
  97. package/node_modules/yaml/browser/dist/nodes/YAMLSeq.js +113 -0
  98. package/node_modules/yaml/browser/dist/nodes/addPairToJSMap.js +63 -0
  99. package/node_modules/yaml/browser/dist/nodes/identity.js +36 -0
  100. package/node_modules/yaml/browser/dist/nodes/toJS.js +37 -0
  101. package/node_modules/yaml/browser/dist/parse/cst-scalar.js +214 -0
  102. package/node_modules/yaml/browser/dist/parse/cst-stringify.js +61 -0
  103. package/node_modules/yaml/browser/dist/parse/cst-visit.js +97 -0
  104. package/node_modules/yaml/browser/dist/parse/cst.js +98 -0
  105. package/node_modules/yaml/browser/dist/parse/lexer.js +721 -0
  106. package/node_modules/yaml/browser/dist/parse/line-counter.js +39 -0
  107. package/node_modules/yaml/browser/dist/parse/parser.js +975 -0
  108. package/node_modules/yaml/browser/dist/public-api.js +102 -0
  109. package/node_modules/yaml/browser/dist/schema/Schema.js +37 -0
  110. package/node_modules/yaml/browser/dist/schema/common/map.js +17 -0
  111. package/node_modules/yaml/browser/dist/schema/common/null.js +15 -0
  112. package/node_modules/yaml/browser/dist/schema/common/seq.js +17 -0
  113. package/node_modules/yaml/browser/dist/schema/common/string.js +14 -0
  114. package/node_modules/yaml/browser/dist/schema/core/bool.js +19 -0
  115. package/node_modules/yaml/browser/dist/schema/core/float.js +43 -0
  116. package/node_modules/yaml/browser/dist/schema/core/int.js +38 -0
  117. package/node_modules/yaml/browser/dist/schema/core/schema.js +23 -0
  118. package/node_modules/yaml/browser/dist/schema/json/schema.js +62 -0
  119. package/node_modules/yaml/browser/dist/schema/tags.js +96 -0
  120. package/node_modules/yaml/browser/dist/schema/yaml-1.1/binary.js +58 -0
  121. package/node_modules/yaml/browser/dist/schema/yaml-1.1/bool.js +26 -0
  122. package/node_modules/yaml/browser/dist/schema/yaml-1.1/float.js +46 -0
  123. package/node_modules/yaml/browser/dist/schema/yaml-1.1/int.js +71 -0
  124. package/node_modules/yaml/browser/dist/schema/yaml-1.1/merge.js +67 -0
  125. package/node_modules/yaml/browser/dist/schema/yaml-1.1/omap.js +74 -0
  126. package/node_modules/yaml/browser/dist/schema/yaml-1.1/pairs.js +78 -0
  127. package/node_modules/yaml/browser/dist/schema/yaml-1.1/schema.js +39 -0
  128. package/node_modules/yaml/browser/dist/schema/yaml-1.1/set.js +93 -0
  129. package/node_modules/yaml/browser/dist/schema/yaml-1.1/timestamp.js +101 -0
  130. package/node_modules/yaml/browser/dist/stringify/foldFlowLines.js +146 -0
  131. package/node_modules/yaml/browser/dist/stringify/stringify.js +129 -0
  132. package/node_modules/yaml/browser/dist/stringify/stringifyCollection.js +153 -0
  133. package/node_modules/yaml/browser/dist/stringify/stringifyComment.js +20 -0
  134. package/node_modules/yaml/browser/dist/stringify/stringifyDocument.js +85 -0
  135. package/node_modules/yaml/browser/dist/stringify/stringifyNumber.js +25 -0
  136. package/node_modules/yaml/browser/dist/stringify/stringifyPair.js +150 -0
  137. package/node_modules/yaml/browser/dist/stringify/stringifyString.js +336 -0
  138. package/node_modules/yaml/browser/dist/util.js +11 -0
  139. package/node_modules/yaml/browser/dist/visit.js +233 -0
  140. package/node_modules/yaml/browser/index.js +5 -0
  141. package/node_modules/yaml/browser/package.json +3 -0
  142. package/node_modules/yaml/dist/cli.d.ts +8 -0
  143. package/node_modules/yaml/dist/cli.mjs +201 -0
  144. package/node_modules/yaml/dist/compose/compose-collection.d.ts +11 -0
  145. package/node_modules/yaml/dist/compose/compose-collection.js +90 -0
  146. package/node_modules/yaml/dist/compose/compose-doc.d.ts +7 -0
  147. package/node_modules/yaml/dist/compose/compose-doc.js +45 -0
  148. package/node_modules/yaml/dist/compose/compose-node.d.ts +29 -0
  149. package/node_modules/yaml/dist/compose/compose-node.js +112 -0
  150. package/node_modules/yaml/dist/compose/compose-scalar.d.ts +5 -0
  151. package/node_modules/yaml/dist/compose/compose-scalar.js +88 -0
  152. package/node_modules/yaml/dist/compose/composer.d.ts +63 -0
  153. package/node_modules/yaml/dist/compose/composer.js +224 -0
  154. package/node_modules/yaml/dist/compose/resolve-block-map.d.ts +6 -0
  155. package/node_modules/yaml/dist/compose/resolve-block-map.js +117 -0
  156. package/node_modules/yaml/dist/compose/resolve-block-scalar.d.ts +11 -0
  157. package/node_modules/yaml/dist/compose/resolve-block-scalar.js +200 -0
  158. package/node_modules/yaml/dist/compose/resolve-block-seq.d.ts +6 -0
  159. package/node_modules/yaml/dist/compose/resolve-block-seq.js +51 -0
  160. package/node_modules/yaml/dist/compose/resolve-end.d.ts +6 -0
  161. package/node_modules/yaml/dist/compose/resolve-end.js +39 -0
  162. package/node_modules/yaml/dist/compose/resolve-flow-collection.d.ts +7 -0
  163. package/node_modules/yaml/dist/compose/resolve-flow-collection.js +209 -0
  164. package/node_modules/yaml/dist/compose/resolve-flow-scalar.d.ts +10 -0
  165. package/node_modules/yaml/dist/compose/resolve-flow-scalar.js +227 -0
  166. package/node_modules/yaml/dist/compose/resolve-props.d.ts +23 -0
  167. package/node_modules/yaml/dist/compose/resolve-props.js +148 -0
  168. package/node_modules/yaml/dist/compose/util-contains-newline.d.ts +2 -0
  169. package/node_modules/yaml/dist/compose/util-contains-newline.js +36 -0
  170. package/node_modules/yaml/dist/compose/util-empty-scalar-position.d.ts +2 -0
  171. package/node_modules/yaml/dist/compose/util-empty-scalar-position.js +28 -0
  172. package/node_modules/yaml/dist/compose/util-flow-indent-check.d.ts +3 -0
  173. package/node_modules/yaml/dist/compose/util-flow-indent-check.js +17 -0
  174. package/node_modules/yaml/dist/compose/util-map-includes.d.ts +4 -0
  175. package/node_modules/yaml/dist/compose/util-map-includes.js +15 -0
  176. package/node_modules/yaml/dist/doc/Document.d.ts +141 -0
  177. package/node_modules/yaml/dist/doc/Document.js +337 -0
  178. package/node_modules/yaml/dist/doc/anchors.d.ts +24 -0
  179. package/node_modules/yaml/dist/doc/anchors.js +76 -0
  180. package/node_modules/yaml/dist/doc/applyReviver.d.ts +9 -0
  181. package/node_modules/yaml/dist/doc/applyReviver.js +57 -0
  182. package/node_modules/yaml/dist/doc/createNode.d.ts +17 -0
  183. package/node_modules/yaml/dist/doc/createNode.js +90 -0
  184. package/node_modules/yaml/dist/doc/directives.d.ts +49 -0
  185. package/node_modules/yaml/dist/doc/directives.js +178 -0
  186. package/node_modules/yaml/dist/errors.d.ts +21 -0
  187. package/node_modules/yaml/dist/errors.js +62 -0
  188. package/node_modules/yaml/dist/index.d.ts +25 -0
  189. package/node_modules/yaml/dist/index.js +50 -0
  190. package/node_modules/yaml/dist/log.d.ts +3 -0
  191. package/node_modules/yaml/dist/log.js +19 -0
  192. package/node_modules/yaml/dist/nodes/Alias.d.ts +29 -0
  193. package/node_modules/yaml/dist/nodes/Alias.js +118 -0
  194. package/node_modules/yaml/dist/nodes/Collection.d.ts +73 -0
  195. package/node_modules/yaml/dist/nodes/Collection.js +151 -0
  196. package/node_modules/yaml/dist/nodes/Node.d.ts +53 -0
  197. package/node_modules/yaml/dist/nodes/Node.js +40 -0
  198. package/node_modules/yaml/dist/nodes/Pair.d.ts +22 -0
  199. package/node_modules/yaml/dist/nodes/Pair.js +39 -0
  200. package/node_modules/yaml/dist/nodes/Scalar.d.ts +47 -0
  201. package/node_modules/yaml/dist/nodes/Scalar.js +27 -0
  202. package/node_modules/yaml/dist/nodes/YAMLMap.d.ts +53 -0
  203. package/node_modules/yaml/dist/nodes/YAMLMap.js +147 -0
  204. package/node_modules/yaml/dist/nodes/YAMLSeq.d.ts +60 -0
  205. package/node_modules/yaml/dist/nodes/YAMLSeq.js +115 -0
  206. package/node_modules/yaml/dist/nodes/addPairToJSMap.d.ts +4 -0
  207. package/node_modules/yaml/dist/nodes/addPairToJSMap.js +65 -0
  208. package/node_modules/yaml/dist/nodes/identity.d.ts +23 -0
  209. package/node_modules/yaml/dist/nodes/identity.js +53 -0
  210. package/node_modules/yaml/dist/nodes/toJS.d.ts +29 -0
  211. package/node_modules/yaml/dist/nodes/toJS.js +39 -0
  212. package/node_modules/yaml/dist/options.d.ts +350 -0
  213. package/node_modules/yaml/dist/parse/cst-scalar.d.ts +64 -0
  214. package/node_modules/yaml/dist/parse/cst-scalar.js +218 -0
  215. package/node_modules/yaml/dist/parse/cst-stringify.d.ts +8 -0
  216. package/node_modules/yaml/dist/parse/cst-stringify.js +63 -0
  217. package/node_modules/yaml/dist/parse/cst-visit.d.ts +39 -0
  218. package/node_modules/yaml/dist/parse/cst-visit.js +99 -0
  219. package/node_modules/yaml/dist/parse/cst.d.ts +109 -0
  220. package/node_modules/yaml/dist/parse/cst.js +112 -0
  221. package/node_modules/yaml/dist/parse/lexer.d.ts +87 -0
  222. package/node_modules/yaml/dist/parse/lexer.js +723 -0
  223. package/node_modules/yaml/dist/parse/line-counter.d.ts +22 -0
  224. package/node_modules/yaml/dist/parse/line-counter.js +41 -0
  225. package/node_modules/yaml/dist/parse/parser.d.ts +84 -0
  226. package/node_modules/yaml/dist/parse/parser.js +980 -0
  227. package/node_modules/yaml/dist/public-api.d.ts +44 -0
  228. package/node_modules/yaml/dist/public-api.js +107 -0
  229. package/node_modules/yaml/dist/schema/Schema.d.ts +17 -0
  230. package/node_modules/yaml/dist/schema/Schema.js +39 -0
  231. package/node_modules/yaml/dist/schema/common/map.d.ts +2 -0
  232. package/node_modules/yaml/dist/schema/common/map.js +19 -0
  233. package/node_modules/yaml/dist/schema/common/null.d.ts +4 -0
  234. package/node_modules/yaml/dist/schema/common/null.js +17 -0
  235. package/node_modules/yaml/dist/schema/common/seq.d.ts +2 -0
  236. package/node_modules/yaml/dist/schema/common/seq.js +19 -0
  237. package/node_modules/yaml/dist/schema/common/string.d.ts +2 -0
  238. package/node_modules/yaml/dist/schema/common/string.js +16 -0
  239. package/node_modules/yaml/dist/schema/core/bool.d.ts +4 -0
  240. package/node_modules/yaml/dist/schema/core/bool.js +21 -0
  241. package/node_modules/yaml/dist/schema/core/float.d.ts +4 -0
  242. package/node_modules/yaml/dist/schema/core/float.js +47 -0
  243. package/node_modules/yaml/dist/schema/core/int.d.ts +4 -0
  244. package/node_modules/yaml/dist/schema/core/int.js +42 -0
  245. package/node_modules/yaml/dist/schema/core/schema.d.ts +1 -0
  246. package/node_modules/yaml/dist/schema/core/schema.js +25 -0
  247. package/node_modules/yaml/dist/schema/json/schema.d.ts +2 -0
  248. package/node_modules/yaml/dist/schema/json/schema.js +64 -0
  249. package/node_modules/yaml/dist/schema/json-schema.d.ts +69 -0
  250. package/node_modules/yaml/dist/schema/tags.d.ts +48 -0
  251. package/node_modules/yaml/dist/schema/tags.js +99 -0
  252. package/node_modules/yaml/dist/schema/types.d.ts +92 -0
  253. package/node_modules/yaml/dist/schema/yaml-1.1/binary.d.ts +2 -0
  254. package/node_modules/yaml/dist/schema/yaml-1.1/binary.js +70 -0
  255. package/node_modules/yaml/dist/schema/yaml-1.1/bool.d.ts +7 -0
  256. package/node_modules/yaml/dist/schema/yaml-1.1/bool.js +29 -0
  257. package/node_modules/yaml/dist/schema/yaml-1.1/float.d.ts +4 -0
  258. package/node_modules/yaml/dist/schema/yaml-1.1/float.js +50 -0
  259. package/node_modules/yaml/dist/schema/yaml-1.1/int.d.ts +5 -0
  260. package/node_modules/yaml/dist/schema/yaml-1.1/int.js +76 -0
  261. package/node_modules/yaml/dist/schema/yaml-1.1/merge.d.ts +9 -0
  262. package/node_modules/yaml/dist/schema/yaml-1.1/merge.js +71 -0
  263. package/node_modules/yaml/dist/schema/yaml-1.1/omap.d.ts +22 -0
  264. package/node_modules/yaml/dist/schema/yaml-1.1/omap.js +77 -0
  265. package/node_modules/yaml/dist/schema/yaml-1.1/pairs.d.ts +10 -0
  266. package/node_modules/yaml/dist/schema/yaml-1.1/pairs.js +82 -0
  267. package/node_modules/yaml/dist/schema/yaml-1.1/schema.d.ts +1 -0
  268. package/node_modules/yaml/dist/schema/yaml-1.1/schema.js +41 -0
  269. package/node_modules/yaml/dist/schema/yaml-1.1/set.d.ts +28 -0
  270. package/node_modules/yaml/dist/schema/yaml-1.1/set.js +96 -0
  271. package/node_modules/yaml/dist/schema/yaml-1.1/timestamp.d.ts +6 -0
  272. package/node_modules/yaml/dist/schema/yaml-1.1/timestamp.js +105 -0
  273. package/node_modules/yaml/dist/stringify/foldFlowLines.d.ts +34 -0
  274. package/node_modules/yaml/dist/stringify/foldFlowLines.js +151 -0
  275. package/node_modules/yaml/dist/stringify/stringify.d.ts +21 -0
  276. package/node_modules/yaml/dist/stringify/stringify.js +132 -0
  277. package/node_modules/yaml/dist/stringify/stringifyCollection.d.ts +17 -0
  278. package/node_modules/yaml/dist/stringify/stringifyCollection.js +155 -0
  279. package/node_modules/yaml/dist/stringify/stringifyComment.d.ts +10 -0
  280. package/node_modules/yaml/dist/stringify/stringifyComment.js +24 -0
  281. package/node_modules/yaml/dist/stringify/stringifyDocument.d.ts +4 -0
  282. package/node_modules/yaml/dist/stringify/stringifyDocument.js +87 -0
  283. package/node_modules/yaml/dist/stringify/stringifyNumber.d.ts +2 -0
  284. package/node_modules/yaml/dist/stringify/stringifyNumber.js +27 -0
  285. package/node_modules/yaml/dist/stringify/stringifyPair.d.ts +3 -0
  286. package/node_modules/yaml/dist/stringify/stringifyPair.js +152 -0
  287. package/node_modules/yaml/dist/stringify/stringifyString.d.ts +9 -0
  288. package/node_modules/yaml/dist/stringify/stringifyString.js +338 -0
  289. package/node_modules/yaml/dist/test-events.d.ts +4 -0
  290. package/node_modules/yaml/dist/test-events.js +134 -0
  291. package/node_modules/yaml/dist/util.d.ts +16 -0
  292. package/node_modules/yaml/dist/util.js +28 -0
  293. package/node_modules/yaml/dist/visit.d.ts +102 -0
  294. package/node_modules/yaml/dist/visit.js +236 -0
  295. package/node_modules/yaml/package.json +97 -0
  296. package/node_modules/yaml/util.js +2 -0
  297. package/package.json +42 -0
@@ -0,0 +1,534 @@
1
+ import path from "node:path";
2
+ import { readdir as fsReaddir, readFile as fsReadFile } from "node:fs/promises";
3
+ import { Command, InvalidArgumentError } from "commander";
4
+ import { createTrayClientForRegion } from "../api/trayClient.js";
5
+ import { readCredentials, writeCredentials } from "../config/credentials.js";
6
+ import { readEnvironments, writeEnvironments } from "../config/environments.js";
7
+ import { readProjectMappings, writeProjectMappings } from "../config/mappings.js";
8
+ import { readProjectState } from "../config/state.js";
9
+ import { readJson } from "../config/io.js";
10
+ import { readTrayYaml } from "../config/trayYaml.js";
11
+ import { entityDisplayName } from "../lib/exportStructure.js";
12
+ import { resolveContainedSafe } from "../lib/pathContainment.js";
13
+ import { describeRegion } from "../lib/regionDisplay.js";
14
+ import { PUBLIC_REGIONS, parseRegion } from "../lib/regionParsing.js";
15
+ import { resolveToken } from "../lib/tokenResolution.js";
16
+ import { isUuid } from "../lib/uuid.js";
17
+ import { OutputFormats, parseFormat } from "../lib/outputFormat.js";
18
+ import { listWorkspaceAuthentications, matchAuthCandidates, prioritizeAuths, } from "../lib/authDiscovery.js";
19
+ import { isFullyResolved, resolveProjectRequirements, } from "../lib/promoteTarget.js";
20
+ import { checkProjectDrift, DriftStatuses } from "./status.js";
21
+ import { printAddedEnvironment, printConnectivityCheck, printEnvAlreadyExists, printEnvNotConfigured, printEnvResolveProject, printEnvResolveProjectFullyResolved, printInvalidEnvName, printNoTargetEnvironments, printNoTokenSkippingConnectivity, printRemovedCredentials, printRemovedEnvironment, printEnvResolveProjectError, printRemovedMapping, printSourceEnvHeader, printSourceEnvLine, printTargetEnvHeader, printTargetEnvLine, printTokenNotSaved, printTrayYamlNotFound, } from "../views/env/env.js";
22
+ import { printEnvListJson, printEnvResolveResultJson, } from "../views/env/shared.js";
23
+ import { printError, printInvalidAuthMappings, printLocalDrift, printNoTargetProjectMapped, printProjectError, printProjectNoStateFile, printProjectNotPulledLocally, printTargetEnvNotFound, } from "../views/promote/promote.js";
24
+ const ENV_NAME_RE = /^[a-zA-Z0-9_-]+$/;
25
+ function emptyMapping() {
26
+ return { authentications: {}, config: {}, connectors: [], services: [] };
27
+ }
28
+ async function checkConnectivity(deps, region, workspaceId, tokenFlag) {
29
+ const credentials = await readCredentials(deps.env);
30
+ let token;
31
+ try {
32
+ token = resolveToken({ tokenFlag, credentials, workspaceId, env: deps.env });
33
+ }
34
+ catch {
35
+ return { status: "no-token" };
36
+ }
37
+ const client = deps.createClient(region, token);
38
+ try {
39
+ await client.request("GET", `/v2/projects/workspaces/${workspaceId}`);
40
+ return { status: "ok" };
41
+ }
42
+ catch (err) {
43
+ return { status: "failed", message: err.message };
44
+ }
45
+ }
46
+ function describeConnectivity(result) {
47
+ switch (result.status) {
48
+ case "ok":
49
+ return "✅ connected";
50
+ case "no-token":
51
+ return "no token available";
52
+ case "failed":
53
+ return `❌ (${result.message})`;
54
+ }
55
+ }
56
+ export async function runEnvAdd(deps, options) {
57
+ const { cwd, env, stdout, stderr } = deps;
58
+ if (!ENV_NAME_RE.test(options.name)) {
59
+ printInvalidEnvName(stderr, ENV_NAME_RE, options.name);
60
+ return 1;
61
+ }
62
+ const environments = await readEnvironments(cwd);
63
+ if (environments.environments[options.name]) {
64
+ printEnvAlreadyExists(stderr, options.name);
65
+ return 1;
66
+ }
67
+ environments.environments[options.name] = {
68
+ region: options.region,
69
+ workspace_id: options.workspaceId,
70
+ };
71
+ await writeEnvironments(environments, cwd);
72
+ printAddedEnvironment(stdout, options.name, describeRegion(options.region), options.workspaceId);
73
+ if (options.token) {
74
+ const credentials = await readCredentials(env);
75
+ const alreadySet = credentials.workspaces[options.workspaceId] !== undefined;
76
+ if (!alreadySet || options.forceToken) {
77
+ credentials.workspaces[options.workspaceId] = {
78
+ region: options.region,
79
+ token: options.token,
80
+ };
81
+ await writeCredentials(credentials, env);
82
+ }
83
+ else {
84
+ printTokenNotSaved(stderr, options.workspaceId);
85
+ }
86
+ }
87
+ const result = await checkConnectivity(deps, options.region, options.workspaceId, options.token);
88
+ if (result.status === "no-token") {
89
+ printNoTokenSkippingConnectivity(stdout);
90
+ }
91
+ else {
92
+ printConnectivityCheck(stdout, describeConnectivity(result));
93
+ }
94
+ return 0;
95
+ }
96
+ function toConnectivityJson(result) {
97
+ return result.status === "failed" ? { status: "failed", message: result.message } : { status: result.status };
98
+ }
99
+ export async function runEnvList(deps, options) {
100
+ const { cwd, stdout, stderr } = deps;
101
+ const trayYaml = await readTrayYaml(cwd);
102
+ if (!trayYaml) {
103
+ printTrayYamlNotFound(stderr);
104
+ return 1;
105
+ }
106
+ const environments = await readEnvironments(cwd);
107
+ const names = Object.keys(environments.environments).sort();
108
+ if (options.format === OutputFormats.JSON) {
109
+ const sourceResult = await checkConnectivity(deps, trayYaml.region, trayYaml.workspace_id);
110
+ const targets = [];
111
+ for (const name of names) {
112
+ const entry = environments.environments[name];
113
+ const result = await checkConnectivity(deps, entry.region, entry.workspace_id);
114
+ targets.push({
115
+ name,
116
+ region: entry.region,
117
+ workspace_id: entry.workspace_id,
118
+ connectivity: toConnectivityJson(result),
119
+ });
120
+ }
121
+ printEnvListJson(stdout, {
122
+ source: {
123
+ region: trayYaml.region,
124
+ workspace_id: trayYaml.workspace_id,
125
+ connectivity: toConnectivityJson(sourceResult),
126
+ },
127
+ targets,
128
+ });
129
+ return 0;
130
+ }
131
+ printSourceEnvHeader(stdout);
132
+ const sourceResult = await checkConnectivity(deps, trayYaml.region, trayYaml.workspace_id);
133
+ printSourceEnvLine(stdout, describeRegion(trayYaml.region), trayYaml.workspace_id, describeConnectivity(sourceResult));
134
+ printTargetEnvHeader(stdout);
135
+ if (names.length === 0) {
136
+ printNoTargetEnvironments(stdout);
137
+ return 0;
138
+ }
139
+ for (const name of names) {
140
+ const entry = environments.environments[name];
141
+ const result = await checkConnectivity(deps, entry.region, entry.workspace_id);
142
+ printTargetEnvLine(stdout, name, describeRegion(entry.region), entry.workspace_id, describeConnectivity(result));
143
+ }
144
+ return 0;
145
+ }
146
+ export async function runEnvRemove(deps, options) {
147
+ const { cwd, env, readdir, stdout, stderr } = deps;
148
+ const environments = await readEnvironments(cwd);
149
+ const entry = environments.environments[options.name];
150
+ if (!entry) {
151
+ printEnvNotConfigured(stdout, options.name);
152
+ return 0;
153
+ }
154
+ delete environments.environments[options.name];
155
+ await writeEnvironments(environments, cwd);
156
+ printRemovedEnvironment(stdout, options.name);
157
+ const trayYaml = await readTrayYaml(cwd);
158
+ if (trayYaml) {
159
+ const projectsRoot = path.join(cwd, "projects");
160
+ let existingDirs;
161
+ try {
162
+ existingDirs = await readdir(projectsRoot);
163
+ }
164
+ catch {
165
+ existingDirs = [];
166
+ }
167
+ for (const projectId of trayYaml.projects) {
168
+ const dirName = existingDirs.find((name) => name.split("--")[0] === projectId);
169
+ if (!dirName)
170
+ continue;
171
+ const projectDirPath = path.join(projectsRoot, dirName);
172
+ const mappings = await readProjectMappings(projectDirPath);
173
+ if (!mappings || !mappings.environments[options.name])
174
+ continue;
175
+ delete mappings.environments[options.name];
176
+ await writeProjectMappings(projectDirPath, mappings);
177
+ printRemovedMapping(stdout, options.name, dirName);
178
+ }
179
+ }
180
+ if (options.forgetCredentials) {
181
+ const credentials = await readCredentials(env);
182
+ if (credentials.workspaces[entry.workspace_id]) {
183
+ delete credentials.workspaces[entry.workspace_id];
184
+ await writeCredentials(credentials, env);
185
+ printRemovedCredentials(stdout, entry.workspace_id);
186
+ }
187
+ }
188
+ return 0;
189
+ }
190
+ function findProjectDirName(existingDirs, projectId) {
191
+ return existingDirs.find((name) => name.split("--")[0] === projectId);
192
+ }
193
+ function toEnvResolveProjectErrorJson(error) {
194
+ if (error.reason === "no_target_project_mapped") {
195
+ return { reason: "no_target_project_mapped", mappings_path: error.mappingsPath };
196
+ }
197
+ if (error.reason === "project_error") {
198
+ return { reason: "project_error", message: error.message, target_project_id: error.targetProjectId };
199
+ }
200
+ return { reason: "invalid_auth_mappings", invalid_auth_mappings: error.invalidAuthMappings };
201
+ }
202
+ export async function runEnvResolve(deps, options) {
203
+ const { cwd, env, createClient, readdir, readFile, readdirRecursive, stdout, stderr } = deps;
204
+ const asJson = options.format === OutputFormats.JSON;
205
+ const trayYaml = await readTrayYaml(cwd);
206
+ if (!trayYaml) {
207
+ printTrayYamlNotFound(stderr);
208
+ return 1;
209
+ }
210
+ const environments = await readEnvironments(cwd);
211
+ const targetEnv = environments.environments[options.to];
212
+ if (!targetEnv) {
213
+ printTargetEnvNotFound(stderr, options.to);
214
+ return 1;
215
+ }
216
+ const credentials = await readCredentials(env);
217
+ let targetToken;
218
+ try {
219
+ targetToken = resolveToken({
220
+ tokenFlag: options.token,
221
+ credentials,
222
+ workspaceId: targetEnv.workspace_id,
223
+ envName: options.to,
224
+ env,
225
+ });
226
+ }
227
+ catch (err) {
228
+ printError(stderr, err.message);
229
+ return 1;
230
+ }
231
+ const targetClient = createClient(targetEnv.region, targetToken);
232
+ const { authentications } = await listWorkspaceAuthentications(targetClient, targetEnv.region, targetEnv.workspace_id);
233
+ const targeted = options.projectIds !== undefined && options.projectIds.length > 0;
234
+ const plannedIds = targeted ? options.projectIds : trayYaml.projects;
235
+ const projectsRoot = path.join(cwd, "projects");
236
+ let existingDirs;
237
+ try {
238
+ existingDirs = await readdir(projectsRoot);
239
+ }
240
+ catch {
241
+ existingDirs = [];
242
+ }
243
+ const projectViews = [];
244
+ let anyUnresolved = false;
245
+ for (const projectId of plannedIds) {
246
+ const dirName = findProjectDirName(existingDirs, projectId);
247
+ if (!dirName) {
248
+ printProjectNotPulledLocally(stderr, projectId);
249
+ return 1;
250
+ }
251
+ const projectDirPath = await resolveContainedSafe(projectsRoot, dirName);
252
+ const drift = await checkProjectDrift({ readdirRecursive, readFile }, projectId, projectDirPath);
253
+ if (drift.never_pulled) {
254
+ printProjectNoStateFile(stderr, projectId);
255
+ return 1;
256
+ }
257
+ const dirty = drift.drift.filter((d) => d.status !== DriftStatuses.CLEAN);
258
+ if (dirty.length > 0) {
259
+ printLocalDrift(stderr, projectId, dirName, dirty);
260
+ return 1;
261
+ }
262
+ const state = (await readProjectState(projectDirPath));
263
+ const projectJsonPath = await resolveContainedSafe(projectDirPath, "project.json");
264
+ const project = await readJson(projectJsonPath);
265
+ const sourceProjectName = project ? entityDisplayName(project) : projectId;
266
+ const knownTargetProjectId = (await readProjectMappings(projectDirPath))?.environments[options.to]
267
+ ?.target_project_id;
268
+ let resolution;
269
+ try {
270
+ resolution = await resolveProjectRequirements(targetClient, { readFile }, {
271
+ projectDirPath,
272
+ envName: options.to,
273
+ targetWorkspaceId: targetEnv.workspace_id,
274
+ sourceProjectName,
275
+ state,
276
+ autoCreateProjects: Boolean(options.dryRun),
277
+ validateAuthMappings: false,
278
+ });
279
+ }
280
+ catch (err) {
281
+ if (!options.dryRun) {
282
+ printProjectError(stderr, projectId, sourceProjectName, err.message, knownTargetProjectId);
283
+ return 1;
284
+ }
285
+ anyUnresolved = true;
286
+ const error = {
287
+ reason: "project_error",
288
+ message: err.message,
289
+ targetProjectId: knownTargetProjectId,
290
+ };
291
+ if (!asJson) {
292
+ printEnvResolveProjectError(stdout, projectId, sourceProjectName, error);
293
+ }
294
+ projectViews.push({
295
+ projectId,
296
+ sourceProjectName,
297
+ unresolvedAuthentications: [],
298
+ autoResolvedAuthentications: [],
299
+ hasNewConfigKeys: false,
300
+ error,
301
+ });
302
+ continue;
303
+ }
304
+ if (resolution.status === "no_target_project_mapped") {
305
+ if (!options.dryRun) {
306
+ printNoTargetProjectMapped(stderr, sourceProjectName, projectId, options.to, resolution.mappingsPath);
307
+ return 1;
308
+ }
309
+ anyUnresolved = true;
310
+ const error = {
311
+ reason: "no_target_project_mapped",
312
+ mappingsPath: resolution.mappingsPath,
313
+ };
314
+ if (!asJson) {
315
+ printEnvResolveProjectError(stdout, projectId, sourceProjectName, error);
316
+ }
317
+ projectViews.push({
318
+ projectId,
319
+ sourceProjectName,
320
+ unresolvedAuthentications: [],
321
+ autoResolvedAuthentications: [],
322
+ hasNewConfigKeys: false,
323
+ error,
324
+ });
325
+ continue;
326
+ }
327
+ if (resolution.status === "invalid_auth_mappings") {
328
+ if (!options.dryRun) {
329
+ printInvalidAuthMappings(stderr, projectId, sourceProjectName, resolution.invalidAuthMappings);
330
+ return 1;
331
+ }
332
+ anyUnresolved = true;
333
+ const error = {
334
+ reason: "invalid_auth_mappings",
335
+ invalidAuthMappings: resolution.invalidAuthMappings,
336
+ };
337
+ if (!asJson) {
338
+ printEnvResolveProjectError(stdout, projectId, sourceProjectName, error);
339
+ }
340
+ projectViews.push({
341
+ projectId,
342
+ sourceProjectName,
343
+ unresolvedAuthentications: [],
344
+ autoResolvedAuthentications: [],
345
+ hasNewConfigKeys: false,
346
+ error,
347
+ });
348
+ continue;
349
+ }
350
+ const { unresolved } = resolution;
351
+ if (isFullyResolved(unresolved)) {
352
+ if (!asJson) {
353
+ printEnvResolveProjectFullyResolved(stdout, projectId, sourceProjectName);
354
+ }
355
+ projectViews.push({
356
+ projectId,
357
+ sourceProjectName,
358
+ unresolvedAuthentications: [],
359
+ autoResolvedAuthentications: [],
360
+ hasNewConfigKeys: false,
361
+ });
362
+ continue;
363
+ }
364
+ const autoResolvedViews = [];
365
+ const unresolvedViews = [];
366
+ const autoResolvedMappings = {};
367
+ for (const auth of unresolved.unresolvedAuthentications) {
368
+ const candidates = prioritizeAuths(matchAuthCandidates(auth, authentications));
369
+ if (options.autoResolve && candidates.length > 0) {
370
+ const chosen = candidates[0];
371
+ autoResolvedMappings[auth.authExportId] = chosen.id;
372
+ autoResolvedViews.push({ authExportId: auth.authExportId, title: auth.title, chosen });
373
+ continue;
374
+ }
375
+ unresolvedViews.push({
376
+ authExportId: auth.authExportId,
377
+ title: auth.title,
378
+ service: auth.service,
379
+ candidates,
380
+ });
381
+ }
382
+ if (Object.keys(autoResolvedMappings).length > 0) {
383
+ const mappingsFile = (await readProjectMappings(projectDirPath)) ?? { version: 1, environments: {} };
384
+ const mapping = mappingsFile.environments[options.to] ?? emptyMapping();
385
+ mapping.authentications = { ...mapping.authentications, ...autoResolvedMappings };
386
+ mappingsFile.environments[options.to] = mapping;
387
+ await writeProjectMappings(projectDirPath, mappingsFile);
388
+ }
389
+ if (unresolvedViews.length > 0 || unresolved.hasNewConfigKeys) {
390
+ anyUnresolved = true;
391
+ }
392
+ const projectView = {
393
+ projectId,
394
+ sourceProjectName,
395
+ unresolvedAuthentications: unresolvedViews,
396
+ autoResolvedAuthentications: autoResolvedViews,
397
+ hasNewConfigKeys: unresolved.hasNewConfigKeys,
398
+ };
399
+ projectViews.push(projectView);
400
+ if (!asJson) {
401
+ printEnvResolveProject(stdout, projectView);
402
+ }
403
+ }
404
+ if (asJson) {
405
+ printEnvResolveResultJson(stdout, {
406
+ projects: projectViews.map((p) => ({
407
+ project_id: p.projectId,
408
+ source_project_name: p.sourceProjectName,
409
+ fully_resolved: !p.error && p.unresolvedAuthentications.length === 0 && !p.hasNewConfigKeys,
410
+ unresolved_authentications: p.unresolvedAuthentications.map((auth) => ({
411
+ auth_export_id: auth.authExportId,
412
+ title: auth.title,
413
+ service: auth.service,
414
+ candidates: auth.candidates.map((c) => ({
415
+ id: c.id,
416
+ name: c.name,
417
+ service: c.service,
418
+ created: c.created,
419
+ match_kind: c.matchKind,
420
+ })),
421
+ })),
422
+ auto_resolved_authentications: p.autoResolvedAuthentications.map((auth) => ({
423
+ auth_export_id: auth.authExportId,
424
+ title: auth.title,
425
+ chosen: {
426
+ id: auth.chosen.id,
427
+ name: auth.chosen.name,
428
+ service: auth.chosen.service,
429
+ created: auth.chosen.created,
430
+ match_kind: auth.chosen.matchKind,
431
+ },
432
+ })),
433
+ has_new_config_keys: p.hasNewConfigKeys,
434
+ ...(p.error ? { error: toEnvResolveProjectErrorJson(p.error) } : {}),
435
+ })),
436
+ });
437
+ }
438
+ return anyUnresolved ? 1 : 0;
439
+ }
440
+ function parseUuid(value, flagName) {
441
+ if (!isUuid(value)) {
442
+ throw new InvalidArgumentError(`${flagName} must be a UUID`);
443
+ }
444
+ return value;
445
+ }
446
+ function parseProjectIds(value, previous) {
447
+ if (!isUuid(value)) {
448
+ throw new InvalidArgumentError("--project must be a UUID");
449
+ }
450
+ return [...(previous ?? []), value];
451
+ }
452
+ async function readdirRecursiveReal(dirPath) {
453
+ try {
454
+ const entries = await fsReaddir(dirPath, { recursive: true, withFileTypes: true });
455
+ return entries
456
+ .filter((entry) => entry.isFile())
457
+ .map((entry) => path.relative(dirPath, path.join(entry.parentPath, entry.name)));
458
+ }
459
+ catch {
460
+ return [];
461
+ }
462
+ }
463
+ function realDeps() {
464
+ return {
465
+ cwd: process.cwd(),
466
+ env: process.env,
467
+ createClient: (region, token) => createTrayClientForRegion(region, token),
468
+ readdir: (dir) => fsReaddir(dir),
469
+ readFile: (filePath) => fsReadFile(filePath, "utf8"),
470
+ readdirRecursive: (dir) => readdirRecursiveReal(dir),
471
+ stdout: (line) => console.log(line),
472
+ stderr: (line) => console.error(line),
473
+ };
474
+ }
475
+ export const envCommand = new Command("env").description("Manage target environments (environments.json)");
476
+ envCommand
477
+ .command("add")
478
+ .description("Add a target environment")
479
+ .argument("<name>", "Environment name")
480
+ .requiredOption("-r, --region <region>", `Tray regions: ${PUBLIC_REGIONS.map(describeRegion).join(", ")}`, parseRegion)
481
+ .requiredOption("-w, --workspace-id <id>", "Tray workspace UUID", (value) => parseUuid(value, "--workspace-id"))
482
+ .option("-t, --token <token>", "Tray API token to store in ~/.tray/credentials.json")
483
+ .option("-f, --force-token", "overwrite an existing credentials entry for this workspace")
484
+ .action(async (name, opts) => {
485
+ const exitCode = await runEnvAdd(realDeps(), {
486
+ name,
487
+ region: opts.region,
488
+ workspaceId: opts.workspaceId,
489
+ token: opts.token,
490
+ forceToken: Boolean(opts.forceToken),
491
+ });
492
+ process.exitCode = exitCode;
493
+ });
494
+ envCommand
495
+ .command("list")
496
+ .description("List source and target environments with connectivity status")
497
+ .option("--format <format>", "human or json", parseFormat, OutputFormats.HUMAN)
498
+ .action(async (opts) => {
499
+ const exitCode = await runEnvList(realDeps(), { format: opts.format });
500
+ process.exitCode = exitCode;
501
+ });
502
+ envCommand
503
+ .command("remove")
504
+ .description("Remove a target environment and its per-project mappings")
505
+ .argument("<name>", "Environment name")
506
+ .option("--forget-credentials", "also remove the workspace's entry from credentials.json")
507
+ .action(async (name, opts) => {
508
+ const exitCode = await runEnvRemove(realDeps(), {
509
+ name,
510
+ forgetCredentials: Boolean(opts.forgetCredentials),
511
+ });
512
+ process.exitCode = exitCode;
513
+ });
514
+ envCommand
515
+ .command("resolve")
516
+ .description("Report unresolved auth requirements for a target env, with candidate matches")
517
+ .argument("<env-name>", "target environment name, e.g. \"staging\" (see `tray env list` for configured names)")
518
+ .option("-p, --project <id...>", "resolve only these project IDs", parseProjectIds)
519
+ .option("-t, --token <token>", "Tray API token (target environment)")
520
+ .option("--auto-resolve", "write the top-ranked candidate for each unresolved authentication into mappings.json")
521
+ .option("--dry-run", "auto-create a missing target project + scaffold mappings.json so a real check can run before ever promoting (writes those two things; never writes an auth pick — combine with --auto-resolve for that)")
522
+ .option("--format <format>", "human or json", parseFormat, OutputFormats.HUMAN)
523
+ .action(async (envName, opts) => {
524
+ const exitCode = await runEnvResolve(realDeps(), {
525
+ to: envName,
526
+ token: opts.token,
527
+ projectIds: opts.project,
528
+ autoResolve: Boolean(opts.autoResolve),
529
+ dryRun: Boolean(opts.dryRun),
530
+ format: opts.format,
531
+ });
532
+ process.exitCode = exitCode;
533
+ });
534
+ //# sourceMappingURL=env.js.map
@@ -0,0 +1,115 @@
1
+ import { readdir as fsReaddir, rename as fsRename, rm as fsRm } from "node:fs/promises";
2
+ import { Command, InvalidArgumentError } from "commander";
3
+ import { createTrayClientForRegion } from "../api/trayClient.js";
4
+ import { readCredentials, writeCredentials } from "../config/credentials.js";
5
+ import { readTrayYaml, writeTrayYaml } from "../config/trayYaml.js";
6
+ import { writeEnvironments } from "../config/environments.js";
7
+ import { Scopes } from "../config/types.js";
8
+ import { describeRegion } from "../lib/regionDisplay.js";
9
+ import { PUBLIC_REGIONS, parseRegion } from "../lib/regionParsing.js";
10
+ import { resolveToken } from "../lib/tokenResolution.js";
11
+ import { isUuid } from "../lib/uuid.js";
12
+ import { runPull } from "./pull.js";
13
+ import { printConnectivityCheckFailed, printConnectivityCheckSucceeded, printNoTokenSkippingConnectivityAndPull, printTokenNotSaved, printTrayYamlAlreadyExists, } from "../views/init/init.js";
14
+ const SCOPES = Object.values(Scopes);
15
+ function parseScope(value) {
16
+ if (!SCOPES.includes(value)) {
17
+ throw new InvalidArgumentError(`scope must be one of: ${SCOPES.join(", ")}`);
18
+ }
19
+ return value;
20
+ }
21
+ function parseUuid(value, flagName) {
22
+ if (!isUuid(value)) {
23
+ throw new InvalidArgumentError(`${flagName} must be a UUID`);
24
+ }
25
+ return value;
26
+ }
27
+ function parseProjectIds(value, previous) {
28
+ return [...(previous ?? []), parseUuid(value, "--project")];
29
+ }
30
+ export async function runInit(deps, options) {
31
+ const { cwd, env, createClient, readdir, rm, rename, stdout, stderr } = deps;
32
+ const existing = await readTrayYaml(cwd);
33
+ if (existing) {
34
+ printTrayYamlAlreadyExists(stderr);
35
+ return 1;
36
+ }
37
+ await writeTrayYaml({
38
+ version: 1,
39
+ scope: options.scope,
40
+ region: options.region,
41
+ workspace_id: options.workspaceId,
42
+ projects: options.scope === Scopes.PROJECT ? (options.projectIds ?? []) : [],
43
+ }, cwd);
44
+ await writeEnvironments({ version: 1, environments: {} }, cwd);
45
+ if (options.token) {
46
+ const credentials = await readCredentials(env);
47
+ const alreadySet = credentials.workspaces[options.workspaceId] !== undefined;
48
+ if (!alreadySet || options.forceToken) {
49
+ credentials.workspaces[options.workspaceId] = {
50
+ region: options.region,
51
+ token: options.token,
52
+ };
53
+ await writeCredentials(credentials, env);
54
+ }
55
+ else {
56
+ printTokenNotSaved(stderr, options.workspaceId, options.region);
57
+ }
58
+ }
59
+ let token;
60
+ try {
61
+ const credentials = await readCredentials(env);
62
+ token = resolveToken({
63
+ tokenFlag: options.token,
64
+ credentials,
65
+ workspaceId: options.workspaceId,
66
+ env,
67
+ });
68
+ }
69
+ catch {
70
+ printNoTokenSkippingConnectivityAndPull(stdout);
71
+ return 0;
72
+ }
73
+ const client = createClient(options.region, token);
74
+ try {
75
+ await client.request("GET", `/v2/projects/workspaces/${options.workspaceId}`);
76
+ printConnectivityCheckSucceeded(stdout);
77
+ }
78
+ catch (err) {
79
+ printConnectivityCheckFailed(stdout, err.message);
80
+ }
81
+ const shouldPull = options.scope === Scopes.WORKSPACE || (options.projectIds?.length ?? 0) > 0;
82
+ if (!shouldPull) {
83
+ return 0;
84
+ }
85
+ return runPull({ cwd, createClient, readdir, rm, rename, stdout }, { token, projectIds: options.scope === Scopes.PROJECT ? options.projectIds : undefined });
86
+ }
87
+ export const initCommand = new Command("init")
88
+ .description("Scaffold a new tray-sync-cli repository")
89
+ .requiredOption("-r, --region <region>", `Tray regions: ${PUBLIC_REGIONS.map(describeRegion).join(", ")}`, parseRegion)
90
+ .requiredOption("-w, --workspace-id <id>", "Tray workspace UUID", (value) => parseUuid(value, "--workspace-id"))
91
+ .option("-s, --scope <scope>", "project or workspace", parseScope, Scopes.PROJECT)
92
+ .option("-p, --project <id...>", "project scope only: pull these project IDs after scaffolding (ignored in workspace scope, which pulls all projects)", parseProjectIds)
93
+ .option("-t, --token <token>", "Tray API token to store in ~/.tray/credentials.json")
94
+ .option("-f, --force-token", "overwrite an existing credentials entry for this workspace")
95
+ .action(async (opts) => {
96
+ const exitCode = await runInit({
97
+ cwd: process.cwd(),
98
+ env: process.env,
99
+ createClient: (region, token) => createTrayClientForRegion(region, token),
100
+ readdir: (dir) => fsReaddir(dir),
101
+ rm: (dir) => fsRm(dir, { recursive: true, force: true }),
102
+ rename: (oldPath, newPath) => fsRename(oldPath, newPath),
103
+ stdout: (line) => console.log(line),
104
+ stderr: (line) => console.error(line),
105
+ }, {
106
+ scope: opts.scope,
107
+ region: opts.region,
108
+ workspaceId: opts.workspaceId,
109
+ projectIds: opts.project,
110
+ token: opts.token,
111
+ forceToken: Boolean(opts.forceToken),
112
+ });
113
+ process.exitCode = exitCode;
114
+ });
115
+ //# sourceMappingURL=init.js.map