@absolutejs/absolute 0.20.0-beta.176 → 0.20.0-beta.178
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 +33 -0
- package/changelog.json +62 -0
- package/dist/angular/browser.js +17 -2
- package/dist/angular/browser.js.map +4 -4
- package/dist/angular/components/core/streamingSlotRegistrar.js +1 -1
- package/dist/angular/components/core/streamingSlotRegistry.js +2 -2
- package/dist/angular/index.js +57 -33
- package/dist/angular/index.js.map +9 -8
- package/dist/angular/server.js +57 -33
- package/dist/angular/server.js.map +9 -8
- package/dist/build.js +532 -416
- package/dist/build.js.map +15 -15
- package/dist/cli/{compile-w2z6c9vt.js → compile-p5yv6ecp.js} +2 -2
- package/dist/cli/config/server.js +45 -12
- package/dist/cli/{dev-8br5mr7t.js → dev-2hbcsvkp.js} +1 -1
- package/dist/cli/{index-420h9hq7.js → index-1ewba8ye.js} +32 -3
- package/dist/cli/{index-7z1hh3fg.js → index-9dzdbbfc.js} +1 -1
- package/dist/cli/index.js +7 -7
- package/dist/cli/{islands-bx67g15t.js → islands-6zgb7501.js} +1 -1
- package/dist/cli/{mobile-we5q51ey.js → mobile-c92dh8s2.js} +2 -2
- package/dist/cli/{start-srs11bm8.js → start-asxb79rc.js} +2 -2
- package/dist/cli/{typecheck-7fvww3b7.js → typecheck-m2j4tkdk.js} +165 -35
- package/dist/client/chunks/{index-8m2qq61n.js → index-58svs66p.js} +13 -3
- package/dist/client/chunks/{index-8m2qq61n.js.map → index-58svs66p.js.map} +5 -4
- package/dist/client/chunks/{islands-mfjmdwnb.js → islands-tcadmgcx.js} +3 -6
- package/dist/client/chunks/{islands-mfjmdwnb.js.map → islands-tcadmgcx.js.map} +3 -4
- package/dist/client/chunks/{react-sprprqzs.js → react-khr6ewhr.js} +2 -2
- package/dist/client/index.js +82 -6
- package/dist/client/index.js.map +7 -6
- package/dist/dev/client/handlers/islands.ts +2 -0
- package/dist/dev/client/handlers/react.ts +92 -111
- package/dist/dev/client/handlers/reactUpdateQueue.ts +153 -0
- package/dist/index.js +506 -389
- package/dist/index.js.map +16 -16
- package/dist/islands/browser.js +2 -2
- package/dist/islands/browser.js.map +3 -3
- package/dist/islands/index.js +13 -6
- package/dist/islands/index.js.map +6 -5
- package/dist/react/browser.js +113 -12
- package/dist/react/browser.js.map +10 -7
- package/dist/react/components/index.js +31 -7
- package/dist/react/components/index.js.map +5 -4
- package/dist/react/components/server/index.js +22 -6
- package/dist/react/index.js +190 -46
- package/dist/react/index.js.map +15 -11
- package/dist/react/server.js +82 -23
- package/dist/react/server.js.map +11 -9
- package/dist/src/build/compileSvelte.d.ts +12 -1
- package/dist/src/build/compileVue.d.ts +1 -0
- package/dist/src/build/islandEntries.d.ts +3 -1
- package/dist/src/cli/scripts/typecheck.d.ts +8 -0
- package/dist/src/cli/scripts/typecheckDiagnostics.d.ts +17 -0
- package/dist/src/client/preserveIslandMarkup.d.ts +4 -0
- package/dist/src/core/islandManifest.d.ts +6 -0
- package/dist/src/core/islandStylesheet.d.ts +17 -0
- package/dist/src/react/Island.d.ts +9 -2
- package/dist/src/react/IslandStyleLink.d.ts +11 -0
- package/dist/src/react/createIsland.d.ts +1 -1
- package/dist/src/react/serverComponents/nodeRendererRef.d.ts +13 -0
- package/dist/src/utils/requestRenderUrl.d.ts +1 -0
- package/dist/src/utils/resolveConvention.d.ts +1 -0
- package/dist/src/vue/Island.browser.d.ts +3 -1
- package/dist/src/vue/Island.d.ts +2 -2
- package/dist/src/vue/createIsland.browser.d.ts +2 -2
- package/dist/src/vue/createIsland.d.ts +2 -2
- package/dist/src/vue/islandStyleLink.d.ts +30 -0
- package/dist/svelte/browser.js +2 -2
- package/dist/svelte/browser.js.map +3 -3
- package/dist/svelte/index.js +51 -49
- package/dist/svelte/index.js.map +9 -8
- package/dist/svelte/server.js +48 -45
- package/dist/svelte/server.js.map +8 -7
- package/dist/types/globals.d.ts +3 -0
- package/dist/vue/browser.js +105 -10
- package/dist/vue/browser.js.map +10 -7
- package/dist/vue/index.js +170 -47
- package/dist/vue/index.js.map +14 -11
- package/dist/vue/server.js +81 -22
- package/dist/vue/server.js.map +9 -7
- package/package.json +1 -1
- /package/dist/cli/{index-6522t968.js → index-yd672jyq.js} +0 -0
- /package/dist/client/chunks/{react-sprprqzs.js.map → react-khr6ewhr.js.map} +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,39 @@ This file is generated by `absolute-changelog` from the entries in
|
|
|
6
6
|
`changelog/`. Edit an entry, not this file — and add new ones under
|
|
7
7
|
`changelog/unreleased/`.
|
|
8
8
|
|
|
9
|
+
## 0.20.0-beta.178 — 2026-11-14
|
|
10
|
+
|
|
11
|
+
### Fixed
|
|
12
|
+
|
|
13
|
+
- **`GET //` no longer returns a 500 on an Angular page**
|
|
14
|
+
Elysia routes a request for `//` to the `/` route, but the request URL keeps both slashes, and the page handlers passed that path on as the URL to render. Angular's server renderer reads `//` as a protocol-relative URL, so `GET //` on an Angular page at `/` returned a 500 (NG05701) in production. The URL a page handler renders for now has repeated slashes collapsed (`//` becomes `/`, `//a//b` becomes `/a/b`; the query string is untouched). The same applies to the `url` the React and Svelte page handlers pass in props and to the URL the Vue router renders.
|
|
15
|
+
- **A copied project no longer inherits the original's build lock**
|
|
16
|
+
A project folder copied while its dev server was running carried `.absolutejs/build.lock` along, and the copy refused to start with "AbsoluteJS build lock is held by PID …", naming the process that serves the original folder. The lock file now records the real path of the project it belongs to, and a lock written for a different path is removed with a warning instead of blocking. Lock files written by earlier versions (without a path) still block while their process is alive.
|
|
17
|
+
- **React page and component edits on pages with islands apply on every save**
|
|
18
|
+
Saving a React page, or a component it imports, now sends one hot update instead of two. The backend route file that imports the page was counted as part of the change, so every save ran a full rebuild right after the fast update and the browser received a second update (logged as "applied" twice). On pages that render an <Island>, those edits often never appeared until a reload; the first edit after boot could fail the same way on any React page. The browser also applies React updates one at a time now: an update that arrives while another is still loading waits for it, and the newest modules are always the ones applied.
|
|
19
|
+
- **Svelte and Vue island styles ship as linked stylesheets, only on pages that render the island: no CSP violations under secureHeaders(), and Vue island styles apply**
|
|
20
|
+
A Svelte island with a `<style>` block had its styles injected at runtime as an inline `<style>` element, which `secureHeaders()` (a nonce-based `style-src`) blocked on every page load, in dev and production, so the island rendered unstyled with a CSP violation. A Vue island's `<style>` / `<style scoped>` was never shipped at all, and its server render stamped a different scope id than the client build used. Island styles (including those of child components and CSS an island imports) are now built into a stylesheet per island, `islands/<framework>/<Name>.<hash>.css`, and the server links it, with the request's CSP nonce, from every page that renders the island, once however many times the island appears, and from no page that doesn't. HTML, HTMX, Svelte, Angular and Vue pages link it in the head; a React page renders it as a stylesheet resource React hoists into the head; a streamed Vue page (streaming slots) renders it just before the island, and hydration reproduces it without a mismatch. An island that arrives later (an HTMX swap) links its stylesheet before it hydrates, and in dev an island style edit swaps the stylesheet in place, wherever it was linked.
|
|
21
|
+
- **JSON requests to unknown routes get a JSON 404, not the not-found page**
|
|
22
|
+
With a not-found convention page (for example `not-found.html`), every unmatched request got that HTML page with status 404, including fetch and API clients sending `Accept: application/json`. The not-found convention now only answers page requests (a browser navigation, `Accept: text/html`, or an HTMX request), the same rule `error.html` already used for errors thrown by routes. Other requests get Elysia's JSON 404.
|
|
23
|
+
- **SuspenseSlot with React content now resolves inside React Server Components**
|
|
24
|
+
A `SuspenseSlot` from `@absolutejs/absolute/react/components` used inside a React Server Component with React content (`fallback` plus `resolve`, `promise` or a render-prop `children`) stayed on its fallback forever in dev and production, with no error. Its content was rendered with `react-dom/server`, which React does not allow in server components, so the slot failed silently. The content is now rendered through the page's own Flight server and SSR renderer. An RSC page also holds streamed slot content back until it has hydrated, so a React-node fallback no longer causes a hydration mismatch that put every slot on the page back on its fallback. Slots that use `fallbackHtml` and return HTML strings, and `StreamSlot`, already worked and are unchanged.
|
|
25
|
+
- **`absolute typecheck` checks Svelte page props again in projects that also use Vue, and labels each error with the checker that found it**
|
|
26
|
+
Since beta.172, `absolute typecheck` in a project with Vue ran vue-check in place of bun check rather than alongside it. vue-check can't see the declarations generated for Svelte components, so a wrong Svelte page prop in a server file passed, and plain TypeScript errors (a wrong React prop) were reported under `vue-check`. Every configured framework's checker now runs: bun check (or tsc) for TypeScript, React and Svelte page props in server files, svelte-check for `.svelte` files, vue-check (or vue-tsc) for `.vue` files and Vue page props, and ngc for Angular templates. Each reports under its own label, an error both TypeScript checkers find is reported once (by bun check), and the check fails if any checker fails. So that bun check can read server code that imports `.vue` files, it gets a generated per-component shim; it does not collide with a project's own `declare module '*.vue'`.
|
|
27
|
+
- **Islands on Vue pages hydrate again**
|
|
28
|
+
A Vue page rendered without streaming slots (the default) left out the island manifest and bootstrap scripts, so the islands it server-rendered never hydrated: they showed their server markup and stayed inert. Those pages now get the island scripts, and the stylesheets of the islands they render, in the head, like every other host page.
|
|
29
|
+
|
|
30
|
+
### Internal
|
|
31
|
+
|
|
32
|
+
- **`__ABS_ISLAND_HMR__` island updates carry an optional `stylePath`**
|
|
33
|
+
The dev-only `Window.__ABS_ISLAND_HMR__` hook (types/globals.d.ts) takes an optional `stylePath` per island update: the rebuilt island stylesheet the island runtime swaps in for the one the page links.
|
|
34
|
+
|
|
35
|
+
## 0.20.0-beta.177 — 2026-11-14
|
|
36
|
+
|
|
37
|
+
### Fixed
|
|
38
|
+
|
|
39
|
+
- **A hot swap keeps shared resources open wherever `.use(networking)` sits in the app chain**
|
|
40
|
+
beta.176 kept an unchanged app's `onStop` from running on a hot swap, but only when `networking` was the last thing chained onto the app. `networking` swaps apps while the statement that builds the app is still running, so in `app.use(networking).onStop(shutdown)` the new app did not have its `onStop` yet when the hooks were compared. The swap decided the hooks had changed and shut the replaced app down, closing the database pool, audit log and queues the new app keeps. The swap now waits for that statement to finish before comparing, so the order of `.use(networking)` and the app's lifecycle hooks no longer matters.
|
|
41
|
+
|
|
9
42
|
## 0.20.0-beta.176 — 2026-11-14
|
|
10
43
|
|
|
11
44
|
### Fixed
|
package/changelog.json
CHANGED
|
@@ -2,6 +2,68 @@
|
|
|
2
2
|
"contract": 1,
|
|
3
3
|
"name": "@absolutejs/absolute",
|
|
4
4
|
"releases": [
|
|
5
|
+
{
|
|
6
|
+
"changes": [
|
|
7
|
+
{
|
|
8
|
+
"detail": "Elysia routes a request for `//` to the `/` route, but the request URL keeps both slashes, and the page handlers passed that path on as the URL to render. Angular's server renderer reads `//` as a protocol-relative URL, so `GET //` on an Angular page at `/` returned a 500 (NG05701) in production. The URL a page handler renders for now has repeated slashes collapsed (`//` becomes `/`, `//a//b` becomes `/a/b`; the query string is untouched). The same applies to the `url` the React and Svelte page handlers pass in props and to the URL the Vue router renders.",
|
|
9
|
+
"kind": "fixed",
|
|
10
|
+
"summary": "`GET //` no longer returns a 500 on an Angular page"
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
"detail": "A project folder copied while its dev server was running carried `.absolutejs/build.lock` along, and the copy refused to start with \"AbsoluteJS build lock is held by PID …\", naming the process that serves the original folder. The lock file now records the real path of the project it belongs to, and a lock written for a different path is removed with a warning instead of blocking. Lock files written by earlier versions (without a path) still block while their process is alive.",
|
|
14
|
+
"kind": "fixed",
|
|
15
|
+
"summary": "A copied project no longer inherits the original's build lock"
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
"detail": "The dev-only `Window.__ABS_ISLAND_HMR__` hook (types/globals.d.ts) takes an optional `stylePath` per island update: the rebuilt island stylesheet the island runtime swaps in for the one the page links.",
|
|
19
|
+
"kind": "internal",
|
|
20
|
+
"summary": "`__ABS_ISLAND_HMR__` island updates carry an optional `stylePath`"
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
"detail": "Saving a React page, or a component it imports, now sends one hot update instead of two. The backend route file that imports the page was counted as part of the change, so every save ran a full rebuild right after the fast update and the browser received a second update (logged as \"applied\" twice). On pages that render an <Island>, those edits often never appeared until a reload; the first edit after boot could fail the same way on any React page. The browser also applies React updates one at a time now: an update that arrives while another is still loading waits for it, and the newest modules are always the ones applied.",
|
|
24
|
+
"kind": "fixed",
|
|
25
|
+
"summary": "React page and component edits on pages with islands apply on every save"
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
"detail": "A Svelte island with a `<style>` block had its styles injected at runtime as an inline `<style>` element, which `secureHeaders()` (a nonce-based `style-src`) blocked on every page load, in dev and production, so the island rendered unstyled with a CSP violation. A Vue island's `<style>` / `<style scoped>` was never shipped at all, and its server render stamped a different scope id than the client build used. Island styles (including those of child components and CSS an island imports) are now built into a stylesheet per island, `islands/<framework>/<Name>.<hash>.css`, and the server links it, with the request's CSP nonce, from every page that renders the island, once however many times the island appears, and from no page that doesn't. HTML, HTMX, Svelte, Angular and Vue pages link it in the head; a React page renders it as a stylesheet resource React hoists into the head; a streamed Vue page (streaming slots) renders it just before the island, and hydration reproduces it without a mismatch. An island that arrives later (an HTMX swap) links its stylesheet before it hydrates, and in dev an island style edit swaps the stylesheet in place, wherever it was linked.",
|
|
29
|
+
"kind": "fixed",
|
|
30
|
+
"summary": "Svelte and Vue island styles ship as linked stylesheets, only on pages that render the island: no CSP violations under secureHeaders(), and Vue island styles apply"
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
"detail": "With a not-found convention page (for example `not-found.html`), every unmatched request got that HTML page with status 404, including fetch and API clients sending `Accept: application/json`. The not-found convention now only answers page requests (a browser navigation, `Accept: text/html`, or an HTMX request), the same rule `error.html` already used for errors thrown by routes. Other requests get Elysia's JSON 404.",
|
|
34
|
+
"kind": "fixed",
|
|
35
|
+
"summary": "JSON requests to unknown routes get a JSON 404, not the not-found page"
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
"detail": "A `SuspenseSlot` from `@absolutejs/absolute/react/components` used inside a React Server Component with React content (`fallback` plus `resolve`, `promise` or a render-prop `children`) stayed on its fallback forever in dev and production, with no error. Its content was rendered with `react-dom/server`, which React does not allow in server components, so the slot failed silently. The content is now rendered through the page's own Flight server and SSR renderer. An RSC page also holds streamed slot content back until it has hydrated, so a React-node fallback no longer causes a hydration mismatch that put every slot on the page back on its fallback. Slots that use `fallbackHtml` and return HTML strings, and `StreamSlot`, already worked and are unchanged.",
|
|
39
|
+
"kind": "fixed",
|
|
40
|
+
"summary": "SuspenseSlot with React content now resolves inside React Server Components"
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
"detail": "Since beta.172, `absolute typecheck` in a project with Vue ran vue-check in place of bun check rather than alongside it. vue-check can't see the declarations generated for Svelte components, so a wrong Svelte page prop in a server file passed, and plain TypeScript errors (a wrong React prop) were reported under `vue-check`. Every configured framework's checker now runs: bun check (or tsc) for TypeScript, React and Svelte page props in server files, svelte-check for `.svelte` files, vue-check (or vue-tsc) for `.vue` files and Vue page props, and ngc for Angular templates. Each reports under its own label, an error both TypeScript checkers find is reported once (by bun check), and the check fails if any checker fails. So that bun check can read server code that imports `.vue` files, it gets a generated per-component shim; it does not collide with a project's own `declare module '*.vue'`.",
|
|
44
|
+
"kind": "fixed",
|
|
45
|
+
"summary": "`absolute typecheck` checks Svelte page props again in projects that also use Vue, and labels each error with the checker that found it"
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
"detail": "A Vue page rendered without streaming slots (the default) left out the island manifest and bootstrap scripts, so the islands it server-rendered never hydrated: they showed their server markup and stayed inert. Those pages now get the island scripts, and the stylesheets of the islands they render, in the head, like every other host page.",
|
|
49
|
+
"kind": "fixed",
|
|
50
|
+
"summary": "Islands on Vue pages hydrate again"
|
|
51
|
+
}
|
|
52
|
+
],
|
|
53
|
+
"date": "2026-11-14",
|
|
54
|
+
"version": "0.20.0-beta.178"
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
"changes": [
|
|
58
|
+
{
|
|
59
|
+
"detail": "beta.176 kept an unchanged app's `onStop` from running on a hot swap, but only when `networking` was the last thing chained onto the app. `networking` swaps apps while the statement that builds the app is still running, so in `app.use(networking).onStop(shutdown)` the new app did not have its `onStop` yet when the hooks were compared. The swap decided the hooks had changed and shut the replaced app down, closing the database pool, audit log and queues the new app keeps. The swap now waits for that statement to finish before comparing, so the order of `.use(networking)` and the app's lifecycle hooks no longer matters.",
|
|
60
|
+
"kind": "fixed",
|
|
61
|
+
"summary": "A hot swap keeps shared resources open wherever `.use(networking)` sits in the app chain"
|
|
62
|
+
}
|
|
63
|
+
],
|
|
64
|
+
"date": "2026-11-14",
|
|
65
|
+
"version": "0.20.0-beta.177"
|
|
66
|
+
},
|
|
5
67
|
{
|
|
6
68
|
"changes": [
|
|
7
69
|
{
|
package/dist/angular/browser.js
CHANGED
|
@@ -111,7 +111,7 @@ var ISLAND_BOOTSTRAP_MANIFEST_KEY = "AbsoluteIslandBootstrap", LEGACY_ISLAND_BOO
|
|
|
111
111
|
islands[framework] = entries;
|
|
112
112
|
}
|
|
113
113
|
return islands;
|
|
114
|
-
}, getIslandManifestKey = (framework, component) => `Island${toIslandFrameworkSegment(framework)}${component}`;
|
|
114
|
+
}, getIslandManifestKey = (framework, component) => `Island${toIslandFrameworkSegment(framework)}${component}`, ISLAND_STYLE_PREFIX = "IslandStyle", getIslandStyleManifestEntries = (manifest) => Object.entries(manifest).filter(([key]) => key.startsWith(ISLAND_STYLE_PREFIX)), getIslandStyleManifestKey = (framework, component) => `${ISLAND_STYLE_PREFIX}${toIslandFrameworkSegment(framework)}${component}`;
|
|
115
115
|
|
|
116
116
|
// src/core/islands.ts
|
|
117
117
|
function getIslandComponent(component) {
|
|
@@ -9626,6 +9626,21 @@ var preserveIslandMarkup = (props) => {
|
|
|
9626
9626
|
innerHTML: liveCandidate.innerHTML
|
|
9627
9627
|
};
|
|
9628
9628
|
};
|
|
9629
|
+
var claimedServerIslands = new WeakSet;
|
|
9630
|
+
var claimServerIslandStyleLink = (props) => {
|
|
9631
|
+
if (typeof document === "undefined")
|
|
9632
|
+
return null;
|
|
9633
|
+
const element = Array.from(document.querySelectorAll('[data-island="true"]')).find((candidate) => !claimedServerIslands.has(candidate) && isMatchingIslandElement(candidate, props));
|
|
9634
|
+
if (!element)
|
|
9635
|
+
return null;
|
|
9636
|
+
claimedServerIslands.add(element);
|
|
9637
|
+
const previous = element.previousSibling;
|
|
9638
|
+
if (!(previous instanceof HTMLLinkElement))
|
|
9639
|
+
return null;
|
|
9640
|
+
const key = previous.dataset.islandStyle;
|
|
9641
|
+
const href = previous.getAttribute("href");
|
|
9642
|
+
return key && href ? { href, key } : null;
|
|
9643
|
+
};
|
|
9629
9644
|
var innerHtmlObjects = new Map;
|
|
9630
9645
|
var getStableInnerHtml = (html) => {
|
|
9631
9646
|
const existing = innerHtmlObjects.get(html);
|
|
@@ -10368,5 +10383,5 @@ export {
|
|
|
10368
10383
|
withPendingTask
|
|
10369
10384
|
};
|
|
10370
10385
|
|
|
10371
|
-
//# debugId=
|
|
10386
|
+
//# debugId=774C8D221132DC5A64756E2164756E21
|
|
10372
10387
|
//# sourceMappingURL=browser.js.map
|