t3code-cli 0.10.0 → 0.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (328) hide show
  1. package/README.md +75 -11
  2. package/dist/application.js +2 -2
  3. package/dist/auth.js +1 -1
  4. package/dist/bin.js +86754 -2675
  5. package/dist/cli.js +15 -2
  6. package/dist/config.js +120 -2
  7. package/dist/connection.js +2 -12
  8. package/dist/index.js +1 -1
  9. package/dist/node.js +6 -0
  10. package/dist/orchestration.js +2 -2
  11. package/dist/rpc.js +2 -2
  12. package/dist/runtime.js +2 -2
  13. package/dist/shared.js +43850 -38040
  14. package/dist/src/application/actions.d.ts +25 -0
  15. package/dist/src/application/index.d.ts +3 -2
  16. package/dist/src/application/layer.d.ts +99 -842
  17. package/dist/src/application/model-selection.d.ts +17 -2
  18. package/dist/src/application/models.d.ts +1 -87
  19. package/dist/src/application/project-commands.d.ts +31 -2
  20. package/dist/src/application/projects.d.ts +15 -137
  21. package/dist/src/application/service.d.ts +147 -5
  22. package/dist/src/application/shell-sequence.d.ts +5 -4
  23. package/dist/src/application/terminals.d.ts +66 -0
  24. package/dist/src/application/thread-commands.d.ts +48 -1
  25. package/dist/src/application/thread-update.d.ts +8 -0
  26. package/dist/src/application/thread-wait.d.ts +4 -6
  27. package/dist/src/application/threads.d.ts +36 -14
  28. package/dist/src/auth/error.d.ts +2 -1
  29. package/dist/src/auth/index.d.ts +1 -1
  30. package/dist/src/auth/layer.d.ts +34 -6
  31. package/dist/src/auth/local-base-dir.d.ts +5 -2
  32. package/dist/src/auth/local-origin.d.ts +3 -3
  33. package/dist/src/auth/local-token.d.ts +3 -3
  34. package/dist/src/auth/service.d.ts +15 -3
  35. package/dist/src/auth/type.d.ts +40 -1
  36. package/dist/src/cli/env/flag.d.ts +2 -0
  37. package/dist/src/cli/env/index.d.ts +2 -0
  38. package/dist/src/cli/env/selection-layer.d.ts +3 -0
  39. package/dist/src/cli/flags.d.ts +5 -0
  40. package/dist/src/cli/format/index.d.ts +1 -0
  41. package/dist/src/cli/format/output.d.ts +12 -0
  42. package/dist/src/cli/index.d.ts +4 -0
  43. package/dist/src/cli/runtime/index.d.ts +1 -0
  44. package/dist/src/cli/runtime/service.d.ts +16 -0
  45. package/dist/src/{scope → cli/scope}/resolve.d.ts +5 -4
  46. package/dist/src/config/config.d.ts +49 -0
  47. package/dist/src/config/credential/cipher-node.d.ts +3 -0
  48. package/dist/src/config/credential/cipher-web.d.ts +3 -0
  49. package/dist/src/config/credential/cipher.d.ts +29 -0
  50. package/dist/src/config/credential/env.d.ts +3 -0
  51. package/dist/src/config/credential/error.d.ts +8 -0
  52. package/dist/src/config/credential/index.d.ts +6 -0
  53. package/dist/src/config/credential/service.d.ts +34 -0
  54. package/dist/src/config/env/env.d.ts +55 -0
  55. package/dist/src/config/env/index.d.ts +2 -0
  56. package/dist/src/{layout/base-dir.d.ts → config/env/layout.d.ts} +0 -1
  57. package/dist/src/config/environment-name/index.d.ts +1 -0
  58. package/dist/src/config/environment-name/name.d.ts +10 -0
  59. package/dist/src/config/error.d.ts +4 -11
  60. package/dist/src/config/index.d.ts +10 -5
  61. package/dist/src/config/keystore/error.d.ts +8 -0
  62. package/dist/src/config/keystore/file.d.ts +9 -0
  63. package/dist/src/config/keystore/index.d.ts +4 -0
  64. package/dist/src/config/keystore/keyring-node.d.ts +4 -0
  65. package/dist/src/config/keystore/service.d.ts +33 -0
  66. package/dist/src/config/paths/index.d.ts +1 -0
  67. package/dist/src/config/paths/paths.d.ts +6 -0
  68. package/dist/src/config/persist/file-mode.d.ts +4 -0
  69. package/dist/src/config/persist/migration.d.ts +68 -0
  70. package/dist/src/config/persist/persist.d.ts +40 -0
  71. package/dist/src/config/persist/schema.d.ts +68 -0
  72. package/dist/src/config/resolve/resolve.d.ts +40 -0
  73. package/dist/src/config/selection/index.d.ts +1 -0
  74. package/dist/src/config/selection/resolve.d.ts +4 -0
  75. package/dist/src/config/selection/service.d.ts +10 -0
  76. package/dist/src/config/types.d.ts +36 -0
  77. package/dist/src/config/url/error.d.ts +10 -0
  78. package/dist/src/config/url/index.d.ts +2 -0
  79. package/dist/src/connection/index.d.ts +0 -1
  80. package/dist/src/contracts/index.d.ts +1 -1
  81. package/dist/src/domain/error.d.ts +27 -1
  82. package/dist/src/domain/helpers.d.ts +8 -2
  83. package/dist/src/domain/model-config.d.ts +30 -1
  84. package/dist/src/domain/thread-activities.d.ts +1 -1
  85. package/dist/src/domain/thread-lifecycle.d.ts +3 -2
  86. package/dist/src/index.d.ts +1 -2
  87. package/dist/src/{connection/node.d.ts → node/connection.d.ts} +1 -1
  88. package/dist/src/node/index.d.ts +1 -0
  89. package/dist/src/orchestration/index.d.ts +1 -1
  90. package/dist/src/orchestration/layer.d.ts +120 -829
  91. package/dist/src/orchestration/service.d.ts +2 -1
  92. package/dist/src/rpc/error.d.ts +5 -3
  93. package/dist/src/rpc/index.d.ts +5 -1
  94. package/dist/src/rpc/layer.d.ts +1166 -40
  95. package/dist/src/rpc/operation.d.ts +6280 -0
  96. package/dist/src/rpc/ws-group.d.ts +372 -27
  97. package/dist/src/runtime/index.d.ts +1 -2
  98. package/dist/src/runtime/layer.d.ts +12 -8
  99. package/dist/src/t3tools/index.d.ts +1 -1
  100. package/dist/t3tools.js +2 -2
  101. package/package.json +27 -19
  102. package/src/application/actions.test.ts +328 -0
  103. package/src/application/actions.ts +475 -0
  104. package/src/application/index.ts +32 -2
  105. package/src/application/layer.ts +43 -5
  106. package/src/application/model-selection.ts +70 -4
  107. package/src/application/models.ts +14 -14
  108. package/src/application/project-commands.ts +38 -5
  109. package/src/application/projects.ts +49 -20
  110. package/src/application/service.ts +275 -78
  111. package/src/application/shell-sequence.ts +6 -8
  112. package/src/application/terminals.ts +208 -0
  113. package/src/application/thread-commands.test.ts +43 -0
  114. package/src/application/thread-commands.ts +82 -1
  115. package/src/application/thread-update.ts +72 -0
  116. package/src/application/thread-wait.ts +47 -48
  117. package/src/application/threads.test.ts +172 -0
  118. package/src/application/threads.ts +128 -45
  119. package/src/auth/error.ts +2 -1
  120. package/src/auth/index.ts +7 -0
  121. package/src/auth/layer.test-utils.ts +34 -0
  122. package/src/auth/layer.ts +116 -34
  123. package/src/auth/local-base-dir.ts +13 -6
  124. package/src/auth/local-origin.ts +10 -7
  125. package/src/auth/local-token.ts +28 -23
  126. package/src/auth/service.test.ts +200 -0
  127. package/src/auth/service.ts +27 -3
  128. package/src/auth/transport.ts +2 -2
  129. package/src/auth/type.ts +47 -1
  130. package/src/bin.ts +26 -6
  131. package/src/cli/action-format.ts +110 -0
  132. package/src/cli/action.ts +398 -0
  133. package/src/cli/app.ts +8 -0
  134. package/src/cli/auth.ts +76 -23
  135. package/src/cli/env/flag.ts +8 -0
  136. package/src/cli/env/index.ts +2 -0
  137. package/src/cli/env/selection-layer.test.ts +49 -0
  138. package/src/cli/env/selection-layer.ts +27 -0
  139. package/src/cli/env.ts +107 -0
  140. package/src/cli/error.ts +26 -3
  141. package/src/cli/extra-args.test.ts +32 -0
  142. package/src/cli/extra-args.ts +22 -0
  143. package/src/cli/flags.ts +26 -1
  144. package/src/cli/format/auth.ts +92 -0
  145. package/src/cli/format/human.ts +131 -0
  146. package/src/cli/format/index.ts +12 -0
  147. package/src/cli/format/model.ts +29 -0
  148. package/src/cli/format/output.ts +51 -0
  149. package/src/cli/format/project.ts +32 -0
  150. package/src/cli/format/terminal.ts +87 -0
  151. package/src/cli/format/thread.test.ts +34 -0
  152. package/src/cli/format/thread.ts +185 -0
  153. package/src/cli/index.ts +20 -0
  154. package/src/cli/input/layer.ts +20 -0
  155. package/src/cli/input/service.ts +1 -0
  156. package/src/cli/interaction/confirm.ts +64 -0
  157. package/src/cli/interaction/self-action.ts +36 -0
  158. package/src/cli/message-input.ts +1 -1
  159. package/src/cli/model.ts +9 -5
  160. package/src/cli/project.ts +15 -8
  161. package/src/cli/projects/delete.ts +51 -0
  162. package/src/cli/require.ts +9 -7
  163. package/src/cli/runtime/index.ts +1 -0
  164. package/src/cli/runtime/service.ts +28 -0
  165. package/src/{scope → cli/scope}/resolve.ts +11 -9
  166. package/src/cli/terminal/attach.ts +29 -0
  167. package/src/cli/terminal/create.ts +55 -0
  168. package/src/cli/terminal/destroy.ts +62 -0
  169. package/src/cli/terminal/encoding.test.ts +63 -0
  170. package/src/cli/terminal/encoding.ts +23 -0
  171. package/src/cli/terminal/error.ts +14 -0
  172. package/src/cli/terminal/io-node-layer.ts +82 -0
  173. package/src/cli/terminal/io-service.ts +25 -0
  174. package/src/cli/terminal/list.ts +36 -0
  175. package/src/cli/terminal/read.test-utils.ts +48 -0
  176. package/src/cli/terminal/read.test.ts +35 -0
  177. package/src/cli/terminal/read.ts +99 -0
  178. package/src/cli/terminal/scope.ts +35 -0
  179. package/src/cli/terminal/shared.ts +250 -0
  180. package/src/cli/terminal/stream.ts +61 -0
  181. package/src/cli/terminal/wait.test.ts +148 -0
  182. package/src/cli/terminal/wait.ts +223 -0
  183. package/src/cli/terminal/write.test.ts +34 -0
  184. package/src/cli/terminal/write.ts +133 -0
  185. package/src/cli/terminal.ts +26 -0
  186. package/src/cli/thread.ts +8 -0
  187. package/src/cli/threads/approve.ts +11 -7
  188. package/src/cli/threads/archive.ts +23 -25
  189. package/src/cli/threads/callback.ts +6 -4
  190. package/src/cli/threads/delete.ts +67 -0
  191. package/src/cli/threads/interrupt.ts +57 -0
  192. package/src/cli/threads/list.test.ts +71 -0
  193. package/src/cli/threads/list.ts +25 -13
  194. package/src/cli/threads/messages.ts +11 -7
  195. package/src/cli/threads/respond.ts +11 -7
  196. package/src/cli/threads/send.ts +39 -9
  197. package/src/cli/threads/show.ts +11 -7
  198. package/src/cli/threads/start.ts +18 -13
  199. package/src/cli/threads/unarchive.ts +48 -0
  200. package/src/cli/threads/update.ts +155 -0
  201. package/src/cli/threads/wait.ts +11 -7
  202. package/src/cli/wait-events.ts +1 -1
  203. package/src/config/config.ts +260 -0
  204. package/src/config/credential/cipher-node.ts +40 -0
  205. package/src/config/credential/cipher-web.ts +82 -0
  206. package/src/config/credential/cipher.ts +39 -0
  207. package/src/config/credential/env.ts +13 -0
  208. package/src/config/credential/error.ts +9 -0
  209. package/src/config/credential/index.ts +6 -0
  210. package/src/config/credential/service.test-utils.ts +25 -0
  211. package/src/config/credential/service.test.ts +116 -0
  212. package/src/config/credential/service.ts +205 -0
  213. package/src/config/env/env.test-utils.ts +14 -0
  214. package/src/config/env/env.ts +81 -0
  215. package/src/config/env/index.ts +2 -0
  216. package/src/{layout/base-dir.ts → config/env/layout.ts} +0 -9
  217. package/src/config/environment-name/index.ts +7 -0
  218. package/src/config/environment-name/name.test.ts +66 -0
  219. package/src/config/environment-name/name.ts +49 -0
  220. package/src/config/error.ts +6 -8
  221. package/src/config/index.ts +16 -5
  222. package/src/config/keystore/error.ts +9 -0
  223. package/src/config/keystore/file.ts +96 -0
  224. package/src/config/keystore/index.ts +4 -0
  225. package/src/config/keystore/keyring-node.test.ts +12 -0
  226. package/src/config/keystore/keyring-node.ts +100 -0
  227. package/src/config/keystore/service.test-utils.ts +15 -0
  228. package/src/config/keystore/service.test.ts +18 -0
  229. package/src/config/keystore/service.ts +29 -0
  230. package/src/config/layer.test-utils.ts +45 -0
  231. package/src/config/layer.test.ts +209 -0
  232. package/src/config/paths/index.ts +1 -0
  233. package/src/config/paths/paths.ts +36 -0
  234. package/src/config/persist/file-mode.ts +21 -0
  235. package/src/config/persist/migration.test.ts +71 -0
  236. package/src/config/persist/migration.ts +82 -0
  237. package/src/config/persist/persist.test.ts +113 -0
  238. package/src/config/persist/persist.ts +65 -0
  239. package/src/config/persist/schema.ts +37 -0
  240. package/src/config/platform.test-utils.ts +20 -0
  241. package/src/config/resolve/resolve.test-utils.ts +20 -0
  242. package/src/config/resolve/resolve.test.ts +137 -0
  243. package/src/config/resolve/resolve.ts +104 -0
  244. package/src/config/selection/index.ts +1 -0
  245. package/src/config/selection/resolve.ts +14 -0
  246. package/src/config/selection/service.ts +29 -0
  247. package/src/config/temp-home.test-utils.ts +7 -0
  248. package/src/config/types.ts +49 -0
  249. package/src/config/url/error.ts +8 -0
  250. package/src/config/url/index.ts +7 -0
  251. package/src/config/url/url.test.ts +31 -0
  252. package/src/connection/index.ts +0 -1
  253. package/src/contracts/index.ts +1 -1
  254. package/src/domain/error.ts +39 -1
  255. package/src/domain/helpers.test.ts +1 -1
  256. package/src/domain/helpers.ts +1 -1
  257. package/src/domain/model-config.ts +5 -1
  258. package/src/domain/thread-activities.test.ts +1 -1
  259. package/src/domain/thread-activities.ts +1 -1
  260. package/src/domain/thread-lifecycle.test.ts +1 -1
  261. package/src/domain/thread-lifecycle.ts +15 -1
  262. package/src/effect.test-utils.ts +25 -0
  263. package/src/index.ts +1 -1
  264. package/src/{connection/node.ts → node/connection.ts} +1 -1
  265. package/src/node/index.ts +1 -0
  266. package/src/orchestration/index.ts +1 -1
  267. package/src/orchestration/layer.ts +34 -86
  268. package/src/orchestration/service.ts +5 -1
  269. package/src/rpc/error.ts +12 -2
  270. package/src/rpc/index.ts +5 -1
  271. package/src/rpc/layer.ts +1 -1
  272. package/src/rpc/operation.ts +83 -0
  273. package/src/rpc/ws-group.ts +25 -1
  274. package/src/runtime/index.ts +2 -1
  275. package/src/runtime/layer.test-utils.ts +32 -0
  276. package/src/runtime/layer.test.ts +66 -0
  277. package/src/runtime/layer.ts +22 -11
  278. package/src/t3tools/index.ts +1 -1
  279. package/src/types/marked-terminal.d.ts +11 -0
  280. package/dist/layout.js +0 -2
  281. package/dist/scope.js +0 -2
  282. package/dist/src/cli/output-format.d.ts +0 -9
  283. package/dist/src/config/layer.d.ts +0 -22
  284. package/dist/src/config/service.d.ts +0 -22
  285. package/dist/src/environment/layer.d.ts +0 -3
  286. package/dist/src/environment/service.d.ts +0 -12
  287. package/dist/src/layout/index.d.ts +0 -1
  288. package/dist/upstream-t3code/packages/contracts/src/auth.d.ts +0 -441
  289. package/dist/upstream-t3code/packages/contracts/src/baseSchemas.d.ts +0 -38
  290. package/dist/upstream-t3code/packages/contracts/src/desktopBootstrap.d.ts +0 -14
  291. package/dist/upstream-t3code/packages/contracts/src/editor.d.ts +0 -124
  292. package/dist/upstream-t3code/packages/contracts/src/environment.d.ts +0 -64
  293. package/dist/upstream-t3code/packages/contracts/src/environmentHttp.d.ts +0 -785
  294. package/dist/upstream-t3code/packages/contracts/src/filesystem.d.ts +0 -26
  295. package/dist/upstream-t3code/packages/contracts/src/git.d.ts +0 -500
  296. package/dist/upstream-t3code/packages/contracts/src/index.d.ts +0 -25
  297. package/dist/upstream-t3code/packages/contracts/src/ipc.d.ts +0 -496
  298. package/dist/upstream-t3code/packages/contracts/src/keybindings.d.ts +0 -133
  299. package/dist/upstream-t3code/packages/contracts/src/model.d.ts +0 -112
  300. package/dist/upstream-t3code/packages/contracts/src/orchestration.d.ts +0 -7338
  301. package/dist/upstream-t3code/packages/contracts/src/project.d.ts +0 -45
  302. package/dist/upstream-t3code/packages/contracts/src/provider.d.ts +0 -130
  303. package/dist/upstream-t3code/packages/contracts/src/providerInstance.d.ts +0 -99
  304. package/dist/upstream-t3code/packages/contracts/src/providerRuntime.d.ts +0 -4450
  305. package/dist/upstream-t3code/packages/contracts/src/relay.d.ts +0 -1262
  306. package/dist/upstream-t3code/packages/contracts/src/relayClient.d.ts +0 -48
  307. package/dist/upstream-t3code/packages/contracts/src/remoteAccess.d.ts +0 -45
  308. package/dist/upstream-t3code/packages/contracts/src/review.d.ts +0 -37
  309. package/dist/upstream-t3code/packages/contracts/src/rpc.d.ts +0 -8710
  310. package/dist/upstream-t3code/packages/contracts/src/server.d.ts +0 -2336
  311. package/dist/upstream-t3code/packages/contracts/src/settings.d.ts +0 -292
  312. package/dist/upstream-t3code/packages/contracts/src/sourceControl.d.ts +0 -177
  313. package/dist/upstream-t3code/packages/contracts/src/terminal.d.ts +0 -333
  314. package/dist/upstream-t3code/packages/contracts/src/vcs.d.ts +0 -148
  315. package/src/cli/auth-format.ts +0 -45
  316. package/src/cli/model-format.ts +0 -18
  317. package/src/cli/output-format.ts +0 -41
  318. package/src/cli/project-format.ts +0 -11
  319. package/src/cli/thread-format.ts +0 -121
  320. package/src/config/layer.ts +0 -105
  321. package/src/config/service.ts +0 -26
  322. package/src/environment/layer.ts +0 -12
  323. package/src/environment/service.ts +0 -13
  324. package/src/layout/index.ts +0 -1
  325. /package/dist/src/{scope → cli/scope}/index.d.ts +0 -0
  326. /package/dist/src/config/{url.d.ts → url/url.d.ts} +0 -0
  327. /package/src/{scope → cli/scope}/index.ts +0 -0
  328. /package/src/config/{url.ts → url/url.ts} +0 -0
