convex 1.36.0 → 1.37.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 (240) hide show
  1. package/CHANGELOG.md +50 -27
  2. package/dist/browser.bundle.js +1 -1
  3. package/dist/browser.bundle.js.map +1 -1
  4. package/dist/cjs/cli/codegen_templates/agentsmd.js +8 -2
  5. package/dist/cjs/cli/codegen_templates/agentsmd.js.map +2 -2
  6. package/dist/cjs/cli/codegen_templates/claudemd.js +2 -0
  7. package/dist/cjs/cli/codegen_templates/claudemd.js.map +2 -2
  8. package/dist/cjs/cli/configure.js +0 -8
  9. package/dist/cjs/cli/configure.js.map +2 -2
  10. package/dist/cjs/cli/deployment.js +2 -1
  11. package/dist/cjs/cli/deployment.js.map +2 -2
  12. package/dist/cjs/cli/deploymentToken.js +30 -0
  13. package/dist/cjs/cli/deploymentToken.js.map +7 -0
  14. package/dist/cjs/cli/deploymentTokenCreate.js +109 -0
  15. package/dist/cjs/cli/deploymentTokenCreate.js.map +7 -0
  16. package/dist/cjs/cli/deploymentTokenDelete.js +87 -0
  17. package/dist/cjs/cli/deploymentTokenDelete.js.map +7 -0
  18. package/dist/cjs/cli/envDefault.js +130 -41
  19. package/dist/cjs/cli/envDefault.js.map +3 -3
  20. package/dist/cjs/cli/generatedApi.js.map +1 -1
  21. package/dist/cjs/cli/lib/command.js +1 -1
  22. package/dist/cjs/cli/lib/command.js.map +1 -1
  23. package/dist/cjs/cli/lib/generatedFunctionLogsApi.js.map +1 -1
  24. package/dist/cjs/cli/lib/login.js +51 -0
  25. package/dist/cjs/cli/lib/login.js.map +3 -3
  26. package/dist/cjs/cli/lib/usage.js +13 -6
  27. package/dist/cjs/cli/lib/usage.js.map +2 -2
  28. package/dist/cjs/cli/lib/workos/environmentApi.js +6 -12
  29. package/dist/cjs/cli/lib/workos/environmentApi.js.map +3 -3
  30. package/dist/cjs/index.js +1 -1
  31. package/dist/cjs/index.js.map +1 -1
  32. package/dist/cjs/react/client.js +40 -42
  33. package/dist/cjs/react/client.js.map +2 -2
  34. package/dist/cjs/react/index.js +1 -0
  35. package/dist/cjs/react/index.js.map +2 -2
  36. package/dist/cjs/react/use_paginated_query.js +5 -46
  37. package/dist/cjs/react/use_paginated_query.js.map +2 -2
  38. package/dist/cjs/react/use_paginated_query2.js.map +2 -2
  39. package/dist/cjs/server/audit_logging.js +67 -0
  40. package/dist/cjs/server/audit_logging.js.map +7 -0
  41. package/dist/cjs/server/impl/meta_impl.js +27 -3
  42. package/dist/cjs/server/impl/meta_impl.js.map +2 -2
  43. package/dist/cjs/server/impl/registration_impl.js +2 -0
  44. package/dist/cjs/server/impl/registration_impl.js.map +2 -2
  45. package/dist/cjs/server/index.js +2 -0
  46. package/dist/cjs/server/index.js.map +2 -2
  47. package/dist/cjs/server/log.js +30 -0
  48. package/dist/cjs/server/log.js.map +7 -0
  49. package/dist/cjs/server/logVars.js +48 -0
  50. package/dist/cjs/server/logVars.js.map +7 -0
  51. package/dist/cjs/server/meta.js.map +1 -1
  52. package/dist/cjs/server/registration.js.map +1 -1
  53. package/dist/cjs-types/cli/codegen_templates/agentsmd.d.ts.map +1 -1
  54. package/dist/cjs-types/cli/codegen_templates/claudemd.d.ts.map +1 -1
  55. package/dist/cjs-types/cli/configure.d.ts.map +1 -1
  56. package/dist/cjs-types/cli/deployment.d.ts.map +1 -1
  57. package/dist/cjs-types/cli/deploymentToken.d.ts +3 -0
  58. package/dist/cjs-types/cli/deploymentToken.d.ts.map +1 -0
  59. package/dist/cjs-types/cli/deploymentToken.test.d.ts +2 -0
  60. package/dist/cjs-types/cli/deploymentToken.test.d.ts.map +1 -0
  61. package/dist/cjs-types/cli/deploymentTokenCreate.d.ts +13 -0
  62. package/dist/cjs-types/cli/deploymentTokenCreate.d.ts.map +1 -0
  63. package/dist/cjs-types/cli/deploymentTokenDelete.d.ts +11 -0
  64. package/dist/cjs-types/cli/deploymentTokenDelete.d.ts.map +1 -0
  65. package/dist/cjs-types/cli/envDefault.d.ts +2 -2
  66. package/dist/cjs-types/cli/envDefault.d.ts.map +1 -1
  67. package/dist/cjs-types/cli/envDefault.test.d.ts +2 -0
  68. package/dist/cjs-types/cli/envDefault.test.d.ts.map +1 -0
  69. package/dist/cjs-types/cli/generatedApi.d.ts +1 -1
  70. package/dist/cjs-types/cli/generatedApi.d.ts.map +1 -1
  71. package/dist/cjs-types/cli/lib/generatedFunctionLogsApi.d.ts +1 -0
  72. package/dist/cjs-types/cli/lib/generatedFunctionLogsApi.d.ts.map +1 -1
  73. package/dist/cjs-types/cli/lib/login.d.ts.map +1 -1
  74. package/dist/cjs-types/cli/lib/usage.d.ts.map +1 -1
  75. package/dist/cjs-types/cli/lib/workos/environmentApi.d.ts.map +1 -1
  76. package/dist/cjs-types/cli/lib/workos/environmentApi.test.d.ts +2 -0
  77. package/dist/cjs-types/cli/lib/workos/environmentApi.test.d.ts.map +1 -0
  78. package/dist/cjs-types/index.d.ts +1 -1
  79. package/dist/cjs-types/react/client.d.ts +52 -0
  80. package/dist/cjs-types/react/client.d.ts.map +1 -1
  81. package/dist/cjs-types/react/index.d.ts +2 -2
  82. package/dist/cjs-types/react/index.d.ts.map +1 -1
  83. package/dist/cjs-types/react/use_paginated_query.d.ts.map +1 -1
  84. package/dist/cjs-types/react/use_paginated_query2.d.ts +63 -1
  85. package/dist/cjs-types/react/use_paginated_query2.d.ts.map +1 -1
  86. package/dist/cjs-types/server/api.intersect.test.d.ts +2 -0
  87. package/dist/cjs-types/server/api.intersect.test.d.ts.map +1 -0
  88. package/dist/cjs-types/server/audit_logging.d.ts +19 -0
  89. package/dist/cjs-types/server/audit_logging.d.ts.map +1 -0
  90. package/dist/cjs-types/server/audit_logging.test.d.ts +2 -0
  91. package/dist/cjs-types/server/audit_logging.test.d.ts.map +1 -0
  92. package/dist/cjs-types/server/impl/meta_impl.d.ts.map +1 -1
  93. package/dist/cjs-types/server/impl/registration_impl.d.ts.map +1 -1
  94. package/dist/cjs-types/server/index.d.ts +2 -2
  95. package/dist/cjs-types/server/index.d.ts.map +1 -1
  96. package/dist/cjs-types/server/log.d.ts +2 -0
  97. package/dist/cjs-types/server/log.d.ts.map +1 -0
  98. package/dist/cjs-types/server/logVars.d.ts +20 -0
  99. package/dist/cjs-types/server/logVars.d.ts.map +1 -0
  100. package/dist/cjs-types/server/meta.d.ts +40 -0
  101. package/dist/cjs-types/server/meta.d.ts.map +1 -1
  102. package/dist/cjs-types/server/registration.d.ts +5 -2
  103. package/dist/cjs-types/server/registration.d.ts.map +1 -1
  104. package/dist/cli.bundle.cjs +362 -74
  105. package/dist/cli.bundle.cjs.map +4 -4
  106. package/dist/esm/cli/codegen_templates/agentsmd.js +8 -2
  107. package/dist/esm/cli/codegen_templates/agentsmd.js.map +2 -2
  108. package/dist/esm/cli/codegen_templates/claudemd.js +2 -0
  109. package/dist/esm/cli/codegen_templates/claudemd.js.map +2 -2
  110. package/dist/esm/cli/configure.js +0 -8
  111. package/dist/esm/cli/configure.js.map +2 -2
  112. package/dist/esm/cli/deployment.js +2 -1
  113. package/dist/esm/cli/deployment.js.map +2 -2
  114. package/dist/esm/cli/deploymentToken.js +8 -0
  115. package/dist/esm/cli/deploymentToken.js.map +7 -0
  116. package/dist/esm/cli/deploymentTokenCreate.js +91 -0
  117. package/dist/esm/cli/deploymentTokenCreate.js.map +7 -0
  118. package/dist/esm/cli/deploymentTokenDelete.js +68 -0
  119. package/dist/esm/cli/deploymentTokenDelete.js.map +7 -0
  120. package/dist/esm/cli/envDefault.js +131 -42
  121. package/dist/esm/cli/envDefault.js.map +3 -3
  122. package/dist/esm/cli/lib/command.js +1 -1
  123. package/dist/esm/cli/lib/command.js.map +1 -1
  124. package/dist/esm/cli/lib/login.js +52 -0
  125. package/dist/esm/cli/lib/login.js.map +3 -3
  126. package/dist/esm/cli/lib/usage.js +15 -8
  127. package/dist/esm/cli/lib/usage.js.map +2 -2
  128. package/dist/esm/cli/lib/workos/environmentApi.js +6 -12
  129. package/dist/esm/cli/lib/workos/environmentApi.js.map +3 -3
  130. package/dist/esm/index.js +1 -1
  131. package/dist/esm/index.js.map +1 -1
  132. package/dist/esm/react/client.js +38 -41
  133. package/dist/esm/react/client.js.map +2 -2
  134. package/dist/esm/react/index.js +4 -1
  135. package/dist/esm/react/index.js.map +2 -2
  136. package/dist/esm/react/use_paginated_query.js +5 -46
  137. package/dist/esm/react/use_paginated_query.js.map +2 -2
  138. package/dist/esm/react/use_paginated_query2.js.map +2 -2
  139. package/dist/esm/server/audit_logging.js +44 -0
  140. package/dist/esm/server/audit_logging.js.map +7 -0
  141. package/dist/esm/server/impl/meta_impl.js +27 -3
  142. package/dist/esm/server/impl/meta_impl.js.map +2 -2
  143. package/dist/esm/server/impl/registration_impl.js +2 -0
  144. package/dist/esm/server/impl/registration_impl.js.map +2 -2
  145. package/dist/esm/server/index.js +1 -0
  146. package/dist/esm/server/index.js.map +2 -2
  147. package/dist/esm/server/log.js +8 -0
  148. package/dist/esm/server/log.js.map +7 -0
  149. package/dist/esm/server/logVars.js +25 -0
  150. package/dist/esm/server/logVars.js.map +7 -0
  151. package/dist/esm-types/cli/codegen_templates/agentsmd.d.ts.map +1 -1
  152. package/dist/esm-types/cli/codegen_templates/claudemd.d.ts.map +1 -1
  153. package/dist/esm-types/cli/configure.d.ts.map +1 -1
  154. package/dist/esm-types/cli/deployment.d.ts.map +1 -1
  155. package/dist/esm-types/cli/deploymentToken.d.ts +3 -0
  156. package/dist/esm-types/cli/deploymentToken.d.ts.map +1 -0
  157. package/dist/esm-types/cli/deploymentToken.test.d.ts +2 -0
  158. package/dist/esm-types/cli/deploymentToken.test.d.ts.map +1 -0
  159. package/dist/esm-types/cli/deploymentTokenCreate.d.ts +13 -0
  160. package/dist/esm-types/cli/deploymentTokenCreate.d.ts.map +1 -0
  161. package/dist/esm-types/cli/deploymentTokenDelete.d.ts +11 -0
  162. package/dist/esm-types/cli/deploymentTokenDelete.d.ts.map +1 -0
  163. package/dist/esm-types/cli/envDefault.d.ts +2 -2
  164. package/dist/esm-types/cli/envDefault.d.ts.map +1 -1
  165. package/dist/esm-types/cli/envDefault.test.d.ts +2 -0
  166. package/dist/esm-types/cli/envDefault.test.d.ts.map +1 -0
  167. package/dist/esm-types/cli/generatedApi.d.ts +1 -1
  168. package/dist/esm-types/cli/generatedApi.d.ts.map +1 -1
  169. package/dist/esm-types/cli/lib/generatedFunctionLogsApi.d.ts +1 -0
  170. package/dist/esm-types/cli/lib/generatedFunctionLogsApi.d.ts.map +1 -1
  171. package/dist/esm-types/cli/lib/login.d.ts.map +1 -1
  172. package/dist/esm-types/cli/lib/usage.d.ts.map +1 -1
  173. package/dist/esm-types/cli/lib/workos/environmentApi.d.ts.map +1 -1
  174. package/dist/esm-types/cli/lib/workos/environmentApi.test.d.ts +2 -0
  175. package/dist/esm-types/cli/lib/workos/environmentApi.test.d.ts.map +1 -0
  176. package/dist/esm-types/index.d.ts +1 -1
  177. package/dist/esm-types/react/client.d.ts +52 -0
  178. package/dist/esm-types/react/client.d.ts.map +1 -1
  179. package/dist/esm-types/react/index.d.ts +2 -2
  180. package/dist/esm-types/react/index.d.ts.map +1 -1
  181. package/dist/esm-types/react/use_paginated_query.d.ts.map +1 -1
  182. package/dist/esm-types/react/use_paginated_query2.d.ts +63 -1
  183. package/dist/esm-types/react/use_paginated_query2.d.ts.map +1 -1
  184. package/dist/esm-types/server/api.intersect.test.d.ts +2 -0
  185. package/dist/esm-types/server/api.intersect.test.d.ts.map +1 -0
  186. package/dist/esm-types/server/audit_logging.d.ts +19 -0
  187. package/dist/esm-types/server/audit_logging.d.ts.map +1 -0
  188. package/dist/esm-types/server/audit_logging.test.d.ts +2 -0
  189. package/dist/esm-types/server/audit_logging.test.d.ts.map +1 -0
  190. package/dist/esm-types/server/impl/meta_impl.d.ts.map +1 -1
  191. package/dist/esm-types/server/impl/registration_impl.d.ts.map +1 -1
  192. package/dist/esm-types/server/index.d.ts +2 -2
  193. package/dist/esm-types/server/index.d.ts.map +1 -1
  194. package/dist/esm-types/server/log.d.ts +2 -0
  195. package/dist/esm-types/server/log.d.ts.map +1 -0
  196. package/dist/esm-types/server/logVars.d.ts +20 -0
  197. package/dist/esm-types/server/logVars.d.ts.map +1 -0
  198. package/dist/esm-types/server/meta.d.ts +40 -0
  199. package/dist/esm-types/server/meta.d.ts.map +1 -1
  200. package/dist/esm-types/server/registration.d.ts +5 -2
  201. package/dist/esm-types/server/registration.d.ts.map +1 -1
  202. package/dist/react.bundle.js +45 -88
  203. package/dist/react.bundle.js.map +2 -2
  204. package/package.json +4 -4
  205. package/src/cli/codegen_templates/agentsmd.ts +8 -2
  206. package/src/cli/codegen_templates/claudemd.ts +2 -0
  207. package/src/cli/configure.ts +0 -9
  208. package/src/cli/deployment.ts +3 -1
  209. package/src/cli/deploymentToken.test.ts +372 -0
  210. package/src/cli/deploymentToken.ts +11 -0
  211. package/src/cli/deploymentTokenCreate.ts +113 -0
  212. package/src/cli/deploymentTokenDelete.ts +91 -0
  213. package/src/cli/envDefault.test.ts +495 -0
  214. package/src/cli/envDefault.ts +222 -107
  215. package/src/cli/generatedApi.ts +1 -1
  216. package/src/cli/lib/command.ts +1 -1
  217. package/src/cli/lib/generatedFunctionLogsApi.ts +1 -0
  218. package/src/cli/lib/login.ts +67 -0
  219. package/src/cli/lib/usage.ts +18 -8
  220. package/src/cli/lib/workos/environmentApi.test.ts +107 -0
  221. package/src/cli/lib/workos/environmentApi.ts +12 -19
  222. package/src/index.ts +1 -1
  223. package/src/react/client.test.tsx +10 -8
  224. package/src/react/client.ts +88 -96
  225. package/src/react/index.ts +6 -1
  226. package/src/react/use_paginated_query.test.tsx +215 -132
  227. package/src/react/use_paginated_query.ts +8 -142
  228. package/src/react/use_paginated_query2.ts +78 -5
  229. package/src/react/use_query_object_options.test.ts +8 -7
  230. package/src/react/use_query_result.test.ts +40 -7
  231. package/src/server/api.intersect.test.ts +109 -0
  232. package/src/server/audit_logging.test.ts +129 -0
  233. package/src/server/audit_logging.ts +75 -0
  234. package/src/server/impl/meta_impl.ts +28 -0
  235. package/src/server/impl/registration_impl.ts +2 -0
  236. package/src/server/index.ts +12 -0
  237. package/src/server/log.ts +16 -0
  238. package/src/server/logVars.ts +34 -0
  239. package/src/server/meta.ts +53 -1
  240. package/src/server/registration.ts +10 -8
