@mintlify/package-builder 0.0.15 → 0.0.17
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 +24 -0
- package/package.json +24 -4
package/README.md
CHANGED
|
@@ -12,6 +12,30 @@ Steps:
|
|
|
12
12
|
4. Renders each island in its own child process with `renderToString`, using `identifierPrefix: mi-<id>-` and a 3 s timeout per island, then sanitizes the HTML (256 KB cap). A fresh process per island means module-level counters (lodash `uniqueId`, recharts clip paths, react-select instance ids) start over for every island, so two islands on a page could render the same ids. When the HTML has an `id`, the process renders the island a second time; every id that differs between the two renders (all ids when the second render throws or runs out of time) becomes `mi-<island id>-<old id>`, together with its references in `url(#...)` values, `href`/`xlink:href="#..."` and id-list attributes such as `for` and `aria-labelledby`. Ids from `useId` already carry the prefix, and ids that are the same in both renders, such as a gradient id written in the source, keep their names, so elements React mounts after hydration still find them. React keeps server attributes when it hydrates, so renamed ids stay in the page; the browser's own counter ids never collide with them. Code that runs after hydration only knows the browser's counter values, so an element mounted later that points at a renamed id (a recharts `ReferenceArea` with `ifOverflow="hidden"` shown after load) or a `getElementById` call for one finds nothing; without renaming, that only worked in the first island to hydrate. Islands render one at a time and a process only ever loads one island, so its code can only affect its own result. The parent accepts `start` and then one well-formed `done` (followed by the HTML and the second render's HTML or `null`) or `error` for that island's id, then kills the process; any other message fails that island, except that a malformed or oversized message after the HTML only drops the second render. On Node 20+ the render process runs under `--permission` with read access only to the server bundle and the render script, so an island cannot read other files, write to disk (including rewriting another island's bundle), or spawn a process or worker while it renders. On Windows the builder first renders a probe island under the same flags and drops them if it fails, so a Node permission model that rejects Windows paths degrades to an unsandboxed render instead of failing every island. Results come back as JSON lines on a plain pipe that the parent parses itself, capped at 1M characters per message and 16M characters of HTML, with log entries clipped to 20 of 2,000 characters, and each island's HTML is sanitized before the next island renders, so the builder holds one raw result at a time; Node IPC is not used because its own message handling throws in the parent on crafted input. Anything an island writes to the pipe fails only that island rather than crashing the build. Network egress is not restricted here; the build container blocks it at the container layer, and `mint dev` / `mint packages check` run the project's own code on the developer's machine. `node:sqlite`, which the permission model does not cover, is turned off with `--no-experimental-sqlite`. On Linux the parent stops a render whose resident memory passes `renderMemoryLimitBytes` (2 GiB by default). `npm-ci` and `prepared` builds never render without the permission model; `local` builds warn and render. An island that throws, times out, runs out of memory or cannot be sandboxed is reported as a warning and renders in the browser only.
|
|
13
13
|
5. Writes `manifest.json` with sha384 integrity and gzip sizes.
|
|
14
14
|
|
|
15
|
+
## Shared helpers
|
|
16
|
+
|
|
17
|
+
Use the focused entry points to share build fingerprints, HTML sanitization and types with hosted services:
|
|
18
|
+
|
|
19
|
+
```ts
|
|
20
|
+
import {
|
|
21
|
+
computeBuildId,
|
|
22
|
+
computeDepsHash,
|
|
23
|
+
computeIslandsHash,
|
|
24
|
+
} from '@mintlify/package-builder/hashing';
|
|
25
|
+
import { MAX_ISLAND_HTML_BYTES, sanitizeIslandHtml } from '@mintlify/package-builder/sanitize';
|
|
26
|
+
import type {
|
|
27
|
+
IslandSpec,
|
|
28
|
+
PackageBuildManifest,
|
|
29
|
+
PackagesConfig,
|
|
30
|
+
} from '@mintlify/package-builder/types';
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
The sanitizer entry point uses `entities/decode` and standard JavaScript APIs. The hashing entry point uses `node:crypto` and `node:zlib`, so Cloudflare Workers consuming it need `nodejs_compat`. These imports avoid loading the build, installation, bundling and rendering modules exported by the package root. Type-only imports do not load runtime code.
|
|
34
|
+
|
|
35
|
+
Pin the helper dependency and the build container to the same published package version. A hosted service must still validate and sanitize untrusted container output before publishing it, even when both use the same implementation.
|
|
36
|
+
|
|
37
|
+
The root import, CLI and existing `@mintlify/package-builder/dist/*` imports remain available. The server and Worker can migrate their copied helpers to these entry points after the package is published.
|
|
38
|
+
|
|
15
39
|
## Build hashes
|
|
16
40
|
|
|
17
41
|
`computeDepsHash` and `computeIslandsHash` in `src/hashing.ts` are the one definition of the build keys. The server and the package-builder worker carry ports, and all three must pass `__test__/fixtures/hash-vectors.json` (copied byte for byte into both server tests).
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mintlify/package-builder",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.17",
|
|
4
4
|
"description": "Installs, bundles and server-renders npm package islands for Mintlify docs",
|
|
5
5
|
"engines": {
|
|
6
6
|
"node": ">=18.0.0"
|
|
@@ -28,6 +28,26 @@
|
|
|
28
28
|
},
|
|
29
29
|
"main": "./dist/index.js",
|
|
30
30
|
"types": "./dist/index.d.ts",
|
|
31
|
+
"exports": {
|
|
32
|
+
".": {
|
|
33
|
+
"types": "./dist/index.d.ts",
|
|
34
|
+
"default": "./dist/index.js"
|
|
35
|
+
},
|
|
36
|
+
"./hashing": {
|
|
37
|
+
"types": "./dist/hashing.d.ts",
|
|
38
|
+
"default": "./dist/hashing.js"
|
|
39
|
+
},
|
|
40
|
+
"./sanitize": {
|
|
41
|
+
"types": "./dist/sanitize.d.ts",
|
|
42
|
+
"default": "./dist/sanitize.js"
|
|
43
|
+
},
|
|
44
|
+
"./types": {
|
|
45
|
+
"types": "./dist/types.d.ts",
|
|
46
|
+
"default": "./dist/types.js"
|
|
47
|
+
},
|
|
48
|
+
"./package.json": "./package.json",
|
|
49
|
+
"./dist/*": "./dist/*"
|
|
50
|
+
},
|
|
31
51
|
"bin": {
|
|
32
52
|
"mint-package-builder": "./dist/cli.js"
|
|
33
53
|
},
|
|
@@ -53,9 +73,9 @@
|
|
|
53
73
|
"semver": "7.7.4"
|
|
54
74
|
},
|
|
55
75
|
"devDependencies": {
|
|
56
|
-
"@mintlify/common": "1.0.
|
|
76
|
+
"@mintlify/common": "1.0.1230",
|
|
57
77
|
"@mintlify/ts-config": "2.0.2",
|
|
58
|
-
"@mintlify/validation": "0.1.
|
|
78
|
+
"@mintlify/validation": "0.1.904",
|
|
59
79
|
"@tsconfig/recommended": "1.0.2",
|
|
60
80
|
"@types/js-yaml": "4.0.9",
|
|
61
81
|
"@types/node": "18.19.21",
|
|
@@ -72,5 +92,5 @@
|
|
|
72
92
|
"typescript": "5.5.3",
|
|
73
93
|
"vitest": "2.1.9"
|
|
74
94
|
},
|
|
75
|
-
"gitHead": "
|
|
95
|
+
"gitHead": "16950ad303f1deae69ce955bac93a411a8cd22df"
|
|
76
96
|
}
|