@oxyhq/core 3.12.0 → 3.13.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/dist/cjs/.tsbuildinfo +1 -1
- package/dist/cjs/utils/profileLinks.js +15 -4
- package/dist/esm/.tsbuildinfo +1 -1
- package/dist/esm/utils/profileLinks.js +15 -4
- package/dist/types/.tsbuildinfo +1 -1
- package/dist/types/utils/profileLinks.d.ts +11 -3
- package/package.json +2 -2
- package/src/utils/__tests__/profileLinks.test.ts +56 -2
- package/src/utils/profileLinks.ts +21 -4
|
@@ -3,11 +3,16 @@
|
|
|
3
3
|
*
|
|
4
4
|
* `id` is a stable key for list rendering (the source entry's id when present,
|
|
5
5
|
* otherwise the source index as a string). `url` is always a non-empty string.
|
|
6
|
+
* `title`, `description`, and `image` are carried through from `linksMetadata`
|
|
7
|
+
* only when present; the legacy `links: string[]` path produces just
|
|
8
|
+
* `{ id, url }`.
|
|
6
9
|
*/
|
|
7
10
|
export interface ProfileLink {
|
|
8
11
|
id: string;
|
|
9
12
|
title?: string;
|
|
10
13
|
url: string;
|
|
14
|
+
description?: string;
|
|
15
|
+
image?: string;
|
|
11
16
|
}
|
|
12
17
|
/** Source shape of a single `User.linksMetadata` entry. */
|
|
13
18
|
export interface ProfileLinkMetadata {
|
|
@@ -23,10 +28,13 @@ export interface ProfileLinkMetadata {
|
|
|
23
28
|
* Pure, no side effects, no I/O.
|
|
24
29
|
*
|
|
25
30
|
* - Prefers `linksMetadata` when it is a non-empty array: maps each entry to
|
|
26
|
-
* `{ id, title, url }`, using `entry.id` when present and
|
|
27
|
-
* entry index.
|
|
31
|
+
* `{ id, title, url, description, image }`, using `entry.id` when present and
|
|
32
|
+
* falling back to the entry index. `title`, `description`, and `image` are
|
|
33
|
+
* carried through only when they are present strings. Entries without a
|
|
34
|
+
* non-empty string `url` are dropped.
|
|
28
35
|
* - Otherwise falls back to the legacy `links` string array: maps each string to
|
|
29
|
-
* `{ id: <index>, url }` (no title). Empty/non-string values
|
|
36
|
+
* `{ id: <index>, url }` (no title/description/image). Empty/non-string values
|
|
37
|
+
* are dropped.
|
|
30
38
|
* - Returns `[]` when both are absent or empty (including when `linksMetadata`
|
|
31
39
|
* is present but every entry is dropped — it does NOT fall back to `links`).
|
|
32
40
|
*
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@oxyhq/core",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.13.0",
|
|
4
4
|
"description": "OxyHQ SDK Foundation — API client, authentication, cryptographic identity, and shared utilities",
|
|
5
5
|
"main": "dist/cjs/index.js",
|
|
6
6
|
"module": "dist/esm/index.js",
|
|
@@ -98,7 +98,7 @@
|
|
|
98
98
|
}
|
|
99
99
|
},
|
|
100
100
|
"dependencies": {
|
|
101
|
-
"@oxyhq/contracts": "
|
|
101
|
+
"@oxyhq/contracts": "workspace:*",
|
|
102
102
|
"bip39": "^3.1.0",
|
|
103
103
|
"buffer": "^6.0.3",
|
|
104
104
|
"elliptic": "^6.6.1",
|
|
@@ -30,6 +30,53 @@ describe('normalizeProfileLinks', () => {
|
|
|
30
30
|
expect(result[0]).not.toHaveProperty('title');
|
|
31
31
|
});
|
|
32
32
|
|
|
33
|
+
it('carries through description and image when present', () => {
|
|
34
|
+
const result = normalizeProfileLinks([
|
|
35
|
+
{
|
|
36
|
+
url: 'https://oxy.so',
|
|
37
|
+
title: 'Oxy',
|
|
38
|
+
description: 'The Oxy ecosystem',
|
|
39
|
+
image: 'https://cdn.example/oxy.png',
|
|
40
|
+
id: 'abc',
|
|
41
|
+
},
|
|
42
|
+
]);
|
|
43
|
+
expect(result).toEqual<ProfileLink[]>([
|
|
44
|
+
{
|
|
45
|
+
id: 'abc',
|
|
46
|
+
title: 'Oxy',
|
|
47
|
+
url: 'https://oxy.so',
|
|
48
|
+
description: 'The Oxy ecosystem',
|
|
49
|
+
image: 'https://cdn.example/oxy.png',
|
|
50
|
+
},
|
|
51
|
+
]);
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
it('omits description and image when absent', () => {
|
|
55
|
+
const result = normalizeProfileLinks([
|
|
56
|
+
{ url: 'https://min.example', title: 'Min' },
|
|
57
|
+
]);
|
|
58
|
+
expect(result).toEqual<ProfileLink[]>([
|
|
59
|
+
{ id: '0', title: 'Min', url: 'https://min.example' },
|
|
60
|
+
]);
|
|
61
|
+
expect(result[0]).not.toHaveProperty('description');
|
|
62
|
+
expect(result[0]).not.toHaveProperty('image');
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
it('carries description and image independently of title', () => {
|
|
66
|
+
const result = normalizeProfileLinks([
|
|
67
|
+
{ url: 'https://only-image.example', image: 'https://cdn.example/i.png' },
|
|
68
|
+
{ url: 'https://only-desc.example', description: 'Just a description' },
|
|
69
|
+
]);
|
|
70
|
+
expect(result).toEqual<ProfileLink[]>([
|
|
71
|
+
{ id: '0', url: 'https://only-image.example', image: 'https://cdn.example/i.png' },
|
|
72
|
+
{ id: '1', url: 'https://only-desc.example', description: 'Just a description' },
|
|
73
|
+
]);
|
|
74
|
+
expect(result[0]).not.toHaveProperty('title');
|
|
75
|
+
expect(result[0]).not.toHaveProperty('description');
|
|
76
|
+
expect(result[1]).not.toHaveProperty('title');
|
|
77
|
+
expect(result[1]).not.toHaveProperty('image');
|
|
78
|
+
});
|
|
79
|
+
|
|
33
80
|
it('drops entries with missing or empty url and keeps stable index ids', () => {
|
|
34
81
|
const result = normalizeProfileLinks([
|
|
35
82
|
{ url: 'https://keep.example', title: 'Keep', id: 'keep' },
|
|
@@ -60,7 +107,7 @@ describe('normalizeProfileLinks', () => {
|
|
|
60
107
|
});
|
|
61
108
|
|
|
62
109
|
describe('legacy links path (no linksMetadata)', () => {
|
|
63
|
-
it('maps strings to { id, url } without
|
|
110
|
+
it('maps strings to { id, url } without title/description/image', () => {
|
|
64
111
|
const result = normalizeProfileLinks(undefined, [
|
|
65
112
|
'https://a.example',
|
|
66
113
|
'https://b.example',
|
|
@@ -69,7 +116,14 @@ describe('normalizeProfileLinks', () => {
|
|
|
69
116
|
{ id: '0', url: 'https://a.example' },
|
|
70
117
|
{ id: '1', url: 'https://b.example' },
|
|
71
118
|
]);
|
|
72
|
-
expect(
|
|
119
|
+
expect(
|
|
120
|
+
result.every(
|
|
121
|
+
(link) =>
|
|
122
|
+
!('title' in link) &&
|
|
123
|
+
!('description' in link) &&
|
|
124
|
+
!('image' in link),
|
|
125
|
+
),
|
|
126
|
+
).toBe(true);
|
|
73
127
|
});
|
|
74
128
|
|
|
75
129
|
it('drops empty and whitespace-only strings, preserving source index ids', () => {
|
|
@@ -3,11 +3,16 @@
|
|
|
3
3
|
*
|
|
4
4
|
* `id` is a stable key for list rendering (the source entry's id when present,
|
|
5
5
|
* otherwise the source index as a string). `url` is always a non-empty string.
|
|
6
|
+
* `title`, `description`, and `image` are carried through from `linksMetadata`
|
|
7
|
+
* only when present; the legacy `links: string[]` path produces just
|
|
8
|
+
* `{ id, url }`.
|
|
6
9
|
*/
|
|
7
10
|
export interface ProfileLink {
|
|
8
11
|
id: string;
|
|
9
12
|
title?: string;
|
|
10
13
|
url: string;
|
|
14
|
+
description?: string;
|
|
15
|
+
image?: string;
|
|
11
16
|
}
|
|
12
17
|
|
|
13
18
|
/** Source shape of a single `User.linksMetadata` entry. */
|
|
@@ -31,10 +36,13 @@ function cleanUrl(value: unknown): string | null {
|
|
|
31
36
|
* Pure, no side effects, no I/O.
|
|
32
37
|
*
|
|
33
38
|
* - Prefers `linksMetadata` when it is a non-empty array: maps each entry to
|
|
34
|
-
* `{ id, title, url }`, using `entry.id` when present and
|
|
35
|
-
* entry index.
|
|
39
|
+
* `{ id, title, url, description, image }`, using `entry.id` when present and
|
|
40
|
+
* falling back to the entry index. `title`, `description`, and `image` are
|
|
41
|
+
* carried through only when they are present strings. Entries without a
|
|
42
|
+
* non-empty string `url` are dropped.
|
|
36
43
|
* - Otherwise falls back to the legacy `links` string array: maps each string to
|
|
37
|
-
* `{ id: <index>, url }` (no title). Empty/non-string values
|
|
44
|
+
* `{ id: <index>, url }` (no title/description/image). Empty/non-string values
|
|
45
|
+
* are dropped.
|
|
38
46
|
* - Returns `[]` when both are absent or empty (including when `linksMetadata`
|
|
39
47
|
* is present but every entry is dropped — it does NOT fall back to `links`).
|
|
40
48
|
*
|
|
@@ -55,7 +63,16 @@ export function normalizeProfileLinks(
|
|
|
55
63
|
? entry.id
|
|
56
64
|
: String(index);
|
|
57
65
|
const title = typeof entry?.title === 'string' ? entry.title : undefined;
|
|
58
|
-
|
|
66
|
+
const description =
|
|
67
|
+
typeof entry?.description === 'string' ? entry.description : undefined;
|
|
68
|
+
const image = typeof entry?.image === 'string' ? entry.image : undefined;
|
|
69
|
+
result.push({
|
|
70
|
+
id,
|
|
71
|
+
url,
|
|
72
|
+
...(title !== undefined ? { title } : {}),
|
|
73
|
+
...(description !== undefined ? { description } : {}),
|
|
74
|
+
...(image !== undefined ? { image } : {}),
|
|
75
|
+
});
|
|
59
76
|
});
|
|
60
77
|
return result;
|
|
61
78
|
}
|