@multiplatform.one/config 7.11.0 → 7.16.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.
@@ -0,0 +1,107 @@
1
+ import { mkdtempSync, rmSync, writeFileSync } from "node:fs";
2
+ import { tmpdir } from "node:os";
3
+ import { dirname, join } from "node:path";
4
+ import { fileURLToPath } from "node:url";
5
+ import { afterEach, describe, expect, it } from "vitest";
6
+ import {
7
+ readSizeRecipeEscapeRegistry,
8
+ readSlotMarginRegistry,
9
+ readSpecTable,
10
+ } from "../spec-registry.mjs";
11
+
12
+ const fixtures: string[] = [];
13
+
14
+ afterEach(() => {
15
+ for (const dir of fixtures.splice(0)) {
16
+ rmSync(dir, { recursive: true, force: true });
17
+ }
18
+ });
19
+
20
+ function specFile(markdown: string) {
21
+ const root = mkdtempSync(join(tmpdir(), "mpo-spec-registry-"));
22
+ fixtures.push(root);
23
+ const specPath = join(root, "spec.md");
24
+ writeFileSync(specPath, markdown);
25
+ return specPath;
26
+ }
27
+
28
+ const repoSpec = join(
29
+ dirname(fileURLToPath(import.meta.url)),
30
+ "..",
31
+ "..",
32
+ "..",
33
+ "docs",
34
+ "theme-propagation-spec.md",
35
+ );
36
+
37
+ describe("readSpecTable", () => {
38
+ it("returns body rows under the heading and stops at the next section", () => {
39
+ const rows = readSpecTable(
40
+ "## A\n\n| X | Y |\n| - | - |\n| a | b |\n\n## B\n\n| X | Y |\n| - | - |\n| c | d |\n",
41
+ "## A",
42
+ );
43
+ expect(rows).toEqual([["a", "b"]]);
44
+ });
45
+
46
+ it("returns null when the heading is absent", () => {
47
+ expect(readSpecTable("## Other\n", "## A")).toBeNull();
48
+ });
49
+ });
50
+
51
+ describe("readSlotMarginRegistry (00 L9a)", () => {
52
+ it("parses the SLOT-MARGIN members", () => {
53
+ const registry = readSlotMarginRegistry(
54
+ specFile(
55
+ "## Slot margins\n\n| Class | Normative meaning |\n| --- | --- |\n| SLOT-MARGIN | Slots. Members: **Card.Footer**, **Card.Header** |\n",
56
+ ),
57
+ );
58
+ expect(registry).toMatchObject({ present: true, members: ["Card.Footer", "Card.Header"] });
59
+ });
60
+
61
+ it("is absent, not an error, when the spec or the section is missing", () => {
62
+ expect(readSlotMarginRegistry(join(tmpdir(), "no-such-spec.md")).present).toBe(false);
63
+ expect(readSlotMarginRegistry(specFile("# Spec\n")).present).toBe(false);
64
+ });
65
+
66
+ it("throws when the section has no SLOT-MARGIN row, so a renamed class cannot empty it", () => {
67
+ expect(() =>
68
+ readSlotMarginRegistry(
69
+ specFile("## Slot margins\n\n| Class | Meaning |\n| --- | --- |\n| SLOTS | x |\n"),
70
+ ),
71
+ ).toThrow(/no SLOT-MARGIN row/);
72
+ });
73
+ });
74
+
75
+ describe("readSizeRecipeEscapeRegistry (00 L8 E8)", () => {
76
+ it("reads one { file, reason } per row, unwrapping code spans", () => {
77
+ const registry = readSizeRecipeEscapeRegistry(
78
+ specFile(
79
+ "## Size-recipe escapes\n\n| File | Reason |\n| --- | --- |\n| `public/forms/src/A.tsx` | `square end-cap; pad lives on Input.Box` |\n",
80
+ ),
81
+ );
82
+ expect(registry.escapes).toEqual([
83
+ { file: "public/forms/src/A.tsx", reason: "square end-cap; pad lives on Input.Box" },
84
+ ]);
85
+ });
86
+
87
+ it("throws on a row with no reason: an escape is declared BY its reason", () => {
88
+ expect(() =>
89
+ readSizeRecipeEscapeRegistry(
90
+ specFile(
91
+ "## Size-recipe escapes\n\n| File | Reason |\n| --- | --- |\n| `public/forms/src/A.tsx` | |\n",
92
+ ),
93
+ ),
94
+ ).toThrow(/has no reason/);
95
+ });
96
+
97
+ it("reads the mpo spec: every row names a file and a reason", () => {
98
+ const registry = readSizeRecipeEscapeRegistry(repoSpec);
99
+ expect(registry.present).toBe(true);
100
+ expect(registry.escapes.length).toBeGreaterThan(0);
101
+ for (const { file, reason } of registry.escapes) {
102
+ expect(file).toMatch(/^(public|packages|apps|features)\//);
103
+ expect(reason.length).toBeGreaterThan(0);
104
+ }
105
+ expect(readSlotMarginRegistry(repoSpec).present).toBe(true);
106
+ });
107
+ });
@@ -29,6 +29,8 @@ describe("createStorybookViteConfig", () => {
29
29
  // @tamagui/lucide-icons-2 was served at a different ?v= hash from the
30
30
  // shared tamagui chunk.
31
31
  for (const dep of [
32
+ "@tamagui/animations-css",
33
+ "@tamagui/react-native-svg",
32
34
  "@tamagui/colors",
33
35
  "@tamagui/config",
34
36
  "@tamagui/config/v5",
package/src/storybook.ts CHANGED
@@ -143,6 +143,13 @@ export function createStorybookViteConfig(
143
143
  // below, and the failure it prevents is worse: a story that renders
144
144
  // nothing is recorded by a render sweep as no data rather than as a
145
145
  // failure.
146
+ // The two below were the last found on their own ?v= after the list
147
+ // above landed: a fresh dev server's sweep of all 2165 stories served
148
+ // @tamagui_animations-css (the theme's css driver) and
149
+ // @tamagui_react-native-svg (Svg, the markdown icons) at hashes of
150
+ // their own while the other 21 tamagui dep files shared one.
151
+ "@tamagui/animations-css",
152
+ "@tamagui/react-native-svg",
146
153
  "@tamagui/colors",
147
154
  "@tamagui/config",
148
155
  "@tamagui/config/v5",
package/src/vite.spec.ts CHANGED
@@ -5,6 +5,9 @@
5
5
  * escape hatches.
6
6
  */
7
7
 
8
+ import fs from "node:fs";
9
+ import os from "node:os";
10
+ import path from "node:path";
8
11
  import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
9
12
  import type { Plugin } from "vite";
10
13
  import { createViteConfig } from "./vite.js";
@@ -24,8 +27,12 @@ function findPlugin(config: ReturnType<typeof createViteConfig>, name: string):
24
27
  | undefined;
25
28
  }
26
29
 
27
- function runConfigResolved(plugin: Plugin, ssrExternal: string[] | boolean | undefined) {
28
- const fakeConfig = { ssr: { external: ssrExternal } } as any;
30
+ function runConfigResolved(
31
+ plugin: Plugin,
32
+ ssrExternal: string[] | boolean | undefined,
33
+ command: "build" | "serve" = "serve",
34
+ ) {
35
+ const fakeConfig = { command, ssr: { external: ssrExternal } } as any;
29
36
  (plugin.configResolved as any)(fakeConfig);
30
37
  return fakeConfig.ssr.external;
31
38
  }
@@ -66,6 +73,15 @@ describe("ssrCjsExternal", () => {
66
73
  expect(external).toContain("use-sync-external-store");
67
74
  });
68
75
 
76
+ it("bundles use-sync-external-store in a build, where React is bundled too", () => {
77
+ const config = createViteConfig({ one: true });
78
+ const plugin = findPlugin(config, "multiplatform-ssr-cjs-external-fix");
79
+ const external = runConfigResolved(plugin!, [], "build") as string[];
80
+ expect(external.filter((e) => e.startsWith("use-sync-external-store"))).toEqual([]);
81
+ expect(external).toContain("hoist-non-react-statics");
82
+ expect(external).toContain("turndown");
83
+ });
84
+
69
85
  it("leaves ssr.external: true untouched (everything already external)", () => {
70
86
  const config = createViteConfig({ one: true });
71
87
  const plugin = findPlugin(config, "multiplatform-ssr-cjs-external-fix");
@@ -145,6 +161,24 @@ describe("public config bake", () => {
145
161
  expect(process.env[bakedKeys]).toBeUndefined();
146
162
  expect(process.env[bakedValues]).toBeUndefined();
147
163
  });
164
+
165
+ it("reads the names from publicConfigFile and adds the dev watcher plugin (MPO-247)", () => {
166
+ const dir = fs.mkdtempSync(path.join(os.tmpdir(), "mpo-vite-spec-"));
167
+ const file = path.join(dir, "config.json");
168
+ fs.writeFileSync(file, JSON.stringify({ private: ["SECRET"], public: ["FRAPPE_ENABLED"] }));
169
+ try {
170
+ const config = createViteConfig({ publicConfigFile: file, publicConfigKeys: ["INLINE"] });
171
+ expect(JSON.parse(process.env[bakedKeys]!)).toEqual(["INLINE", "FRAPPE_ENABLED"]);
172
+ expect(findPlugin(config, "multiplatform-public-config")?.apply).toBe("serve");
173
+ } finally {
174
+ fs.rmSync(dir, { recursive: true, force: true });
175
+ }
176
+ });
177
+
178
+ it("adds no watcher plugin when the keys are declared inline", () => {
179
+ const config = createViteConfig({ publicConfigKeys: ["INLINE"] });
180
+ expect(findPlugin(config, "multiplatform-public-config")).toBeUndefined();
181
+ });
148
182
  });
149
183
 
150
184
  describe("One HMR ports (MPO-233)", () => {
@@ -166,3 +200,25 @@ describe("One HMR ports (MPO-233)", () => {
166
200
  expect(config.server?.hmr).toEqual(hmr);
167
201
  });
168
202
  });
203
+
204
+ describe("clientBrokenEsm (MPO-223)", () => {
205
+ it("pre-bundles react's JSX runtimes for the client environment", () => {
206
+ const config = createViteConfig({ one: true });
207
+ const plugin = findPlugin(config, "multiplatform-client-broken-esm");
208
+ expect(plugin).toBeDefined();
209
+ const fakeConfig = { environments: { client: { optimizeDeps: { include: ["react"] } } } };
210
+ (plugin!.configResolved as any)(fakeConfig);
211
+ const include = fakeConfig.environments.client.optimizeDeps.include;
212
+ expect(include).toContain("react/jsx-runtime");
213
+ expect(include).toContain("react/jsx-dev-runtime");
214
+ expect(include.filter((d) => d === "react")).toHaveLength(1);
215
+ });
216
+
217
+ it("pre-bundles tamagui for the client, which a deep src import reaches from inside node_modules", () => {
218
+ const config = createViteConfig({ one: true });
219
+ const plugin = findPlugin(config, "multiplatform-client-broken-esm");
220
+ const fakeConfig = { environments: { client: { optimizeDeps: {} as { include?: string[] } } } };
221
+ (plugin!.configResolved as any)(fakeConfig);
222
+ expect(fakeConfig.environments.client.optimizeDeps.include).toContain("tamagui");
223
+ });
224
+ });
package/src/vite.ts CHANGED
@@ -1,9 +1,15 @@
1
1
  import fs from "node:fs";
2
2
  import path from "node:path";
3
- import { lookupTamaguiModules, resolveConfig } from "@multiplatform.one/utils/dev";
3
+ import { lookupTamaguiModules } from "@multiplatform.one/utils/dev";
4
4
  import { discoverPublicPackageRoots } from "./workspacePublicPackages.js";
5
5
  import { withSingletonDepAliases } from "./singletonDepAliases.js";
6
6
  import { ensureTamaguiWorkspacePaths } from "./tamaguiWorkspacePaths.js";
7
+ import {
8
+ bakePublicConfig,
9
+ mergePublicConfigKeys,
10
+ publicConfigPlugin,
11
+ readPublicConfigKeys,
12
+ } from "./publicConfig.js";
7
13
  import { tamaguiPlugin } from "@tamagui/vite-plugin";
8
14
  import dotenv from "dotenv";
9
15
  import type { Plugin, UserConfig } from "vite";
@@ -18,11 +24,20 @@ export interface CreateViteConfigOptions {
18
24
  projectRoot?: string;
19
25
 
20
26
  /**
21
- * Public config keys to expose via VITE_MP_CONFIG.
22
- * These are typically the `public` keys from features/config.json.
27
+ * Public config keys to expose via VITE_MP_CONFIG, declared inline.
23
28
  */
24
29
  publicConfigKeys?: string[];
25
30
 
31
+ /**
32
+ * Absolute path of the config.json whose `public` array names the keys to
33
+ * expose via VITE_MP_CONFIG. Use this rather than importing the file into
34
+ * the vite config: an import makes it a config dependency, so adding a key
35
+ * restarts the dev server and re-optimizes deps, which 504s every open tab
36
+ * (MPO-247). Read instead, the file is watched in dev: a change rebakes the
37
+ * keys and reloads open clients, and the server never restarts.
38
+ */
39
+ publicConfigFile?: string;
40
+
26
41
  /**
27
42
  * Enable Tamagui plugin. Defaults to true.
28
43
  */
@@ -163,11 +178,11 @@ export interface CreateViteConfigOptions {
163
178
  * @example
164
179
  * ```ts
165
180
  * // apps/one/vite.config.ts
181
+ * import path from "node:path";
166
182
  * import { createViteConfig } from "@multiplatform.one/config/vite";
167
- * import { public as publicConfigKeys } from "../../features/config.json";
168
183
  *
169
184
  * export default createViteConfig({
170
- * publicConfigKeys,
185
+ * publicConfigFile: path.resolve(__dirname, "../../packages/config/config.json"),
171
186
  * one: { web: { deploy: "node", defaultRenderMode: "ssr" } },
172
187
  * tamagui: { config: "./config/tamagui.config.ts" },
173
188
  * i18n: { paths: ["../../features/i18n"] },
@@ -180,7 +195,8 @@ export function createViteConfig(options: CreateViteConfigOptions = {}): UserCon
180
195
  ensureTamaguiWorkspacePaths();
181
196
  const {
182
197
  projectRoot: _projectRoot,
183
- publicConfigKeys = [],
198
+ publicConfigKeys: inlinePublicConfigKeys = [],
199
+ publicConfigFile,
184
200
  tamagui = true,
185
201
  i18n = false,
186
202
  one = false,
@@ -195,22 +211,29 @@ export function createViteConfig(options: CreateViteConfigOptions = {}): UserCon
195
211
  } = options;
196
212
 
197
213
  const projectRoot = _projectRoot || findProjectRoot();
214
+ const publicConfigKeys = publicConfigFile
215
+ ? mergePublicConfigKeys(inlinePublicConfigKeys, readPublicConfigKeys(publicConfigFile))
216
+ : inlinePublicConfigKeys;
198
217
 
199
218
  // Load env from project root
200
219
  dotenv.config({ path: path.resolve(projectRoot, ".env") });
201
220
  if (publicConfigKeys.length > 0) {
202
- process.env.VITE_MP_CONFIG = JSON.stringify(resolveConfig(publicConfigKeys));
203
221
  // Bake only the NAMES of the public keys, never a value: this is what lets
204
222
  // the SSR node process resolve their values from ITS OWN process.env at
205
223
  // request time and publish them into the served document
206
224
  // (@multiplatform.one/platform runtimeConfig.ts). Values stay out of the
207
225
  // image, so one build is deployable to every environment; the names are
208
226
  // also the allowlist that keeps a private key from ever being serialized.
209
- process.env.VITE_MP_PUBLIC_CONFIG_KEYS = JSON.stringify(publicConfigKeys);
227
+ bakePublicConfig(publicConfigKeys);
210
228
  }
211
229
 
212
230
  const vitePlugins: UserConfig["plugins"] = [];
213
231
  vitePlugins.push(preferBuiltWorkspaceEntryPlugin());
232
+ if (publicConfigFile) {
233
+ vitePlugins.push(
234
+ publicConfigPlugin({ file: publicConfigFile, projectRoot, keys: inlinePublicConfigKeys }),
235
+ );
236
+ }
214
237
 
215
238
  if (one) {
216
239
  // One plugin must be added by the consumer in their extraPlugins.
@@ -501,6 +524,11 @@ export {
501
524
  discoverPublicPackageRoots,
502
525
  publicPackageViteSourceAliases,
503
526
  } from "./workspacePublicPackages.js";
527
+ export {
528
+ publicConfigPlugin,
529
+ readPublicConfigKeys,
530
+ type PublicConfigPluginOptions,
531
+ } from "./publicConfig.js";
504
532
 
505
533
  /**
506
534
  * Aliases react-native to react-native-web in the SSR environment.
@@ -565,6 +593,18 @@ function clientBrokenEsmPlugin(): Plugin {
565
593
  "color",
566
594
  // query-string v7 is CJS-only; imported by @react-navigation/core for URL parsing.
567
595
  "query-string",
596
+ // react's JSX runtimes are CJS with no "import" condition, so a deep
597
+ // import of a @multiplatform.one/* src .tsx served raw fails with
598
+ // "does not provide an export named 'jsx'" (MPO-223).
599
+ "react/jsx-runtime",
600
+ "react/jsx-dev-runtime",
601
+ // Vite never discovers a dep imported from a file inside
602
+ // node_modules; it serves it raw. A consumer's deep import of a
603
+ // @multiplatform.one/* src file sits in node_modules, so its bare
604
+ // "tamagui" import went raw and dragged react-native-web in raw, whose
605
+ // CJS deps (@react-native/normalize-colors, inline-style-prefixer/lib)
606
+ // have no ESM default. The barrel path never meets it (MPO-223).
607
+ "tamagui",
568
608
  ];
569
609
  const include: string[] = clientEnv.optimizeDeps.include ?? [];
570
610
  for (const dep of extras) {
@@ -845,6 +885,7 @@ function ssrCjsExternalFixPlugin(extras: string[]): Plugin {
845
885
  const external = config.ssr.external ?? [];
846
886
  if (!Array.isArray(external)) return; // true = everything external already
847
887
  for (const e of extras) {
888
+ if (config.command === "build" && requiresReact(e)) continue;
848
889
  if (!external.includes(e)) external.push(e);
849
890
  }
850
891
  (config.ssr as { external?: string[] | boolean }).external = external;
@@ -852,6 +893,10 @@ function ssrCjsExternalFixPlugin(extras: string[]): Plugin {
852
893
  };
853
894
  }
854
895
 
896
+ function requiresReact(id: string): boolean {
897
+ return id === "use-sync-external-store" || id.startsWith("use-sync-external-store/");
898
+ }
899
+
855
900
  /**
856
901
  * Restore Object.prototype methods shadowed by hoisted globals on NATIVE.
857
902
  *
@@ -0,0 +1,36 @@
1
+ import type { Plugin } from "vite";
2
+ export declare const bakedConfigEnvKey = "VITE_MP_CONFIG";
3
+ export declare const publicConfigKeysEnvKey = "VITE_MP_PUBLIC_CONFIG_KEYS";
4
+ /**
5
+ * The `public` key names of a config.json, read rather than imported: a
6
+ * static import puts the file on Vite's configFileDependencies, and every
7
+ * edit then restarts the dev server, re-optimizes deps and 504s each open tab
8
+ * (MPO-247). A read keeps it off that list.
9
+ */
10
+ export declare function readPublicConfigKeys(file: string): string[];
11
+ export declare function mergePublicConfigKeys(...lists: string[][]): string[];
12
+ /**
13
+ * Put the bake on process.env: the values resolved from the environment under
14
+ * VITE_MP_CONFIG and the key NAMES under VITE_MP_PUBLIC_CONFIG_KEYS. Names,
15
+ * never a value, is what lets the SSR node process resolve them from its own
16
+ * environment at request time (@multiplatform.one/platform runtimeConfig.ts).
17
+ */
18
+ export declare function bakePublicConfig(keys: string[]): void;
19
+ export interface PublicConfigPluginOptions {
20
+ /** Absolute path of the config.json whose `public` array names the keys. */
21
+ file: string;
22
+ /** Directory holding the `.env` the values are resolved from. */
23
+ projectRoot: string;
24
+ /** Keys the config declares inline, kept alongside the file's. */
25
+ keys?: string[];
26
+ }
27
+ /**
28
+ * Dev-server half of `publicConfigFile`. vite:define freezes its replacement
29
+ * table per environment when the server starts, so this plugin inlines the
30
+ * two baked expressions itself (it runs ahead of vite:define), remembers the
31
+ * modules that carried them, and when config.json changes rebakes,
32
+ * invalidates those modules and reloads every environment. The server never
33
+ * restarts, so the dep optimizer never runs again.
34
+ */
35
+ export declare function publicConfigPlugin(options: PublicConfigPluginOptions): Plugin;
36
+ //# sourceMappingURL=publicConfig.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"publicConfig.d.ts","sourceRoot":"","sources":["../src/publicConfig.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAe,MAAM,EAAiB,MAAM,MAAM,CAAC;AAE/D,eAAO,MAAM,iBAAiB,mBAAmB,CAAC;AAClD,eAAO,MAAM,sBAAsB,+BAA+B,CAAC;AAEnE;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAK3D;AAED,wBAAgB,qBAAqB,CAAC,GAAG,KAAK,EAAE,MAAM,EAAE,EAAE,GAAG,MAAM,EAAE,CAEpE;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CAGrD;AAED,MAAM,WAAW,yBAAyB;IACxC,4EAA4E;IAC5E,IAAI,EAAE,MAAM,CAAC;IACb,iEAAiE;IACjE,WAAW,EAAE,MAAM,CAAC;IACpB,kEAAkE;IAClE,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;CACjB;AAgCD;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,yBAAyB,GAAG,MAAM,CAoF7E"}
@@ -1 +1 @@
1
- {"version":3,"file":"singletonDepAliases.d.ts","sourceRoot":"","sources":["../src/singletonDepAliases.ts"],"names":[],"mappings":"AAsGA;;;;;;;;;GASG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,GAAE,MAAsB,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAUxF;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,uBAAuB,CACrC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC5B,IAAI,GAAE,MAAsB,EAC5B,SAAS,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAM,GACrC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAOxB"}
1
+ {"version":3,"file":"singletonDepAliases.d.ts","sourceRoot":"","sources":["../src/singletonDepAliases.ts"],"names":[],"mappings":"AA6GA;;;;;;;;;GASG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,GAAE,MAAsB,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAUxF;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,uBAAuB,CACrC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC5B,IAAI,GAAE,MAAsB,EAC5B,SAAS,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAM,GACrC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAOxB"}
@@ -1 +1 @@
1
- {"version":3,"file":"storybook.d.ts","sourceRoot":"","sources":["../src/storybook.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAU,UAAU,EAAE,MAAM,MAAM,CAAC;AAM/C,MAAM,WAAW,gCAAgC;IAC/C;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IAEvB;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAEjC;;OAEG;IACH,OAAO,CAAC,EAAE,UAAU,CAAC,SAAS,CAAC,CAAC;IAEhC;;OAEG;IACH,MAAM,CAAC,EAAE,UAAU,CAAC,QAAQ,CAAC,CAAC;CAC/B;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,yBAAyB,CACvC,OAAO,GAAE,gCAAqC,GAC7C,UAAU,CA8KZ"}
1
+ {"version":3,"file":"storybook.d.ts","sourceRoot":"","sources":["../src/storybook.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAU,UAAU,EAAE,MAAM,MAAM,CAAC;AAM/C,MAAM,WAAW,gCAAgC;IAC/C;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IAEvB;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAEjC;;OAEG;IACH,OAAO,CAAC,EAAE,UAAU,CAAC,SAAS,CAAC,CAAC;IAEhC;;OAEG;IACH,MAAM,CAAC,EAAE,UAAU,CAAC,QAAQ,CAAC,CAAC;CAC/B;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,yBAAyB,CACvC,OAAO,GAAE,gCAAqC,GAC7C,UAAU,CAqLZ"}
package/types/vite.d.ts CHANGED
@@ -6,10 +6,18 @@ export interface CreateViteConfigOptions {
6
6
  */
7
7
  projectRoot?: string;
8
8
  /**
9
- * Public config keys to expose via VITE_MP_CONFIG.
10
- * These are typically the `public` keys from features/config.json.
9
+ * Public config keys to expose via VITE_MP_CONFIG, declared inline.
11
10
  */
12
11
  publicConfigKeys?: string[];
12
+ /**
13
+ * Absolute path of the config.json whose `public` array names the keys to
14
+ * expose via VITE_MP_CONFIG. Use this rather than importing the file into
15
+ * the vite config: an import makes it a config dependency, so adding a key
16
+ * restarts the dev server and re-optimizes deps, which 504s every open tab
17
+ * (MPO-247). Read instead, the file is watched in dev: a change rebakes the
18
+ * keys and reloads open clients, and the server never restarts.
19
+ */
20
+ publicConfigFile?: string;
13
21
  /**
14
22
  * Enable Tamagui plugin. Defaults to true.
15
23
  */
@@ -139,11 +147,11 @@ export interface CreateViteConfigOptions {
139
147
  * @example
140
148
  * ```ts
141
149
  * // apps/one/vite.config.ts
150
+ * import path from "node:path";
142
151
  * import { createViteConfig } from "@multiplatform.one/config/vite";
143
- * import { public as publicConfigKeys } from "../../features/config.json";
144
152
  *
145
153
  * export default createViteConfig({
146
- * publicConfigKeys,
154
+ * publicConfigFile: path.resolve(__dirname, "../../packages/config/config.json"),
147
155
  * one: { web: { deploy: "node", defaultRenderMode: "ssr" } },
148
156
  * tamagui: { config: "./config/tamagui.config.ts" },
149
157
  * i18n: { paths: ["../../features/i18n"] },
@@ -152,4 +160,5 @@ export interface CreateViteConfigOptions {
152
160
  */
153
161
  export declare function createViteConfig(options?: CreateViteConfigOptions): UserConfig;
154
162
  export { discoverPublicPackageRoots, publicPackageViteSourceAliases, } from "./workspacePublicPackages.js";
163
+ export { publicConfigPlugin, readPublicConfigKeys, type PublicConfigPluginOptions, } from "./publicConfig.js";
155
164
  //# sourceMappingURL=vite.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"vite.d.ts","sourceRoot":"","sources":["../src/vite.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAU,UAAU,EAAE,MAAM,MAAM,CAAC;AAI/C,MAAM,WAAW,uBAAuB;IACtC;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB;;;OAGG;IACH,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC;IAE5B;;OAEG;IACH,OAAO,CAAC,EACJ,OAAO,GACP;QACE;;;WAGG;QACH,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;QAEtB;;;WAGG;QACH,MAAM,CAAC,EAAE,MAAM,CAAC;QAEhB;;WAEG;QACH,SAAS,CAAC,EAAE,MAAM,CAAC;KACpB,CAAC;IAEN;;OAEG;IACH,IAAI,CAAC,EACD,OAAO,GACP;QACE;;;WAGG;QACH,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;QAEjB;;WAEG;QACH,mBAAmB,CAAC,EAAE,MAAM,CAAC;KAC9B,CAAC;IAEN;;;OAGG;IACH,GAAG,CAAC,EACA,OAAO,GACP;QACE,MAAM,CAAC,EAAE;YAAE,IAAI,CAAC,EAAE,MAAM,CAAA;SAAE,CAAC;QAC3B,GAAG,CAAC,EAAE;YAAE,MAAM,CAAC,EAAE,MAAM,CAAC;YAAC,iBAAiB,CAAC,EAAE,MAAM,CAAA;SAAE,CAAC;QACtD,KAAK,CAAC,EAAE;YAAE,QAAQ,CAAC,EAAE,OAAO,CAAA;SAAE,CAAC;QAC/B,MAAM,CAAC,EAAE;YAAE,GAAG,CAAC,EAAE,MAAM,CAAA;SAAE,CAAC;QAC1B,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;KAChC,CAAC;IAEN;;OAEG;IACH,GAAG,CAAC,EAAE,UAAU,CAAC,KAAK,CAAC,CAAC;IAExB;;OAEG;IACH,MAAM,CAAC,EAAE,UAAU,CAAC,QAAQ,CAAC,CAAC;IAE9B;;OAEG;IACH,OAAO,CAAC,EAAE,UAAU,CAAC,SAAS,CAAC,CAAC;IAEhC;;OAEG;IACH,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAE9B;;OAEG;IACH,OAAO,CAAC,EAAE;QACR,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;QACnB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;QACnB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;KACrB,CAAC;IAEF;;;;;;OAMG;IACH,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IAEtB;;;;;;;;OAQG;IACH,cAAc,CAAC,EAAE,MAAM,EAAE,GAAG,KAAK,CAAC;IAElC;;;OAGG;IACH,WAAW,CAAC,EAAE;QACZ;;;;;;WAMG;QACH,WAAW,CAAC,EAAE,OAAO,CAAC;QACtB;;;;;;;WAOG;QACH,QAAQ,CAAC,EAAE,OAAO,CAAC;KACpB,CAAC;CACH;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,GAAE,uBAA4B,GAAG,UAAU,CAiUlF;AAED,OAAO,EACL,0BAA0B,EAC1B,8BAA8B,GAC/B,MAAM,8BAA8B,CAAC"}
1
+ {"version":3,"file":"vite.d.ts","sourceRoot":"","sources":["../src/vite.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAU,UAAU,EAAE,MAAM,MAAM,CAAC;AAI/C,MAAM,WAAW,uBAAuB;IACtC;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB;;OAEG;IACH,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC;IAE5B;;;;;;;OAOG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAE1B;;OAEG;IACH,OAAO,CAAC,EACJ,OAAO,GACP;QACE;;;WAGG;QACH,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;QAEtB;;;WAGG;QACH,MAAM,CAAC,EAAE,MAAM,CAAC;QAEhB;;WAEG;QACH,SAAS,CAAC,EAAE,MAAM,CAAC;KACpB,CAAC;IAEN;;OAEG;IACH,IAAI,CAAC,EACD,OAAO,GACP;QACE;;;WAGG;QACH,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;QAEjB;;WAEG;QACH,mBAAmB,CAAC,EAAE,MAAM,CAAC;KAC9B,CAAC;IAEN;;;OAGG;IACH,GAAG,CAAC,EACA,OAAO,GACP;QACE,MAAM,CAAC,EAAE;YAAE,IAAI,CAAC,EAAE,MAAM,CAAA;SAAE,CAAC;QAC3B,GAAG,CAAC,EAAE;YAAE,MAAM,CAAC,EAAE,MAAM,CAAC;YAAC,iBAAiB,CAAC,EAAE,MAAM,CAAA;SAAE,CAAC;QACtD,KAAK,CAAC,EAAE;YAAE,QAAQ,CAAC,EAAE,OAAO,CAAA;SAAE,CAAC;QAC/B,MAAM,CAAC,EAAE;YAAE,GAAG,CAAC,EAAE,MAAM,CAAA;SAAE,CAAC;QAC1B,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;KAChC,CAAC;IAEN;;OAEG;IACH,GAAG,CAAC,EAAE,UAAU,CAAC,KAAK,CAAC,CAAC;IAExB;;OAEG;IACH,MAAM,CAAC,EAAE,UAAU,CAAC,QAAQ,CAAC,CAAC;IAE9B;;OAEG;IACH,OAAO,CAAC,EAAE,UAAU,CAAC,SAAS,CAAC,CAAC;IAEhC;;OAEG;IACH,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAE9B;;OAEG;IACH,OAAO,CAAC,EAAE;QACR,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;QACnB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;QACnB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;KACrB,CAAC;IAEF;;;;;;OAMG;IACH,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IAEtB;;;;;;;;OAQG;IACH,cAAc,CAAC,EAAE,MAAM,EAAE,GAAG,KAAK,CAAC;IAElC;;;OAGG;IACH,WAAW,CAAC,EAAE;QACZ;;;;;;WAMG;QACH,WAAW,CAAC,EAAE,OAAO,CAAC;QACtB;;;;;;;WAOG;QACH,QAAQ,CAAC,EAAE,OAAO,CAAC;KACpB,CAAC;CACH;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,GAAE,uBAA4B,GAAG,UAAU,CAyUlF;AAED,OAAO,EACL,0BAA0B,EAC1B,8BAA8B,GAC/B,MAAM,8BAA8B,CAAC;AACtC,OAAO,EACL,kBAAkB,EAClB,oBAAoB,EACpB,KAAK,yBAAyB,GAC/B,MAAM,mBAAmB,CAAC"}