@mapled/next 0.9.0 → 0.10.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/README.md +2 -0
- package/dist/live-pages.js +2 -2
- package/dist/live.d.ts +2 -1
- package/dist/live.js +2 -2
- package/dist/watch.d.ts +9 -1
- package/dist/watch.js +16 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -372,6 +372,8 @@ export function UpdateNotice() {
|
|
|
372
372
|
- The route reads the release under the same `mapled` cache tag as the content, so it moves when the webhook refreshes the cache and not before — a tab that refreshes on it never renders the old release again. Live updates therefore need the webhook from [Refresh on publish](#refresh-on-publish); without it both change only when their ISR window (`revalidate`, 3600 by default) runs out.
|
|
373
373
|
- The route answers `{ release, publishedAt }` — the number of publishes and the time of the last one, nothing else — and may be cached by anyone. While Mapled can't be reached it keeps answering the last release it knew.
|
|
374
374
|
- Expect a publish to reach an open tab in about ten seconds with the defaults. `<MapledLive interval={3} />` and `createReleaseHandler({ key, ttl: 1 })` make it quicker at the price of more requests to your site.
|
|
375
|
+
- With a `basePath` in `next.config`, the route answers under it, and so does the default: `<MapledLive />` asks `/docs/api/mapled/release` on a site with `basePath: "/docs"` — Next writes the basePath into the bundle, and the component reads it from there (0.10.0 and later; earlier versions ask `/api/mapled/release`). An `endpoint` you pass is asked as written, basePath included: `<MapledLive endpoint="/docs/live" />`.
|
|
376
|
+
- Leave route segment config off the release route: `createReleaseHandler` sets how it is cached. `dynamic = "force-static"` turns it into a copy Next builds without the tab's request, and `fetchCache = "force-no-store"` reads the release past the cache tag — the route would move before the webhook refreshes the pages. `dynamic = "force-dynamic"` does the same when the handler's `revalidate` is `false` or `0`; at its default it is harmless. Middleware that runs on the route has to let the tab's `GET` through: no redirect, rewrite or sign-in wall. `output: "export"` has no server to run the route at all.
|
|
375
377
|
|
|
376
378
|
Outside React, `watchRelease({ onPublish })` from `@mapled/next` is the same watch as a plain function — it returns the function that stops it.
|
|
377
379
|
|
package/dist/live-pages.js
CHANGED
|
@@ -7,8 +7,8 @@
|
|
|
7
7
|
<><Component {...pageProps} /><MapledLive /></>
|
|
8
8
|
|
|
9
9
|
It asks the release route (`createPagesReleaseHandler` from
|
|
10
|
-
"@mapled/next/server", mounted at pages/api/mapled/release
|
|
11
|
-
seconds and, when a publish lands, runs the page's data again through
|
|
10
|
+
"@mapled/next/server", mounted at pages/api/mapled/release — under
|
|
11
|
+
the site's basePath, when next.config sets one) every few seconds and, when a publish lands, runs the page's data again through
|
|
12
12
|
the router, in place — scroll position and client state stay. A
|
|
13
13
|
module of its own, so an App Router bundle never pulls in
|
|
14
14
|
`next/router`, nor a Pages one `next/navigation`. */
|
package/dist/live.d.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { type Release } from "./watch.js";
|
|
2
2
|
export type { Release } from "./watch.js";
|
|
3
3
|
export type MapledLiveProps = {
|
|
4
|
-
/** Where the release route is mounted (default
|
|
4
|
+
/** Where the release route is mounted, asked as written (default
|
|
5
|
+
"/api/mapled/release" under the site's `basePath`). */
|
|
5
6
|
endpoint?: string;
|
|
6
7
|
/** Seconds between checks while the tab is visible (default 10, at least 2). */
|
|
7
8
|
interval?: number;
|
package/dist/live.js
CHANGED
|
@@ -6,8 +6,8 @@
|
|
|
6
6
|
<body>{children}<MapledLive /></body>
|
|
7
7
|
|
|
8
8
|
It asks the release route (`createReleaseHandler` from
|
|
9
|
-
"@mapled/next/server", mounted at /api/mapled/release
|
|
10
|
-
seconds and, when a publish lands, refreshes the page's server
|
|
9
|
+
"@mapled/next/server", mounted at /api/mapled/release — under the
|
|
10
|
+
site's basePath, when next.config sets one) every few seconds and, when a publish lands, refreshes the page's server
|
|
11
11
|
components in place — scroll position and client state stay. */
|
|
12
12
|
import { useRouter } from "next/navigation";
|
|
13
13
|
import { useEffect, useRef } from "react";
|
package/dist/watch.d.ts
CHANGED
|
@@ -8,7 +8,8 @@ export type Release = {
|
|
|
8
8
|
publishedAt: string;
|
|
9
9
|
};
|
|
10
10
|
export type WatchOptions = {
|
|
11
|
-
/** Where the release route is mounted (default
|
|
11
|
+
/** Where the release route is mounted, asked as written (default
|
|
12
|
+
"/api/mapled/release" under the site's `basePath`). */
|
|
12
13
|
endpoint?: string;
|
|
13
14
|
/** Seconds between checks while the tab is visible (default 10, at least 2). */
|
|
14
15
|
interval?: number;
|
|
@@ -16,6 +17,13 @@ export type WatchOptions = {
|
|
|
16
17
|
watch knew before — null when nothing was published yet. */
|
|
17
18
|
onPublish: (next: Release, previous: number | null) => void;
|
|
18
19
|
};
|
|
20
|
+
/** The site's `basePath` from next.config, "" without one. Next writes it
|
|
21
|
+
into the code it bundles — its own and every package's — in place of
|
|
22
|
+
this very expression, the way its router adds it to every link, so a
|
|
23
|
+
route under the basePath is where the default endpoint lives. Outside
|
|
24
|
+
Next a browser has no `process`, and Node no such variable: "". Not
|
|
25
|
+
part of the package's API. */
|
|
26
|
+
export declare function nextBasePath(): string;
|
|
19
27
|
/** Starts watching; returns the function that stops it. The first answer
|
|
20
28
|
is where the watch starts from; `onPublish` runs once per release that
|
|
21
29
|
comes after it. A hidden tab doesn't ask — it checks the moment it is
|
package/dist/watch.js
CHANGED
|
@@ -5,6 +5,21 @@
|
|
|
5
5
|
is this plus `router.refresh()`. */
|
|
6
6
|
const DEFAULT_ENDPOINT = "/api/mapled/release";
|
|
7
7
|
const MAX_BACKOFF_MS = 5 * 60_000;
|
|
8
|
+
/** The site's `basePath` from next.config, "" without one. Next writes it
|
|
9
|
+
into the code it bundles — its own and every package's — in place of
|
|
10
|
+
this very expression, the way its router adds it to every link, so a
|
|
11
|
+
route under the basePath is where the default endpoint lives. Outside
|
|
12
|
+
Next a browser has no `process`, and Node no such variable: "". Not
|
|
13
|
+
part of the package's API. */
|
|
14
|
+
export function nextBasePath() {
|
|
15
|
+
try {
|
|
16
|
+
const base = process.env.__NEXT_ROUTER_BASEPATH;
|
|
17
|
+
return typeof base === "string" && base.startsWith("/") ? base : "";
|
|
18
|
+
}
|
|
19
|
+
catch {
|
|
20
|
+
return "";
|
|
21
|
+
}
|
|
22
|
+
}
|
|
8
23
|
/** The route's answer — null before the first publish — or undefined
|
|
9
24
|
when it isn't one. */
|
|
10
25
|
function pointer(body) {
|
|
@@ -31,7 +46,7 @@ export function watchRelease(options) {
|
|
|
31
46
|
it, an older one (or null: not known) to hand the first answer to
|
|
32
47
|
`onPublish` as well. Not part of the package's API. */
|
|
33
48
|
export function watchFrom(options, from) {
|
|
34
|
-
const endpoint = options.endpoint ?? DEFAULT_ENDPOINT;
|
|
49
|
+
const endpoint = options.endpoint ?? nextBasePath() + DEFAULT_ENDPOINT;
|
|
35
50
|
const everyMs = Math.max(2, options.interval ?? 10) * 1000;
|
|
36
51
|
const doc = typeof document === "undefined" ? null : document;
|
|
37
52
|
/** undefined until the first answer; null while nothing is published */
|
package/package.json
CHANGED