track-cli 3.0.0-rc

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 (224) hide show
  1. package/LICENSE +7 -0
  2. package/README.md +3 -0
  3. package/esm/_dnt.polyfills.d.ts +6 -0
  4. package/esm/_dnt.polyfills.js +1 -0
  5. package/esm/_dnt.shims.d.ts +19 -0
  6. package/esm/_dnt.shims.js +78 -0
  7. package/esm/deps/deno.land/std@0.170.0/fmt/colors.d.ts +270 -0
  8. package/esm/deps/deno.land/std@0.170.0/fmt/colors.js +473 -0
  9. package/esm/deps/deno.land/std@0.195.0/_util/os.d.ts +4 -0
  10. package/esm/deps/deno.land/std@0.195.0/_util/os.js +18 -0
  11. package/esm/deps/deno.land/std@0.195.0/assert/assert.d.ts +2 -0
  12. package/esm/deps/deno.land/std@0.195.0/assert/assert.js +8 -0
  13. package/esm/deps/deno.land/std@0.195.0/assert/assertion_error.d.ts +4 -0
  14. package/esm/deps/deno.land/std@0.195.0/assert/assertion_error.js +12 -0
  15. package/esm/deps/deno.land/std@0.195.0/datetime/_common.d.ts +50 -0
  16. package/esm/deps/deno.land/std@0.195.0/datetime/_common.js +545 -0
  17. package/esm/deps/deno.land/std@0.195.0/datetime/constants.d.ts +55 -0
  18. package/esm/deps/deno.land/std@0.195.0/datetime/constants.js +57 -0
  19. package/esm/deps/deno.land/std@0.195.0/datetime/day_of_year.d.ts +26 -0
  20. package/esm/deps/deno.land/std@0.195.0/datetime/day_of_year.js +45 -0
  21. package/esm/deps/deno.land/std@0.195.0/datetime/difference.d.ts +38 -0
  22. package/esm/deps/deno.land/std@0.195.0/datetime/difference.js +93 -0
  23. package/esm/deps/deno.land/std@0.195.0/datetime/format.d.ts +22 -0
  24. package/esm/deps/deno.land/std@0.195.0/datetime/format.js +28 -0
  25. package/esm/deps/deno.land/std@0.195.0/datetime/is_leap.d.ts +49 -0
  26. package/esm/deps/deno.land/std@0.195.0/datetime/is_leap.js +60 -0
  27. package/esm/deps/deno.land/std@0.195.0/datetime/mod.d.ts +43 -0
  28. package/esm/deps/deno.land/std@0.195.0/datetime/mod.js +45 -0
  29. package/esm/deps/deno.land/std@0.195.0/datetime/parse.d.ts +21 -0
  30. package/esm/deps/deno.land/std@0.195.0/datetime/parse.js +29 -0
  31. package/esm/deps/deno.land/std@0.195.0/datetime/to_imf.d.ts +17 -0
  32. package/esm/deps/deno.land/std@0.195.0/datetime/to_imf.js +44 -0
  33. package/esm/deps/deno.land/std@0.195.0/datetime/week_of_year.d.ts +13 -0
  34. package/esm/deps/deno.land/std@0.195.0/datetime/week_of_year.js +38 -0
  35. package/esm/deps/deno.land/std@0.195.0/fmt/colors.d.ts +270 -0
  36. package/esm/deps/deno.land/std@0.195.0/fmt/colors.js +474 -0
  37. package/esm/deps/deno.land/std@0.195.0/fmt/duration.d.ts +15 -0
  38. package/esm/deps/deno.land/std@0.195.0/fmt/duration.js +96 -0
  39. package/esm/deps/deno.land/std@0.195.0/fs/_util.d.ts +35 -0
  40. package/esm/deps/deno.land/std@0.195.0/fs/_util.js +80 -0
  41. package/esm/deps/deno.land/std@0.195.0/fs/copy.d.ts +51 -0
  42. package/esm/deps/deno.land/std@0.195.0/fs/copy.js +244 -0
  43. package/esm/deps/deno.land/std@0.195.0/fs/empty_dir.d.ts +31 -0
  44. package/esm/deps/deno.land/std@0.195.0/fs/empty_dir.js +74 -0
  45. package/esm/deps/deno.land/std@0.195.0/fs/ensure_dir.d.ts +27 -0
  46. package/esm/deps/deno.land/std@0.195.0/fs/ensure_dir.js +55 -0
  47. package/esm/deps/deno.land/std@0.195.0/fs/ensure_file.d.ts +33 -0
  48. package/esm/deps/deno.land/std@0.195.0/fs/ensure_file.js +75 -0
  49. package/esm/deps/deno.land/std@0.195.0/fs/ensure_link.d.ts +31 -0
  50. package/esm/deps/deno.land/std@0.195.0/fs/ensure_link.js +43 -0
  51. package/esm/deps/deno.land/std@0.195.0/fs/ensure_symlink.d.ts +17 -0
  52. package/esm/deps/deno.land/std@0.195.0/fs/ensure_symlink.js +68 -0
  53. package/esm/deps/deno.land/std@0.195.0/fs/eol.d.ts +40 -0
  54. package/esm/deps/deno.land/std@0.195.0/fs/eol.js +53 -0
  55. package/esm/deps/deno.land/std@0.195.0/fs/exists.d.ts +102 -0
  56. package/esm/deps/deno.land/std@0.195.0/fs/exists.js +163 -0
  57. package/esm/deps/deno.land/std@0.195.0/fs/expand_glob.d.ts +37 -0
  58. package/esm/deps/deno.land/std@0.195.0/fs/expand_glob.js +216 -0
  59. package/esm/deps/deno.land/std@0.195.0/fs/mod.d.ts +16 -0
  60. package/esm/deps/deno.land/std@0.195.0/fs/mod.js +17 -0
  61. package/esm/deps/deno.land/std@0.195.0/fs/move.d.ts +29 -0
  62. package/esm/deps/deno.land/std@0.195.0/fs/move.js +88 -0
  63. package/esm/deps/deno.land/std@0.195.0/fs/walk.d.ts +40 -0
  64. package/esm/deps/deno.land/std@0.195.0/fs/walk.js +158 -0
  65. package/esm/deps/deno.land/std@0.195.0/path/_constants.d.ts +39 -0
  66. package/esm/deps/deno.land/std@0.195.0/path/_constants.js +46 -0
  67. package/esm/deps/deno.land/std@0.195.0/path/_interface.d.ts +26 -0
  68. package/esm/deps/deno.land/std@0.195.0/path/_interface.js +3 -0
  69. package/esm/deps/deno.land/std@0.195.0/path/_util.d.ts +11 -0
  70. package/esm/deps/deno.land/std@0.195.0/path/_util.js +161 -0
  71. package/esm/deps/deno.land/std@0.195.0/path/common.d.ts +13 -0
  72. package/esm/deps/deno.land/std@0.195.0/path/common.js +36 -0
  73. package/esm/deps/deno.land/std@0.195.0/path/glob.d.ts +83 -0
  74. package/esm/deps/deno.land/std@0.195.0/path/glob.js +361 -0
  75. package/esm/deps/deno.land/std@0.195.0/path/mod.d.ts +9 -0
  76. package/esm/deps/deno.land/std@0.195.0/path/mod.js +33 -0
  77. package/esm/deps/deno.land/std@0.195.0/path/posix.d.ts +86 -0
  78. package/esm/deps/deno.land/std@0.195.0/path/posix.js +442 -0
  79. package/esm/deps/deno.land/std@0.195.0/path/separator.d.ts +2 -0
  80. package/esm/deps/deno.land/std@0.195.0/path/separator.js +5 -0
  81. package/esm/deps/deno.land/std@0.195.0/path/win32.d.ts +91 -0
  82. package/esm/deps/deno.land/std@0.195.0/path/win32.js +909 -0
  83. package/esm/deps/deno.land/x/cliffy@v0.25.7/_utils/distance.d.ts +1 -0
  84. package/esm/deps/deno.land/x/cliffy@v0.25.7/_utils/distance.js +26 -0
  85. package/esm/deps/deno.land/x/cliffy@v0.25.7/command/_errors.d.ts +76 -0
  86. package/esm/deps/deno.land/x/cliffy@v0.25.7/command/_errors.js +154 -0
  87. package/esm/deps/deno.land/x/cliffy@v0.25.7/command/_utils.d.ts +32 -0
  88. package/esm/deps/deno.land/x/cliffy@v0.25.7/command/_utils.js +105 -0
  89. package/esm/deps/deno.land/x/cliffy@v0.25.7/command/command.d.ts +831 -0
  90. package/esm/deps/deno.land/x/cliffy@v0.25.7/command/command.js +1701 -0
  91. package/esm/deps/deno.land/x/cliffy@v0.25.7/command/completions/_bash_completions_generator.d.ts +17 -0
  92. package/esm/deps/deno.land/x/cliffy@v0.25.7/command/completions/_bash_completions_generator.js +201 -0
  93. package/esm/deps/deno.land/x/cliffy@v0.25.7/command/completions/_fish_completions_generator.d.ts +14 -0
  94. package/esm/deps/deno.land/x/cliffy@v0.25.7/command/completions/_fish_completions_generator.js +141 -0
  95. package/esm/deps/deno.land/x/cliffy@v0.25.7/command/completions/_zsh_completions_generator.d.ts +21 -0
  96. package/esm/deps/deno.land/x/cliffy@v0.25.7/command/completions/_zsh_completions_generator.js +285 -0
  97. package/esm/deps/deno.land/x/cliffy@v0.25.7/command/completions/bash.d.ts +6 -0
  98. package/esm/deps/deno.land/x/cliffy@v0.25.7/command/completions/bash.js +38 -0
  99. package/esm/deps/deno.land/x/cliffy@v0.25.7/command/completions/complete.d.ts +8 -0
  100. package/esm/deps/deno.land/x/cliffy@v0.25.7/command/completions/complete.js +32 -0
  101. package/esm/deps/deno.land/x/cliffy@v0.25.7/command/completions/fish.d.ts +6 -0
  102. package/esm/deps/deno.land/x/cliffy@v0.25.7/command/completions/fish.js +38 -0
  103. package/esm/deps/deno.land/x/cliffy@v0.25.7/command/completions/mod.d.ts +6 -0
  104. package/esm/deps/deno.land/x/cliffy@v0.25.7/command/completions/mod.js +46 -0
  105. package/esm/deps/deno.land/x/cliffy@v0.25.7/command/completions/zsh.d.ts +6 -0
  106. package/esm/deps/deno.land/x/cliffy@v0.25.7/command/completions/zsh.js +38 -0
  107. package/esm/deps/deno.land/x/cliffy@v0.25.7/command/deprecated.d.ts +45 -0
  108. package/esm/deps/deno.land/x/cliffy@v0.25.7/command/deprecated.js +2 -0
  109. package/esm/deps/deno.land/x/cliffy@v0.25.7/command/deps.d.ts +1 -0
  110. package/esm/deps/deno.land/x/cliffy@v0.25.7/command/deps.js +1 -0
  111. package/esm/deps/deno.land/x/cliffy@v0.25.7/command/help/_help_generator.d.ts +27 -0
  112. package/esm/deps/deno.land/x/cliffy@v0.25.7/command/help/_help_generator.js +323 -0
  113. package/esm/deps/deno.land/x/cliffy@v0.25.7/command/help/mod.d.ts +6 -0
  114. package/esm/deps/deno.land/x/cliffy@v0.25.7/command/help/mod.js +34 -0
  115. package/esm/deps/deno.land/x/cliffy@v0.25.7/command/mod.d.ts +18 -0
  116. package/esm/deps/deno.land/x/cliffy@v0.25.7/command/mod.js +17 -0
  117. package/esm/deps/deno.land/x/cliffy@v0.25.7/command/type.d.ts +41 -0
  118. package/esm/deps/deno.land/x/cliffy@v0.25.7/command/type.js +24 -0
  119. package/esm/deps/deno.land/x/cliffy@v0.25.7/command/types/action_list.d.ts +9 -0
  120. package/esm/deps/deno.land/x/cliffy@v0.25.7/command/types/action_list.js +20 -0
  121. package/esm/deps/deno.land/x/cliffy@v0.25.7/command/types/boolean.d.ts +9 -0
  122. package/esm/deps/deno.land/x/cliffy@v0.25.7/command/types/boolean.js +13 -0
  123. package/esm/deps/deno.land/x/cliffy@v0.25.7/command/types/child_command.d.ts +9 -0
  124. package/esm/deps/deno.land/x/cliffy@v0.25.7/command/types/child_command.js +27 -0
  125. package/esm/deps/deno.land/x/cliffy@v0.25.7/command/types/command.d.ts +7 -0
  126. package/esm/deps/deno.land/x/cliffy@v0.25.7/command/types/command.js +9 -0
  127. package/esm/deps/deno.land/x/cliffy@v0.25.7/command/types/enum.d.ts +10 -0
  128. package/esm/deps/deno.land/x/cliffy@v0.25.7/command/types/enum.js +29 -0
  129. package/esm/deps/deno.land/x/cliffy@v0.25.7/command/types/file.d.ts +5 -0
  130. package/esm/deps/deno.land/x/cliffy@v0.25.7/command/types/file.js +12 -0
  131. package/esm/deps/deno.land/x/cliffy@v0.25.7/command/types/integer.d.ts +7 -0
  132. package/esm/deps/deno.land/x/cliffy@v0.25.7/command/types/integer.js +9 -0
  133. package/esm/deps/deno.land/x/cliffy@v0.25.7/command/types/number.d.ts +7 -0
  134. package/esm/deps/deno.land/x/cliffy@v0.25.7/command/types/number.js +9 -0
  135. package/esm/deps/deno.land/x/cliffy@v0.25.7/command/types/string.d.ts +7 -0
  136. package/esm/deps/deno.land/x/cliffy@v0.25.7/command/types/string.js +9 -0
  137. package/esm/deps/deno.land/x/cliffy@v0.25.7/command/types.d.ts +118 -0
  138. package/esm/deps/deno.land/x/cliffy@v0.25.7/command/types.js +2 -0
  139. package/esm/deps/deno.land/x/cliffy@v0.25.7/command/upgrade/mod.d.ts +5 -0
  140. package/esm/deps/deno.land/x/cliffy@v0.25.7/command/upgrade/mod.js +5 -0
  141. package/esm/deps/deno.land/x/cliffy@v0.25.7/command/upgrade/provider/deno_land.d.ts +14 -0
  142. package/esm/deps/deno.land/x/cliffy@v0.25.7/command/upgrade/provider/deno_land.js +46 -0
  143. package/esm/deps/deno.land/x/cliffy@v0.25.7/command/upgrade/provider/github.d.ts +26 -0
  144. package/esm/deps/deno.land/x/cliffy@v0.25.7/command/upgrade/provider/github.js +118 -0
  145. package/esm/deps/deno.land/x/cliffy@v0.25.7/command/upgrade/provider/nest_land.d.ts +14 -0
  146. package/esm/deps/deno.land/x/cliffy@v0.25.7/command/upgrade/provider/nest_land.js +55 -0
  147. package/esm/deps/deno.land/x/cliffy@v0.25.7/command/upgrade/provider.d.ts +27 -0
  148. package/esm/deps/deno.land/x/cliffy@v0.25.7/command/upgrade/provider.js +102 -0
  149. package/esm/deps/deno.land/x/cliffy@v0.25.7/command/upgrade/upgrade_command.d.ts +17 -0
  150. package/esm/deps/deno.land/x/cliffy@v0.25.7/command/upgrade/upgrade_command.js +75 -0
  151. package/esm/deps/deno.land/x/cliffy@v0.25.7/flags/_errors.d.ts +60 -0
  152. package/esm/deps/deno.land/x/cliffy@v0.25.7/flags/_errors.js +117 -0
  153. package/esm/deps/deno.land/x/cliffy@v0.25.7/flags/_utils.d.ts +18 -0
  154. package/esm/deps/deno.land/x/cliffy@v0.25.7/flags/_utils.js +106 -0
  155. package/esm/deps/deno.land/x/cliffy@v0.25.7/flags/_validate_flags.d.ts +10 -0
  156. package/esm/deps/deno.land/x/cliffy@v0.25.7/flags/_validate_flags.js +157 -0
  157. package/esm/deps/deno.land/x/cliffy@v0.25.7/flags/deprecated.d.ts +24 -0
  158. package/esm/deps/deno.land/x/cliffy@v0.25.7/flags/deprecated.js +9 -0
  159. package/esm/deps/deno.land/x/cliffy@v0.25.7/flags/flags.d.ts +33 -0
  160. package/esm/deps/deno.land/x/cliffy@v0.25.7/flags/flags.js +402 -0
  161. package/esm/deps/deno.land/x/cliffy@v0.25.7/flags/types/boolean.d.ts +3 -0
  162. package/esm/deps/deno.land/x/cliffy@v0.25.7/flags/types/boolean.js +11 -0
  163. package/esm/deps/deno.land/x/cliffy@v0.25.7/flags/types/integer.d.ts +3 -0
  164. package/esm/deps/deno.land/x/cliffy@v0.25.7/flags/types/integer.js +9 -0
  165. package/esm/deps/deno.land/x/cliffy@v0.25.7/flags/types/number.d.ts +3 -0
  166. package/esm/deps/deno.land/x/cliffy@v0.25.7/flags/types/number.js +9 -0
  167. package/esm/deps/deno.land/x/cliffy@v0.25.7/flags/types/string.d.ts +3 -0
  168. package/esm/deps/deno.land/x/cliffy@v0.25.7/flags/types/string.js +4 -0
  169. package/esm/deps/deno.land/x/cliffy@v0.25.7/flags/types.d.ts +59 -0
  170. package/esm/deps/deno.land/x/cliffy@v0.25.7/flags/types.js +1 -0
  171. package/esm/deps/deno.land/x/cliffy@v0.25.7/table/border.d.ts +20 -0
  172. package/esm/deps/deno.land/x/cliffy@v0.25.7/table/border.js +18 -0
  173. package/esm/deps/deno.land/x/cliffy@v0.25.7/table/cell.d.ts +78 -0
  174. package/esm/deps/deno.land/x/cliffy@v0.25.7/table/cell.js +128 -0
  175. package/esm/deps/deno.land/x/cliffy@v0.25.7/table/deps.d.ts +1 -0
  176. package/esm/deps/deno.land/x/cliffy@v0.25.7/table/deps.js +1 -0
  177. package/esm/deps/deno.land/x/cliffy@v0.25.7/table/layout.d.ts +99 -0
  178. package/esm/deps/deno.land/x/cliffy@v0.25.7/table/layout.js +529 -0
  179. package/esm/deps/deno.land/x/cliffy@v0.25.7/table/row.d.ts +49 -0
  180. package/esm/deps/deno.land/x/cliffy@v0.25.7/table/row.js +74 -0
  181. package/esm/deps/deno.land/x/cliffy@v0.25.7/table/table.d.ts +135 -0
  182. package/esm/deps/deno.land/x/cliffy@v0.25.7/table/table.js +237 -0
  183. package/esm/deps/deno.land/x/cliffy@v0.25.7/table/utils.d.ts +13 -0
  184. package/esm/deps/deno.land/x/cliffy@v0.25.7/table/utils.js +60 -0
  185. package/esm/package.json +3 -0
  186. package/esm/src/action/add.d.ts +1 -0
  187. package/esm/src/action/add.js +57 -0
  188. package/esm/src/action/clone.d.ts +6 -0
  189. package/esm/src/action/clone.js +108 -0
  190. package/esm/src/action/lang.d.ts +1 -0
  191. package/esm/src/action/lang.js +40 -0
  192. package/esm/src/action/pull.d.ts +1 -0
  193. package/esm/src/action/pull.js +22 -0
  194. package/esm/src/action/remove.d.ts +4 -0
  195. package/esm/src/action/remove.js +67 -0
  196. package/esm/src/action/reset.d.ts +1 -0
  197. package/esm/src/action/reset.js +21 -0
  198. package/esm/src/action/run.d.ts +4 -0
  199. package/esm/src/action/run.js +163 -0
  200. package/esm/src/action/status.d.ts +1 -0
  201. package/esm/src/action/status.js +5 -0
  202. package/esm/src/main.d.ts +2 -0
  203. package/esm/src/main.js +96 -0
  204. package/esm/src/meta.d.ts +3 -0
  205. package/esm/src/meta.js +51 -0
  206. package/esm/src/orca/client.d.ts +20 -0
  207. package/esm/src/orca/client.js +152 -0
  208. package/esm/src/orca/types.d.ts +54 -0
  209. package/esm/src/orca/types.js +12 -0
  210. package/esm/src/shared/config.d.ts +24 -0
  211. package/esm/src/shared/config.js +24 -0
  212. package/esm/src/shared/errors.d.ts +82 -0
  213. package/esm/src/shared/errors.js +228 -0
  214. package/esm/src/shared/file.d.ts +30 -0
  215. package/esm/src/shared/file.js +110 -0
  216. package/esm/src/shared/mod.d.ts +40 -0
  217. package/esm/src/shared/mod.js +383 -0
  218. package/esm/src/shared/types.d.ts +12 -0
  219. package/esm/src/shared/types.js +1 -0
  220. package/esm/src/track/client.d.ts +60 -0
  221. package/esm/src/track/client.js +268 -0
  222. package/esm/src/track/types.d.ts +210 -0
  223. package/esm/src/track/types.js +40 -0
  224. package/package.json +35 -0
