@takazudo/zfb 0.1.0-next.5 → 0.1.0-next.50
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 +26 -0
- package/bin/zfb.mjs +54 -14
- package/dist/client-script.d.ts +55 -0
- package/dist/client-script.d.ts.map +1 -0
- package/dist/client-script.js +67 -0
- package/dist/client-script.js.map +1 -0
- package/dist/config.d.ts +467 -14
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js.map +1 -1
- package/dist/content.d.ts +42 -1
- package/dist/content.d.ts.map +1 -1
- package/dist/content.js +100 -27
- package/dist/content.js.map +1 -1
- package/dist/index.d.ts +4 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/dist/island.d.ts +10 -0
- package/dist/island.d.ts.map +1 -1
- package/dist/island.js +67 -28
- package/dist/island.js.map +1 -1
- package/dist/jsx-types.d.ts +16 -6
- package/dist/jsx-types.d.ts.map +1 -1
- package/dist/runtime.d.ts +6 -0
- package/dist/runtime.d.ts.map +1 -1
- package/dist/runtime.js +161 -25
- package/dist/runtime.js.map +1 -1
- package/dist/slugify.d.ts +69 -0
- package/dist/slugify.d.ts.map +1 -0
- package/dist/slugify.js +197 -0
- package/dist/slugify.js.map +1 -0
- package/dist/types.d.ts +4 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +2 -2
- package/dist/types.js.map +1 -1
- package/package.json +14 -7
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,32 @@
|
|
|
2
2
|
|
|
3
3
|
> **Newer releases:** see https://takazudomodular.com/pj/zudo-front-builder/docs/changelog/ for v0.1.0-next.5 and later. Entries below are historical (kept for npm readers).
|
|
4
4
|
|
|
5
|
+
## Unreleased
|
|
6
|
+
|
|
7
|
+
### New features
|
|
8
|
+
|
|
9
|
+
**`VNode`, `VNodeArray`, `VNodeObject` exported from `"@takazudo/zfb"`** (#972):
|
|
10
|
+
|
|
11
|
+
The structural JSX-node types are now part of the public API:
|
|
12
|
+
|
|
13
|
+
```ts
|
|
14
|
+
import type { VNode, VNodeArray, VNodeObject } from "@takazudo/zfb";
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
`VNode` now includes a bare `object` member (matching Preact's own `ComponentChild` design), making Preact's `ComponentChildren`, `VNode<Props>`, `JSX.Element`, and `JSX.Element[]` all assignable at `Island` input boundaries (`children` and `ssrFallback`) with zero `as unknown as` casts.
|
|
18
|
+
|
|
19
|
+
**Name-collision caveat for Preact consumers:** if a consumer file already has `import { VNode } from "preact"`, use a qualified import to avoid the clash:
|
|
20
|
+
|
|
21
|
+
```ts
|
|
22
|
+
import type { VNode as ZfbVNode } from "@takazudo/zfb";
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
### Breaking changes (pre-1.0)
|
|
26
|
+
|
|
27
|
+
**`linkValidation.allowExternal` removed** (#925):
|
|
28
|
+
|
|
29
|
+
The `allowExternal` config knob has been removed. It was accepted but never did anything — external URL network validation is out of scope. Migration: delete `allowExternal` from your `linkValidation` config; external URLs continue to be silently skipped (unchanged runtime behaviour).
|
|
30
|
+
|
|
5
31
|
## 0.1.0-next.4
|
|
6
32
|
|
|
7
33
|
### Bug fixes
|
package/bin/zfb.mjs
CHANGED
|
@@ -1,9 +1,14 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
// Followed biome's pattern: pure os/cpu lookup → resolve platform package → spawn binary.
|
|
3
3
|
// See: https://github.com/biomejs/biome (packages/js/biome/bin/biome.mjs reference)
|
|
4
|
+
// Divergence from biome: async spawn + signal forwarding instead of spawnSync.
|
|
5
|
+
// biome is a short-lived CLI, but `zfb dev` is a long-running server — without
|
|
6
|
+
// forwarding, SIGTERM to the wrapper orphans the native binary (PPID 1) and
|
|
7
|
+
// leaves the dev-server port bound (issue #873).
|
|
4
8
|
import { existsSync } from "node:fs";
|
|
5
|
-
import {
|
|
9
|
+
import { spawn } from "node:child_process";
|
|
6
10
|
import { createRequire } from "node:module";
|
|
11
|
+
import { constants as osConstants } from "node:os";
|
|
7
12
|
import { join } from "node:path";
|
|
8
13
|
|
|
9
14
|
const require = createRequire(import.meta.url);
|
|
@@ -57,26 +62,61 @@ if (!existsSync(binPath)) {
|
|
|
57
62
|
process.exit(1);
|
|
58
63
|
}
|
|
59
64
|
|
|
60
|
-
const
|
|
65
|
+
const child = spawn(binPath, process.argv.slice(2), { stdio: "inherit" });
|
|
61
66
|
|
|
62
|
-
//
|
|
63
|
-
//
|
|
64
|
-
//
|
|
65
|
-
//
|
|
66
|
-
//
|
|
67
|
-
|
|
68
|
-
|
|
67
|
+
// Forward termination signals to the child. Supervisors (concurrently
|
|
68
|
+
// --kill-others, Playwright webServer teardown, timeout(1), CI runners)
|
|
69
|
+
// signal only the wrapper; without forwarding, the native server survives
|
|
70
|
+
// with PPID 1 and keeps its port bound. Terminal Ctrl+C already signals the
|
|
71
|
+
// whole foreground group, so the child may receive SIGINT twice — the native
|
|
72
|
+
// binary treats repeated signals as the same shutdown request.
|
|
73
|
+
// SIGHUP is POSIX-only: on Windows child.kill("SIGHUP") throws (libuv only
|
|
74
|
+
// emulates SIGINT/SIGTERM/SIGKILL/SIGQUIT), and the OS tears down console
|
|
75
|
+
// processes on window close anyway.
|
|
76
|
+
const forwardedSignals =
|
|
77
|
+
process.platform === "win32" ? ["SIGINT", "SIGTERM"] : ["SIGINT", "SIGTERM", "SIGHUP"];
|
|
78
|
+
const signalForwarders = new Map();
|
|
79
|
+
for (const sig of forwardedSignals) {
|
|
80
|
+
const forward = () => child.kill(sig);
|
|
81
|
+
signalForwarders.set(sig, forward);
|
|
82
|
+
process.on(sig, forward);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// Surface spawn failures clearly. Without this, a 0644 binary (EACCES) is
|
|
86
|
+
// silently swallowed and the process exits with code 1 and no message —
|
|
87
|
+
// making it impossible for the user to diagnose a corrupted/incomplete npm
|
|
88
|
+
// install. (Issue #447 / #441 — pnpm publish strips the executable bit.)
|
|
89
|
+
child.on("error", (error) => {
|
|
90
|
+
if (error.code === "EACCES") {
|
|
69
91
|
process.stderr.write(
|
|
70
92
|
`[zfb] binary is not executable; was the install corrupt?\n` +
|
|
71
93
|
` ${binPath}\n` +
|
|
72
94
|
` Try reinstalling: npm install --include=optional\n`,
|
|
73
95
|
);
|
|
74
96
|
} else {
|
|
75
|
-
process.stderr.write(
|
|
76
|
-
`[zfb] failed to spawn binary: ${result.error.message}\n` + ` ${binPath}\n`,
|
|
77
|
-
);
|
|
97
|
+
process.stderr.write(`[zfb] failed to spawn binary: ${error.message}\n` + ` ${binPath}\n`);
|
|
78
98
|
}
|
|
79
99
|
process.exit(1);
|
|
80
|
-
}
|
|
100
|
+
});
|
|
81
101
|
|
|
82
|
-
|
|
102
|
+
child.on("exit", (code, signal) => {
|
|
103
|
+
if (signal) {
|
|
104
|
+
// Re-raise the child's termination signal on ourselves so the caller
|
|
105
|
+
// sees the real cause of death (e.g. WIFSIGNALED), not a plain exit code.
|
|
106
|
+
// Remove our forwarding listener first or it would swallow the re-raise.
|
|
107
|
+
const forward = signalForwarders.get(signal);
|
|
108
|
+
if (forward) {
|
|
109
|
+
process.off(signal, forward);
|
|
110
|
+
}
|
|
111
|
+
try {
|
|
112
|
+
process.kill(process.pid, signal);
|
|
113
|
+
} catch {
|
|
114
|
+
// Signal cannot be re-raised on this platform (Windows emulation).
|
|
115
|
+
}
|
|
116
|
+
// Reached only if the re-raised signal did not terminate us — fall back
|
|
117
|
+
// to the shell's 128+n convention for death-by-signal.
|
|
118
|
+
const signum = osConstants.signals[signal];
|
|
119
|
+
process.exit(signum ? 128 + signum : 1);
|
|
120
|
+
}
|
|
121
|
+
process.exit(code ?? 1);
|
|
122
|
+
});
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SSR helper for referencing a client-script asset URL in a page or layout.
|
|
3
|
+
*
|
|
4
|
+
* ## Usage
|
|
5
|
+
*
|
|
6
|
+
* ```tsx
|
|
7
|
+
* import { clientScript } from "@takazudo/zfb";
|
|
8
|
+
*
|
|
9
|
+
* export default function MyPage() {
|
|
10
|
+
* return (
|
|
11
|
+
* <html>
|
|
12
|
+
* <head>
|
|
13
|
+
* <script type="module" src={clientScript("search-widget")} />
|
|
14
|
+
* </head>
|
|
15
|
+
* <body>…</body>
|
|
16
|
+
* </html>
|
|
17
|
+
* );
|
|
18
|
+
* }
|
|
19
|
+
* ```
|
|
20
|
+
*
|
|
21
|
+
* ## How it works
|
|
22
|
+
*
|
|
23
|
+
* `clientScript(name)` returns the **stable URL** for the named client-script
|
|
24
|
+
* entry: `${base}/assets/client/<name>.js`. The production build pipeline
|
|
25
|
+
* (`ProductionAssetPipeline`) rewrites every occurrence of this stable URL in
|
|
26
|
+
* rendered HTML to the content-hashed equivalent
|
|
27
|
+
* (`/assets/client/<name>-<hash>.js`), so the hash never needs to be known at
|
|
28
|
+
* SSR time.
|
|
29
|
+
*
|
|
30
|
+
* The `base` prefix is read from `globalThis.__zfb?.base` (emitted by the
|
|
31
|
+
* bundler when at least one `*.client.*` file exists in the project). For
|
|
32
|
+
* root-mounted sites (`base` is absent or `"/"`), the prefix is the empty
|
|
33
|
+
* string and `clientScript("search-widget")` returns
|
|
34
|
+
* `"/assets/client/search-widget.js"`. For a sub-path deploy
|
|
35
|
+
* (`base="/foo/"`), it returns `"/foo/assets/client/search-widget.js"`.
|
|
36
|
+
*
|
|
37
|
+
* ## SSR-only note (v1)
|
|
38
|
+
*
|
|
39
|
+
* This is an SSR-time helper. Calling it in browser-executed code works but
|
|
40
|
+
* the base prefix (`globalThis.__zfb.base`) is currently not shipped to the
|
|
41
|
+
* browser — `clientScript()` will return the unprefixed stable URL
|
|
42
|
+
* (`/assets/client/<name>.js`) in that context. For the common use-case of
|
|
43
|
+
* rendering a `<script src>` tag at SSR time this is not a problem.
|
|
44
|
+
*/
|
|
45
|
+
/**
|
|
46
|
+
* Returns the base-prefixed stable public URL for the named client-script entry.
|
|
47
|
+
*
|
|
48
|
+
* `name` is the entry name (file stem minus `.client`, e.g. `"search-widget"`
|
|
49
|
+
* for `search-widget.client.ts`).
|
|
50
|
+
*
|
|
51
|
+
* The returned URL is `${base}/assets/client/<name>.js`. The production
|
|
52
|
+
* pipeline rewrites it to the hashed URL; dev serves the stable URL directly.
|
|
53
|
+
*/
|
|
54
|
+
export declare function clientScript(name: string): string;
|
|
55
|
+
//# sourceMappingURL=client-script.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client-script.d.ts","sourceRoot":"","sources":["../src/client-script.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AAKH;;;;;;;;GAQG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAUjD"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SSR helper for referencing a client-script asset URL in a page or layout.
|
|
3
|
+
*
|
|
4
|
+
* ## Usage
|
|
5
|
+
*
|
|
6
|
+
* ```tsx
|
|
7
|
+
* import { clientScript } from "@takazudo/zfb";
|
|
8
|
+
*
|
|
9
|
+
* export default function MyPage() {
|
|
10
|
+
* return (
|
|
11
|
+
* <html>
|
|
12
|
+
* <head>
|
|
13
|
+
* <script type="module" src={clientScript("search-widget")} />
|
|
14
|
+
* </head>
|
|
15
|
+
* <body>…</body>
|
|
16
|
+
* </html>
|
|
17
|
+
* );
|
|
18
|
+
* }
|
|
19
|
+
* ```
|
|
20
|
+
*
|
|
21
|
+
* ## How it works
|
|
22
|
+
*
|
|
23
|
+
* `clientScript(name)` returns the **stable URL** for the named client-script
|
|
24
|
+
* entry: `${base}/assets/client/<name>.js`. The production build pipeline
|
|
25
|
+
* (`ProductionAssetPipeline`) rewrites every occurrence of this stable URL in
|
|
26
|
+
* rendered HTML to the content-hashed equivalent
|
|
27
|
+
* (`/assets/client/<name>-<hash>.js`), so the hash never needs to be known at
|
|
28
|
+
* SSR time.
|
|
29
|
+
*
|
|
30
|
+
* The `base` prefix is read from `globalThis.__zfb?.base` (emitted by the
|
|
31
|
+
* bundler when at least one `*.client.*` file exists in the project). For
|
|
32
|
+
* root-mounted sites (`base` is absent or `"/"`), the prefix is the empty
|
|
33
|
+
* string and `clientScript("search-widget")` returns
|
|
34
|
+
* `"/assets/client/search-widget.js"`. For a sub-path deploy
|
|
35
|
+
* (`base="/foo/"`), it returns `"/foo/assets/client/search-widget.js"`.
|
|
36
|
+
*
|
|
37
|
+
* ## SSR-only note (v1)
|
|
38
|
+
*
|
|
39
|
+
* This is an SSR-time helper. Calling it in browser-executed code works but
|
|
40
|
+
* the base prefix (`globalThis.__zfb.base`) is currently not shipped to the
|
|
41
|
+
* browser — `clientScript()` will return the unprefixed stable URL
|
|
42
|
+
* (`/assets/client/<name>.js`) in that context. For the common use-case of
|
|
43
|
+
* rendering a `<script src>` tag at SSR time this is not a problem.
|
|
44
|
+
*/
|
|
45
|
+
/** Stable public-URL prefix for client-script entries, matching the Rust constant. */
|
|
46
|
+
const CLIENT_SCRIPTS_URL_PREFIX = "/assets/client/";
|
|
47
|
+
/**
|
|
48
|
+
* Returns the base-prefixed stable public URL for the named client-script entry.
|
|
49
|
+
*
|
|
50
|
+
* `name` is the entry name (file stem minus `.client`, e.g. `"search-widget"`
|
|
51
|
+
* for `search-widget.client.ts`).
|
|
52
|
+
*
|
|
53
|
+
* The returned URL is `${base}/assets/client/<name>.js`. The production
|
|
54
|
+
* pipeline rewrites it to the hashed URL; dev serves the stable URL directly.
|
|
55
|
+
*/
|
|
56
|
+
export function clientScript(name) {
|
|
57
|
+
// `globalThis.__zfb?.base` is set to the resolved base prefix by the
|
|
58
|
+
// bundler when the project has at least one `*.client.*` entry (#978).
|
|
59
|
+
// For root-mounted or no-base builds the value is `""`, yielding
|
|
60
|
+
// `/assets/client/<name>.js` as expected. The `?? ""` fallback handles
|
|
61
|
+
// the edge case where __zfb.base was not emitted (zero-script project,
|
|
62
|
+
// or a browser context where the slot was never populated).
|
|
63
|
+
const base = globalThis.__zfb;
|
|
64
|
+
const prefix = base?.base ?? "";
|
|
65
|
+
return `${prefix}${CLIENT_SCRIPTS_URL_PREFIX}${name}.js`;
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=client-script.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client-script.js","sourceRoot":"","sources":["../src/client-script.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AAEH,sFAAsF;AACtF,MAAM,yBAAyB,GAAG,iBAAiB,CAAC;AAEpD;;;;;;;;GAQG;AACH,MAAM,UAAU,YAAY,CAAC,IAAY;IACvC,qEAAqE;IACrE,uEAAuE;IACvE,iEAAiE;IACjE,uEAAuE;IACvE,uEAAuE;IACvE,4DAA4D;IAC5D,MAAM,IAAI,GAAI,UAAsC,CAAC,KAAsC,CAAC;IAC5F,MAAM,MAAM,GAAG,IAAI,EAAE,IAAI,IAAI,EAAE,CAAC;IAChC,OAAO,GAAG,MAAM,GAAG,yBAAyB,GAAG,IAAI,KAAK,CAAC;AAC3D,CAAC"}
|