convex 1.42.3 → 1.43.0-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (243) hide show
  1. package/bin/main-dev +6 -1
  2. package/dist/browser.bundle.js +49 -10
  3. package/dist/browser.bundle.js.map +2 -2
  4. package/dist/cjs/browser/simple_client-node.js +35 -35
  5. package/dist/cjs/browser/simple_client-node.js.map +2 -2
  6. package/dist/cjs/browser/sync/paginated_query_client.js +20 -9
  7. package/dist/cjs/browser/sync/paginated_query_client.js.map +2 -2
  8. package/dist/cjs/cli/codegen_templates/validator_helpers.js +2 -0
  9. package/dist/cjs/cli/codegen_templates/validator_helpers.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/deploymentCreate.js.map +2 -2
  13. package/dist/cjs/cli/generatedApi.js.map +1 -1
  14. package/dist/cjs/cli/lib/deployApi/validator.js +1 -0
  15. package/dist/cjs/cli/lib/deployApi/validator.js.map +2 -2
  16. package/dist/cjs/cli/lib/deploymentSelection.js.map +2 -2
  17. package/dist/cjs/cli/lib/generateDocs.js +1 -1
  18. package/dist/cjs/cli/lib/generateDocs.js.map +2 -2
  19. package/dist/cjs/cli/lib/generatedFunctionLogsApi.js.map +1 -1
  20. package/dist/cjs/cli/lib/localDeployment/projectMismatch.js.map +2 -2
  21. package/dist/cjs/cli/lib/login.js +23 -23
  22. package/dist/cjs/cli/lib/login.js.map +2 -2
  23. package/dist/cjs/cli/lib/typecheck.js +28 -25
  24. package/dist/cjs/cli/lib/typecheck.js.map +2 -2
  25. package/dist/cjs/cli/lib/usageLimits.js +164 -0
  26. package/dist/cjs/cli/lib/usageLimits.js.map +7 -0
  27. package/dist/cjs/cli/usageLimits.js +326 -0
  28. package/dist/cjs/cli/usageLimits.js.map +7 -0
  29. package/dist/cjs/index.js +1 -1
  30. package/dist/cjs/index.js.map +1 -1
  31. package/dist/cjs/server/components/index.js.map +2 -2
  32. package/dist/cjs/server/cron.js +33 -29
  33. package/dist/cjs/server/cron.js.map +2 -2
  34. package/dist/cjs/server/database.js.map +1 -1
  35. package/dist/cjs/server/impl/database_impl.js +3 -0
  36. package/dist/cjs/server/impl/database_impl.js.map +2 -2
  37. package/dist/cjs/server/log.js +2 -1
  38. package/dist/cjs/server/log.js.map +2 -2
  39. package/dist/cjs/server/logVars.js +12 -1
  40. package/dist/cjs/server/logVars.js.map +2 -2
  41. package/dist/cjs/values/compare.js +5 -1
  42. package/dist/cjs/values/compare.js.map +2 -2
  43. package/dist/cjs/values/index.js +1 -0
  44. package/dist/cjs/values/index.js.map +2 -2
  45. package/dist/cjs/values/size.js +4 -0
  46. package/dist/cjs/values/size.js.map +2 -2
  47. package/dist/cjs/values/validator.js +11 -0
  48. package/dist/cjs/values/validator.js.map +2 -2
  49. package/dist/cjs/values/validators.js +20 -0
  50. package/dist/cjs/values/validators.js.map +2 -2
  51. package/dist/cjs/values/value.js +31 -0
  52. package/dist/cjs/values/value.js.map +2 -2
  53. package/dist/cjs-types/cli/codegen_templates/validator_helpers.d.ts.map +1 -1
  54. package/dist/cjs-types/cli/codegen_templates/validator_helpers.test.d.ts +2 -0
  55. package/dist/cjs-types/cli/codegen_templates/validator_helpers.test.d.ts.map +1 -0
  56. package/dist/cjs-types/cli/deployment.d.ts.map +1 -1
  57. package/dist/cjs-types/cli/deploymentCreate.d.ts +2 -2
  58. package/dist/cjs-types/cli/generatedApi.d.ts +43 -43
  59. package/dist/cjs-types/cli/generatedApi.d.ts.map +1 -1
  60. package/dist/cjs-types/cli/lib/deployApi/validator.d.ts +6 -0
  61. package/dist/cjs-types/cli/lib/deployApi/validator.d.ts.map +1 -1
  62. package/dist/cjs-types/cli/lib/deploymentSelection.d.ts +2 -2
  63. package/dist/cjs-types/cli/lib/deploymentSelection.d.ts.map +1 -1
  64. package/dist/cjs-types/cli/lib/generatedFunctionLogsApi.d.ts +45 -45
  65. package/dist/cjs-types/cli/lib/generatedFunctionLogsApi.d.ts.map +1 -1
  66. package/dist/cjs-types/cli/lib/localDeployment/projectMismatch.d.ts +2 -2
  67. package/dist/cjs-types/cli/lib/localDeployment/projectMismatch.d.ts.map +1 -1
  68. package/dist/cjs-types/cli/lib/login.d.ts.map +1 -1
  69. package/dist/cjs-types/cli/lib/mcp/tools/insights.d.ts +24 -24
  70. package/dist/cjs-types/cli/lib/typecheck.d.ts +2 -0
  71. package/dist/cjs-types/cli/lib/typecheck.d.ts.map +1 -1
  72. package/dist/cjs-types/cli/lib/typecheck.test.d.ts +2 -0
  73. package/dist/cjs-types/cli/lib/typecheck.test.d.ts.map +1 -0
  74. package/dist/cjs-types/cli/lib/usageLimits.d.ts +46 -0
  75. package/dist/cjs-types/cli/lib/usageLimits.d.ts.map +1 -0
  76. package/dist/cjs-types/cli/usageLimits.d.ts +22 -0
  77. package/dist/cjs-types/cli/usageLimits.d.ts.map +1 -0
  78. package/dist/cjs-types/index.d.ts +1 -1
  79. package/dist/cjs-types/index.d.ts.map +1 -1
  80. package/dist/cjs-types/server/components/index.d.ts +26 -8
  81. package/dist/cjs-types/server/components/index.d.ts.map +1 -1
  82. package/dist/cjs-types/server/cron.d.ts +20 -11
  83. package/dist/cjs-types/server/cron.d.ts.map +1 -1
  84. package/dist/cjs-types/server/cron.test.d.ts +2 -0
  85. package/dist/cjs-types/server/cron.test.d.ts.map +1 -0
  86. package/dist/cjs-types/server/database.d.ts +14 -0
  87. package/dist/cjs-types/server/database.d.ts.map +1 -1
  88. package/dist/cjs-types/server/impl/database_impl.d.ts.map +1 -1
  89. package/dist/cjs-types/server/log.d.ts.map +1 -1
  90. package/dist/cjs-types/server/logVars.d.ts +14 -1
  91. package/dist/cjs-types/server/logVars.d.ts.map +1 -1
  92. package/dist/cjs-types/values/compare.d.ts.map +1 -1
  93. package/dist/cjs-types/values/index.d.ts +2 -2
  94. package/dist/cjs-types/values/index.d.ts.map +1 -1
  95. package/dist/cjs-types/values/size.d.ts +1 -1
  96. package/dist/cjs-types/values/size.d.ts.map +1 -1
  97. package/dist/cjs-types/values/validator.d.ts +10 -1
  98. package/dist/cjs-types/values/validator.d.ts.map +1 -1
  99. package/dist/cjs-types/values/validators.d.ts +14 -3
  100. package/dist/cjs-types/values/validators.d.ts.map +1 -1
  101. package/dist/cjs-types/values/value.d.ts +18 -1
  102. package/dist/cjs-types/values/value.d.ts.map +1 -1
  103. package/dist/cli.bundle.cjs +2534 -2009
  104. package/dist/cli.bundle.cjs.map +4 -4
  105. package/dist/esm/browser/simple_client-node.js +35 -35
  106. package/dist/esm/browser/simple_client-node.js.map +1 -1
  107. package/dist/esm/browser/sync/paginated_query_client.js +20 -9
  108. package/dist/esm/browser/sync/paginated_query_client.js.map +2 -2
  109. package/dist/esm/cli/codegen_templates/validator_helpers.js +2 -0
  110. package/dist/esm/cli/codegen_templates/validator_helpers.js.map +2 -2
  111. package/dist/esm/cli/deployment.js +2 -1
  112. package/dist/esm/cli/deployment.js.map +2 -2
  113. package/dist/esm/cli/deploymentCreate.js.map +2 -2
  114. package/dist/esm/cli/lib/deployApi/validator.js +1 -0
  115. package/dist/esm/cli/lib/deployApi/validator.js.map +2 -2
  116. package/dist/esm/cli/lib/deploymentSelection.js.map +2 -2
  117. package/dist/esm/cli/lib/generateDocs.js +1 -1
  118. package/dist/esm/cli/lib/generateDocs.js.map +2 -2
  119. package/dist/esm/cli/lib/localDeployment/projectMismatch.js.map +2 -2
  120. package/dist/esm/cli/lib/login.js +23 -23
  121. package/dist/esm/cli/lib/login.js.map +2 -2
  122. package/dist/esm/cli/lib/typecheck.js +27 -25
  123. package/dist/esm/cli/lib/typecheck.js.map +2 -2
  124. package/dist/esm/cli/lib/usageLimits.js +129 -0
  125. package/dist/esm/cli/lib/usageLimits.js.map +7 -0
  126. package/dist/esm/cli/usageLimits.js +316 -0
  127. package/dist/esm/cli/usageLimits.js.map +7 -0
  128. package/dist/esm/index.js +1 -1
  129. package/dist/esm/index.js.map +1 -1
  130. package/dist/esm/server/components/index.js.map +2 -2
  131. package/dist/esm/server/cron.js +33 -29
  132. package/dist/esm/server/cron.js.map +2 -2
  133. package/dist/esm/server/impl/database_impl.js +4 -1
  134. package/dist/esm/server/impl/database_impl.js.map +2 -2
  135. package/dist/esm/server/log.js +3 -2
  136. package/dist/esm/server/log.js.map +2 -2
  137. package/dist/esm/server/logVars.js +11 -1
  138. package/dist/esm/server/logVars.js.map +2 -2
  139. package/dist/esm/values/compare.js +5 -1
  140. package/dist/esm/values/compare.js.map +2 -2
  141. package/dist/esm/values/index.js +1 -1
  142. package/dist/esm/values/index.js.map +2 -2
  143. package/dist/esm/values/size.js +4 -0
  144. package/dist/esm/values/size.js.map +2 -2
  145. package/dist/esm/values/validator.js +12 -0
  146. package/dist/esm/values/validator.js.map +2 -2
  147. package/dist/esm/values/validators.js +19 -0
  148. package/dist/esm/values/validators.js.map +2 -2
  149. package/dist/esm/values/value.js +29 -1
  150. package/dist/esm/values/value.js.map +2 -2
  151. package/dist/esm-types/cli/codegen_templates/validator_helpers.d.ts.map +1 -1
  152. package/dist/esm-types/cli/codegen_templates/validator_helpers.test.d.ts +2 -0
  153. package/dist/esm-types/cli/codegen_templates/validator_helpers.test.d.ts.map +1 -0
  154. package/dist/esm-types/cli/deployment.d.ts.map +1 -1
  155. package/dist/esm-types/cli/deploymentCreate.d.ts +2 -2
  156. package/dist/esm-types/cli/generatedApi.d.ts +43 -43
  157. package/dist/esm-types/cli/generatedApi.d.ts.map +1 -1
  158. package/dist/esm-types/cli/lib/deployApi/validator.d.ts +6 -0
  159. package/dist/esm-types/cli/lib/deployApi/validator.d.ts.map +1 -1
  160. package/dist/esm-types/cli/lib/deploymentSelection.d.ts +2 -2
  161. package/dist/esm-types/cli/lib/deploymentSelection.d.ts.map +1 -1
  162. package/dist/esm-types/cli/lib/generatedFunctionLogsApi.d.ts +45 -45
  163. package/dist/esm-types/cli/lib/generatedFunctionLogsApi.d.ts.map +1 -1
  164. package/dist/esm-types/cli/lib/localDeployment/projectMismatch.d.ts +2 -2
  165. package/dist/esm-types/cli/lib/localDeployment/projectMismatch.d.ts.map +1 -1
  166. package/dist/esm-types/cli/lib/login.d.ts.map +1 -1
  167. package/dist/esm-types/cli/lib/mcp/tools/insights.d.ts +24 -24
  168. package/dist/esm-types/cli/lib/typecheck.d.ts +2 -0
  169. package/dist/esm-types/cli/lib/typecheck.d.ts.map +1 -1
  170. package/dist/esm-types/cli/lib/typecheck.test.d.ts +2 -0
  171. package/dist/esm-types/cli/lib/typecheck.test.d.ts.map +1 -0
  172. package/dist/esm-types/cli/lib/usageLimits.d.ts +46 -0
  173. package/dist/esm-types/cli/lib/usageLimits.d.ts.map +1 -0
  174. package/dist/esm-types/cli/usageLimits.d.ts +22 -0
  175. package/dist/esm-types/cli/usageLimits.d.ts.map +1 -0
  176. package/dist/esm-types/index.d.ts +1 -1
  177. package/dist/esm-types/index.d.ts.map +1 -1
  178. package/dist/esm-types/server/components/index.d.ts +26 -8
  179. package/dist/esm-types/server/components/index.d.ts.map +1 -1
  180. package/dist/esm-types/server/cron.d.ts +20 -11
  181. package/dist/esm-types/server/cron.d.ts.map +1 -1
  182. package/dist/esm-types/server/cron.test.d.ts +2 -0
  183. package/dist/esm-types/server/cron.test.d.ts.map +1 -0
  184. package/dist/esm-types/server/database.d.ts +14 -0
  185. package/dist/esm-types/server/database.d.ts.map +1 -1
  186. package/dist/esm-types/server/impl/database_impl.d.ts.map +1 -1
  187. package/dist/esm-types/server/log.d.ts.map +1 -1
  188. package/dist/esm-types/server/logVars.d.ts +14 -1
  189. package/dist/esm-types/server/logVars.d.ts.map +1 -1
  190. package/dist/esm-types/values/compare.d.ts.map +1 -1
  191. package/dist/esm-types/values/index.d.ts +2 -2
  192. package/dist/esm-types/values/index.d.ts.map +1 -1
  193. package/dist/esm-types/values/size.d.ts +1 -1
  194. package/dist/esm-types/values/size.d.ts.map +1 -1
  195. package/dist/esm-types/values/validator.d.ts +10 -1
  196. package/dist/esm-types/values/validator.d.ts.map +1 -1
  197. package/dist/esm-types/values/validators.d.ts +14 -3
  198. package/dist/esm-types/values/validators.d.ts.map +1 -1
  199. package/dist/esm-types/values/value.d.ts +18 -1
  200. package/dist/esm-types/values/value.d.ts.map +1 -1
  201. package/dist/react.bundle.js +53 -11
  202. package/dist/react.bundle.js.map +2 -2
  203. package/package.json +9 -10
  204. package/schemas/convex.schema.json +2 -1
  205. package/src/browser/sync/paginated_query_client.test.ts +209 -1
  206. package/src/browser/sync/paginated_query_client.ts +26 -9
  207. package/src/cli/codegen_templates/validator_helpers.test.ts +31 -0
  208. package/src/cli/codegen_templates/validator_helpers.ts +6 -0
  209. package/src/cli/deployment.ts +4 -1
  210. package/src/cli/deploymentCreate.test.ts +2 -2
  211. package/src/cli/deploymentCreate.ts +2 -2
  212. package/src/cli/generatedApi.ts +43 -43
  213. package/src/cli/lib/deployApi/validator.ts +1 -0
  214. package/src/cli/lib/deploymentSelection.ts +2 -2
  215. package/src/cli/lib/generateDocs.test.ts +1 -1
  216. package/src/cli/lib/generateDocs.ts +3 -3
  217. package/src/cli/lib/generatedFunctionLogsApi.ts +45 -45
  218. package/src/cli/lib/localDeployment/projectMismatch.ts +2 -2
  219. package/src/cli/lib/login.ts +33 -30
  220. package/src/cli/lib/typecheck.test.ts +71 -0
  221. package/src/cli/lib/typecheck.ts +33 -27
  222. package/src/cli/lib/usageLimits.ts +242 -0
  223. package/src/cli/usageLimits.ts +420 -0
  224. package/src/index.ts +1 -1
  225. package/src/server/audit_logging.test.ts +2 -0
  226. package/src/server/components/index.test.ts +33 -1
  227. package/src/server/components/index.ts +41 -14
  228. package/src/server/cron.test.ts +58 -0
  229. package/src/server/cron.ts +82 -21
  230. package/src/server/database.ts +15 -0
  231. package/src/server/impl/database_impl.ts +4 -1
  232. package/src/server/log.ts +4 -1
  233. package/src/server/logVars.ts +17 -1
  234. package/src/server/schema.test.ts +6 -1
  235. package/src/values/compare.ts +5 -2
  236. package/src/values/index.ts +2 -1
  237. package/src/values/size.test.ts +5 -0
  238. package/src/values/size.ts +5 -1
  239. package/src/values/validator.test.ts +16 -1
  240. package/src/values/validator.ts +13 -0
  241. package/src/values/validators.ts +29 -1
  242. package/src/values/value.test.ts +35 -0
  243. package/src/values/value.ts +56 -1
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/cli/lib/generatedFunctionLogsApi.ts"],
4
- "sourcesContent": ["/**\n * This file was auto-generated by openapi-typescript.\n * Do not make direct changes to the file.\n */\n\nexport type paths = Record<string, never>;\nexport type webhooks = Record<string, never>;\nexport interface components {\n schemas: {\n FunctionExecutionJson: {\n cachedResult: boolean;\n caller: string;\n componentPath?: string | null;\n environment: string;\n error?: string | null;\n executionId: string;\n /** Format: double */\n executionTime: number;\n /** Format: double */\n executionTimestamp: number;\n identifier: string;\n identityType: string;\n /** @enum {string} */\n kind: \"Completion\";\n logLines: components[\"schemas\"][\"Value\"][];\n occInfo?: null | components[\"schemas\"][\"OccInfoJson\"];\n parentExecutionId?: string | null;\n requestId: string;\n /** Format: double */\n returnBytes?: number | null;\n success?: null | components[\"schemas\"][\"Value\"];\n /** Format: double */\n timestamp: number;\n udfType: components[\"schemas\"][\"UdfTypeJson\"];\n usageStats: components[\"schemas\"][\"UsageStatsJson\"];\n /** Format: double */\n userExecutionTime?: number | null;\n willRetry: boolean;\n } | {\n componentPath?: string | null;\n executionId: string;\n identifier: string;\n /** @enum {string} */\n kind: \"Progress\";\n logLines: components[\"schemas\"][\"Value\"][];\n requestId: string;\n /** Format: double */\n timestamp: number;\n udfType: components[\"schemas\"][\"UdfTypeJson\"];\n };\n /** @enum {string} */\n LogLevelJson: \"DEBUG\" | \"ERROR\" | \"WARN\" | \"INFO\" | \"LOG\";\n LogLineJson: {\n componentPath?: string | null;\n isTruncated: boolean;\n level: components[\"schemas\"][\"LogLevelJson\"];\n messages: string[];\n systemMetadata?: null | components[\"schemas\"][\"SystemLogMetadataJson\"];\n /** Format: int64 */\n timestamp: number;\n udfPath?: string | null;\n };\n OccInfoJson: {\n componentPath?: string | null;\n documentId?: string | null;\n /** Format: int64 */\n retryCount?: number | null;\n tableName?: string | null;\n writeSource?: string | null;\n };\n StreamFunctionLogs: {\n /** Format: int32 */\n clientRequestCounter?: number | null;\n /** Format: double */\n cursor: number;\n sessionId?: string | null;\n };\n StreamUdfExecutionQueryArgs: {\n /** Format: double */\n cursor: number;\n };\n StreamUdfExecutionResponse: {\n entries: components[\"schemas\"][\"FunctionExecutionJson\"][];\n /** Format: double */\n newCursor: number;\n };\n SystemLogMetadataJson: {\n code: string;\n };\n /** @enum {string} */\n UdfTypeJson: \"Query\" | \"Mutation\" | \"Action\" | \"HttpAction\";\n UsageStatsJson: {\n /** Format: int64 */\n databaseIoReadBytes: number;\n /** Format: int64 */\n databaseIoWriteBytes: number;\n /** Format: int64 */\n databaseReadBytes: number;\n /** Format: int64 */\n databaseReadDocuments: number;\n /** Format: int64 */\n databaseWriteBytes: number;\n /** Format: int64 */\n memoryUsedMb: number;\n /** Format: int64 */\n networkEgressBytes: number;\n /** Format: int64 */\n storageReadBytes: number;\n /** Format: int64 */\n storageWriteBytes: number;\n /** Format: int64 */\n textIndexQueryBytes: number;\n /** Format: int64 */\n textIndexWriteQueryBytes: number;\n /** Format: int64 */\n vectorIndexReadBytes: number;\n /** Format: int64 */\n vectorIndexReadQueryBytes: number;\n /** Format: int64 */\n vectorIndexWriteBytes: number;\n /** Format: int64 */\n vectorIndexWriteQueryBytes: number;\n };\n Value: unknown;\n };\n responses: never;\n parameters: never;\n requestBodies: never;\n headers: never;\n pathItems: never;\n}\nexport type FunctionExecutionJson = components['schemas']['FunctionExecutionJson'];\nexport type LogLevelJson = components['schemas']['LogLevelJson'];\nexport type LogLineJson = components['schemas']['LogLineJson'];\nexport type OccInfoJson = components['schemas']['OccInfoJson'];\nexport type StreamFunctionLogs = components['schemas']['StreamFunctionLogs'];\nexport type StreamUdfExecutionQueryArgs = components['schemas']['StreamUdfExecutionQueryArgs'];\nexport type StreamUdfExecutionResponse = components['schemas']['StreamUdfExecutionResponse'];\nexport type SystemLogMetadataJson = components['schemas']['SystemLogMetadataJson'];\nexport type UdfTypeJson = components['schemas']['UdfTypeJson'];\nexport type UsageStatsJson = components['schemas']['UsageStatsJson'];\nexport type Value = components['schemas']['Value'];\nexport type $defs = Record<string, never>;\nexport type operations = Record<string, never>;\n"],
4
+ "sourcesContent": ["/**\n * This file was auto-generated by openapi-typescript.\n * Do not make direct changes to the file.\n */\n\nexport type paths = Record<string, never>;\nexport type webhooks = Record<string, never>;\nexport interface components {\n schemas: {\n FunctionExecutionJson: {\n udfType: components[\"schemas\"][\"UdfTypeJson\"];\n componentPath?: string | null;\n identifier: string;\n logLines: components[\"schemas\"][\"Value\"][];\n /** Format: double */\n timestamp: number;\n cachedResult: boolean;\n caller: string;\n parentExecutionId?: string | null;\n /** Format: double */\n executionTime: number;\n /** Format: double */\n userExecutionTime?: number | null;\n success?: null | components[\"schemas\"][\"Value\"];\n error?: string | null;\n requestId: string;\n executionId: string;\n usageStats: components[\"schemas\"][\"UsageStatsJson\"];\n /** Format: double */\n returnBytes?: number | null;\n occInfo?: null | components[\"schemas\"][\"OccInfoJson\"];\n willRetry: boolean;\n /** Format: double */\n executionTimestamp: number;\n identityType: string;\n environment: string;\n /** @enum {string} */\n kind: \"Completion\";\n } | {\n udfType: components[\"schemas\"][\"UdfTypeJson\"];\n componentPath?: string | null;\n identifier: string;\n /** Format: double */\n timestamp: number;\n logLines: components[\"schemas\"][\"Value\"][];\n requestId: string;\n executionId: string;\n /** @enum {string} */\n kind: \"Progress\";\n };\n /** @enum {string} */\n LogLevelJson: \"DEBUG\" | \"ERROR\" | \"WARN\" | \"INFO\" | \"LOG\";\n LogLineJson: {\n messages: string[];\n isTruncated: boolean;\n /** Format: int64 */\n timestamp: number;\n level: components[\"schemas\"][\"LogLevelJson\"];\n systemMetadata?: null | components[\"schemas\"][\"SystemLogMetadataJson\"];\n componentPath?: string | null;\n udfPath?: string | null;\n };\n OccInfoJson: {\n tableName?: string | null;\n documentId?: string | null;\n writeSource?: string | null;\n componentPath?: string | null;\n /** Format: int64 */\n retryCount?: number | null;\n };\n StreamFunctionLogs: {\n /** Format: double */\n cursor: number;\n sessionId?: string | null;\n /** Format: int32 */\n clientRequestCounter?: number | null;\n };\n StreamUdfExecutionQueryArgs: {\n /** Format: double */\n cursor: number;\n };\n StreamUdfExecutionResponse: {\n entries: components[\"schemas\"][\"FunctionExecutionJson\"][];\n /** Format: double */\n newCursor: number;\n };\n SystemLogMetadataJson: {\n code: string;\n };\n /** @enum {string} */\n UdfTypeJson: \"Query\" | \"Mutation\" | \"Action\" | \"HttpAction\";\n UsageStatsJson: {\n /** Format: int64 */\n databaseReadBytes: number;\n /** Format: int64 */\n databaseWriteBytes: number;\n /** Format: int64 */\n databaseIoReadBytes: number;\n /** Format: int64 */\n databaseIoWriteBytes: number;\n /** Format: int64 */\n databaseReadDocuments: number;\n /** Format: int64 */\n storageReadBytes: number;\n /** Format: int64 */\n storageWriteBytes: number;\n /** Format: int64 */\n vectorIndexReadBytes: number;\n /** Format: int64 */\n vectorIndexWriteBytes: number;\n /** Format: int64 */\n textIndexQueryBytes: number;\n /** Format: int64 */\n textIndexWriteQueryBytes: number;\n /** Format: int64 */\n vectorIndexReadQueryBytes: number;\n /** Format: int64 */\n vectorIndexWriteQueryBytes: number;\n /** Format: int64 */\n networkEgressBytes: number;\n /** Format: int64 */\n memoryUsedMb: number;\n };\n Value: unknown;\n };\n responses: never;\n parameters: never;\n requestBodies: never;\n headers: never;\n pathItems: never;\n}\nexport type FunctionExecutionJson = components['schemas']['FunctionExecutionJson'];\nexport type LogLevelJson = components['schemas']['LogLevelJson'];\nexport type LogLineJson = components['schemas']['LogLineJson'];\nexport type OccInfoJson = components['schemas']['OccInfoJson'];\nexport type StreamFunctionLogs = components['schemas']['StreamFunctionLogs'];\nexport type StreamUdfExecutionQueryArgs = components['schemas']['StreamUdfExecutionQueryArgs'];\nexport type StreamUdfExecutionResponse = components['schemas']['StreamUdfExecutionResponse'];\nexport type SystemLogMetadataJson = components['schemas']['SystemLogMetadataJson'];\nexport type UdfTypeJson = components['schemas']['UdfTypeJson'];\nexport type UsageStatsJson = components['schemas']['UsageStatsJson'];\nexport type Value = components['schemas']['Value'];\nexport type $defs = Record<string, never>;\nexport type operations = Record<string, never>;\n"],
5
5
  "mappings": ";;;;;;;;;;;;;;AAAA;AAAA;",