@@ -0,0 +1,495 @@
1
+ import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
2
+ import { nodeFs } from "../bundler/fs.js";
3
+ import { env } from "./env.js";
4
+ import { bigBrainAPI, bigBrainAPIMaybeThrows } from "./lib/utils/utils.js";
5
+ import { readGlobalConfig } from "./lib/utils/globalConfig.js";
6
+
7
+ vi.mock("../bundler/fs.js", async (importOriginal) => {
8
+ const actual = await importOriginal<typeof import("../bundler/fs.js")>();
9
+ return {
10
+ ...actual,
11
+ nodeFs: {
12
+ ...actual.nodeFs,
13
+ exists: vi.fn().mockImplementation(() => {
14
+ throw new Error("nodeFs.exists should be mocked in test");
15
+ }),
16
+ readUtf8File: vi.fn().mockImplementation(() => {
17
+ throw new Error("nodeFs.readUtf8File should be mocked in test");
18
+ }),
19
+ },
20
+ };
21
+ });
22
+
23
+ const mockPlatformGet = vi.fn();
24
+ const mockPlatformPost = vi.fn();
25
+
26
+ vi.mock("./lib/utils/utils.js", async (importOriginal) => {
27
+ const actual = await importOriginal<typeof import("./lib/utils/utils.js")>();
28
+ return {
29
+ ...actual,
30
+ deploymentFetch: vi.fn(),
31
+ ensureHasConvexDependency: vi.fn(),
32
+ bigBrainAPI: vi.fn(),
33
+ bigBrainAPIMaybeThrows: vi.fn(),
34
+ validateOrSelectTeam: vi.fn(),
35
+ validateOrSelectProject: vi.fn(),
36
+ typedPlatformClient: vi.fn(() => ({
37
+ GET: mockPlatformGet,
38
+ POST: mockPlatformPost,
39
+ })),
40
+ };
41
+ });
42
+
43
+ vi.mock("./lib/utils/globalConfig.js", async (importOriginal) => {
44
+ const actual =
45
+ await importOriginal<typeof import("./lib/utils/globalConfig.js")>();
46
+ return {
47
+ ...actual,
48
+ readGlobalConfig: vi.fn().mockReturnValue(null),
49
+ };
50
+ });
51
+
52
+ vi.mock("dotenv", async (importOriginal) => {
53
+ const actual = await importOriginal<typeof import("dotenv")>();
54
+ return {
55
+ ...actual,
56
+ config: vi.fn(),
57
+ };
58
+ });
59
+
60
+ vi.mock("@sentry/node", () => ({
61
+ captureException: vi.fn(),
62
+ close: vi.fn(),
63
+ }));
64
+
65
+ function setupBigBrainRoutes(routes: Record<string, (data?: any) => any>) {
66
+ const handler = (args: { path: string; data?: any }) => {
67
+ for (const [routePath, routeHandler] of Object.entries(routes)) {
68
+ if (args.path === routePath || args.path.startsWith(routePath)) {
69
+ return routeHandler(args.data);
70
+ }
71
+ }
72
+ throw new Error(`Unmocked Big Brain route: ${args.path}`);
73
+ };
74
+ vi.mocked(bigBrainAPI).mockImplementation(handler as any);
75
+ vi.mocked(bigBrainAPIMaybeThrows).mockImplementation(handler as any);
76
+ }
77
+
78
+ describe("env default", () => {
79
+ let savedEnv: NodeJS.ProcessEnv;
80
+ let savedIsTTY: boolean | undefined;
81
+
82
+ beforeEach(() => {
83
+ savedEnv = { ...process.env };
84
+ savedIsTTY = process.stdin.isTTY;
85
+ process.env = {};
86
+ process.stdin.isTTY = true as any;
87
+
88
+ vi.resetAllMocks();
89
+ vi.mocked(readGlobalConfig).mockReturnValue(null);
90
+ vi.mocked(nodeFs.exists).mockReturnValue(false);
91
+
92
+ mockPlatformGet.mockReset();
93
+ mockPlatformPost.mockReset();
94
+ });
95
+
96
+ afterEach(() => {
97
+ process.env = savedEnv;
98
+ process.stdin.isTTY = savedIsTTY as any;
99
+ });
100
+
101
+ beforeEach(() => {
102
+ vi.spyOn(process, "exit").mockImplementation((() => {
103
+ throw new Error("process.exit called");
104
+ }) as any);
105
+ vi.spyOn(process.stderr, "write").mockImplementation(() => true);
106
+ vi.spyOn(process.stdout, "write").mockImplementation(() => true);
107
+ });
108
+
109
+ afterEach(() => {
110
+ vi.restoreAllMocks();
111
+ });
112
+
113
+ function setupDefaultEnvPlatformMocks({
114
+ projectId = 42,
115
+ teamSlug = "my-team",
116
+ projectSlug = "my-project",
117
+ }: {
118
+ projectId?: number;
119
+ teamSlug?: string;
120
+ projectSlug?: string;
121
+ } = {}) {
122
+ mockPlatformGet.mockImplementation((path: string, _opts: any) => {
123
+ if (path === "/teams/{team_id_or_slug}/projects/{project_slug}") {
124
+ return {
125
+ data: {
126
+ id: projectId,
127
+ slug: projectSlug,
128
+ name: projectSlug,
129
+ teamId: 1,
130
+ teamSlug,
131
+ createTime: 0,
132
+ },
133
+ };
134
+ }
135
+ if (
136
+ path === "/projects/{project_id}/list_default_environment_variables"
137
+ ) {
138
+ return { data: { items: [] } };
139
+ }
140
+ throw new Error(`Unmocked platform GET: ${path}`);
141
+ });
142
+ mockPlatformPost.mockImplementation(async (path: string, _opts: any) => {
143
+ if (
144
+ path === "/projects/{project_id}/update_default_environment_variables"
145
+ ) {
146
+ return { data: {} };
147
+ }
148
+ throw new Error(`Unmocked platform POST: ${path}`);
149
+ });
150
+ }
151
+
152
+ describe("default behavior (no --type, no --project)", () => {
153
+ it("uses current deployment's project and inferred dtype", async () => {
154
+ process.env.CONVEX_DEPLOYMENT = "dev:foo-bar-123";
155
+ vi.mocked(readGlobalConfig).mockReturnValue({
156
+ accessToken: "test-token",
157
+ });
158
+ setupBigBrainRoutes({
159
+ "deployment/foo-bar-123/team_and_project": () => ({
160
+ team: "my-team",
161
+ project: "my-project",
162
+ teamId: 1,
163
+ projectId: 42,
164
+ }),
165
+ "deployment/authorize_within_current_project": () => ({
166
+ adminKey: "dev-key",
167
+ url: "https://foo-bar-123.convex.cloud",
168
+ deploymentName: "foo-bar-123",
169
+ deploymentType: "dev",
170
+ }),
171
+ });
172
+ setupDefaultEnvPlatformMocks({ projectId: 42 });
173
+
174
+ await env.parseAsync(["default", "set", "ABC", "DEF"], { from: "user" });
175
+
176
+ expect(mockPlatformPost).toHaveBeenCalledWith(
177
+ "/projects/{project_id}/update_default_environment_variables",
178
+ expect.objectContaining({
179
+ params: { path: { project_id: 42 } },
180
+ body: {
181
+ changes: [{ name: "ABC", deploymentType: "dev", value: "DEF" }],
182
+ },
183
+ }),
184
+ );
185
+ });
186
+ });
187
+
188
+ describe("--type override", () => {
189
+ it("--type prod overrides dtype, still uses current deployment's project", async () => {
190
+ process.env.CONVEX_DEPLOYMENT = "dev:foo-bar-123";
191
+ vi.mocked(readGlobalConfig).mockReturnValue({
192
+ accessToken: "test-token",
193
+ });
194
+ setupBigBrainRoutes({
195
+ "deployment/foo-bar-123/team_and_project": () => ({
196
+ team: "my-team",
197
+ project: "my-project",
198
+ teamId: 1,
199
+ projectId: 42,
200
+ }),
201
+ "deployment/authorize_within_current_project": () => ({
202
+ adminKey: "dev-key",
203
+ url: "https://foo-bar-123.convex.cloud",
204
+ deploymentName: "foo-bar-123",
205
+ deploymentType: "dev",
206
+ }),
207
+ });
208
+ setupDefaultEnvPlatformMocks({ projectId: 42 });
209
+
210
+ await env.parseAsync(["default", "set", "ABC", "DEF", "--type", "prod"], {
211
+ from: "user",
212
+ });
213
+
214
+ expect(mockPlatformPost).toHaveBeenCalledWith(
215
+ "/projects/{project_id}/update_default_environment_variables",
216
+ expect.objectContaining({
217
+ params: { path: { project_id: 42 } },
218
+ body: {
219
+ changes: [{ name: "ABC", deploymentType: "prod", value: "DEF" }],
220
+ },
221
+ }),
222
+ );
223
+ });
224
+
225
+ it("--type production aliases to prod", async () => {
226
+ process.env.CONVEX_DEPLOYMENT = "dev:foo-bar-123";
227
+ vi.mocked(readGlobalConfig).mockReturnValue({
228
+ accessToken: "test-token",
229
+ });
230
+ setupBigBrainRoutes({
231
+ "deployment/foo-bar-123/team_and_project": () => ({
232
+ team: "my-team",
233
+ project: "my-project",
234
+ teamId: 1,
235
+ projectId: 42,
236
+ }),
237
+ "deployment/authorize_within_current_project": () => ({
238
+ adminKey: "dev-key",
239
+ url: "https://foo-bar-123.convex.cloud",
240
+ deploymentName: "foo-bar-123",
241
+ deploymentType: "dev",
242
+ }),
243
+ });
244
+ setupDefaultEnvPlatformMocks({ projectId: 42 });
245
+
246
+ await env.parseAsync(["default", "list", "--type", "production"], {
247
+ from: "user",
248
+ });
249
+
250
+ expect(mockPlatformGet).toHaveBeenCalledWith(
251
+ "/projects/{project_id}/list_default_environment_variables",
252
+ expect.objectContaining({
253
+ params: {
254
+ path: { project_id: 42 },
255
+ query: { deploymentType: "prod" },
256
+ },
257
+ }),
258
+ );
259
+ });
260
+
261
+ it("--type development aliases to dev", async () => {
262
+ process.env.CONVEX_DEPLOYMENT = "prod:foo-bar-123";
263
+ vi.mocked(readGlobalConfig).mockReturnValue({
264
+ accessToken: "test-token",
265
+ });
266
+ setupBigBrainRoutes({
267
+ "deployment/foo-bar-123/team_and_project": () => ({
268
+ team: "my-team",
269
+ project: "my-project",
270
+ teamId: 1,
271
+ projectId: 42,
272
+ }),
273
+ "deployment/authorize_within_current_project": () => ({
274
+ adminKey: "dev-key",
275
+ url: "https://foo-bar-123.convex.cloud",
276
+ deploymentName: "foo-bar-123",
277
+ deploymentType: "prod",
278
+ }),
279
+ });
280
+ setupDefaultEnvPlatformMocks({ projectId: 42 });
281
+
282
+ await env.parseAsync(["default", "list", "--type", "development"], {
283
+ from: "user",
284
+ });
285
+
286
+ expect(mockPlatformGet).toHaveBeenCalledWith(
287
+ "/projects/{project_id}/list_default_environment_variables",
288
+ expect.objectContaining({
289
+ params: {
290
+ path: { project_id: 42 },
291
+ query: { deploymentType: "dev" },
292
+ },
293
+ }),
294
+ );
295
+ });
296
+ });
297
+
298
+ describe("--project", () => {
299
+ it("--project team:proj --type prod does not require a current deployment", async () => {
300
+ vi.mocked(readGlobalConfig).mockReturnValue({
301
+ accessToken: "test-token",
302
+ });
303
+ setupBigBrainRoutes({});
304
+ setupDefaultEnvPlatformMocks({
305
+ projectId: 99,
306
+ teamSlug: "my-team",
307
+ projectSlug: "my-proj",
308
+ });
309
+
310
+ await env.parseAsync(
311
+ [
312
+ "default",
313
+ "set",
314
+ "ABC",
315
+ "DEF",
316
+ "--project",
317
+ "my-team:my-proj",
318
+ "--type",
319
+ "prod",
320
+ ],
321
+ { from: "user" },
322
+ );
323
+
324
+ expect(bigBrainAPI).not.toHaveBeenCalled();
325
+ expect(mockPlatformGet).toHaveBeenCalledWith(
326
+ "/teams/{team_id_or_slug}/projects/{project_slug}",
327
+ expect.objectContaining({
328
+ params: {
329
+ path: { team_id_or_slug: "my-team", project_slug: "my-proj" },
330
+ },
331
+ }),
332
+ );
333
+ expect(mockPlatformPost).toHaveBeenCalledWith(
334
+ "/projects/{project_id}/update_default_environment_variables",
335
+ expect.objectContaining({
336
+ params: { path: { project_id: 99 } },
337
+ body: {
338
+ changes: [{ name: "ABC", deploymentType: "prod", value: "DEF" }],
339
+ },
340
+ }),
341
+ );
342
+ });
343
+
344
+ it("--project just-proj --type prod uses current deployment's team", async () => {
345
+ process.env.CONVEX_DEPLOYMENT = "dev:foo-bar-123";
346
+ vi.mocked(readGlobalConfig).mockReturnValue({
347
+ accessToken: "test-token",
348
+ });
349
+ setupBigBrainRoutes({
350
+ "deployment/foo-bar-123/team_and_project": () => ({
351
+ team: "my-team",
352
+ project: "original-project",
353
+ teamId: 1,
354
+ projectId: 42,
355
+ }),
356
+ "deployment/authorize_within_current_project": () => ({
357
+ adminKey: "dev-key",
358
+ url: "https://foo-bar-123.convex.cloud",
359
+ deploymentName: "foo-bar-123",
360
+ deploymentType: "dev",
361
+ }),
362
+ });
363
+ setupDefaultEnvPlatformMocks({
364
+ projectId: 77,
365
+ teamSlug: "my-team",
366
+ projectSlug: "just-proj",
367
+ });
368
+
369
+ await env.parseAsync(
370
+ ["default", "list", "--project", "just-proj", "--type", "prod"],
371
+ { from: "user" },
372
+ );
373
+
374
+ expect(mockPlatformGet).toHaveBeenCalledWith(
375
+ "/teams/{team_id_or_slug}/projects/{project_slug}",
376
+ expect.objectContaining({
377
+ params: {
378
+ path: { team_id_or_slug: "my-team", project_slug: "just-proj" },
379
+ },
380
+ }),
381
+ );
382
+ expect(mockPlatformGet).toHaveBeenCalledWith(
383
+ "/projects/{project_id}/list_default_environment_variables",
384
+ expect.objectContaining({
385
+ params: {
386
+ path: { project_id: 77 },
387
+ query: { deploymentType: "prod" },
388
+ },
389
+ }),
390
+ );
391
+ });
392
+
393
+ it("--project team:proj without --type exits with a fatal error", async () => {
394
+ await expect(
395
+ env.parseAsync(["default", "list", "--project", "my-team:my-proj"], {
396
+ from: "user",
397
+ }),
398
+ ).rejects.toThrow();
399
+ expect(process.stderr.write).toHaveBeenCalledWith(
400
+ expect.stringContaining("--project requires --type"),
401
+ );
402
+ });
403
+
404
+ it("--project a:b:c (too many colons) exits with a fatal error", async () => {
405
+ await expect(
406
+ env.parseAsync(
407
+ ["default", "list", "--project", "a:b:c", "--type", "prod"],
408
+ { from: "user" },
409
+ ),
410
+ ).rejects.toThrow();
411
+ expect(process.stderr.write).toHaveBeenCalledWith(
412
+ expect.stringContaining("--project must be"),
413
+ );
414
+ });
415
+ });
416
+
417
+ describe("--type forwarded values", () => {
418
+ it("invalid --type values are forwarded; backend error surfaces", async () => {
419
+ process.env.CONVEX_DEPLOYMENT = "dev:foo-bar-123";
420
+ vi.mocked(readGlobalConfig).mockReturnValue({
421
+ accessToken: "test-token",
422
+ });
423
+ setupBigBrainRoutes({
424
+ "deployment/foo-bar-123/team_and_project": () => ({
425
+ team: "my-team",
426
+ project: "my-project",
427
+ teamId: 1,
428
+ projectId: 42,
429
+ }),
430
+ "deployment/authorize_within_current_project": () => ({
431
+ adminKey: "dev-key",
432
+ url: "https://foo-bar-123.convex.cloud",
433
+ deploymentName: "foo-bar-123",
434
+ deploymentType: "dev",
435
+ }),
436
+ });
437
+ mockPlatformGet.mockImplementation((path: string) => {
438
+ if (
439
+ path === "/projects/{project_id}/list_default_environment_variables"
440
+ ) {
441
+ throw new Error("backend rejected deploymentType: invalid-type");
442
+ }
443
+ throw new Error(`Unmocked platform GET: ${path}`);
444
+ });
445
+
446
+ await expect(
447
+ env.parseAsync(["default", "list", "--type", "invalid-type"], {
448
+ from: "user",
449
+ }),
450
+ ).rejects.toThrow();
451
+
452
+ expect(mockPlatformGet).toHaveBeenCalledWith(
453
+ "/projects/{project_id}/list_default_environment_variables",
454
+ expect.objectContaining({
455
+ params: expect.objectContaining({
456
+ query: expect.objectContaining({ deploymentType: "invalid-type" }),
457
+ }),
458
+ }),
459
+ );
460
+ });
461
+ });
462
+
463
+ describe("remove subcommand", () => {
464
+ it("--project team:proj --type prod wires through", async () => {
465
+ vi.mocked(readGlobalConfig).mockReturnValue({
466
+ accessToken: "test-token",
467
+ });
468
+ setupBigBrainRoutes({});
469
+ setupDefaultEnvPlatformMocks({ projectId: 55 });
470
+
471
+ await env.parseAsync(
472
+ [
473
+ "default",
474
+ "remove",
475
+ "ABC",
476
+ "--project",
477
+ "my-team:my-proj",
478
+ "--type",
479
+ "prod",
480
+ ],
481
+ { from: "user" },
482
+ );
483
+
484
+ expect(mockPlatformPost).toHaveBeenCalledWith(
485
+ "/projects/{project_id}/update_default_environment_variables",
486
+ expect.objectContaining({
487
+ params: { path: { project_id: 55 } },
488
+ body: {
489
+ changes: [{ name: "ABC", deploymentType: "prod", value: null }],
490
+ },
491
+ }),
492
+ );
493
+ });
494
+ });
495
+ });