Skip to content

Commit 4ab3e81

Browse files
fix(fetch): additional stuff
1 parent d108485 commit 4ab3e81

25 files changed

+310
-44
lines changed
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
const test = await fetch('https://dummyjson.com/products?limit=10&skip=0&select=title,price');
2+
console.log(test);
3+
const a = new Blob([test]);
4+
console.log(a);
5+
6+
const fr = new FileReader();
7+
8+
fr.onload = function () {
9+
console.log(JSON.parse(this.result));
10+
};
11+
12+
fr.readAsText(a);

packages/operators/src/fetch/concurrentDownload.test.js

Lines changed: 0 additions & 40 deletions
This file was deleted.

packages/operators/src/json.js

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import { concatMap, map } from 'rxjs';
2+
3+
import { replaceTypes } from './json/replacer.js';
4+
import { reviveTypes } from './json/reviver.js';
5+
import { defaultDeserializeReworker, defaultSerializeReworker } from './json/reworker/default.js';
6+
import { signJSON, verifyJSON } from './sign.js';
7+
8+
export const serialize = (reworker, signer) => source =>
9+
source.pipe(
10+
rework(reworker || defaultSerializeReworker),
11+
map(data => JSON.stringify(data, replaceTypes)),
12+
signJSON(signer)
13+
);
14+
15+
export const deserialize = (reworker, signAddress) => source =>
16+
source.pipe(
17+
verifyJSON(signAddress),
18+
map(data => JSON.parse(data, reviveTypes)),
19+
rework(reworker || defaultDeserializeReworker)
20+
);
21+
22+
const rework = reworker => source =>
23+
source.pipe(
24+
concatMap(data => reworkEntry('data', data, reworker)),
25+
map(data => Object.fromEntries(data).data)
26+
);
27+
28+
const reworkEntry = async (key, value, reworker) => {
29+
const { transform } = reworker.find(({ type }) => type === value?.constructor) || {};
30+
if (transform) {
31+
return await transform(key, value, reworkEntry, reworker);
32+
} else {
33+
return [[key, value]];
34+
}
35+
};
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
export const replaceTypes = (key, value) => {
2+
if (value?.constructor && value.constructor === Date) {
3+
return value.toISOString();
4+
}
5+
6+
if (value?.constructor && value.constructor === BigInt) {
7+
return value.toString();
8+
}
9+
return value;
10+
};
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
export const reviveTypes = (key, value) => {
2+
if (isValidUrl(value)) {
3+
return new URL(value);
4+
}
5+
if (isValidISODateString(value)) {
6+
return new Date(value);
7+
}
8+
if (isBigInt(value)) {
9+
return BigInt(value);
10+
}
11+
return value;
12+
};
13+
14+
const isValidUrl = value => {
15+
return URL.canParse(value) && /^[\w]+:\/\/\S+$/gm.test(value);
16+
};
17+
18+
function isValidISODateString(value) {
19+
if (!/\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.\d{3}Z/.test(value)) return false;
20+
const d = new Date(value);
21+
return d instanceof Date && !isNaN(d.getTime()) && d.toISOString() === value; // valid date
22+
}
23+
24+
function isBigInt(value) {
25+
return value?.constructor === String && /^\d+$/.test(value);
26+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
export const defaultReworker = [
2+
{
3+
type: Array,
4+
transform: async (key, value, rework, reworker) => [
5+
[
6+
key,
7+
Array.from(
8+
await Promise.all(value.map((entry, key) => rework(key, entry, reworker))),
9+
([[, value]]) => value
10+
)
11+
]
12+
]
13+
},
14+
{
15+
type: Object,
16+
transform: async (key, value, rework, reworker) => [
17+
[
18+
key,
19+
Object.fromEntries(
20+
await Object.entries(value).reduce(async (accumulator, [key, value]) => {
21+
return [...(await accumulator), ...(await rework(key, await value, reworker))];
22+
}, Promise.resolve([]))
23+
)
24+
]
25+
]
26+
}
27+
];
28+
29+
export const defaultSerializeReworker = defaultReworker;
30+
export const defaultDeserializeReworker = defaultReworker;
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import { defaultDeserializeReworker, defaultSerializeReworker } from './default.js';
2+
3+
const serializeMapping = {
4+
tokenData: { name: 'tokenURI', preserve: false },
5+
contractData: { name: 'contractURI', preserve: false }
6+
};
7+
export const serializeReworker = resolve =>
8+
defaultSerializeReworker.concat([
9+
{
10+
type: Blob,
11+
transform: async (key, value) => transform(key, value, serializeMapping[String(key)], resolve)
12+
}
13+
]);
14+
15+
const deserializeMapping = {
16+
tokenURI: { name: 'tokenData', preserve: true },
17+
contractURI: { name: 'contractData', preserve: true }
18+
};
19+
export const deserializeReworker = resolve =>
20+
defaultDeserializeReworker.concat([
21+
{
22+
type: URL,
23+
transform: async (key, value) =>
24+
transform(key, value, deserializeMapping[String(key)], resolve)
25+
}
26+
]);
27+
28+
const transform = async (key, value, config, resolve) => {
29+
const result = await resolve(normalizeUrl(value), key);
30+
if (config?.preserve) {
31+
result.tokenURI = value.toString();
32+
}
33+
return [
34+
!config || config.preserve ? [key, value] : undefined,
35+
[config?.name || key, result]
36+
].filter(Boolean);
37+
};
38+
39+
const normalizeUrl = url => {
40+
const regex = /^(?<protocol>\w+:)\/\/(?<cid>\w+)\/*(?<filename>[\w.]+)*$/gm;
41+
const { groups } = regex.exec(url);
42+
return url + (groups.filename ? '' : '0');
43+
};
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import { ReplaySubject, share, timer } from 'rxjs';
2+
3+
export const cache = ttl => {
4+
return source =>
5+
source.pipe(
6+
share({
7+
// TODO: check if a buffer size is neccessary
8+
connector: () => new ReplaySubject(),
9+
resetOnComplete: () => timer(ttl)
10+
})
11+
);
12+
};

0 commit comments

Comments
 (0)