@ar.io/wayfinder-core 1.7.1-alpha.2 → 1.7.2-alpha.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/client.d.ts.map +1 -1
- package/dist/client.js +17 -13
- package/dist/constants.d.ts +59 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +60 -0
- package/dist/utils/verify-stream.d.ts +40 -0
- package/dist/utils/verify-stream.d.ts.map +1 -0
- package/dist/utils/verify-stream.js +106 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/wayfinder.d.ts +0 -11
- package/dist/wayfinder.d.ts.map +1 -1
- package/dist/wayfinder.js +2 -81
- package/package.json +1 -1
package/dist/client.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAUH,OAAO,KAAK,EACV,gBAAgB,EAChB,MAAM,EACN,aAAa,EACb,eAAe,EACf,kBAAkB,EAClB,oBAAoB,EACpB,gBAAgB,EACjB,MAAM,YAAY,CAAC;AAKpB,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAI3C;;GAEG;AACH,eAAO,MAAM,qBAAqB,GAAI,yCAInC;IACD,QAAQ,EAAE,aAAa,CAAC;IACxB,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;IACpC,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,KAAG,
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAUH,OAAO,KAAK,EACV,gBAAgB,EAChB,MAAM,EACN,aAAa,EACb,eAAe,EACf,kBAAkB,EAClB,oBAAoB,EACpB,gBAAgB,EACjB,MAAM,YAAY,CAAC;AAKpB,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAI3C;;GAEG;AACH,eAAO,MAAM,qBAAqB,GAAI,yCAInC;IACD,QAAQ,EAAE,aAAa,CAAC;IACxB,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;IACpC,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,KAAG,eAuBH,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,0BAA0B,GAAI,wCAIxC;IACD,QAAQ,EAAE,kBAAkB,CAAC;IAC7B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,eAAe,CAAC,EAAE,GAAG,EAAE,CAAC;CACzB,KAAG,oBAQH,CAAC;AAqCF;;;GAGG;AACH,wBAAgB,qBAAqB,CACnC,OAAO,GAAE,gBAAqB,GAC7B,SAAS,CA+BX;AAED,eAAO,MAAM,eAAe,8BAAwB,CAAC"}
|
package/dist/client.js
CHANGED
|
@@ -33,19 +33,23 @@ const DEFAULT_TRUSTED_GATEWAY = 'https://permagate.io';
|
|
|
33
33
|
*/
|
|
34
34
|
export const createRoutingStrategy = ({ strategy, gatewaysProvider, logger, }) => {
|
|
35
35
|
const baseConfig = { gatewaysProvider, logger };
|
|
36
|
-
|
|
37
|
-
random:
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
36
|
+
switch (strategy) {
|
|
37
|
+
case 'random':
|
|
38
|
+
return new RandomRoutingStrategy(baseConfig);
|
|
39
|
+
case 'fastest':
|
|
40
|
+
return new FastestPingRoutingStrategy(baseConfig);
|
|
41
|
+
case 'balanced':
|
|
42
|
+
return new RoundRobinRoutingStrategy(baseConfig);
|
|
43
|
+
case 'preferred':
|
|
44
|
+
return new PreferredWithFallbackRoutingStrategy({
|
|
45
|
+
preferredGateway: 'https://arweave.net',
|
|
46
|
+
fallbackStrategy: createRoutingStrategy({
|
|
47
|
+
strategy: 'fastest',
|
|
48
|
+
gatewaysProvider,
|
|
49
|
+
logger,
|
|
50
|
+
}),
|
|
51
|
+
});
|
|
52
|
+
}
|
|
49
53
|
};
|
|
50
54
|
/**
|
|
51
55
|
* Helper function to construct a verification strategy
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WayFinder
|
|
3
|
+
* Copyright (C) 2022-2025 Permanent Data Solutions, Inc.
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/
|
|
17
|
+
export declare const arnsRegex: RegExp;
|
|
18
|
+
export declare const txIdRegex: RegExp;
|
|
19
|
+
export declare const arioHeaderNames: {
|
|
20
|
+
hops: string;
|
|
21
|
+
origin: string;
|
|
22
|
+
originNodeRelease: string;
|
|
23
|
+
digest: string;
|
|
24
|
+
contentDigest: string;
|
|
25
|
+
expectedDigest: string;
|
|
26
|
+
stable: string;
|
|
27
|
+
verified: string;
|
|
28
|
+
trusted: string;
|
|
29
|
+
cache: string;
|
|
30
|
+
chunkSourceType: string;
|
|
31
|
+
chunkHost: string;
|
|
32
|
+
chunkDataPath: string;
|
|
33
|
+
chunkDataRoot: string;
|
|
34
|
+
chunkStartOffset: string;
|
|
35
|
+
chunkRelativeStartOffset: string;
|
|
36
|
+
chunkReadOffset: string;
|
|
37
|
+
chunkTxDataSize: string;
|
|
38
|
+
chunkTxPath: string;
|
|
39
|
+
chunkTxId: string;
|
|
40
|
+
chunkTxStartOffset: string;
|
|
41
|
+
rootTransactionId: string;
|
|
42
|
+
dataItemDataOffset: string;
|
|
43
|
+
dataItemRootParentOffset: string;
|
|
44
|
+
dataItemOffset: string;
|
|
45
|
+
dataItemSize: string;
|
|
46
|
+
rootDataItemOffset: string;
|
|
47
|
+
rootDataOffset: string;
|
|
48
|
+
arnsTtlSeconds: string;
|
|
49
|
+
arnsName: string;
|
|
50
|
+
arnsBasename: string;
|
|
51
|
+
arnsRecord: string;
|
|
52
|
+
arnsResolvedId: string;
|
|
53
|
+
dataId: string;
|
|
54
|
+
arnsProcessId: string;
|
|
55
|
+
arnsResolvedAt: string;
|
|
56
|
+
arnsLimit: string;
|
|
57
|
+
arnsIndex: string;
|
|
58
|
+
};
|
|
59
|
+
//# sourceMappingURL=constants.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAGH,eAAO,MAAM,SAAS,QAA2C,CAAC;AAClE,eAAO,MAAM,SAAS,QAAwB,CAAC;AAG/C,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAuC3B,CAAC"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WayFinder
|
|
3
|
+
* Copyright (C) 2022-2025 Permanent Data Solutions, Inc.
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/
|
|
17
|
+
// known regexes for wayfinder urls
|
|
18
|
+
export const arnsRegex = /^[a-z0-9_-]{1,42}$|^[a-z0-9_-]{44,51}$/;
|
|
19
|
+
export const txIdRegex = /^[A-Za-z0-9_-]{43}$/;
|
|
20
|
+
// ar.io gateway header names
|
|
21
|
+
export const arioHeaderNames = {
|
|
22
|
+
hops: 'X-AR-IO-Hops',
|
|
23
|
+
origin: 'X-AR-IO-Origin',
|
|
24
|
+
originNodeRelease: 'X-AR-IO-Origin-Node-Release',
|
|
25
|
+
digest: 'X-AR-IO-Digest',
|
|
26
|
+
contentDigest: 'Content-Digest',
|
|
27
|
+
expectedDigest: 'X-AR-IO-Expected-Digest',
|
|
28
|
+
stable: 'X-AR-IO-Stable',
|
|
29
|
+
verified: 'X-AR-IO-Verified',
|
|
30
|
+
trusted: 'X-AR-IO-Trusted',
|
|
31
|
+
cache: 'X-Cache',
|
|
32
|
+
chunkSourceType: 'X-AR-IO-Chunk-Source-Type',
|
|
33
|
+
chunkHost: 'X-AR-IO-Chunk-Host',
|
|
34
|
+
chunkDataPath: 'X-Arweave-Chunk-Data-Path',
|
|
35
|
+
chunkDataRoot: 'X-Arweave-Chunk-Data-Root',
|
|
36
|
+
chunkStartOffset: 'X-Arweave-Chunk-Start-Offset',
|
|
37
|
+
chunkRelativeStartOffset: 'X-Arweave-Chunk-Relative-Start-Offset',
|
|
38
|
+
chunkReadOffset: 'X-Arweave-Chunk-Read-Offset',
|
|
39
|
+
chunkTxDataSize: 'X-Arweave-Chunk-Tx-Data-Size',
|
|
40
|
+
chunkTxPath: 'X-Arweave-Chunk-Tx-Path',
|
|
41
|
+
chunkTxId: 'X-Arweave-Chunk-Tx-Id',
|
|
42
|
+
chunkTxStartOffset: 'X-Arweave-Chunk-Tx-Start-Offset',
|
|
43
|
+
rootTransactionId: 'X-AR-IO-Root-Transaction-Id',
|
|
44
|
+
dataItemDataOffset: 'X-AR-IO-Data-Item-Data-Offset',
|
|
45
|
+
dataItemRootParentOffset: 'X-AR-IO-Data-Item-Root-Parent-Offset',
|
|
46
|
+
dataItemOffset: 'X-AR-IO-Data-Item-Offset',
|
|
47
|
+
dataItemSize: 'X-AR-IO-Data-Item-Size',
|
|
48
|
+
rootDataItemOffset: 'X-AR-IO-Root-Data-Item-Offset',
|
|
49
|
+
rootDataOffset: 'X-AR-IO-Root-Data-Offset',
|
|
50
|
+
arnsTtlSeconds: 'X-ArNS-TTL-Seconds',
|
|
51
|
+
arnsName: 'X-ArNS-Name',
|
|
52
|
+
arnsBasename: 'X-ArNS-Basename',
|
|
53
|
+
arnsRecord: 'X-ArNS-Record',
|
|
54
|
+
arnsResolvedId: 'X-ArNS-Resolved-Id',
|
|
55
|
+
dataId: 'X-AR-IO-Data-Id',
|
|
56
|
+
arnsProcessId: 'X-ArNS-Process-Id',
|
|
57
|
+
arnsResolvedAt: 'X-ArNS-Resolved-At',
|
|
58
|
+
arnsLimit: 'X-ArNS-Undername-Limit',
|
|
59
|
+
arnsIndex: 'X-ArNS-Record-Index',
|
|
60
|
+
};
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WayFinder
|
|
3
|
+
* Copyright (C) 2022-2025 Permanent Data Solutions, Inc.
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/
|
|
17
|
+
import { WayfinderEmitter } from '../index.js';
|
|
18
|
+
import { VerificationStrategy } from '../types.js';
|
|
19
|
+
/**
|
|
20
|
+
* Utility to tap a ReadableStream for verification while passing through data to the client.
|
|
21
|
+
*
|
|
22
|
+
* @param originalStream The original ReadableStream from the fetch response.
|
|
23
|
+
* @param contentLength The total content length of the stream, used for progress reporting.
|
|
24
|
+
* @param verifyData The verification function to process the tapped stream.
|
|
25
|
+
* @param txId The transaction ID associated with the data.
|
|
26
|
+
* @param emitter Optional WayfinderEmitter to emit verification events.
|
|
27
|
+
* @param headers Optional headers to pass to the verification function.
|
|
28
|
+
* @param strict If true, the client stream will error if verification fails; otherwise, verification runs asynchronously.
|
|
29
|
+
* @returns A ReadableStream that passes through data to the client while verifying in parallel.
|
|
30
|
+
*/
|
|
31
|
+
export declare const tapAndVerifyReadableStream: ({ originalStream, contentLength, verifyData, txId, emitter, headers, strict, }: {
|
|
32
|
+
originalStream: ReadableStream;
|
|
33
|
+
contentLength: number;
|
|
34
|
+
headers?: Record<string, string>;
|
|
35
|
+
verifyData: VerificationStrategy["verifyData"];
|
|
36
|
+
txId: string;
|
|
37
|
+
emitter?: WayfinderEmitter;
|
|
38
|
+
strict?: boolean;
|
|
39
|
+
}) => ReadableStream;
|
|
40
|
+
//# sourceMappingURL=verify-stream.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"verify-stream.d.ts","sourceRoot":"","sources":["../../src/utils/verify-stream.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAEnD;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,0BAA0B,GAAI,gFAQxC;IACD,cAAc,EAAE,cAAc,CAAC;IAC/B,aAAa,EAAE,MAAM,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,UAAU,EAAE,oBAAoB,CAAC,YAAY,CAAC,CAAC;IAC/C,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,gBAAgB,CAAC;IAC3B,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB,KAAG,cAkFH,CAAC"}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WayFinder
|
|
3
|
+
* Copyright (C) 2022-2025 Permanent Data Solutions, Inc.
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/
|
|
17
|
+
/**
|
|
18
|
+
* Utility to tap a ReadableStream for verification while passing through data to the client.
|
|
19
|
+
*
|
|
20
|
+
* @param originalStream The original ReadableStream from the fetch response.
|
|
21
|
+
* @param contentLength The total content length of the stream, used for progress reporting.
|
|
22
|
+
* @param verifyData The verification function to process the tapped stream.
|
|
23
|
+
* @param txId The transaction ID associated with the data.
|
|
24
|
+
* @param emitter Optional WayfinderEmitter to emit verification events.
|
|
25
|
+
* @param headers Optional headers to pass to the verification function.
|
|
26
|
+
* @param strict If true, the client stream will error if verification fails; otherwise, verification runs asynchronously.
|
|
27
|
+
* @returns A ReadableStream that passes through data to the client while verifying in parallel.
|
|
28
|
+
*/
|
|
29
|
+
export const tapAndVerifyReadableStream = ({ originalStream, contentLength, verifyData, txId, emitter, headers = {}, strict = false, }) => {
|
|
30
|
+
if (originalStream instanceof ReadableStream &&
|
|
31
|
+
typeof originalStream.tee === 'function') {
|
|
32
|
+
/**
|
|
33
|
+
* NOTE: tee requires the streams both streams to be consumed, so we need to make sure we consume the client branch
|
|
34
|
+
* by the caller. This means when `request` is called, the client stream must be consumed by the caller via await request.text()
|
|
35
|
+
* for verification to complete.
|
|
36
|
+
*
|
|
37
|
+
* It is feasible to make the verification stream not to depend on the client branch being consumed, should the DX not be obvious.
|
|
38
|
+
*/
|
|
39
|
+
const [verifyBranch, clientBranch] = originalStream.tee();
|
|
40
|
+
// setup our promise to verify the data
|
|
41
|
+
const verificationPromise = verifyData({
|
|
42
|
+
data: verifyBranch,
|
|
43
|
+
txId,
|
|
44
|
+
headers,
|
|
45
|
+
});
|
|
46
|
+
let bytesProcessed = 0;
|
|
47
|
+
const reader = clientBranch.getReader();
|
|
48
|
+
const clientStreamWithVerification = new ReadableStream({
|
|
49
|
+
async pull(controller) {
|
|
50
|
+
const { done, value } = await reader.read();
|
|
51
|
+
if (done) {
|
|
52
|
+
if (strict) {
|
|
53
|
+
// in strict mode, we wait for verification to complete before closing the controller
|
|
54
|
+
try {
|
|
55
|
+
await verificationPromise;
|
|
56
|
+
emitter?.emit('verification-succeeded', { txId });
|
|
57
|
+
controller.close();
|
|
58
|
+
}
|
|
59
|
+
catch (err) {
|
|
60
|
+
// emit the verification failed event
|
|
61
|
+
emitter?.emit('verification-failed', err);
|
|
62
|
+
// In strict mode, we report the error to the client stream
|
|
63
|
+
controller.error(new Error('Verification failed', { cause: err }));
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
else {
|
|
67
|
+
// in non-strict mode, we close the controller immediately and handle verification asynchronously
|
|
68
|
+
controller.close();
|
|
69
|
+
// trigger the verification promise and emit events for the result
|
|
70
|
+
verificationPromise
|
|
71
|
+
.then(() => {
|
|
72
|
+
emitter?.emit('verification-succeeded', { txId });
|
|
73
|
+
})
|
|
74
|
+
.catch((error) => {
|
|
75
|
+
emitter?.emit('verification-failed', error);
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
else {
|
|
80
|
+
bytesProcessed += value.length;
|
|
81
|
+
emitter?.emit('verification-progress', {
|
|
82
|
+
txId,
|
|
83
|
+
totalBytes: contentLength,
|
|
84
|
+
processedBytes: bytesProcessed,
|
|
85
|
+
});
|
|
86
|
+
controller.enqueue(value);
|
|
87
|
+
}
|
|
88
|
+
},
|
|
89
|
+
cancel(reason) {
|
|
90
|
+
// cancel the reader regardless of verification status
|
|
91
|
+
reader.cancel(reason);
|
|
92
|
+
// emit the verification cancellation event
|
|
93
|
+
emitter?.emit('verification-failed', {
|
|
94
|
+
txId,
|
|
95
|
+
error: new Error('Verification cancelled', {
|
|
96
|
+
cause: {
|
|
97
|
+
reason,
|
|
98
|
+
},
|
|
99
|
+
}),
|
|
100
|
+
});
|
|
101
|
+
},
|
|
102
|
+
});
|
|
103
|
+
return clientStreamWithVerification;
|
|
104
|
+
}
|
|
105
|
+
throw new Error('Unsupported body type for cloning');
|
|
106
|
+
};
|
package/dist/version.d.ts
CHANGED
|
@@ -14,5 +14,5 @@
|
|
|
14
14
|
* See the License for the specific language governing permissions and
|
|
15
15
|
* limitations under the License.
|
|
16
16
|
*/
|
|
17
|
-
export declare const WAYFINDER_CORE_VERSION = "v1.7.
|
|
17
|
+
export declare const WAYFINDER_CORE_VERSION = "v1.7.2-alpha.0";
|
|
18
18
|
//# sourceMappingURL=version.d.ts.map
|
package/dist/version.js
CHANGED
package/dist/wayfinder.d.ts
CHANGED
|
@@ -25,8 +25,6 @@ export declare const createWayfinderRequestHeaders: ({ traceId, }: {
|
|
|
25
25
|
'x-ar-io-trace-id'?: string | undefined;
|
|
26
26
|
'x-ar-io-component': string;
|
|
27
27
|
};
|
|
28
|
-
export declare const arnsRegex: RegExp;
|
|
29
|
-
export declare const txIdRegex: RegExp;
|
|
30
28
|
/**
|
|
31
29
|
* Parses the original URL from the params and returns a WayfinderURL (e.g. ar://<txId>)
|
|
32
30
|
* @param params - The params to parse
|
|
@@ -55,15 +53,6 @@ export declare const constructGatewayUrl: ({ selectedGateway, subdomain, path, }
|
|
|
55
53
|
subdomain: string;
|
|
56
54
|
path: string;
|
|
57
55
|
}) => URL;
|
|
58
|
-
export declare function tapAndVerifyReadableStream({ originalStream, contentLength, verifyData, txId, emitter, headers, strict, }: {
|
|
59
|
-
originalStream: ReadableStream;
|
|
60
|
-
contentLength: number;
|
|
61
|
-
headers?: Record<string, string>;
|
|
62
|
-
verifyData: VerificationStrategy['verifyData'];
|
|
63
|
-
txId: string;
|
|
64
|
-
emitter?: WayfinderEmitter;
|
|
65
|
-
strict?: boolean;
|
|
66
|
-
}): ReadableStream;
|
|
67
56
|
/**
|
|
68
57
|
* Creates a wrapped fetch function that supports ar:// protocol
|
|
69
58
|
*
|
package/dist/wayfinder.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"wayfinder.d.ts","sourceRoot":"","sources":["../src/wayfinder.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAIH,OAAO,EAAQ,KAAK,MAAM,EAAkB,MAAM,oBAAoB,CAAC;AACvE,OAAO,EACL,mBAAmB,EACnB,kBAAkB,EACnB,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;
|
|
1
|
+
{"version":3,"file":"wayfinder.d.ts","sourceRoot":"","sources":["../src/wayfinder.ts"],"names":[],"mappings":"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"}
|
package/dist/wayfinder.js
CHANGED
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
*/
|
|
17
17
|
import { defaultLogger } from './logger.js';
|
|
18
18
|
import { context, trace } from '@opentelemetry/api';
|
|
19
|
+
import { arnsRegex, txIdRegex } from './constants.js';
|
|
19
20
|
import { WayfinderEmitter } from './emitter.js';
|
|
20
21
|
import { createBaseFetch } from './fetch.js';
|
|
21
22
|
import { TrustedPeersGatewaysProvider } from './gateways/trusted-peers.js';
|
|
@@ -23,6 +24,7 @@ import { PingRoutingStrategy } from './routing/ping.js';
|
|
|
23
24
|
import { RandomRoutingStrategy } from './routing/random.js';
|
|
24
25
|
import { initTelemetry, startRequestSpans } from './telemetry.js';
|
|
25
26
|
import { sandboxFromId } from './utils/base64.js';
|
|
27
|
+
import { tapAndVerifyReadableStream } from './utils/verify-stream.js';
|
|
26
28
|
import { HashVerificationStrategy } from './verification/hash-verification.js';
|
|
27
29
|
// headers
|
|
28
30
|
export const createWayfinderRequestHeaders = ({ traceId, }) => {
|
|
@@ -32,9 +34,6 @@ export const createWayfinderRequestHeaders = ({ traceId, }) => {
|
|
|
32
34
|
...(traceId ? { 'x-ar-io-trace-id': traceId } : {}),
|
|
33
35
|
};
|
|
34
36
|
};
|
|
35
|
-
// known regexes for wayfinder urls
|
|
36
|
-
export const arnsRegex = /^[a-z0-9_-]{1,51}$/;
|
|
37
|
-
export const txIdRegex = /^[A-Za-z0-9_-]{43}$/;
|
|
38
37
|
/**
|
|
39
38
|
* Parses the original URL from the params and returns a WayfinderURL (e.g. ar://<txId>)
|
|
40
39
|
* @param params - The params to parse
|
|
@@ -132,84 +131,6 @@ export const constructGatewayUrl = ({ selectedGateway, subdomain, path, }) => {
|
|
|
132
131
|
}
|
|
133
132
|
return gatewayUrl;
|
|
134
133
|
};
|
|
135
|
-
export function tapAndVerifyReadableStream({ originalStream, contentLength, verifyData, txId, emitter, headers = {}, strict = false, }) {
|
|
136
|
-
if (originalStream instanceof ReadableStream &&
|
|
137
|
-
typeof originalStream.tee === 'function') {
|
|
138
|
-
/**
|
|
139
|
-
* NOTE: tee requires the streams both streams to be consumed, so we need to make sure we consume the client branch
|
|
140
|
-
* by the caller. This means when `request` is called, the client stream must be consumed by the caller via await request.text()
|
|
141
|
-
* for verification to complete.
|
|
142
|
-
*
|
|
143
|
-
* It is feasible to make the verification stream not to depend on the client branch being consumed, should the DX not be obvious.
|
|
144
|
-
*/
|
|
145
|
-
const [verifyBranch, clientBranch] = originalStream.tee();
|
|
146
|
-
// setup our promise to verify the data
|
|
147
|
-
const verificationPromise = verifyData({
|
|
148
|
-
data: verifyBranch,
|
|
149
|
-
txId,
|
|
150
|
-
headers,
|
|
151
|
-
});
|
|
152
|
-
let bytesProcessed = 0;
|
|
153
|
-
const reader = clientBranch.getReader();
|
|
154
|
-
const clientStreamWithVerification = new ReadableStream({
|
|
155
|
-
async pull(controller) {
|
|
156
|
-
const { done, value } = await reader.read();
|
|
157
|
-
if (done) {
|
|
158
|
-
if (strict) {
|
|
159
|
-
// in strict mode, we wait for verification to complete before closing the controller
|
|
160
|
-
try {
|
|
161
|
-
await verificationPromise;
|
|
162
|
-
emitter?.emit('verification-succeeded', { txId });
|
|
163
|
-
controller.close();
|
|
164
|
-
}
|
|
165
|
-
catch (err) {
|
|
166
|
-
// emit the verification failed event
|
|
167
|
-
emitter?.emit('verification-failed', err);
|
|
168
|
-
// In strict mode, we report the error to the client stream
|
|
169
|
-
controller.error(new Error('Verification failed', { cause: err }));
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
else {
|
|
173
|
-
// trigger the verification promise and emit events for the result
|
|
174
|
-
verificationPromise
|
|
175
|
-
.then(() => {
|
|
176
|
-
emitter?.emit('verification-succeeded', { txId });
|
|
177
|
-
})
|
|
178
|
-
.catch((error) => {
|
|
179
|
-
emitter?.emit('verification-failed', error);
|
|
180
|
-
});
|
|
181
|
-
// in non-strict mode, we close the controller immediately and handle verification asynchronously
|
|
182
|
-
controller.close();
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
else {
|
|
186
|
-
bytesProcessed += value.length;
|
|
187
|
-
emitter?.emit('verification-progress', {
|
|
188
|
-
txId,
|
|
189
|
-
totalBytes: contentLength,
|
|
190
|
-
processedBytes: bytesProcessed,
|
|
191
|
-
});
|
|
192
|
-
controller.enqueue(value);
|
|
193
|
-
}
|
|
194
|
-
},
|
|
195
|
-
cancel(reason) {
|
|
196
|
-
// cancel the reader regardless of verification status
|
|
197
|
-
reader.cancel(reason);
|
|
198
|
-
// emit the verification cancellation event
|
|
199
|
-
emitter?.emit('verification-failed', {
|
|
200
|
-
txId,
|
|
201
|
-
error: new Error('Verification cancelled', {
|
|
202
|
-
cause: {
|
|
203
|
-
reason,
|
|
204
|
-
},
|
|
205
|
-
}),
|
|
206
|
-
});
|
|
207
|
-
},
|
|
208
|
-
});
|
|
209
|
-
return clientStreamWithVerification;
|
|
210
|
-
}
|
|
211
|
-
throw new Error('Unsupported body type for cloning');
|
|
212
|
-
}
|
|
213
134
|
/**
|
|
214
135
|
* Creates a wrapped fetch function that supports ar:// protocol
|
|
215
136
|
*
|
package/package.json
CHANGED