@multiplatform.one/config 6.6.0 → 7.0.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 CHANGED
@@ -1,5 +1,5 @@
1
- import { t as createViteConfig } from "./vite-C6psj1Lz.js";
2
- import { createStorybookViteConfig } from "./storybook.js";
1
+ import { t as createViteConfig } from "./vite-DzOl_bpS.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 { r as resolvePackageMainSource, t as discoverPublicPackageRoots } from "./workspacePublicPackages-CkDbm3QT.js";
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-CkDbm3QT.js";
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,7 +77,7 @@ 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
83
  if (publicConfigKeys.length > 0) process.env.VITE_MP_CONFIG = JSON.stringify(resolveConfig(publicConfigKeys));
@@ -89,6 +89,9 @@ function createViteConfig(options = {}) {
89
89
  registerNativeEngineIoBrowserTransports();
90
90
  registerNativeWorkspaceEntries();
91
91
  registerNativePhosphorIcons();
92
+ if (nativeFixes?.protoShadow !== false) registerNativeProtoShadowFix();
93
+ if (nativeFixes?.web3Stub !== false) registerNativeWeb3Stub();
94
+ if (ssrCjsExternal !== false) vitePlugins.push(ssrCjsExternalFixPlugin([...DEFAULT_SSR_CJS_EXTERNAL, ...ssrCjsExternal ?? []]));
92
95
  }
93
96
  if (tamagui) {
94
97
  const tamaguiOpts = typeof tamagui === "object" ? tamagui : {};
@@ -324,6 +327,111 @@ function registerNativeWorkspaceEntries() {
324
327
  }
325
328
  });
326
329
  }