@@ -0,0 +1,22 @@
1
+ import * as dntShim from "../../_dnt.shims.js";
2
+ import { save as saveConfig } from "../shared/config.js";
3
+ import { archiveExistingChallengeFiles, downloadChallengeFilesTo, getCommonChallengeContext, } from "../shared/mod.js";
4
+ export async function pull() {
5
+ const trackContext = await getCommonChallengeContext();
6
+ const { api, codingContext, applicantExam, challengeResult, config, challengePosition, } = trackContext;
7
+ const configLang = config.programmingLanguage;
8
+ const currentLang = challengeResult.programmingLanguage;
9
+ const currentDir = dntShim.Deno.cwd();
10
+ if (configLang && currentLang && configLang !== currentLang) {
11
+ console.log("Your programming language has changed elsewhere since you last ran this challenge");
12
+ const selectedLanguage = await api.findProgrammingLanguage(configLang);
13
+ await archiveExistingChallengeFiles(config.orgName, challengePosition, { selectedLanguage, challengeDir: currentDir });
14
+ const updatedConfig = Object.assign({}, config, {
15
+ programmingLanguage: currentLang,
16
+ });
17
+ await saveConfig(updatedConfig);
18
+ }
19
+ const showFileDiff = true;
20
+ const includeTarball = false;
21
+ await downloadChallengeFilesTo(codingContext, currentDir, api, applicantExam.id, challengeResult.id, showFileDiff, includeTarball);
22
+ }
@@ -0,0 +1,4 @@
1
+ export interface RemoveOptions {
2
+ recursive?: boolean;
3
+ }
4
+ export declare function remove(filePaths: string[], options?: RemoveOptions): Promise<void>;
@@ -0,0 +1,67 @@
1
+ import * as dntShim from "../../_dnt.shims.js";
2
+ import { DeleteFilesNotAllowed, OtherError } from "../shared/errors.js";
3
+ import { isEmptyDirectory, pathsToFilenameSet, toNativeStyle, } from "../shared/file.js";
4
+ import { getCommonChallengeContext, listFileNames, printWorkingFileSet, } from "../shared/mod.js";
5
+ import { FileListType } from "../track/types.js";
6
+ import * as colors from "../../deps/deno.land/std@0.195.0/fmt/colors.js";
7
+ export async function remove(filePaths, options) {
8
+ const trackContext = await getCommonChallengeContext();
9
+ const { config, api, codingContext } = trackContext;
10
+ if (!codingContext.settings.allowNewFile) {
11
+ throw new DeleteFilesNotAllowed();
12
+ }
13
+ const requestedPathsToDelete = await pathsToFilenameSet(filePaths, {
14
+ recursive: options?.recursive,
15
+ allowNonExistent: false,
16
+ });
17
+ const filesToDelete = [];
18
+ const filesToKeep = [];
19
+ for (const path of listFileNames(codingContext, FileListType.UserAddedFiles)) {
20
+ if (requestedPathsToDelete.has(path)) {
21
+ filesToDelete.push(path);
22
+ }
23
+ else {
24
+ filesToKeep.push(path);
25
+ }
26
+ }
27
+ if (filesToDelete.length > 0) {
28
+ console.log(colors.green("Deleting:"));
29
+ for (const file of filesToDelete) {
30
+ console.log(`\t${toNativeStyle(file)}`);
31
+ }
32
+ console.log();
33
+ const saveFilesRequest = {
34
+ versionId: codingContext.challengeVersionId,
35
+ addedFiles: filesToKeep,
36
+ updatedFiles: {},
37
+ };
38
+ await api.saveFiles(config.applicantExamId, config.challengeResultId, saveFilesRequest);
39
+ await Promise.all(filesToDelete.map((file) => dntShim.Deno.remove(file)))
40
+ .catch((e) => Promise.reject(new OtherError(`An error occurred while deleting files: ${e}`)));
41
+ // For each file to delete, walk the file's parents and delete directories
42
+ // if they are empty, stopping at the first non-empty one.
43
+ for (const file of filesToDelete) {
44
+ let current = file;
45
+ const re = /\/[^/]+$/;
46
+ while (true) {
47
+ const parent = current.replace(re, "");
48
+ if (parent === current || parent === "." || parent === "/" ||
49
+ parent === "") {
50
+ break;
51
+ }
52
+ if (await isEmptyDirectory(parent)) {
53
+ await dntShim.Deno.remove(parent);
54
+ }
55
+ current = parent;
56
+ }
57
+ }
58
+ const newCodingContext = await api.getChallengeCodingContext(config.applicantExamId, config.challengeResultId);
59
+ printWorkingFileSet(newCodingContext);
60
+ }
61
+ else {
62
+ console.log("No files to delete.");
63
+ console.log(colors.red("Use --recursive or -r to delete directories"));
64
+ console.log();
65
+ printWorkingFileSet(codingContext);
66
+ }
67
+ }
@@ -0,0 +1 @@
1
+ export declare function reset(): Promise<void>;
@@ -0,0 +1,21 @@
1
+ import * as dntShim from "../../_dnt.shims.js";
2
+ import { archiveExistingChallengeFiles, downloadChallengeFilesTo, getCommonChallengeContext, } from "../shared/mod.js";
3
+ export async function reset() {
4
+ const trackContext = await getCommonChallengeContext();
5
+ const { config, api, codingContext, applicantExam, challengeResult, challengePosition, } = trackContext;
6
+ console.log("Your existing code will be archived in this directory and the original challenge code will be downloaded");
7
+ const shouldContinue = dntShim.confirm("Are you sure you want to reset this challenge?");
8
+ if (!shouldContinue) {
9
+ return;
10
+ }
11
+ const currentDir = dntShim.Deno.cwd();
12
+ const selectedLanguage = codingContext.selectedLanguage
13
+ ? await api.findProgrammingLanguage(codingContext.selectedLanguage)
14
+ : undefined;
15
+ await archiveExistingChallengeFiles(config.orgName, challengePosition, { selectedLanguage, challengeDir: currentDir });
16
+ await api.reset(config.applicantExamId, config.challengeResultId);
17
+ const newCodingContext = await api.getChallengeCodingContext(config.applicantExamId, config.challengeResultId);
18
+ const showFileDiff = false;
19
+ const includeTarball = true;
20
+ await downloadChallengeFilesTo(newCodingContext, currentDir, api, applicantExam.id, challengeResult.id, showFileDiff, includeTarball);
21
+ }
@@ -0,0 +1,4 @@
1
+ export interface RunOptions {
2
+ noSave?: boolean;
3
+ }
4
+ export declare function run(options?: RunOptions): Promise<void>;
@@ -0,0 +1,163 @@
1
+ import * as dntShim from "../../_dnt.shims.js";
2
+ import { webUrl } from "../shared/config.js";
3
+ import { CantReadFile } from "../shared/errors.js";
4
+ import { getCommonChallengeContext, listFileNames, printTimeLeft, } from "../shared/mod.js";
5
+ import { EnvSettings, FileListType, } from "../track/types.js";
6
+ import { OrcaClient } from "../orca/client.js";
7
+ import { FileType } from "../orca/types.js";
8
+ import * as colors from "../../deps/deno.land/std@0.195.0/fmt/colors.js";
9
+ export async function run(options) {
10
+ const trackContext = await getCommonChallengeContext();
11
+ const api = trackContext.api;
12
+ const config = trackContext.config;
13
+ const codingContext = trackContext.codingContext;
14
+ // const orcaHost = Deno.env.get("ORCA_HOST") || "track-prod-frontend.orca.run";
15
+ // Temporary code to retrieve the Orca host. Will be able to get from CodingContext in the future.
16
+ const orcaHost = await api.orcaHost();
17
+ const token = await api.orcaToken(codingContext.urlForOrcaToken);
18
+ const orca = new OrcaClient(orcaHost, token);
19
+ await orca.connect();
20
+ const envConfig = codingContext.answers.envConfig || EnvSettings.default;
21
+ await orca.prepare({
22
+ imageName: envConfig.imageName,
23
+ interactive: false,
24
+ cacheDirs: envConfig.cacheDirs,
25
+ username: envConfig.username,
26
+ baseDir: envConfig.baseDir,
27
+ });
28
+ const envVars = Object.assign({}, envConfig.variables);
29
+ envVars["CHALLENGE_LANGUAGE"] = codingContext.challengeLanguage;
30
+ if (codingContext.answers.appCommand) {
31
+ envVars["APP_COMMAND"] = codingContext.answers.appCommand;
32
+ }
33
+ await orca.envVars(envVars);
34
+ const files = Object.entries(await getAllEditableFileContent(codingContext))
35
+ .map(([name, content]) => ({
36
+ name,
37
+ content,
38
+ type: FileType.UTF8,
39
+ }));
40
+ let saveFilesRequest;
41
+ if (!options?.noSave) {
42
+ const updatedFiles = await getAllEditableFileContent(codingContext);
43
+ saveFilesRequest = {
44
+ versionId: codingContext.challengeVersionId,
45
+ addedFiles: codingContext.answers.addedFiles || [],
46
+ updatedFiles: updatedFiles,
47
+ };
48
+ console.log("Saving challenge files");
49
+ await api.saveFiles(config.applicantExamId, config.challengeResultId, saveFilesRequest);
50
+ console.log(colors.green("Challenge files saved"));
51
+ }
52
+ console.log();
53
+ console.log("Running Tests");
54
+ console.log("-".repeat(50));
55
+ console.log();
56
+ let buildRan = false;
57
+ const runId = dntShim.crypto.randomUUID();
58
+ // Run the initialize/build commands if they exist
59
+ let buildDoneData;
60
+ if ((codingContext.answers.build?.length || 0) > 0 ||
61
+ codingContext.settings.initialize.length > 0) {
62
+ const shellCommand = []
63
+ .concat(codingContext.settings.initialize)
64
+ .concat(codingContext.answers.build || [])
65
+ .filter((s) => s && s.length > 0);
66
+ const runCmd = {
67
+ id: `${runId}-build`,
68
+ imageName: envConfig.imageName,
69
+ workingDir: envConfig.workingDir ?? "",
70
+ shellCmd: shellCommand.join(" && "),
71
+ attachVolume: true,
72
+ files,
73
+ envVars: {},
74
+ tarballUrls: codingContext.tarballUrls,
75
+ };
76
+ buildRan = true;
77
+ buildDoneData = await orca.simpleRunCommand(runCmd);
78
+ }
79
+ // Run the actual command
80
+ if (!buildDoneData || buildDoneData.exitCode === 0) {
81
+ const runCmd = {
82
+ id: `${runId}-run`,
83
+ imageName: envConfig.imageName,
84
+ workingDir: envConfig.workingDir ?? "",
85
+ shellCmd: codingContext.settings.test,
86
+ attachVolume: true,
87
+ files: buildRan ? [] : files,
88
+ envVars: {},
89
+ tarballUrls: buildRan ? [] : codingContext.tarballUrls,
90
+ };
91
+ const scoreCounter = new CountPassingLineHandler();
92
+ const runDoneData = await orca.simpleRunCommand(runCmd, scoreCounter);
93
+ console.log(`exit_code = ${runDoneData.exitCode}, reason = ${runDoneData.reason}`);
94
+ console.log();
95
+ console.log("Test Results");
96
+ console.log("-".repeat(50));
97
+ console.log();
98
+ if (trackContext.challenge.openTestcases) {
99
+ const totalPassed = scoreCounter.totalPassed();
100
+ const scoreStr = `${totalPassed}/${trackContext.challenge.openTestcases}`;
101
+ console.log(`Score: ${colors.green(scoreStr)}`);
102
+ await api.updateEditorScore(config.applicantExamId, config.challengeResultId, totalPassed);
103
+ }
104
+ const timeLeft = await api.timeLeft(config.applicantExamId, config.challengeResultId);
105
+ printTimeLeft(timeLeft);
106
+ }
107
+ else {
108
+ console.log();
109
+ console.log(colors.red("Build error!"));
110
+ }
111
+ // If we saved the files, print out the files we actually saved
112
+ // and where the user can find them in the web editor
113
+ if (saveFilesRequest) {
114
+ const updatedDisplayFiles = Object.keys(saveFilesRequest.updatedFiles);
115
+ updatedDisplayFiles.sort();
116
+ console.log();
117
+ console.log("Saved:");
118
+ console.log();
119
+ for (const file of updatedDisplayFiles) {
120
+ console.log(colors.green(`\t${file}`));
121
+ }
122
+ const url = `${webUrl(config)}/challenges/${config.challengeId}`;
123
+ console.log();
124
+ console.log(`Files uploaded successfully to ${url}`);
125
+ }
126
+ }
127
+ async function getAllEditableFileContent(context) {
128
+ const result = {};
129
+ for (const filePath of listFileNames(context, FileListType.Editable)) {
130
+ try {
131
+ const fileStr = await dntShim.Deno.readFile(filePath);
132
+ result[filePath] = new TextDecoder().decode(fileStr);
133
+ }
134
+ catch (_e) {
135
+ throw new CantReadFile(filePath);
136
+ }
137
+ }
138
+ return result;
139
+ }
140
+ class CountPassingLineHandler {
141
+ constructor() {
142
+ Object.defineProperty(this, "_totalPassed", {
143
+ enumerable: true,
144
+ configurable: true,
145
+ writable: true,
146
+ value: 0
147
+ });
148
+ Object.defineProperty(this, "_passPattern", {
149
+ enumerable: true,
150
+ configurable: true,
151
+ writable: true,
152
+ value: /^ok \d+/
153
+ });
154
+ }
155
+ totalPassed() {
156
+ return this._totalPassed;
157
+ }
158
+ handleLine(line) {
159
+ if (this._passPattern.test(line)) {
160
+ this._totalPassed += 1;
161
+ }
162
+ }
163
+ }
@@ -0,0 +1 @@
1
+ export declare function status(): Promise<void>;
@@ -0,0 +1,5 @@
1
+ import { getCommonChallengeContext, printChallengeInfo } from "../shared/mod.js";
2
+ export async function status() {
3
+ const trackContext = await getCommonChallengeContext();
4
+ await printChallengeInfo(trackContext);
5
+ }
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ import "../_dnt.polyfills.js";
@@ -0,0 +1,96 @@
1
+ #!/usr/bin/env node
2
+ import "../_dnt.polyfills.js";
3
+ import * as dntShim from "../_dnt.shims.js";
4
+ import { clone as cloneAction } from "./action/clone.js";
5
+ import { run as runAction } from "./action/run.js";
6
+ import { lang as langAction } from "./action/lang.js";
7
+ import { reset as resetAction } from "./action/reset.js";
8
+ import { pull as pullAction } from "./action/pull.js";
9
+ import { add as addAction } from "./action/add.js";
10
+ import { remove as removeAction } from "./action/remove.js";
11
+ import { status as statusAction } from "./action/status.js";
12
+ import { checkUpdates, DESCRIPTION, VERSION } from "./meta.js";
13
+ import { TrackError } from "./shared/errors.js";
14
+ import { red } from "../deps/deno.land/std@0.195.0/fmt/colors.js";
15
+ import { Command } from "../deps/deno.land/x/cliffy@v0.25.7/command/mod.js";
16
+ (async () => {
17
+ const cloneCommand = new Command()
18
+ .description("Clone challenge result from tracks.run")
19
+ .arguments("<url:string> [target_dir:string]")
20
+ .option("--basic-auth-user <user:string>", "The basic auth username if this server requires Basic Authentication")
21
+ .option("--basic-auth-password <password:string>", "The basic auth password if this server requires Basic Authentication (leave blank to type in manually)")
22
+ .action(async ({ basicAuthUser, basicAuthPassword }, ...[url, targetDir]) => {
23
+ await cloneAction(url, {
24
+ targetDir,
25
+ basicAuthUser,
26
+ basicAuthPassword,
27
+ });
28
+ });
29
+ const runCommand = new Command()
30
+ .description("Save and run the challenge on the remote code execution server")
31
+ .option("--no-save", "If this flag is specified, your files will not be uploaded to track after running the challenge tests")
32
+ .action(async ({ save }) => {
33
+ await runAction({ noSave: !save });
34
+ });
35
+ const langCommand = new Command()
36
+ .description("Change the programming language used for this challenge.")
37
+ .action(async () => {
38
+ await langAction();
39
+ });
40
+ const resetCommand = new Command()
41
+ .description("Reset the challenge files back to their starting point and archive your current challenge files")
42
+ .action(async () => {
43
+ await resetAction();
44
+ });
45
+ const pullCommand = new Command()
46
+ .description("Pull your most recent changes into this directory (caution: overwrites existing files)")
47
+ .action(async () => {
48
+ await pullAction();
49
+ });
50
+ const addCommand = new Command()
51
+ .description("Add a file to be included in your challenge submission")
52
+ .arguments("<file_paths...:string>")
53
+ .action(async (_, ...filePaths) => {
54
+ await addAction(filePaths);
55
+ });
56
+ const removeCommand = new Command()
57
+ .description("Remove files from your challenge submission")
58
+ .arguments("<file_paths...:string>")
59
+ .option("-r --recursive", "Allow recursive removal when a directory is given")
60
+ .action(async ({ recursive }, ...filePaths) => {
61
+ await removeAction(filePaths, { recursive });
62
+ });
63
+ const statusCommand = new Command()
64
+ .description("Display the current status for this challenge")
65
+ .action(async () => {
66
+ await statusAction();
67
+ });
68
+ if (!await checkUpdates()) {
69
+ dntShim.Deno.exit(1);
70
+ }
71
+ await new Command()
72
+ .name("track")
73
+ .description(DESCRIPTION)
74
+ .version(`v${VERSION}`)
75
+ .action(function () {
76
+ this.showHelp();
77
+ })
78
+ .command("clone", cloneCommand)
79
+ .command("run", runCommand)
80
+ .command("lang", langCommand)
81
+ .command("reset", resetCommand)
82
+ .command("pull", pullCommand)
83
+ .command("add", addCommand)
84
+ .command("rm", removeCommand)
85
+ .command("status", statusCommand)
86
+ .parse(dntShim.Deno.args);
87
+ dntShim.Deno.exit(0);
88
+ })().catch((err) => {
89
+ if (err instanceof TrackError) {
90
+ console.error(`${red("[ERROR]")} ${err.message}`);
91
+ dntShim.Deno.exit(1);
92
+ }
93
+ else {
94
+ throw err;
95
+ }
96
+ });
@@ -0,0 +1,3 @@
1
+ export declare const VERSION = "3.0.0-rc1";
2
+ export declare const DESCRIPTION = "A CLI for interacting with tracks.run and running code tests on track's servers";
3
+ export declare function checkUpdates(): Promise<boolean>;
@@ -0,0 +1,51 @@
1
+ import * as colors from "../deps/deno.land/std@0.195.0/fmt/colors.js";
2
+ // @ts-ignore: has no exported member
3
+ import { CookieJar, fetch } from "node-fetch-cookies";
4
+ export const VERSION = "3.0.0-rc1";
5
+ export const DESCRIPTION = "A CLI for interacting with tracks.run and running code tests on track's servers";
6
+ const VERSION_RE = /^(\d+)\.(\d+)\.(\d+)(?:-?(.*))$/;
7
+ function parseSemver(s) {
8
+ const match = VERSION_RE.exec(s);
9
+ if (!match) {
10
+ return;
11
+ }
12
+ return [
13
+ parseInt(match[1]),
14
+ parseInt(match[2]),
15
+ parseInt(match[3]),
16
+ match[4],
17
+ ];
18
+ }
19
+ export async function checkUpdates() {
20
+ const res = await fetch(new CookieJar(), "https://track-cli.s3-ap-northeast-1.amazonaws.com/version.json");
21
+ const publishedVersion = await res.json();
22
+ const supportedFrom = parseSemver(publishedVersion.supported_from) ??
23
+ [1, 0, 0, ""];
24
+ const latest = parseSemver(publishedVersion.latest) ?? [1, 0, 0, ""];
25
+ const current = parseSemver(VERSION);
26
+ // deno-fmt-ignore
27
+ if (parseSemver(VERSION) < supportedFrom) {
28
+ console.log("╭─────────────────────────────────────────────────────────────────────────────────────────────╮");
29
+ console.log("| |");
30
+ console.log(`| ${colors.bold(colors.red("!!! OUTDATED !!!"))} |`);
31
+ console.log("| This version of Track CLI is no more supported. |");
32
+ console.log(`| Current version: ${VERSION.padEnd(20)} |`);
33
+ console.log(`| Latest version: ${publishedVersion.latest.padEnd(20)} |`);
34
+ console.log("| |");
35
+ console.log("╰─────────────────────────────────────────────────────────────────────────────────────────────╯");
36
+ return false;
37
+ }
38
+ else if (current < latest) {
39
+ console.log("╭─────────────────────────────────────────────────────────────────────────────────────────────╮");
40
+ console.log("| |");
41
+ console.log("| New version of Track CLI is available! |");
42
+ console.log(`| Current version: ${VERSION.padEnd(20)} |`);
43
+ console.log(`| Latest version: ${publishedVersion.latest.padEnd(20)} |`);
44
+ console.log("| |");
45
+ console.log("╰─────────────────────────────────────────────────────────────────────────────────────────────╯");
46
+ return true;
47
+ }
48
+ else {
49
+ return true;
50
+ }
51
+ }
@@ -0,0 +1,20 @@
1
+ import { CommandDoneData, LineHandler, PrepareCommand, SimpleRunCommand } from "./types.js";
2
+ export declare class OrcaClient {
3
+ private hostname;
4
+ private token?;
5
+ private socket?;
6
+ private eventEmitter;
7
+ constructor(hostname: string, token?: string | undefined);
8
+ connect(): Promise<void>;
9
+ private handleMessage;
10
+ private handleStdOut;
11
+ private handleStdErr;
12
+ private handleCommandDone;
13
+ private printCommandResultWithColor;
14
+ on(eventName: string, func: (...args: unknown[]) => void): void;
15
+ off(eventName: string, func: (...args: unknown[]) => void): void;
16
+ private send;
17
+ prepare(request: PrepareCommand): Promise<void>;
18
+ envVars(envVars: Record<string, string>): Promise<void>;
19
+ simpleRunCommand(request: SimpleRunCommand, lineHandler?: LineHandler): Promise<CommandDoneData>;
20
+ }
@@ -0,0 +1,152 @@
1
+ import * as dntShim from "../../_dnt.shims.js";
2
+ import { OtherError } from "../shared/errors.js";
3
+ import { SnakeCase } from "../shared/mod.js";
4
+ import { green, red } from "../../deps/deno.land/std@0.195.0/fmt/colors.js";
5
+ import { EventEmitter } from "eventemitter3";
6
+ import ProxyAgent from "proxy-agent";
7
+ import WebSocket from "ws";
8
+ const RE_TAP_OK = new RegExp("^ok \\d+ ");
9
+ const RE_TAP_NG = new RegExp("^not ok \\d+ ");
10
+ export class OrcaClient {
11
+ constructor(hostname, token) {
12
+ Object.defineProperty(this, "hostname", {
13
+ enumerable: true,
14
+ configurable: true,
15
+ writable: true,
16
+ value: hostname
17
+ });
18
+ Object.defineProperty(this, "token", {
19
+ enumerable: true,
20
+ configurable: true,
21
+ writable: true,
22
+ value: token
23
+ });
24
+ Object.defineProperty(this, "socket", {
25
+ enumerable: true,
26
+ configurable: true,
27
+ writable: true,
28
+ value: void 0
29
+ });
30
+ Object.defineProperty(this, "eventEmitter", {
31
+ enumerable: true,
32
+ configurable: true,
33
+ writable: true,
34
+ value: new EventEmitter()
35
+ });
36
+ }
37
+ connect() {
38
+ return new Promise((res, _rej) => {
39
+ const scheme = this.hostname.startsWith("localhost") ? "ws://" : "wss://";
40
+ const query = this.token ? `?token=${this.token}` : "";
41
+ const url = `${scheme}${this.hostname}/socket${query}`;
42
+ const options = { agent: new ProxyAgent() };
43
+ const socket = new WebSocket(url, options);
44
+ socket.onmessage = this.handleMessage.bind(this);
45
+ socket.onopen = () => {
46
+ console.log("WebSocket connection established");
47
+ res();
48
+ this.eventEmitter.emit("connect", url);
49
+ };
50
+ socket.onclose = (event) => {
51
+ console.log(event);
52
+ console.log(`WebSocket connection closed with code: ${event.code}`);
53
+ this.eventEmitter.emit("disconnect", event.code);
54
+ };
55
+ this.socket = socket;
56
+ });
57
+ }
58
+ handleMessage(event) {
59
+ if (typeof event.data !== "string")
60
+ return;
61
+ const message = JSON.parse(event.data);
62
+ const data = SnakeCase.from(message.data);
63
+ switch (message.e) {
64
+ case "stdout":
65
+ this.handleStdOut(data);
66
+ break;
67
+ case "stderr":
68
+ this.handleStdErr(data);
69
+ break;
70
+ case "cmd_done":
71
+ this.handleCommandDone(data);
72
+ break;
73
+ default:
74
+ break;
75
+ }
76
+ this.eventEmitter.emit(message.e, data);
77
+ }
78
+ handleStdOut(data) {
79
+ this.printCommandResultWithColor(data.l);
80
+ }
81
+ handleStdErr(data) {
82
+ console.log(data.l);
83
+ }
84
+ handleCommandDone(data) {
85
+ const reason = data.reason ? `: ${data.reason}` : "";
86
+ console.log(`Command ${data.id} done with exit code ${data.exitCode}${reason}`);
87
+ }
88
+ printCommandResultWithColor(s) {
89
+ const lines = s.split("\n");
90
+ const encoder = new TextEncoder();
91
+ function print(s, isLast = false) {
92
+ if (isLast) {
93
+ dntShim.Deno.stdout.write(encoder.encode(s));
94
+ }
95
+ else {
96
+ dntShim.Deno.stdout.write(encoder.encode(s + "\n"));
97
+ }
98
+ }
99
+ lines.forEach((line, i) => {
100
+ const isLast = i === lines.length - 1;
101
+ if (RE_TAP_OK.test(line)) {
102
+ print(green(line), isLast);
103
+ }
104
+ else if (RE_TAP_NG.test(line)) {
105
+ print(red(line), isLast);
106
+ }
107
+ else {
108
+ print(line, isLast);
109
+ }
110
+ });
111
+ }
112
+ on(eventName, func) {
113
+ this.eventEmitter.on(eventName, func);
114
+ }
115
+ off(eventName, func) {
116
+ this.eventEmitter.off(eventName, func);
117
+ }
118
+ send(commandName, eventName, data, toSnakeCase = true) {
119
+ return new Promise((res, rej) => {
120
+ this.eventEmitter.once(eventName, (e) => {
121
+ res(SnakeCase.from(e));
122
+ });
123
+ try {
124
+ const d = toSnakeCase ? SnakeCase.to(data) : data;
125
+ this.socket?.send(JSON.stringify({
126
+ e: commandName,
127
+ data: d,
128
+ }));
129
+ }
130
+ catch (e) {
131
+ rej(new OtherError(e.message));
132
+ }
133
+ });
134
+ }
135
+ prepare(request) {
136
+ return this.send("prepare", "prepare_done", request);
137
+ }
138
+ envVars(envVars) {
139
+ return this.send("env_vars", "env_vars_done", { env_vars: envVars }, false);
140
+ }
141
+ async simpleRunCommand(request, lineHandler) {
142
+ const handler = lineHandler?.handleLine
143
+ ? function (e) {
144
+ e.l.split("\n").forEach((line) => lineHandler.handleLine(line));
145
+ }
146
+ : (() => { });
147
+ this.on("stdout", handler);
148
+ const result = await this.send("simple_run", "cmd_done", request);
149
+ this.off("stdout", handler);
150
+ return result;
151
+ }
152
+ }