6
6
  "names": []
7
7
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../src/cli/lib/localDeployment/projectMismatch.ts"],
4
- "sourcesContent": ["import { PlatformProjectDetails } from \"@convex-dev/platform/managementApi\";\nimport { Context } from \"../../../bundler/context.js\";\nimport { logVerbose } from \"../../../bundler/log.js\";\nimport {\n DeploymentSelection,\n getProjectDetails,\n} from \"../deploymentSelection.js\";\nimport { ParsedDeploymentSelector } from \"../deploymentSelector.js\";\nimport { typedPlatformClient } from \"../utils/utils.js\";\nimport { bigBrainPause } from \"./bigBrain.js\";\nimport { LocalDeploymentConfig } from \"./filePaths.js\";\n\n/**\n * Returns the cloud project the user is targeting with a `[team:project:]local`\n * selector, or `null` if the project context can't be determined (e.g.\n * anonymous mode, no current project).\n */\nexport async function targetProjectForLocalSelector(\n ctx: Context,\n parsed: ParsedDeploymentSelector,\n currentSelection: DeploymentSelection,\n): Promise<PlatformProjectDetails | null> {\n switch (parsed.kind) {\n case \"inTeamProject\":\n return await getProjectDetails(ctx, {\n kind: \"teamAndProjectSlugs\",\n teamSlug: parsed.teamSlug,\n projectSlug: parsed.projectSlug,\n });\n case \"inCurrentProject\":\n if (currentSelection.kind !== \"deploymentWithinProject\") return null;\n return await getProjectDetails(ctx, currentSelection.targetProject);\n case \"inProject\": {\n if (currentSelection.kind !== \"deploymentWithinProject\") return null;\n // For `project:local` we keep the team from the current cloud project\n // and switch only the project slug.\n const current = await getProjectDetails(\n ctx,\n currentSelection.targetProject,\n );\n return await getProjectDetails(ctx, {\n kind: \"teamAndProjectSlugs\",\n teamSlug: current.teamSlug,\n projectSlug: parsed.projectSlug,\n });\n }\n default:\n return null;\n }\n}\n\n/**\n * Compares the cloud project association stored in `config.json` against the\n * cloud project the user is asking about. Returns `\"skip\"` when the on-disk\n * config has no `cloudProjectId` (older configs, anonymous mode).\n */\nexport function checkLocalConfigMatchesProject(\n _ctx: Context,\n localConfig: LocalDeploymentConfig,\n target: { id: number },\n): \"match\" | \"mismatch\" | \"skip\" {\n if (localConfig.cloudProjectId === undefined) {\n return \"skip\";\n }\n return localConfig.cloudProjectId === target.id ? \"match\" : \"mismatch\";\n}\n\n/**\n * Best-effort lookup of a cloud project's team/project slugs by id. Returns\n * `null` if the project can't be resolved (e.g. it was deleted from the\n * dashboard).\n */\nexport async function getCloudProjectSlugsBestEffort(\n ctx: Context,\n cloudProjectId: number,\n): Promise<{ teamSlug: string; slug: string } | null> {\n try {\n const result = await typedPlatformClient(ctx, { throw: true }).GET(\n \"/projects/{project_id}\",\n {\n params: { path: { project_id: cloudProjectId } },\n },\n );\n const project = result.data;\n if (!project) return null;\n return { teamSlug: project.teamSlug, slug: project.slug };\n } catch (e) {\n logVerbose(\n `Failed to resolve cloud project ${cloudProjectId}: ${e as any}`,\n );\n return null;\n }\n}\n\n/**\n * Best-effort call to `local_deployment/pause` for the local deployment\n * associated with the given cloud project. Swallows any errors.\n */\nexport async function pauseLocalDeploymentBestEffort(\n ctx: Context,\n project: { teamSlug: string; slug: string } | null,\n): Promise<void> {\n if (project === null) return;\n try {\n await bigBrainPause(ctx, {\n teamSlug: project.teamSlug,\n projectSlug: project.slug,\n });\n } catch (e) {\n logVerbose(`Failed to pause local deployment: ${e as any}`);\n }\n}\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAEA,iBAA2B;AAC3B,iCAGO;AAEP,mBAAoC;AACpC,sBAA8B;AAQ9B,eAAsB,8BACpB,KACA,QACA,kBACwC;AACxC,UAAQ,OAAO,MAAM;AAAA,IACnB,KAAK;AACH,aAAO,UAAM,8CAAkB,KAAK;AAAA,QAClC,MAAM;AAAA,QACN,UAAU,OAAO;AAAA,QACjB,aAAa,OAAO;AAAA,MACtB,CAAC;AAAA,IACH,KAAK;AACH,UAAI,iBAAiB,SAAS,0BAA2B,QAAO;AAChE,aAAO,UAAM,8CAAkB,KAAK,iBAAiB,aAAa;AAAA,IACpE,KAAK,aAAa;AAChB,UAAI,iBAAiB,SAAS,0BAA2B,QAAO;AAGhE,YAAM,UAAU,UAAM;AAAA,QACpB;AAAA,QACA,iBAAiB;AAAA,MACnB;AACA,aAAO,UAAM,8CAAkB,KAAK;AAAA,QAClC,MAAM;AAAA,QACN,UAAU,QAAQ;AAAA,QAClB,aAAa,OAAO;AAAA,MACtB,CAAC;AAAA,IACH;AAAA,IACA;AACE,aAAO;AAAA,EACX;AACF;AAOO,SAAS,+BACd,MACA,aACA,QAC+B;AAC/B,MAAI,YAAY,mBAAmB,QAAW;AAC5C,WAAO;AAAA,EACT;AACA,SAAO,YAAY,mBAAmB,OAAO,KAAK,UAAU;AAC9D;AAOA,eAAsB,+BACpB,KACA,gBACoD;AACpD,MAAI;AACF,UAAM,SAAS,UAAM,kCAAoB,KAAK,EAAE,OAAO,KAAK,CAAC,EAAE;AAAA,MAC7D;AAAA,MACA;AAAA,QACE,QAAQ,EAAE,MAAM,EAAE,YAAY,eAAe,EAAE;AAAA,MACjD;AAAA,IACF;AACA,UAAM,UAAU,OAAO;AACvB,QAAI,CAAC,QAAS,QAAO;AACrB,WAAO,EAAE,UAAU,QAAQ,UAAU,MAAM,QAAQ,KAAK;AAAA,EAC1D,SAAS,GAAG;AACV;AAAA,MACE,mCAAmC,cAAc,KAAK,CAAQ;AAAA,IAChE;AACA,WAAO;AAAA,EACT;AACF;AAMA,eAAsB,+BACpB,KACA,SACe;AACf,MAAI,YAAY,KAAM;AACtB,MAAI;AACF,cAAM,+BAAc,KAAK;AAAA,MACvB,UAAU,QAAQ;AAAA,MAClB,aAAa,QAAQ;AAAA,IACvB,CAAC;AAAA,EACH,SAAS,GAAG;AACV,+BAAW,qCAAqC,CAAQ,EAAE;AAAA,EAC5D;AACF;",
4
+ "sourcesContent": ["import { ProjectResponse } from \"@convex-dev/platform/managementApi\";\nimport { Context } from \"../../../bundler/context.js\";\nimport { logVerbose } from \"../../../bundler/log.js\";\nimport {\n DeploymentSelection,\n getProjectDetails,\n} from \"../deploymentSelection.js\";\nimport { ParsedDeploymentSelector } from \"../deploymentSelector.js\";\nimport { typedPlatformClient } from \"../utils/utils.js\";\nimport { bigBrainPause } from \"./bigBrain.js\";\nimport { LocalDeploymentConfig } from \"./filePaths.js\";\n\n/**\n * Returns the cloud project the user is targeting with a `[team:project:]local`\n * selector, or `null` if the project context can't be determined (e.g.\n * anonymous mode, no current project).\n */\nexport async function targetProjectForLocalSelector(\n ctx: Context,\n parsed: ParsedDeploymentSelector,\n currentSelection: DeploymentSelection,\n): Promise<ProjectResponse | null> {\n switch (parsed.kind) {\n case \"inTeamProject\":\n return await getProjectDetails(ctx, {\n kind: \"teamAndProjectSlugs\",\n teamSlug: parsed.teamSlug,\n projectSlug: parsed.projectSlug,\n });\n case \"inCurrentProject\":\n if (currentSelection.kind !== \"deploymentWithinProject\") return null;\n return await getProjectDetails(ctx, currentSelection.targetProject);\n case \"inProject\": {\n if (currentSelection.kind !== \"deploymentWithinProject\") return null;\n // For `project:local` we keep the team from the current cloud project\n // and switch only the project slug.\n const current = await getProjectDetails(\n ctx,\n currentSelection.targetProject,\n );\n return await getProjectDetails(ctx, {\n kind: \"teamAndProjectSlugs\",\n teamSlug: current.teamSlug,\n projectSlug: parsed.projectSlug,\n });\n }\n default:\n return null;\n }\n}\n\n/**\n * Compares the cloud project association stored in `config.json` against the\n * cloud project the user is asking about. Returns `\"skip\"` when the on-disk\n * config has no `cloudProjectId` (older configs, anonymous mode).\n */\nexport function checkLocalConfigMatchesProject(\n _ctx: Context,\n localConfig: LocalDeploymentConfig,\n target: { id: number },\n): \"match\" | \"mismatch\" | \"skip\" {\n if (localConfig.cloudProjectId === undefined) {\n return \"skip\";\n }\n return localConfig.cloudProjectId === target.id ? \"match\" : \"mismatch\";\n}\n\n/**\n * Best-effort lookup of a cloud project's team/project slugs by id. Returns\n * `null` if the project can't be resolved (e.g. it was deleted from the\n * dashboard).\n */\nexport async function getCloudProjectSlugsBestEffort(\n ctx: Context,\n cloudProjectId: number,\n): Promise<{ teamSlug: string; slug: string } | null> {\n try {\n const result = await typedPlatformClient(ctx, { throw: true }).GET(\n \"/projects/{project_id}\",\n {\n params: { path: { project_id: cloudProjectId } },\n },\n );\n const project = result.data;\n if (!project) return null;\n return { teamSlug: project.teamSlug, slug: project.slug };\n } catch (e) {\n logVerbose(\n `Failed to resolve cloud project ${cloudProjectId}: ${e as any}`,\n );\n return null;\n }\n}\n\n/**\n * Best-effort call to `local_deployment/pause` for the local deployment\n * associated with the given cloud project. Swallows any errors.\n */\nexport async function pauseLocalDeploymentBestEffort(\n ctx: Context,\n project: { teamSlug: string; slug: string } | null,\n): Promise<void> {\n if (project === null) return;\n try {\n await bigBrainPause(ctx, {\n teamSlug: project.teamSlug,\n projectSlug: project.slug,\n });\n } catch (e) {\n logVerbose(`Failed to pause local deployment: ${e as any}`);\n }\n}\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAEA,iBAA2B;AAC3B,iCAGO;AAEP,mBAAoC;AACpC,sBAA8B;AAQ9B,eAAsB,8BACpB,KACA,QACA,kBACiC;AACjC,UAAQ,OAAO,MAAM;AAAA,IACnB,KAAK;AACH,aAAO,UAAM,8CAAkB,KAAK;AAAA,QAClC,MAAM;AAAA,QACN,UAAU,OAAO;AAAA,QACjB,aAAa,OAAO;AAAA,MACtB,CAAC;AAAA,IACH,KAAK;AACH,UAAI,iBAAiB,SAAS,0BAA2B,QAAO;AAChE,aAAO,UAAM,8CAAkB,KAAK,iBAAiB,aAAa;AAAA,IACpE,KAAK,aAAa;AAChB,UAAI,iBAAiB,SAAS,0BAA2B,QAAO;AAGhE,YAAM,UAAU,UAAM;AAAA,QACpB;AAAA,QACA,iBAAiB;AAAA,MACnB;AACA,aAAO,UAAM,8CAAkB,KAAK;AAAA,QAClC,MAAM;AAAA,QACN,UAAU,QAAQ;AAAA,QAClB,aAAa,OAAO;AAAA,MACtB,CAAC;AAAA,IACH;AAAA,IACA;AACE,aAAO;AAAA,EACX;AACF;AAOO,SAAS,+BACd,MACA,aACA,QAC+B;AAC/B,MAAI,YAAY,mBAAmB,QAAW;AAC5C,WAAO;AAAA,EACT;AACA,SAAO,YAAY,mBAAmB,OAAO,KAAK,UAAU;AAC9D;AAOA,eAAsB,+BACpB,KACA,gBACoD;AACpD,MAAI;AACF,UAAM,SAAS,UAAM,kCAAoB,KAAK,EAAE,OAAO,KAAK,CAAC,EAAE;AAAA,MAC7D;AAAA,MACA;AAAA,QACE,QAAQ,EAAE,MAAM,EAAE,YAAY,eAAe,EAAE;AAAA,MACjD;AAAA,IACF;AACA,UAAM,UAAU,OAAO;AACvB,QAAI,CAAC,QAAS,QAAO;AACrB,WAAO,EAAE,UAAU,QAAQ,UAAU,MAAM,QAAQ,KAAK;AAAA,EAC1D,SAAS,GAAG;AACV;AAAA,MACE,mCAAmC,cAAc,KAAK,CAAQ;AAAA,IAChE;AACA,WAAO;AAAA,EACT;AACF;AAMA,eAAsB,+BACpB,KACA,SACe;AACf,MAAI,YAAY,KAAM;AACtB,MAAI;AACF,cAAM,+BAAc,KAAK;AAAA,MACvB,UAAU,QAAQ;AAAA,MAClB,aAAa,QAAQ;AAAA,IACvB,CAAC;AAAA,EACH,SAAS,GAAG;AACV,+BAAW,qCAAqC,CAAQ,EAAE;AAAA,EAC5D;AACF;",
6
6
  "names": []
7
7
  }
@@ -234,38 +234,34 @@ async function performLogin(ctx, {
234
234
  });
235
235
  }
