convex 1.41.0 → 1.42.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 (191) hide show
  1. package/CHANGELOG.md +38 -0
  2. package/dist/browser.bundle.js +24 -6
  3. package/dist/browser.bundle.js.map +2 -2
  4. package/dist/cjs/browser/simple_client-node.js +85 -27
  5. package/dist/cjs/browser/simple_client-node.js.map +3 -3
  6. package/dist/cjs/browser/sync/authentication_manager.js +21 -4
  7. package/dist/cjs/browser/sync/authentication_manager.js.map +2 -2
  8. package/dist/cjs/browser/sync/client.js +2 -1
  9. package/dist/cjs/browser/sync/client.js.map +2 -2
  10. package/dist/cjs/cli/env.js +12 -5
  11. package/dist/cjs/cli/env.js.map +2 -2
  12. package/dist/cjs/cli/envDefault.js +12 -7
  13. package/dist/cjs/cli/envDefault.js.map +2 -2
  14. package/dist/cjs/cli/insights.js +11 -1
  15. package/dist/cjs/cli/insights.js.map +2 -2
  16. package/dist/cjs/cli/lib/env.js +5 -1
  17. package/dist/cjs/cli/lib/env.js.map +2 -2
  18. package/dist/cjs/cli/lib/login.js +16 -12
  19. package/dist/cjs/cli/lib/login.js.map +2 -2
  20. package/dist/cjs/cli/lib/logs.js +4 -1
  21. package/dist/cjs/cli/lib/logs.js.map +2 -2
  22. package/dist/cjs/cli/lib/run.js +27 -2
  23. package/dist/cjs/cli/lib/run.js.map +2 -2
  24. package/dist/cjs/cli/lib/typecheck.js +28 -10
  25. package/dist/cjs/cli/lib/typecheck.js.map +2 -2
  26. package/dist/cjs/cli/lib/utils/utils.js +30 -0
  27. package/dist/cjs/cli/lib/utils/utils.js.map +2 -2
  28. package/dist/cjs/cli/program.js +2 -1
  29. package/dist/cjs/cli/program.js.map +2 -2
  30. package/dist/cjs/cli/project.js +27 -0
  31. package/dist/cjs/cli/project.js.map +7 -0
  32. package/dist/cjs/cli/projectCreate.js +90 -0
  33. package/dist/cjs/cli/projectCreate.js.map +7 -0
  34. package/dist/cjs/index.js +1 -1
  35. package/dist/cjs/index.js.map +1 -1
  36. package/dist/cjs/server/database.js.map +1 -1
  37. package/dist/cjs/server/impl/meta_impl.js +6 -6
  38. package/dist/cjs/server/impl/meta_impl.js.map +2 -2
  39. package/dist/cjs/server/impl/registration_impl.js +9 -4
  40. package/dist/cjs/server/impl/registration_impl.js.map +2 -2
  41. package/dist/cjs/server/index.js.map +2 -2
  42. package/dist/cjs/server/meta.js.map +1 -1
  43. package/dist/cjs/server/query.js.map +1 -1
  44. package/dist/cjs/server/registration.js.map +1 -1
  45. package/dist/cjs/server/storage.js.map +1 -1
  46. package/dist/cjs/server/system_fields.js.map +1 -1
  47. package/dist/cjs-types/browser/sync/authentication_manager.d.ts +2 -0
  48. package/dist/cjs-types/browser/sync/authentication_manager.d.ts.map +1 -1
  49. package/dist/cjs-types/browser/sync/client.d.ts +16 -0
  50. package/dist/cjs-types/browser/sync/client.d.ts.map +1 -1
  51. package/dist/cjs-types/cli/env.d.ts.map +1 -1
  52. package/dist/cjs-types/cli/envDefault.d.ts.map +1 -1
  53. package/dist/cjs-types/cli/insights.d.ts +1 -0
  54. package/dist/cjs-types/cli/insights.d.ts.map +1 -1
  55. package/dist/cjs-types/cli/lib/env.d.ts +3 -1
  56. package/dist/cjs-types/cli/lib/env.d.ts.map +1 -1
  57. package/dist/cjs-types/cli/lib/env.test.d.ts +2 -0
  58. package/dist/cjs-types/cli/lib/env.test.d.ts.map +1 -0
  59. package/dist/cjs-types/cli/lib/login.d.ts.map +1 -1
  60. package/dist/cjs-types/cli/lib/logs.d.ts +1 -1
  61. package/dist/cjs-types/cli/lib/logs.d.ts.map +1 -1
  62. package/dist/cjs-types/cli/lib/run.d.ts +1 -1
  63. package/dist/cjs-types/cli/lib/run.d.ts.map +1 -1
  64. package/dist/cjs-types/cli/lib/utils/utils.d.ts +10 -0
  65. package/dist/cjs-types/cli/lib/utils/utils.d.ts.map +1 -1
  66. package/dist/cjs-types/cli/program.d.ts.map +1 -1
  67. package/dist/cjs-types/cli/project.d.ts +3 -0
  68. package/dist/cjs-types/cli/project.d.ts.map +1 -0
  69. package/dist/cjs-types/cli/projectCreate.d.ts +5 -0
  70. package/dist/cjs-types/cli/projectCreate.d.ts.map +1 -0
  71. package/dist/cjs-types/index.d.ts +1 -1
  72. package/dist/cjs-types/server/database.d.ts +21 -3
  73. package/dist/cjs-types/server/database.d.ts.map +1 -1
  74. package/dist/cjs-types/server/impl/meta_impl.d.ts.map +1 -1
  75. package/dist/cjs-types/server/impl/registration_impl.d.ts.map +1 -1
  76. package/dist/cjs-types/server/index.d.ts +1 -1
  77. package/dist/cjs-types/server/index.d.ts.map +1 -1
  78. package/dist/cjs-types/server/meta.d.ts +10 -0
  79. package/dist/cjs-types/server/meta.d.ts.map +1 -1
  80. package/dist/cjs-types/server/query.d.ts +1 -1
  81. package/dist/cjs-types/server/registration.d.ts +15 -3
  82. package/dist/cjs-types/server/registration.d.ts.map +1 -1
  83. package/dist/cjs-types/server/storage.d.ts +20 -3
  84. package/dist/cjs-types/server/storage.d.ts.map +1 -1
  85. package/dist/cli.bundle.cjs +1099 -634
  86. package/dist/cli.bundle.cjs.map +4 -4
  87. package/dist/esm/browser/simple_client-node.js +85 -27
  88. package/dist/esm/browser/simple_client-node.js.map +3 -3
  89. package/dist/esm/browser/sync/authentication_manager.js +21 -4
  90. package/dist/esm/browser/sync/authentication_manager.js.map +2 -2
  91. package/dist/esm/browser/sync/client.js +2 -1
  92. package/dist/esm/browser/sync/client.js.map +2 -2
  93. package/dist/esm/cli/env.js +12 -5
  94. package/dist/esm/cli/env.js.map +2 -2
  95. package/dist/esm/cli/envDefault.js +12 -7
  96. package/dist/esm/cli/envDefault.js.map +2 -2
  97. package/dist/esm/cli/insights.js +11 -1
  98. package/dist/esm/cli/insights.js.map +2 -2
  99. package/dist/esm/cli/lib/env.js +5 -1
  100. package/dist/esm/cli/lib/env.js.map +2 -2
  101. package/dist/esm/cli/lib/login.js +18 -13
  102. package/dist/esm/cli/lib/login.js.map +2 -2
  103. package/dist/esm/cli/lib/logs.js +5 -2
  104. package/dist/esm/cli/lib/logs.js.map +2 -2
  105. package/dist/esm/cli/lib/run.js +32 -3
  106. package/dist/esm/cli/lib/run.js.map +2 -2
  107. package/dist/esm/cli/lib/typecheck.js +28 -10
  108. package/dist/esm/cli/lib/typecheck.js.map +3 -3
  109. package/dist/esm/cli/lib/utils/utils.js +29 -0
  110. package/dist/esm/cli/lib/utils/utils.js.map +2 -2
  111. package/dist/esm/cli/program.js +2 -1
  112. package/dist/esm/cli/program.js.map +2 -2
  113. package/dist/esm/cli/project.js +5 -0
  114. package/dist/esm/cli/project.js.map +7 -0
  115. package/dist/esm/cli/projectCreate.js +68 -0
  116. package/dist/esm/cli/projectCreate.js.map +7 -0
  117. package/dist/esm/index.js +1 -1
  118. package/dist/esm/index.js.map +1 -1
  119. package/dist/esm/server/impl/meta_impl.js +6 -6
  120. package/dist/esm/server/impl/meta_impl.js.map +2 -2
  121. package/dist/esm/server/impl/registration_impl.js +9 -4
  122. package/dist/esm/server/impl/registration_impl.js.map +2 -2
  123. package/dist/esm/server/index.js.map +2 -2
  124. package/dist/esm-types/browser/sync/authentication_manager.d.ts +2 -0
  125. package/dist/esm-types/browser/sync/authentication_manager.d.ts.map +1 -1
  126. package/dist/esm-types/browser/sync/client.d.ts +16 -0
  127. package/dist/esm-types/browser/sync/client.d.ts.map +1 -1
  128. package/dist/esm-types/cli/env.d.ts.map +1 -1
  129. package/dist/esm-types/cli/envDefault.d.ts.map +1 -1
  130. package/dist/esm-types/cli/insights.d.ts +1 -0
  131. package/dist/esm-types/cli/insights.d.ts.map +1 -1
  132. package/dist/esm-types/cli/lib/env.d.ts +3 -1
  133. package/dist/esm-types/cli/lib/env.d.ts.map +1 -1
  134. package/dist/esm-types/cli/lib/env.test.d.ts +2 -0
  135. package/dist/esm-types/cli/lib/env.test.d.ts.map +1 -0
  136. package/dist/esm-types/cli/lib/login.d.ts.map +1 -1
  137. package/dist/esm-types/cli/lib/logs.d.ts +1 -1
  138. package/dist/esm-types/cli/lib/logs.d.ts.map +1 -1
  139. package/dist/esm-types/cli/lib/run.d.ts +1 -1
  140. package/dist/esm-types/cli/lib/run.d.ts.map +1 -1
  141. package/dist/esm-types/cli/lib/utils/utils.d.ts +10 -0
  142. package/dist/esm-types/cli/lib/utils/utils.d.ts.map +1 -1
  143. package/dist/esm-types/cli/program.d.ts.map +1 -1
  144. package/dist/esm-types/cli/project.d.ts +3 -0
  145. package/dist/esm-types/cli/project.d.ts.map +1 -0
  146. package/dist/esm-types/cli/projectCreate.d.ts +5 -0
  147. package/dist/esm-types/cli/projectCreate.d.ts.map +1 -0
  148. package/dist/esm-types/index.d.ts +1 -1
  149. package/dist/esm-types/server/database.d.ts +21 -3
  150. package/dist/esm-types/server/database.d.ts.map +1 -1
  151. package/dist/esm-types/server/impl/meta_impl.d.ts.map +1 -1
  152. package/dist/esm-types/server/impl/registration_impl.d.ts.map +1 -1
  153. package/dist/esm-types/server/index.d.ts +1 -1
  154. package/dist/esm-types/server/index.d.ts.map +1 -1
  155. package/dist/esm-types/server/meta.d.ts +10 -0
  156. package/dist/esm-types/server/meta.d.ts.map +1 -1
  157. package/dist/esm-types/server/query.d.ts +1 -1
  158. package/dist/esm-types/server/registration.d.ts +15 -3
  159. package/dist/esm-types/server/registration.d.ts.map +1 -1
  160. package/dist/esm-types/server/storage.d.ts +20 -3
  161. package/dist/esm-types/server/storage.d.ts.map +1 -1
  162. package/dist/react.bundle.js +24 -6
  163. package/dist/react.bundle.js.map +2 -2
  164. package/package.json +4 -4
  165. package/src/browser/sync/authentication_manager.ts +42 -14
  166. package/src/browser/sync/client.ts +17 -0
  167. package/src/cli/env.ts +16 -6
  168. package/src/cli/envDefault.ts +13 -7
  169. package/src/cli/insights.ts +12 -0
  170. package/src/cli/lib/env.test.ts +60 -0
  171. package/src/cli/lib/env.ts +9 -1
  172. package/src/cli/lib/login.ts +18 -18
  173. package/src/cli/lib/logs.ts +7 -2
  174. package/src/cli/lib/run.ts +37 -3
  175. package/src/cli/lib/typecheck.ts +26 -10
  176. package/src/cli/lib/utils/utils.ts +56 -0
  177. package/src/cli/program.ts +2 -0
  178. package/src/cli/project.ts +7 -0
  179. package/src/cli/projectCreate.ts +99 -0
  180. package/src/index.ts +1 -1
  181. package/src/react/ConvexAuthState.test.tsx +145 -0
  182. package/src/server/database.ts +21 -3
  183. package/src/server/impl/meta_impl.ts +7 -6
  184. package/src/server/impl/registration_impl.ts +11 -5
  185. package/src/server/index.ts +1 -0
  186. package/src/server/meta.ts +10 -0
  187. package/src/server/query.ts +1 -1
  188. package/src/server/registration.test.ts +25 -1
  189. package/src/server/registration.ts +16 -1
  190. package/src/server/storage.ts +22 -3
  191. package/src/server/system_fields.ts +1 -1
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/cli/lib/run.ts"],
4
- "sourcesContent": ["import { chalkStderr } from \"chalk\";\nimport util from \"util\";\nimport ws from \"ws\";\nimport { ConvexHttpClient } from \"../../browser/http_client.js\";\nimport { BaseConvexClient } from \"../../browser/index.js\";\nimport {\n PaginationResult,\n UserIdentityAttributes,\n makeFunctionReference,\n} from \"../../server/index.js\";\nimport { Value, convexToJson, jsonToConvex } from \"../../values/value.js\";\nimport { Context, OneoffCtx } from \"../../bundler/context.js\";\nimport { logFinishedStep, logMessage, logOutput } from \"../../bundler/log.js\";\nimport { waitForever, waitUntilCalled } from \"./utils/utils.js\";\nimport JSON5 from \"json5\";\nimport path from \"path\";\nimport { readProjectConfig } from \"./config.js\";\nimport { watchAndPush } from \"./dev.js\";\nimport { Logger, DefaultLogger } from \"../../browser/logging.js\";\n\nexport async function runFunctionAndLog(\n ctx: Context,\n args: {\n deploymentUrl: string;\n adminKey: string;\n functionName: string;\n argsString: string;\n identityString?: string | undefined;\n componentPath?: string | undefined;\n callbacks?:\n | {\n onSuccess?: () => void | undefined;\n }\n | undefined;\n },\n) {\n const client = new ConvexHttpClient(args.deploymentUrl, {\n logger: instantiateStderrLogger(),\n });\n const identity = args.identityString\n ? await getFakeIdentity(ctx, args.identityString)\n : undefined;\n client.setAdminAuth(args.adminKey, identity);\n\n const functionArgs = await parseArgs(ctx, args.argsString);\n const { projectConfig } = await readProjectConfig(ctx);\n const parsedFunctionName = await parseFunctionName(\n ctx,\n args.functionName,\n projectConfig.functions,\n );\n let result: Value;\n try {\n result = await client.function(\n makeFunctionReference(parsedFunctionName),\n args.componentPath,\n functionArgs,\n );\n } catch (err) {\n const errorMessage = (err as Error).toString().trim();\n\n if (errorMessage.includes(\"Could not find function\")) {\n const functions = (await runSystemQuery(ctx, {\n deploymentUrl: args.deploymentUrl,\n adminKey: args.adminKey,\n functionName: \"_system/cli/modules:apiSpec\",\n componentPath: args.componentPath,\n args: {},\n })) as (\n | {\n functionType: \"Query\" | \"Mutation\" | \"Action\";\n identifier: string;\n }\n | {\n functionType: \"HttpAction\";\n }\n )[];\n\n const functionNames = functions\n .filter(\n (\n fn,\n ): fn is {\n functionType: \"Query\" | \"Mutation\" | \"Action\";\n identifier: string;\n } => fn.functionType !== \"HttpAction\",\n )\n .map(({ identifier }) => {\n const separatorPos = identifier.indexOf(\":\");\n\n const path =\n separatorPos === -1\n ? \"\"\n : identifier.substring(0, separatorPos).replace(/\\.js$/, \"\");\n const name =\n separatorPos === -1\n ? identifier\n : identifier.substring(separatorPos + 1);\n\n return `\u2022 ${chalkStderr.gray(`${path}:`)}${name}`;\n });\n\n const availableFunctionsMessage =\n functionNames.length > 0\n ? `Available functions:\\n${functionNames.join(\"\\n\")}`\n : \"No functions found.\";\n\n return await ctx.crash({\n exitCode: 1,\n errorType: \"invalid filesystem data\",\n printedMessage: `Failed to run function \"${args.functionName}\":\\n${chalkStderr.red(errorMessage)}\\n\\n${availableFunctionsMessage}`,\n });\n }\n\n return await ctx.crash({\n exitCode: 1,\n errorType: \"invalid filesystem or env vars\",\n printedMessage: `Failed to run function \"${args.functionName}\":\\n${chalkStderr.red(errorMessage)}`,\n });\n }\n\n args.callbacks?.onSuccess?.();\n\n // `null` is the default return type\n if (result !== null) {\n logOutput(formatValue(result));\n }\n}\n\nasync function getFakeIdentity(ctx: Context, identityString: string) {\n let identity: UserIdentityAttributes;\n try {\n identity = JSON5.parse(identityString);\n } catch (err) {\n return await ctx.crash({\n exitCode: 1,\n errorType: \"fatal\",\n printedMessage: `Failed to parse identity as JSON: \"${identityString}\"\\n${chalkStderr.red((err as Error).toString().trim())}`,\n });\n }\n const subject = identity.subject ?? \"\" + simpleHash(JSON.stringify(identity));\n const issuer = identity.issuer ?? \"https://convex.test\";\n const tokenIdentifier =\n identity.tokenIdentifier ?? `${issuer.toString()}|${subject.toString()}`;\n return {\n ...identity,\n subject,\n issuer,\n tokenIdentifier,\n };\n}\n\nexport async function parseArgs(ctx: Context, argsString: string) {\n try {\n const argsJson = JSON5.parse(argsString);\n return jsonToConvex(argsJson) as Record<string, Value>;\n } catch (err) {\n return await ctx.crash({\n exitCode: 1,\n errorType: \"invalid filesystem or env vars\",\n printedMessage: `Failed to parse arguments as JSON: \"${argsString}\"\\n${chalkStderr.red((err as Error).toString().trim())}`,\n });\n }\n}\n\nexport async function parseFunctionName(\n ctx: Context,\n functionName: string,\n // Usually `convex/` -- should contain trailing slash\n functionDirName: string,\n) {\n // api.foo.bar -> foo:bar\n // foo/bar -> foo/bar:default\n // foo/bar:baz -> foo/bar:baz\n // convex/foo/bar -> foo/bar:default\n\n // This is the `api.foo.bar` format\n if (functionName.startsWith(\"api.\") || functionName.startsWith(\"internal.\")) {\n const parts = functionName.split(\".\");\n if (parts.length < 3) {\n return await ctx.crash({\n exitCode: 1,\n errorType: \"fatal\",\n printedMessage: `Function name has too few parts: \"${functionName}\"`,\n });\n }\n const exportName = parts.pop();\n const parsedName = `${parts.slice(1).join(\"/\")}:${exportName}`;\n return parsedName;\n }\n\n // This is the `foo/bar:baz` format\n\n // This is something like `convex/foo/bar`, which could either be addressing `foo/bar:default` or `convex/foo/bar:default`\n // if there's a directory with the same name as the functions directory nested directly underneath.\n // We'll prefer the `convex/foo/bar:default` version, and check if the file exists, and otherwise treat this as a relative path from the project root.\n const filePath = functionName.split(\":\")[0];\n const possibleExtensions = [\n \".ts\",\n \".js\",\n \".tsx\",\n \".jsx\",\n \".mts\",\n \".mjs\",\n \".cts\",\n \".cjs\",\n ];\n let hasExtension = false;\n let normalizedFilePath: string = filePath;\n for (const extension of possibleExtensions) {\n if (filePath.endsWith(extension)) {\n normalizedFilePath = filePath.slice(0, -extension.length);\n hasExtension = true;\n break;\n }\n }\n\n const exportName = functionName.split(\":\")[1] ?? \"default\";\n const normalizedName = `${normalizedFilePath}:${exportName}`;\n\n // This isn't a relative path from the project root\n if (!filePath.startsWith(functionDirName)) {\n return normalizedName;\n }\n\n const filePathWithoutPrefix = normalizedFilePath.slice(\n functionDirName.length,\n );\n const functionNameWithoutPrefix = `${filePathWithoutPrefix}:${exportName}`;\n\n if (hasExtension) {\n if (ctx.fs.exists(path.join(functionDirName, filePath))) {\n return normalizedName;\n } else {\n return functionNameWithoutPrefix;\n }\n } else {\n const exists = possibleExtensions.some((extension) =>\n ctx.fs.exists(path.join(functionDirName, filePath + extension)),\n );\n if (exists) {\n return normalizedName;\n } else {\n return functionNameWithoutPrefix;\n }\n }\n}\n\nfunction simpleHash(string: string) {\n let hash = 0;\n for (let i = 0; i < string.length; i++) {\n const char = string.charCodeAt(i);\n hash = (hash << 5) - hash + char;\n hash = hash & hash; // Convert to 32bit integer\n }\n return hash;\n}\n\nexport async function runSystemPaginatedQuery(\n ctx: Context,\n args: {\n deploymentUrl: string;\n adminKey: string;\n functionName: string;\n componentPath: string | undefined;\n args: Record<string, Value>;\n limit?: number;\n },\n) {\n const results = [];\n let cursor = null;\n let isDone = false;\n while (!isDone && (args.limit === undefined || results.length < args.limit)) {\n const paginationResult = (await runSystemQuery(ctx, {\n ...args,\n args: {\n ...args.args,\n paginationOpts: {\n cursor,\n numItems:\n args.limit === undefined ? 10000 : args.limit - results.length,\n },\n },\n })) as unknown as PaginationResult<Record<string, Value>>;\n isDone = paginationResult.isDone;\n cursor = paginationResult.continueCursor;\n results.push(...paginationResult.page);\n }\n return results;\n}\n\nexport async function runSystemQuery(\n ctx: Context,\n args: {\n deploymentUrl: string;\n adminKey: string;\n functionName: string;\n componentPath: string | undefined;\n args: Record<string, Value>;\n },\n): Promise<Value> {\n let onResult: (result: Value) => void;\n const resultPromise = new Promise<Value>((resolve) => {\n onResult = resolve;\n });\n const [donePromise, onDone] = waitUntilCalled();\n await subscribe(ctx, {\n ...args,\n parsedFunctionName: args.functionName,\n parsedFunctionArgs: args.args,\n until: donePromise,\n callbacks: {\n onChange: (result) => {\n onDone();\n onResult(result);\n },\n },\n });\n return resultPromise;\n}\n\nexport function formatValue(value: Value) {\n const json = convexToJson(value);\n if (process.stdout.isTTY) {\n // TODO (Tom) add JSON syntax highlighting like https://stackoverflow.com/a/51319962/398212\n // until then, just spit out something that isn't quite JSON because it's easy\n return util.inspect(value, { colors: true, depth: null });\n } else {\n return JSON.stringify(json, null, 2);\n }\n}\n\nexport async function subscribeAndLog(\n ctx: Context,\n args: {\n deploymentUrl: string;\n adminKey: string;\n functionName: string;\n argsString: string;\n identityString?: string | undefined;\n componentPath: string | undefined;\n },\n) {\n const { projectConfig } = await readProjectConfig(ctx);\n\n const parsedFunctionName = await parseFunctionName(\n ctx,\n args.functionName,\n projectConfig.functions,\n );\n const identity = args.identityString\n ? await getFakeIdentity(ctx, args.identityString)\n : undefined;\n const functionArgs = await parseArgs(ctx, args.argsString);\n return subscribe(ctx, {\n deploymentUrl: args.deploymentUrl,\n adminKey: args.adminKey,\n identity,\n parsedFunctionName,\n parsedFunctionArgs: functionArgs,\n componentPath: args.componentPath,\n until: waitForever(),\n callbacks: {\n onStart() {\n logFinishedStep(\n `Watching query ${args.functionName} on ${args.deploymentUrl}...`,\n );\n },\n onChange(result) {\n logOutput(formatValue(result));\n },\n onStop() {\n logMessage(`Closing connection to ${args.deploymentUrl}...`);\n },\n },\n });\n}\n\nexport async function subscribe(\n _ctx: Context,\n args: {\n deploymentUrl: string;\n adminKey: string;\n identity?: UserIdentityAttributes | undefined;\n parsedFunctionName: string;\n parsedFunctionArgs: Record<string, Value>;\n componentPath: string | undefined;\n until: Promise<unknown>;\n callbacks?:\n | {\n onStart?: () => void;\n onChange?: (result: Value) => void;\n onStop?: () => void;\n }\n | undefined;\n },\n) {\n const client = new BaseConvexClient(\n args.deploymentUrl,\n (updatedQueries) => {\n for (const queryToken of updatedQueries) {\n args.callbacks?.onChange?.(client.localQueryResultByToken(queryToken)!);\n }\n },\n {\n // pretend that a Node.js 'ws' library WebSocket is a browser WebSocket\n webSocketConstructor: ws as unknown as typeof WebSocket,\n unsavedChangesWarning: false,\n },\n );\n client.setAdminAuth(args.adminKey, args.identity);\n const { unsubscribe } = client.subscribe(\n args.parsedFunctionName,\n args.parsedFunctionArgs,\n {\n componentPath: args.componentPath,\n },\n );\n\n args.callbacks?.onStart?.();\n\n let done = false;\n const [donePromise, onDone] = waitUntilCalled();\n const stopWatching = () => {\n if (done) {\n return;\n }\n done = true;\n unsubscribe();\n void client.close();\n process.off(\"SIGINT\", sigintListener);\n onDone();\n args.callbacks?.onStop?.();\n };\n function sigintListener() {\n stopWatching();\n }\n process.on(\"SIGINT\", sigintListener);\n void args.until.finally(stopWatching);\n while (!done) {\n // loops once per day (any large value < 2**31 would work)\n const oneDay = 24 * 60 * 60 * 1000;\n await Promise.race([\n donePromise,\n new Promise((resolve) => setTimeout(resolve, oneDay)),\n ]);\n }\n}\n\nexport async function runInDeployment(\n ctx: OneoffCtx,\n args: {\n deploymentUrl: string;\n adminKey: string;\n deploymentName: string | null;\n functionName: string;\n argsString: string;\n identityString?: string | undefined;\n push: boolean;\n watch: boolean;\n typecheck: \"enable\" | \"try\" | \"disable\";\n typecheckComponents: boolean;\n codegen: boolean;\n componentPath: string | undefined;\n liveComponentSources: boolean;\n },\n) {\n if (args.push) await pushToDeployment(ctx, args);\n\n if (args.watch) {\n return await subscribeAndLog(ctx, args);\n }\n return await runFunctionAndLog(ctx, args);\n}\n\nexport async function pushToDeployment(\n ctx: OneoffCtx,\n args: {\n deploymentUrl: string;\n adminKey: string;\n deploymentName: string | null;\n typecheck: \"enable\" | \"try\" | \"disable\";\n typecheckComponents: boolean;\n codegen: boolean;\n liveComponentSources: boolean;\n },\n) {\n await watchAndPush(\n ctx,\n {\n url: args.deploymentUrl,\n adminKey: args.adminKey,\n deploymentName: args.deploymentName,\n verbose: false,\n dryRun: false,\n typecheck: args.typecheck,\n typecheckComponents: args.typecheckComponents,\n debug: false,\n debugNodeApis: false,\n codegen: args.codegen,\n liveComponentSources: args.liveComponentSources,\n pushAllModules: false,\n largeIndexDeletionCheck: \"no verification\", // `convex run` can\u2019t push to prod\n message: null,\n },\n {\n once: true,\n traceEvents: false,\n untilSuccess: true,\n },\n );\n}\n\nfunction instantiateStderrLogger(): Logger {\n const logger = new DefaultLogger({ verbose: false });\n logger.addLogLineListener((_level, ...args) => {\n // eslint-disable-next-line no-console\n console.error(...args);\n });\n return logger;\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { chalkStderr } from \"chalk\";\nimport util from \"util\";\nimport ws from \"ws\";\nimport { ConvexHttpClient } from \"../../browser/http_client.js\";\nimport { BaseConvexClient } from \"../../browser/index.js\";\nimport {\n PaginationResult,\n UserIdentityAttributes,\n makeFunctionReference,\n} from \"../../server/index.js\";\nimport { Value, convexToJson, jsonToConvex } from \"../../values/value.js\";\nimport { Context, OneoffCtx } from \"../../bundler/context.js\";\nimport { logFinishedStep, logMessage, logOutput } from \"../../bundler/log.js\";\nimport {\n permissionDeniedErrorMessage,\n waitForever,\n waitUntilCalled,\n} from \"./utils/utils.js\";\nimport JSON5 from \"json5\";\nimport path from \"path\";\nimport { readProjectConfig } from \"./config.js\";\nimport { watchAndPush } from \"./dev.js\";\nimport { Logger, DefaultLogger } from \"../../browser/logging.js\";\n\nexport async function runFunctionAndLog(\n ctx: Context,\n args: {\n deploymentUrl: string;\n adminKey: string;\n functionName: string;\n argsString: string;\n identityString?: string | undefined;\n componentPath?: string | undefined;\n callbacks?:\n | {\n onSuccess?: () => void | undefined;\n }\n | undefined;\n },\n) {\n const client = new ConvexHttpClient(args.deploymentUrl, {\n logger: instantiateStderrLogger(),\n });\n const identity = args.identityString\n ? await getFakeIdentity(ctx, args.identityString)\n : undefined;\n client.setAdminAuth(args.adminKey, identity);\n\n const functionArgs = await parseArgs(ctx, args.argsString);\n const { projectConfig } = await readProjectConfig(ctx);\n const parsedFunctionName = await parseFunctionName(\n ctx,\n args.functionName,\n projectConfig.functions,\n );\n let result: Value;\n try {\n result = await client.function(\n makeFunctionReference(parsedFunctionName),\n args.componentPath,\n functionArgs,\n );\n } catch (err) {\n const errorMessage = (err as Error).toString().trim();\n\n const permissionError = permissionDeniedErrorMessage(errorMessage);\n if (permissionError !== null) {\n return await ctx.crash({\n exitCode: 1,\n errorType: \"fatal\",\n printedMessage: chalkStderr.red(permissionError),\n });\n }\n\n if (errorMessage.includes(\"Could not find function\")) {\n const functions = (await runSystemQuery(ctx, {\n deploymentUrl: args.deploymentUrl,\n adminKey: args.adminKey,\n functionName: \"_system/cli/modules:apiSpec\",\n componentPath: args.componentPath,\n args: {},\n })) as (\n | {\n functionType: \"Query\" | \"Mutation\" | \"Action\";\n identifier: string;\n }\n | {\n functionType: \"HttpAction\";\n }\n )[];\n\n const functionNames = functions\n .filter(\n (\n fn,\n ): fn is {\n functionType: \"Query\" | \"Mutation\" | \"Action\";\n identifier: string;\n } => fn.functionType !== \"HttpAction\",\n )\n .map(({ identifier }) => {\n const separatorPos = identifier.indexOf(\":\");\n\n const path =\n separatorPos === -1\n ? \"\"\n : identifier.substring(0, separatorPos).replace(/\\.js$/, \"\");\n const name =\n separatorPos === -1\n ? identifier\n : identifier.substring(separatorPos + 1);\n\n return `\u2022 ${chalkStderr.gray(`${path}:`)}${name}`;\n });\n\n const availableFunctionsMessage =\n functionNames.length > 0\n ? `Available functions:\\n${functionNames.join(\"\\n\")}`\n : \"No functions found.\";\n\n return await ctx.crash({\n exitCode: 1,\n errorType: \"invalid filesystem data\",\n printedMessage: `Failed to run function \"${args.functionName}\":\\n${chalkStderr.red(errorMessage)}\\n\\n${availableFunctionsMessage}`,\n });\n }\n\n return await ctx.crash({\n exitCode: 1,\n errorType: \"invalid filesystem or env vars\",\n printedMessage: `Failed to run function \"${args.functionName}\":\\n${chalkStderr.red(errorMessage)}`,\n });\n }\n\n args.callbacks?.onSuccess?.();\n\n // `null` is the default return type\n if (result !== null) {\n logOutput(formatValue(result));\n }\n}\n\nasync function getFakeIdentity(ctx: Context, identityString: string) {\n let identity: UserIdentityAttributes;\n try {\n identity = JSON5.parse(identityString);\n } catch (err) {\n return await ctx.crash({\n exitCode: 1,\n errorType: \"fatal\",\n printedMessage: `Failed to parse identity as JSON: \"${identityString}\"\\n${chalkStderr.red((err as Error).toString().trim())}`,\n });\n }\n const subject = identity.subject ?? \"\" + simpleHash(JSON.stringify(identity));\n const issuer = identity.issuer ?? \"https://convex.test\";\n const tokenIdentifier =\n identity.tokenIdentifier ?? `${issuer.toString()}|${subject.toString()}`;\n return {\n ...identity,\n subject,\n issuer,\n tokenIdentifier,\n };\n}\n\nexport async function parseArgs(ctx: Context, argsString: string) {\n try {\n const argsJson = JSON5.parse(argsString);\n return jsonToConvex(argsJson) as Record<string, Value>;\n } catch (err) {\n return await ctx.crash({\n exitCode: 1,\n errorType: \"invalid filesystem or env vars\",\n printedMessage: `Failed to parse arguments as JSON: \"${argsString}\"\\n${chalkStderr.red((err as Error).toString().trim())}`,\n });\n }\n}\n\nexport async function parseFunctionName(\n ctx: Context,\n functionName: string,\n // Usually `convex/` -- should contain trailing slash\n functionDirName: string,\n) {\n // api.foo.bar -> foo:bar\n // foo/bar -> foo/bar:default\n // foo/bar:baz -> foo/bar:baz\n // convex/foo/bar -> foo/bar:default\n\n // This is the `api.foo.bar` format\n if (functionName.startsWith(\"api.\") || functionName.startsWith(\"internal.\")) {\n const parts = functionName.split(\".\");\n if (parts.length < 3) {\n return await ctx.crash({\n exitCode: 1,\n errorType: \"fatal\",\n printedMessage: `Function name has too few parts: \"${functionName}\"`,\n });\n }\n const exportName = parts.pop();\n const parsedName = `${parts.slice(1).join(\"/\")}:${exportName}`;\n return parsedName;\n }\n\n // This is the `foo/bar:baz` format\n\n // This is something like `convex/foo/bar`, which could either be addressing `foo/bar:default` or `convex/foo/bar:default`\n // if there's a directory with the same name as the functions directory nested directly underneath.\n // We'll prefer the `convex/foo/bar:default` version, and check if the file exists, and otherwise treat this as a relative path from the project root.\n const filePath = functionName.split(\":\")[0];\n const possibleExtensions = [\n \".ts\",\n \".js\",\n \".tsx\",\n \".jsx\",\n \".mts\",\n \".mjs\",\n \".cts\",\n \".cjs\",\n ];\n let hasExtension = false;\n let normalizedFilePath: string = filePath;\n for (const extension of possibleExtensions) {\n if (filePath.endsWith(extension)) {\n normalizedFilePath = filePath.slice(0, -extension.length);\n hasExtension = true;\n break;\n }\n }\n\n const exportName = functionName.split(\":\")[1] ?? \"default\";\n const normalizedName = `${normalizedFilePath}:${exportName}`;\n\n // This isn't a relative path from the project root\n if (!filePath.startsWith(functionDirName)) {\n return normalizedName;\n }\n\n const filePathWithoutPrefix = normalizedFilePath.slice(\n functionDirName.length,\n );\n const functionNameWithoutPrefix = `${filePathWithoutPrefix}:${exportName}`;\n\n if (hasExtension) {\n if (ctx.fs.exists(path.join(functionDirName, filePath))) {\n return normalizedName;\n } else {\n return functionNameWithoutPrefix;\n }\n } else {\n const exists = possibleExtensions.some((extension) =>\n ctx.fs.exists(path.join(functionDirName, filePath + extension)),\n );\n if (exists) {\n return normalizedName;\n } else {\n return functionNameWithoutPrefix;\n }\n }\n}\n\nfunction simpleHash(string: string) {\n let hash = 0;\n for (let i = 0; i < string.length; i++) {\n const char = string.charCodeAt(i);\n hash = (hash << 5) - hash + char;\n hash = hash & hash; // Convert to 32bit integer\n }\n return hash;\n}\n\nexport async function runSystemPaginatedQuery(\n ctx: Context,\n args: {\n deploymentUrl: string;\n adminKey: string;\n functionName: string;\n componentPath: string | undefined;\n args: Record<string, Value>;\n limit?: number;\n },\n) {\n const results = [];\n let cursor = null;\n let isDone = false;\n while (!isDone && (args.limit === undefined || results.length < args.limit)) {\n const paginationResult = (await runSystemQuery(ctx, {\n ...args,\n args: {\n ...args.args,\n paginationOpts: {\n cursor,\n numItems:\n args.limit === undefined ? 10000 : args.limit - results.length,\n },\n },\n })) as unknown as PaginationResult<Record<string, Value>>;\n isDone = paginationResult.isDone;\n cursor = paginationResult.continueCursor;\n results.push(...paginationResult.page);\n }\n return results;\n}\n\nexport async function runSystemQuery(\n ctx: Context,\n args: {\n deploymentUrl: string;\n adminKey: string;\n functionName: string;\n componentPath: string | undefined;\n args: Record<string, Value>;\n },\n): Promise<Value> {\n let onResult: (result: Value) => void;\n const resultPromise = new Promise<Value>((resolve) => {\n onResult = resolve;\n });\n const [donePromise, onDone] = waitUntilCalled();\n await subscribe(ctx, {\n ...args,\n parsedFunctionName: args.functionName,\n parsedFunctionArgs: args.args,\n until: donePromise,\n callbacks: {\n onChange: (result) => {\n onDone();\n onResult(result);\n },\n },\n });\n return resultPromise;\n}\n\nexport function formatValue(value: Value) {\n const json = convexToJson(value);\n if (process.stdout.isTTY) {\n // TODO (Tom) add JSON syntax highlighting like https://stackoverflow.com/a/51319962/398212\n // until then, just spit out something that isn't quite JSON because it's easy\n return util.inspect(value, { colors: true, depth: null });\n } else {\n return JSON.stringify(json, null, 2);\n }\n}\n\nexport async function subscribeAndLog(\n ctx: Context,\n args: {\n deploymentUrl: string;\n adminKey: string;\n functionName: string;\n argsString: string;\n identityString?: string | undefined;\n componentPath: string | undefined;\n },\n) {\n const { projectConfig } = await readProjectConfig(ctx);\n\n const parsedFunctionName = await parseFunctionName(\n ctx,\n args.functionName,\n projectConfig.functions,\n );\n const identity = args.identityString\n ? await getFakeIdentity(ctx, args.identityString)\n : undefined;\n const functionArgs = await parseArgs(ctx, args.argsString);\n return subscribe(ctx, {\n deploymentUrl: args.deploymentUrl,\n adminKey: args.adminKey,\n identity,\n parsedFunctionName,\n parsedFunctionArgs: functionArgs,\n componentPath: args.componentPath,\n until: waitForever(),\n callbacks: {\n onStart() {\n logFinishedStep(\n `Watching query ${args.functionName} on ${args.deploymentUrl}...`,\n );\n },\n onChange(result) {\n logOutput(formatValue(result));\n },\n onStop() {\n logMessage(`Closing connection to ${args.deploymentUrl}...`);\n },\n },\n });\n}\n\nexport async function subscribe(\n ctx: Context,\n args: {\n deploymentUrl: string;\n adminKey: string;\n identity?: UserIdentityAttributes | undefined;\n parsedFunctionName: string;\n parsedFunctionArgs: Record<string, Value>;\n componentPath: string | undefined;\n until: Promise<unknown>;\n callbacks?:\n | {\n onStart?: () => void;\n onChange?: (result: Value) => void;\n onStop?: () => void;\n }\n | undefined;\n },\n) {\n const client = new BaseConvexClient(\n args.deploymentUrl,\n (updatedQueries) => {\n for (const queryToken of updatedQueries) {\n let result: Value;\n try {\n result = client.localQueryResultByToken(queryToken)!;\n } catch (err) {\n // A failed query (e.g. a permission error) throws here. Surface\n // permission errors cleanly instead of an uncaught stack trace, and\n // let any other error propagate as before.\n const permissionError = permissionDeniedErrorMessage(\n (err as Error).toString(),\n );\n if (permissionError !== null) {\n void ctx.crash({\n exitCode: 1,\n errorType: \"fatal\",\n printedMessage: chalkStderr.red(permissionError),\n });\n return;\n }\n // eslint-disable-next-line no-restricted-syntax\n throw err;\n }\n args.callbacks?.onChange?.(result);\n }\n },\n {\n // pretend that a Node.js 'ws' library WebSocket is a browser WebSocket\n webSocketConstructor: ws as unknown as typeof WebSocket,\n unsavedChangesWarning: false,\n },\n );\n client.setAdminAuth(args.adminKey, args.identity);\n const { unsubscribe } = client.subscribe(\n args.parsedFunctionName,\n args.parsedFunctionArgs,\n {\n componentPath: args.componentPath,\n },\n );\n\n args.callbacks?.onStart?.();\n\n let done = false;\n const [donePromise, onDone] = waitUntilCalled();\n const stopWatching = () => {\n if (done) {\n return;\n }\n done = true;\n unsubscribe();\n void client.close();\n process.off(\"SIGINT\", sigintListener);\n onDone();\n args.callbacks?.onStop?.();\n };\n function sigintListener() {\n stopWatching();\n }\n process.on(\"SIGINT\", sigintListener);\n void args.until.finally(stopWatching);\n while (!done) {\n // loops once per day (any large value < 2**31 would work)\n const oneDay = 24 * 60 * 60 * 1000;\n await Promise.race([\n donePromise,\n new Promise((resolve) => setTimeout(resolve, oneDay)),\n ]);\n }\n}\n\nexport async function runInDeployment(\n ctx: OneoffCtx,\n args: {\n deploymentUrl: string;\n adminKey: string;\n deploymentName: string | null;\n functionName: string;\n argsString: string;\n identityString?: string | undefined;\n push: boolean;\n watch: boolean;\n typecheck: \"enable\" | \"try\" | \"disable\";\n typecheckComponents: boolean;\n codegen: boolean;\n componentPath: string | undefined;\n liveComponentSources: boolean;\n },\n) {\n if (args.push) await pushToDeployment(ctx, args);\n\n if (args.watch) {\n return await subscribeAndLog(ctx, args);\n }\n return await runFunctionAndLog(ctx, args);\n}\n\nexport async function pushToDeployment(\n ctx: OneoffCtx,\n args: {\n deploymentUrl: string;\n adminKey: string;\n deploymentName: string | null;\n typecheck: \"enable\" | \"try\" | \"disable\";\n typecheckComponents: boolean;\n codegen: boolean;\n liveComponentSources: boolean;\n },\n) {\n await watchAndPush(\n ctx,\n {\n url: args.deploymentUrl,\n adminKey: args.adminKey,\n deploymentName: args.deploymentName,\n verbose: false,\n dryRun: false,\n typecheck: args.typecheck,\n typecheckComponents: args.typecheckComponents,\n debug: false,\n debugNodeApis: false,\n codegen: args.codegen,\n liveComponentSources: args.liveComponentSources,\n pushAllModules: false,\n largeIndexDeletionCheck: \"no verification\", // `convex run` can\u2019t push to prod\n message: null,\n },\n {\n once: true,\n traceEvents: false,\n untilSuccess: true,\n },\n );\n}\n\nfunction instantiateStderrLogger(): Logger {\n const logger = new DefaultLogger({ verbose: false });\n logger.addLogLineListener((_level, ...args) => {\n // eslint-disable-next-line no-console\n console.error(...args);\n });\n return logger;\n}\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAA4B;AAC5B,kBAAiB;AACjB,gBAAe;AACf,yBAAiC;AACjC,qBAAiC;AACjC,oBAIO;AACP,mBAAkD;AAElD,iBAAuD;AACvD,mBAIO;AACP,mBAAkB;AAClB,kBAAiB;AACjB,oBAAkC;AAClC,iBAA6B;AAC7B,qBAAsC;AAEtC,eAAsB,kBACpB,KACA,MAaA;AACA,QAAM,SAAS,IAAI,oCAAiB,KAAK,eAAe;AAAA,IACtD,QAAQ,wBAAwB;AAAA,EAClC,CAAC;AACD,QAAM,WAAW,KAAK,iBAClB,MAAM,gBAAgB,KAAK,KAAK,cAAc,IAC9C;AACJ,SAAO,aAAa,KAAK,UAAU,QAAQ;AAE3C,QAAM,eAAe,MAAM,UAAU,KAAK,KAAK,UAAU;AACzD,QAAM,EAAE,cAAc,IAAI,UAAM,iCAAkB,GAAG;AACrD,QAAM,qBAAqB,MAAM;AAAA,IAC/B;AAAA,IACA,KAAK;AAAA,IACL,cAAc;AAAA,EAChB;AACA,MAAI;AACJ,MAAI;AACF,aAAS,MAAM,OAAO;AAAA,UACpB,qCAAsB,kBAAkB;AAAA,MACxC,KAAK;AAAA,MACL;AAAA,IACF;AAAA,EACF,SAAS,KAAK;AACZ,UAAM,eAAgB,IAAc,SAAS,EAAE,KAAK;AAEpD,UAAM,sBAAkB,2CAA6B,YAAY;AACjE,QAAI,oBAAoB,MAAM;AAC5B,aAAO,MAAM,IAAI,MAAM;AAAA,QACrB,UAAU;AAAA,QACV,WAAW;AAAA,QACX,gBAAgB,yBAAY,IAAI,eAAe;AAAA,MACjD,CAAC;AAAA,IACH;AAEA,QAAI,aAAa,SAAS,yBAAyB,GAAG;AACpD,YAAM,YAAa,MAAM,eAAe,KAAK;AAAA,QAC3C,eAAe,KAAK;AAAA,QACpB,UAAU,KAAK;AAAA,QACf,cAAc;AAAA,QACd,eAAe,KAAK;AAAA,QACpB,MAAM,CAAC;AAAA,MACT,CAAC;AAUD,YAAM,gBAAgB,UACnB;AAAA,QACC,CACE,OAIG,GAAG,iBAAiB;AAAA,MAC3B,EACC,IAAI,CAAC,EAAE,WAAW,MAAM;AACvB,cAAM,eAAe,WAAW,QAAQ,GAAG;AAE3C,cAAMA,QACJ,iBAAiB,KACb,KACA,WAAW,UAAU,GAAG,YAAY,EAAE,QAAQ,SAAS,EAAE;AAC/D,cAAM,OACJ,iBAAiB,KACb,aACA,WAAW,UAAU,eAAe,CAAC;AAE3C,eAAO,UAAK,yBAAY,KAAK,GAAGA,KAAI,GAAG,CAAC,GAAG,IAAI;AAAA,MACjD,CAAC;AAEH,YAAM,4BACJ,cAAc,SAAS,IACnB;AAAA,EAAyB,cAAc,KAAK,IAAI,CAAC,KACjD;AAEN,aAAO,MAAM,IAAI,MAAM;AAAA,QACrB,UAAU;AAAA,QACV,WAAW;AAAA,QACX,gBAAgB,2BAA2B,KAAK,YAAY;AAAA,EAAO,yBAAY,IAAI,YAAY,CAAC;AAAA;AAAA,EAAO,yBAAyB;AAAA,MAClI,CAAC;AAAA,IACH;AAEA,WAAO,MAAM,IAAI,MAAM;AAAA,MACrB,UAAU;AAAA,MACV,WAAW;AAAA,MACX,gBAAgB,2BAA2B,KAAK,YAAY;AAAA,EAAO,yBAAY,IAAI,YAAY,CAAC;AAAA,IAClG,CAAC;AAAA,EACH;AAEA,OAAK,WAAW,YAAY;AAG5B,MAAI,WAAW,MAAM;AACnB,8BAAU,YAAY,MAAM,CAAC;AAAA,EAC/B;AACF;AAEA,eAAe,gBAAgB,KAAc,gBAAwB;AACnE,MAAI;AACJ,MAAI;AACF,eAAW,aAAAC,QAAM,MAAM,cAAc;AAAA,EACvC,SAAS,KAAK;AACZ,WAAO,MAAM,IAAI,MAAM;AAAA,MACrB,UAAU;AAAA,MACV,WAAW;AAAA,MACX,gBAAgB,sCAAsC,cAAc;AAAA,EAAM,yBAAY,IAAK,IAAc,SAAS,EAAE,KAAK,CAAC,CAAC;AAAA,IAC7H,CAAC;AAAA,EACH;AACA,QAAM,UAAU,SAAS,WAAW,KAAK,WAAW,KAAK,UAAU,QAAQ,CAAC;AAC5E,QAAM,SAAS,SAAS,UAAU;AAClC,QAAM,kBACJ,SAAS,mBAAmB,GAAG,OAAO,SAAS,CAAC,IAAI,QAAQ,SAAS,CAAC;AACxE,SAAO;AAAA,IACL,GAAG;AAAA,IACH;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAEA,eAAsB,UAAU,KAAc,YAAoB;AAChE,MAAI;AACF,UAAM,WAAW,aAAAA,QAAM,MAAM,UAAU;AACvC,eAAO,2BAAa,QAAQ;AAAA,EAC9B,SAAS,KAAK;AACZ,WAAO,MAAM,IAAI,MAAM;AAAA,MACrB,UAAU;AAAA,MACV,WAAW;AAAA,MACX,gBAAgB,uCAAuC,UAAU;AAAA,EAAM,yBAAY,IAAK,IAAc,SAAS,EAAE,KAAK,CAAC,CAAC;AAAA,IAC1H,CAAC;AAAA,EACH;AACF;AAEA,eAAsB,kBACpB,KACA,cAEA,iBACA;AAOA,MAAI,aAAa,WAAW,MAAM,KAAK,aAAa,WAAW,WAAW,GAAG;AAC3E,UAAM,QAAQ,aAAa,MAAM,GAAG;AACpC,QAAI,MAAM,SAAS,GAAG;AACpB,aAAO,MAAM,IAAI,MAAM;AAAA,QACrB,UAAU;AAAA,QACV,WAAW;AAAA,QACX,gBAAgB,qCAAqC,YAAY;AAAA,MACnE,CAAC;AAAA,IACH;AACA,UAAMC,cAAa,MAAM,IAAI;AAC7B,UAAM,aAAa,GAAG,MAAM,MAAM,CAAC,EAAE,KAAK,GAAG,CAAC,IAAIA,WAAU;AAC5D,WAAO;AAAA,EACT;AAOA,QAAM,WAAW,aAAa,MAAM,GAAG,EAAE,CAAC;AAC1C,QAAM,qBAAqB;AAAA,IACzB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACA,MAAI,eAAe;AACnB,MAAI,qBAA6B;AACjC,aAAW,aAAa,oBAAoB;AAC1C,QAAI,SAAS,SAAS,SAAS,GAAG;AAChC,2BAAqB,SAAS,MAAM,GAAG,CAAC,UAAU,MAAM;AACxD,qBAAe;AACf;AAAA,IACF;AAAA,EACF;AAEA,QAAM,aAAa,aAAa,MAAM,GAAG,EAAE,CAAC,KAAK;AACjD,QAAM,iBAAiB,GAAG,kBAAkB,IAAI,UAAU;AAG1D,MAAI,CAAC,SAAS,WAAW,eAAe,GAAG;AACzC,WAAO;AAAA,EACT;AAEA,QAAM,wBAAwB,mBAAmB;AAAA,IAC/C,gBAAgB;AAAA,EAClB;AACA,QAAM,4BAA4B,GAAG,qBAAqB,IAAI,UAAU;AAExE,MAAI,cAAc;AAChB,QAAI,IAAI,GAAG,OAAO,YAAAF,QAAK,KAAK,iBAAiB,QAAQ,CAAC,GAAG;AACvD,aAAO;AAAA,IACT,OAAO;AACL,aAAO;AAAA,IACT;AAAA,EACF,OAAO;AACL,UAAM,SAAS,mBAAmB;AAAA,MAAK,CAAC,cACtC,IAAI,GAAG,OAAO,YAAAA,QAAK,KAAK,iBAAiB,WAAW,SAAS,CAAC;AAAA,IAChE;AACA,QAAI,QAAQ;AACV,aAAO;AAAA,IACT,OAAO;AACL,aAAO;AAAA,IACT;AAAA,EACF;AACF;AAEA,SAAS,WAAW,QAAgB;AAClC,MAAI,OAAO;AACX,WAAS,IAAI,GAAG,IAAI,OAAO,QAAQ,KAAK;AACtC,UAAM,OAAO,OAAO,WAAW,CAAC;AAChC,YAAQ,QAAQ,KAAK,OAAO;AAC5B,WAAO,OAAO;AAAA,EAChB;AACA,SAAO;AACT;AAEA,eAAsB,wBACpB,KACA,MAQA;AACA,QAAM,UAAU,CAAC;AACjB,MAAI,SAAS;AACb,MAAI,SAAS;AACb,SAAO,CAAC,WAAW,KAAK,UAAU,UAAa,QAAQ,SAAS,KAAK,QAAQ;AAC3E,UAAM,mBAAoB,MAAM,eAAe,KAAK;AAAA,MAClD,GAAG;AAAA,MACH,MAAM;AAAA,QACJ,GAAG,KAAK;AAAA,QACR,gBAAgB;AAAA,UACd;AAAA,UACA,UACE,KAAK,UAAU,SAAY,MAAQ,KAAK,QAAQ,QAAQ;AAAA,QAC5D;AAAA,MACF;AAAA,IACF,CAAC;AACD,aAAS,iBAAiB;AAC1B,aAAS,iBAAiB;AAC1B,YAAQ,KAAK,GAAG,iBAAiB,IAAI;AAAA,EACvC;AACA,SAAO;AACT;AAEA,eAAsB,eACpB,KACA,MAOgB;AAChB,MAAI;AACJ,QAAM,gBAAgB,IAAI,QAAe,CAAC,YAAY;AACpD,eAAW;AAAA,EACb,CAAC;AACD,QAAM,CAAC,aAAa,MAAM,QAAI,8BAAgB;AAC9C,QAAM,UAAU,KAAK;AAAA,IACnB,GAAG;AAAA,IACH,oBAAoB,KAAK;AAAA,IACzB,oBAAoB,KAAK;AAAA,IACzB,OAAO;AAAA,IACP,WAAW;AAAA,MACT,UAAU,CAAC,WAAW;AACpB,eAAO;AACP,iBAAS,MAAM;AAAA,MACjB;AAAA,IACF;AAAA,EACF,CAAC;AACD,SAAO;AACT;AAEO,SAAS,YAAY,OAAc;AACxC,QAAM,WAAO,2BAAa,KAAK;AAC/B,MAAI,QAAQ,OAAO,OAAO;AAGxB,WAAO,YAAAG,QAAK,QAAQ,OAAO,EAAE,QAAQ,MAAM,OAAO,KAAK,CAAC;AAAA,EAC1D,OAAO;AACL,WAAO,KAAK,UAAU,MAAM,MAAM,CAAC;AAAA,EACrC;AACF;AAEA,eAAsB,gBACpB,KACA,MAQA;AACA,QAAM,EAAE,cAAc,IAAI,UAAM,iCAAkB,GAAG;AAErD,QAAM,qBAAqB,MAAM;AAAA,IAC/B;AAAA,IACA,KAAK;AAAA,IACL,cAAc;AAAA,EAChB;AACA,QAAM,WAAW,KAAK,iBAClB,MAAM,gBAAgB,KAAK,KAAK,cAAc,IAC9C;AACJ,QAAM,eAAe,MAAM,UAAU,KAAK,KAAK,UAAU;AACzD,SAAO,UAAU,KAAK;AAAA,IACpB,eAAe,KAAK;AAAA,IACpB,UAAU,KAAK;AAAA,IACf;AAAA,IACA;AAAA,IACA,oBAAoB;AAAA,IACpB,eAAe,KAAK;AAAA,IACpB,WAAO,0BAAY;AAAA,IACnB,WAAW;AAAA,MACT,UAAU;AACR;AAAA,UACE,kBAAkB,KAAK,YAAY,OAAO,KAAK,aAAa;AAAA,QAC9D;AAAA,MACF;AAAA,MACA,SAAS,QAAQ;AACf,kCAAU,YAAY,MAAM,CAAC;AAAA,MAC/B;AAAA,MACA,SAAS;AACP,mCAAW,yBAAyB,KAAK,aAAa,KAAK;AAAA,MAC7D;AAAA,IACF;AAAA,EACF,CAAC;AACH;AAEA,eAAsB,UACpB,KACA,MAgBA;AACA,QAAM,SAAS,IAAI;AAAA,IACjB,KAAK;AAAA,IACL,CAAC,mBAAmB;AAClB,iBAAW,cAAc,gBAAgB;AACvC,YAAI;AACJ,YAAI;AACF,mBAAS,OAAO,wBAAwB,UAAU;AAAA,QACpD,SAAS,KAAK;AAIZ,gBAAM,sBAAkB;AAAA,YACrB,IAAc,SAAS;AAAA,UAC1B;AACA,cAAI,oBAAoB,MAAM;AAC5B,iBAAK,IAAI,MAAM;AAAA,cACb,UAAU;AAAA,cACV,WAAW;AAAA,cACX,gBAAgB,yBAAY,IAAI,eAAe;AAAA,YACjD,CAAC;AACD;AAAA,UACF;AAEA,gBAAM;AAAA,QACR;AACA,aAAK,WAAW,WAAW,MAAM;AAAA,MACnC;AAAA,IACF;AAAA,IACA;AAAA;AAAA,MAEE,sBAAsB,UAAAC;AAAA,MACtB,uBAAuB;AAAA,IACzB;AAAA,EACF;AACA,SAAO,aAAa,KAAK,UAAU,KAAK,QAAQ;AAChD,QAAM,EAAE,YAAY,IAAI,OAAO;AAAA,IAC7B,KAAK;AAAA,IACL,KAAK;AAAA,IACL;AAAA,MACE,eAAe,KAAK;AAAA,IACtB;AAAA,EACF;AAEA,OAAK,WAAW,UAAU;AAE1B,MAAI,OAAO;AACX,QAAM,CAAC,aAAa,MAAM,QAAI,8BAAgB;AAC9C,QAAM,eAAe,MAAM;AACzB,QAAI,MAAM;AACR;AAAA,IACF;AACA,WAAO;AACP,gBAAY;AACZ,SAAK,OAAO,MAAM;AAClB,YAAQ,IAAI,UAAU,cAAc;AACpC,WAAO;AACP,SAAK,WAAW,SAAS;AAAA,EAC3B;AACA,WAAS,iBAAiB;AACxB,iBAAa;AAAA,EACf;AACA,UAAQ,GAAG,UAAU,cAAc;AACnC,OAAK,KAAK,MAAM,QAAQ,YAAY;AACpC,SAAO,CAAC,MAAM;AAEZ,UAAM,SAAS,KAAK,KAAK,KAAK;AAC9B,UAAM,QAAQ,KAAK;AAAA,MACjB;AAAA,MACA,IAAI,QAAQ,CAAC,YAAY,WAAW,SAAS,MAAM,CAAC;AAAA,IACtD,CAAC;AAAA,EACH;AACF;AAEA,eAAsB,gBACpB,KACA,MAeA;AACA,MAAI,KAAK,KAAM,OAAM,iBAAiB,KAAK,IAAI;AAE/C,MAAI,KAAK,OAAO;AACd,WAAO,MAAM,gBAAgB,KAAK,IAAI;AAAA,EACxC;AACA,SAAO,MAAM,kBAAkB,KAAK,IAAI;AAC1C;AAEA,eAAsB,iBACpB,KACA,MASA;AACA,YAAM;AAAA,IACJ;AAAA,IACA;AAAA,MACE,KAAK,KAAK;AAAA,MACV,UAAU,KAAK;AAAA,MACf,gBAAgB,KAAK;AAAA,MACrB,SAAS;AAAA,MACT,QAAQ;AAAA,MACR,WAAW,KAAK;AAAA,MAChB,qBAAqB,KAAK;AAAA,MAC1B,OAAO;AAAA,MACP,eAAe;AAAA,MACf,SAAS,KAAK;AAAA,MACd,sBAAsB,KAAK;AAAA,MAC3B,gBAAgB;AAAA,MAChB,yBAAyB;AAAA;AAAA,MACzB,SAAS;AAAA,IACX;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,aAAa;AAAA,MACb,cAAc;AAAA,IAChB;AAAA,EACF;AACF;AAEA,SAAS,0BAAkC;AACzC,QAAM,SAAS,IAAI,6BAAc,EAAE,SAAS,MAAM,CAAC;AACnD,SAAO,mBAAmB,CAAC,WAAW,SAAS;AAE7C,YAAQ,MAAM,GAAG,IAAI;AAAA,EACvB,CAAC;AACD,SAAO;AACT;",
6
6
  "names": ["path", "JSON5", "exportName", "util", "ws"]
7
7
  }