package/src/cli/auth.ts CHANGED
@@ -8,14 +8,49 @@ import {
8
8
  formatAuthPaired,
9
9
  formatAuthStatusHuman,
10
10
  formatAuthStatusJson,
11
- } from "./auth-format.ts";
11
+ } from "./format/auth.ts";
12
12
  import { T3Auth } from "../auth/service.ts";
13
- import { T3Config } from "../config/service.ts";
14
- import { Environment } from "../environment/service.ts";
15
- import { formatFlag } from "./flags.ts";
16
- import { resolveOutputFormat } from "./output-format.ts";
13
+ import { extraArgsConfig } from "./extra-args.ts";
14
+ import { CliRuntime } from "../cli/runtime/service.ts";
15
+ import { loadT3CliEnv } from "../config/env/env.ts";
16
+ import { requireEnvironmentReplaceConfirmation } from "./interaction/confirm.ts";
17
+ import { envNameFlag, formatFlag, replaceFlag } from "./flags.ts";
18
+ import { resolveOutputFormat } from "./format/output.ts";
17
19
  import { T3Output } from "./output/service.ts";
18
20
 
21
+ const persistAuthEnvironment = Effect.fn("persistAuthEnvironment")(function* (input: {
22
+ readonly explicitName: Option.Option<string>;
23
+ readonly fallbackName: string;
24
+ readonly url: string;
25
+ readonly token: string;
26
+ readonly local: boolean;
27
+ readonly replace: boolean;
28
+ }) {
29
+ const auth = yield* T3Auth;
30
+ const cliRuntime = yield* CliRuntime;
31
+ const t3CliEnv = yield* loadT3CliEnv;
32
+ const environmentName = Option.isSome(input.explicitName)
33
+ ? input.explicitName.value
34
+ : input.fallbackName;
35
+ const exists = yield* auth.environmentExists(environmentName);
36
+ if (exists) {
37
+ yield* requireEnvironmentReplaceConfirmation({
38
+ name: environmentName,
39
+ replace: input.replace,
40
+ cliRuntime,
41
+ t3CliEnv,
42
+ });
43
+ }
44
+ return yield* auth.persistEnvironment({
45
+ name: environmentName,
46
+ url: input.url,
47
+ token: input.token,
48
+ local: input.local,
49
+ replace: input.replace,
50
+ allowReplace: true,
51
+ });
52
+ });
53
+
19
54
  export function createAuthCommand() {
20
55
  return Command.make("auth").pipe(
21
56
  Command.withDescription("auth commands"),
@@ -28,24 +63,33 @@ const pairCommand = Command.make(
28
63
  {
29
64
  url: Flag.string("url"),
30
65
  local: Flag.boolean("local"),
66
+ name: envNameFlag,
67
+ replace: replaceFlag,
31
68
  format: formatFlag,
69
+ ...extraArgsConfig,
32
70
  },
33
- ({ url, local, format }) =>
71
+ ({ url, local, name, replace, format }) =>
34
72
  Effect.gen(function* () {
35
73
  const auth = yield* T3Auth;
36
- const environment = yield* Environment;
74
+ const cliRuntime = yield* CliRuntime;
75
+ const t3CliEnv = yield* loadT3CliEnv;
37
76
  const output = yield* T3Output;
38
- const resolvedFormat = resolveOutputFormat(format, environment, "json");
77
+ const resolvedFormat = resolveOutputFormat(format, cliRuntime, t3CliEnv, "json");
39
78
  const result = yield* auth.pair(url);
40
- yield* auth.writeConfig({
79
+ const fallbackName = yield* auth.defaultNameFromUrl(result.url);
80
+ const environmentName = yield* persistAuthEnvironment({
81
+ explicitName: name,
82
+ fallbackName,
41
83
  url: result.url,
42
84
  token: result.token,
43
85
  local,
86
+ replace,
44
87
  });
88
+ const payload = { ...result, name: environmentName };
45
89
  if (resolvedFormat === "json") {
46
- yield* output.printJson(result);
90
+ yield* output.printJson(payload);
47
91
  } else {
48
- yield* output.printInfo(formatAuthPaired(result));
92
+ yield* output.printInfo(formatAuthPaired(payload));
49
93
  }
50
94
  }),
51
95
  ).pipe(Command.withDescription("pair with t3code server"));
@@ -58,14 +102,18 @@ const localCommand = Command.make(
58
102
  role: Flag.choice("role", ["owner", "client"] as const).pipe(Flag.withDefault("owner")),
59
103
  label: Flag.string("label").pipe(Flag.withDefault("t3cli")),
60
104
  subject: Flag.string("subject").pipe(Flag.withDefault("t3cli-local")),
105
+ name: envNameFlag,
106
+ replace: replaceFlag,
61
107
  format: formatFlag,
108
+ ...extraArgsConfig,
62
109
  },
63
- ({ baseDir, origin, role, label, subject, format }) =>
110
+ ({ baseDir, origin, role, label, subject, name, replace, format }) =>
64
111
  Effect.gen(function* () {
65
112
  const auth = yield* T3Auth;
66
- const environment = yield* Environment;
113
+ const cliRuntime = yield* CliRuntime;
114
+ const t3CliEnv = yield* loadT3CliEnv;
67
115
  const output = yield* T3Output;
68
- const resolvedFormat = resolveOutputFormat(format, environment, "json");
116
+ const resolvedFormat = resolveOutputFormat(format, cliRuntime, t3CliEnv, "json");
69
117
  const result = yield* auth.local({
70
118
  role,
71
119
  label,
@@ -73,15 +121,20 @@ const localCommand = Command.make(
73
121
  ...(Option.isSome(baseDir) ? { baseDir: baseDir.value } : {}),
74
122
  ...(Option.isSome(origin) ? { origin: origin.value } : {}),
75
123
  });
76
- yield* auth.writeConfig({
124
+ const fallbackName = yield* auth.defaultNameForLocal();
125
+ const environmentName = yield* persistAuthEnvironment({
126
+ explicitName: name,
127
+ fallbackName,
77
128
  url: result.url,
78
129
  token: result.token,
79
130
  local: true,
131
+ replace,
80
132
  });
133
+ const payload = { ...result, name: environmentName };
81
134
  if (resolvedFormat === "json") {
82
- yield* output.printJson(formatAuthLocalJson(result));
135
+ yield* output.printJson(formatAuthLocalJson(payload));
83
136
  } else {
84
- yield* output.printInfo(formatAuthLocalHuman(result));
137
+ yield* output.printInfo(formatAuthLocalHuman(payload));
85
138
  }
86
139
  }),
87
140
  ).pipe(Command.withDescription("authenticate with local t3code installation"));
@@ -90,20 +143,20 @@ const statusCommand = Command.make(
90
143
  "status",
91
144
  {
92
145
  format: formatFlag,
146
+ ...extraArgsConfig,
93
147
  },
94
148
  ({ format }) =>
95
149
  Effect.gen(function* () {
96
- const configService = yield* T3Config;
97
150
  const auth = yield* T3Auth;
98
- const environment = yield* Environment;
151
+ const cliRuntime = yield* CliRuntime;
152
+ const t3CliEnv = yield* loadT3CliEnv;
99
153
  const output = yield* T3Output;
100
- const resolvedFormat = resolveOutputFormat(format, environment, "json");
101
- const config = yield* configService.resolve();
154
+ const resolvedFormat = resolveOutputFormat(format, cliRuntime, t3CliEnv, "json");
102
155
  const result = yield* auth.status();
103
156
  if (resolvedFormat === "json") {
104
- yield* output.printJson(formatAuthStatusJson({ config, result }));
157
+ yield* output.printJson(formatAuthStatusJson(result));
105
158
  } else {
106
- yield* output.printInfo(formatAuthStatusHuman({ config, result }));
159
+ yield* output.printInfo(formatAuthStatusHuman(result));
107
160
  }
108
161
  }),
109
162
  ).pipe(Command.withDescription("show auth status"));
@@ -0,0 +1,8 @@
1
+ import { Flag, GlobalFlag } from "effect/unstable/cli";
2
+
3
+ export const cliEnvironmentSetting = GlobalFlag.setting("environment")({
4
+ flag: Flag.string("environment").pipe(
5
+ Flag.withDescription("Auth environment name for this command"),
6
+ Flag.optional,
7
+ ),
8
+ });
@@ -0,0 +1,2 @@
1
+ export { cliEnvironmentSetting } from "./flag.ts";
2
+ export * as Selection from "./selection-layer.ts";
@@ -0,0 +1,49 @@
1
+ import "vite-plus/test/config";
2
+
3
+ import * as Effect from "effect/Effect";
4
+ import { assert, describe, it } from "@effect/vitest";
5
+
6
+ import { T3Config } from "../../config/config.ts";
7
+ import { ConfigPlatformLayer } from "../../config/platform.test-utils.ts";
8
+ import { makeTempHomeScoped } from "../../config/temp-home.test-utils.ts";
9
+ import { t3ConfigDepsLayer } from "../../config/layer.test-utils.ts";
10
+
11
+ describe("T3ConfigSelectionLive", () => {
12
+ it.effect("resolves T3CLI_ENV through the selection layer", () =>
13
+ Effect.gen(function* () {
14
+ return yield* makeTempHomeScoped("t3cli-selection-");
15
+ }).pipe(
16
+ Effect.flatMap((homeDir) =>
17
+ Effect.gen(function* () {
18
+ const config = yield* T3Config;
19
+ yield* config.upsertEnvironment({
20
+ name: "home",
21
+ url: "https://home.example",
22
+ token: "home-token",
23
+ local: false,
24
+ });
25
+ yield* config.upsertEnvironment({
26
+ name: "work",
27
+ url: "https://work.example",
28
+ token: "work-token",
29
+ local: true,
30
+ });
31
+ const resolved = yield* config.resolve();
32
+ assert.equal(resolved.source, "config");
33
+ if (resolved.source === "config") {
34
+ assert.equal(resolved.environment, "work");
35
+ }
36
+ }).pipe(
37
+ Effect.provide(
38
+ t3ConfigDepsLayer(homeDir, {
39
+ useSelectionLive: true,
40
+ env: { T3CLI_ENV: "work" },
41
+ }),
42
+ ),
43
+ ),
44
+ ),
45
+ Effect.provide(ConfigPlatformLayer),
46
+ Effect.scoped,
47
+ ),
48
+ );
49
+ });
@@ -0,0 +1,27 @@
1
+ import * as Effect from "effect/Effect";
2
+ import * as Layer from "effect/Layer";
3
+ import * as Option from "effect/Option";
4
+
5
+ import { resolveConfiguredEnvironment } from "../../config/selection/resolve.ts";
6
+ import { T3ConfigSelection } from "../../config/selection/service.ts";
7
+ import { loadT3CliEnv } from "../../config/env/env.ts";
8
+ import { cliEnvironmentSetting } from "./flag.ts";
9
+
10
+ export const layer = Layer.effect(
11
+ T3ConfigSelection,
12
+ Effect.gen(function* () {
13
+ const t3CliEnv = yield* loadT3CliEnv;
14
+ return {
15
+ getSelectedEnvironment: () =>
16
+ Effect.gen(function* () {
17
+ const cliEnvironment = yield* Effect.serviceOption(cliEnvironmentSetting);
18
+ return resolveConfiguredEnvironment({
19
+ cliFlag: Option.isSome(cliEnvironment)
20
+ ? Option.getOrUndefined(cliEnvironment.value)
21
+ : undefined,
22
+ t3cliEnv: Option.getOrUndefined(t3CliEnv.t3cliEnv),
23
+ });
24
+ }),
25
+ };
26
+ }),
27
+ );
package/src/cli/env.ts ADDED
@@ -0,0 +1,107 @@
1
+ import * as Effect from "effect/Effect";
2
+ import * as Option from "effect/Option";
3
+ import { Argument, Command } from "effect/unstable/cli";
4
+
5
+ import {
6
+ formatAuthListHuman,
7
+ formatAuthListJson,
8
+ formatAuthUnpairHuman,
9
+ formatAuthUseHuman,
10
+ } from "./format/auth.ts";
11
+ import { T3Auth } from "../auth/service.ts";
12
+ import { CliRuntime } from "../cli/runtime/service.ts";
13
+ import { loadT3CliEnv } from "../config/env/env.ts";
14
+ import { requireDestructiveConfirmation } from "./interaction/confirm.ts";
15
+ import { extraArgsConfig } from "./extra-args.ts";
16
+ import { envNameFlag, formatFlag, yesFlag } from "./flags.ts";
17
+ import { resolveOutputFormat } from "./format/output.ts";
18
+ import { T3Output } from "./output/service.ts";
19
+
20
+ export function createEnvCommand() {
21
+ return Command.make("env").pipe(
22
+ Command.withDescription("manage stored environments"),
23
+ Command.withSubcommands([listCommand, useCommand, removeCommand]),
24
+ );
25
+ }
26
+
27
+ const listCommand = Command.make(
28
+ "list",
29
+ {
30
+ format: formatFlag,
31
+ ...extraArgsConfig,
32
+ },
33
+ ({ format }) =>
34
+ Effect.gen(function* () {
35
+ const auth = yield* T3Auth;
36
+ const cliRuntime = yield* CliRuntime;
37
+ const t3CliEnv = yield* loadT3CliEnv;
38
+ const output = yield* T3Output;
39
+ const resolvedFormat = resolveOutputFormat(format, cliRuntime, t3CliEnv, "json");
40
+ const environments = yield* auth.listEnvironments();
41
+ if (resolvedFormat === "json") {
42
+ yield* output.printJson(formatAuthListJson(environments));
43
+ } else {
44
+ yield* output.printInfo(formatAuthListHuman(environments));
45
+ }
46
+ }),
47
+ ).pipe(Command.withDescription("list stored environments"));
48
+
49
+ const useCommand = Command.make(
50
+ "use",
51
+ {
52
+ name: Argument.string("name"),
53
+ format: formatFlag,
54
+ ...extraArgsConfig,
55
+ },
56
+ ({ name, format }) =>
57
+ Effect.gen(function* () {
58
+ const auth = yield* T3Auth;
59
+ const cliRuntime = yield* CliRuntime;
60
+ const t3CliEnv = yield* loadT3CliEnv;
61
+ const output = yield* T3Output;
62
+ const resolvedFormat = resolveOutputFormat(format, cliRuntime, t3CliEnv, "json");
63
+ const result = yield* auth.useEnvironment(name);
64
+ if (resolvedFormat === "json") {
65
+ yield* output.printJson(result);
66
+ } else {
67
+ yield* output.printInfo(formatAuthUseHuman(result));
68
+ }
69
+ }),
70
+ ).pipe(Command.withDescription("set the default environment"));
71
+
72
+ const removeCommand = Command.make(
73
+ "remove",
74
+ {
75
+ name: envNameFlag,
76
+ yes: yesFlag,
77
+ format: formatFlag,
78
+ ...extraArgsConfig,
79
+ },
80
+ ({ name, yes, format }) =>
81
+ Effect.gen(function* () {
82
+ const auth = yield* T3Auth;
83
+ const cliRuntime = yield* CliRuntime;
84
+ const t3CliEnv = yield* loadT3CliEnv;
85
+ const output = yield* T3Output;
86
+ const resolvedFormat = resolveOutputFormat(format, cliRuntime, t3CliEnv, "json");
87
+ const targetName = yield* auth.resolveUnpairTarget(
88
+ Option.isSome(name) ? { name: name.value } : {},
89
+ );
90
+ yield* requireDestructiveConfirmation({
91
+ message: `Remove local credentials for environment '${targetName}'?`,
92
+ yes,
93
+ cliRuntime,
94
+ t3CliEnv,
95
+ });
96
+ const result = yield* auth.unpairEnvironment({ name: targetName });
97
+ if (resolvedFormat === "json") {
98
+ yield* output.printJson(result);
99
+ } else {
100
+ yield* output.printInfo(formatAuthUnpairHuman(result));
101
+ }
102
+ }),
103
+ ).pipe(
104
+ Command.withDescription(
105
+ "remove local credentials for an environment (remote tokens may remain valid until expiry)",
106
+ ),
107
+ );
package/src/cli/error.ts CHANGED
@@ -22,11 +22,20 @@ export class MissingThreadError extends Schema.TaggedErrorClass<MissingThreadErr
22
22
  },
23
23
  ) {}
24
24
 
25
- export class SelfArchiveError extends Schema.TaggedErrorClass<SelfArchiveError>()(
26
- "SelfArchiveError",
25
+ export class SelfActionError extends Schema.TaggedErrorClass<SelfActionError>()("SelfActionError", {
26
+ message: Schema.String,
27
+ threadId: Schema.String,
28
+ }) {}
29
+
30
+ export class DestructiveConfirmationRequiredError extends Schema.TaggedErrorClass<DestructiveConfirmationRequiredError>()(
31
+ "DestructiveConfirmationRequiredError",
32
+ { message: Schema.String },
33
+ ) {}
34
+
35
+ export class InvalidFlagCombinationError extends Schema.TaggedErrorClass<InvalidFlagCombinationError>()(
36
+ "InvalidFlagCombinationError",
27
37
  {
28
38
  message: Schema.String,
29
- threadId: Schema.String,
30
39
  },
31
40
  ) {}
32
41
 
@@ -36,3 +45,17 @@ export class MissingRequestError extends Schema.TaggedErrorClass<MissingRequestE
36
45
  message: Schema.String,
37
46
  },
38
47
  ) {}
48
+
49
+ export class MissingUpdateFieldsError extends Schema.TaggedErrorClass<MissingUpdateFieldsError>()(
50
+ "MissingUpdateFieldsError",
51
+ {
52
+ message: Schema.String,
53
+ },
54
+ ) {}
55
+
56
+ export class ConflictingUpdateFlagsError extends Schema.TaggedErrorClass<ConflictingUpdateFlagsError>()(
57
+ "ConflictingUpdateFlagsError",
58
+ {
59
+ message: Schema.String,
60
+ },
61
+ ) {}
@@ -0,0 +1,32 @@
1
+ import "vite-plus/test/config";
2
+
3
+ import * as Cause from "effect/Cause";
4
+ import * as Effect from "effect/Effect";
5
+ import * as Exit from "effect/Exit";
6
+ import * as Option from "effect/Option";
7
+ import { assert, describe, it } from "@effect/vitest";
8
+ import { CliError } from "effect/unstable/cli";
9
+
10
+ import { extraArgsConfig } from "./extra-args.ts";
11
+
12
+ describe("extraArgsConfig", () => {
13
+ it("rejects leftover positional arguments", () =>
14
+ Effect.gen(function* () {
15
+ const exit = yield* extraArgsConfig.extraArgs
16
+ .parse({ flags: {}, arguments: ["extra"] })
17
+ .pipe(Effect.exit);
18
+ assert.isTrue(Exit.isFailure(exit));
19
+ if (!Exit.isFailure(exit)) {
20
+ return;
21
+ }
22
+ const error = Cause.findErrorOption(exit.cause);
23
+ assert.isTrue(Option.isSome(error));
24
+ if (Option.isSome(error)) {
25
+ assert.instanceOf(error.value, CliError.InvalidValue);
26
+ assert.equal(
27
+ error.value.message,
28
+ 'Invalid value for argument <extra>: "extra". Expected: no extra arguments',
29
+ );
30
+ }
31
+ }));
32
+ });
@@ -0,0 +1,22 @@
1
+ import * as Effect from "effect/Effect";
2
+ import { Argument, CliError } from "effect/unstable/cli";
3
+
4
+ const rejectExtraArguments = Argument.string("extra").pipe(
5
+ Argument.variadic(),
6
+ Argument.mapEffect((extra) =>
7
+ extra.length === 0
8
+ ? Effect.void
9
+ : Effect.fail(
10
+ new CliError.InvalidValue({
11
+ option: "extra",
12
+ value: extra[0] ?? "",
13
+ expected: "no extra arguments",
14
+ kind: "argument",
15
+ }),
16
+ ),
17
+ ),
18
+ );
19
+
20
+ export const extraArgsConfig = {
21
+ extraArgs: rejectExtraArguments,
22
+ };
package/src/cli/flags.ts CHANGED
@@ -4,7 +4,7 @@ import {
4
4
  humanJsonFormatChoices,
5
5
  humanJsonNdjsonFormatChoices,
6
6
  humanNdjsonFormatChoices,
7
- } from "./output-format.ts";
7
+ } from "./format/output.ts";
8
8
 
9
9
  export const projectFlag = Flag.string("project").pipe(
10
10
  Flag.withDescription(
@@ -30,6 +30,31 @@ export const projectPathFlag = Flag.string("path").pipe(
30
30
  Flag.withDefault("."),
31
31
  );
32
32
 
33
+ export const yesFlag = Flag.boolean("yes").pipe(
34
+ Flag.withDescription("Skip interactive confirmation"),
35
+ Flag.withDefault(false),
36
+ );
37
+
38
+ export const replaceFlag = Flag.boolean("replace").pipe(
39
+ Flag.withDescription("Replace an existing environment with the same name"),
40
+ Flag.withDefault(false),
41
+ );
42
+
43
+ export const envNameFlag = Flag.string("name").pipe(
44
+ Flag.withDescription("Environment name"),
45
+ Flag.optional,
46
+ );
47
+
48
+ export const forceFlag = Flag.boolean("force").pipe(
49
+ Flag.withDescription("Delete non-empty project (cascade thread deletes)"),
50
+ Flag.withDefault(false),
51
+ );
52
+
53
+ export const selfActionForceFlag = Flag.boolean("force").pipe(
54
+ Flag.withDescription("Confirm an action targeting the calling agent thread"),
55
+ Flag.withAlias("f"),
56
+ );
57
+
33
58
  export const formatFlag = Flag.choice("format", humanJsonFormatChoices).pipe(
34
59
  Flag.withDefault("auto"),
35
60
  );
@@ -0,0 +1,92 @@
1
+ import type {
2
+ AuthEnvironmentListItem,
3
+ AuthStatusResult,
4
+ LocalAuthResult,
5
+ PairResult,
6
+ } from "../../auth/type.ts";
7
+ import { formatRecord, formatTable } from "./human.ts";
8
+
9
+ export function formatAuthPaired(result: PairResult & { readonly name: string }) {
10
+ return `paired\n${formatRecord([
11
+ { field: "url", value: result.url },
12
+ { field: "name", value: result.name },
13
+ { field: "role", value: result.role },
14
+ { field: "expires", value: result.expiresAt },
15
+ ])}`;
16
+ }
17
+
18
+ export function formatAuthLocalHuman(result: LocalAuthResult & { readonly name: string }) {
19
+ return `paired\n${formatRecord([
20
+ { field: "url", value: result.url },
21
+ { field: "name", value: result.name },
22
+ { field: "role", value: result.role },
23
+ { field: "expires", value: result.expiresAt },
24
+ { field: "base dir", value: result.baseDir },
25
+ ])}`;
26
+ }
27
+
28
+ export function formatAuthLocalJson(result: LocalAuthResult & { readonly name: string }) {
29
+ return result;
30
+ }
31
+
32
+ export function formatAuthStatusHuman(input: AuthStatusResult) {
33
+ return formatRecord([
34
+ ...(input.config.environment !== undefined
35
+ ? [{ field: "environment", value: input.config.environment }]
36
+ : []),
37
+ { field: "url", value: input.config.url },
38
+ { field: "local", value: input.config.local ? "yes" : "no" },
39
+ { field: "source", value: input.config.source },
40
+ { field: "authenticated", value: input.session.authenticated ? "yes" : "no" },
41
+ ...(input.session.role !== undefined ? [{ field: "role", value: input.session.role }] : []),
42
+ ...(input.session.expiresAt !== undefined
43
+ ? [{ field: "expires", value: input.session.expiresAt }]
44
+ : []),
45
+ ]);
46
+ }
47
+
48
+ export function formatAuthStatusJson(input: AuthStatusResult) {
49
+ return {
50
+ ...input.session,
51
+ ...(input.config.environment !== undefined ? { environment: input.config.environment } : {}),
52
+ url: input.config.url,
53
+ source: input.config.source,
54
+ local: input.config.local,
55
+ };
56
+ }
57
+
58
+ export function formatAuthListHuman(environments: readonly AuthEnvironmentListItem[]) {
59
+ if (environments.length === 0) {
60
+ return "no environments";
61
+ }
62
+ return formatTable(
63
+ [
64
+ { header: "name", value: (environment) => environment.name, maxWidth: 24 },
65
+ { header: "url", value: (environment) => environment.url, maxWidth: 72 },
66
+ { header: "local", value: (environment) => (environment.local ? "yes" : "no"), maxWidth: 6 },
67
+ {
68
+ header: "default",
69
+ value: (environment) => (environment.default ? "yes" : "no"),
70
+ maxWidth: 7,
71
+ },
72
+ {
73
+ header: "active",
74
+ value: (environment) => (environment.active ? "yes" : "no"),
75
+ maxWidth: 6,
76
+ },
77
+ ],
78
+ environments,
79
+ );
80
+ }
81
+
82
+ export function formatAuthListJson(environments: readonly AuthEnvironmentListItem[]) {
83
+ return environments;
84
+ }
85
+
86
+ export function formatAuthUseHuman(result: { readonly name: string }) {
87
+ return `default environment: ${result.name}`;
88
+ }
89
+
90
+ export function formatAuthUnpairHuman(result: { readonly name: string }) {
91
+ return `removed environment: ${result.name}`;
92
+ }