@multiplatform.one/config 6.7.0 → 7.1.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/lib/index.js +2 -2
- package/lib/storybook-CrdwuS_Y.js +274 -0
- package/lib/storybook.js +1 -204
- package/lib/{vite-C6psj1Lz.js → vite-C7884n3X.js} +114 -3
- package/lib/vite.js +2 -2
- package/package.json +5 -4
- package/src/shims/web3Stub.native.js +18 -0
- package/src/storybook.ts +19 -9
- package/src/unexportedDepAliases.spec.ts +90 -0
- package/src/unexportedDepAliases.ts +77 -0
- package/src/vite.spec.ts +148 -0
- package/src/vite.ts +183 -0
- package/types/storybook.d.ts.map +1 -1
- package/types/unexportedDepAliases.d.ts +16 -0
- package/types/unexportedDepAliases.d.ts.map +1 -0
- package/types/vite.d.ts +33 -0
- package/types/vite.d.ts.map +1 -1
- /package/lib/{workspacePublicPackages-CkDbm3QT.js → workspacePublicPackages-COicQSj4.js} +0 -0
package/lib/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { t as createViteConfig } from "./vite-
|
|
2
|
-
import { createStorybookViteConfig } from "./storybook.js";
|
|
1
|
+
import { t as createViteConfig } from "./vite-C7884n3X.js";
|
|
2
|
+
import { t as createStorybookViteConfig } from "./storybook-CrdwuS_Y.js";
|
|
3
3
|
import { createVitestConfig } from "./vitest.js";
|
|
4
4
|
|
|
5
5
|
export { createStorybookViteConfig, createViteConfig, createVitestConfig };
|
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
import { r as resolvePackageMainSource, t as discoverPublicPackageRoots } from "./workspacePublicPackages-COicQSj4.js";
|
|
2
|
+
import { createRequire } from "node:module";
|
|
3
|
+
import fs from "node:fs";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
|
|
6
|
+
//#region src/unexportedDepAliases.ts
|
|
7
|
+
/**
|
|
8
|
+
* Package subtrees that consumers deep-import but the publisher never declared
|
|
9
|
+
* in its `exports` map.
|
|
10
|
+
*
|
|
11
|
+
* `one`'s `fork/SSRNavigationContainer` (every dist flavour plus its source)
|
|
12
|
+
* imports three `@react-navigation/core` internals:
|
|
13
|
+
*
|
|
14
|
+
* @react-navigation/core/lib/module/NavigationBuilderContext
|
|
15
|
+
* @react-navigation/core/lib/module/NavigationStateContext
|
|
16
|
+
* @react-navigation/core/lib/module/EnsureSingleNavigator
|
|
17
|
+
*
|
|
18
|
+
* The published package exports only "." and "./package.json", so those are
|
|
19
|
+
* undeclared subpaths of a bare specifier — Node rejects them with
|
|
20
|
+
* ERR_PACKAGE_PATH_NOT_EXPORTED and Rolldown (Vite 8) rejects them at build
|
|
21
|
+
* time. Both are behaving correctly; the deep imports are the bug.
|
|
22
|
+
*
|
|
23
|
+
* vxrn papers over it by rewriting the dependency's package.json in place
|
|
24
|
+
* (`vxrn` builtInDepPatches, which leaves a package.json.vxrn.original behind),
|
|
25
|
+
* but that only runs when something invokes vxrn — never during a plain
|
|
26
|
+
* `vite build` or `storybook build`, and never on a fresh CI install. Mapping
|
|
27
|
+
* the subtree to its real directory resolves those files by path, which is
|
|
28
|
+
* exactly where the missing exports entries would have pointed.
|
|
29
|
+
*/
|
|
30
|
+
const UNEXPORTED_SUBTREES = ["@react-navigation/core/lib/module"];
|
|
31
|
+
/**
|
|
32
|
+
* Vite `resolve.alias` entries that let known-undeclared package internals
|
|
33
|
+
* resolve by filesystem path.
|
|
34
|
+
*
|
|
35
|
+
* Scoped to one subtree of one package: Vite alias keys match the whole
|
|
36
|
+
* specifier or a `key + "/"` prefix, so sibling paths (`lib/moduleOther`) and
|
|
37
|
+
* the package's own entry (`@react-navigation/core`) keep going through the
|
|
38
|
+
* `exports` map. Nothing here disables exports enforcement globally.
|
|
39
|
+
*
|
|
40
|
+
* Entries are omitted when the package (or the target directory) is absent, so
|
|
41
|
+
* consumers that do not install `one`/react-navigation are unaffected.
|
|
42
|
+
*
|
|
43
|
+
* @param root Directory whose `node_modules` the packages resolve from.
|
|
44
|
+
*/
|
|
45
|
+
function unexportedDepAliases(root = process.cwd()) {
|
|
46
|
+
const aliases = {};
|
|
47
|
+
const requireFrom = createRequire(path.join(root, "package.json"));
|
|
48
|
+
for (const specifier of UNEXPORTED_SUBTREES) {
|
|
49
|
+
const [pkgName, subpath] = splitPackageSubpath(specifier);
|
|
50
|
+
const pkgDir = resolvePackageDir(pkgName, root, requireFrom);
|
|
51
|
+
if (!pkgDir) continue;
|
|
52
|
+
const target = path.join(pkgDir, subpath);
|
|
53
|
+
if (fs.existsSync(target)) aliases[specifier] = target;
|
|
54
|
+
}
|
|
55
|
+
return aliases;
|
|
56
|
+
}
|
|
57
|
+
function splitPackageSubpath(specifier) {
|
|
58
|
+
const segments = specifier.split("/");
|
|
59
|
+
const nameLength = specifier.startsWith("@") ? 2 : 1;
|
|
60
|
+
return [segments.slice(0, nameLength).join("/"), segments.slice(nameLength).join("/")];
|
|
61
|
+
}
|
|
62
|
+
function resolvePackageDir(pkgName, root, requireFrom) {
|
|
63
|
+
try {
|
|
64
|
+
return path.dirname(requireFrom.resolve(`${pkgName}/package.json`));
|
|
65
|
+
} catch {
|
|
66
|
+
const hoisted = path.join(root, "node_modules", ...pkgName.split("/"));
|
|
67
|
+
return fs.existsSync(path.join(hoisted, "package.json")) ? hoisted : void 0;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
//#endregion
|
|
72
|
+
//#region src/storybook.ts
|
|
73
|
+
/**
|
|
74
|
+
* Creates a Vite configuration for Storybook in the multiplatform.one monorepo.
|
|
75
|
+
*
|
|
76
|
+
* Auto-discovers packages/ entries (multiplatform.one, package, and root
|
|
77
|
+
* multiplatform.one scopes) and every workspace package under public/ with a
|
|
78
|
+
* package.json name (including other scopes such as bitspur). Aliases point at
|
|
79
|
+
* TypeScript source; sub-path exports come from each package exports field.
|
|
80
|
+
*
|
|
81
|
+
* Includes React plugin, node:async_hooks stub, and Storybook optimizeDeps.
|
|
82
|
+
*
|
|
83
|
+
* @example
|
|
84
|
+
* ```ts
|
|
85
|
+
* // apps/storybook/vite.config.ts
|
|
86
|
+
* import { createStorybookViteConfig } from "@multiplatform.one/config/storybook";
|
|
87
|
+
*
|
|
88
|
+
* export default createStorybookViteConfig();
|
|
89
|
+
* ```
|
|
90
|
+
*/
|
|
91
|
+
function createStorybookViteConfig(options = {}) {
|
|
92
|
+
const workspaceRoot = options.workspaceRoot || findWorkspaceRoot();
|
|
93
|
+
const aliases = {
|
|
94
|
+
...discoverPackageAliases(path.join(workspaceRoot, "packages")),
|
|
95
|
+
...discoverPublicPackageViteAliases(workspaceRoot),
|
|
96
|
+
...unexportedDepAliases(workspaceRoot)
|
|
97
|
+
};
|
|
98
|
+
if (options.aliases) Object.assign(aliases, options.aliases);
|
|
99
|
+
const sortedAliases = {};
|
|
100
|
+
for (const key of Object.keys(aliases).sort((a, b) => b.length - a.length)) sortedAliases[key] = aliases[key];
|
|
101
|
+
return {
|
|
102
|
+
define: {
|
|
103
|
+
"process.env.VITE_ENVIRONMENT": JSON.stringify("client"),
|
|
104
|
+
...options.define
|
|
105
|
+
},
|
|
106
|
+
resolve: {
|
|
107
|
+
conditions: ["default"],
|
|
108
|
+
extensions: [
|
|
109
|
+
".storybook.ts",
|
|
110
|
+
".storybook.tsx",
|
|
111
|
+
".storybook.js",
|
|
112
|
+
".storybook.jsx",
|
|
113
|
+
".web.ts",
|
|
114
|
+
".web.tsx",
|
|
115
|
+
".web.js",
|
|
116
|
+
".web.jsx",
|
|
117
|
+
".ts",
|
|
118
|
+
".tsx",
|
|
119
|
+
".js",
|
|
120
|
+
".jsx",
|
|
121
|
+
".mjs",
|
|
122
|
+
".json"
|
|
123
|
+
],
|
|
124
|
+
alias: sortedAliases
|
|
125
|
+
},
|
|
126
|
+
optimizeDeps: {
|
|
127
|
+
include: [
|
|
128
|
+
"react",
|
|
129
|
+
"react-dom",
|
|
130
|
+
"react-native-web",
|
|
131
|
+
"@tamagui/core",
|
|
132
|
+
"@tamagui/web",
|
|
133
|
+
"@tamagui/helpers-icon",
|
|
134
|
+
"tamagui",
|
|
135
|
+
"@mdx-js/react",
|
|
136
|
+
"i18next",
|
|
137
|
+
"react-i18next",
|
|
138
|
+
"d3-shape",
|
|
139
|
+
"d3-scale",
|
|
140
|
+
"@storybook-community/storybook-dark-mode",
|
|
141
|
+
"use-latest-callback",
|
|
142
|
+
"escape-string-regexp",
|
|
143
|
+
"use-sync-external-store",
|
|
144
|
+
"use-sync-external-store/with-selector",
|
|
145
|
+
"fast-deep-equal",
|
|
146
|
+
"color",
|
|
147
|
+
"query-string",
|
|
148
|
+
"react-is"
|
|
149
|
+
],
|
|
150
|
+
exclude: [
|
|
151
|
+
"one/dist/esm/vite/one-server-only.mjs",
|
|
152
|
+
"@storybook/preview-api",
|
|
153
|
+
"@storybook/theming",
|
|
154
|
+
"@react-navigation/core",
|
|
155
|
+
"@react-navigation/native",
|
|
156
|
+
"@react-navigation/routers",
|
|
157
|
+
"@react-navigation/elements",
|
|
158
|
+
"@react-navigation/bottom-tabs",
|
|
159
|
+
"@react-navigation/native-stack"
|
|
160
|
+
]
|
|
161
|
+
},
|
|
162
|
+
plugins: [nodeAsyncHooksStub(), ...options.plugins || []]
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Scans packages/ for workspace packages (multiplatform.one and package scopes)
|
|
167
|
+
* and returns resolve aliases.
|
|
168
|
+
*/
|
|
169
|
+
function discoverPackageAliases(packagesDir) {
|
|
170
|
+
const aliases = {};
|
|
171
|
+
if (!fs.existsSync(packagesDir)) return aliases;
|
|
172
|
+
const entries = fs.readdirSync(packagesDir, { withFileTypes: true });
|
|
173
|
+
for (const entry of entries) {
|
|
174
|
+
if (!entry.isDirectory()) continue;
|
|
175
|
+
const pkgDir = path.join(packagesDir, entry.name);
|
|
176
|
+
const pkgJsonPath = path.join(pkgDir, "package.json");
|
|
177
|
+
if (!fs.existsSync(pkgJsonPath)) continue;
|
|
178
|
+
let pkgJson;
|
|
179
|
+
try {
|
|
180
|
+
pkgJson = JSON.parse(fs.readFileSync(pkgJsonPath, "utf-8"));
|
|
181
|
+
} catch {
|
|
182
|
+
continue;
|
|
183
|
+
}
|
|
184
|
+
const pkgName = pkgJson.name;
|
|
185
|
+
if (!pkgName) continue;
|
|
186
|
+
if (!pkgName.startsWith("@multiplatform.one/") && !pkgName.startsWith("@package/") && pkgName !== "multiplatform.one") continue;
|
|
187
|
+
mergePackageResolveAliases(pkgDir, pkgName, pkgJson, aliases);
|
|
188
|
+
}
|
|
189
|
+
return aliases;
|
|
190
|
+
}
|
|
191
|
+
/** All workspace packages under public/ (any npm scope), including export subpaths. */
|
|
192
|
+
function discoverPublicPackageViteAliases(workspaceRoot) {
|
|
193
|
+
const aliases = {};
|
|
194
|
+
for (const [pkgName, pkgDir] of discoverPublicPackageRoots(workspaceRoot)) {
|
|
195
|
+
const pkgJsonPath = path.join(pkgDir, "package.json");
|
|
196
|
+
let pkgJson;
|
|
197
|
+
try {
|
|
198
|
+
pkgJson = JSON.parse(fs.readFileSync(pkgJsonPath, "utf-8"));
|
|
199
|
+
} catch {
|
|
200
|
+
continue;
|
|
201
|
+
}
|
|
202
|
+
mergePackageResolveAliases(pkgDir, pkgName, pkgJson, aliases);
|
|
203
|
+
}
|
|
204
|
+
return aliases;
|
|
205
|
+
}
|
|
206
|
+
function mergePackageResolveAliases(pkgDir, pkgName, pkgJson, aliases) {
|
|
207
|
+
const mainEntry = resolvePackageMainSource(pkgDir);
|
|
208
|
+
if (mainEntry) aliases[pkgName] = mainEntry;
|
|
209
|
+
if (pkgJson.exports && typeof pkgJson.exports === "object") for (const exportKey of Object.keys(pkgJson.exports)) {
|
|
210
|
+
if (exportKey === "." || exportKey === "./package.json") continue;
|
|
211
|
+
const subpath = exportKey.replace(/^\.\//, "");
|
|
212
|
+
if (path.extname(subpath)) {
|
|
213
|
+
const parentDir = path.dirname(subpath);
|
|
214
|
+
if (parentDir && parentDir !== ".") {
|
|
215
|
+
const fullParentDir = path.join(pkgDir, parentDir);
|
|
216
|
+
if (fs.existsSync(fullParentDir) && fs.statSync(fullParentDir).isDirectory()) aliases[`${pkgName}/${parentDir}`] = fullParentDir;
|
|
217
|
+
}
|
|
218
|
+
} else {
|
|
219
|
+
const resolved = resolveSubpathSource(pkgDir, subpath);
|
|
220
|
+
if (resolved) aliases[`${pkgName}/${subpath}`] = resolved;
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
function resolveSubpathSource(pkgDir, subpath) {
|
|
225
|
+
const candidates = [
|
|
226
|
+
path.join(pkgDir, "src", `${subpath}.storybook.ts`),
|
|
227
|
+
path.join(pkgDir, "src", `${subpath}.storybook.tsx`),
|
|
228
|
+
path.join(pkgDir, "src", `${subpath}.ts`),
|
|
229
|
+
path.join(pkgDir, "src", `${subpath}.tsx`),
|
|
230
|
+
path.join(pkgDir, "src", subpath, "index.storybook.ts"),
|
|
231
|
+
path.join(pkgDir, "src", subpath, "index.storybook.tsx"),
|
|
232
|
+
path.join(pkgDir, "src", subpath, "index.ts"),
|
|
233
|
+
path.join(pkgDir, "src", subpath, "index.tsx"),
|
|
234
|
+
path.join(pkgDir, `${subpath}.storybook.ts`),
|
|
235
|
+
path.join(pkgDir, `${subpath}.storybook.tsx`),
|
|
236
|
+
path.join(pkgDir, `${subpath}.ts`),
|
|
237
|
+
path.join(pkgDir, `${subpath}.tsx`),
|
|
238
|
+
path.join(pkgDir, subpath, "index.storybook.ts"),
|
|
239
|
+
path.join(pkgDir, subpath, "index.storybook.tsx"),
|
|
240
|
+
path.join(pkgDir, subpath, "index.ts"),
|
|
241
|
+
path.join(pkgDir, subpath, "index.tsx"),
|
|
242
|
+
path.join(pkgDir, subpath, "index.js")
|
|
243
|
+
];
|
|
244
|
+
for (const c of candidates) if (fs.existsSync(c)) return c;
|
|
245
|
+
const dirPath = path.join(pkgDir, subpath);
|
|
246
|
+
if (fs.existsSync(dirPath) && fs.statSync(dirPath).isDirectory()) return dirPath;
|
|
247
|
+
}
|
|
248
|
+
/** Virtual module plugin that stubs `node:async_hooks` for browser environments. */
|
|
249
|
+
function nodeAsyncHooksStub() {
|
|
250
|
+
return {
|
|
251
|
+
name: "storybook:node-async-hooks-stub",
|
|
252
|
+
resolveId(id) {
|
|
253
|
+
if (id === "node:async_hooks") return "\0node:async_hooks";
|
|
254
|
+
},
|
|
255
|
+
load(id) {
|
|
256
|
+
if (id === "\0node:async_hooks") return "export class AsyncLocalStorage {}";
|
|
257
|
+
}
|
|
258
|
+
};
|
|
259
|
+
}
|
|
260
|
+
function findWorkspaceRoot() {
|
|
261
|
+
let dir = process.cwd();
|
|
262
|
+
while (dir !== path.dirname(dir)) {
|
|
263
|
+
if (fs.existsSync(path.join(dir, "pnpm-workspace.yaml"))) return dir;
|
|
264
|
+
const pkgJsonPath = path.join(dir, "package.json");
|
|
265
|
+
if (fs.existsSync(pkgJsonPath)) try {
|
|
266
|
+
if (JSON.parse(fs.readFileSync(pkgJsonPath, "utf-8")).workspaces) return dir;
|
|
267
|
+
} catch {}
|
|
268
|
+
dir = path.dirname(dir);
|
|
269
|
+
}
|
|
270
|
+
return process.cwd();
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
//#endregion
|
|
274
|
+
export { createStorybookViteConfig as t };
|
package/lib/storybook.js
CHANGED
|
@@ -1,206 +1,3 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import fs from "node:fs";
|
|
3
|
-
import path from "node:path";
|
|
1
|
+
import { t as createStorybookViteConfig } from "./storybook-CrdwuS_Y.js";
|
|
4
2
|
|
|
5
|
-
//#region src/storybook.ts
|
|
6
|
-
/**
|
|
7
|
-
* Creates a Vite configuration for Storybook in the multiplatform.one monorepo.
|
|
8
|
-
*
|
|
9
|
-
* Auto-discovers packages/ entries (multiplatform.one, package, and root
|
|
10
|
-
* multiplatform.one scopes) and every workspace package under public/ with a
|
|
11
|
-
* package.json name (including other scopes such as bitspur). Aliases point at
|
|
12
|
-
* TypeScript source; sub-path exports come from each package exports field.
|
|
13
|
-
*
|
|
14
|
-
* Includes React plugin, node:async_hooks stub, and Storybook optimizeDeps.
|
|
15
|
-
*
|
|
16
|
-
* @example
|
|
17
|
-
* ```ts
|
|
18
|
-
* // apps/storybook/vite.config.ts
|
|
19
|
-
* import { createStorybookViteConfig } from "@multiplatform.one/config/storybook";
|
|
20
|
-
*
|
|
21
|
-
* export default createStorybookViteConfig();
|
|
22
|
-
* ```
|
|
23
|
-
*/
|
|
24
|
-
function createStorybookViteConfig(options = {}) {
|
|
25
|
-
const workspaceRoot = options.workspaceRoot || findWorkspaceRoot();
|
|
26
|
-
const aliases = {
|
|
27
|
-
...discoverPackageAliases(path.join(workspaceRoot, "packages")),
|
|
28
|
-
...discoverPublicPackageViteAliases(workspaceRoot)
|
|
29
|
-
};
|
|
30
|
-
if (options.aliases) Object.assign(aliases, options.aliases);
|
|
31
|
-
const sortedAliases = {};
|
|
32
|
-
for (const key of Object.keys(aliases).sort((a, b) => b.length - a.length)) sortedAliases[key] = aliases[key];
|
|
33
|
-
return {
|
|
34
|
-
define: {
|
|
35
|
-
"process.env.VITE_ENVIRONMENT": JSON.stringify("client"),
|
|
36
|
-
...options.define
|
|
37
|
-
},
|
|
38
|
-
resolve: {
|
|
39
|
-
conditions: ["default"],
|
|
40
|
-
extensions: [
|
|
41
|
-
".storybook.ts",
|
|
42
|
-
".storybook.tsx",
|
|
43
|
-
".storybook.js",
|
|
44
|
-
".storybook.jsx",
|
|
45
|
-
".web.ts",
|
|
46
|
-
".web.tsx",
|
|
47
|
-
".web.js",
|
|
48
|
-
".web.jsx",
|
|
49
|
-
".ts",
|
|
50
|
-
".tsx",
|
|
51
|
-
".js",
|
|
52
|
-
".jsx",
|
|
53
|
-
".mjs",
|
|
54
|
-
".json"
|
|
55
|
-
],
|
|
56
|
-
alias: sortedAliases
|
|
57
|
-
},
|
|
58
|
-
optimizeDeps: {
|
|
59
|
-
include: [
|
|
60
|
-
"react",
|
|
61
|
-
"react-dom",
|
|
62
|
-
"react-native-web",
|
|
63
|
-
"@tamagui/core",
|
|
64
|
-
"@tamagui/web",
|
|
65
|
-
"@tamagui/helpers-icon",
|
|
66
|
-
"tamagui",
|
|
67
|
-
"@mdx-js/react",
|
|
68
|
-
"i18next",
|
|
69
|
-
"react-i18next",
|
|
70
|
-
"d3-shape",
|
|
71
|
-
"d3-scale",
|
|
72
|
-
"@storybook-community/storybook-dark-mode",
|
|
73
|
-
"use-latest-callback",
|
|
74
|
-
"escape-string-regexp",
|
|
75
|
-
"use-sync-external-store",
|
|
76
|
-
"use-sync-external-store/with-selector",
|
|
77
|
-
"fast-deep-equal",
|
|
78
|
-
"color",
|
|
79
|
-
"query-string",
|
|
80
|
-
"react-is"
|
|
81
|
-
],
|
|
82
|
-
exclude: [
|
|
83
|
-
"one/dist/esm/vite/one-server-only.mjs",
|
|
84
|
-
"@storybook/preview-api",
|
|
85
|
-
"@storybook/theming",
|
|
86
|
-
"@react-navigation/core",
|
|
87
|
-
"@react-navigation/native",
|
|
88
|
-
"@react-navigation/routers",
|
|
89
|
-
"@react-navigation/elements",
|
|
90
|
-
"@react-navigation/bottom-tabs",
|
|
91
|
-
"@react-navigation/native-stack"
|
|
92
|
-
]
|
|
93
|
-
},
|
|
94
|
-
plugins: [nodeAsyncHooksStub(), ...options.plugins || []]
|
|
95
|
-
};
|
|
96
|
-
}
|
|
97
|
-
/**
|
|
98
|
-
* Scans packages/ for workspace packages (multiplatform.one and package scopes)
|
|
99
|
-
* and returns resolve aliases.
|
|
100
|
-
*/
|
|
101
|
-
function discoverPackageAliases(packagesDir) {
|
|
102
|
-
const aliases = {};
|
|
103
|
-
if (!fs.existsSync(packagesDir)) return aliases;
|
|
104
|
-
const entries = fs.readdirSync(packagesDir, { withFileTypes: true });
|
|
105
|
-
for (const entry of entries) {
|
|
106
|
-
if (!entry.isDirectory()) continue;
|
|
107
|
-
const pkgDir = path.join(packagesDir, entry.name);
|
|
108
|
-
const pkgJsonPath = path.join(pkgDir, "package.json");
|
|
109
|
-
if (!fs.existsSync(pkgJsonPath)) continue;
|
|
110
|
-
let pkgJson;
|
|
111
|
-
try {
|
|
112
|
-
pkgJson = JSON.parse(fs.readFileSync(pkgJsonPath, "utf-8"));
|
|
113
|
-
} catch {
|
|
114
|
-
continue;
|
|
115
|
-
}
|
|
116
|
-
const pkgName = pkgJson.name;
|
|
117
|
-
if (!pkgName) continue;
|
|
118
|
-
if (!pkgName.startsWith("@multiplatform.one/") && !pkgName.startsWith("@package/") && pkgName !== "multiplatform.one") continue;
|
|
119
|
-
mergePackageResolveAliases(pkgDir, pkgName, pkgJson, aliases);
|
|
120
|
-
}
|
|
121
|
-
return aliases;
|
|
122
|
-
}
|
|
123
|
-
/** All workspace packages under public/ (any npm scope), including export subpaths. */
|
|
124
|
-
function discoverPublicPackageViteAliases(workspaceRoot) {
|
|
125
|
-
const aliases = {};
|
|
126
|
-
for (const [pkgName, pkgDir] of discoverPublicPackageRoots(workspaceRoot)) {
|
|
127
|
-
const pkgJsonPath = path.join(pkgDir, "package.json");
|
|
128
|
-
let pkgJson;
|
|
129
|
-
try {
|
|
130
|
-
pkgJson = JSON.parse(fs.readFileSync(pkgJsonPath, "utf-8"));
|
|
131
|
-
} catch {
|
|
132
|
-
continue;
|
|
133
|
-
}
|
|
134
|
-
mergePackageResolveAliases(pkgDir, pkgName, pkgJson, aliases);
|
|
135
|
-
}
|
|
136
|
-
return aliases;
|
|
137
|
-
}
|
|
138
|
-
function mergePackageResolveAliases(pkgDir, pkgName, pkgJson, aliases) {
|
|
139
|
-
const mainEntry = resolvePackageMainSource(pkgDir);
|
|
140
|
-
if (mainEntry) aliases[pkgName] = mainEntry;
|
|
141
|
-
if (pkgJson.exports && typeof pkgJson.exports === "object") for (const exportKey of Object.keys(pkgJson.exports)) {
|
|
142
|
-
if (exportKey === "." || exportKey === "./package.json") continue;
|
|
143
|
-
const subpath = exportKey.replace(/^\.\//, "");
|
|
144
|
-
if (path.extname(subpath)) {
|
|
145
|
-
const parentDir = path.dirname(subpath);
|
|
146
|
-
if (parentDir && parentDir !== ".") {
|
|
147
|
-
const fullParentDir = path.join(pkgDir, parentDir);
|
|
148
|
-
if (fs.existsSync(fullParentDir) && fs.statSync(fullParentDir).isDirectory()) aliases[`${pkgName}/${parentDir}`] = fullParentDir;
|
|
149
|
-
}
|
|
150
|
-
} else {
|
|
151
|
-
const resolved = resolveSubpathSource(pkgDir, subpath);
|
|
152
|
-
if (resolved) aliases[`${pkgName}/${subpath}`] = resolved;
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
function resolveSubpathSource(pkgDir, subpath) {
|
|
157
|
-
const candidates = [
|
|
158
|
-
path.join(pkgDir, "src", `${subpath}.storybook.ts`),
|
|
159
|
-
path.join(pkgDir, "src", `${subpath}.storybook.tsx`),
|
|
160
|
-
path.join(pkgDir, "src", `${subpath}.ts`),
|
|
161
|
-
path.join(pkgDir, "src", `${subpath}.tsx`),
|
|
162
|
-
path.join(pkgDir, "src", subpath, "index.storybook.ts"),
|
|
163
|
-
path.join(pkgDir, "src", subpath, "index.storybook.tsx"),
|
|
164
|
-
path.join(pkgDir, "src", subpath, "index.ts"),
|
|
165
|
-
path.join(pkgDir, "src", subpath, "index.tsx"),
|
|
166
|
-
path.join(pkgDir, `${subpath}.storybook.ts`),
|
|
167
|
-
path.join(pkgDir, `${subpath}.storybook.tsx`),
|
|
168
|
-
path.join(pkgDir, `${subpath}.ts`),
|
|
169
|
-
path.join(pkgDir, `${subpath}.tsx`),
|
|
170
|
-
path.join(pkgDir, subpath, "index.storybook.ts"),
|
|
171
|
-
path.join(pkgDir, subpath, "index.storybook.tsx"),
|
|
172
|
-
path.join(pkgDir, subpath, "index.ts"),
|
|
173
|
-
path.join(pkgDir, subpath, "index.tsx"),
|
|
174
|
-
path.join(pkgDir, subpath, "index.js")
|
|
175
|
-
];
|
|
176
|
-
for (const c of candidates) if (fs.existsSync(c)) return c;
|
|
177
|
-
const dirPath = path.join(pkgDir, subpath);
|
|
178
|
-
if (fs.existsSync(dirPath) && fs.statSync(dirPath).isDirectory()) return dirPath;
|
|
179
|
-
}
|
|
180
|
-
/** Virtual module plugin that stubs `node:async_hooks` for browser environments. */
|
|
181
|
-
function nodeAsyncHooksStub() {
|
|
182
|
-
return {
|
|
183
|
-
name: "storybook:node-async-hooks-stub",
|
|
184
|
-
resolveId(id) {
|
|
185
|
-
if (id === "node:async_hooks") return "\0node:async_hooks";
|
|
186
|
-
},
|
|
187
|
-
load(id) {
|
|
188
|
-
if (id === "\0node:async_hooks") return "export class AsyncLocalStorage {}";
|
|
189
|
-
}
|
|
190
|
-
};
|
|
191
|
-
}
|
|
192
|
-
function findWorkspaceRoot() {
|
|
193
|
-
let dir = process.cwd();
|
|
194
|
-
while (dir !== path.dirname(dir)) {
|
|
195
|
-
if (fs.existsSync(path.join(dir, "pnpm-workspace.yaml"))) return dir;
|
|
196
|
-
const pkgJsonPath = path.join(dir, "package.json");
|
|
197
|
-
if (fs.existsSync(pkgJsonPath)) try {
|
|
198
|
-
if (JSON.parse(fs.readFileSync(pkgJsonPath, "utf-8")).workspaces) return dir;
|
|
199
|
-
} catch {}
|
|
200
|
-
dir = path.dirname(dir);
|
|
201
|
-
}
|
|
202
|
-
return process.cwd();
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
//#endregion
|
|
206
3
|
export { createStorybookViteConfig };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { t as discoverPublicPackageRoots } from "./workspacePublicPackages-
|
|
1
|
+
import { t as discoverPublicPackageRoots } from "./workspacePublicPackages-COicQSj4.js";
|
|
2
2
|
import { createRequire } from "node:module";
|
|
3
3
|
import fs from "node:fs";
|
|
4
4
|
import path from "node:path";
|
|
@@ -77,10 +77,13 @@ function lookupProjectRoot() {
|
|
|
77
77
|
* ```
|
|
78
78
|
*/
|
|
79
79
|
function createViteConfig(options = {}) {
|
|
80
|
-
const { projectRoot: _projectRoot, publicConfigKeys = [], tamagui = true, i18n = false, one = false, ssr, server, plugins: extraPlugins = [], externalReactRouter, ssrDeps, ssrEntries } = options;
|
|
80
|
+
const { projectRoot: _projectRoot, publicConfigKeys = [], tamagui = true, i18n = false, one = false, ssr, server, plugins: extraPlugins = [], externalReactRouter, ssrDeps, ssrEntries, ssrCjsExternal, nativeFixes } = options;
|
|
81
81
|
const projectRoot = _projectRoot || findProjectRoot();
|
|
82
82
|
dotenv.config({ path: path.resolve(projectRoot, ".env") });
|
|
83
|
-
if (publicConfigKeys.length > 0)
|
|
83
|
+
if (publicConfigKeys.length > 0) {
|
|
84
|
+
process.env.VITE_MP_CONFIG = JSON.stringify(resolveConfig(publicConfigKeys));
|
|
85
|
+
process.env.VITE_MP_PUBLIC_CONFIG_KEYS = JSON.stringify(publicConfigKeys);
|
|
86
|
+
}
|
|
84
87
|
const vitePlugins = [];
|
|
85
88
|
vitePlugins.push(preferBuiltWorkspaceEntryPlugin());
|
|
86
89
|
if (one) {
|
|
@@ -89,6 +92,9 @@ function createViteConfig(options = {}) {
|
|
|
89
92
|
registerNativeEngineIoBrowserTransports();
|
|
90
93
|
registerNativeWorkspaceEntries();
|
|
91
94
|
registerNativePhosphorIcons();
|
|
95
|
+
if (nativeFixes?.protoShadow !== false) registerNativeProtoShadowFix();
|
|
96
|
+
if (nativeFixes?.web3Stub !== false) registerNativeWeb3Stub();
|
|
97
|
+
if (ssrCjsExternal !== false) vitePlugins.push(ssrCjsExternalFixPlugin([...DEFAULT_SSR_CJS_EXTERNAL, ...ssrCjsExternal ?? []]));
|
|
92
98
|
}
|
|
93
99
|
if (tamagui) {
|
|
94
100
|
const tamaguiOpts = typeof tamagui === "object" ? tamagui : {};
|
|
@@ -324,6 +330,111 @@ function registerNativeWorkspaceEntries() {
|
|
|
324
330
|
}
|
|
325
331
|
});
|
|
326
332
|
}
|
|
333
|
+
/**
|
|
334
|
+
* CJS-only ids (no usable ESM build) that escape Vite's SSR dep optimizer and
|
|
335
|
+
* hit the ESM evaluator ("module is not defined" / "exports is not defined")
|
|
336
|
+
* unless Node's native CJS loader handles them. Union of the lists the
|
|
337
|
+
* monorepo's apps/one and downstream consumer apps (desibox) carried as
|
|
338
|
+
* app-side ssrExternalFix plugins; ids for packages an app never imports are
|
|
339
|
+
* inert, so one shared default list is safe.
|
|
340
|
+
*/
|
|
341
|
+
const DEFAULT_SSR_CJS_EXTERNAL = [
|
|
342
|
+
"better-sqlite3",
|
|
343
|
+
"dotenv",
|
|
344
|
+
"color",
|
|
345
|
+
"use-sync-external-store",
|
|
346
|
+
"use-sync-external-store/shim",
|
|
347
|
+
"use-sync-external-store/shim/with-selector",
|
|
348
|
+
"highlight.js",
|
|
349
|
+
"highlight.js/lib/core",
|
|
350
|
+
"turndown",
|
|
351
|
+
"@mixmark-io/domino",
|
|
352
|
+
"lowlight",
|
|
353
|
+
"shallowequal",
|
|
354
|
+
"@emotion/is-prop-valid",
|
|
355
|
+
"hoist-non-react-statics",
|
|
356
|
+
"qrcode"
|
|
357
|
+
];
|
|
358
|
+
/**
|
|
359
|
+
* Force-append CJS-only ids to `ssr.external`. The one() plugin REPLACES
|
|
360
|
+
* ssr.external with its own list during the config hook, dropping anything
|
|
361
|
+
* set statically by createViteConfig — configResolved runs after all config
|
|
362
|
+
* hooks are merged, so appends here survive.
|
|
363
|
+
*/
|
|
364
|
+
function ssrCjsExternalFixPlugin(extras) {
|
|
365
|
+
return {
|
|
366
|
+
name: "multiplatform-ssr-cjs-external-fix",
|
|
367
|
+
configResolved(config) {
|
|
368
|
+
const external = config.ssr.external ?? [];
|
|
369
|
+
if (!Array.isArray(external)) return;
|
|
370
|
+
for (const e of extras) if (!external.includes(e)) external.push(e);
|
|
371
|
+
config.ssr.external = external;
|
|
372
|
+
}
|
|
373
|
+
};
|
|
374
|
+
}
|
|
375
|
+
/**
|
|
376
|
+
* Restore Object.prototype methods shadowed by hoisted globals on NATIVE.
|
|
377
|
+
*
|
|
378
|
+
* vxrn's rolldown native mode emits the whole dev bundle as ONE classic
|
|
379
|
+
* script and forces Hermes V1. Hermes V1 implements spec-compliant global
|
|
380
|
+
* var hoisting, so a flattened module's top-level `var hasOwnProperty`
|
|
381
|
+
* (e.g. acorn via an mdx pipeline) creates
|
|
382
|
+
* `globalThis.hasOwnProperty = undefined` at parse time, shadowing
|
|
383
|
+
* Object.prototype.hasOwnProperty for the entire runtime. React Native core
|
|
384
|
+
* calls `global.hasOwnProperty()` during boot (FuseboxSessionObserver) and
|
|
385
|
+
* dies with "undefined is not a function". Prepend a snippet that copies any
|
|
386
|
+
* Object.prototype method back over an undefined shadowing own-property
|
|
387
|
+
* before any module code runs — the shadowed vars are reassigned by their
|
|
388
|
+
* own modules on init, so this only bridges the parse-to-init window.
|
|
389
|
+
* Registered through globalThis.__vxrnAddNativePlugins (vxrn's native engine
|
|
390
|
+
* ignores vite resolve/config). Web/SSR bundles are ESM (module-scoped vars)
|
|
391
|
+
* and unaffected.
|
|
392
|
+
*/
|
|
393
|
+
function registerNativeProtoShadowFix() {
|
|
394
|
+
const g = globalThis;
|
|
395
|
+
const name = "vxrn-proto-shadow-fix";
|
|
396
|
+
g.__vxrnAddNativePlugins = g.__vxrnAddNativePlugins ?? [];
|
|
397
|
+
if (g.__vxrnAddNativePlugins.some((p) => p?.name === name)) return;
|
|
398
|
+
const snippet = "(function(){var p=Object.prototype,h=p.hasOwnProperty,ns=Object.getOwnPropertyNames(p);for(var i=0;i<ns.length;i++){var k=ns[i];if(typeof p[k]===\"function\"&&globalThis[k]===void 0&&h.call(globalThis,k)){try{globalThis[k]=p[k]}catch(e){}}}})();";
|
|
399
|
+
g.__vxrnAddNativePlugins.push({
|
|
400
|
+
name,
|
|
401
|
+
renderChunk(code) {
|
|
402
|
+
return {
|
|
403
|
+
code: `${snippet}\n${code}`,
|
|
404
|
+
map: null
|
|
405
|
+
};
|
|
406
|
+
}
|
|
407
|
+
});
|
|
408
|
+
}
|
|
409
|
+
/**
|
|
410
|
+
* Redirect the OPTIONAL `@multiplatform.one/web3` native import to a no-op
|
|
411
|
+
* shim on NATIVE when the package is not installed (see the nativeFixes
|
|
412
|
+
* option docs). Rolldown leaves the unresolvable specifier as a bare dynamic
|
|
413
|
+
* `import()` in the classic-script native bundle — Hermes rejects that at
|
|
414
|
+
* lazy-compile time ("SyntaxError: Invalid expression encountered"), killing
|
|
415
|
+
* the root _layout route. Web/SSR resolve the same specifier through vite's
|
|
416
|
+
* normal pipeline and are unaffected.
|
|
417
|
+
*/
|
|
418
|
+
function registerNativeWeb3Stub() {
|
|
419
|
+
const g = globalThis;
|
|
420
|
+
const name = "vxrn-web3-stub";
|
|
421
|
+
g.__vxrnAddNativePlugins = g.__vxrnAddNativePlugins ?? [];
|
|
422
|
+
if (g.__vxrnAddNativePlugins.some((p) => p?.name === name)) return;
|
|
423
|
+
try {
|
|
424
|
+
__require.resolve("@multiplatform.one/web3", { paths: [findProjectRoot(), process.cwd()] });
|
|
425
|
+
return;
|
|
426
|
+
} catch {}
|
|
427
|
+
const here = path.dirname(new URL(import.meta.url).pathname);
|
|
428
|
+
const shim = [path.resolve(here, "shims/web3Stub.native.js"), path.resolve(here, "../src/shims/web3Stub.native.js")].find((candidate) => fs.existsSync(candidate));
|
|
429
|
+
if (!shim) return;
|
|
430
|
+
g.__vxrnAddNativePlugins.push({
|
|
431
|
+
name,
|
|
432
|
+
resolveId(id) {
|
|
433
|
+
if (id === "@multiplatform.one/web3/native" || id === "@multiplatform.one/web3") return shim;
|
|
434
|
+
return null;
|
|
435
|
+
}
|
|
436
|
+
});
|
|
437
|
+
}
|
|
327
438
|
function findProjectRoot() {
|
|
328
439
|
try {
|
|
329
440
|
const { execSync } = __require("node:child_process");
|
package/lib/vite.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { t as createViteConfig } from "./vite-
|
|
2
|
-
import { n as publicPackageViteSourceAliases, t as discoverPublicPackageRoots } from "./workspacePublicPackages-
|
|
1
|
+
import { t as createViteConfig } from "./vite-C7884n3X.js";
|
|
2
|
+
import { n as publicPackageViteSourceAliases, t as discoverPublicPackageRoots } from "./workspacePublicPackages-COicQSj4.js";
|
|
3
3
|
|
|
4
4
|
export { createViteConfig, discoverPublicPackageRoots, publicPackageViteSourceAliases };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@multiplatform.one/config",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "7.1.0",
|
|
4
4
|
"description": "Shared build and test configuration presets for multiplatform.one",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"config",
|
|
@@ -80,14 +80,14 @@
|
|
|
80
80
|
"access": "public"
|
|
81
81
|
},
|
|
82
82
|
"dependencies": {
|
|
83
|
-
"@tamagui/vite-plugin": "2.
|
|
83
|
+
"@tamagui/vite-plugin": "2.7.6",
|
|
84
84
|
"@vitejs/plugin-react": "^6.0.1",
|
|
85
85
|
"dotenv": "^17.4.2",
|
|
86
86
|
"vite": "^8.0.10",
|
|
87
87
|
"vite-plugin-external": "^6.2.2",
|
|
88
88
|
"vite-plugin-i18next-loader": "^3.1.3",
|
|
89
89
|
"vitest": "^4.1.5",
|
|
90
|
-
"@multiplatform.one/utils": "
|
|
90
|
+
"@multiplatform.one/utils": "7.1.0"
|
|
91
91
|
},
|
|
92
92
|
"devDependencies": {
|
|
93
93
|
"tsdown": "^0.21.10",
|
|
@@ -110,6 +110,7 @@
|
|
|
110
110
|
},
|
|
111
111
|
"scripts": {
|
|
112
112
|
"typecheck": "tsgo --noEmit",
|
|
113
|
-
"build": "rm -rf lib types 2>/dev/null && tsc -p tsconfig.build.json && tsdown"
|
|
113
|
+
"build": "rm -rf lib types 2>/dev/null && tsc -p tsconfig.build.json && tsdown",
|
|
114
|
+
"test": "vitest run --coverage --coverage.provider=v8 --coverage.reporter=text --coverage.reporter=lcov --coverage.reporter=html"
|
|
114
115
|
}
|
|
115
116
|
}
|