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
@@ -7,9 +7,10 @@ import { test, describe } from "vitest";
7
7
  import { anyApi } from "../server/api.js";
8
8
 
9
9
  import type { ApiFromModules, QueryBuilder } from "../server/index.js";
10
- import { useQuery as useQueryReal } from "./client.js";
10
+ import { useQuery_experimental as useQuery_experimentalReal } from "./client.js";
11
11
 
12
- const useQuery = (() => {}) as unknown as typeof useQueryReal;
12
+ const useQuery_experimental =
13
+ (() => {}) as unknown as typeof useQuery_experimentalReal;
13
14
  const query: QueryBuilder<any, "public"> = (() => {}) as any;
14
15
 
15
16
  const module = {
@@ -21,28 +22,28 @@ const api = anyApi as unknown as API;
21
22
 
22
23
  describe("useQuery object options", () => {
23
24
  test("supports object options and skip sentinel", () => {
24
- useQuery({
25
+ useQuery_experimental({
25
26
  query: api.module.noArgs,
26
27
  args: {},
27
28
  });
28
29
 
29
- useQuery({
30
+ useQuery_experimental({
30
31
  query: api.module.args,
31
32
  args: { _arg: "asdf" },
32
33
  });
33
34
 
34
35
  const _arg: string | undefined = undefined;
35
- useQuery({
36
+ useQuery_experimental({
36
37
  query: api.module.args,
37
38
  args: _arg ? { _arg } : "skip",
38
39
  });
39
40
 
40
- useQuery({
41
+ useQuery_experimental({
41
42
  query: api.module.args,
42
43
  args: { _arg: "asdf" },
43
44
  });
44
45
 
45
- useQuery({
46
+ useQuery_experimental({
46
47
  query: api.module.noArgs,
47
48
  args: "skip",
48
49
  });
@@ -7,9 +7,12 @@ import { test, describe, expectTypeOf } from "vitest";
7
7
  import { anyApi } from "../server/api.js";
8
8
 
9
9
  import type { ApiFromModules, QueryBuilder } from "../server/index.js";
10
- import { useQuery as useQueryReal, type UseQueryResult } from "./client.js";
10
+ import {
11
+ useQuery_experimental as useQueryReal,
12
+ type UseQueryResult,
13
+ } from "./client.js";
11
14
 
12
- const useQuery = (() => {}) as unknown as typeof useQueryReal;
15
+ const useQuery_experimental = (() => {}) as unknown as typeof useQueryReal;
13
16
  const query: QueryBuilder<any, "public"> = (() => {}) as any;
14
17
 
15
18
  const module = {
@@ -19,24 +22,54 @@ const module = {
19
22
  type API = ApiFromModules<{ module: typeof module }>;
20
23
  const api = anyApi as unknown as API;
21
24
 
22
- describe("useQuery object-form result types", () => {
25
+ describe("useQuery_experimental result types", () => {
23
26
  test("supports object-form result usage", () => {
24
- useQuery({
27
+ useQuery_experimental({
25
28
  query: api.module.args,
26
29
  args: { _arg: "asdf" },
27
30
  });
28
31
 
29
- useQuery({
32
+ const throwingResult = useQuery_experimental({
30
33
  query: api.module.args,
31
34
  args: { _arg: "asdf" },
32
35
  throwOnError: true,
33
36
  });
37
+ expectTypeOf(throwingResult).toEqualTypeOf<UseQueryResult<string, true>>();
34
38
 
35
39
  const _arg: string | undefined = undefined;
36
- const conditionalResult = useQuery({
40
+ const conditionalResult = useQuery_experimental({
37
41
  query: api.module.args,
38
42
  args: _arg ? { _arg } : "skip",
39
43
  });
40
- expectTypeOf(conditionalResult).toEqualTypeOf<UseQueryResult<string>>();
44
+ expectTypeOf(conditionalResult).toEqualTypeOf<
45
+ UseQueryResult<string, false>
46
+ >();
47
+ });
48
+
49
+ test("throwOnError:true omits error from result", () => {
50
+ // Never executed; exists only for type checking.
51
+ () => {
52
+ const throwingResult = useQuery_experimental({
53
+ query: api.module.args,
54
+ args: { _arg: "asdf" },
55
+ throwOnError: true,
56
+ });
57
+ expectTypeOf<(typeof throwingResult)["status"]>().toEqualTypeOf<
58
+ "pending" | "success"
59
+ >();
60
+ };
61
+ });
62
+
63
+ test("throwOnError ommitted includes error in result", () => {
64
+ // Never executed; exists only for type checking.
65
+ () => {
66
+ const throwingResult = useQuery_experimental({
67
+ query: api.module.args,
68
+ args: { _arg: "asdf" },
69
+ });
70
+ expectTypeOf<(typeof throwingResult)["status"]>().toEqualTypeOf<
71
+ "pending" | "success" | "error"
72
+ >();
73
+ };
41
74
  });
42
75
  });
@@ -0,0 +1,109 @@
1
+ /* eslint-disable @typescript-eslint/no-unused-vars */
2
+ import { assert, Equals } from "../test/type_testing.js";
3
+ import { test } from "vitest";
4
+ import {
5
+ ApiFromModules,
6
+ FilterApi,
7
+ FunctionReference,
8
+ FunctionReferenceFromExport,
9
+ } from "./api.js";
10
+ import {
11
+ EmptyObject,
12
+ RegisteredAction,
13
+ RegisteredMutation,
14
+ RegisteredQuery,
15
+ } from "./registration.js";
16
+
17
+ test("FunctionReferenceFromExport preserves visibility through intersections", () => {
18
+ type TaggedPublicMutation = RegisteredMutation<
19
+ "public",
20
+ EmptyObject,
21
+ string
22
+ > & { foo: "bar" };
23
+ type TaggedInternalMutation = RegisteredMutation<
24
+ "internal",
25
+ EmptyObject,
26
+ string
27
+ > & { foo: "bar" };
28
+ type TaggedInternalQuery = RegisteredQuery<
29
+ "internal",
30
+ { x: number },
31
+ string
32
+ > & { tag: true };
33
+ type TaggedPublicAction = RegisteredAction<"public", EmptyObject, number> & {
34
+ a: 1;
35
+ };
36
+
37
+ assert<
38
+ Equals<
39
+ FunctionReferenceFromExport<TaggedPublicMutation>,
40
+ FunctionReference<"mutation", "public", EmptyObject, string>
41
+ >
42
+ >();
43
+ assert<
44
+ Equals<
45
+ FunctionReferenceFromExport<TaggedInternalMutation>,
46
+ FunctionReference<"mutation", "internal", EmptyObject, string>
47
+ >
48
+ >();
49
+ assert<
50
+ Equals<
51
+ FunctionReferenceFromExport<TaggedInternalQuery>,
52
+ FunctionReference<"query", "internal", { x: number }, string>
53
+ >
54
+ >();
55
+ assert<
56
+ Equals<
57
+ FunctionReferenceFromExport<TaggedPublicAction>,
58
+ FunctionReference<"action", "public", EmptyObject, number>
59
+ >
60
+ >();
61
+ });
62
+
63
+ test("intersected functions show up in api / internal", () => {
64
+ type TaggedInternal = RegisteredMutation<"internal", EmptyObject, string> & {
65
+ foo: "bar";
66
+ };
67
+ type TaggedPublic = RegisteredMutation<"public", EmptyObject, number> & {
68
+ tag: true;
69
+ };
70
+
71
+ const myModule = {
72
+ taggedInternal: null as unknown as TaggedInternal,
73
+ taggedPublic: null as unknown as TaggedPublic,
74
+ };
75
+ type API = ApiFromModules<{ myModule: typeof myModule }>;
76
+ type Internal = FilterApi<API, FunctionReference<any, "internal">>;
77
+ type Public = FilterApi<API, FunctionReference<any, "public">>;
78
+
79
+ assert<
80
+ Equals<
81
+ Internal,
82
+ {
83
+ myModule: {
84
+ taggedInternal: FunctionReference<
85
+ "mutation",
86
+ "internal",
87
+ EmptyObject,
88
+ string
89
+ >;
90
+ };
91
+ }
92
+ >
93
+ >();
94
+ assert<
95
+ Equals<
96
+ Public,
97
+ {
98
+ myModule: {
99
+ taggedPublic: FunctionReference<
100
+ "mutation",
101
+ "public",
102
+ EmptyObject,
103
+ number
104
+ >;
105
+ };
106
+ }
107
+ >
108
+ >();
109
+ });
@@ -0,0 +1,129 @@
1
+ import { describe, expect, test } from "vitest";
2
+ import { AuditLogBody, cloneWithSentinels } from "./audit_logging.js";
3
+ import { log } from "./log.js";
4
+
5
+ describe("cloneWithSentinels", () => {
6
+ test("clones the body when there are no log vars", () => {
7
+ const input: AuditLogBody = {
8
+ foo: "bar",
9
+ count: 42,
10
+ flag: true,
11
+ empty: null,
12
+ nested: { inner: "value", arr: [1, 2, 3] },
13
+ };
14
+ const result = cloneWithSentinels(input);
15
+
16
+ expect(result).toEqual(input);
17
+ expect(result).not.toBe(input);
18
+ expect(result.nested).not.toBe(input.nested);
19
+ });
20
+
21
+ test("replaces log vars with sentinel objects", () => {
22
+ const input: AuditLogBody = {
23
+ userIp: log.vars.ip,
24
+ agent: log.vars.userAgent,
25
+ ts: log.vars.now,
26
+ reqId: log.vars.requestId,
27
+ note: "hello",
28
+ };
29
+ const result = cloneWithSentinels(input);
30
+
31
+ expect(result).toEqual({
32
+ userIp: { $var: "ip" },
33
+ agent: { $var: "userAgent" },
34
+ ts: { $var: "now" },
35
+ reqId: { $var: "requestId" },
36
+ note: "hello",
37
+ });
38
+ });
39
+
40
+ test("handles log vars nested inside an object", () => {
41
+ const input: AuditLogBody = {
42
+ outer: {
43
+ inner: {
44
+ userIp: log.vars.ip,
45
+ ts: log.vars.now,
46
+ },
47
+ label: "x",
48
+ },
49
+ };
50
+ const result = cloneWithSentinels(input);
51
+
52
+ expect(result).toEqual({
53
+ outer: {
54
+ inner: { userIp: { $var: "ip" }, ts: { $var: "now" } },
55
+ label: "x",
56
+ },
57
+ });
58
+ });
59
+
60
+ test("handles log vars inside arrays", () => {
61
+ const input: AuditLogBody = {
62
+ items: [log.vars.ip, log.vars.userAgent, log.vars.now, "literal"],
63
+ };
64
+ const result = cloneWithSentinels(input);
65
+
66
+ expect(result).toEqual({
67
+ items: [
68
+ { $var: "ip" },
69
+ { $var: "userAgent" },
70
+ { $var: "now" },
71
+ "literal",
72
+ ],
73
+ });
74
+ });
75
+
76
+ test("handles the same var used multiple times", () => {
77
+ const input: AuditLogBody = {
78
+ topIp: log.vars.ip,
79
+ nested: { anotherIp: log.vars.ip },
80
+ list: [log.vars.ip],
81
+ };
82
+ const result = cloneWithSentinels(input);
83
+
84
+ expect(result).toEqual({
85
+ topIp: { $var: "ip" },
86
+ nested: { anotherIp: { $var: "ip" } },
87
+ list: [{ $var: "ip" }],
88
+ });
89
+ });
90
+
91
+ test("handles log vars inside objects within an array", () => {
92
+ const input: AuditLogBody = {
93
+ records: [
94
+ { ip: log.vars.ip, name: "a" },
95
+ { ts: log.vars.now, name: "b" },
96
+ { agent: log.vars.userAgent, name: "c" },
97
+ ],
98
+ };
99
+ const result = cloneWithSentinels(input);
100
+
101
+ expect(result).toEqual({
102
+ records: [
103
+ { ip: { $var: "ip" }, name: "a" },
104
+ { ts: { $var: "now" }, name: "b" },
105
+ { agent: { $var: "userAgent" }, name: "c" },
106
+ ],
107
+ });
108
+ });
109
+
110
+ test("throws on keys starting with $", () => {
111
+ expect(() => cloneWithSentinels({ $var: "ip" })).toThrow(
112
+ 'keys must not start with "$"',
113
+ );
114
+ });
115
+
116
+ test("throws on $ keys nested inside objects", () => {
117
+ expect(() => cloneWithSentinels({ outer: { $secret: "value" } })).toThrow(
118
+ 'keys must not start with "$"',
119
+ );
120
+ });
121
+
122
+ test("throws on unknown symbol var", () => {
123
+ const fakeVar = Symbol("var.fake");
124
+ expect(() =>
125
+ // @ts-expect-error intentionally passing an invalid var symbol
126
+ cloneWithSentinels({ x: fakeVar }),
127
+ ).toThrow("Unknown audit var symbol");
128
+ });
129
+ });
@@ -0,0 +1,75 @@
1
+ import { performAsyncSyscall } from "./impl/syscall.js";
2
+ import { LogVar, varNames } from "./logVars.js";
3
+
4
+ export type AuditLogBody = { [key: string]: AuditLogValue };
5
+ export type AuditLogValue =
6
+ | null
7
+ | undefined
8
+ | boolean
9
+ | number
10
+ | string
11
+ | LogVar
12
+ | AuditLogValue[]
13
+ | { [key: string]: AuditLogValue };
14
+
15
+ type JsonValue =
16
+ | null
17
+ | undefined
18
+ | boolean
19
+ | number
20
+ | string
21
+ | JsonValue[]
22
+ | { [key: string]: JsonValue };
23
+
24
+ function validateKey(key: string) {
25
+ if (key.startsWith("$")) {
26
+ throw new Error(`Audit log body keys must not start with "$": "${key}"`);
27
+ }
28
+ }
29
+
30
+ function cloneValue(value: AuditLogValue): JsonValue {
31
+ if (typeof value === "symbol") {
32
+ if (!(value in varNames)) {
33
+ throw new Error(
34
+ `Unknown audit var symbol: ${String(value)}. Use one of log.var.requestId, log.var.ip, log.var.userAgent, or log.var.now.`,
35
+ );
36
+ }
37
+ return { $var: varNames[value] };
38
+ }
39
+ if (value === null || value === undefined || typeof value !== "object") {
40
+ return value;
41
+ }
42
+ if (Array.isArray(value)) {
43
+ return value.map(cloneValue);
44
+ }
45
+ const result: { [key: string]: JsonValue } = {};
46
+ for (const [key, val] of Object.entries(value)) {
47
+ validateKey(key);
48
+ result[key] = cloneValue(val);
49
+ }
50
+ return result;
51
+ }
52
+
53
+ /**
54
+ * Deep-clone the body, replacing audit var symbols with sentinel objects
55
+ * like `{ $var: "ip" }`.
56
+ */
57
+ export function cloneWithSentinels(body: AuditLogBody): {
58
+ [key: string]: JsonValue;
59
+ } {
60
+ const result: { [key: string]: JsonValue } = {};
61
+ for (const [key, val] of Object.entries(body)) {
62
+ validateKey(key);
63
+ result[key] = cloneValue(val);
64
+ }
65
+ return result;
66
+ }
67
+
68
+ /**
69
+ * @internal
70
+ */
71
+ export const audit = async (body: AuditLogBody): Promise<void> => {
72
+ await performAsyncSyscall("1.0/auditLog", {
73
+ body: cloneWithSentinels(body),
74
+ });
75
+ };
@@ -3,8 +3,10 @@ import {
3
3
  ActionMeta,
4
4
  MutationMeta,
5
5
  QueryMeta,
6
+ RequestMetadata,
6
7
  FunctionMetadata,
7
8
  TransactionMetrics,
9
+ DeploymentMetadata,
8
10
  } from "../meta.js";
9
11
  import { performAsyncSyscall } from "./syscall.js";
10
12
 
@@ -35,6 +37,27 @@ async function getFunctionMetadata(): Promise<{
35
37
  return { name, componentPath };
36
38
  }
37
39
 
40
+ async function getDeploymentMetadata(): Promise<DeploymentMetadata> {
41
+ const syscallJSON = await performAsyncSyscall(
42
+ "1.0/getDeploymentMetadata",
43
+ {},
44
+ );
45
+ const result = jsonToConvex(syscallJSON) as any;
46
+ return {
47
+ name: result.name,
48
+ region: result.region ?? null,
49
+ class: result.class,
50
+ };
51
+ }
52
+
53
+ async function getRequestMetadata(): Promise<RequestMetadata> {
54
+ const { ip, userAgent, requestId } = await performAsyncSyscall(
55
+ "1.0/getRequestMetadata",
56
+ {},
57
+ );
58
+ return { ip, userAgent, requestId };
59
+ }
60
+
38
61
  export function setupQueryMeta(
39
62
  visibility: FunctionMetadata["visibility"],
40
63
  ): QueryMeta {
@@ -45,6 +68,7 @@ export function setupQueryMeta(
45
68
  visibility,
46
69
  }),
47
70
  getTransactionMetrics,
71
+ getDeploymentMetadata,
48
72
  };
49
73
  }
50
74
 
@@ -58,6 +82,8 @@ export function setupMutationMeta(
58
82
  visibility,
59
83
  }),
60
84
  getTransactionMetrics,
85
+ getDeploymentMetadata,
86
+ getRequestMetadata,
61
87
  };
62
88
  }
63
89
 
@@ -70,5 +96,7 @@ export function setupActionMeta(
70
96
  type: "action",
71
97
  visibility,
72
98
  }),
99
+ getDeploymentMetadata,
100
+ getRequestMetadata,
73
101
  };
74
102
  }
@@ -492,6 +492,7 @@ export const internalQueryGeneric: QueryBuilder<any, "internal"> = ((
492
492
  async function invokeAction<
493
493
  F extends (ctx: GenericActionCtx<GenericDataModel>, ...args: any) => any,
494
494
  >(func: F, requestId: string, argsStr: string, visibility: FunctionVisibility) {
495
+ (globalThis as any).Convex?.setupPerformance?.();
495
496
  const args = jsonToConvex(JSON.parse(argsStr));
496
497
  const calls = setupActionCalls(requestId);
497
498
  const ctx = {
@@ -673,6 +674,7 @@ export const internalActionGeneric: ActionBuilder<any, "internal"> = ((
673
674
  async function invokeHttpAction<
674
675
  F extends (ctx: GenericActionCtx<GenericDataModel>, request: Request) => any,
675
676
  >(func: F, request: Request) {
677
+ (globalThis as any).Convex?.setupPerformance?.();
676
678
  // TODO(presley): Change the function signature and propagate the requestId from Rust.
677
679
  // Ok, to mock it out for now, since http endpoints are only running in V8.
678
680
  const requestId = "";
@@ -107,6 +107,8 @@ export type {
107
107
  TransactionMetric,
108
108
  TransactionMetrics,
109
109
  FunctionMetadata,
110
+ DeploymentMetadata,
111
+ RequestMetadata,
110
112
  QueryMeta,
111
113
  MutationMeta,
112
114
  ActionMeta,
@@ -177,6 +179,7 @@ export type {
177
179
  PartialApi,
178
180
  ArgsAndOptions,
179
181
  FunctionReturnType,
182
+ ValidatorTypeToReturnType,
180
183
  } from "./api.js";
181
184
  export {
182
185
  defineApp,
@@ -201,6 +204,15 @@ export type {
201
204
  */
202
205
  export type { Index, SearchIndex, VectorIndex } from "./schema.js";
203
206
 
207
+ /**
208
+ * @internal
209
+ */
210
+ export { log } from "./log.js";
211
+ /**
212
+ * @internal
213
+ */
214
+ export type { AuditLogBody, AuditLogValue } from "./audit_logging.js";
215
+
204
216
  export type {
205
217
  SearchIndexConfig,
206
218
  VectorIndexConfig,
@@ -0,0 +1,16 @@
1
+ import { audit } from "./audit_logging.js";
2
+ import { vars } from "./logVars.js";
3
+
4
+ // Type annotations are needed for the `unique symbol` types in `vars` to typecheck correctly
5
+ interface Log {
6
+ audit: typeof audit;
7
+ vars: typeof vars;
8
+ }
9
+
10
+ /**
11
+ * @internal
12
+ */
13
+ export const log: Log = {
14
+ audit,
15
+ vars,
16
+ };
@@ -0,0 +1,34 @@
1
+ const REQUEST_ID = Symbol("var.requestId");
2
+ const IP = Symbol("var.ip");
3
+ const USER_AGENT = Symbol("var.userAgent");
4
+ const NOW = Symbol("var.now");
5
+
6
+ export type LogVar =
7
+ | typeof REQUEST_ID
8
+ | typeof IP
9
+ | typeof USER_AGENT
10
+ | typeof NOW;
11
+
12
+ /**
13
+ * @internal
14
+ */
15
+ export const varNames: Record<symbol, string> = {
16
+ [REQUEST_ID]: "requestId",
17
+ [IP]: "ip",
18
+ [USER_AGENT]: "userAgent",
19
+ [NOW]: "now",
20
+ };
21
+
22
+ export const vars = {
23
+ /** Resolved to the request ID. */
24
+ requestId: REQUEST_ID,
25
+ /** Resolved to the client's IP address. */
26
+ ip: IP,
27
+ /** Resolved to the client's User-Agent header. */
28
+ userAgent: USER_AGENT,
29
+ /**
30
+ * Resolved to the current server timestamp, as milliseconds from the
31
+ * Unix epoch.
32
+ */
33
+ now: NOW,
34
+ } as const;
@@ -49,6 +49,46 @@ export type FunctionMetadata = {
49
49
  visibility: FunctionVisibility;
50
50
  };
51
51
 
52
+ /**
53
+ * Metadata about the deployment this function is running on.
54
+ *
55
+ * @public
56
+ */
57
+ export type DeploymentMetadata = {
58
+ /**
59
+ * The deployment name, e.g. `"tall-tiger-123"` for cloud deployments,
60
+ * `"local-my_team-my_project"` for local deployments, or
61
+ * `"anonymous-*"` for anonymous deployments.
62
+ */
63
+ name: string;
64
+ /**
65
+ * The deployment region, e.g. `"aws-us-east-1"`.
66
+ * `null` for local and self-hosted deployments.
67
+ */
68
+ region: string | null;
69
+ /**
70
+ * The deployment class, e.g. `"s16"`, `"s256"`, or `"d1024"`.
71
+ */
72
+ class: "s16" | "s256" | "d1024";
73
+ };
74
+
75
+ /**
76
+ * Metadata about the HTTP request that triggered the current function execution.
77
+ *
78
+ * `ip` and `userAgent` are `null` when the function was not triggered by an
79
+ * HTTP request (e.g. scheduled jobs or cron jobs).
80
+ *
81
+ * Functions called from within a function (i.e. using `runMutation` or
82
+ * `runAction`) will have the same request metadata as the parent function.
83
+ *
84
+ * @public
85
+ */
86
+ export type RequestMetadata = {
87
+ ip: string | null;
88
+ userAgent: string | null;
89
+ requestId: string;
90
+ };
91
+
52
92
  /**
53
93
  * Extra context available in Convex query functions.
54
94
  *
@@ -57,6 +97,7 @@ export type FunctionMetadata = {
57
97
  export interface QueryMeta {
58
98
  getFunctionMetadata(): Promise<FunctionMetadata>;
59
99
  getTransactionMetrics(): Promise<TransactionMetrics>;
100
+ getDeploymentMetadata(): Promise<DeploymentMetadata>;
60
101
  }
61
102
 
62
103
  /**
@@ -64,7 +105,12 @@ export interface QueryMeta {
64
105
  *
65
106
  * @public
66
107
  */
67
- export interface MutationMeta extends QueryMeta {}
108
+ export interface MutationMeta extends QueryMeta {
109
+ /**
110
+ * @internal
111
+ */
112
+ getRequestMetadata(): Promise<RequestMetadata>;
113
+ }
68
114
 
69
115
  /**
70
116
  * Extra context available in Convex action functions.
@@ -73,4 +119,10 @@ export interface MutationMeta extends QueryMeta {}
73
119
  */
74
120
  export interface ActionMeta {
75
121
  getFunctionMetadata(): Promise<FunctionMetadata>;
122
+ getDeploymentMetadata(): Promise<DeploymentMetadata>;
123
+
124
+ /**
125
+ * @internal
126
+ */
127
+ getRequestMetadata(): Promise<RequestMetadata>;
76
128
  }