@samebase/convex-hosting 0.3.1 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (193) hide show
  1. package/CHANGELOG.md +10 -128
  2. package/README.md +136 -398
  3. package/dist/cli/convex.d.ts +63 -0
  4. package/dist/cli/convex.js +108 -0
  5. package/dist/cli/convex.js.map +1 -0
  6. package/dist/cli/files.d.ts +18 -0
  7. package/dist/cli/files.js +106 -0
  8. package/dist/cli/files.js.map +1 -0
  9. package/dist/cli/index.d.ts +1 -11
  10. package/dist/cli/index.js +3 -58
  11. package/dist/cli/index.js.map +1 -1
  12. package/dist/cli/main.d.ts +5 -0
  13. package/dist/cli/main.js +346 -0
  14. package/dist/cli/main.js.map +1 -0
  15. package/dist/client/index.d.ts +8 -115
  16. package/dist/client/index.js +65 -254
  17. package/dist/client/index.js.map +1 -1
  18. package/dist/client/types.d.ts +5 -0
  19. package/dist/client/version-module.d.ts +6 -0
  20. package/dist/component/_generated/api.d.ts +0 -5
  21. package/dist/component/_generated/api.js.map +1 -1
  22. package/dist/component/_generated/component.d.ts +20 -18
  23. package/dist/component/_generated/dataModel.d.ts +0 -1
  24. package/dist/component/_generated/server.d.ts +12 -1
  25. package/dist/component/_generated/server.js +2 -0
  26. package/dist/component/_generated/server.js.map +1 -1
  27. package/dist/component/convex.config.d.ts +0 -1
  28. package/dist/component/lib.d.ts +175 -156
  29. package/dist/component/lib.js +396 -710
  30. package/dist/component/lib.js.map +1 -1
  31. package/dist/component/schema.d.ts +76 -72
  32. package/dist/component/schema.js +35 -59
  33. package/dist/component/schema.js.map +1 -1
  34. package/dist/workers-shared/asset-worker/src/analytics.d.ts +39 -0
  35. package/dist/workers-shared/asset-worker/src/analytics.js +86 -0
  36. package/dist/workers-shared/asset-worker/src/analytics.js.map +1 -0
  37. package/dist/workers-shared/asset-worker/src/compatibility-flags.d.ts +19 -0
  38. package/dist/workers-shared/asset-worker/src/compatibility-flags.js +29 -0
  39. package/dist/workers-shared/asset-worker/src/compatibility-flags.js.map +1 -0
  40. package/dist/workers-shared/asset-worker/src/configuration.d.ts +3 -0
  41. package/dist/workers-shared/asset-worker/src/configuration.js +30 -0
  42. package/dist/workers-shared/asset-worker/src/configuration.js.map +1 -0
  43. package/dist/workers-shared/asset-worker/src/constants.d.ts +1 -0
  44. package/dist/workers-shared/asset-worker/src/constants.js +3 -0
  45. package/dist/workers-shared/asset-worker/src/constants.js.map +1 -0
  46. package/dist/workers-shared/asset-worker/src/handler.d.ts +28 -0
  47. package/dist/workers-shared/asset-worker/src/handler.js +717 -0
  48. package/dist/workers-shared/asset-worker/src/handler.js.map +1 -0
  49. package/dist/workers-shared/asset-worker/src/types.d.ts +13 -0
  50. package/dist/workers-shared/asset-worker/src/types.js +2 -0
  51. package/dist/workers-shared/asset-worker/src/types.js.map +1 -0
  52. package/dist/workers-shared/asset-worker/src/utils/base-path.d.ts +29 -0
  53. package/dist/workers-shared/asset-worker/src/utils/base-path.js +56 -0
  54. package/dist/workers-shared/asset-worker/src/utils/base-path.js.map +1 -0
  55. package/dist/workers-shared/asset-worker/src/utils/headers.d.ts +11 -0
  56. package/dist/workers-shared/asset-worker/src/utils/headers.js +77 -0
  57. package/dist/workers-shared/asset-worker/src/utils/headers.js.map +1 -0
  58. package/dist/workers-shared/asset-worker/src/utils/rules-engine.d.ts +23 -0
  59. package/dist/workers-shared/asset-worker/src/utils/rules-engine.js +133 -0
  60. package/dist/workers-shared/asset-worker/src/utils/rules-engine.js.map +1 -0
  61. package/dist/workers-shared/asset-worker/src/worker.d.ts +14 -0
  62. package/dist/workers-shared/asset-worker/src/worker.js +12 -0
  63. package/dist/workers-shared/asset-worker/src/worker.js.map +1 -0
  64. package/dist/workers-shared/utils/base-path.d.ts +32 -0
  65. package/dist/workers-shared/utils/base-path.js +94 -0
  66. package/dist/workers-shared/utils/base-path.js.map +1 -0
  67. package/dist/workers-shared/utils/configuration/constants.d.ts +15 -0
  68. package/dist/workers-shared/utils/configuration/constants.js +16 -0
  69. package/dist/workers-shared/utils/configuration/constants.js.map +1 -0
  70. package/dist/workers-shared/utils/configuration/constructConfiguration.d.ts +12 -0
  71. package/dist/workers-shared/utils/configuration/constructConfiguration.js +103 -0
  72. package/dist/workers-shared/utils/configuration/constructConfiguration.js.map +1 -0
  73. package/dist/workers-shared/utils/configuration/parseHeaders.d.ts +5 -0
  74. package/dist/workers-shared/utils/configuration/parseHeaders.js +181 -0
  75. package/dist/workers-shared/utils/configuration/parseHeaders.js.map +1 -0
  76. package/dist/workers-shared/utils/configuration/parseRedirects.d.ts +8 -0
  77. package/dist/workers-shared/utils/configuration/parseRedirects.js +129 -0
  78. package/dist/workers-shared/utils/configuration/parseRedirects.js.map +1 -0
  79. package/dist/workers-shared/utils/configuration/parseStaticRouting.d.ts +2 -0
  80. package/dist/workers-shared/utils/configuration/parseStaticRouting.js +94 -0
  81. package/dist/workers-shared/utils/configuration/parseStaticRouting.js.map +1 -0
  82. package/dist/workers-shared/utils/configuration/types.d.ts +38 -0
  83. package/dist/workers-shared/utils/configuration/types.js +2 -0
  84. package/dist/workers-shared/utils/configuration/types.js.map +1 -0
  85. package/dist/workers-shared/utils/configuration/validateURL.d.ts +3 -0
  86. package/dist/workers-shared/utils/configuration/validateURL.js +56 -0
  87. package/dist/workers-shared/utils/configuration/validateURL.js.map +1 -0
  88. package/dist/workers-shared/utils/constants.d.ts +28 -0
  89. package/dist/workers-shared/utils/constants.js +34 -0
  90. package/dist/workers-shared/utils/constants.js.map +1 -0
  91. package/dist/workers-shared/utils/helpers.d.ts +22 -0
  92. package/dist/workers-shared/utils/helpers.js +73 -0
  93. package/dist/workers-shared/utils/helpers.js.map +1 -0
  94. package/dist/workers-shared/utils/responses.d.ts +43 -0
  95. package/dist/workers-shared/utils/responses.js +125 -0
  96. package/dist/workers-shared/utils/responses.js.map +1 -0
  97. package/dist/workers-shared/utils/tracing.d.ts +3 -0
  98. package/dist/workers-shared/utils/tracing.js +29 -0
  99. package/dist/workers-shared/utils/tracing.js.map +1 -0
  100. package/dist/workers-shared/utils/types.d.ts +131 -0
  101. package/dist/workers-shared/utils/types.js +72 -0
  102. package/dist/workers-shared/utils/types.js.map +1 -0
  103. package/package.json +16 -32
  104. package/INTEGRATION.md +0 -399
  105. package/dist/cli/args.d.ts +0 -28
  106. package/dist/cli/args.d.ts.map +0 -1
  107. package/dist/cli/args.js +0 -148
  108. package/dist/cli/args.js.map +0 -1
  109. package/dist/cli/argumentChunks.d.ts +0 -3
  110. package/dist/cli/argumentChunks.d.ts.map +0 -1
  111. package/dist/cli/argumentChunks.js +0 -29
  112. package/dist/cli/argumentChunks.js.map +0 -1
  113. package/dist/cli/collectFiles.d.ts +0 -10
  114. package/dist/cli/collectFiles.d.ts.map +0 -1
  115. package/dist/cli/collectFiles.js +0 -53
  116. package/dist/cli/collectFiles.js.map +0 -1
  117. package/dist/cli/commands.d.ts +0 -8
  118. package/dist/cli/commands.d.ts.map +0 -1
  119. package/dist/cli/commands.js +0 -56
  120. package/dist/cli/commands.js.map +0 -1
  121. package/dist/cli/componentName.d.ts +0 -32
  122. package/dist/cli/componentName.d.ts.map +0 -1
  123. package/dist/cli/componentName.js +0 -43
  124. package/dist/cli/componentName.js.map +0 -1
  125. package/dist/cli/deploy.d.ts +0 -16
  126. package/dist/cli/deploy.d.ts.map +0 -1
  127. package/dist/cli/deploy.js +0 -283
  128. package/dist/cli/deploy.js.map +0 -1
  129. package/dist/cli/deployEnvironment.d.ts +0 -10
  130. package/dist/cli/deployEnvironment.d.ts.map +0 -1
  131. package/dist/cli/deployEnvironment.js +0 -12
  132. package/dist/cli/deployEnvironment.js.map +0 -1
  133. package/dist/cli/index.d.ts.map +0 -1
  134. package/dist/cli/upload.d.ts +0 -22
  135. package/dist/cli/upload.d.ts.map +0 -1
  136. package/dist/cli/upload.js +0 -630
  137. package/dist/cli/upload.js.map +0 -1
  138. package/dist/client/_generated/_ignore.d.ts +0 -1
  139. package/dist/client/_generated/_ignore.d.ts.map +0 -1
  140. package/dist/client/_generated/_ignore.js +0 -3
  141. package/dist/client/_generated/_ignore.js.map +0 -1
  142. package/dist/client/index.d.ts.map +0 -1
  143. package/dist/component/_generated/api.d.ts.map +0 -1
  144. package/dist/component/_generated/component.d.ts.map +0 -1
  145. package/dist/component/_generated/dataModel.d.ts.map +0 -1
  146. package/dist/component/_generated/server.d.ts.map +0 -1
  147. package/dist/component/convex.config.d.ts.map +0 -1
  148. package/dist/component/http.d.ts +0 -4
  149. package/dist/component/http.d.ts.map +0 -1
  150. package/dist/component/http.js +0 -125
  151. package/dist/component/http.js.map +0 -1
  152. package/dist/component/lib.d.ts.map +0 -1
  153. package/dist/component/schema.d.ts.map +0 -1
  154. package/dist/component/serving.d.ts +0 -17
  155. package/dist/component/serving.d.ts.map +0 -1
  156. package/dist/component/serving.js +0 -150
  157. package/dist/component/serving.js.map +0 -1
  158. package/dist/react/index.d.ts +0 -59
  159. package/dist/react/index.d.ts.map +0 -1
  160. package/dist/react/index.js +0 -137
  161. package/dist/react/index.js.map +0 -1
  162. package/src/cli/args.test.ts +0 -79
  163. package/src/cli/args.ts +0 -153
  164. package/src/cli/argumentChunks.test.ts +0 -27
  165. package/src/cli/argumentChunks.ts +0 -40
  166. package/src/cli/collectFiles.test.ts +0 -26
  167. package/src/cli/collectFiles.ts +0 -59
  168. package/src/cli/commands.ts +0 -68
  169. package/src/cli/componentName.test.ts +0 -41
  170. package/src/cli/componentName.ts +0 -46
  171. package/src/cli/deploy.ts +0 -336
  172. package/src/cli/deployEnvironment.test.ts +0 -27
  173. package/src/cli/deployEnvironment.ts +0 -17
  174. package/src/cli/index.ts +0 -65
  175. package/src/cli/upload.ts +0 -837
  176. package/src/client/_generated/_ignore.ts +0 -1
  177. package/src/client/index.test.ts +0 -510
  178. package/src/client/index.ts +0 -355
  179. package/src/client/setup.test.ts +0 -22
  180. package/src/component/_generated/api.ts +0 -54
  181. package/src/component/_generated/component.ts +0 -55
  182. package/src/component/_generated/dataModel.ts +0 -60
  183. package/src/component/_generated/server.ts +0 -156
  184. package/src/component/convex.config.ts +0 -3
  185. package/src/component/http.test.ts +0 -223
  186. package/src/component/http.ts +0 -144
  187. package/src/component/lib.test.ts +0 -1007
  188. package/src/component/lib.ts +0 -862
  189. package/src/component/schema.ts +0 -75
  190. package/src/component/serving.ts +0 -158
  191. package/src/component/setup.test.ts +0 -11
  192. package/src/react/index.tsx +0 -197
  193. package/src/test.ts +0 -23