236
236
  const issuer = overrideAuthUrl ?? "https://auth.convex.dev";
237
- let authIssuer;
237
+ const clientId = overrideAuthClient ?? "HFtA247jp9iNs08NTLIB7JsNPMmRIyfi";
238
238
  let accessToken;
239
- if (loginFlow === "paste" || loginFlow === "auto" && (0, import_utils.isWebContainer)()) {
239
+ if (overrideAccessToken) {
240
+ accessToken = overrideAccessToken;
241
+ } else if (overrideAuthUsername && overrideAuthPassword) {
242
+ accessToken = await performPasswordAuthentication(
243
+ ctx,
244
+ clientId,
245
+ overrideAuthUsername,
246
+ overrideAuthPassword
247
+ );
248
+ } else if (loginFlow === "paste" || loginFlow === "auto" && (0, import_utils.isWebContainer)()) {
240
249
  accessToken = await (0, import_prompts.promptString)(ctx, {
241
250
  message: "Open https://dashboard.convex.dev/auth, log in and paste the token here:"
242
251
  });
243
252
  } else {
253
+ let authIssuer;
244
254
  try {
245
255
  authIssuer = await import_openid_client2.Issuer.discover(issuer);
246
256
  } catch {
247
- accessToken = await (0, import_prompts.promptString)(ctx, {
248
- message: "Open https://dashboard.convex.dev/auth, log in and paste the token here:"
249
- });
257
+ authIssuer = void 0;
250
258
  }
251
- }
252
- if (authIssuer) {
253
- const clientId = overrideAuthClient ?? "HFtA247jp9iNs08NTLIB7JsNPMmRIyfi";
254
- const authClient = new authIssuer.Client({
255
- client_id: clientId,
256
- token_endpoint_auth_method: "none",
257
- id_token_signed_response_alg: "RS256"
258
- });
259
- if (overrideAccessToken) {
260
- accessToken = overrideAccessToken;
261
- } else if (overrideAuthUsername && overrideAuthPassword) {
262
- accessToken = await performPasswordAuthentication(
263
- ctx,
264
- clientId,
265
- overrideAuthUsername,
266
- overrideAuthPassword
267
- );
268
- } else {
259
+ if (authIssuer) {
260
+ const authClient = new authIssuer.Client({
261
+ client_id: clientId,
262
+ token_endpoint_auth_method: "none",
263
+ id_token_signed_response_alg: "RS256"
264
+ });
269
265
  accessToken = await performDeviceAuthorization(
270
266
  ctx,
271
267
  authClient,
@@ -273,6 +269,10 @@ async function performLogin(ctx, {
273
269
  vercel,
274
270
  vercelOverride
275
271
  );
272
+ } else {
273
+ accessToken = await (0, import_prompts.promptString)(ctx, {
274
+ message: "Open https://dashboard.convex.dev/auth, log in and paste the token here:"
275
+ });
276
276
  }
277
277
  }
278
278
  if (dumpAccessToken) {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/cli/lib/login.ts"],
4
- "sourcesContent": ["import { errors, BaseClient, custom } from \"openid-client\";\nimport {\n bigBrainAPI,\n bigBrainFetch,\n logAndHandleFetchError,\n throwingFetch,\n isWebContainer,\n typedPlatformClient,\n} from \"./utils/utils.js\";\nimport open from \"open\";\nimport { chalkStderr } from \"chalk\";\nimport { provisionHost } from \"./config.js\";\nimport { version } from \"../version.js\";\nimport { Context } from \"../../bundler/context.js\";\nimport {\n changeSpinner,\n logError,\n logFailure,\n logFinishedStep,\n logMessage,\n logOutput,\n logVerbose,\n showSpinner,\n} from \"../../bundler/log.js\";\nimport { Issuer } from \"openid-client\";\nimport { hostname } from \"os\";\nimport { execSync } from \"child_process\";\nimport { promptString, promptYesNo } from \"./utils/prompts.js\";\nimport {\n formatPathForPrinting,\n globalConfigPath,\n modifyGlobalConfig,\n} from \"./utils/globalConfig.js\";\nimport { updateBigBrainAuthAfterLogin } from \"./deploymentSelection.js\";\n\n// Per https://github.com/panva/node-openid-client/tree/main/docs#customizing\ncustom.setHttpOptionsDefaults({\n timeout: parseInt(process.env.OPENID_CLIENT_TIMEOUT || \"10000\"),\n});\n\nexport async function checkAuthorization(\n ctx: Context,\n acceptOptIns: boolean,\n): Promise<boolean> {\n const header = ctx.bigBrainAuth()?.header ?? null;\n if (header === null) {\n return false;\n }\n try {\n const resp = await fetch(`${provisionHost}/api/authorize`, {\n method: \"HEAD\",\n headers: {\n Authorization: header,\n \"Convex-Client\": `npm-cli-${version}`,\n },\n });\n // Don't throw an error if this request returns a non-200 status.\n // Big Brain responds with a variety of error codes -- 401 if the token is correctly-formed but not valid, and either 400 or 500 if the token is ill-formed.\n // We only care if this check returns a 200 code (so we can skip logging in again) -- any other errors should be silently skipped and we'll run the whole login flow again.\n if (resp.status !== 200) {\n return false;\n }\n } catch (e: any) {\n // This `catch` block should only be hit if a network error was encountered\n logError(\n `Unexpected error when authorizing - are you connected to the internet?`,\n );\n return await logAndHandleFetchError(ctx, e);\n }\n\n // Check that we have optin as well\n const shouldContinue = await optins(ctx, acceptOptIns);\n if (!shouldContinue) {\n return await ctx.crash({\n exitCode: 1,\n errorType: \"fatal\",\n printedMessage: null,\n });\n }\n return true;\n}\n\nasync function performDeviceAuthorization(\n ctx: Context,\n authClient: BaseClient,\n shouldOpen: boolean,\n vercel?: boolean,\n vercelOverride?: string,\n): Promise<string> {\n // Device authorization flow follows this guide: https://github.com/auth0/auth0-device-flow-cli-sample/blob/9f0f3b76a6cd56ea8d99e76769187ea5102d519d/cli.js\n // License: MIT License\n // Copyright (c) 2019 Auth0 Samples\n /*\n The MIT License (MIT)\n\n Copyright (c) 2019 Auth0 Samples\n\n Permission is hereby granted, free of charge, to any person obtaining a copy\n of this software and associated documentation files (the \"Software\"), to deal\n in the Software without restriction, including without limitation the rights\n to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n copies of the Software, and to permit persons to whom the Software is\n furnished to do so, subject to the following conditions:\n\n The above copyright notice and this permission notice shall be included in all\n copies or substantial portions of the Software.\n\n THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n SOFTWARE.\n */\n\n // Device Authorization Request - https://tools.ietf.org/html/rfc8628#section-3.1\n // Get authentication URL\n let handle;\n try {\n handle = await authClient.deviceAuthorization();\n } catch {\n // We couldn't get verification URL from the auth provider, proceed with manual auth\n return promptString(ctx, {\n message:\n \"Open https://dashboard.convex.dev/auth, log in and paste the token here:\",\n });\n }\n\n // Device Authorization Response - https://tools.ietf.org/html/rfc8628#section-3.2\n // Open authentication URL\n const { verification_uri_complete, user_code, expires_in } = handle;\n\n // Construct Vercel URL if --vercel flag is used\n const urlToOpen = vercel\n ? `https://vercel.com/sso/integrations/${vercelOverride || \"convex\"}?url=${verification_uri_complete}`\n : verification_uri_complete;\n\n logMessage(\n `Visit ${urlToOpen} to finish logging in.\\n` +\n `You should see the following code which expires in ${\n expires_in % 60 === 0\n ? `${expires_in / 60} minutes`\n : `${expires_in} seconds`\n }: ${user_code}`,\n );\n if (shouldOpen) {\n shouldOpen = await promptYesNo(ctx, {\n message: `Open the browser?`,\n default: true,\n });\n }\n\n if (shouldOpen) {\n showSpinner(`Opening ${urlToOpen} in your browser to log in...\\n`);\n try {\n const p = await open(urlToOpen);\n p.once(\"error\", () => {\n changeSpinner(`Manually open ${urlToOpen} in your browser to log in.`);\n });\n changeSpinner(\"Waiting for the confirmation...\");\n } catch {\n logError(chalkStderr.red(`Unable to open browser.`));\n changeSpinner(`Manually open ${urlToOpen} in your browser to log in.`);\n }\n } else {\n showSpinner(`Open ${urlToOpen} in your browser to log in.`);\n }\n\n // Device Access Token Request - https://tools.ietf.org/html/rfc8628#section-3.4\n // Device Access Token Response - https://tools.ietf.org/html/rfc8628#section-3.5\n try {\n const tokens = await handle.poll();\n if (typeof tokens.access_token === \"string\") {\n return tokens.access_token;\n } else {\n // Unexpected error\n // eslint-disable-next-line no-restricted-syntax\n throw Error(\"Access token is missing\");\n }\n } catch (err: any) {\n switch (err.error) {\n case \"access_denied\": // end-user declined the device confirmation prompt, consent or rules failed\n return await ctx.crash({\n exitCode: 1,\n errorType: \"fatal\",\n printedMessage: \"Access denied.\",\n errForSentry: err,\n });\n case \"expired_token\": // end-user did not complete the interaction in time\n return await ctx.crash({\n exitCode: 1,\n errorType: \"fatal\",\n printedMessage: \"Device flow expired.\",\n errForSentry: err,\n });\n default: {\n const message =\n err instanceof errors.OPError\n ? `Error = ${err.error}; error_description = ${err.error_description}`\n : `Login failed with error: ${err}`;\n return await ctx.crash({\n exitCode: 1,\n errorType: \"fatal\",\n printedMessage: message,\n errForSentry: err,\n });\n }\n }\n }\n}\n\nasync function performPasswordAuthentication(\n ctx: Context,\n clientId: string,\n username: string,\n password: string,\n): Promise<string> {\n if (!process.env.WORKOS_API_SECRET) {\n return await ctx.crash({\n exitCode: 1,\n errorType: \"fatal\",\n printedMessage: \"WORKOS_API_SECRET environment variable is not set\",\n });\n }\n\n // Unfortunately, `openid-client` doesn't support the resource owner password credentials flow so we need to manually send the requests.\n const options: Parameters<typeof throwingFetch>[1] = {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n grant_type: \"password\",\n email: username,\n password: password,\n client_id: clientId,\n client_secret: process.env.WORKOS_API_SECRET,\n }),\n };\n\n try {\n const response = await throwingFetch(\n \"https://apiauth.convex.dev/user_management/authenticate\",\n options,\n );\n const data = await response.json();\n if (typeof data.access_token === \"string\") {\n return data.access_token;\n } else {\n // Unexpected error\n // eslint-disable-next-line no-restricted-syntax\n throw Error(\"Access token is missing\");\n }\n } catch (err: any) {\n logFailure(`Password flow failed: ${err}`);\n if (err.response) {\n logError(chalkStderr.red(`${JSON.stringify(err.response.data)}`));\n }\n return await ctx.crash({\n exitCode: 1,\n errorType: \"fatal\",\n errForSentry: err,\n printedMessage: null,\n });\n }\n}\n\nexport async function performLogin(\n ctx: Context,\n {\n overrideAuthUrl,\n overrideAuthClient,\n overrideAuthUsername,\n overrideAuthPassword,\n overrideAccessToken,\n loginFlow,\n open,\n acceptOptIns,\n dumpAccessToken,\n deviceName: deviceNameOverride,\n anonymousId,\n vercel,\n vercelOverride,\n }: {\n overrideAuthUrl?: string | undefined;\n overrideAuthClient?: string | undefined;\n overrideAuthUsername?: string | undefined;\n overrideAuthPassword?: string | undefined;\n overrideAccessToken?: string | undefined;\n loginFlow?: \"auto\" | \"paste\" | \"poll\" | undefined;\n // default `true`\n open?: boolean | undefined;\n // default `false`\n acceptOptIns?: boolean | undefined;\n dumpAccessToken?: boolean | undefined;\n deviceName?: string | undefined;\n anonymousId?: string | undefined;\n vercel?: boolean | undefined;\n vercelOverride?: string | undefined;\n } = {},\n) {\n loginFlow = loginFlow || \"auto\";\n // Get access token from big-brain\n // Default the device name to the hostname, but allow the user to change this if the terminal is interactive.\n // On Macs, the `hostname()` may be a weirdly-truncated form of the computer name. Attempt to read the \"real\" name before falling back to hostname.\n let deviceName = deviceNameOverride ?? \"\";\n if (!deviceName && process.platform === \"darwin\") {\n try {\n deviceName = execSync(\"scutil --get ComputerName\").toString().trim();\n } catch {\n // Just fall back to the hostname default below.\n }\n }\n if (!deviceName) {\n deviceName = hostname();\n }\n if (!deviceNameOverride) {\n logMessage(\n chalkStderr.bold(\n `Welcome to developing with Convex, let's get you logged in.`,\n ),\n );\n deviceName = await promptString(ctx, {\n message: \"Device name:\",\n default: deviceName,\n });\n }\n\n const issuer = overrideAuthUrl ?? \"https://auth.convex.dev\";\n let authIssuer;\n let accessToken: string;\n\n if (loginFlow === \"paste\" || (loginFlow === \"auto\" && isWebContainer())) {\n accessToken = await promptString(ctx, {\n message:\n \"Open https://dashboard.convex.dev/auth, log in and paste the token here:\",\n });\n } else {\n try {\n authIssuer = await Issuer.discover(issuer);\n } catch {\n // Couldn't contact https://auth.convex.dev/.well-known/openid-configuration,\n // proceed with manual auth.\n accessToken = await promptString(ctx, {\n message:\n \"Open https://dashboard.convex.dev/auth, log in and paste the token here:\",\n });\n }\n }\n\n // typical path\n if (authIssuer) {\n const clientId = overrideAuthClient ?? \"HFtA247jp9iNs08NTLIB7JsNPMmRIyfi\";\n const authClient = new authIssuer.Client({\n client_id: clientId,\n token_endpoint_auth_method: \"none\",\n id_token_signed_response_alg: \"RS256\",\n });\n\n if (overrideAccessToken) {\n accessToken = overrideAccessToken;\n } else if (overrideAuthUsername && overrideAuthPassword) {\n accessToken = await performPasswordAuthentication(\n ctx,\n clientId,\n overrideAuthUsername,\n overrideAuthPassword,\n );\n } else {\n accessToken = await performDeviceAuthorization(\n ctx,\n authClient,\n open ?? true,\n vercel,\n vercelOverride,\n );\n }\n }\n\n if (dumpAccessToken) {\n logOutput(`${accessToken!}`);\n return await ctx.crash({\n exitCode: 0,\n errorType: \"fatal\",\n printedMessage: null,\n });\n }\n\n // Exchange the WorkOS access token for a Convex personal access token.\n ctx._updateBigBrainAuth({\n accessToken: accessToken!,\n kind: \"accessToken\",\n header: `Bearer ${accessToken!}`,\n });\n const response = await typedPlatformClient(ctx).POST(\n \"/create_personal_access_token\",\n {\n // `anonymousId` links a prior anonymous session to this account. It's\n // intentionally absent from the generated platform API types,\n // so cast to pass it through.\n body: { name: deviceName, anonymousId } as { name: string },\n },\n );\n const newAccessToken = response.data!.accessToken;\n const globalConfig = { accessToken: newAccessToken };\n try {\n await modifyGlobalConfig(ctx, globalConfig);\n const path = globalConfigPath();\n logFinishedStep(`Saved credentials to ${formatPathForPrinting(path)}`);\n } catch (err: unknown) {\n return await ctx.crash({\n exitCode: 1,\n errorType: \"invalid filesystem data\",\n errForSentry: err,\n printedMessage: null,\n });\n }\n\n logVerbose(`performLogin: updating big brain auth after login`);\n await updateBigBrainAuthAfterLogin(ctx, newAccessToken);\n\n logVerbose(`performLogin: checking opt ins, acceptOptIns: ${acceptOptIns}`);\n // Do opt in to TOS and Privacy Policy stuff\n const shouldContinue = await optins(ctx, acceptOptIns ?? false);\n if (!shouldContinue) {\n return await ctx.crash({\n exitCode: 1,\n errorType: \"fatal\",\n printedMessage: null,\n });\n }\n\n if (vercel) {\n await promptJoinVercelTeams(ctx);\n }\n}\n\ntype PotentialVercelTeam = {\n teamId: number;\n teamName: string;\n teamSlug: string;\n planId: string;\n planName: string;\n pricingNotice: string | null;\n};\n\n// After `--vercel` login, surface any Vercel-marketplace teams the user has\n// access to but isn't yet a member of, and prompt to join each.\nasync function promptJoinVercelTeams(ctx: Context): Promise<void> {\n const fetch = bigBrainFetch(ctx);\n let teams: PotentialVercelTeam[];\n try {\n const res = await fetch(\n new URL(\"vercel/potential_teams\", `${provisionHost}/`),\n );\n if (!res.ok) {\n logVerbose(\n `vercel/potential_teams returned ${res.status}; skipping team-join prompt`,\n );\n return;\n }\n teams = await res.json();\n } catch (err) {\n logVerbose(`Failed to fetch potential Vercel teams: ${String(err)}`);\n return;\n }\n if (teams.length === 0) return;\n\n for (const [index, team] of teams.entries()) {\n const displayName = team.teamName.replace(/ \\(Vercel\\)$/, \"\");\n const counter = teams.length > 1 ? `[${index + 1}/${teams.length}] ` : \"\";\n const lines = [\n chalkStderr.bold(`${counter}You've been invited to join ${displayName}`) +\n ` (${team.planName}) through the Vercel marketplace.`,\n ];\n if (team.pricingNotice) {\n lines.push(chalkStderr.yellow(team.pricingNotice));\n }\n lines.push(`Join \"${displayName}\"?`);\n const join = await promptYesNo(ctx, {\n message: `${lines.join(\"\\n\")}`,\n default: true,\n });\n if (!join) continue;\n try {\n await fetch(\n new URL(\n `vercel/potential_teams/${team.teamId}/join`,\n `${provisionHost}/`,\n ),\n { method: \"POST\" },\n );\n logFinishedStep(`Joined ${displayName}`);\n } catch (err) {\n logFailure(`Failed to join ${displayName}: ${String(err)}`);\n }\n }\n}\n\n/// There are fields like version, but we keep them opaque\ntype OptIn = Record<string, unknown>;\n\ntype OptInToAccept = {\n optIn: OptIn;\n message: string;\n};\n\ntype AcceptOptInsArgs = {\n optInsAccepted: OptIn[];\n};\n\n// Returns whether we can proceed or not.\nasync function optins(ctx: Context, acceptOptIns: boolean): Promise<boolean> {\n const bbAuth = ctx.bigBrainAuth();\n if (bbAuth === null) {\n // This should never happen, but if we're not even logged in, we can't proceed.\n return false;\n }\n switch (bbAuth.kind) {\n case \"accessToken\":\n break;\n case \"deploymentKey\":\n case \"projectKey\":\n case \"previewDeployKey\":\n // If we have a key configured as auth, we do not need to check opt ins.\n return true;\n default: {\n bbAuth satisfies never;\n return await ctx.crash({\n exitCode: 1,\n errorType: \"fatal\",\n errForSentry: `Unexpected auth kind ${(bbAuth as any).kind}`,\n printedMessage: \"Hit an unexpected error while logging in.\",\n });\n }\n }\n const data = await bigBrainAPI({\n ctx,\n method: \"POST\",\n path: \"check_opt_ins\",\n });\n if (data.optInsToAccept.length === 0) {\n return true;\n }\n for (const optInToAccept of data.optInsToAccept) {\n const confirmed =\n acceptOptIns ||\n (await promptYesNo(ctx, {\n message: optInToAccept.message,\n }));\n if (!confirmed) {\n logFailure(\"Please accept the Terms of Service to use Convex.\");\n return Promise.resolve(false);\n }\n }\n\n const optInsAccepted = data.optInsToAccept.map((o: OptInToAccept) => o.optIn);\n const args: AcceptOptInsArgs = { optInsAccepted };\n await bigBrainAPI({\n ctx,\n method: \"POST\",\n path: \"accept_opt_ins\",\n data: args,\n });\n return true;\n}\n\nexport async function ensureLoggedIn(\n ctx: Context,\n options?: {\n message?: string | undefined;\n overrideAuthUrl?: string | undefined;\n overrideAuthClient?: string | undefined;\n overrideAuthUsername?: string | undefined;\n overrideAuthPassword?: string | undefined;\n },\n) {\n const isLoggedIn = await checkAuthorization(ctx, false);\n if (!isLoggedIn) {\n if (options?.message) {\n logMessage(options.message);\n }\n await performLogin(ctx, {\n acceptOptIns: false,\n overrideAuthUrl: options?.overrideAuthUrl,\n overrideAuthClient: options?.overrideAuthClient,\n overrideAuthUsername: options?.overrideAuthUsername,\n overrideAuthPassword: options?.overrideAuthPassword,\n });\n }\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { errors, BaseClient, custom } from \"openid-client\";\nimport {\n bigBrainAPI,\n bigBrainFetch,\n logAndHandleFetchError,\n throwingFetch,\n isWebContainer,\n typedPlatformClient,\n} from \"./utils/utils.js\";\nimport open from \"open\";\nimport { chalkStderr } from \"chalk\";\nimport { provisionHost } from \"./config.js\";\nimport { version } from \"../version.js\";\nimport { Context } from \"../../bundler/context.js\";\nimport {\n changeSpinner,\n logError,\n logFailure,\n logFinishedStep,\n logMessage,\n logOutput,\n logVerbose,\n showSpinner,\n} from \"../../bundler/log.js\";\nimport { Issuer } from \"openid-client\";\nimport { hostname } from \"os\";\nimport { execSync } from \"child_process\";\nimport { promptString, promptYesNo } from \"./utils/prompts.js\";\nimport {\n formatPathForPrinting,\n globalConfigPath,\n modifyGlobalConfig,\n} from \"./utils/globalConfig.js\";\nimport { updateBigBrainAuthAfterLogin } from \"./deploymentSelection.js\";\n\n// Per https://github.com/panva/node-openid-client/tree/main/docs#customizing\ncustom.setHttpOptionsDefaults({\n timeout: parseInt(process.env.OPENID_CLIENT_TIMEOUT || \"10000\"),\n});\n\nexport async function checkAuthorization(\n ctx: Context,\n acceptOptIns: boolean,\n): Promise<boolean> {\n const header = ctx.bigBrainAuth()?.header ?? null;\n if (header === null) {\n return false;\n }\n try {\n const resp = await fetch(`${provisionHost}/api/authorize`, {\n method: \"HEAD\",\n headers: {\n Authorization: header,\n \"Convex-Client\": `npm-cli-${version}`,\n },\n });\n // Don't throw an error if this request returns a non-200 status.\n // Big Brain responds with a variety of error codes -- 401 if the token is correctly-formed but not valid, and either 400 or 500 if the token is ill-formed.\n // We only care if this check returns a 200 code (so we can skip logging in again) -- any other errors should be silently skipped and we'll run the whole login flow again.\n if (resp.status !== 200) {\n return false;\n }\n } catch (e: any) {\n // This `catch` block should only be hit if a network error was encountered\n logError(\n `Unexpected error when authorizing - are you connected to the internet?`,\n );\n return await logAndHandleFetchError(ctx, e);\n }\n\n // Check that we have optin as well\n const shouldContinue = await optins(ctx, acceptOptIns);\n if (!shouldContinue) {\n return await ctx.crash({\n exitCode: 1,\n errorType: \"fatal\",\n printedMessage: null,\n });\n }\n return true;\n}\n\nasync function performDeviceAuthorization(\n ctx: Context,\n authClient: BaseClient,\n shouldOpen: boolean,\n vercel?: boolean,\n vercelOverride?: string,\n): Promise<string> {\n // Device authorization flow follows this guide: https://github.com/auth0/auth0-device-flow-cli-sample/blob/9f0f3b76a6cd56ea8d99e76769187ea5102d519d/cli.js\n // License: MIT License\n // Copyright (c) 2019 Auth0 Samples\n /*\n The MIT License (MIT)\n\n Copyright (c) 2019 Auth0 Samples\n\n Permission is hereby granted, free of charge, to any person obtaining a copy\n of this software and associated documentation files (the \"Software\"), to deal\n in the Software without restriction, including without limitation the rights\n to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n copies of the Software, and to permit persons to whom the Software is\n furnished to do so, subject to the following conditions:\n\n The above copyright notice and this permission notice shall be included in all\n copies or substantial portions of the Software.\n\n THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n SOFTWARE.\n */\n\n // Device Authorization Request - https://tools.ietf.org/html/rfc8628#section-3.1\n // Get authentication URL\n let handle;\n try {\n handle = await authClient.deviceAuthorization();\n } catch {\n // We couldn't get verification URL from the auth provider, proceed with manual auth\n return promptString(ctx, {\n message:\n \"Open https://dashboard.convex.dev/auth, log in and paste the token here:\",\n });\n }\n\n // Device Authorization Response - https://tools.ietf.org/html/rfc8628#section-3.2\n // Open authentication URL\n const { verification_uri_complete, user_code, expires_in } = handle;\n\n // Construct Vercel URL if --vercel flag is used\n const urlToOpen = vercel\n ? `https://vercel.com/sso/integrations/${vercelOverride || \"convex\"}?url=${verification_uri_complete}`\n : verification_uri_complete;\n\n logMessage(\n `Visit ${urlToOpen} to finish logging in.\\n` +\n `You should see the following code which expires in ${\n expires_in % 60 === 0\n ? `${expires_in / 60} minutes`\n : `${expires_in} seconds`\n }: ${user_code}`,\n );\n if (shouldOpen) {\n shouldOpen = await promptYesNo(ctx, {\n message: `Open the browser?`,\n default: true,\n });\n }\n\n if (shouldOpen) {\n showSpinner(`Opening ${urlToOpen} in your browser to log in...\\n`);\n try {\n const p = await open(urlToOpen);\n p.once(\"error\", () => {\n changeSpinner(`Manually open ${urlToOpen} in your browser to log in.`);\n });\n changeSpinner(\"Waiting for the confirmation...\");\n } catch {\n logError(chalkStderr.red(`Unable to open browser.`));\n changeSpinner(`Manually open ${urlToOpen} in your browser to log in.`);\n }\n } else {\n showSpinner(`Open ${urlToOpen} in your browser to log in.`);\n }\n\n // Device Access Token Request - https://tools.ietf.org/html/rfc8628#section-3.4\n // Device Access Token Response - https://tools.ietf.org/html/rfc8628#section-3.5\n try {\n const tokens = await handle.poll();\n if (typeof tokens.access_token === \"string\") {\n return tokens.access_token;\n } else {\n // Unexpected error\n // eslint-disable-next-line no-restricted-syntax\n throw Error(\"Access token is missing\");\n }\n } catch (err: any) {\n switch (err.error) {\n case \"access_denied\": // end-user declined the device confirmation prompt, consent or rules failed\n return await ctx.crash({\n exitCode: 1,\n errorType: \"fatal\",\n printedMessage: \"Access denied.\",\n errForSentry: err,\n });\n case \"expired_token\": // end-user did not complete the interaction in time\n return await ctx.crash({\n exitCode: 1,\n errorType: \"fatal\",\n printedMessage: \"Device flow expired.\",\n errForSentry: err,\n });\n default: {\n const message =\n err instanceof errors.OPError\n ? `Error = ${err.error}; error_description = ${err.error_description}`\n : `Login failed with error: ${err}`;\n return await ctx.crash({\n exitCode: 1,\n errorType: \"fatal\",\n printedMessage: message,\n errForSentry: err,\n });\n }\n }\n }\n}\n\nasync function performPasswordAuthentication(\n ctx: Context,\n clientId: string,\n username: string,\n password: string,\n): Promise<string> {\n if (!process.env.WORKOS_API_SECRET) {\n return await ctx.crash({\n exitCode: 1,\n errorType: \"fatal\",\n printedMessage: \"WORKOS_API_SECRET environment variable is not set\",\n });\n }\n\n // Unfortunately, `openid-client` doesn't support the resource owner password credentials flow so we need to manually send the requests.\n const options: Parameters<typeof throwingFetch>[1] = {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n grant_type: \"password\",\n email: username,\n password: password,\n client_id: clientId,\n client_secret: process.env.WORKOS_API_SECRET,\n }),\n };\n\n try {\n const response = await throwingFetch(\n \"https://apiauth.convex.dev/user_management/authenticate\",\n options,\n );\n const data = await response.json();\n if (typeof data.access_token === \"string\") {\n return data.access_token;\n } else {\n // Unexpected error\n // eslint-disable-next-line no-restricted-syntax\n throw Error(\"Access token is missing\");\n }\n } catch (err: any) {\n logFailure(`Password flow failed: ${err}`);\n if (err.response) {\n logError(chalkStderr.red(`${JSON.stringify(err.response.data)}`));\n }\n return await ctx.crash({\n exitCode: 1,\n errorType: \"fatal\",\n errForSentry: err,\n printedMessage: null,\n });\n }\n}\n\nexport async function performLogin(\n ctx: Context,\n {\n overrideAuthUrl,\n overrideAuthClient,\n overrideAuthUsername,\n overrideAuthPassword,\n overrideAccessToken,\n loginFlow,\n open,\n acceptOptIns,\n dumpAccessToken,\n deviceName: deviceNameOverride,\n anonymousId,\n vercel,\n vercelOverride,\n }: {\n overrideAuthUrl?: string | undefined;\n overrideAuthClient?: string | undefined;\n overrideAuthUsername?: string | undefined;\n overrideAuthPassword?: string | undefined;\n overrideAccessToken?: string | undefined;\n loginFlow?: \"auto\" | \"paste\" | \"poll\" | undefined;\n // default `true`\n open?: boolean | undefined;\n // default `false`\n acceptOptIns?: boolean | undefined;\n dumpAccessToken?: boolean | undefined;\n deviceName?: string | undefined;\n anonymousId?: string | undefined;\n vercel?: boolean | undefined;\n vercelOverride?: string | undefined;\n } = {},\n) {\n loginFlow = loginFlow || \"auto\";\n // Get access token from big-brain\n // Default the device name to the hostname, but allow the user to change this if the terminal is interactive.\n // On Macs, the `hostname()` may be a weirdly-truncated form of the computer name. Attempt to read the \"real\" name before falling back to hostname.\n let deviceName = deviceNameOverride ?? \"\";\n if (!deviceName && process.platform === \"darwin\") {\n try {\n deviceName = execSync(\"scutil --get ComputerName\").toString().trim();\n } catch {\n // Just fall back to the hostname default below.\n }\n }\n if (!deviceName) {\n deviceName = hostname();\n }\n if (!deviceNameOverride) {\n logMessage(\n chalkStderr.bold(\n `Welcome to developing with Convex, let's get you logged in.`,\n ),\n );\n deviceName = await promptString(ctx, {\n message: \"Device name:\",\n default: deviceName,\n });\n }\n\n const issuer = overrideAuthUrl ?? \"https://auth.convex.dev\";\n const clientId = overrideAuthClient ?? \"HFtA247jp9iNs08NTLIB7JsNPMmRIyfi\";\n let accessToken: string;\n\n if (overrideAccessToken) {\n // Access token was supplied directly.\n accessToken = overrideAccessToken;\n } else if (overrideAuthUsername && overrideAuthPassword) {\n // Username/Password auth\n accessToken = await performPasswordAuthentication(\n ctx,\n clientId,\n overrideAuthUsername,\n overrideAuthPassword,\n );\n } else if (\n loginFlow === \"paste\" ||\n (loginFlow === \"auto\" && isWebContainer())\n ) {\n accessToken = await promptString(ctx, {\n message:\n \"Open https://dashboard.convex.dev/auth, log in and paste the token here:\",\n });\n } else {\n // Device authorization flow. Contact OIDC issuer.\n let authIssuer;\n try {\n authIssuer = await Issuer.discover(issuer);\n } catch {\n // Couldn't contact https://auth.convex.dev/.well-known/openid-configuration,\n // proceed with manual auth.\n authIssuer = undefined;\n }\n if (authIssuer) {\n const authClient = new authIssuer.Client({\n client_id: clientId,\n token_endpoint_auth_method: \"none\",\n id_token_signed_response_alg: \"RS256\",\n });\n accessToken = await performDeviceAuthorization(\n ctx,\n authClient,\n open ?? true,\n vercel,\n vercelOverride,\n );\n } else {\n accessToken = await promptString(ctx, {\n message:\n \"Open https://dashboard.convex.dev/auth, log in and paste the token here:\",\n });\n }\n }\n\n if (dumpAccessToken) {\n logOutput(`${accessToken}`);\n return await ctx.crash({\n exitCode: 0,\n errorType: \"fatal\",\n printedMessage: null,\n });\n }\n\n // Exchange the WorkOS access token for a Convex personal access token.\n ctx._updateBigBrainAuth({\n accessToken: accessToken,\n kind: \"accessToken\",\n header: `Bearer ${accessToken}`,\n });\n const response = await typedPlatformClient(ctx).POST(\n \"/create_personal_access_token\",\n {\n // `anonymousId` links a prior anonymous session to this account. It's\n // intentionally absent from the generated platform API types,\n // so cast to pass it through.\n body: { name: deviceName, anonymousId } as { name: string },\n },\n );\n const newAccessToken = response.data!.accessToken;\n const globalConfig = { accessToken: newAccessToken };\n try {\n await modifyGlobalConfig(ctx, globalConfig);\n const path = globalConfigPath();\n logFinishedStep(`Saved credentials to ${formatPathForPrinting(path)}`);\n } catch (err: unknown) {\n return await ctx.crash({\n exitCode: 1,\n errorType: \"invalid filesystem data\",\n errForSentry: err,\n printedMessage: null,\n });\n }\n\n logVerbose(`performLogin: updating big brain auth after login`);\n await updateBigBrainAuthAfterLogin(ctx, newAccessToken);\n\n logVerbose(`performLogin: checking opt ins, acceptOptIns: ${acceptOptIns}`);\n // Do opt in to TOS and Privacy Policy stuff\n const shouldContinue = await optins(ctx, acceptOptIns ?? false);\n if (!shouldContinue) {\n return await ctx.crash({\n exitCode: 1,\n errorType: \"fatal\",\n printedMessage: null,\n });\n }\n\n if (vercel) {\n await promptJoinVercelTeams(ctx);\n }\n}\n\ntype PotentialVercelTeam = {\n teamId: number;\n teamName: string;\n teamSlug: string;\n planId: string;\n planName: string;\n pricingNotice: string | null;\n};\n\n// After `--vercel` login, surface any Vercel-marketplace teams the user has\n// access to but isn't yet a member of, and prompt to join each.\nasync function promptJoinVercelTeams(ctx: Context): Promise<void> {\n const fetch = bigBrainFetch(ctx);\n let teams: PotentialVercelTeam[];\n try {\n const res = await fetch(\n new URL(\"vercel/potential_teams\", `${provisionHost}/`),\n );\n if (!res.ok) {\n logVerbose(\n `vercel/potential_teams returned ${res.status}; skipping team-join prompt`,\n );\n return;\n }\n teams = await res.json();\n } catch (err) {\n logVerbose(`Failed to fetch potential Vercel teams: ${String(err)}`);\n return;\n }\n if (teams.length === 0) return;\n\n for (const [index, team] of teams.entries()) {\n const displayName = team.teamName.replace(/ \\(Vercel\\)$/, \"\");\n const counter = teams.length > 1 ? `[${index + 1}/${teams.length}] ` : \"\";\n const lines = [\n chalkStderr.bold(`${counter}You've been invited to join ${displayName}`) +\n ` (${team.planName}) through the Vercel marketplace.`,\n ];\n if (team.pricingNotice) {\n lines.push(chalkStderr.yellow(team.pricingNotice));\n }\n lines.push(`Join \"${displayName}\"?`);\n const join = await promptYesNo(ctx, {\n message: `${lines.join(\"\\n\")}`,\n default: true,\n });\n if (!join) continue;\n try {\n await fetch(\n new URL(\n `vercel/potential_teams/${team.teamId}/join`,\n `${provisionHost}/`,\n ),\n { method: \"POST\" },\n );\n logFinishedStep(`Joined ${displayName}`);\n } catch (err) {\n logFailure(`Failed to join ${displayName}: ${String(err)}`);\n }\n }\n}\n\n/// There are fields like version, but we keep them opaque\ntype OptIn = Record<string, unknown>;\n\ntype OptInToAccept = {\n optIn: OptIn;\n message: string;\n};\n\ntype AcceptOptInsArgs = {\n optInsAccepted: OptIn[];\n};\n\n// Returns whether we can proceed or not.\nasync function optins(ctx: Context, acceptOptIns: boolean): Promise<boolean> {\n const bbAuth = ctx.bigBrainAuth();\n if (bbAuth === null) {\n // This should never happen, but if we're not even logged in, we can't proceed.\n return false;\n }\n switch (bbAuth.kind) {\n case \"accessToken\":\n break;\n case \"deploymentKey\":\n case \"projectKey\":\n case \"previewDeployKey\":\n // If we have a key configured as auth, we do not need to check opt ins.\n return true;\n default: {\n bbAuth satisfies never;\n return await ctx.crash({\n exitCode: 1,\n errorType: \"fatal\",\n errForSentry: `Unexpected auth kind ${(bbAuth as any).kind}`,\n printedMessage: \"Hit an unexpected error while logging in.\",\n });\n }\n }\n const data = await bigBrainAPI({\n ctx,\n method: \"POST\",\n path: \"check_opt_ins\",\n });\n if (data.optInsToAccept.length === 0) {\n return true;\n }\n for (const optInToAccept of data.optInsToAccept) {\n const confirmed =\n acceptOptIns ||\n (await promptYesNo(ctx, {\n message: optInToAccept.message,\n }));\n if (!confirmed) {\n logFailure(\"Please accept the Terms of Service to use Convex.\");\n return Promise.resolve(false);\n }\n }\n\n const optInsAccepted = data.optInsToAccept.map((o: OptInToAccept) => o.optIn);\n const args: AcceptOptInsArgs = { optInsAccepted };\n await bigBrainAPI({\n ctx,\n method: \"POST\",\n path: \"accept_opt_ins\",\n data: args,\n });\n return true;\n}\n\nexport async function ensureLoggedIn(\n ctx: Context,\n options?: {\n message?: string | undefined;\n overrideAuthUrl?: string | undefined;\n overrideAuthClient?: string | undefined;\n overrideAuthUsername?: string | undefined;\n overrideAuthPassword?: string | undefined;\n },\n) {\n const isLoggedIn = await checkAuthorization(ctx, false);\n if (!isLoggedIn) {\n if (options?.message) {\n logMessage(options.message);\n }\n await performLogin(ctx, {\n acceptOptIns: false,\n overrideAuthUrl: options?.overrideAuthUrl,\n overrideAuthClient: options?.overrideAuthClient,\n overrideAuthUsername: options?.overrideAuthUsername,\n overrideAuthPassword: options?.overrideAuthPassword,\n });\n }\n}\n"],
5
+ "mappings": "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",
6
6
  "names": ["import_openid_client", "open", "fetch"]
7
7
  }
@@ -28,6 +28,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
28
28
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
29
  var typecheck_exports = {};
30
30
  __export(typecheck_exports, {
31
+ findTypeScriptCompilerPath: () => findTypeScriptCompilerPath,
31
32
  resolveTypescriptCompiler: () => resolveTypescriptCompiler,
32
33
  typeCheckFunctions: () => typeCheckFunctions,
33
34
  typeCheckFunctionsInMode: () => typeCheckFunctionsInMode
@@ -110,31 +111,7 @@ async function typeCheckFunctions(ctx, typescriptCompiler, functionsDir, handleR
110
111
  );
111
112
  }
112
113
  async function runTsc(ctx, typescriptCompiler, tscArgs, handleResult) {
113
- let compilerPath;
114
- switch (typescriptCompiler) {
115
- case "tsgo": {
116
- const tsgoPaths = ["tsgo", "tsgo.js"].map(
117
- (filename) => import_path.default.join(
118
- "node_modules",
119
- "@typescript",
120
- "native-preview",
121
- "bin",
122
- filename
123
- )
124
- );
125
- compilerPath = tsgoPaths.find((path2) => ctx.fs.exists(path2));
126
- break;
127
- }
128
- case "tsc": {
129
- const tscPath = import_path.default.join("node_modules", "typescript", "bin", "tsc");
130
- if (ctx.fs.exists(tscPath)) {
131
- compilerPath = tscPath;
132
- }
133
- break;
134
- }
135
- default:
136
- typescriptCompiler;
137
- }
114
+ const compilerPath = findTypeScriptCompilerPath(ctx.fs, typescriptCompiler);
138
115
  if (!compilerPath) {
139
116
  return handleResult("cantTypeCheck", () => {
140
117
  (0, import_log.logError)(
@@ -159,6 +136,32 @@ async function runTsc(ctx, typescriptCompiler, tscArgs, handleResult) {
159
136
  );
160
137
  }
161
138
  }
139
+ function findTypeScriptCompilerPath(fs, typescriptCompiler) {
140
+ switch (typescriptCompiler) {
141
+ case "tsgo": {
142
+ const tsgoPaths = ["tsgo", "tsgo.js"].map(
143
+ (filename) => import_path.default.join(
144
+ "node_modules",
145
+ "@typescript",
146
+ "native-preview",
147
+ "bin",
148
+ filename
149
+ )
150
+ );
151
+ return tsgoPaths.find((path2) => fs.exists(path2));
152
+ }
153
+ case "tsc": {
154
+ const tscPaths = [
155
+ // TypeScript 7's recommended alias when the TypeScript 6 API is also installed.
156
+ import_path.default.join("node_modules", "@typescript", "native", "bin", "tsc"),
157
+ import_path.default.join("node_modules", "typescript", "bin", "tsc")
158
+ ];
159
+ return tscPaths.find((path2) => fs.exists(path2));
160
+ }
161
+ default:
162
+ typescriptCompiler;
163
+ }
164
+ }
162
165
  async function runTscInner(ctx, tscPath, tscArgs, handleResult) {
163
166
  const result = await (0, import_utils.spawnAsync)(ctx, process.execPath, [
164
167
  tscPath,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/cli/lib/typecheck.ts"],
4
- "sourcesContent": ["import { chalkStderr } from \"chalk\";\nimport path from \"path\";\nimport { performance } from \"perf_hooks\";\nimport { Context } from \"../../bundler/context.js\";\nimport {\n changeSpinner,\n logError,\n logFailure,\n logMessage,\n showSpinner,\n} from \"../../bundler/log.js\";\nimport * as Sentry from \"@sentry/node\";\nimport * as semver from \"semver\";\nimport { formatDuration, spawnAsync } from \"./utils/utils.js\";\nimport { readProjectConfig } from \"./config.js\";\nimport { WatchContext } from \"./watch.js\";\n\nexport type TypecheckResult = \"cantTypeCheck\" | \"success\" | \"typecheckFailed\";\n\nexport type TypeCheckMode = \"enable\" | \"try\" | \"disable\";\n\nexport type TypescriptCompiler = \"tsc\" | \"tsgo\";\n\nconst SLOW_TYPECHECK_THRESHOLD_MS = 10_000;\nconst SLOW_TYPECHECK_DOCS_URL =\n \"https://docs.convex.dev/cli/troubleshooting/typecheck-performance\";\n\n/**\n * Resolves the TypeScript compiler to use based on CLI flag, config file, and default.\n * Precedence: CLI flag \u2192 config file \u2192 default \"tsc\"\n */\nexport async function resolveTypescriptCompiler(\n ctx: Context,\n cliOption?: TypescriptCompiler,\n): Promise<TypescriptCompiler> {\n const { projectConfig } = await readProjectConfig(ctx);\n return cliOption ?? projectConfig?.typescriptCompiler ?? \"tsc\";\n}\n\ntype TypecheckResultHandler = (\n result: TypecheckResult,\n logSpecificError?: () => void,\n // If given, we run it to print out errors.\n // We expect it to throw or resolve to \"success\"\n // if a concurrent change invalidated the error result.\n runOnError?: () => Promise<\"success\">,\n) => Promise<void>;\n\n/**\n * Conditionally run a typecheck function and interpret the result.\n *\n * If typeCheckMode === \"disable\", never run the typecheck function.\n * If typeCheckMode === \"enable\", run the typecheck and crash if typechecking\n * fails or we can't find tsc.\n * If typeCheckMode === \"try\", try and run the typecheck. crash if typechecking\n * fails but don't worry if tsc is missing and we can't run it.\n */\nexport async function typeCheckFunctionsInMode(\n ctx: Context,\n typeCheckMode: TypeCheckMode,\n functionsDir: string,\n): Promise<void> {\n if (typeCheckMode === \"disable\") {\n return;\n }\n const typescriptCompiler = await resolveTypescriptCompiler(ctx);\n const typecheckStart = performance.now();\n const slowTypecheckTimeout = setTimeout(() => {\n changeSpinner(\n `Still running TypeScript... see ${SLOW_TYPECHECK_DOCS_URL} to troubleshoot.`,\n );\n }, SLOW_TYPECHECK_THRESHOLD_MS);\n try {\n await typeCheckFunctions(\n ctx,\n typescriptCompiler,\n functionsDir,\n async (result, logSpecificError, runOnError) => {\n if (\n (result === \"cantTypeCheck\" && typeCheckMode === \"enable\") ||\n result === \"typecheckFailed\"\n ) {\n logSpecificError?.();\n logError(\n chalkStderr.gray(\n \"To ignore failing typecheck, use `--typecheck=disable`.\",\n ),\n );\n try {\n const result = await runOnError?.();\n // Concurrent change invalidated the error, don't fail\n if (result === \"success\") {\n return;\n }\n } catch {\n // As expected, `runOnError` threw\n }\n await ctx.crash({\n exitCode: 1,\n errorType: \"invalid filesystem data\",\n printedMessage: null,\n });\n }\n },\n );\n } finally {\n clearTimeout(slowTypecheckTimeout);\n }\n maybeLogSlowTypecheckSuggestion(ctx, performance.now() - typecheckStart);\n}\n\n// Runs TypeScript compiler to typecheck Convex query and mutation functions.\nexport async function typeCheckFunctions(\n ctx: Context,\n typescriptCompiler: TypescriptCompiler,\n functionsDir: string,\n handleResult: TypecheckResultHandler,\n): Promise<void> {\n const tsconfig = path.join(functionsDir, \"tsconfig.json\");\n if (!ctx.fs.exists(tsconfig)) {\n return handleResult(\"cantTypeCheck\", () => {\n logError(\n \"Found no convex/tsconfig.json to use to typecheck Convex functions, so skipping typecheck.\",\n );\n logError(\"Run `npx convex codegen --init` to create one.\");\n });\n }\n await runTsc(\n ctx,\n typescriptCompiler,\n [\"--project\", functionsDir],\n handleResult,\n );\n}\n\nasync function runTsc(\n ctx: Context,\n typescriptCompiler: TypescriptCompiler,\n tscArgs: string[],\n handleResult: TypecheckResultHandler,\n): Promise<void> {\n // Check if the TypeScript compiler is even installed\n let compilerPath: string | undefined;\n switch (typescriptCompiler) {\n case \"tsgo\": {\n // @typescript/native-preview@7.0.0-dev.20260626.1 switched to using `bin/tsgo` instead of `bin/tsgo.js`.\n const tsgoPaths = [\"tsgo\", \"tsgo.js\"].map((filename) =>\n path.join(\n \"node_modules\",\n \"@typescript\",\n \"native-preview\",\n \"bin\",\n filename,\n ),\n );\n compilerPath = tsgoPaths.find((path) => ctx.fs.exists(path));\n break;\n }\n case \"tsc\": {\n const tscPath = path.join(\"node_modules\", \"typescript\", \"bin\", \"tsc\");\n if (ctx.fs.exists(tscPath)) {\n compilerPath = tscPath;\n }\n break;\n }\n default:\n typescriptCompiler satisfies never;\n }\n if (!compilerPath) {\n return handleResult(\"cantTypeCheck\", () => {\n logError(\n chalkStderr.gray(\n `No \\`${typescriptCompiler}\\` binary found, so skipping typecheck.`,\n ),\n );\n });\n }\n\n // Check the TypeScript version matches the recommendation from Convex\n const versionResult = await spawnAsync(ctx, process.execPath, [\n compilerPath,\n \"--version\",\n ]);\n\n const version = versionResult.stdout.match(/Version (.*)/)?.[1] ?? null;\n const hasOlderTypeScriptVersion = version && semver.lt(version, \"4.8.4\");\n\n await runTscInner(ctx, compilerPath, tscArgs, handleResult);\n\n // Print this warning after any logs from running `tsc`\n if (hasOlderTypeScriptVersion) {\n logError(\n chalkStderr.yellow(\n \"Convex works best with TypeScript version 4.8.4 or newer -- npm i --save-dev typescript@latest to update.\",\n ),\n );\n }\n}\n\nasync function runTscInner(\n ctx: Context,\n tscPath: string,\n tscArgs: string[],\n handleResult: TypecheckResultHandler,\n) {\n // Run `tsc` once and have it print out the files it touched. This output won't\n // be very useful if there's an error, but we'll run it again to get a nice\n // user-facing error in this exceptional case.\n // The `--listFiles` command prints out files touched on success or error.\n const result = await spawnAsync(ctx, process.execPath, [\n tscPath,\n ...tscArgs,\n \"--listFiles\",\n ]);\n if (result.status === null) {\n return handleResult(\"typecheckFailed\", () => {\n logFailure(`TypeScript typecheck timed out.`);\n if (result.error) {\n logError(chalkStderr.red(`${result.error.toString()}`));\n }\n });\n }\n // Okay, we may have failed `tsc` but at least it returned. Try to parse its\n // output to discover which files it touched.\n const filesTouched = result.stdout\n .split(\"\\n\")\n .map((s) => s.trim())\n .filter((s) => s.length > 0);\n let anyPathsFound = false;\n for (const fileTouched of filesTouched) {\n const absPath = path.resolve(fileTouched);\n let st;\n try {\n st = ctx.fs.stat(absPath);\n anyPathsFound = true;\n } catch {\n // Just move on if we have a bogus path from `tsc`. We'll log below if\n // we fail to stat *any* of the paths emitted by `tsc`.\n // TODO: Switch to using their JS API so we can get machine readable output.\n continue;\n }\n ctx.fs.registerPath(absPath, st);\n }\n if (filesTouched.length > 0 && !anyPathsFound) {\n const err = new Error(\n `Failed to stat any files emitted by tsc (received ${filesTouched.length})`,\n );\n Sentry.captureException(err);\n }\n\n if (!result.error && result.status === 0) {\n return handleResult(\"success\");\n }\n\n // This is the \"No inputs were found\", which is fine and we shouldn't\n // report it to the user.\n if (result.stdout.startsWith(\"error TS18003\")) {\n return handleResult(\"success\");\n }\n\n // At this point we know that `tsc` failed. Rerun it without `--listFiles`\n // and with stderr redirected to have it print out a nice error.\n return handleResult(\n \"typecheckFailed\",\n () => {\n logFailure(\"TypeScript typecheck via `tsc` failed.\");\n },\n async () => {\n showSpinner(\"Collecting TypeScript errors\");\n await spawnAsync(\n ctx,\n process.execPath,\n [tscPath, ...tscArgs, \"--pretty\", \"true\"],\n {\n stdio: \"inherit\",\n },\n );\n // If this passes, we had a concurrent file change that'll overlap with\n // our observations in the first run. Invalidate our context's filesystem\n // but allow the rest of the system to observe the success.\n ctx.fs.invalidate();\n return \"success\";\n },\n );\n}\n\nfunction maybeLogSlowTypecheckSuggestion(ctx: Context, durationMs: number) {\n if (!(ctx instanceof WatchContext)) {\n return;\n }\n if (!ctx.isFirstPush) {\n return;\n }\n if (durationMs <= SLOW_TYPECHECK_THRESHOLD_MS) {\n return;\n }\n const formattedDuration = formatDuration(durationMs);\n logMessage(\n chalkStderr.gray(\n `Typechecking took ${formattedDuration}. For faster iteration, see ${SLOW_TYPECHECK_DOCS_URL} to troubleshoot typecheck performance.`,\n ),\n );\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { chalkStderr } from \"chalk\";\nimport path from \"path\";\nimport { performance } from \"perf_hooks\";\nimport { Context } from \"../../bundler/context.js\";\nimport {\n changeSpinner,\n logError,\n logFailure,\n logMessage,\n showSpinner,\n} from \"../../bundler/log.js\";\nimport * as Sentry from \"@sentry/node\";\nimport * as semver from \"semver\";\nimport { formatDuration, spawnAsync } from \"./utils/utils.js\";\nimport { readProjectConfig } from \"./config.js\";\nimport { WatchContext } from \"./watch.js\";\nimport { Filesystem } from \"../../bundler/fs.js\";\n\nexport type TypecheckResult = \"cantTypeCheck\" | \"success\" | \"typecheckFailed\";\n\nexport type TypeCheckMode = \"enable\" | \"try\" | \"disable\";\n\nexport type TypescriptCompiler = \"tsc\" | \"tsgo\";\n\nconst SLOW_TYPECHECK_THRESHOLD_MS = 10_000;\nconst SLOW_TYPECHECK_DOCS_URL =\n \"https://docs.convex.dev/cli/troubleshooting/typecheck-performance\";\n\n/**\n * Resolves the TypeScript compiler to use based on CLI flag, config file, and default.\n * Precedence: CLI flag \u2192 config file \u2192 default \"tsc\"\n */\nexport async function resolveTypescriptCompiler(\n ctx: Context,\n cliOption?: TypescriptCompiler,\n): Promise<TypescriptCompiler> {\n const { projectConfig } = await readProjectConfig(ctx);\n return cliOption ?? projectConfig?.typescriptCompiler ?? \"tsc\";\n}\n\ntype TypecheckResultHandler = (\n result: TypecheckResult,\n logSpecificError?: () => void,\n // If given, we run it to print out errors.\n // We expect it to throw or resolve to \"success\"\n // if a concurrent change invalidated the error result.\n runOnError?: () => Promise<\"success\">,\n) => Promise<void>;\n\n/**\n * Conditionally run a typecheck function and interpret the result.\n *\n * If typeCheckMode === \"disable\", never run the typecheck function.\n * If typeCheckMode === \"enable\", run the typecheck and crash if typechecking\n * fails or we can't find tsc.\n * If typeCheckMode === \"try\", try and run the typecheck. crash if typechecking\n * fails but don't worry if tsc is missing and we can't run it.\n */\nexport async function typeCheckFunctionsInMode(\n ctx: Context,\n typeCheckMode: TypeCheckMode,\n functionsDir: string,\n): Promise<void> {\n if (typeCheckMode === \"disable\") {\n return;\n }\n const typescriptCompiler = await resolveTypescriptCompiler(ctx);\n const typecheckStart = performance.now();\n const slowTypecheckTimeout = setTimeout(() => {\n changeSpinner(\n `Still running TypeScript... see ${SLOW_TYPECHECK_DOCS_URL} to troubleshoot.`,\n );\n }, SLOW_TYPECHECK_THRESHOLD_MS);\n try {\n await typeCheckFunctions(\n ctx,\n typescriptCompiler,\n functionsDir,\n async (result, logSpecificError, runOnError) => {\n if (\n (result === \"cantTypeCheck\" && typeCheckMode === \"enable\") ||\n result === \"typecheckFailed\"\n ) {\n logSpecificError?.();\n logError(\n chalkStderr.gray(\n \"To ignore failing typecheck, use `--typecheck=disable`.\",\n ),\n );\n try {\n const result = await runOnError?.();\n // Concurrent change invalidated the error, don't fail\n if (result === \"success\") {\n return;\n }\n } catch {\n // As expected, `runOnError` threw\n }\n await ctx.crash({\n exitCode: 1,\n errorType: \"invalid filesystem data\",\n printedMessage: null,\n });\n }\n },\n );\n } finally {\n clearTimeout(slowTypecheckTimeout);\n }\n maybeLogSlowTypecheckSuggestion(ctx, performance.now() - typecheckStart);\n}\n\n// Runs TypeScript compiler to typecheck Convex query and mutation functions.\nexport async function typeCheckFunctions(\n ctx: Context,\n typescriptCompiler: TypescriptCompiler,\n functionsDir: string,\n handleResult: TypecheckResultHandler,\n): Promise<void> {\n const tsconfig = path.join(functionsDir, \"tsconfig.json\");\n if (!ctx.fs.exists(tsconfig)) {\n return handleResult(\"cantTypeCheck\", () => {\n logError(\n \"Found no convex/tsconfig.json to use to typecheck Convex functions, so skipping typecheck.\",\n );\n logError(\"Run `npx convex codegen --init` to create one.\");\n });\n }\n await runTsc(\n ctx,\n typescriptCompiler,\n [\"--project\", functionsDir],\n handleResult,\n );\n}\n\nasync function runTsc(\n ctx: Context,\n typescriptCompiler: TypescriptCompiler,\n tscArgs: string[],\n handleResult: TypecheckResultHandler,\n): Promise<void> {\n const compilerPath = findTypeScriptCompilerPath(ctx.fs, typescriptCompiler);\n if (!compilerPath) {\n return handleResult(\"cantTypeCheck\", () => {\n logError(\n chalkStderr.gray(\n `No \\`${typescriptCompiler}\\` binary found, so skipping typecheck.`,\n ),\n );\n });\n }\n\n // Check the TypeScript version matches the recommendation from Convex\n const versionResult = await spawnAsync(ctx, process.execPath, [\n compilerPath,\n \"--version\",\n ]);\n\n const version = versionResult.stdout.match(/Version (.*)/)?.[1] ?? null;\n const hasOlderTypeScriptVersion = version && semver.lt(version, \"4.8.4\");\n\n await runTscInner(ctx, compilerPath, tscArgs, handleResult);\n\n // Print this warning after any logs from running `tsc`\n if (hasOlderTypeScriptVersion) {\n logError(\n chalkStderr.yellow(\n \"Convex works best with TypeScript version 4.8.4 or newer -- npm i --save-dev typescript@latest to update.\",\n ),\n );\n }\n}\n\nexport function findTypeScriptCompilerPath(\n fs: Pick<Filesystem, \"exists\">,\n typescriptCompiler: TypescriptCompiler,\n): string | undefined {\n switch (typescriptCompiler) {\n case \"tsgo\": {\n // @typescript/native-preview@7.0.0-dev.20260626.1 switched to using `bin/tsgo` instead of `bin/tsgo.js`.\n const tsgoPaths = [\"tsgo\", \"tsgo.js\"].map((filename) =>\n path.join(\n \"node_modules\",\n \"@typescript\",\n \"native-preview\",\n \"bin\",\n filename,\n ),\n );\n return tsgoPaths.find((path) => fs.exists(path));\n }\n case \"tsc\": {\n const tscPaths = [\n // TypeScript 7's recommended alias when the TypeScript 6 API is also installed.\n path.join(\"node_modules\", \"@typescript\", \"native\", \"bin\", \"tsc\"),\n path.join(\"node_modules\", \"typescript\", \"bin\", \"tsc\"),\n ];\n return tscPaths.find((path) => fs.exists(path));\n }\n default:\n typescriptCompiler satisfies never;\n }\n}\n\nasync function runTscInner(\n ctx: Context,\n tscPath: string,\n tscArgs: string[],\n handleResult: TypecheckResultHandler,\n) {\n // Run `tsc` once and have it print out the files it touched. This output won't\n // be very useful if there's an error, but we'll run it again to get a nice\n // user-facing error in this exceptional case.\n // The `--listFiles` command prints out files touched on success or error.\n const result = await spawnAsync(ctx, process.execPath, [\n tscPath,\n ...tscArgs,\n \"--listFiles\",\n ]);\n if (result.status === null) {\n return handleResult(\"typecheckFailed\", () => {\n logFailure(`TypeScript typecheck timed out.`);\n if (result.error) {\n logError(chalkStderr.red(`${result.error.toString()}`));\n }\n });\n }\n // Okay, we may have failed `tsc` but at least it returned. Try to parse its\n // output to discover which files it touched.\n const filesTouched = result.stdout\n .split(\"\\n\")\n .map((s) => s.trim())\n .filter((s) => s.length > 0);\n let anyPathsFound = false;\n for (const fileTouched of filesTouched) {\n const absPath = path.resolve(fileTouched);\n let st;\n try {\n st = ctx.fs.stat(absPath);\n anyPathsFound = true;\n } catch {\n // Just move on if we have a bogus path from `tsc`. We'll log below if\n // we fail to stat *any* of the paths emitted by `tsc`.\n // TODO: Switch to using their JS API so we can get machine readable output.\n continue;\n }\n ctx.fs.registerPath(absPath, st);\n }\n if (filesTouched.length > 0 && !anyPathsFound) {\n const err = new Error(\n `Failed to stat any files emitted by tsc (received ${filesTouched.length})`,\n );\n Sentry.captureException(err);\n }\n\n if (!result.error && result.status === 0) {\n return handleResult(\"success\");\n }\n\n // This is the \"No inputs were found\", which is fine and we shouldn't\n // report it to the user.\n if (result.stdout.startsWith(\"error TS18003\")) {\n return handleResult(\"success\");\n }\n\n // At this point we know that `tsc` failed. Rerun it without `--listFiles`\n // and with stderr redirected to have it print out a nice error.\n return handleResult(\n \"typecheckFailed\",\n () => {\n logFailure(\"TypeScript typecheck via `tsc` failed.\");\n },\n async () => {\n showSpinner(\"Collecting TypeScript errors\");\n await spawnAsync(\n ctx,\n process.execPath,\n [tscPath, ...tscArgs, \"--pretty\", \"true\"],\n {\n stdio: \"inherit\",\n },\n );\n // If this passes, we had a concurrent file change that'll overlap with\n // our observations in the first run. Invalidate our context's filesystem\n // but allow the rest of the system to observe the success.\n ctx.fs.invalidate();\n return \"success\";\n },\n );\n}\n\nfunction maybeLogSlowTypecheckSuggestion(ctx: Context, durationMs: number) {\n if (!(ctx instanceof WatchContext)) {\n return;\n }\n if (!ctx.isFirstPush) {\n return;\n }\n if (durationMs <= SLOW_TYPECHECK_THRESHOLD_MS) {\n return;\n }\n const formattedDuration = formatDuration(durationMs);\n logMessage(\n chalkStderr.gray(\n `Typechecking took ${formattedDuration}. For faster iteration, see ${SLOW_TYPECHECK_DOCS_URL} to troubleshoot typecheck performance.`,\n ),\n );\n}\n"],
5
+ "mappings": "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",
6
6
  "names": ["result", "path"]
7
7
  }
@@ -0,0 +1,164 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+ var usageLimits_exports = {};
20
+ __export(usageLimits_exports, {
21
+ METRIC_LABELS: () => METRIC_LABELS,
22
+ USAGE_LIMIT_METRICS: () => USAGE_LIMIT_METRICS,
23
+ USAGE_LIMIT_TYPES: () => USAGE_LIMIT_TYPES,
24
+ USAGE_LIMIT_WINDOWS: () => USAGE_LIMIT_WINDOWS,
25
+ compareMetricNames: () => compareMetricNames,
26
+ compareUsageLimits: () => compareUsageLimits,
27
+ createUsageLimit: () => createUsageLimit,
28
+ deleteUsageLimit: () => deleteUsageLimit,
29
+ findUsageLimitByKey: () => findUsageLimitByKey,
30
+ getCurrentUsage: () => getCurrentUsage,
31
+ listUsageLimits: () => listUsageLimits,
32
+ listUsageLimitsWithStatus: () => listUsageLimitsWithStatus,
33
+ metricLabel: () => metricLabel,
34
+ updateUsageLimit: () => updateUsageLimit
35
+ });
36
+ module.exports = __toCommonJS(usageLimits_exports);
37
+ var import_utils = require("./utils/utils.js");
38
+ const USAGE_LIMIT_METRICS = [
39
+ "functionCalls",
40
+ "queryMutationComputeGbHours",
41
+ "actionComputeConvexGbHours",
42
+ "actionComputeNodeJsGbHours",
43
+ "actionComputeCpuGbHours",
44
+ "databaseIoGb",
45
+ "searchQueryGb",
46
+ "dataEgressGb"
47
+ ];
48
+ const _metricsExhaustive = true;
49
+ void _metricsExhaustive;
50
+ const USAGE_LIMIT_WINDOWS = ["day", "month"];
51
+ const USAGE_LIMIT_TYPES = ["warning", "disable"];
52
+ const METRIC_LABELS = {
53
+ functionCalls: "Function calls",
54
+ queryMutationComputeGbHours: "Query/Mutation compute",
55
+ actionComputeConvexGbHours: "Action compute",
56
+ actionComputeNodeJsGbHours: "Action compute (Node.js)",
57
+ actionComputeCpuGbHours: "Action compute (CPU)",
58
+ databaseIoGb: "Database I/O",
59
+ searchQueryGb: "Search queries",
60
+ dataEgressGb: "Data egress"
61
+ };
62
+ function metricLabel(metric) {
63
+ return METRIC_LABELS[metric] ?? metric;
64
+ }
65
+ async function usageLimitFetch(ctx, deployment, path, init) {
66
+ const fetch = (0, import_utils.deploymentFetch)(ctx, deployment);
67
+ try {
68
+ const response = await fetch(`/api/v1${path}`, {
69
+ method: init?.method ?? "GET",
70
+ ...init?.body !== void 0 ? { body: JSON.stringify(init.body) } : {}
71
+ });
72
+ const text = await response.text();
73
+ return text.length > 0 ? JSON.parse(text) : void 0;
74
+ } catch (e) {
75
+ return await (0, import_utils.logAndHandleFetchError)(ctx, e);
76
+ }
77
+ }
78
+ async function listUsageLimits(ctx, deployment) {
79
+ const result = await usageLimitFetch(
80
+ ctx,
81
+ deployment,
82
+ "/list_usage_limits"
83
+ );
84
+ return result.usageLimits;
85
+ }
86
+ async function createUsageLimit(ctx, deployment, config) {
87
+ const result = await usageLimitFetch(
88
+ ctx,
89
+ deployment,
90
+ "/create_usage_limit",
91
+ {
92
+ method: "POST",
93
+ body: config
94
+ }
95
+ );
96
+ return result.usageLimit;
97
+ }
98
+ async function updateUsageLimit(ctx, deployment, id, config) {
99
+ const result = await usageLimitFetch(
100
+ ctx,
101
+ deployment,
102
+ `/update_usage_limit/${id}`,
103
+ { method: "POST", body: config }
104
+ );
105
+ return result.usageLimit;
106
+ }
107
+ async function deleteUsageLimit(ctx, deployment, id) {
108
+ await usageLimitFetch(ctx, deployment, `/delete_usage_limit/${id}`, {
109
+ method: "POST"
110
+ });
111
+ }
112
+ async function getCurrentUsage(ctx, deployment) {
113
+ return await usageLimitFetch(
114
+ ctx,
115
+ deployment,
116
+ "/get_current_usage"
117
+ );
118
+ }
119
+ function metricRank(metric) {
120
+ const i = USAGE_LIMIT_METRICS.indexOf(metric);
121
+ return i === -1 ? USAGE_LIMIT_METRICS.length : i;
122
+ }
123
+ const windowRank = (w) => w === "month" ? 0 : 1;
124
+ const typeRank = (t) => t === "warning" ? 0 : 1;
125
+ function compareUsageLimits(a, b) {
126
+ return metricRank(a.metric) - metricRank(b.metric) || windowRank(a.window) - windowRank(b.window) || typeRank(a.limitType) - typeRank(b.limitType);
127
+ }
128
+ function compareMetricNames(a, b) {
129
+ return metricRank(a) - metricRank(b);
130
+ }
131
+ function usageInWindow(usage, metric, window) {
132
+ const m = usage.metrics[metric];
133
+ if (m === void 0) {
134
+ return null;
135
+ }
136
+ return window === "day" ? m.usage.current_day : m.usage.current_month;
137
+ }
138
+ async function listUsageLimitsWithStatus(ctx, deployment) {
139
+ const [limits, usage] = await Promise.all([
140
+ listUsageLimits(ctx, deployment),
141
+ getCurrentUsage(ctx, deployment)
142
+ ]);
143
+ const withStatus = limits.map((limit) => {
144
+ const currentUsage = usageInWindow(usage, limit.metric, limit.window);
145
+ const unit = usage.metrics[limit.metric]?.unit ?? null;
146
+ const triggered = limit.enabled && currentUsage !== null && currentUsage >= limit.limit;
147
+ return { ...limit, currentUsage, unit, triggered };
148
+ }).sort(compareUsageLimits);
149
+ return { limits: withStatus, seedStatus: usage.seedStatus };
150
+ }
151
+ async function findUsageLimitByKey(ctx, deployment, key) {
152
+ const match = (await listUsageLimits(ctx, deployment)).find(
153
+ (limit) => limit.metric === key.metric && limit.window === key.window && limit.limitType === key.limitType
154
+ );
155
+ if (match === void 0) {
156
+ return ctx.crash({
157
+ exitCode: 1,
158
+ errorType: "fatal",
159
+ printedMessage: `error: No ${key.limitType} usage limit on ${key.metric} per ${key.window}${deployment.deploymentNotice}.`
160
+ });
161
+ }
162
+ return match;
163
+ }
164
+ //# sourceMappingURL=usageLimits.js.map