@oxyhq/services 9.0.0 → 10.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/commonjs/ui/components/OxyProvider.js +2 -2
- package/lib/commonjs/ui/components/OxyProvider.js.map +1 -1
- package/lib/commonjs/ui/components/SignInModal.js +14 -3
- package/lib/commonjs/ui/components/SignInModal.js.map +1 -1
- package/lib/commonjs/ui/context/OxyContext.js +30 -18
- package/lib/commonjs/ui/context/OxyContext.js.map +1 -1
- package/lib/commonjs/ui/hooks/useWebSSO.js +7 -8
- package/lib/commonjs/ui/hooks/useWebSSO.js.map +1 -1
- package/lib/commonjs/ui/screens/OxyAuthScreen.js +14 -3
- package/lib/commonjs/ui/screens/OxyAuthScreen.js.map +1 -1
- package/lib/commonjs/utils/silentGuardKey.js +54 -0
- package/lib/commonjs/utils/silentGuardKey.js.map +1 -0
- package/lib/module/ui/components/OxyProvider.js +2 -2
- package/lib/module/ui/components/OxyProvider.js.map +1 -1
- package/lib/module/ui/components/SignInModal.js +14 -3
- package/lib/module/ui/components/SignInModal.js.map +1 -1
- package/lib/module/ui/context/OxyContext.js +30 -18
- package/lib/module/ui/context/OxyContext.js.map +1 -1
- package/lib/module/ui/hooks/useWebSSO.js +7 -8
- package/lib/module/ui/hooks/useWebSSO.js.map +1 -1
- package/lib/module/ui/screens/OxyAuthScreen.js +14 -3
- package/lib/module/ui/screens/OxyAuthScreen.js.map +1 -1
- package/lib/module/utils/silentGuardKey.js +49 -0
- package/lib/module/utils/silentGuardKey.js.map +1 -0
- package/lib/typescript/commonjs/ui/components/SignInModal.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/context/OxyContext.d.ts +12 -8
- package/lib/typescript/commonjs/ui/context/OxyContext.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/hooks/mutations/useAccountMutations.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/hooks/useWebSSO.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/screens/OxyAuthScreen.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/types/navigation.d.ts +8 -6
- package/lib/typescript/commonjs/ui/types/navigation.d.ts.map +1 -1
- package/lib/typescript/commonjs/utils/silentGuardKey.d.ts +31 -0
- package/lib/typescript/commonjs/utils/silentGuardKey.d.ts.map +1 -0
- package/lib/typescript/module/ui/components/SignInModal.d.ts.map +1 -1
- package/lib/typescript/module/ui/context/OxyContext.d.ts +12 -8
- package/lib/typescript/module/ui/context/OxyContext.d.ts.map +1 -1
- package/lib/typescript/module/ui/hooks/mutations/useAccountMutations.d.ts.map +1 -1
- package/lib/typescript/module/ui/hooks/useWebSSO.d.ts.map +1 -1
- package/lib/typescript/module/ui/screens/OxyAuthScreen.d.ts.map +1 -1
- package/lib/typescript/module/ui/types/navigation.d.ts +8 -6
- package/lib/typescript/module/ui/types/navigation.d.ts.map +1 -1
- package/lib/typescript/module/utils/silentGuardKey.d.ts +31 -0
- package/lib/typescript/module/utils/silentGuardKey.d.ts.map +1 -0
- package/package.json +2 -2
- package/src/ui/components/OxyProvider.tsx +2 -2
- package/src/ui/components/SignInModal.tsx +14 -3
- package/src/ui/context/OxyContext.tsx +42 -29
- package/src/ui/hooks/useWebSSO.ts +7 -8
- package/src/ui/screens/OxyAuthScreen.tsx +14 -3
- package/src/ui/types/navigation.ts +8 -6
- package/src/utils/__tests__/silentGuardKey.test.ts +82 -0
- package/src/utils/silentGuardKey.ts +46 -0
- package/lib/commonjs/ui/utils/appName.js +0 -62
- package/lib/commonjs/ui/utils/appName.js.map +0 -1
- package/lib/module/ui/utils/appName.js +0 -59
- package/lib/module/ui/utils/appName.js.map +0 -1
- package/lib/typescript/commonjs/ui/utils/appName.d.ts +0 -22
- package/lib/typescript/commonjs/ui/utils/appName.d.ts.map +0 -1
- package/lib/typescript/module/ui/utils/appName.d.ts +0 -22
- package/lib/typescript/module/ui/utils/appName.d.ts.map +0 -1
- package/src/ui/utils/__tests__/appName.test.ts +0 -52
- package/src/ui/utils/appName.ts +0 -62
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared, pure helpers for building the `origin|baseURL` signature used as the
|
|
3
|
+
* module-level run-once guard key for cold-boot silent-SSO probes
|
|
4
|
+
* (`silentColdBootKey` in `OxyContext`, `ssoSignature` in `useWebSSO`).
|
|
5
|
+
*
|
|
6
|
+
* NATIVE SAFETY (the bug this fixes): React Native aliases a global `window`
|
|
7
|
+
* (it points at the JS global object), so `typeof window !== 'undefined'` is
|
|
8
|
+
* `true` on native — but `window.location` is `undefined`. Reading
|
|
9
|
+
* `window.location.origin` after only a `typeof window` check therefore throws
|
|
10
|
+
* `TypeError: Cannot read property 'origin' of undefined` on native. Because
|
|
11
|
+
* the key is built UNCONDITIONALLY at the top of the cold-boot path (before its
|
|
12
|
+
* try/catch), that throw escaped session restore entirely and broke
|
|
13
|
+
* cross-session restore on native. Both prior copies of the guard had the same
|
|
14
|
+
* insufficient `typeof window` check and were prone to drift, so the read is
|
|
15
|
+
* consolidated here behind a guard that also verifies `window.location`.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Read `window.location.origin` safely on every platform.
|
|
20
|
+
*
|
|
21
|
+
* Returns the browser origin on web, and the sentinel `'no-origin'` anywhere
|
|
22
|
+
* `window.location` is absent (React Native, SSR/Node). Never throws.
|
|
23
|
+
*/
|
|
24
|
+
export function safeWindowOrigin(): string {
|
|
25
|
+
if (typeof window !== 'undefined' && typeof window.location !== 'undefined') {
|
|
26
|
+
return window.location.origin;
|
|
27
|
+
}
|
|
28
|
+
return 'no-origin';
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Build the stable `origin|baseURL` signature for the silent-SSO run-once
|
|
33
|
+
* guard. Two providers pointed at the same API from the same origin share one
|
|
34
|
+
* attempt. `getBaseURL` is invoked defensively (it may be absent or throw on a
|
|
35
|
+
* partially-initialised client); any failure degrades to an empty baseURL.
|
|
36
|
+
*/
|
|
37
|
+
export function buildSilentGuardKey(getBaseURL?: () => string | undefined): string {
|
|
38
|
+
const origin = safeWindowOrigin();
|
|
39
|
+
let baseURL = '';
|
|
40
|
+
try {
|
|
41
|
+
baseURL = getBaseURL?.() ?? '';
|
|
42
|
+
} catch {
|
|
43
|
+
baseURL = '';
|
|
44
|
+
}
|
|
45
|
+
return `${origin}|${baseURL}`;
|
|
46
|
+
}
|
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
Object.defineProperty(exports, "__esModule", {
|
|
4
|
-
value: true
|
|
5
|
-
});
|
|
6
|
-
exports.resolveAppDisplayName = resolveAppDisplayName;
|
|
7
|
-
var _reactNative = require("react-native");
|
|
8
|
-
/**
|
|
9
|
-
* The `storageKeyPrefix` default applied by `OxyContextProvider`. When the
|
|
10
|
-
* consumer never overrides it, the prefix carries no app-identity signal and
|
|
11
|
-
* must NOT be used to derive a display name (it would surface "Oxy_session").
|
|
12
|
-
*/
|
|
13
|
-
const DEFAULT_STORAGE_KEY_PREFIX = 'oxy_session';
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* Capitalize the first character of a non-empty string. Used to turn a lower
|
|
17
|
-
* case `storageKeyPrefix` (e.g. `"mention"`) into a presentable label
|
|
18
|
-
* (`"Mention"`). Pure; leaves the remainder untouched so multi-word or already
|
|
19
|
-
* capitalized values are preserved.
|
|
20
|
-
*/
|
|
21
|
-
function capitalizeFirst(value) {
|
|
22
|
-
return value.charAt(0).toUpperCase() + value.slice(1);
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* Resolve a human-readable application display name for the consent / sign-in
|
|
27
|
-
* UI shown by the central Oxy auth experience (e.g. "Mention wants to access
|
|
28
|
-
* your Oxy account"). This is sent as the `appId` field on
|
|
29
|
-
* `POST /auth/session/create` and rendered verbatim by the auth consent page.
|
|
30
|
-
*
|
|
31
|
-
* Resolution order (first non-empty wins):
|
|
32
|
-
* 1. An explicit `appName` declared by the consumer on `OxyProvider`.
|
|
33
|
-
* 2. The capitalized `storageKeyPrefix` — but only when the consumer actually
|
|
34
|
-
* overrode the default. Apps already pass a brand-shaped prefix
|
|
35
|
-
* (`"mention"`, `"homiio"`, …) so this gives most apps a correct name with
|
|
36
|
-
* zero extra config.
|
|
37
|
-
* 3. On web only, a meaningful `document.title` (trimmed). This rescues
|
|
38
|
-
* zero-config web apps that set a page title but no prefix.
|
|
39
|
-
* 4. `Platform.OS` as the terminal fallback. On web this yields the historical
|
|
40
|
-
* `"web"` value — now reached ONLY when an app supplies neither an explicit
|
|
41
|
-
* name, a custom prefix, nor a document title.
|
|
42
|
-
*
|
|
43
|
-
* The result is never empty.
|
|
44
|
-
*/
|
|
45
|
-
function resolveAppDisplayName(appName, storageKeyPrefix) {
|
|
46
|
-
const explicit = appName?.trim();
|
|
47
|
-
if (explicit) {
|
|
48
|
-
return explicit;
|
|
49
|
-
}
|
|
50
|
-
const prefix = storageKeyPrefix?.trim();
|
|
51
|
-
if (prefix && prefix !== DEFAULT_STORAGE_KEY_PREFIX) {
|
|
52
|
-
return capitalizeFirst(prefix);
|
|
53
|
-
}
|
|
54
|
-
if (_reactNative.Platform.OS === 'web' && typeof document !== 'undefined') {
|
|
55
|
-
const title = document.title?.trim();
|
|
56
|
-
if (title) {
|
|
57
|
-
return title;
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
return _reactNative.Platform.OS;
|
|
61
|
-
}
|
|
62
|
-
//# sourceMappingURL=appName.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"names":["_reactNative","require","DEFAULT_STORAGE_KEY_PREFIX","capitalizeFirst","value","charAt","toUpperCase","slice","resolveAppDisplayName","appName","storageKeyPrefix","explicit","trim","prefix","Platform","OS","document","title"],"sourceRoot":"../../../../src","sources":["ui/utils/appName.ts"],"mappings":";;;;;;AAAA,IAAAA,YAAA,GAAAC,OAAA;AAEA;AACA;AACA;AACA;AACA;AACA,MAAMC,0BAA0B,GAAG,aAAa;;AAEhD;AACA;AACA;AACA;AACA;AACA;AACA,SAASC,eAAeA,CAACC,KAAa,EAAU;EAC9C,OAAOA,KAAK,CAACC,MAAM,CAAC,CAAC,CAAC,CAACC,WAAW,CAAC,CAAC,GAAGF,KAAK,CAACG,KAAK,CAAC,CAAC,CAAC;AACvD;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,SAASC,qBAAqBA,CACnCC,OAA2B,EAC3BC,gBAAoC,EAC5B;EACR,MAAMC,QAAQ,GAAGF,OAAO,EAAEG,IAAI,CAAC,CAAC;EAChC,IAAID,QAAQ,EAAE;IACZ,OAAOA,QAAQ;EACjB;EAEA,MAAME,MAAM,GAAGH,gBAAgB,EAAEE,IAAI,CAAC,CAAC;EACvC,IAAIC,MAAM,IAAIA,MAAM,KAAKX,0BAA0B,EAAE;IACnD,OAAOC,eAAe,CAACU,MAAM,CAAC;EAChC;EAEA,IAAIC,qBAAQ,CAACC,EAAE,KAAK,KAAK,IAAI,OAAOC,QAAQ,KAAK,WAAW,EAAE;IAC5D,MAAMC,KAAK,GAAGD,QAAQ,CAACC,KAAK,EAAEL,IAAI,CAAC,CAAC;IACpC,IAAIK,KAAK,EAAE;MACT,OAAOA,KAAK;IACd;EACF;EAEA,OAAOH,qBAAQ,CAACC,EAAE;AACpB","ignoreList":[]}
|
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
import { Platform } from 'react-native';
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* The `storageKeyPrefix` default applied by `OxyContextProvider`. When the
|
|
7
|
-
* consumer never overrides it, the prefix carries no app-identity signal and
|
|
8
|
-
* must NOT be used to derive a display name (it would surface "Oxy_session").
|
|
9
|
-
*/
|
|
10
|
-
const DEFAULT_STORAGE_KEY_PREFIX = 'oxy_session';
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* Capitalize the first character of a non-empty string. Used to turn a lower
|
|
14
|
-
* case `storageKeyPrefix` (e.g. `"mention"`) into a presentable label
|
|
15
|
-
* (`"Mention"`). Pure; leaves the remainder untouched so multi-word or already
|
|
16
|
-
* capitalized values are preserved.
|
|
17
|
-
*/
|
|
18
|
-
function capitalizeFirst(value) {
|
|
19
|
-
return value.charAt(0).toUpperCase() + value.slice(1);
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* Resolve a human-readable application display name for the consent / sign-in
|
|
24
|
-
* UI shown by the central Oxy auth experience (e.g. "Mention wants to access
|
|
25
|
-
* your Oxy account"). This is sent as the `appId` field on
|
|
26
|
-
* `POST /auth/session/create` and rendered verbatim by the auth consent page.
|
|
27
|
-
*
|
|
28
|
-
* Resolution order (first non-empty wins):
|
|
29
|
-
* 1. An explicit `appName` declared by the consumer on `OxyProvider`.
|
|
30
|
-
* 2. The capitalized `storageKeyPrefix` — but only when the consumer actually
|
|
31
|
-
* overrode the default. Apps already pass a brand-shaped prefix
|
|
32
|
-
* (`"mention"`, `"homiio"`, …) so this gives most apps a correct name with
|
|
33
|
-
* zero extra config.
|
|
34
|
-
* 3. On web only, a meaningful `document.title` (trimmed). This rescues
|
|
35
|
-
* zero-config web apps that set a page title but no prefix.
|
|
36
|
-
* 4. `Platform.OS` as the terminal fallback. On web this yields the historical
|
|
37
|
-
* `"web"` value — now reached ONLY when an app supplies neither an explicit
|
|
38
|
-
* name, a custom prefix, nor a document title.
|
|
39
|
-
*
|
|
40
|
-
* The result is never empty.
|
|
41
|
-
*/
|
|
42
|
-
export function resolveAppDisplayName(appName, storageKeyPrefix) {
|
|
43
|
-
const explicit = appName?.trim();
|
|
44
|
-
if (explicit) {
|
|
45
|
-
return explicit;
|
|
46
|
-
}
|
|
47
|
-
const prefix = storageKeyPrefix?.trim();
|
|
48
|
-
if (prefix && prefix !== DEFAULT_STORAGE_KEY_PREFIX) {
|
|
49
|
-
return capitalizeFirst(prefix);
|
|
50
|
-
}
|
|
51
|
-
if (Platform.OS === 'web' && typeof document !== 'undefined') {
|
|
52
|
-
const title = document.title?.trim();
|
|
53
|
-
if (title) {
|
|
54
|
-
return title;
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
return Platform.OS;
|
|
58
|
-
}
|
|
59
|
-
//# sourceMappingURL=appName.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"names":["Platform","DEFAULT_STORAGE_KEY_PREFIX","capitalizeFirst","value","charAt","toUpperCase","slice","resolveAppDisplayName","appName","storageKeyPrefix","explicit","trim","prefix","OS","document","title"],"sourceRoot":"../../../../src","sources":["ui/utils/appName.ts"],"mappings":";;AAAA,SAASA,QAAQ,QAAQ,cAAc;;AAEvC;AACA;AACA;AACA;AACA;AACA,MAAMC,0BAA0B,GAAG,aAAa;;AAEhD;AACA;AACA;AACA;AACA;AACA;AACA,SAASC,eAAeA,CAACC,KAAa,EAAU;EAC9C,OAAOA,KAAK,CAACC,MAAM,CAAC,CAAC,CAAC,CAACC,WAAW,CAAC,CAAC,GAAGF,KAAK,CAACG,KAAK,CAAC,CAAC,CAAC;AACvD;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASC,qBAAqBA,CACnCC,OAA2B,EAC3BC,gBAAoC,EAC5B;EACR,MAAMC,QAAQ,GAAGF,OAAO,EAAEG,IAAI,CAAC,CAAC;EAChC,IAAID,QAAQ,EAAE;IACZ,OAAOA,QAAQ;EACjB;EAEA,MAAME,MAAM,GAAGH,gBAAgB,EAAEE,IAAI,CAAC,CAAC;EACvC,IAAIC,MAAM,IAAIA,MAAM,KAAKX,0BAA0B,EAAE;IACnD,OAAOC,eAAe,CAACU,MAAM,CAAC;EAChC;EAEA,IAAIZ,QAAQ,CAACa,EAAE,KAAK,KAAK,IAAI,OAAOC,QAAQ,KAAK,WAAW,EAAE;IAC5D,MAAMC,KAAK,GAAGD,QAAQ,CAACC,KAAK,EAAEJ,IAAI,CAAC,CAAC;IACpC,IAAII,KAAK,EAAE;MACT,OAAOA,KAAK;IACd;EACF;EAEA,OAAOf,QAAQ,CAACa,EAAE;AACpB","ignoreList":[]}
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Resolve a human-readable application display name for the consent / sign-in
|
|
3
|
-
* UI shown by the central Oxy auth experience (e.g. "Mention wants to access
|
|
4
|
-
* your Oxy account"). This is sent as the `appId` field on
|
|
5
|
-
* `POST /auth/session/create` and rendered verbatim by the auth consent page.
|
|
6
|
-
*
|
|
7
|
-
* Resolution order (first non-empty wins):
|
|
8
|
-
* 1. An explicit `appName` declared by the consumer on `OxyProvider`.
|
|
9
|
-
* 2. The capitalized `storageKeyPrefix` — but only when the consumer actually
|
|
10
|
-
* overrode the default. Apps already pass a brand-shaped prefix
|
|
11
|
-
* (`"mention"`, `"homiio"`, …) so this gives most apps a correct name with
|
|
12
|
-
* zero extra config.
|
|
13
|
-
* 3. On web only, a meaningful `document.title` (trimmed). This rescues
|
|
14
|
-
* zero-config web apps that set a page title but no prefix.
|
|
15
|
-
* 4. `Platform.OS` as the terminal fallback. On web this yields the historical
|
|
16
|
-
* `"web"` value — now reached ONLY when an app supplies neither an explicit
|
|
17
|
-
* name, a custom prefix, nor a document title.
|
|
18
|
-
*
|
|
19
|
-
* The result is never empty.
|
|
20
|
-
*/
|
|
21
|
-
export declare function resolveAppDisplayName(appName: string | undefined, storageKeyPrefix: string | undefined): string;
|
|
22
|
-
//# sourceMappingURL=appName.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"appName.d.ts","sourceRoot":"","sources":["../../../../../src/ui/utils/appName.ts"],"names":[],"mappings":"AAmBA;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,MAAM,GAAG,SAAS,EAC3B,gBAAgB,EAAE,MAAM,GAAG,SAAS,GACnC,MAAM,CAmBR"}
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Resolve a human-readable application display name for the consent / sign-in
|
|
3
|
-
* UI shown by the central Oxy auth experience (e.g. "Mention wants to access
|
|
4
|
-
* your Oxy account"). This is sent as the `appId` field on
|
|
5
|
-
* `POST /auth/session/create` and rendered verbatim by the auth consent page.
|
|
6
|
-
*
|
|
7
|
-
* Resolution order (first non-empty wins):
|
|
8
|
-
* 1. An explicit `appName` declared by the consumer on `OxyProvider`.
|
|
9
|
-
* 2. The capitalized `storageKeyPrefix` — but only when the consumer actually
|
|
10
|
-
* overrode the default. Apps already pass a brand-shaped prefix
|
|
11
|
-
* (`"mention"`, `"homiio"`, …) so this gives most apps a correct name with
|
|
12
|
-
* zero extra config.
|
|
13
|
-
* 3. On web only, a meaningful `document.title` (trimmed). This rescues
|
|
14
|
-
* zero-config web apps that set a page title but no prefix.
|
|
15
|
-
* 4. `Platform.OS` as the terminal fallback. On web this yields the historical
|
|
16
|
-
* `"web"` value — now reached ONLY when an app supplies neither an explicit
|
|
17
|
-
* name, a custom prefix, nor a document title.
|
|
18
|
-
*
|
|
19
|
-
* The result is never empty.
|
|
20
|
-
*/
|
|
21
|
-
export declare function resolveAppDisplayName(appName: string | undefined, storageKeyPrefix: string | undefined): string;
|
|
22
|
-
//# sourceMappingURL=appName.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"appName.d.ts","sourceRoot":"","sources":["../../../../../src/ui/utils/appName.ts"],"names":[],"mappings":"AAmBA;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,MAAM,GAAG,SAAS,EAC3B,gBAAgB,EAAE,MAAM,GAAG,SAAS,GACnC,MAAM,CAmBR"}
|
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
import { resolveAppDisplayName } from '../appName';
|
|
2
|
-
|
|
3
|
-
// The shared react-native mock pins `Platform.OS` to 'web', which is exactly
|
|
4
|
-
// the platform on which the historical "web wants to access your Oxy account"
|
|
5
|
-
// regression occurred. These tests assert the resolution order that prevents it.
|
|
6
|
-
|
|
7
|
-
describe('resolveAppDisplayName', () => {
|
|
8
|
-
const originalTitle = typeof document !== 'undefined' ? document.title : '';
|
|
9
|
-
|
|
10
|
-
afterEach(() => {
|
|
11
|
-
if (typeof document !== 'undefined') {
|
|
12
|
-
document.title = originalTitle;
|
|
13
|
-
}
|
|
14
|
-
});
|
|
15
|
-
|
|
16
|
-
it('prefers an explicit appName, trimmed', () => {
|
|
17
|
-
expect(resolveAppDisplayName(' Mention ', 'oxy_session')).toBe('Mention');
|
|
18
|
-
});
|
|
19
|
-
|
|
20
|
-
it('explicit appName wins over a custom storageKeyPrefix', () => {
|
|
21
|
-
expect(resolveAppDisplayName('Mention', 'homiio')).toBe('Mention');
|
|
22
|
-
});
|
|
23
|
-
|
|
24
|
-
it('capitalizes a custom storageKeyPrefix when no appName is given', () => {
|
|
25
|
-
expect(resolveAppDisplayName(undefined, 'mention')).toBe('Mention');
|
|
26
|
-
});
|
|
27
|
-
|
|
28
|
-
it('ignores the default storageKeyPrefix (never surfaces "Oxy_session")', () => {
|
|
29
|
-
if (typeof document !== 'undefined') {
|
|
30
|
-
document.title = '';
|
|
31
|
-
}
|
|
32
|
-
expect(resolveAppDisplayName(undefined, 'oxy_session')).toBe('web');
|
|
33
|
-
});
|
|
34
|
-
|
|
35
|
-
it('falls back to document.title on web when no name or custom prefix is set', () => {
|
|
36
|
-
if (typeof document !== 'undefined') {
|
|
37
|
-
document.title = 'Homiio';
|
|
38
|
-
}
|
|
39
|
-
expect(resolveAppDisplayName(undefined, 'oxy_session')).toBe('Homiio');
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
it('falls back to the platform only when nothing else is available', () => {
|
|
43
|
-
if (typeof document !== 'undefined') {
|
|
44
|
-
document.title = '';
|
|
45
|
-
}
|
|
46
|
-
expect(resolveAppDisplayName(undefined, undefined)).toBe('web');
|
|
47
|
-
});
|
|
48
|
-
|
|
49
|
-
it('treats a whitespace-only appName as absent', () => {
|
|
50
|
-
expect(resolveAppDisplayName(' ', 'mention')).toBe('Mention');
|
|
51
|
-
});
|
|
52
|
-
});
|
package/src/ui/utils/appName.ts
DELETED
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
import { Platform } from 'react-native';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* The `storageKeyPrefix` default applied by `OxyContextProvider`. When the
|
|
5
|
-
* consumer never overrides it, the prefix carries no app-identity signal and
|
|
6
|
-
* must NOT be used to derive a display name (it would surface "Oxy_session").
|
|
7
|
-
*/
|
|
8
|
-
const DEFAULT_STORAGE_KEY_PREFIX = 'oxy_session';
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* Capitalize the first character of a non-empty string. Used to turn a lower
|
|
12
|
-
* case `storageKeyPrefix` (e.g. `"mention"`) into a presentable label
|
|
13
|
-
* (`"Mention"`). Pure; leaves the remainder untouched so multi-word or already
|
|
14
|
-
* capitalized values are preserved.
|
|
15
|
-
*/
|
|
16
|
-
function capitalizeFirst(value: string): string {
|
|
17
|
-
return value.charAt(0).toUpperCase() + value.slice(1);
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* Resolve a human-readable application display name for the consent / sign-in
|
|
22
|
-
* UI shown by the central Oxy auth experience (e.g. "Mention wants to access
|
|
23
|
-
* your Oxy account"). This is sent as the `appId` field on
|
|
24
|
-
* `POST /auth/session/create` and rendered verbatim by the auth consent page.
|
|
25
|
-
*
|
|
26
|
-
* Resolution order (first non-empty wins):
|
|
27
|
-
* 1. An explicit `appName` declared by the consumer on `OxyProvider`.
|
|
28
|
-
* 2. The capitalized `storageKeyPrefix` — but only when the consumer actually
|
|
29
|
-
* overrode the default. Apps already pass a brand-shaped prefix
|
|
30
|
-
* (`"mention"`, `"homiio"`, …) so this gives most apps a correct name with
|
|
31
|
-
* zero extra config.
|
|
32
|
-
* 3. On web only, a meaningful `document.title` (trimmed). This rescues
|
|
33
|
-
* zero-config web apps that set a page title but no prefix.
|
|
34
|
-
* 4. `Platform.OS` as the terminal fallback. On web this yields the historical
|
|
35
|
-
* `"web"` value — now reached ONLY when an app supplies neither an explicit
|
|
36
|
-
* name, a custom prefix, nor a document title.
|
|
37
|
-
*
|
|
38
|
-
* The result is never empty.
|
|
39
|
-
*/
|
|
40
|
-
export function resolveAppDisplayName(
|
|
41
|
-
appName: string | undefined,
|
|
42
|
-
storageKeyPrefix: string | undefined,
|
|
43
|
-
): string {
|
|
44
|
-
const explicit = appName?.trim();
|
|
45
|
-
if (explicit) {
|
|
46
|
-
return explicit;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
const prefix = storageKeyPrefix?.trim();
|
|
50
|
-
if (prefix && prefix !== DEFAULT_STORAGE_KEY_PREFIX) {
|
|
51
|
-
return capitalizeFirst(prefix);
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
if (Platform.OS === 'web' && typeof document !== 'undefined') {
|
|
55
|
-
const title = document.title?.trim();
|
|
56
|
-
if (title) {
|
|
57
|
-
return title;
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
return Platform.OS;
|
|
62
|
-
}
|