@@ -0,0 +1,346 @@
1
+ import { randomUUID } from "node:crypto";
2
+ import { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
3
+ import { join, resolve } from "node:path";
4
+ import { fileURLToPath } from "node:url";
5
+ import { parseArgs } from "node:util";
6
+ import { z } from "zod";
7
+ import { internal } from "../component/_generated/api.js";
8
+ import { AssetConfigSchema } from "../workers-shared/utils/types.js";
9
+ import { deploymentSelector, probeComponent, runComponent, } from "./convex.js";
10
+ import { readDist } from "./files.js";
11
+ const USAGE = `Usage:
12
+ convex-hosting deploy --build "<command>" --dist <dir> [options]
13
+
14
+ Options:
15
+ --dev the development deployment of this checkout, instead of production
16
+ --preview-name <name> the preview deployment with this name, instead of production
17
+ --html-handling <value> auto-trailing-slash (default), force-trailing-slash,
18
+ drop-trailing-slash, or none
19
+ --not-found-handling <value> none (default), single-page-application, or 404-page
20
+ --component <name> the component instance (default: hosting)
21
+ -h, --help this text`;
22
+ /**
23
+ * The CLI's state folder at the project root, like Wrangler's `.wrangler/`. It holds its own
24
+ * `.gitignore`, so git ignores it without a line in the app's ignore file.
25
+ */
26
+ const STATE_DIR = ".convex-hosting";
27
+ /** The file that the upload writes and the app's `convex/http.ts` imports. */
28
+ export const VERSION_FILE = join(STATE_DIR, "version.js");
29
+ /**
30
+ * The inner `upload` of a first install writes this file when the component is not installed yet.
31
+ * `deploy` then uploads after the push.
32
+ */
33
+ const FIRST_INSTALL_MARKER = join(STATE_DIR, "first-install");
34
+ /** Files that the upload sends to storage at once. */
35
+ const UPLOAD_CONCURRENCY = 4;
36
+ /**
37
+ * Files per page of uploads. A page's upload URLs are made together, and its entries are recorded
38
+ * before the next page starts, so a retry after a crash reuses them.
39
+ */
40
+ const UPLOAD_PAGE = 100;
41
+ /**
42
+ * `npx convex run` passes the arguments on the command line, which Windows limits to 32,767
43
+ * characters; `knownFiles` and `recordFiles` calls stay well below that. The component counts
44
+ * what a call of this length reads and writes.
45
+ */
46
+ const MAX_ARGUMENT_LENGTH = 8_000;
47
+ const htmlHandlingSchema = AssetConfigSchema.shape.html_handling.unwrap();
48
+ const notFoundHandlingSchema = AssetConfigSchema.shape.not_found_handling.unwrap();
49
+ function parseCommand(args) {
50
+ const { values, positionals } = parseArgs({
51
+ args,
52
+ allowPositionals: true,
53
+ strict: true,
54
+ options: {
55
+ build: { type: "string" },
56
+ dist: { type: "string" },
57
+ dev: { type: "boolean", default: false },
58
+ "preview-name": { type: "string" },
59
+ "html-handling": { type: "string", default: "auto-trailing-slash" },
60
+ "not-found-handling": { type: "string", default: "none" },
61
+ component: { type: "string", default: "hosting" },
62
+ "version-id": { type: "string" },
63
+ help: { type: "boolean", short: "h", default: false },
64
+ },
65
+ });
66
+ if (args.length === 0 || values.help)
67
+ return { name: "help" };
68
+ const [name, ...rest] = positionals;
69
+ if ((name !== "deploy" && name !== "upload") || rest.length > 0)
70
+ throw new Error(USAGE);
71
+ if (values.dist === undefined)
72
+ throw new Error(`--dist is required.\n\n${USAGE}`);
73
+ if (values.dev && values["preview-name"] !== undefined) {
74
+ throw new Error("--dev and --preview-name exclude each other.");
75
+ }
76
+ const htmlHandling = htmlHandlingSchema.safeParse(values["html-handling"]);
77
+ if (!htmlHandling.success) {
78
+ throw new Error(`--html-handling must be one of: ${htmlHandlingSchema.options.join(", ")}.`);
79
+ }
80
+ const notFoundHandling = notFoundHandlingSchema.safeParse(values["not-found-handling"]);
81
+ if (!notFoundHandling.success) {
82
+ throw new Error(`--not-found-handling must be one of: ${notFoundHandlingSchema.options.join(", ")}.`);
83
+ }
84
+ const options = {
85
+ dist: values.dist,
86
+ html_handling: htmlHandling.data,
87
+ not_found_handling: notFoundHandling.data,
88
+ component: values.component,
89
+ destination: values.dev
90
+ ? { kind: "dev" }
91
+ : values["preview-name"] === undefined
92
+ ? { kind: "production" }
93
+ : { kind: "preview", name: values["preview-name"] },
94
+ };
95
+ // `upload` is the step that `deploy` runs inside `npx convex deploy --cmd`, after the build.
96
+ if (name === "upload") {
97
+ if (values["version-id"] === undefined || values.build !== undefined || values.dev) {
98
+ throw new Error(USAGE);
99
+ }
100
+ return { name, versionId: values["version-id"], options };
101
+ }
102
+ if (values.build === undefined)
103
+ throw new Error(`--build is required.\n\n${USAGE}`);
104
+ if (values["version-id"] !== undefined)
105
+ throw new Error(USAGE);
106
+ return { name, build: values.build, options };
107
+ }
108
+ /** Runs one `convex-hosting` command and returns the exit code. */
109
+ export async function main(args, cli) {
110
+ try {
111
+ const command = parseCommand(args);
112
+ if (command.name === "help") {
113
+ cli.log(USAGE);
114
+ }
115
+ else if (command.name === "deploy") {
116
+ await deploy(cli, command.options, command.build);
117
+ }
118
+ else {
119
+ await uploadInsideDeploy(cli, command.options, command.versionId);
120
+ }
121
+ return 0;
122
+ }
123
+ catch (error) {
124
+ cli.log(error instanceof Error ? error.message : String(error));
125
+ return 1;
126
+ }
127
+ }
128
+ /** Quotes one argument of the `--cmd` that `npx convex deploy` runs in a shell. */
129
+ function quote(arg) {
130
+ return process.platform === "win32" ? `"${arg}"` : `'${arg.replaceAll("'", `'\\''`)}'`;
131
+ }
132
+ /**
133
+ * Builds, uploads, writes the version file, and pushes. The push is the switch, and the command
134
+ * ends: the first request that the new code serves marks its version live.
135
+ */
136
+ async function deploy(cli, options, build) {
137
+ const target = {
138
+ component: options.component,
139
+ flags: deploymentSelector(cli, options.destination),
140
+ };
141
+ const versionId = randomUUID();
142
+ if (options.destination.kind === "dev") {
143
+ await deployDev(cli, options, target, versionId, build);
144
+ }
145
+ else {
146
+ await deployWithConvexDeploy(cli, options, target, versionId, build);
147
+ }
148
+ cli.log(`Deployed version ${versionId}.`);
149
+ }
150
+ /**
151
+ * The development deployment, in one process. The build runs as a child of this process in the
152
+ * project directory: the framework reads the deployment's URL from `.env.local` itself (Vite reads
153
+ * `VITE_CONVEX_URL`). Then the upload runs here, and `npx convex run --push` pushes, with an inline
154
+ * query at the app's root, which exists before the push installs the component. It works whether
155
+ * or not `npx convex dev` runs; `npx convex dev --once` refuses while it runs a local deployment's
156
+ * backend.
157
+ */
158
+ async function deployDev(cli, options, target, versionId, build) {
159
+ const buildExitCode = await cli.shell(build);
160
+ if (buildExitCode !== 0)
161
+ throw new Error(`The build failed with exit code ${buildExitCode}.`);
162
+ const missing = await upload(cli, options, target, versionId);
163
+ if (missing !== undefined)
164
+ cli.log(notInstalledYet(options.component));
165
+ const exitCode = await cli.convexInherited(["run", "--push", "--inline-query", "null"]);
166
+ if (exitCode !== 0)
167
+ throw new Error(`npx convex run --push failed with exit code ${exitCode}.`);
168
+ if (missing !== undefined)
169
+ await uploadAfterPush(cli, options, target, versionId);
170
+ }
171
+ /** Production or a preview: the build and the upload run inside `npx convex deploy --cmd`. */
172
+ async function deployWithConvexDeploy(cli, options, target, versionId, build) {
173
+ const marker = join(cli.cwd, FIRST_INSTALL_MARKER);
174
+ rmSync(marker, { force: true });
175
+ // `npx convex deploy` goes to production by default and has no `--prod` flag.
176
+ const deployFlags = target.flags.filter((flag) => flag !== "--prod");
177
+ const previewFlags = options.destination.kind === "preview" ? ["--preview-name", options.destination.name] : [];
178
+ const innerUpload = [
179
+ process.execPath,
180
+ fileURLToPath(new URL("./index.js", import.meta.url)),
181
+ "upload",
182
+ "--dist",
183
+ options.dist,
184
+ "--version-id",
185
+ versionId,
186
+ "--html-handling",
187
+ options.html_handling,
188
+ "--not-found-handling",
189
+ options.not_found_handling,
190
+ "--component",
191
+ options.component,
192
+ ...previewFlags,
193
+ ]
194
+ .map(quote)
195
+ .join(" ");
196
+ // The build and the upload run in the project directory; a build must not change directory.
197
+ const exitCode = await cli.convexInherited([
198
+ "deploy",
199
+ "--cmd",
200
+ `${build} && ${innerUpload}`,
201
+ ...deployFlags,
202
+ ]);
203
+ const firstInstall = existsSync(marker);
204
+ rmSync(marker, { force: true });
205
+ if (exitCode !== 0)
206
+ throw new Error(`npx convex deploy failed with exit code ${exitCode}.`);
207
+ if (firstInstall)
208
+ await uploadAfterPush(cli, options, target, versionId);
209
+ }
210
+ /** The upload inside `npx convex deploy --cmd`. On a first install, `deploy` uploads after the push. */
211
+ async function uploadInsideDeploy(cli, options, versionId) {
212
+ const target = {
213
+ component: options.component,
214
+ flags: deploymentSelector(cli, options.destination),
215
+ };
216
+ if ((await upload(cli, options, target, versionId)) !== undefined) {
217
+ writeStateFile(cli, FIRST_INSTALL_MARKER, "");
218
+ cli.log(notInstalledYet(options.component));
219
+ }
220
+ }
221
+ function notInstalledYet(component) {
222
+ return `The component "${component}" is not installed yet. The push installs it, and the upload runs after the push.`;
223
+ }
224
+ /** The upload of a first install, after the push. The probe's output shows a mistyped `--component`. */
225
+ async function uploadAfterPush(cli, options, target, versionId) {
226
+ const missing = await upload(cli, options, target, versionId);
227
+ if (missing !== undefined) {
228
+ throw new Error(`The component "${options.component}" is not installed after the push. The Convex CLI ` +
229
+ `said:\n${missing}`);
230
+ }
231
+ }
232
+ /**
233
+ * Uploads `--dist` as version `versionId` and writes the version file. When the component is not
234
+ * installed yet, it writes only the version file, so that the push that follows installs the
235
+ * component, and returns the probe's output.
236
+ */
237
+ async function upload(cli, options, target, versionId) {
238
+ const dist = resolve(cli.cwd, options.dist);
239
+ const { config, entries } = await readDist(dist, options, cli.log);
240
+ const generateUploadUrls = (count) => runComponent(cli, target, internal.lib.generateUploadUrls, { count }, z.array(z.string()).length(count));
241
+ const missing = await probeComponent(cli, target);
242
+ if (missing !== undefined) {
243
+ writeVersionFile(cli, versionId);
244
+ return missing;
245
+ }
246
+ cli.log(`Uploading version ${versionId}: ${entries.length} files.`);
247
+ const [configUrl] = await generateUploadUrls(1);
248
+ const configId = await store(cli, configUrl, JSON.stringify(config), "application/json");
249
+ await runComponent(cli, target, internal.lib.createVersion, { versionId, configId }, z.null());
250
+ // Entries with the same bytes share one stored file.
251
+ const groups = new Map();
252
+ for (const entry of entries) {
253
+ groups.set(entry.sha256, [...(groups.get(entry.sha256) ?? []), entry]);
254
+ }
255
+ /** Sends the complete entries of stored files, in batches that fit a command line. */
256
+ const record = async (stored) => {
257
+ const complete = stored.flatMap(({ sha256, storageId }) => (groups.get(sha256) ?? []).map(({ path, contentType }) => ({
258
+ path,
259
+ sha256,
260
+ contentType,
261
+ storageId,
262
+ })));
263
+ for (const chunk of chunkByLength(complete)) {
264
+ await runComponent(cli, target, internal.lib.recordFiles, { versionId, entries: chunk }, z.null());
265
+ }
266
+ };
267
+ // Files that an entry of any version has keep their stored file.
268
+ const known = new Set();
269
+ for (const sha256s of chunkByLength([...groups.keys()])) {
270
+ const files = await runComponent(cli, target, internal.lib.knownFiles, { sha256s }, z.array(z.object({ sha256: z.string(), storageId: storageIdSchema })));
271
+ for (const { sha256 } of files)
272
+ known.add(sha256);
273
+ await record(files);
274
+ }
275
+ const unknown = [...groups.values()].filter((group) => !known.has(group[0].sha256));
276
+ for (let start = 0; start < unknown.length; start += UPLOAD_PAGE) {
277
+ const page = unknown.slice(start, start + UPLOAD_PAGE);
278
+ const urls = await generateUploadUrls(page.length);
279
+ const uploaded = [];
280
+ let next = 0;
281
+ const worker = async () => {
282
+ while (next < page.length) {
283
+ const index = next++;
284
+ const [{ sha256, contentType, file }] = page[index];
285
+ const storageId = await store(cli, urls[index], readFileSync(file), contentType);
286
+ uploaded.push({ sha256, storageId });
287
+ }
288
+ };
289
+ await Promise.all(Array.from({ length: UPLOAD_CONCURRENCY }, worker));
290
+ await record(uploaded);
291
+ }
292
+ await runComponent(cli, target, internal.lib.finishVersion, { versionId }, z.null());
293
+ writeVersionFile(cli, versionId);
294
+ cli.log(`Uploaded version ${versionId} and wrote ${VERSION_FILE}.`);
295
+ return undefined;
296
+ }
297
+ function writeVersionFile(cli, versionId) {
298
+ writeStateFile(cli, VERSION_FILE, `export const versionId = ${JSON.stringify(versionId)};\n`);
299
+ }
300
+ /** Writes a file of the state folder, and the folder's `.gitignore` when it is absent. */
301
+ function writeStateFile(cli, path, body) {
302
+ const gitignore = join(cli.cwd, STATE_DIR, ".gitignore");
303
+ if (!existsSync(gitignore)) {
304
+ mkdirSync(join(cli.cwd, STATE_DIR), { recursive: true });
305
+ writeFileSync(gitignore, "*\n");
306
+ }
307
+ writeFileSync(join(cli.cwd, path), body);
308
+ }
309
+ /** Stores one file through an upload URL and returns its storage id. */
310
+ async function store(cli, url, body, contentType) {
311
+ const response = await cli.fetch(url, {
312
+ method: "POST",
313
+ headers: contentType === undefined ? {} : { "Content-Type": contentType },
314
+ body,
315
+ });
316
+ if (!response.ok) {
317
+ throw new Error(`Storing a file failed with ${response.status}: ${await response.text()}`);
318
+ }
319
+ return z.object({ storageId: storageIdSchema }).parse(await response.json()).storageId;
320
+ }
321
+ /**
322
+ * A storage id that an upload URL answers with, the documented source of an `Id<"_storage">`, or
323
+ * that `knownFiles` returns. At runtime an id is a string, and its table exists only in its type,
324
+ * so the narrowest honest check here is that it is a string; the `v.id("_storage")` validators of
325
+ * `createVersion` and `recordFiles` check the table on the server.
326
+ */
327
+ const storageIdSchema = z.custom((value) => typeof value === "string");
328
+ function chunkByLength(items) {
329
+ const chunks = [];
330
+ let chunk = [];
331
+ let length = 0;
332
+ for (const item of items) {
333
+ const itemLength = JSON.stringify(item).length + 1;
334
+ if (chunk.length > 0 && length + itemLength > MAX_ARGUMENT_LENGTH) {
335
+ chunks.push(chunk);
336
+ chunk = [];
337
+ length = 0;
338
+ }
339
+ chunk.push(item);
340
+ length += itemLength;
341
+ }
342
+ if (chunk.length > 0)
343
+ chunks.push(chunk);
344
+ return chunks;
345
+ }
346
+ //# sourceMappingURL=main.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"main.js","sourceRoot":"","sources":["../../src/cli/main.ts"],"names":[],"mappings":"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"}
@@ -1,119 +1,12 @@
1
- import { type GenericActionCtx, type GenericDataModel, type HttpRouter } from "convex/server";
1
+ import type { GenericActionCtx, GenericDataModel } from "convex/server";
2
2
  import type { ComponentApi } from "../component/_generated/component.js";
3
- import { decodeRequestPath } from "../component/serving.js";
4
- type CdnBaseUrl = string | ((request: Request) => string);
5
- /** The parts of an action context needed to serve a static file. */
6
- type AssetServingCtx = Pick<GenericActionCtx<GenericDataModel>, "runQuery" | "storage">;
7
3
  /**
8
- * Register app-owned HTTP routes for the hosted site.
4
+ * Answers `request` with the asset of version `versionId` that Cloudflare's asset handler picks.
9
5
  *
10
- * Prefer mounting the component's own HTTP routes when it can own the URL
11
- * prefix. Use this compatibility mode when existing app HTTP routes must stay
12
- * at the same root. Exact app routes take precedence over this catch-all.
13
- * Assets and deployment state still live in the component.
14
- *
15
- * @example
16
- * ```typescript
17
- * // convex/convex.config.ts
18
- * const app = defineApp();
19
- * app.use(hosting); // no httpPrefix: the app owns HTTP routing
20
- *
21
- * // convex/http.ts
22
- * const http = httpRouter();
23
- * auth.addHttpRoutes(http);
24
- * registerStaticRoutes(http, components.hosting);
25
- * export default http;
26
- * ```
27
- */
28
- export declare function registerStaticRoutes(http: HttpRouter, component: ComponentApi, { pathPrefix, spaFallback, cdnBaseUrl, }?: {
29
- /** URL prefix where the app should serve static files. */
30
- pathPrefix?: string;
31
- /** Override the deployment's SPA fallback setting. */
32
- spaFallback?: boolean;
33
- /** Optional custom base URL for convex-fs blob redirects. */
34
- cdnBaseUrl?: CdnBaseUrl;
35
- }): void;
36
- /**
37
- * Serve an uploaded static file from your own HTTP action, or return null when
38
- * no file matches so the action can continue with its own routing: server
39
- * rendering, prerendered pages, redirects.
40
- *
41
- * Found files get the same response as `registerStaticRoutes`: content type,
42
- * cache headers, ETag revalidation, and legacy CDN redirects. A found file
43
- * whose storage can't be read gets a 500 response. A request path with
44
- * malformed percent-encoding matches no file, so it returns null.
45
- *
46
- * The lookup is exact by default. `/` is not mapped to `/index.html`, and there
47
- * is no SPA fallback, so the SPA shell never answers for a route your action
48
- * handles. To serve the shell, pass `{ path: "/index.html" }`. When your route
49
- * has a prefix, pass `path` with the prefix removed.
50
- *
51
- * @example
52
- * ```typescript
53
- * // convex/http.ts
54
- * const http = httpRouter();
55
- * http.route({
56
- * pathPrefix: "/",
57
- * method: "GET",
58
- * handler: httpAction(async (ctx, request) => {
59
- * const file = await serveStaticAsset(ctx, components.hosting, request);
60
- * if (file) return file;
61
- * return await renderPage(request);
62
- * }),
63
- * });
64
- * export default http;
65
- * ```
66
- */
67
- export declare function serveStaticAsset(ctx: AssetServingCtx, component: ComponentApi, request: Request, { path, spaFallback, cdnBaseUrl, }?: {
68
- /**
69
- * Decoded file path to look up, starting with `/`, such as
70
- * `/about/index.html`. Defaults to the decoded request path.
71
- */
72
- path?: string;
73
- /** Serve `/index.html` for a missing path without a file extension. */
74
- spaFallback?: boolean;
75
- /** Optional custom base URL for convex-fs blob redirects. */
76
- cdnBaseUrl?: CdnBaseUrl;
77
- }): Promise<Response | null>;
78
- export { decodeRequestPath };
79
- /**
80
- * Expose a query that clients can subscribe to for live reload on deploy.
81
- * This is only needed if you use `UpdateBanner` / `useDeploymentUpdates` from
82
- * `@samebase/convex-hosting/react`. If you don't surface deployment updates
83
- * in your app, you don't need to call this.
84
- *
85
- * @example
86
- * ```typescript
87
- * // convex/hosting.ts
88
- * import { exposeDeploymentQuery } from "@samebase/convex-hosting";
89
- * import { components } from "./_generated/api";
90
- *
91
- * export const { getCurrentDeployment } = exposeDeploymentQuery(
92
- * components.hosting,
93
- * );
94
- * ```
95
- */
96
- export declare function exposeDeploymentQuery(component: ComponentApi): {
97
- getCurrentDeployment: import("convex/server").RegisteredQuery<"public", {}, Promise<{
98
- _creationTime: number;
99
- _id: string;
100
- currentDeploymentId: string;
101
- deployedAt: number;
102
- spaFallback?: boolean;
103
- } | null>>;
104
- };
105
- /**
106
- * Derive the Convex cloud URL from a `.convex.site` hostname.
107
- * Useful when your frontend is served by this component and needs
108
- * to connect to its own Convex backend without an explicit env var.
109
- *
110
- * @example
111
- * ```typescript
112
- * import { getConvexUrl } from "@samebase/convex-hosting";
113
- *
114
- * const convexUrl = import.meta.env.VITE_CONVEX_URL ?? getConvexUrl();
115
- * const convex = new ConvexReactClient(convexUrl);
116
- * ```
6
+ * Returns `null` when no asset matches, so the app continues (a static site answers 404, a
7
+ * server-rendered site renders the page). A version that does not exist, is still uploading, or
8
+ * is being deleted answers 404, so a half-installed site does not render pages without their
9
+ * files. The first request for a `ready` version marks it live, which deletes the versions that
10
+ * were live before it.
117
11
  */
118
- export declare function getConvexUrl(): string;
119
- //# sourceMappingURL=index.d.ts.map
12
+ export declare function serveAsset(ctx: Pick<GenericActionCtx<GenericDataModel>, "runQuery" | "runMutation">, component: ComponentApi, request: Request, versionId: string): Promise<Response | null>;