@multiplatform.one/platform 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.
Files changed (44) hide show
  1. package/README.md +7 -3
  2. package/dist/cjs/config/config.cjs +14 -8
  3. package/dist/cjs/config/index.cjs +1 -0
  4. package/dist/cjs/config/runtimeConfig.cjs +100 -0
  5. package/dist/cjs/index.cjs +2 -0
  6. package/dist/cjs/platform/index.gnome.cjs +59 -0
  7. package/dist/cjs/platform/platformBase.cjs +8 -1
  8. package/dist/esm/config/config.mjs +14 -7
  9. package/dist/esm/config/config.mjs.map +1 -1
  10. package/dist/esm/config/index.mjs +1 -0
  11. package/dist/esm/config/index.mjs.map +1 -1
  12. package/dist/esm/config/runtimeConfig.mjs +67 -0
  13. package/dist/esm/config/runtimeConfig.mjs.map +1 -0
  14. package/dist/esm/index.mjs +2 -1
  15. package/dist/esm/index.mjs.map +1 -1
  16. package/dist/esm/platform/index.gnome.mjs +34 -0
  17. package/dist/esm/platform/index.gnome.mjs.map +1 -0
  18. package/dist/esm/platform/platformBase.mjs +8 -1
  19. package/dist/esm/platform/platformBase.mjs.map +1 -1
  20. package/package.json +8 -4
  21. package/src/config/config.spec.ts +62 -1
  22. package/src/config/config.ts +17 -8
  23. package/src/config/index.ts +1 -0
  24. package/src/config/runtimeConfig.native.ts +84 -0
  25. package/src/config/runtimeConfig.spec.ts +128 -0
  26. package/src/config/runtimeConfig.ts +159 -0
  27. package/src/index.ts +1 -0
  28. package/src/platform/index.gnome.spec.ts +42 -0
  29. package/src/platform/index.gnome.ts +51 -0
  30. package/src/platform/platformBase.spec.ts +7 -0
  31. package/src/platform/platformBase.ts +8 -0
  32. package/types/config/config.d.ts.map +1 -1
  33. package/types/config/index.d.ts +1 -0
  34. package/types/config/index.d.ts.map +1 -1
  35. package/types/config/runtimeConfig.d.ts +74 -0
  36. package/types/config/runtimeConfig.d.ts.map +1 -0
  37. package/types/config/runtimeConfig.native.d.ts +21 -0
  38. package/types/config/runtimeConfig.native.d.ts.map +1 -0
  39. package/types/index.d.ts +1 -1
  40. package/types/index.d.ts.map +1 -1
  41. package/types/platform/index.gnome.d.ts +5 -0
  42. package/types/platform/index.gnome.d.ts.map +1 -0
  43. package/types/platform/platformBase.d.ts +3 -1
  44. package/types/platform/platformBase.d.ts.map +1 -1
package/README.md CHANGED
@@ -13,7 +13,7 @@ pnpm add @multiplatform.one/platform
13
13
  ## What it owns
14
14
 
15
15
  - **Detection flags** — `isWeb`, `isNative`, `isIos`, `isAndroid`, `isServer`,
16
- `isClient`, `isTauri`, `isDesktop`, `isExpo`, `isNext`, `isStorybook`,
16
+ `isClient`, `isGnome`, `isTauri`, `isDesktop`, `isExpo`, `isNext`, `isStorybook`,
17
17
  `isChrome`, `isFirefox`, `isWebExtension`, `isChromeExtension`,
18
18
  `isFirefoxExtension`, `isIframe`, `isTouchable`, `isWebTouchable`,
19
19
  `isWindowDefined`, … plus the full `platform` object (`platform.preciseName`)
@@ -29,12 +29,16 @@ pnpm add @multiplatform.one/platform
29
29
  ## Usage
30
30
 
