@samebase/convex-hosting 0.4.1 → 0.5.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.
- package/CHANGELOG.md +7 -0
- package/README.md +16 -14
- package/dist/client/index.d.ts +12 -4
- package/dist/client/index.js +22 -4
- package/dist/client/index.js.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.5.0
|
|
4
|
+
|
|
5
|
+
- `serveSite(ctx, component, request, versionId, render?)` serves the whole site from one route: the
|
|
6
|
+
file that matches, else the page that `render` returns, else 404. A page and a 404 answer
|
|
7
|
+
`Cache-Control: no-store`, so `convex/http.ts` no longer sets it. `serveAsset` stays, as its first
|
|
8
|
+
step.
|
|
9
|
+
|
|
3
10
|
## 0.4.1
|
|
4
11
|
|
|
5
12
|
- `convex-hosting init` writes `.convex-hosting/version.js` with no site version when it is absent,
|
package/README.md
CHANGED
|
@@ -35,7 +35,7 @@ Requires `convex` 1.46 or later.
|
|
|
35
35
|
|
|
36
36
|
```ts
|
|
37
37
|
import { httpRouter } from "convex/server";
|
|
38
|
-
import {
|
|
38
|
+
import { serveSite } from "@samebase/convex-hosting";
|
|
39
39
|
import { components } from "./_generated/api.js";
|
|
40
40
|
import { httpAction } from "./_generated/server.js";
|
|
41
41
|
import { versionId } from "../.convex-hosting/version.js";
|
|
@@ -45,13 +45,7 @@ Requires `convex` 1.46 or later.
|
|
|
45
45
|
http.route({
|
|
46
46
|
pathPrefix: "/",
|
|
47
47
|
method: "GET",
|
|
48
|
-
handler: httpAction(
|
|
49
|
-
const asset = await serveAsset(ctx, components.hosting, request, versionId);
|
|
50
|
-
if (asset) return asset;
|
|
51
|
-
// A static site: 404. A server-rendered site: render the page here, also with `no-store`.
|
|
52
|
-
// The deployment's Cloudflare front caches answers on static-looking paths.
|
|
53
|
-
return new Response(null, { status: 404, headers: { "Cache-Control": "no-store" } });
|
|
54
|
-
}),
|
|
48
|
+
handler: httpAction((ctx, request) => serveSite(ctx, components.hosting, request, versionId)),
|
|
55
49
|
});
|
|
56
50
|
|
|
57
51
|
export default http;
|
|
@@ -90,7 +84,6 @@ declares the type of `.convex-hosting/version.js`, so the app typechecks without
|
|
|
90
84
|
after `init` that is none: the site answers 404 until the next `convex-hosting deploy`.
|
|
91
85
|
- Do not commit `.convex-hosting/`. It ignores itself.
|
|
92
86
|
- Do not change directory in `--build`. The build and the upload run in the project directory.
|
|
93
|
-
- Answer a miss in `convex/http.ts` with `Cache-Control: no-store`, as in step 3.
|
|
94
87
|
|
|
95
88
|
## Deploy
|
|
96
89
|
|
|
@@ -191,9 +184,15 @@ files for a year, add a `_headers` rule:
|
|
|
191
184
|
|
|
192
185
|
## Routing
|
|
193
186
|
|
|
194
|
-
`
|
|
195
|
-
|
|
196
|
-
|
|
187
|
+
`serveSite` answers with the file that matches, else with the page that `render` returns (see
|
|
188
|
+
[Server-rendered pages](#server-rendered-pages)), else 404. A page and a 404 answer
|
|
189
|
+
`Cache-Control: no-store`. The deployment's Cloudflare front keeps that for a path without an
|
|
190
|
+
extension and replaces it with a four-hour browser `max-age` for a path with one, so a browser that
|
|
191
|
+
asks for a script before its upload ended keeps the 404; the deploy order prevents that case,
|
|
192
|
+
because no page refers to a file that is not uploaded yet. When the version does not exist or is
|
|
193
|
+
still uploading, it answers 404 naming the version. At the first request for a new version, it marks
|
|
194
|
+
the version live. `serveAsset`, its first step, returns the file's response or `null`, for a route
|
|
195
|
+
that does something else on a miss.
|
|
197
196
|
|
|
198
197
|
`not_found_handling` applies to navigation requests (`Sec-Fetch-Mode: navigate`) only, as on
|
|
199
198
|
Cloudflare when a Worker runs: other requests that match no file reach your code. Browsers send that
|
|
@@ -242,9 +241,12 @@ export function useReloadOnNewVersion() {
|
|
|
242
241
|
|
|
243
242
|
## Server-rendered pages
|
|
244
243
|
|
|
244
|
+
`serveSite` takes a fifth argument, `render`, a function from the request to the page's response,
|
|
245
|
+
and calls it when no file matches.
|
|
245
246
|
[`@samebase/convex-hosting-tanstack-start`](https://github.com/samebase/convex-hosting/tree/main/packages/convex-hosting-tanstack-start)
|
|
246
|
-
renders TanStack Start pages in
|
|
247
|
-
[TanStack Start example](https://github.com/samebase/convex-hosting/tree/main/examples/tanstack-ssr)
|
|
247
|
+
renders TanStack Start pages in it. See the
|
|
248
|
+
[TanStack Start example](https://github.com/samebase/convex-hosting/tree/main/examples/tanstack-ssr),
|
|
249
|
+
live at [gallant-llama-40.convex.site](https://gallant-llama-40.convex.site).
|
|
248
250
|
|
|
249
251
|
## License
|
|
250
252
|
|
package/dist/client/index.d.ts
CHANGED
|
@@ -1,12 +1,20 @@
|
|
|
1
1
|
import type { GenericActionCtx, GenericDataModel } from "convex/server";
|
|
2
2
|
import type { ComponentApi } from "../component/_generated/component.js";
|
|
3
|
+
/**
|
|
4
|
+
* Answers `request` with the file of version `versionId`, else with the page that `render`
|
|
5
|
+
* returns, else 404. A page and a miss answer `Cache-Control: no-store`. The deployment's
|
|
6
|
+
* Cloudflare front keeps that for a path without an extension and replaces it with a four-hour
|
|
7
|
+
* browser `max-age` for a path with one, so a browser that asks for a script before its upload
|
|
8
|
+
* ended keeps the 404; the deploy order prevents that case, because no page refers to a file that
|
|
9
|
+
* is not uploaded yet.
|
|
10
|
+
*/
|
|
11
|
+
export declare function serveSite(ctx: Pick<GenericActionCtx<GenericDataModel>, "runQuery" | "runMutation">, component: ComponentApi, request: Request, versionId: string, render?: () => Promise<Response>): Promise<Response>;
|
|
3
12
|
/**
|
|
4
13
|
* Answers `request` with the asset of version `versionId` that Cloudflare's asset handler picks.
|
|
5
14
|
*
|
|
6
|
-
* Returns `null` when no asset matches, so the
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
* files. The first request for a `ready` version marks it live, which deletes the versions that
|
|
15
|
+
* Returns `null` when no asset matches, so the caller continues, as `serveSite` does. A version
|
|
16
|
+
* that does not exist, is still uploading, or is being deleted answers 404, so a half-installed
|
|
17
|
+
* site does not render pages without their files. The first request for a `ready` version marks it live, which deletes the versions that
|
|
10
18
|
* were live before it.
|
|
11
19
|
*/
|
|
12
20
|
export declare function serveAsset(ctx: Pick<GenericActionCtx<GenericDataModel>, "runQuery" | "runMutation">, component: ComponentApi, request: Request, versionId: string): Promise<Response | null>;
|
package/dist/client/index.js
CHANGED
|
@@ -1,10 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Answers `request` with the file of version `versionId`, else with the page that `render`
|
|
3
|
+
* returns, else 404. A page and a miss answer `Cache-Control: no-store`. The deployment's
|
|
4
|
+
* Cloudflare front keeps that for a path without an extension and replaces it with a four-hour
|
|
5
|
+
* browser `max-age` for a path with one, so a browser that asks for a script before its upload
|
|
6
|
+
* ended keeps the 404; the deploy order prevents that case, because no page refers to a file that
|
|
7
|
+
* is not uploaded yet.
|
|
8
|
+
*/
|
|
9
|
+
export async function serveSite(ctx, component, request, versionId, render) {
|
|
10
|
+
const asset = await serveAsset(ctx, component, request, versionId);
|
|
11
|
+
if (asset !== null)
|
|
12
|
+
return asset;
|
|
13
|
+
if (render === undefined)
|
|
14
|
+
return new Response(null, { status: 404, headers: NO_STORE });
|
|
15
|
+
const page = await render();
|
|
16
|
+
const headers = new Headers(page.headers);
|
|
17
|
+
headers.set("Cache-Control", "no-store");
|
|
18
|
+
return new Response(page.body, { status: page.status, headers });
|
|
19
|
+
}
|
|
1
20
|
/**
|
|
2
21
|
* Answers `request` with the asset of version `versionId` that Cloudflare's asset handler picks.
|
|
3
22
|
*
|
|
4
|
-
* Returns `null` when no asset matches, so the
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* files. The first request for a `ready` version marks it live, which deletes the versions that
|
|
23
|
+
* Returns `null` when no asset matches, so the caller continues, as `serveSite` does. A version
|
|
24
|
+
* that does not exist, is still uploading, or is being deleted answers 404, so a half-installed
|
|
25
|
+
* site does not render pages without their files. The first request for a `ready` version marks it live, which deletes the versions that
|
|
8
26
|
* were live before it.
|
|
9
27
|
*/
|
|
10
28
|
export async function serveAsset(ctx, component, request, versionId) {
|
package/dist/client/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/client/index.ts"],"names":[],"mappings":"AAGA
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/client/index.ts"],"names":[],"mappings":"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"}
|