@@ -110,14 +110,32 @@ async function typeCheckFunctions(ctx, typescriptCompiler, functionsDir, handleR
110
110
  );
111
111
  }
112
112
  async function runTsc(ctx, typescriptCompiler, tscArgs, handleResult) {
113
- const tscPath = typescriptCompiler === "tsgo" ? import_path.default.join(
114
- "node_modules",
115
- "@typescript",
116
- "native-preview",
117
- "bin",
118
- "tsgo.js"
119
- ) : import_path.default.join("node_modules", "typescript", "bin", "tsc");
120
- if (!ctx.fs.exists(tscPath)) {
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
+ }
138
+ if (!compilerPath) {
121
139
  return handleResult("cantTypeCheck", () => {
122
140
  (0, import_log.logError)(
123
141
  import_chalk.chalkStderr.gray(
@@ -127,12 +145,12 @@ async function runTsc(ctx, typescriptCompiler, tscArgs, handleResult) {
127
145
  });
128
146
  }
129
147
  const versionResult = await (0, import_utils.spawnAsync)(ctx, process.execPath, [
130
- tscPath,
148
+ compilerPath,
131
149
  "--version"
132
150
  ]);
133
151
  const version = versionResult.stdout.match(/Version (.*)/)?.[1] ?? null;
134
152
  const hasOlderTypeScriptVersion = version && semver.lt(version, "4.8.4");
135
- await runTscInner(ctx, tscPath, tscArgs, handleResult);
153
+ await runTscInner(ctx, compilerPath, tscArgs, handleResult);
136
154
  if (hasOlderTypeScriptVersion) {
137
155
  (0, import_log.logError)(
138
156
  import_chalk.chalkStderr.yellow(
@@ -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 tsc is even installed\n const tscPath =\n typescriptCompiler === \"tsgo\"\n ? path.join(\n \"node_modules\",\n \"@typescript\",\n \"native-preview\",\n \"bin\",\n \"tsgo.js\",\n )\n : path.join(\"node_modules\", \"typescript\", \"bin\", \"tsc\");\n if (!ctx.fs.exists(tscPath)) {\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 tscPath,\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, tscPath, 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\";\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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",
6
6
  "names": ["result", "path"]
7
7
  }
@@ -62,6 +62,7 @@ __export(utils_exports, {
62
62
  logNoDefaultRegionMessage: () => logNoDefaultRegionMessage,
63
63
  parseInteger: () => parseInteger,
64
64
  parsePositiveInteger: () => parsePositiveInteger,
65
+ permissionDeniedErrorMessage: () => permissionDeniedErrorMessage,
65
66
  poll: () => poll,
66
67
  processDeployKeyValue: () => processDeployKeyValue,
67
68
  productionProvisionHost: () => productionProvisionHost,
@@ -131,6 +132,27 @@ function readDeployKeyFromEnv(getEnv) {
131
132
  const fromToken = getEnv(CONVEX_DEPLOYMENT_TOKEN_ENV_VAR_NAME);
132
133
  return fromDeployKey || fromToken || void 0;
133
134
  }
135
+ const PERMISSION_DENIED_MESSAGE_PREFIX = "You do not have permission to perform this operation";
136
+ function deployKeyPermissionAdvice() {
137
+ const envVarName = process.env[CONVEX_DEPLOY_KEY_ENV_VAR_NAME] ? CONVEX_DEPLOY_KEY_ENV_VAR_NAME : process.env[CONVEX_DEPLOYMENT_TOKEN_ENV_VAR_NAME] ? CONVEX_DEPLOYMENT_TOKEN_ENV_VAR_NAME : null;
138
+ if (envVarName === null) {
139
+ return null;
140
+ }
141
+ return `This is determined by the permissions granted to ${envVarName}.`;
142
+ }
143
+ function permissionDeniedErrorMessage(errorMessage) {
144
+ const index = errorMessage.indexOf(PERMISSION_DENIED_MESSAGE_PREFIX);
145
+ if (index === -1) {
146
+ return null;
147
+ }
148
+ let msg = errorMessage.slice(index).split("\n")[0].trim();
149
+ const advice = deployKeyPermissionAdvice();
150
+ if (advice) {
151
+ msg = `${msg}
152
+ ${advice}`;
153
+ }
154
+ return msg;
155
+ }
134
156
  function parsePositiveInteger(value) {
135
157
  const parsedValue = parseInteger(value);
136
158
  if (parsedValue <= 0) {
@@ -185,6 +207,14 @@ class ThrowingFetchError extends Error {
185
207
  error_type = "fatal";
186
208
  msg = `${msg}
187
209
  Authenticate with \`npx convex dev\``;
210
+ } else if (this.response.status === 403) {
211
+ error_type = "fatal";
212
+ msg = this.serverErrorData?.message ?? msg;
213
+ const advice = deployKeyPermissionAdvice();
214
+ if (advice) {
215
+ msg = `${msg}
216
+ ${advice}`;
217
+ }
188
218
  } else if (this.response.status === 404) {
189
219
  error_type = "fatal";
190
220
  msg = `${msg}: ${this.response.url}`;