@uniweb/unipress 0.4.27 → 0.4.29

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.
@@ -0,0 +1,138 @@
1
+ // Single-instance linkage for dynamically imported foundations.
2
+ //
3
+ // A built foundation externalizes its peer deps — react, react-dom,
4
+ // react-dom/server, react/jsx-runtime, react/jsx-dev-runtime, @uniweb/core
5
+ // (the set in @uniweb/build's foundation/config.js DEFAULT_EXTERNALS). When
6
+ // unipress fetches a foundation to its cache and dynamically imports the built
7
+ // entry.js, those bare imports must resolve to unipress's OWN copies so the
8
+ // foundation shares one React instance with @uniweb/runtime/ssr and one
9
+ // @uniweb/core with the Website graph the orchestrator builds.
10
+ //
11
+ // The old approach symlinked unipress's node_modules copies beside the cached
12
+ // entry. That relies on those copies existing on disk and being locatable via
13
+ // require.resolve — which fails in the `bun --compile` standalone binary: the
14
+ // deps are bundled INTO the binary, and require.resolve does CWD-relative
15
+ // resolution, so it finds nothing when unipress runs from a project (like a
16
+ // loose book folder) that has no react up its directory tree. The symlink step
17
+ // then produced an empty node_modules and the foundation import failed with
18
+ // "Cannot find module 'react/jsx-runtime'".
19
+ //
20
+ // Instead we mirror @uniweb/runtime's worker-isolate shims (its
21
+ // build-worker.js): publish each package on a globalThis bridge here, and write
22
+ // tiny shim modules into the cache's co-located node_modules (see
23
+ // writeExternalShims in foundation-fetch.js) that re-export from the bridge.
24
+ // Bun/Node resolve the foundation's bare imports to the shims (nearest
25
+ // node_modules wins); each shim reads the bridge and yields unipress's exact
26
+ // instance — no on-disk package needed, works identically in the compiled
27
+ // binary and in source/npm mode.
28
+ //
29
+ // Why globalThis rather than a direct import inside the shim: the shim lives on
30
+ // disk beside the foundation; an `import 'react'` from it would re-enter
31
+ // resolution (and in the binary resolve to nothing). Reading a global sidesteps
32
+ // module resolution entirely — the same reason the isolate uses it.
33
+ //
34
+ // Importing this module has the SIDE EFFECT of setting the globalThis bridges,
35
+ // so it must be imported before any foundation is dynamically imported. Both
36
+ // foundation-fetch.js (which writes the shims) and orchestrator.js (which does
37
+ // the import) import it; ESM evaluates it once.
38
+
39
+ import * as React from 'react'
40
+ import * as ReactJsxRuntime from 'react/jsx-runtime'
41
+ import * as ReactJsxDevRuntime from 'react/jsx-dev-runtime'
42
+ import * as ReactDom from 'react-dom'
43
+ import * as ReactDomServer from 'react-dom/server'
44
+ import * as UniwebCore from '@uniweb/core'
45
+
46
+ // globalThis bridge keys. Namespaced to unipress so they never collide with
47
+ // @uniweb/runtime's worker isolate (__PLATFORM_*), which a foundation could
48
+ // conceivably bundle into the same realm.
49
+ const REACT_KEY = '__UNIPRESS_REACT'
50
+ const JSX_RUNTIME_KEY = '__UNIPRESS_JSX_RUNTIME'
51
+ const JSX_DEV_RUNTIME_KEY = '__UNIPRESS_JSX_DEV_RUNTIME'
52
+ const REACT_DOM_KEY = '__UNIPRESS_REACT_DOM'
53
+ const REACT_DOM_SERVER_KEY = '__UNIPRESS_REACT_DOM_SERVER'
54
+ const UNIWEB_CORE_KEY = '__UNIPRESS_UNIWEB_CORE'
55
+
56
+ globalThis[REACT_KEY] = React
57
+ globalThis[JSX_RUNTIME_KEY] = ReactJsxRuntime
58
+ globalThis[JSX_DEV_RUNTIME_KEY] = ReactJsxDevRuntime
59
+ globalThis[REACT_DOM_KEY] = ReactDom
60
+ globalThis[REACT_DOM_SERVER_KEY] = ReactDomServer
61
+ globalThis[UNIWEB_CORE_KEY] = UniwebCore
62
+
63
+ const VALID_IDENTIFIER = /^[A-Za-z_$][A-Za-z0-9_$]*$/
64
+
65
+ // Generate an ESM shim module that re-exports every named export of `ns` from
66
+ // the globalThis bridge. Names are enumerated from the live namespace (as
67
+ // build-worker.js does) so the shim tracks the actual React / core surface
68
+ // without a hardcoded list. Non-identifier keys (e.g. "module.exports" from CJS
69
+ // interop) are skipped; `default` is re-exported explicitly.
70
+ function shimSource(globalKey, ns) {
71
+ const names = Object.keys(ns).filter(
72
+ (name) => name !== 'default' && VALID_IDENTIFIER.test(name)
73
+ )
74
+ return [
75
+ `// AUTO-GENERATED by unipress — re-exports from globalThis.${globalKey}.`,
76
+ `// unipress publishes its own bundled instance there (see runtime-externals.js),`,
77
+ `// giving this dynamically-imported foundation the SAME instance unipress uses.`,
78
+ `const __ns = globalThis.${globalKey}`,
79
+ `export default __ns?.default ?? __ns`,
80
+ ...names.map((name) => `export const ${name} = __ns.${name}`),
81
+ ''
82
+ ].join('\n')
83
+ }
84
+
85
+ function modulePackageJson(name, exportsMap) {
86
+ return JSON.stringify(
87
+ {
88
+ name,
89
+ type: 'module',
90
+ exports: { ...exportsMap, './package.json': './package.json' }
91
+ },
92
+ null,
93
+ 2
94
+ )
95
+ }
96
+
97
+ // The shim packages to lay into a fetched foundation's co-located node_modules.
98
+ // Each entry: the package directory (relative to node_modules, POSIX-style),
99
+ // its package.json text, and the shim files keyed by relative path. Subpath
100
+ // specifiers (react/jsx-runtime, react-dom/server) are served through the
101
+ // package's `exports` map so Node/Bun resolve them to the right shim file.
102
+ export function externalShimPackages() {
103
+ return [
104
+ {
105
+ dir: 'react',
106
+ packageJson: modulePackageJson('react', {
107
+ '.': './index.js',
108
+ './jsx-runtime': './jsx-runtime.js',
109
+ './jsx-dev-runtime': './jsx-dev-runtime.js'
110
+ }),
111
+ files: {
112
+ 'index.js': shimSource(REACT_KEY, React),
113
+ 'jsx-runtime.js': shimSource(JSX_RUNTIME_KEY, ReactJsxRuntime),
114
+ 'jsx-dev-runtime.js': shimSource(JSX_DEV_RUNTIME_KEY, ReactJsxDevRuntime)
115
+ }
116
+ },
117
+ {
118
+ dir: 'react-dom',
119
+ packageJson: modulePackageJson('react-dom', {
120
+ '.': './index.js',
121
+ './server': './server.js'
122
+ }),
123
+ files: {
124
+ 'index.js': shimSource(REACT_DOM_KEY, ReactDom),
125
+ 'server.js': shimSource(REACT_DOM_SERVER_KEY, ReactDomServer)
126
+ }
127
+ },
128
+ {
129
+ dir: '@uniweb/core',
130
+ packageJson: modulePackageJson('@uniweb/core', {
131
+ '.': './index.js'
132
+ }),
133
+ files: {
134
+ 'index.js': shimSource(UNIWEB_CORE_KEY, UniwebCore)
135
+ }
136
+ }
137
+ ]
138
+ }