31
31
  ```tsx
32
- import { isNative, isServer, isTauri } from "@multiplatform.one/platform";
32
+ import { isGnome, isNative, isServer, isTauri } from "@multiplatform.one/platform";
33
33
 
34
34
  export function saveFile(contents: string) {
35
35
  if (isServer) return;
36
36
  if (isTauri) {
37
- // desktop path (see @multiplatform.one/desktop)
37
+ // webview desktop path (see @multiplatform.one/desktop)
38
+ return;
39
+ }
40
+ if (isGnome) {
41
+ // GTK desktop path (see @multiplatform.one/desktop)
38
42
  return;
39
43
  }
40
44
  if (isNative) {
@@ -25,13 +25,14 @@ __export(config_exports, {
25
25
  Config: () => Config
26
26
  });
27
27
  module.exports = __toCommonJS(config_exports);
28
- const import_meta = {};
28
+ var import_runtimeConfig = require("./runtimeConfig.cjs");
29
29
  class Config {
30
30
  _config = {};
31
31
  _blacklist = /* @__PURE__ */new Set([]);
32
32
  _lookupEnv(key) {
33
33
  if (this._blacklist.has(key)) return void 0;
34
- return process?.env?.[key];
34
+ if (typeof process === "undefined") return void 0;
35
+ return process.env?.[key];
35
36
  }
36
37
  _resolveConfig() {
37
38
  return Object.keys(this._config).reduce((config, key) => {
@@ -47,13 +48,18 @@ class Config {
47
48
  }, {});
48
49
  }
49
50
  constructor(config = {}) {
50
- let viteConfig = {};
51
- try {
52
- const raw = typeof import_meta !== "undefined" && import_meta.env?.VITE_MP_CONFIG;
53
- viteConfig = JSON.parse(raw || "{}");
54
- } catch {}
55
51
  this._config = {
56
- ...this._reduceConfig(typeof viteConfig === "object" ? viteConfig : {}),
52
+ // 1. BUILD time: public config baked into the bundle via VITE_MP_CONFIG.
53
+ // Kept first (and kept working) so apps that bake their config in —
54
+ // native, GNOME, static web — are unchanged.
55
+ ...this._reduceConfig((0, import_runtimeConfig.bakedPublicConfig)()),
56
+ // 2. RUNTIME: the public payload the SSR document published into the
57
+ // browser (see runtimeConfig.ts). Wins over the bake so a redeployed
58
+ // container overrides a stale build-time value, and so an image built
59
+ // with an EMPTY build environment can still be configured per
60
+ // deployment. `process.env` is not reachable here.
61
+ ...this._reduceConfig((0, import_runtimeConfig.readRuntimePublicConfig)()),
62
+ // 3. Explicit values handed to the constructor always win.
57
63
  ...this._reduceConfig(config)
58
64
  };
59
65
  }
@@ -28,4 +28,5 @@ __export(config_exports, {
28
28
  module.exports = __toCommonJS(config_exports);
29
29
  var import_config = require("./config.cjs");
30
30
  __reExport(config_exports, require("./config.cjs"), module.exports);
31
+ __reExport(config_exports, require("./runtimeConfig.cjs"), module.exports);
31
32
  const config = new import_config.Config();
@@ -0,0 +1,100 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
3
+ var __getOwnPropNames = Object.getOwnPropertyNames;
4
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
5
+ var __export = (target, all) => {
6
+ for (var name in all) __defProp(target, name, {
7
+ get: all[name],
8
+ enumerable: true
9
+ });
10
+ };
11
+ var __copyProps = (to, from, except, desc) => {
12
+ if (from && typeof from === "object" || typeof from === "function") {
13
+ for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
14
+ get: () => from[key],
15
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
16
+ });
17
+ }
18
+ return to;
19
+ };
20
+ var __toCommonJS = mod => __copyProps(__defProp({}, "__esModule", {
21
+ value: true
22
+ }), mod);
23
+ var runtimeConfig_exports = {};
24
+ __export(runtimeConfig_exports, {
25
+ bakedConfigEnvKey: () => bakedConfigEnvKey,
26
+ bakedPublicConfig: () => bakedPublicConfig,
27
+ publicConfigKeys: () => publicConfigKeys,
28
+ publicConfigKeysEnvKey: () => publicConfigKeysEnvKey,
29
+ readRuntimePublicConfig: () => readRuntimePublicConfig,
30
+ resolvePublicConfig: () => resolvePublicConfig,
31
+ runtimePublicConfigKey: () => runtimePublicConfigKey,
32
+ serializeRuntimePublicConfig: () => serializeRuntimePublicConfig
33
+ });
34
+ module.exports = __toCommonJS(runtimeConfig_exports);
35
+ const import_meta = {};
36
+ const runtimePublicConfigKey = "__mp_public_config__";
37
+ const publicConfigKeysEnvKey = "VITE_MP_PUBLIC_CONFIG_KEYS";
38
+ const bakedConfigEnvKey = "VITE_MP_CONFIG";
39
+ function importMetaEnv() {
40
+ try {
41
+ if (typeof import_meta === "undefined") return {};
42
+ return import_meta.env || {};
43
+ } catch {
44
+ return {};
45
+ }
46
+ }
47
+ function processEnv() {
48
+ try {
49
+ if (typeof process === "undefined") return {};
50
+ return process.env || {};
51
+ } catch {
52
+ return {};
53
+ }
54
+ }
55
+ function readBuildEnv(key) {
56
+ return importMetaEnv()[key] ?? processEnv()[key];
57
+ }
58
+ function parseJson(raw) {
59
+ if (!raw) return void 0;
60
+ try {
61
+ return JSON.parse(raw);
62
+ } catch {
63
+ return void 0;
64
+ }
65
+ }
66
+ function stringifyValues(source) {
67
+ return Object.entries(source).reduce((acc, [key, value]) => {
68
+ if (typeof value !== "undefined" && value !== null) acc[key] = String(value);
69
+ return acc;
70
+ }, {});
71
+ }
72
+ function publicConfigKeys() {
73
+ const parsed = parseJson(readBuildEnv(publicConfigKeysEnvKey));
74
+ if (!Array.isArray(parsed)) return [];
75
+ return parsed.filter(key => typeof key === "string" && key.length > 0);
76
+ }
77
+ function bakedPublicConfig() {
78
+ const parsed = parseJson(readBuildEnv(bakedConfigEnvKey));
79
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return {};
80
+ return stringifyValues(parsed);
81
+ }
82
+ function resolvePublicConfig(env = processEnv()) {
83
+ const baked = bakedPublicConfig();
84
+ return publicConfigKeys().reduce((acc, key) => {
85
+ const value = env[key] ?? baked[key];
86
+ if (typeof value === "string" && value.length > 0) acc[key] = value;
87
+ return acc;
88
+ }, {});
89
+ }
90
+ function readRuntimePublicConfig() {
91
+ const raw = globalThis[runtimePublicConfigKey];
92
+ if (!raw || typeof raw !== "object" || Array.isArray(raw)) return void 0;
93
+ return stringifyValues(raw);
94
+ }
95
+ function safeJsonStringify(value) {
96
+ return JSON.stringify(value ?? {}).replace(/</g, "\\u003c").replace(/>/g, "\\u003e").replace(/\u2028/g, "\\u2028").replace(/\u2029/g, "\\u2029");
97
+ }
98
+ function serializeRuntimePublicConfig(config = resolvePublicConfig()) {
99
+ return `globalThis[${JSON.stringify(runtimePublicConfigKey)}]=${safeJsonStringify(config)};`;
100
+ }
@@ -32,6 +32,7 @@ __export(index_exports, {
32
32
  isExpo: () => isExpo,
33
33
  isFirefox: () => isFirefox,
34
34
  isFirefoxExtension: () => isFirefoxExtension,
35
+ isGnome: () => isGnome,
35
36
  isIframe: () => isIframe,
36
37
  isIos: () => isIos,
37
38
  isNative: () => isNative,
@@ -65,6 +66,7 @@ const {
65
66
  isExpo,
66
67
  isFirefox,
67
68
  isFirefoxExtension,
69
+ isGnome,
68
70
  isIframe,
69
71
  isIos,
70
72
  isNative,
@@ -0,0 +1,59 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
3
+ var __getOwnPropNames = Object.getOwnPropertyNames;
4
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
5
+ var __export = (target, all) => {
6
+ for (var name in all) __defProp(target, name, {
7
+ get: all[name],
8
+ enumerable: true
9
+ });
10
+ };
11
+ var __copyProps = (to, from, except, desc) => {
12
+ if (from && typeof from === "object" || typeof from === "function") {
13
+ for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
14
+ get: () => from[key],
15
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
16
+ });
17
+ }
18
+ return to;
19
+ };
20
+ var __toCommonJS = mod => __copyProps(__defProp({}, "__esModule", {
21
+ value: true
22
+ }), mod);
23
+ var index_gnome_exports = {};
24
+ __export(index_gnome_exports, {
25
+ platform: () => platform
26
+ });
27
+ module.exports = __toCommonJS(index_gnome_exports);
28
+ var import_platformBase = require("./platformBase.cjs");
29
+ const platform = {
30
+ ...import_platformBase.platformBase,
31
+ isGnome: true,
32
+ // GTK is a desktop, and it is not a browser — so `isNative` too, which is
33
+ // exactly why Gnome sits ahead of Native in the precision order.
34
+ isDesktop: true,
35
+ isNative: true,
36
+ isClient: true,
37
+ isServer: false,
38
+ isWeb: false,
39
+ isBrowser: false,
40
+ isChrome: false,
41
+ isFirefox: false,
42
+ isIframe: false,
43
+ isStorybook: false,
44
+ isWebExtension: false,
45
+ isChromeExtension: false,
46
+ isFirefoxExtension: false,
47
+ isExpo: false,
48
+ isNext: false,
49
+ // A GTK pointer desktop. Touch exists on some hardware but is not the
50
+ // interaction model the layout should assume.
51
+ isTouchable: false,
52
+ isWebTouchable: false,
53
+ // There is a `window` under the react-gnome polyfills, but it is a stub
54
+ // with no layout, no events and no document. Callers branching on this are
55
+ // asking "can I touch the DOM", and the answer is no.
56
+ isWindowDefined: false
57
+ };
58
+ platform.preciseName = (0, import_platformBase.getPreciseName)(platform);
59
+ platform.broadName = (0, import_platformBase.getBroadName)(platform);
@@ -28,7 +28,13 @@ __export(platformBase_exports, {
28
28
  });
29
29
  module.exports = __toCommonJS(platformBase_exports);
30
30
  var import_constants = require("@tamagui/constants");
31
- const platformOrder = ["Ios", "Android", "Native", "Tauri", "Desktop", "ChromeExtension", "FirefoxExtension", "WebExtension", "Next", "Expo", "Chrome", "Firefox", "Web", "Browser", "Client", "Server", "Iframe", "Storybook"];
31
+ const platformOrder = ["Ios", "Android",
32
+ // Gnome outranks Native: the GTK target reports isNative (it is not a
33
+ // browser) but "gnome" is the precise answer callers want.
34
+ "Gnome", "Native",
35
+ // Tauri outranks Desktop/Web the same way: the webview host reports isWeb
36
+ // and isDesktop, but "tauri" is the precise answer.
37
+ "Tauri", "Desktop", "ChromeExtension", "FirefoxExtension", "WebExtension", "Next", "Expo", "Chrome", "Firefox", "Web", "Browser", "Client", "Server", "Iframe", "Storybook"];
32
38
  const platformBase = {
33
39
  isAndroid: false,
34
40
  isBrowser: false,
@@ -39,6 +45,7 @@ const platformBase = {
39
45
  isExpo: false,
40
46
  isFirefox: false,
41
47
  isFirefoxExtension: false,
48
+ isGnome: false,
42
49
  isIframe: false,
43
50
  isIos: false,
44
51
  isNative: false,
@@ -1,9 +1,11 @@
1
+ import { bakedPublicConfig, readRuntimePublicConfig } from "./runtimeConfig.mjs";
1
2
  class Config {
2
3
  _config = {};
3
4
  _blacklist = /* @__PURE__ */new Set([]);
4
5
  _lookupEnv(key) {
5
6
  if (this._blacklist.has(key)) return void 0;
6
- return process?.env?.[key];
7
+ if (typeof process === "undefined") return void 0;
8
+ return process.env?.[key];
7
9
  }
8
10
  _resolveConfig() {
9
11
  return Object.keys(this._config).reduce((config, key) => {
@@ -19,13 +21,18 @@ class Config {
19
21
  }, {});
20
22
  }
21
23
  constructor(config = {}) {
22
- let viteConfig = {};
23
- try {
24
- const raw = typeof import.meta !== "undefined" && import.meta.env?.VITE_MP_CONFIG;
25
- viteConfig = JSON.parse(raw || "{}");
26
- } catch {}
27
24
  this._config = {
28
- ...this._reduceConfig(typeof viteConfig === "object" ? viteConfig : {}),
25
+ // 1. BUILD time: public config baked into the bundle via VITE_MP_CONFIG.
26
+ // Kept first (and kept working) so apps that bake their config in —
27
+ // native, GNOME, static web — are unchanged.
28
+ ...this._reduceConfig(bakedPublicConfig()),
29
+ // 2. RUNTIME: the public payload the SSR document published into the
30
+ // browser (see runtimeConfig.ts). Wins over the bake so a redeployed
31
+ // container overrides a stale build-time value, and so an image built
32
+ // with an EMPTY build environment can still be configured per
33
+ // deployment. `process.env` is not reachable here.
34
+ ...this._reduceConfig(readRuntimePublicConfig()),
35
+ // 3. Explicit values handed to the constructor always win.
29
36
  ...this._reduceConfig(config)
30
37
  };
31
38
  }
@@ -1 +1 @@
1
- {"version":3,"names":["Config","_config","_blacklist","Set","_lookupEnv","key","has","process","env","_resolveConfig","Object","keys","reduce","config","value","_reduceConfig","entries","toString","constructor","viteConfig","raw","import","meta","VITE_MP_CONFIG","JSON","parse","get","defaultValue","set","add","remove"],"sources":["../../../src/config/config.ts"],"sourcesContent":[null],"mappings":"AAEO,MAAMA,MAAA,CAA0B;EAC7BC,OAAA,GAAkC,CAAC;EAEnCC,UAAA,GAA0B,mBAAIC,GAAA,CAAI,EAAE;EAEpCC,WAAWC,GAAA,EAAiC;IAClD,IAAI,KAAKH,UAAA,CAAWI,GAAA,CAAID,GAAG,GAAG,OAAO;IACrC,OAAOE,OAAA,EAASC,GAAA,GAAMH,GAAG;EAC3B;EAEQI,eAAA,EAAiB;IACvB,OAAOC,MAAA,CAAOC,IAAA,CAAK,KAAKV,OAAO,EAAEW,MAAA,CAA+B,CAACC,MAAA,EAAQR,GAAA,KAAQ;MAC/E,MAAMS,KAAA,GAAQ,KAAKV,UAAA,CAAWC,GAAG,KAAK,KAAKJ,OAAA,CAAQI,GAAG;MACtD,IAAI,OAAOS,KAAA,KAAU,aAAaD,MAAA,CAAOR,GAAG,IAAIS,KAAA;MAChD,OAAOD,MAAA;IACT,GAAG,CAAC,CAAC;EACP;EAEQE,cAAcF,MAAA,GAA6C,CAAC,GAAG;IACrE,OAAOH,MAAA,CAAOM,OAAA,CAAQH,MAAM,EAAED,MAAA,CAC5B,CAACC,OAAA,EAAQ,CAACR,GAAA,EAAKS,KAAK,MAAoC;MACtD,IAAI,OAAOA,KAAA,KAAU,aAAaD,OAAA,CAAOR,GAAG,IAAIS,KAAA,CAAMG,QAAA,CAAS;MAC/D,OAAOJ,OAAA;IACT,GACA,CAAC,CACH;EACF;EAEAK,YAAYL,MAAA,GAA6C,CAAC,GAAG;IAC3D,IAAIM,UAAA,GAAiD,CAAC;IACtD,IAAI;MAEF,MAAMC,GAAA,GAAM,OAAOC,MAAA,CAAAC,IAAA,KAAgB,eAAeD,MAAA,CAAAC,IAAA,CAAYd,GAAA,EAAKe,cAAA;MACnEJ,UAAA,GAAaK,IAAA,CAAKC,KAAA,CAAML,GAAA,IAAO,IAAI;IACrC,QAAQ,CAAC;IACT,KAAKnB,OAAA,GAAU;MACb,GAAG,KAAKc,aAAA,CAAc,OAAOI,UAAA,KAAe,WAAWA,UAAA,GAAa,CAAC,CAAC;MACtE,GAAG,KAAKJ,aAAA,CAAcF,MAAM;IAC9B;EACF;EAKAa,IAAIrB,GAAA,EAAcsB,YAAA,EAAoE;IACpF,MAAMd,MAAA,GAAS,KAAKJ,cAAA,CAAe;IACnC,IAAI,CAACJ,GAAA,EAAK,OAAOQ,MAAA;IACjB,OAAOA,MAAA,CAAOR,GAAG,KAAKsB,YAAA;EACxB;EAEAC,IAAIvB,GAAA,EAAaS,KAAA,EAAe;IAC9B,KAAKb,OAAA,CAAQI,GAAG,IAAIS,KAAA;IACpB,OAAOA,KAAA;EACT;EAEAe,IAAIf,KAAA,EAA+B;IACjC,KAAKb,OAAA,GAAU;MACb,GAAG,KAAKA,OAAA;MACR,GAAGa;IACL;IACA,OAAO,KAAKY,GAAA,CAAI;EAClB;EAEAI,OAAOzB,GAAA,EAAiC;IACtC,MAAMS,KAAA,GAAQ,KAAKY,GAAA,CAAIrB,GAAG;IAC1B,OAAO,KAAKJ,OAAA,CAAQI,GAAG;IACvB,OAAOS,KAAA;EACT;AACF","ignoreList":[]}
1
+ {"version":3,"names":["bakedPublicConfig","readRuntimePublicConfig","Config","_config","_blacklist","Set","_lookupEnv","key","has","process","env","_resolveConfig","Object","keys","reduce","config","value","_reduceConfig","entries","toString","constructor","get","defaultValue","set","add","remove"],"sources":["../../../src/config/config.ts"],"sourcesContent":[null],"mappings":"AAAA,SAASA,iBAAA,EAAmBC,uBAAA,QAA+B;AAGpD,MAAMC,MAAA,CAA0B;EAC7BC,OAAA,GAAkC,CAAC;EAEnCC,UAAA,GAA0B,mBAAIC,GAAA,CAAI,EAAE;EAEpCC,WAAWC,GAAA,EAAiC;IAClD,IAAI,KAAKH,UAAA,CAAWI,GAAA,CAAID,GAAG,GAAG,OAAO;IAIrC,IAAI,OAAOE,OAAA,KAAY,aAAa,OAAO;IAC3C,OAAOA,OAAA,CAAQC,GAAA,GAAMH,GAAG;EAC1B;EAEQI,eAAA,EAAiB;IACvB,OAAOC,MAAA,CAAOC,IAAA,CAAK,KAAKV,OAAO,EAAEW,MAAA,CAA+B,CAACC,MAAA,EAAQR,GAAA,KAAQ;MAC/E,MAAMS,KAAA,GAAQ,KAAKV,UAAA,CAAWC,GAAG,KAAK,KAAKJ,OAAA,CAAQI,GAAG;MACtD,IAAI,OAAOS,KAAA,KAAU,aAAaD,MAAA,CAAOR,GAAG,IAAIS,KAAA;MAChD,OAAOD,MAAA;IACT,GAAG,CAAC,CAAC;EACP;EAEQE,cAAcF,MAAA,GAA6C,CAAC,GAAG;IACrE,OAAOH,MAAA,CAAOM,OAAA,CAAQH,MAAM,EAAED,MAAA,CAC5B,CAACC,OAAA,EAAQ,CAACR,GAAA,EAAKS,KAAK,MAAoC;MACtD,IAAI,OAAOA,KAAA,KAAU,aAAaD,OAAA,CAAOR,GAAG,IAAIS,KAAA,CAAMG,QAAA,CAAS;MAC/D,OAAOJ,OAAA;IACT,GACA,CAAC,CACH;EACF;EAEAK,YAAYL,MAAA,GAA6C,CAAC,GAAG;IAC3D,KAAKZ,OAAA,GAAU;MAAA;MAAA;MAAA;MAIb,GAAG,KAAKc,aAAA,CAAcjB,iBAAA,CAAkB,CAAC;MAAA;MAAA;MAAA;MAAA;MAAA;MAMzC,GAAG,KAAKiB,aAAA,CAAchB,uBAAA,CAAwB,CAAC;MAAA;MAE/C,GAAG,KAAKgB,aAAA,CAAcF,MAAM;IAC9B;EACF;EAKAM,IAAId,GAAA,EAAce,YAAA,EAAoE;IACpF,MAAMP,MAAA,GAAS,KAAKJ,cAAA,CAAe;IACnC,IAAI,CAACJ,GAAA,EAAK,OAAOQ,MAAA;IACjB,OAAOA,MAAA,CAAOR,GAAG,KAAKe,YAAA;EACxB;EAEAC,IAAIhB,GAAA,EAAaS,KAAA,EAAe;IAC9B,KAAKb,OAAA,CAAQI,GAAG,IAAIS,KAAA;IACpB,OAAOA,KAAA;EACT;EAEAQ,IAAIR,KAAA,EAA+B;IACjC,KAAKb,OAAA,GAAU;MACb,GAAG,KAAKA,OAAA;MACR,GAAGa;IACL;IACA,OAAO,KAAKK,GAAA,CAAI;EAClB;EAEAI,OAAOlB,GAAA,EAAiC;IACtC,MAAMS,KAAA,GAAQ,KAAKK,GAAA,CAAId,GAAG;IAC1B,OAAO,KAAKJ,OAAA,CAAQI,GAAG;IACvB,OAAOS,KAAA;EACT;AACF","ignoreList":[]}
@@ -1,5 +1,6 @@
1
1
  import { Config } from "./config.mjs";
2
2
  export * from "./config.mjs";
3
+ export * from "./runtimeConfig.mjs";
3
4
  const config = new Config();
4
5
  export { config };
5
6
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"names":["Config","config"],"sources":["../../../src/config/index.ts"],"sourcesContent":[null],"mappings":"AAAA,SAASA,MAAA,QAAc;AAKvB,cAAc;AAHd,MAAMC,MAAA,GAAS,IAAID,MAAA,CAAO","ignoreList":[]}
1
+ {"version":3,"names":["Config","config"],"sources":["../../../src/config/index.ts"],"sourcesContent":[null],"mappings":"AAAA,SAASA,MAAA,QAAc;AAKvB,cAAc;AACd,cAAc;AAJd,MAAMC,MAAA,GAAS,IAAID,MAAA,CAAO","ignoreList":[]}
@@ -0,0 +1,67 @@
1
+ const runtimePublicConfigKey = "__mp_public_config__";
2
+ const publicConfigKeysEnvKey = "VITE_MP_PUBLIC_CONFIG_KEYS";
3
+ const bakedConfigEnvKey = "VITE_MP_CONFIG";
4
+ function importMetaEnv() {
5
+ try {
6
+ if (typeof import.meta === "undefined") return {};
7
+ return import.meta.env || {};
8
+ } catch {
9
+ return {};
10
+ }
11
+ }
12
+ function processEnv() {
13
+ try {
14
+ if (typeof process === "undefined") return {};
15
+ return process.env || {};
16
+ } catch {
17
+ return {};
18
+ }
19
+ }
20
+ function readBuildEnv(key) {
21
+ return importMetaEnv()[key] ?? processEnv()[key];
22
+ }
23
+ function parseJson(raw) {
24
+ if (!raw) return void 0;
25
+ try {
26
+ return JSON.parse(raw);
27
+ } catch {
28
+ return void 0;
29
+ }
30
+ }
31
+ function stringifyValues(source) {
32
+ return Object.entries(source).reduce((acc, [key, value]) => {
33
+ if (typeof value !== "undefined" && value !== null) acc[key] = String(value);
34
+ return acc;
35
+ }, {});
36
+ }
37
+ function publicConfigKeys() {
38
+ const parsed = parseJson(readBuildEnv(publicConfigKeysEnvKey));
39
+ if (!Array.isArray(parsed)) return [];
40
+ return parsed.filter(key => typeof key === "string" && key.length > 0);
41
+ }
42
+ function bakedPublicConfig() {
43
+ const parsed = parseJson(readBuildEnv(bakedConfigEnvKey));
44
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return {};
45
+ return stringifyValues(parsed);
46
+ }
47
+ function resolvePublicConfig(env = processEnv()) {
48
+ const baked = bakedPublicConfig();
49
+ return publicConfigKeys().reduce((acc, key) => {
50
+ const value = env[key] ?? baked[key];
51
+ if (typeof value === "string" && value.length > 0) acc[key] = value;
52
+ return acc;
53
+ }, {});
54
+ }
55
+ function readRuntimePublicConfig() {
56
+ const raw = globalThis[runtimePublicConfigKey];
57
+ if (!raw || typeof raw !== "object" || Array.isArray(raw)) return void 0;
58
+ return stringifyValues(raw);
59
+ }
60
+ function safeJsonStringify(value) {
61
+ return JSON.stringify(value ?? {}).replace(/</g, "\\u003c").replace(/>/g, "\\u003e").replace(/\u2028/g, "\\u2028").replace(/\u2029/g, "\\u2029");
62
+ }
63
+ function serializeRuntimePublicConfig(config = resolvePublicConfig()) {
64
+ return `globalThis[${JSON.stringify(runtimePublicConfigKey)}]=${safeJsonStringify(config)};`;
65
+ }
66
+ export { bakedConfigEnvKey, bakedPublicConfig, publicConfigKeys, publicConfigKeysEnvKey, readRuntimePublicConfig, resolvePublicConfig, runtimePublicConfigKey, serializeRuntimePublicConfig };
67
+ //# sourceMappingURL=runtimeConfig.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["runtimePublicConfigKey","publicConfigKeysEnvKey","bakedConfigEnvKey","importMetaEnv","import","meta","env","processEnv","process","readBuildEnv","key","parseJson","raw","JSON","parse","stringifyValues","source","Object","entries","reduce","acc","value","String","publicConfigKeys","parsed","Array","isArray","filter","length","bakedPublicConfig","resolvePublicConfig","baked","readRuntimePublicConfig","globalThis","safeJsonStringify","stringify","replace","serializeRuntimePublicConfig","config"],"sources":["../../../src/config/runtimeConfig.ts"],"sourcesContent":[null],"mappings":"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","ignoreList":[]}
@@ -17,6 +17,7 @@ const {
17
17
  isExpo,
18
18
  isFirefox,
19
19
  isFirefoxExtension,
20
+ isGnome,
20
21
  isIframe,
21
22
  isIos,
22
23
  isNative,
@@ -31,5 +32,5 @@ const {
31
32
  isWebTouchable,
32
33
  isWindowDefined
33
34
  } = platform;
34
- export { isAndroid, isBrowser, isChrome, isChromeExtension, isClient, isDesktop, isExpo, isFirefox, isFirefoxExtension, isIframe, isIos, isNative, isNext, isServer, isStorybook, isTauri, isTouchable, isWeb, isWebExtension, isWebTouchable, isWindowDefined };
35
+ export { isAndroid, isBrowser, isChrome, isChromeExtension, isClient, isDesktop, isExpo, isFirefox, isFirefoxExtension, isGnome, isIframe, isIos, isNative, isNext, isServer, isStorybook, isTauri, isTouchable, isWeb, isWebExtension, isWebTouchable, isWindowDefined };
35
36
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"names":["platform","isAndroid","isBrowser","isChrome","isChromeExtension","isClient","isExpo","isFirefox","isFirefoxExtension","isIframe","isIos","isNative","isNext","isServer","isStorybook","isTauri","isDesktop","isTouchable","isWeb","isWebExtension","isWebTouchable","isWindowDefined"],"sources":["../../src/index.ts"],"sourcesContent":[null],"mappings":"AAAA,SAASA,QAAA,QAAgB;AA0BzB,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AAhCP,MAAM;EACXC,SAAA;EACAC,SAAA;EACAC,QAAA;EACAC,iBAAA;EACAC,QAAA;EACAC,MAAA;EACAC,SAAA;EACAC,kBAAA;EACAC,QAAA;EACAC,KAAA;EACAC,QAAA;EACAC,MAAA;EACAC,QAAA;EACAC,WAAA;EACAC,OAAA;EACAC,SAAA;EACAC,WAAA;EACAC,KAAA;EACAC,cAAA;EACAC,cAAA;EACAC;AACF,IAAIrB,QAAA","ignoreList":[]}
1
+ {"version":3,"names":["platform","isAndroid","isBrowser","isChrome","isChromeExtension","isClient","isExpo","isFirefox","isFirefoxExtension","isGnome","isIframe","isIos","isNative","isNext","isServer","isStorybook","isTauri","isDesktop","isTouchable","isWeb","isWebExtension","isWebTouchable","isWindowDefined"],"sources":["../../src/index.ts"],"sourcesContent":[null],"mappings":"AAAA,SAASA,QAAA,QAAgB;AA2BzB,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AAjCP,MAAM;EACXC,SAAA;EACAC,SAAA;EACAC,QAAA;EACAC,iBAAA;EACAC,QAAA;EACAC,MAAA;EACAC,SAAA;EACAC,kBAAA;EACAC,OAAA;EACAC,QAAA;EACAC,KAAA;EACAC,QAAA;EACAC,MAAA;EACAC,QAAA;EACAC,WAAA;EACAC,OAAA;EACAC,SAAA;EACAC,WAAA;EACAC,KAAA;EACAC,cAAA;EACAC,cAAA;EACAC;AACF,IAAItB,QAAA","ignoreList":[]}
@@ -0,0 +1,34 @@
1
+ import { getBroadName, getPreciseName, platformBase } from "./platformBase.mjs";
2
+ const platform = {
3
+ ...platformBase,
4
+ isGnome: true,
5
+ // GTK is a desktop, and it is not a browser — so `isNative` too, which is
6
+ // exactly why Gnome sits ahead of Native in the precision order.
7
+ isDesktop: true,
8
+ isNative: true,
9
+ isClient: true,
10
+ isServer: false,
11
+ isWeb: false,
12
+ isBrowser: false,
13
+ isChrome: false,
14
+ isFirefox: false,
15
+ isIframe: false,
16
+ isStorybook: false,
17
+ isWebExtension: false,
18
+ isChromeExtension: false,
19
+ isFirefoxExtension: false,
20
+ isExpo: false,
21
+ isNext: false,
22
+ // A GTK pointer desktop. Touch exists on some hardware but is not the
23
+ // interaction model the layout should assume.
24
+ isTouchable: false,
25
+ isWebTouchable: false,
26
+ // There is a `window` under the react-gnome polyfills, but it is a stub
27
+ // with no layout, no events and no document. Callers branching on this are
28
+ // asking "can I touch the DOM", and the answer is no.
29
+ isWindowDefined: false
30
+ };
31
+ platform.preciseName = getPreciseName(platform);
32
+ platform.broadName = getBroadName(platform);
33
+ export { platform };
34
+ //# sourceMappingURL=index.gnome.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["getBroadName","getPreciseName","platformBase","platform","isGnome","isDesktop","isNative","isClient","isServer","isWeb","isBrowser","isChrome","isFirefox","isIframe","isStorybook","isWebExtension","isChromeExtension","isFirefoxExtension","isExpo","isNext","isTouchable","isWebTouchable","isWindowDefined","preciseName","broadName"],"sources":["../../../src/platform/index.gnome.ts"],"sourcesContent":[null],"mappings":"AAeA,SAAwBA,YAAA,EAAcC,cAAA,EAAgBC,YAAA,QAAoB;AAEnE,MAAMC,QAAA,GAAqB;EAChC,GAAGD,YAAA;EACHE,OAAA,EAAS;EAAA;EAAA;EAGTC,SAAA,EAAW;EACXC,QAAA,EAAU;EACVC,QAAA,EAAU;EACVC,QAAA,EAAU;EACVC,KAAA,EAAO;EACPC,SAAA,EAAW;EACXC,QAAA,EAAU;EACVC,SAAA,EAAW;EACXC,QAAA,EAAU;EACVC,WAAA,EAAa;EACbC,cAAA,EAAgB;EAChBC,iBAAA,EAAmB;EACnBC,kBAAA,EAAoB;EACpBC,MAAA,EAAQ;EACRC,MAAA,EAAQ;EAAA;EAAA;EAGRC,WAAA,EAAa;EACbC,cAAA,EAAgB;EAAA;EAAA;EAAA;EAIhBC,eAAA,EAAiB;AACnB;AACAnB,QAAA,CAASoB,WAAA,GAActB,cAAA,CAAeE,QAAQ;AAC9CA,QAAA,CAASqB,SAAA,GAAYxB,YAAA,CAAaG,QAAQ","ignoreList":[]}
@@ -1,5 +1,11 @@
1
1
  import { isChrome, isClient, isServer, isTouchable, isWeb, isWebTouchable, isWindowDefined } from "@tamagui/constants";
2
- const platformOrder = ["Ios", "Android", "Native", "Tauri", "Desktop", "ChromeExtension", "FirefoxExtension", "WebExtension", "Next", "Expo", "Chrome", "Firefox", "Web", "Browser", "Client", "Server", "Iframe", "Storybook"];
2
+ const platformOrder = ["Ios", "Android",
3
+ // Gnome outranks Native: the GTK target reports isNative (it is not a
4
+ // browser) but "gnome" is the precise answer callers want.
5
+ "Gnome", "Native",
6
+ // Tauri outranks Desktop/Web the same way: the webview host reports isWeb
7
+ // and isDesktop, but "tauri" is the precise answer.
8
+ "Tauri", "Desktop", "ChromeExtension", "FirefoxExtension", "WebExtension", "Next", "Expo", "Chrome", "Firefox", "Web", "Browser", "Client", "Server", "Iframe", "Storybook"];
3
9
  const platformBase = {
4
10
  isAndroid: false,
5
11
  isBrowser: false,
@@ -10,6 +16,7 @@ const platformBase = {
10
16
  isExpo: false,
11
17
  isFirefox: false,
12
18
  isFirefoxExtension: false,
19
+ isGnome: false,
13
20
  isIframe: false,
14
21
  isIos: false,
15
22
  isNative: false,
@@ -1 +1 @@
1
- {"version":3,"names":["isChrome","isClient","isServer","isTouchable","isWeb","isWebTouchable","isWindowDefined","platformOrder","platformBase","isAndroid","isBrowser","isChromeExtension","isDesktop","isExpo","isFirefox","isFirefoxExtension","isIframe","isIos","isNative","isNext","isStorybook","window","__STORYBOOK_ADDONS_PREVIEW","isTauri","isWebExtension","preciseName","broadName","getPreciseName","platform","flags","name","toLowerCase","slice","getBroadName","reverse"],"sources":["../../../src/platform/platformBase.ts"],"sourcesContent":[null],"mappings":"AAAA,SACEA,QAAA,EACAC,QAAA,EACAC,QAAA,EACAC,WAAA,EACAC,KAAA,EACAC,cAAA,EACAC,eAAA,QACK;AAQP,MAAMC,aAAA,GAAgB,CACpB,OACA,WACA,UACA,SACA,WACA,mBACA,oBACA,gBACA,QACA,QACA,UACA,WACA,OACA,WACA,UACA,UACA,UACA,YACF;AAuBO,MAAMC,YAAA,GAAe;EAC1BC,SAAA,EAAW;EACXC,SAAA,EAAW;EACXV,QAAA;EACAW,iBAAA,EAAmB;EACnBV,QAAA;EACAW,SAAA,EAAW;EACXC,MAAA,EAAQ;EACRC,SAAA,EAAW;EACXC,kBAAA,EAAoB;EACpBC,QAAA,EAAU;EACVC,KAAA,EAAO;EACPC,QAAA,EAAU;EACVC,MAAA,EAAQ;EACRjB,QAAA;EACAkB,WAAA,EAAad,eAAA,IAAmB,OAAOe,MAAA,CAAOC,0BAAA,KAA+B;EAC7EC,OAAA,EAAS;EACTpB,WAAA;EACAC,KAAA;EACAoB,cAAA,EAAgB;EAChBnB,cAAA;EACAC,eAAA;EACAmB,WAAA,EAAa;EACbC,SAAA,EAAW;AACb;AAEO,SAASC,eAAeC,QAAA,EAAyC;EACtE,MAAMC,KAAA,GAAQD,QAAA;EACd,WAAWE,IAAA,IAAQvB,aAAA,EAAe;IAChC,IAAIsB,KAAA,CAAM,KAAKC,IAAI,EAAE,GAAG;MACtB,OAAO,GAAGA,IAAA,CAAK,CAAC,EAAEC,WAAA,CAAY,CAAC,GAAGD,IAAA,CAAKE,KAAA,CAAM,CAAC,CAAC;IACjD;EACF;EACA,OAAO;AACT;AAEO,SAASC,aAAaL,QAAA,EAAuC;EAClE,MAAMC,KAAA,GAAQD,QAAA;EACd,WAAWE,IAAA,IAAQvB,aAAA,CAAcyB,KAAA,CAAM,EAAEE,OAAA,CAAQ,GAAG;IAClD,IAAIL,KAAA,CAAM,KAAKC,IAAI,EAAE,GAAG;MACtB,OAAO,GAAGA,IAAA,CAAK,CAAC,EAAEC,WAAA,CAAY,CAAC,GAAGD,IAAA,CAAKE,KAAA,CAAM,CAAC,CAAC;IACjD;EACF;EACA,OAAO;AACT","ignoreList":[]}
1
+ {"version":3,"names":["isChrome","isClient","isServer","isTouchable","isWeb","isWebTouchable","isWindowDefined","platformOrder","platformBase","isAndroid","isBrowser","isChromeExtension","isDesktop","isExpo","isFirefox","isFirefoxExtension","isGnome","isIframe","isIos","isNative","isNext","isStorybook","window","__STORYBOOK_ADDONS_PREVIEW","isTauri","isWebExtension","preciseName","broadName","getPreciseName","platform","flags","name","toLowerCase","slice","getBroadName","reverse"],"sources":["../../../src/platform/platformBase.ts"],"sourcesContent":[null],"mappings":"AAAA,SACEA,QAAA,EACAC,QAAA,EACAC,QAAA,EACAC,WAAA,EACAC,KAAA,EACAC,cAAA,EACAC,eAAA,QACK;AAQP,MAAMC,aAAA,GAAgB,CACpB,OACA;AAAA;AAAA;AAGA,SACA;AAAA;AAAA;AAGA,SACA,WACA,mBACA,oBACA,gBACA,QACA,QACA,UACA,WACA,OACA,WACA,UACA,UACA,UACA,YACF;AAwBO,MAAMC,YAAA,GAAe;EAC1BC,SAAA,EAAW;EACXC,SAAA,EAAW;EACXV,QAAA;EACAW,iBAAA,EAAmB;EACnBV,QAAA;EACAW,SAAA,EAAW;EACXC,MAAA,EAAQ;EACRC,SAAA,EAAW;EACXC,kBAAA,EAAoB;EACpBC,OAAA,EAAS;EACTC,QAAA,EAAU;EACVC,KAAA,EAAO;EACPC,QAAA,EAAU;EACVC,MAAA,EAAQ;EACRlB,QAAA;EACAmB,WAAA,EAAaf,eAAA,IAAmB,OAAOgB,MAAA,CAAOC,0BAAA,KAA+B;EAC7EC,OAAA,EAAS;EACTrB,WAAA;EACAC,KAAA;EACAqB,cAAA,EAAgB;EAChBpB,cAAA;EACAC,eAAA;EACAoB,WAAA,EAAa;EACbC,SAAA,EAAW;AACb;AAEO,SAASC,eAAeC,QAAA,EAAyC;EACtE,MAAMC,KAAA,GAAQD,QAAA;EACd,WAAWE,IAAA,IAAQxB,aAAA,EAAe;IAChC,IAAIuB,KAAA,CAAM,KAAKC,IAAI,EAAE,GAAG;MACtB,OAAO,GAAGA,IAAA,CAAK,CAAC,EAAEC,WAAA,CAAY,CAAC,GAAGD,IAAA,CAAKE,KAAA,CAAM,CAAC,CAAC;IACjD;EACF;EACA,OAAO;AACT;AAEO,SAASC,aAAaL,QAAA,EAAuC;EAClE,MAAMC,KAAA,GAAQD,QAAA;EACd,WAAWE,IAAA,IAAQxB,aAAA,CAAc0B,KAAA,CAAM,EAAEE,OAAA,CAAQ,GAAG;IAClD,IAAIL,KAAA,CAAM,KAAKC,IAAI,EAAE,GAAG;MACtB,OAAO,GAAGA,IAAA,CAAK,CAAC,EAAEC,WAAA,CAAY,CAAC,GAAGD,IAAA,CAAKE,KAAA,CAAM,CAAC,CAAC;IACjD;EACF;EACA,OAAO;AACT","ignoreList":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@multiplatform.one/platform",
3
- "version": "6.7.0",
3
+ "version": "7.1.0",
4
4
  "description": "Platform detection flags and utilities for multiplatform.one",
5
5
  "keywords": [
6
6
  "detection",
@@ -44,16 +44,19 @@
44
44
  "access": "public"
45
45
  },
46
46
  "dependencies": {
47
- "@tamagui/constants": "2.0.0-rc.41"
47
+ "@tamagui/constants": "2.7.6"
48
48
  },
49
49
  "devDependencies": {
50
- "@tamagui/build": "2.0.0-rc.41",
50
+ "@tamagui/build": "2.7.6",
51
51
  "@types/chrome": "^0.1.40",
52
52
  "@types/firefox-webext-browser": "^143.0.0",
53
53
  "@types/react": "~19.2.14",
54
+ "@vitest/coverage-v8": "^4.1.5",
55
+ "happy-dom": "^20.9.0",
54
56
  "react": "19.2.5",
55
57
  "typescript": "~5.9.3",
56
- "@multiplatform.one/config": "6.7.0"
58
+ "vitest": "^4.1.5",
59
+ "@multiplatform.one/config": "7.1.0"
57
60
  },
58
61
  "peerDependencies": {
59
62
  "expo-constants": "~55.0.15",
@@ -69,6 +72,7 @@
69
72
  },
70
73
  "scripts": {
71
74
  "build": "rm -rf dist types 2>/dev/null && tamagui-build --ts-project ./tsconfig.build.json --exclude '\\.spec\\.|\\.test\\.|\\.stories\\.' && find dist -name '*.native.js' -delete && find dist -name '*.native.js.map' -delete",
75
+ "test": "vitest run --coverage --coverage.provider=v8 --coverage.reporter=text --coverage.reporter=lcov --coverage.reporter=html",
72
76
  "typecheck": "tsgo --noEmit"
73
77
  }
74
78
  }
@@ -1,9 +1,23 @@
1
- import { beforeEach, describe, expect, it, vi } from "vitest";
1
+ import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
2
2
  import { Config } from "./config";
3
+ import { bakedConfigEnvKey, runtimePublicConfigKey } from "./runtimeConfig";
4
+
5
+ function setRuntimePayload(payload: Record<string, string>) {
6
+ (globalThis as unknown as Record<string, unknown>)[runtimePublicConfigKey] = payload;
7
+ }
8
+
9
+ function clearRuntimePayload() {
10
+ delete (globalThis as unknown as Record<string, unknown>)[runtimePublicConfigKey];
11
+ }
3
12
 
4
13
  describe("Config", () => {
5
14
  beforeEach(() => {
6
15
  vi.unstubAllEnvs();
16
+ clearRuntimePayload();
17
+ });
18
+
19
+ afterEach(() => {
20
+ clearRuntimePayload();
7
21
  });
8
22
 
9
23
  describe("constructor", () => {
@@ -130,4 +144,51 @@ describe("Config", () => {
130
144
  expect(c.get("ADDED_KEY")).toBe("env-wins");
131
145
  });
132
146
  });
147
+
148
+ describe("runtime public config published by the SSR document", () => {
149
+ it("resolves MARKETPLACE_API_URL from the runtime payload with no build-time VITE_MP_CONFIG", () => {
150
+ // The exact production shape: an image built by CI with an EMPTY build
151
+ // environment (no VITE_MP_CONFIG baked), configured per deployment by
152
+ // the container env, which the SSR document publishes to the browser.
153
+ setRuntimePayload({ MARKETPLACE_API_URL: "https://api.marketplace.example.org" });
154
+ const c = new Config();
155
+ expect(c.get("MARKETPLACE_API_URL")).toBe("https://api.marketplace.example.org");
156
+ });
157
+
158
+ it("resolves FRAPPE_ENABLED from the runtime payload so the frappe provider can mount", () => {
159
+ // CreateApp.tsx gates FrappeProvider on config.get("FRAPPE_ENABLED") === "1".
160
+ setRuntimePayload({ FRAPPE_ENABLED: "1" });
161
+ const c = new Config();
162
+ expect(c.get("FRAPPE_ENABLED")).toBe("1");
163
+ });
164
+
165
+ // These use MARKETPLACE_API_URL rather than BASE_URL on purpose: vite (and
166
+ // therefore vitest) publishes its own BASE_URL="/" into process.env, and
167
+ // _lookupEnv still outranks everything on the SERVER — so a BASE_URL
168
+ // fixture would measure vite's value, not the precedence under test.
169
+ it("prefers the runtime payload over a stale build-time baked value", () => {
170
+ vi.stubEnv(
171
+ bakedConfigEnvKey,
172
+ JSON.stringify({ MARKETPLACE_API_URL: "https://stale.example.org" }),
173
+ );
174
+ setRuntimePayload({ MARKETPLACE_API_URL: "https://fresh.example.org" });
175
+ const c = new Config();
176
+ expect(c.get("MARKETPLACE_API_URL")).toBe("https://fresh.example.org");
177
+ });
178
+
179
+ it("still resolves the build-time baked value when no runtime payload exists", () => {
180
+ vi.stubEnv(
181
+ bakedConfigEnvKey,
182
+ JSON.stringify({ MARKETPLACE_API_URL: "https://baked.example.org" }),
183
+ );
184
+ const c = new Config();
185
+ expect(c.get("MARKETPLACE_API_URL")).toBe("https://baked.example.org");
186
+ });
187
+
188
+ it("lets explicit constructor values win over the runtime payload", () => {
189
+ setRuntimePayload({ MARKETPLACE_API_URL: "https://runtime.example.org" });
190
+ const c = new Config({ MARKETPLACE_API_URL: "https://explicit.example.org" });
191
+ expect(c.get("MARKETPLACE_API_URL")).toBe("https://explicit.example.org");
192
+ });
193
+ });
133
194
  });