@upcoming/bee-js 12.0.0 → 12.2.2
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/bee.js +11 -6
- package/dist/cjs/index.js +1 -3
- package/dist/cjs/modules/feed.js +1 -1
- package/dist/cjs/modules/status.js +1 -0
- package/dist/cjs/utils/http.js +92 -52
- package/dist/cjs/utils/tar.browser.js +55 -7
- package/dist/cjs/utils/tar.js +48 -7
- package/dist/cjs/utils/tokens.js +12 -0
- package/dist/index.browser.min.js +1 -1
- package/dist/index.browser.min.js.map +1 -1
- package/dist/mjs/bee.js +12 -7
- package/dist/mjs/index.js +1 -2
- package/dist/mjs/modules/feed.js +3 -1
- package/dist/mjs/modules/status.js +2 -1
- package/dist/mjs/utils/http.js +97 -59
- package/dist/mjs/utils/tar.browser.js +66 -8
- package/dist/mjs/utils/tar.js +59 -8
- package/dist/mjs/utils/tokens.js +12 -0
- package/dist/types/bee.d.ts +3 -3
- package/dist/types/index.d.ts +1 -3
- package/dist/types/utils/http.d.ts +18 -3
- package/dist/types/utils/tar-uploader.browser.d.ts +1 -1
- package/dist/types/utils/tar-uploader.d.ts +1 -1
- package/dist/types/utils/tokens.d.ts +4 -0
- package/package.json +10 -7
- package/dist/cjs/bee-dev.js +0 -78
- package/dist/mjs/bee-dev.js +0 -98
- package/dist/types/bee-dev.d.ts +0 -5
package/dist/cjs/bee.js
CHANGED
|
@@ -319,7 +319,7 @@ class Bee {
|
|
|
319
319
|
const fileData = await (0, file_1.fileArrayBuffer)(data);
|
|
320
320
|
const fileName = name ?? data.name;
|
|
321
321
|
const contentType = data.type;
|
|
322
|
-
const fileOptions = {
|
|
322
|
+
const fileOptions = { ...options, contentType };
|
|
323
323
|
return bzz.uploadFile(this.getRequestOptionsForCall(requestOptions), fileData, postageBatchId, fileName, fileOptions);
|
|
324
324
|
}
|
|
325
325
|
else {
|
|
@@ -1629,10 +1629,16 @@ class Bee {
|
|
|
1629
1629
|
? currentAmount * multiplier
|
|
1630
1630
|
: (currentAmount + additionalAmount) * multiplier;
|
|
1631
1631
|
const amountDelta = targetAmount - currentAmount;
|
|
1632
|
-
|
|
1632
|
+
let transactionId;
|
|
1633
|
+
if (amountDelta > 0n) {
|
|
1634
|
+
transactionId = await this.topUpBatch(batch.batchID, amountDelta, requestOptions);
|
|
1635
|
+
}
|
|
1633
1636
|
if (depthDelta > 0) {
|
|
1634
1637
|
return this.diluteBatch(batch.batchID, depth, requestOptions);
|
|
1635
1638
|
}
|
|
1639
|
+
if (!transactionId) {
|
|
1640
|
+
throw new Error('Nothing to extend, both size and duration are already sufficient');
|
|
1641
|
+
}
|
|
1636
1642
|
return transactionId;
|
|
1637
1643
|
}
|
|
1638
1644
|
/**
|
|
@@ -1760,16 +1766,15 @@ class Bee {
|
|
|
1760
1766
|
/**
|
|
1761
1767
|
* Calculates the `amount` and expected duration extension for topping up a postage batch with a given BZZ value.
|
|
1762
1768
|
*
|
|
1763
|
-
* @param
|
|
1769
|
+
* @param depth Depth of the postage batch to top up.
|
|
1764
1770
|
* @param bzz The amount of BZZ to spend on the top-up.
|
|
1765
1771
|
* @param requestOptions Options for making requests, such as timeouts, custom HTTP agents, headers, etc.
|
|
1766
1772
|
* @returns An object with `amount` (to pass to {@link topUpBatch}) and `duration` (the expected TTL extension).
|
|
1767
1773
|
*/
|
|
1768
|
-
async calculateTopUpForBzz(
|
|
1769
|
-
const batch = await this.getPostageBatch(postageBatchId, requestOptions);
|
|
1774
|
+
async calculateTopUpForBzz(depth, bzz, requestOptions) {
|
|
1770
1775
|
const chainState = await this.getChainState(requestOptions);
|
|
1771
1776
|
const blockTime = this.network === 'gnosis' ? 5 : 15;
|
|
1772
|
-
const amount = bzz.toPLURBigInt() / 2n ** BigInt(
|
|
1777
|
+
const amount = bzz.toPLURBigInt() / 2n ** BigInt(depth);
|
|
1773
1778
|
const duration = (0, stamps_1.getStampDuration)(amount, chainState.currentPrice, blockTime);
|
|
1774
1779
|
return { amount, duration };
|
|
1775
1780
|
}
|
package/dist/cjs/index.js
CHANGED
|
@@ -36,11 +36,9 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
36
36
|
};
|
|
37
37
|
})();
|
|
38
38
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
-
exports.Stamper = exports.
|
|
39
|
+
exports.Stamper = exports.Bee = exports.Size = exports.Utils = exports.Duration = exports.Bytes = exports.SUPPORTED_BEE_VERSION_EXACT = exports.SUPPORTED_BEE_VERSION = exports.MantarayNode = exports.MerkleTree = void 0;
|
|
40
40
|
const bee_1 = require("./bee");
|
|
41
41
|
Object.defineProperty(exports, "Bee", { enumerable: true, get: function () { return bee_1.Bee; } });
|
|
42
|
-
const bee_dev_1 = require("./bee-dev");
|
|
43
|
-
Object.defineProperty(exports, "BeeDev", { enumerable: true, get: function () { return bee_dev_1.BeeDev; } });
|
|
44
42
|
const stamper_1 = require("./stamper/stamper");
|
|
45
43
|
Object.defineProperty(exports, "Stamper", { enumerable: true, get: function () { return stamper_1.Stamper; } });
|
|
46
44
|
var cafe_utility_1 = require("cafe-utility");
|
package/dist/cjs/modules/feed.js
CHANGED
|
@@ -60,7 +60,7 @@ async function fetchLatestFeedUpdate(requestOptions, owner, topic, options) {
|
|
|
60
60
|
const response = await (0, http_1.http)(requestOptions, {
|
|
61
61
|
responseType: 'arraybuffer',
|
|
62
62
|
url: `${feedEndpoint}/${owner}/${topic}`,
|
|
63
|
-
params: options,
|
|
63
|
+
params: { ...options },
|
|
64
64
|
});
|
|
65
65
|
return {
|
|
66
66
|
payload: new bytes_1.Bytes(response.data),
|
package/dist/cjs/utils/http.js
CHANGED
|
@@ -5,29 +5,20 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.DEFAULT_HTTP_CONFIG = void 0;
|
|
7
7
|
exports.http = http;
|
|
8
|
-
|
|
8
|
+
exports.toBeeResponse = toBeeResponse;
|
|
9
9
|
const cafe_utility_1 = require("cafe-utility");
|
|
10
10
|
const debug_1 = __importDefault(require("debug"));
|
|
11
11
|
const index_1 = require("../index");
|
|
12
12
|
const debug = (0, debug_1.default)('bee-js:http');
|
|
13
|
-
const { AxiosError } = axios_1.default;
|
|
14
13
|
const MAX_FAILED_ATTEMPTS = 100000;
|
|
15
14
|
const DELAY_FAST = 200;
|
|
16
15
|
const DELAY_SLOW = 1000;
|
|
17
|
-
const
|
|
18
|
-
const ABORT_ERROR_MESSAGE = 'Request aborted';
|
|
16
|
+
const FAST_RETRY_COUNT = 300;
|
|
19
17
|
exports.DEFAULT_HTTP_CONFIG = {
|
|
20
18
|
headers: {
|
|
21
19
|
accept: 'application/json, text/plain, */*',
|
|
22
20
|
},
|
|
23
|
-
maxBodyLength: Infinity,
|
|
24
|
-
maxContentLength: Infinity,
|
|
25
21
|
};
|
|
26
|
-
function throwIfAborted(signal, config, responseData, responseStatus) {
|
|
27
|
-
if (signal?.aborted) {
|
|
28
|
-
throw new index_1.BeeResponseError(config.method || 'get', config.url || '<unknown>', ABORT_ERROR_MESSAGE, responseData, responseStatus, 'ERR_CANCELED');
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
22
|
/**
|
|
32
23
|
* Main function to make HTTP requests.
|
|
33
24
|
* @param options User defined settings
|
|
@@ -37,65 +28,114 @@ async function http(options, config) {
|
|
|
37
28
|
const requestConfig = cafe_utility_1.Objects.deepMerge3(exports.DEFAULT_HTTP_CONFIG, config, options);
|
|
38
29
|
if (options.signal) {
|
|
39
30
|
requestConfig.signal = options.signal;
|
|
40
|
-
throwIfAborted(options.signal, config);
|
|
41
31
|
}
|
|
42
|
-
|
|
32
|
+
attachBody(requestConfig);
|
|
43
33
|
if (requestConfig.params) {
|
|
44
|
-
const
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
if (value === undefined) {
|
|
48
|
-
delete requestConfig.params[key];
|
|
49
|
-
}
|
|
34
|
+
for (const k of Object.keys(requestConfig.params)) {
|
|
35
|
+
if (requestConfig.params[k] === undefined)
|
|
36
|
+
delete requestConfig.params[k];
|
|
50
37
|
}
|
|
51
38
|
}
|
|
39
|
+
const url = buildUrl(requestConfig);
|
|
40
|
+
const method = (requestConfig.method || 'GET').toUpperCase();
|
|
41
|
+
requestConfig.method = method;
|
|
42
|
+
options.onRequest?.({
|
|
43
|
+
method,
|
|
44
|
+
url,
|
|
45
|
+
headers: { ...requestConfig.headers },
|
|
46
|
+
params: requestConfig.params,
|
|
47
|
+
});
|
|
52
48
|
let failedAttempts = 0;
|
|
53
49
|
while (failedAttempts < MAX_FAILED_ATTEMPTS) {
|
|
54
|
-
throwIfAborted(options.signal, config);
|
|
55
50
|
try {
|
|
56
|
-
debug(`${
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
const response = await (0, axios_1.default)(requestConfig);
|
|
62
|
-
return response;
|
|
51
|
+
debug(`${method} ${url}`, { headers: requestConfig.headers, params: requestConfig.params });
|
|
52
|
+
const res = await fetch(url, requestConfig);
|
|
53
|
+
if (!res.ok)
|
|
54
|
+
await throwHttpError(method, url, res, requestConfig.responseType);
|
|
55
|
+
return toBeeResponse(res, requestConfig.responseType);
|
|
63
56
|
}
|
|
64
57
|
catch (e) {
|
|
65
|
-
if (e instanceof
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
await cafe_utility_1.System.sleepMillis(failedAttempts < DELAY_THRESHOLD ? DELAY_FAST : DELAY_SLOW);
|
|
72
|
-
}
|
|
73
|
-
else {
|
|
74
|
-
throw new index_1.BeeResponseError(config.method || 'get', config.url || '<unknown>', e.message, e.response?.data, e.response?.status, e.response?.statusText);
|
|
75
|
-
}
|
|
58
|
+
if (e instanceof index_1.BeeResponseError)
|
|
59
|
+
throw e;
|
|
60
|
+
const err = e;
|
|
61
|
+
if (err.name === 'TimeoutError' && options.endlesslyRetry) {
|
|
62
|
+
failedAttempts++;
|
|
63
|
+
await cafe_utility_1.System.sleepMillis(failedAttempts < FAST_RETRY_COUNT ? DELAY_FAST : DELAY_SLOW);
|
|
76
64
|
}
|
|
77
65
|
else {
|
|
78
|
-
throw
|
|
66
|
+
throw toBeeError(err, method, url);
|
|
79
67
|
}
|
|
80
68
|
}
|
|
81
69
|
}
|
|
82
70
|
throw Error('Max number of failed attempts reached');
|
|
83
71
|
}
|
|
84
|
-
function
|
|
85
|
-
if (
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
}
|
|
72
|
+
function attachBody(config) {
|
|
73
|
+
if (config.data === undefined)
|
|
74
|
+
return;
|
|
75
|
+
const data = config.data;
|
|
76
|
+
const isJsonShape = (data !== null && typeof data === 'object' && data.constructor === Object) || Array.isArray(data);
|
|
77
|
+
if (isJsonShape) {
|
|
78
|
+
config.body = JSON.stringify(data);
|
|
79
|
+
config.headers = { 'content-type': 'application/json', ...config.headers };
|
|
80
|
+
}
|
|
81
|
+
else {
|
|
82
|
+
config.body = data;
|
|
83
|
+
config.duplex = 'half';
|
|
84
|
+
const ct = data instanceof Blob && data.type ? data.type : 'application/octet-stream';
|
|
85
|
+
config.headers = { 'content-type': ct, ...config.headers };
|
|
92
86
|
}
|
|
93
87
|
}
|
|
94
|
-
function
|
|
95
|
-
|
|
96
|
-
|
|
88
|
+
async function throwHttpError(method, url, res, responseType) {
|
|
89
|
+
const errBody = await toBeeResponse(res, responseType).catch(() => ({ data: undefined }));
|
|
90
|
+
const bodyMsg = typeof errBody.data === 'string' ? errBody.data : JSON.stringify(errBody.data);
|
|
91
|
+
const message = bodyMsg && bodyMsg !== 'undefined' ? `${res.statusText}: ${bodyMsg}` : res.statusText;
|
|
92
|
+
throw new index_1.BeeResponseError(method, url, message, errBody.data, res.status, res.statusText);
|
|
93
|
+
}
|
|
94
|
+
function toBeeError(err, method, url) {
|
|
95
|
+
if (err.name === 'AbortError') {
|
|
96
|
+
return new index_1.BeeResponseError(method, url, 'Request aborted', undefined, undefined, 'ERR_CANCELED');
|
|
97
97
|
}
|
|
98
|
-
|
|
99
|
-
|
|
98
|
+
const cause = err.cause;
|
|
99
|
+
const message = cause?.message ? `${err.message}: ${cause.message}` : err.message;
|
|
100
|
+
return new index_1.BeeResponseError(method, url, message);
|
|
101
|
+
}
|
|
102
|
+
async function toBeeResponse(res, responseType = 'json') {
|
|
103
|
+
let data;
|
|
104
|
+
switch (responseType) {
|
|
105
|
+
case 'arraybuffer':
|
|
106
|
+
data = await res.arrayBuffer();
|
|
107
|
+
break;
|
|
108
|
+
case 'text':
|
|
109
|
+
data = await res.text();
|
|
110
|
+
break;
|
|
111
|
+
case 'blob':
|
|
112
|
+
data = await res.blob();
|
|
113
|
+
break;
|
|
114
|
+
case 'stream':
|
|
115
|
+
data = res.body;
|
|
116
|
+
break;
|
|
117
|
+
case 'json':
|
|
118
|
+
default: {
|
|
119
|
+
const text = await res.text();
|
|
120
|
+
data = text ? JSON.parse(text) : null;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
return {
|
|
124
|
+
data: data,
|
|
125
|
+
status: res.status,
|
|
126
|
+
statusText: res.statusText,
|
|
127
|
+
headers: Object.fromEntries(res.headers.entries()),
|
|
128
|
+
raw: res,
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
function buildUrl(config) {
|
|
132
|
+
let url = cafe_utility_1.Strings.joinUrl([config.baseURL ?? '', config.url ?? '']);
|
|
133
|
+
if (config.params) {
|
|
134
|
+
const qs = new URLSearchParams(Object.entries(config.params)
|
|
135
|
+
.filter(([, v]) => v !== undefined)
|
|
136
|
+
.map(([k, v]) => [k, String(v)])).toString();
|
|
137
|
+
if (qs)
|
|
138
|
+
url += `?${qs}`;
|
|
100
139
|
}
|
|
140
|
+
return url;
|
|
101
141
|
}
|
|
@@ -15,10 +15,17 @@ class TarStream {
|
|
|
15
15
|
});
|
|
16
16
|
}
|
|
17
17
|
beginFile(path, size) {
|
|
18
|
-
|
|
19
|
-
|
|
18
|
+
const { name, prefix, longLink } = splitPath(path);
|
|
19
|
+
if (longLink) {
|
|
20
|
+
const encoder = new TextEncoder();
|
|
21
|
+
const pathData = encoder.encode(path + '\0');
|
|
22
|
+
this.pieces.push(createLongLinkHeader(pathData.length));
|
|
23
|
+
this.pieces.push(pathData);
|
|
24
|
+
const padding = pathData.length % 512 === 0 ? 0 : 512 - (pathData.length % 512);
|
|
25
|
+
if (padding > 0)
|
|
26
|
+
this.pieces.push(new Uint8Array(padding));
|
|
20
27
|
}
|
|
21
|
-
const header = createHeader(
|
|
28
|
+
const header = createHeader(name, prefix, size);
|
|
22
29
|
this.pieces.push(header);
|
|
23
30
|
this.currentFileSize = 0;
|
|
24
31
|
}
|
|
@@ -37,7 +44,46 @@ class TarStream {
|
|
|
37
44
|
}
|
|
38
45
|
}
|
|
39
46
|
exports.TarStream = TarStream;
|
|
40
|
-
function
|
|
47
|
+
function splitPath(path) {
|
|
48
|
+
if (path.length <= 100)
|
|
49
|
+
return { name: path, prefix: '', longLink: false };
|
|
50
|
+
for (let i = path.length - 1; i >= 0; i--) {
|
|
51
|
+
if (path[i] === '/') {
|
|
52
|
+
const name = path.substring(i + 1);
|
|
53
|
+
const prefix = path.substring(0, i);
|
|
54
|
+
if (name.length <= 100 && prefix.length <= 155)
|
|
55
|
+
return { name, prefix, longLink: false };
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
// Filename itself is > 100 chars or path > 255 chars — use GNU LongLink
|
|
59
|
+
const lastSlash = path.lastIndexOf('/');
|
|
60
|
+
const truncatedName = (lastSlash >= 0 ? path.substring(lastSlash + 1) : path).slice(0, 100);
|
|
61
|
+
return { name: truncatedName, prefix: '', longLink: true };
|
|
62
|
+
}
|
|
63
|
+
function createLongLinkHeader(size) {
|
|
64
|
+
const encoder = new TextEncoder();
|
|
65
|
+
function writeToBuffer(str, offset, length) {
|
|
66
|
+
const bytes = encoder.encode(str);
|
|
67
|
+
header.set(bytes.slice(0, length), offset);
|
|
68
|
+
}
|
|
69
|
+
const header = new Uint8Array(512);
|
|
70
|
+
header.fill(0);
|
|
71
|
+
writeToBuffer('././@LongLink', 0, 100);
|
|
72
|
+
writeToBuffer('0000644\0', 100, 8);
|
|
73
|
+
writeToBuffer('0000000\0', 108, 8);
|
|
74
|
+
writeToBuffer('0000000\0', 116, 8);
|
|
75
|
+
writeToBuffer(size.toString(8).padStart(11, '0') + '\0', 124, 12);
|
|
76
|
+
writeToBuffer('00000000000\0', 136, 12);
|
|
77
|
+
writeToBuffer(' ', 148, 8);
|
|
78
|
+
writeToBuffer('L', 156, 1);
|
|
79
|
+
writeToBuffer('ustar\0\0', 257, 8);
|
|
80
|
+
let checksum = 0;
|
|
81
|
+
for (let i = 0; i < 512; i++)
|
|
82
|
+
checksum += header[i];
|
|
83
|
+
writeToBuffer(checksum.toString(8).padStart(6, '0') + '\0 ', 148, 8);
|
|
84
|
+
return header;
|
|
85
|
+
}
|
|
86
|
+
function createHeader(name, prefix, size) {
|
|
41
87
|
const encoder = new TextEncoder();
|
|
42
88
|
function writeToBuffer(str, offset, length) {
|
|
43
89
|
const bytes = encoder.encode(str);
|
|
@@ -47,7 +93,7 @@ function createHeader(path, size) {
|
|
|
47
93
|
const header = new Uint8Array(512);
|
|
48
94
|
header.fill(0, 0, 512);
|
|
49
95
|
// File name, truncated to 100 characters if necessary
|
|
50
|
-
writeToBuffer(
|
|
96
|
+
writeToBuffer(name.slice(0, 100).padEnd(100, '\0'), 0, 100);
|
|
51
97
|
// File mode (octal) and null-terminated
|
|
52
98
|
writeToBuffer('0000777\0', 100, 8);
|
|
53
99
|
// UID and GID (octal) and null-terminated
|
|
@@ -64,11 +110,13 @@ function createHeader(path, size) {
|
|
|
64
110
|
writeToBuffer('0', 156, 1);
|
|
65
111
|
// USTAR magic and version
|
|
66
112
|
writeToBuffer('ustar\0\0', 257, 8);
|
|
113
|
+
// UStar prefix field (offset 345, 155 bytes) — used when path > 100 but fits split
|
|
114
|
+
if (prefix)
|
|
115
|
+
writeToBuffer(prefix.slice(0, 155).padEnd(155, '\0'), 345, 155);
|
|
67
116
|
// Calculate checksum
|
|
68
117
|
let checksum = 0;
|
|
69
|
-
for (let i = 0; i < 512; i++)
|
|
118
|
+
for (let i = 0; i < 512; i++)
|
|
70
119
|
checksum += header[i];
|
|
71
|
-
}
|
|
72
120
|
writeToBuffer(checksum.toString(8).padStart(6, '0') + '\0 ', 148, 8);
|
|
73
121
|
return header;
|
|
74
122
|
}
|
package/dist/cjs/utils/tar.js
CHANGED
|
@@ -8,10 +8,16 @@ class TarStream {
|
|
|
8
8
|
this.currentFileSize = 0;
|
|
9
9
|
}
|
|
10
10
|
beginFile(path, size) {
|
|
11
|
-
|
|
12
|
-
|
|
11
|
+
const { name, prefix, longLink } = splitPath(path);
|
|
12
|
+
if (longLink) {
|
|
13
|
+
const pathData = Buffer.from(path + '\0');
|
|
14
|
+
this.output.write(createLongLinkHeader(pathData.length));
|
|
15
|
+
this.output.write(pathData);
|
|
16
|
+
const padding = pathData.length % 512 === 0 ? 0 : 512 - (pathData.length % 512);
|
|
17
|
+
if (padding > 0)
|
|
18
|
+
this.output.write(Buffer.alloc(padding, 0));
|
|
13
19
|
}
|
|
14
|
-
const header = createHeader(
|
|
20
|
+
const header = createHeader(name, prefix, size);
|
|
15
21
|
this.output.write(header);
|
|
16
22
|
this.currentFileSize = 0;
|
|
17
23
|
}
|
|
@@ -44,11 +50,44 @@ class TarStream {
|
|
|
44
50
|
}
|
|
45
51
|
}
|
|
46
52
|
exports.TarStream = TarStream;
|
|
47
|
-
function
|
|
53
|
+
function splitPath(path) {
|
|
54
|
+
if (path.length <= 100)
|
|
55
|
+
return { name: path, prefix: '', longLink: false };
|
|
56
|
+
for (let i = path.length - 1; i >= 0; i--) {
|
|
57
|
+
if (path[i] === '/') {
|
|
58
|
+
const name = path.substring(i + 1);
|
|
59
|
+
const prefix = path.substring(0, i);
|
|
60
|
+
if (name.length <= 100 && prefix.length <= 155)
|
|
61
|
+
return { name, prefix, longLink: false };
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
// Filename itself is > 100 chars or path > 255 chars — use GNU LongLink
|
|
65
|
+
const lastSlash = path.lastIndexOf('/');
|
|
66
|
+
const truncatedName = (lastSlash >= 0 ? path.substring(lastSlash + 1) : path).slice(0, 100);
|
|
67
|
+
return { name: truncatedName, prefix: '', longLink: true };
|
|
68
|
+
}
|
|
69
|
+
function createLongLinkHeader(size) {
|
|
70
|
+
const header = Buffer.alloc(512, 0);
|
|
71
|
+
header.write('././@LongLink', 0, 100);
|
|
72
|
+
header.write('0000644\0', 100, 8);
|
|
73
|
+
header.write('0000000\0', 108, 8);
|
|
74
|
+
header.write('0000000\0', 116, 8);
|
|
75
|
+
header.write(size.toString(8).padStart(11, '0') + '\0', 124, 12);
|
|
76
|
+
header.write('00000000000\0', 136, 12);
|
|
77
|
+
header.write(' ', 148, 8);
|
|
78
|
+
header.write('L', 156, 1);
|
|
79
|
+
header.write('ustar\0\0', 257, 8);
|
|
80
|
+
let checksum = 0;
|
|
81
|
+
for (let i = 0; i < 512; i++)
|
|
82
|
+
checksum += header[i];
|
|
83
|
+
header.write(checksum.toString(8).padStart(6, '0') + '\0 ', 148, 8);
|
|
84
|
+
return header;
|
|
85
|
+
}
|
|
86
|
+
function createHeader(name, prefix, size) {
|
|
48
87
|
// Initialize header with zeros
|
|
49
88
|
const header = Buffer.alloc(512, 0);
|
|
50
89
|
// File name, truncated to 100 characters if necessary
|
|
51
|
-
header.write(
|
|
90
|
+
header.write(name.slice(0, 100).padEnd(100, '\0'), 0, 100);
|
|
52
91
|
// File mode (octal) and null-terminated
|
|
53
92
|
header.write('0000777\0', 100, 8);
|
|
54
93
|
// UID and GID (octal) and null-terminated
|
|
@@ -65,11 +104,13 @@ function createHeader(path, size) {
|
|
|
65
104
|
header.write('0', 156, 1);
|
|
66
105
|
// USTAR magic and version
|
|
67
106
|
header.write('ustar\0\0', 257, 8);
|
|
107
|
+
// UStar prefix field (offset 345, 155 bytes) — used when path > 100 but fits split
|
|
108
|
+
if (prefix)
|
|
109
|
+
header.write(prefix.slice(0, 155).padEnd(155, '\0'), 345, 155);
|
|
68
110
|
// Calculate checksum
|
|
69
111
|
let checksum = 0;
|
|
70
|
-
for (let i = 0; i < 512; i++)
|
|
112
|
+
for (let i = 0; i < 512; i++)
|
|
71
113
|
checksum += header[i];
|
|
72
|
-
}
|
|
73
114
|
header.write(checksum.toString(8).padStart(6, '0') + '\0 ', 148, 8);
|
|
74
115
|
return header;
|
|
75
116
|
}
|
package/dist/cjs/utils/tokens.js
CHANGED
|
@@ -12,6 +12,9 @@ class BZZ {
|
|
|
12
12
|
static fromPLUR(plur) {
|
|
13
13
|
return new BZZ(new cafe_utility_1.FixedPointNumber(plur, BZZ.DIGITS));
|
|
14
14
|
}
|
|
15
|
+
static fromFloat(float) {
|
|
16
|
+
return new BZZ(cafe_utility_1.FixedPointNumber.fromFloat(float, BZZ.DIGITS));
|
|
17
|
+
}
|
|
15
18
|
toPLURString() {
|
|
16
19
|
return this.state.toString();
|
|
17
20
|
}
|
|
@@ -21,6 +24,9 @@ class BZZ {
|
|
|
21
24
|
toDecimalString() {
|
|
22
25
|
return this.state.toDecimalString();
|
|
23
26
|
}
|
|
27
|
+
toFloat() {
|
|
28
|
+
return this.state.toFloat();
|
|
29
|
+
}
|
|
24
30
|
toSignificantDigits(digits) {
|
|
25
31
|
return this.toDecimalString().slice(0, this.toDecimalString().indexOf('.') + digits + 1);
|
|
26
32
|
}
|
|
@@ -82,6 +88,9 @@ class DAI {
|
|
|
82
88
|
static fromWei(wei) {
|
|
83
89
|
return new DAI(new cafe_utility_1.FixedPointNumber(wei, DAI.DIGITS));
|
|
84
90
|
}
|
|
91
|
+
static fromFloat(float) {
|
|
92
|
+
return new DAI(cafe_utility_1.FixedPointNumber.fromFloat(float, DAI.DIGITS));
|
|
93
|
+
}
|
|
85
94
|
toWeiString() {
|
|
86
95
|
return this.state.toString();
|
|
87
96
|
}
|
|
@@ -94,6 +103,9 @@ class DAI {
|
|
|
94
103
|
toSignificantDigits(digits) {
|
|
95
104
|
return this.toDecimalString().slice(0, this.toDecimalString().indexOf('.') + digits + 1);
|
|
96
105
|
}
|
|
106
|
+
toFloat() {
|
|
107
|
+
return this.state.toFloat();
|
|
108
|
+
}
|
|
97
109
|
/**
|
|
98
110
|
* Does not mutate the current DAI instance.
|
|
99
111
|
*
|