330
+ /**
331
+ * CJS-only ids (no usable ESM build) that escape Vite's SSR dep optimizer and
332
+ * hit the ESM evaluator ("module is not defined" / "exports is not defined")
333
+ * unless Node's native CJS loader handles them. Union of the lists the
334
+ * monorepo's apps/one and downstream consumer apps (desibox) carried as
335
+ * app-side ssrExternalFix plugins; ids for packages an app never imports are
336
+ * inert, so one shared default list is safe.
337
+ */
338
+ const DEFAULT_SSR_CJS_EXTERNAL = [
339
+ "better-sqlite3",
340
+ "dotenv",
341
+ "color",
342
+ "use-sync-external-store",
343
+ "use-sync-external-store/shim",
344
+ "use-sync-external-store/shim/with-selector",
345
+ "highlight.js",
346
+ "highlight.js/lib/core",
347
+ "turndown",
348
+ "@mixmark-io/domino",
349
+ "lowlight",
350
+ "shallowequal",
351
+ "@emotion/is-prop-valid",
352
+ "hoist-non-react-statics",
353
+ "qrcode"
354
+ ];
355
+ /**
356
+ * Force-append CJS-only ids to `ssr.external`. The one() plugin REPLACES
357
+ * ssr.external with its own list during the config hook, dropping anything
358
+ * set statically by createViteConfig — configResolved runs after all config
359
+ * hooks are merged, so appends here survive.
360
+ */
361
+ function ssrCjsExternalFixPlugin(extras) {
362
+ return {
363
+ name: "multiplatform-ssr-cjs-external-fix",
364
+ configResolved(config) {
365
+ const external = config.ssr.external ?? [];
366
+ if (!Array.isArray(external)) return;
367
+ for (const e of extras) if (!external.includes(e)) external.push(e);
368
+ config.ssr.external = external;
369
+ }
370
+ };
371
+ }
372
+ /**
373
+ * Restore Object.prototype methods shadowed by hoisted globals on NATIVE.
374
+ *
375
+ * vxrn's rolldown native mode emits the whole dev bundle as ONE classic
376
+ * script and forces Hermes V1. Hermes V1 implements spec-compliant global
377
+ * var hoisting, so a flattened module's top-level `var hasOwnProperty`
378
+ * (e.g. acorn via an mdx pipeline) creates
379
+ * `globalThis.hasOwnProperty = undefined` at parse time, shadowing
380
+ * Object.prototype.hasOwnProperty for the entire runtime. React Native core
381
+ * calls `global.hasOwnProperty()` during boot (FuseboxSessionObserver) and
382
+ * dies with "undefined is not a function". Prepend a snippet that copies any
383
+ * Object.prototype method back over an undefined shadowing own-property
384
+ * before any module code runs — the shadowed vars are reassigned by their
385
+ * own modules on init, so this only bridges the parse-to-init window.
386
+ * Registered through globalThis.__vxrnAddNativePlugins (vxrn's native engine
387
+ * ignores vite resolve/config). Web/SSR bundles are ESM (module-scoped vars)
388
+ * and unaffected.
389
+ */
390
+ function registerNativeProtoShadowFix() {
391
+ const g = globalThis;
392
+ const name = "vxrn-proto-shadow-fix";
393
+ g.__vxrnAddNativePlugins = g.__vxrnAddNativePlugins ?? [];
394
+ if (g.__vxrnAddNativePlugins.some((p) => p?.name === name)) return;
395
+ 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){}}}})();";
396
+ g.__vxrnAddNativePlugins.push({
397
+ name,
398
+ renderChunk(code) {
399
+ return {
400
+ code: `${snippet}\n${code}`,
401
+ map: null
402
+ };
403
+ }
404
+ });
405
+ }
406
+ /**
407
+ * Redirect the OPTIONAL `@multiplatform.one/web3` native import to a no-op
408
+ * shim on NATIVE when the package is not installed (see the nativeFixes
409
+ * option docs). Rolldown leaves the unresolvable specifier as a bare dynamic
410
+ * `import()` in the classic-script native bundle — Hermes rejects that at
411
+ * lazy-compile time ("SyntaxError: Invalid expression encountered"), killing
412
+ * the root _layout route. Web/SSR resolve the same specifier through vite's
413
+ * normal pipeline and are unaffected.
414
+ */
415
+ function registerNativeWeb3Stub() {
416
+ const g = globalThis;
417
+ const name = "vxrn-web3-stub";
418
+ g.__vxrnAddNativePlugins = g.__vxrnAddNativePlugins ?? [];
419
+ if (g.__vxrnAddNativePlugins.some((p) => p?.name === name)) return;
420
+ try {
421
+ __require.resolve("@multiplatform.one/web3", { paths: [findProjectRoot(), process.cwd()] });
422
+ return;
423
+ } catch {}
424
+ const here = path.dirname(new URL(import.meta.url).pathname);
425
+ const shim = [path.resolve(here, "shims/web3Stub.native.js"), path.resolve(here, "../src/shims/web3Stub.native.js")].find((candidate) => fs.existsSync(candidate));
426
+ if (!shim) return;
427
+ g.__vxrnAddNativePlugins.push({
428
+ name,
429
+ resolveId(id) {
430
+ if (id === "@multiplatform.one/web3/native" || id === "@multiplatform.one/web3") return shim;
431
+ return null;
432
+ }
433
+ });
434
+ }
327
435
  function findProjectRoot() {
328
436
  try {
329
437
  const { execSync } = __require("node:child_process");
package/lib/vite.js CHANGED
@@ -1,4 +1,4 @@
1
- import { t as createViteConfig } from "./vite-C6psj1Lz.js";
2
- import { n as publicPackageViteSourceAliases, t as discoverPublicPackageRoots } from "./workspacePublicPackages-CkDbm3QT.js";
1
+ import { t as createViteConfig } from "./vite-DzOl_bpS.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": "6.6.0",
3
+ "version": "7.0.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.0.0-rc.41",
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": "6.6.0"
90
+ "@multiplatform.one/utils": "7.0.0"
91
91
  },
92
92
  "devDependencies": {
93
93
  "tsdown": "^0.21.10",
@@ -109,7 +109,8 @@
109
109
  "node": ">=18.0.0"
110
110
  },
111
111
  "scripts": {
112
- "typecheck": "tsc --noEmit",
113
- "build": "rm -rf lib types 2>/dev/null && tsc -p tsconfig.build.json && tsdown"
112
+ "typecheck": "tsgo --noEmit",
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
  }
@@ -0,0 +1,18 @@
1
+ /**
2
+ * No-op `@multiplatform.one/web3(/native)` shim for NATIVE runs.
3
+ *
4
+ * `@multiplatform.one/core`'s loadWalletProvider.native.ts lazily
5
+ * `import("@multiplatform.one/web3/native")` — an OPTIONAL package many apps
6
+ * do not install. vxrn's rolldown native bundler leaves the unresolvable
7
+ * specifier as a bare dynamic `import()` expression in the classic-script
8
+ * bundle, which Hermes rejects at lazy-compile time with "SyntaxError:
9
+ * Invalid expression encountered", killing the root _layout route.
10
+ * createViteConfig's registerNativeWeb3Stub redirects the specifier here so
11
+ * the import inlines and parses; it auto-skips when web3 is installed.
12
+ *
13
+ * Plain JS (not TS): vxrn's native pipeline does not transform node_modules
14
+ * TypeScript.
15
+ */
16
+ export function WalletProvider({ children }) {
17
+ return children ?? null;
18
+ }