bulletin-deploy 0.6.6 → 0.6.7-rc.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/bin/bulletin-deploy +3 -0
- package/dist/{chunk-YB4HKYPR.js → chunk-5B6UCUSH.js} +28 -9
- package/dist/{chunk-BYYVSN7E.js → chunk-DOBGWPA3.js} +5 -2
- package/dist/chunk-GZ5UUECB.js +77 -0
- package/dist/{chunk-7FNQBFFQ.js → chunk-HMCNHEMO.js} +1 -1
- package/dist/deploy.d.ts +5 -1
- package/dist/deploy.js +4 -3
- package/dist/dotns.js +2 -2
- package/dist/index.d.ts +1 -0
- package/dist/index.js +7 -3
- package/dist/merkle.d.ts +7 -0
- package/dist/merkle.js +7 -0
- package/dist/telemetry.js +1 -1
- package/package.json +5 -2
package/bin/bulletin-deploy
CHANGED
|
@@ -16,6 +16,7 @@ for (let i = 0; i < args.length; i++) {
|
|
|
16
16
|
else if (args[i] === "--rpc") { flags.rpc = args[++i]; }
|
|
17
17
|
else if (args[i] === "--password") { flags.password = args[++i]; }
|
|
18
18
|
else if (args[i] === "--playground") { flags.playground = true; }
|
|
19
|
+
else if (args[i] === "--js-merkle") { flags.jsMerkle = true; }
|
|
19
20
|
else if (args[i] === "--version" || args[i] === "-V") { flags.version = true; }
|
|
20
21
|
else if (args[i] === "--help" || args[i] === "-h") { flags.help = true; }
|
|
21
22
|
else { positional.push(args[i]); }
|
|
@@ -39,6 +40,7 @@ Options:
|
|
|
39
40
|
--pool-size N Number of pool accounts (default: 10)
|
|
40
41
|
--password "..." Encrypt SPA content (users will be prompted to decrypt)
|
|
41
42
|
--playground Publish to the playground remix registry
|
|
43
|
+
--js-merkle Use pure-JS merkleization (no IPFS Kubo binary required)
|
|
42
44
|
--version Show version
|
|
43
45
|
--help Show this help`);
|
|
44
46
|
process.exit(0);
|
|
@@ -61,6 +63,7 @@ try {
|
|
|
61
63
|
rpc: flags.rpc,
|
|
62
64
|
poolSize: flags.poolSize,
|
|
63
65
|
password: flags.password,
|
|
66
|
+
jsMerkle: flags.jsMerkle,
|
|
64
67
|
});
|
|
65
68
|
|
|
66
69
|
const output = process.env.GITHUB_OUTPUT;
|
|
@@ -4,7 +4,10 @@ import {
|
|
|
4
4
|
TX_TIMEOUT_MS,
|
|
5
5
|
fetchNonce,
|
|
6
6
|
validateDomainLabel
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-HMCNHEMO.js";
|
|
8
|
+
import {
|
|
9
|
+
merkleizeJS
|
|
10
|
+
} from "./chunk-GZ5UUECB.js";
|
|
8
11
|
import {
|
|
9
12
|
derivePoolAccounts,
|
|
10
13
|
ensureAuthorized,
|
|
@@ -18,7 +21,7 @@ import {
|
|
|
18
21
|
setDeployAttribute,
|
|
19
22
|
withDeploySpan,
|
|
20
23
|
withSpan
|
|
21
|
-
} from "./chunk-
|
|
24
|
+
} from "./chunk-DOBGWPA3.js";
|
|
22
25
|
|
|
23
26
|
// src/deploy.ts
|
|
24
27
|
import { Buffer } from "buffer";
|
|
@@ -778,12 +781,23 @@ async function merkleize(directoryPath, outputCarPath) {
|
|
|
778
781
|
console.log(` CAR: ${(size / 1024 / 1024).toFixed(2)} MB`);
|
|
779
782
|
return { carPath: outputCarPath, cid };
|
|
780
783
|
}
|
|
781
|
-
async function storeDirectory(directoryPath, provider = {}, password) {
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
784
|
+
async function storeDirectory(directoryPath, provider = {}, password, jsMerkle) {
|
|
785
|
+
let carContent;
|
|
786
|
+
let ipfsCid;
|
|
787
|
+
if (jsMerkle) {
|
|
788
|
+
const result = await withSpan("deploy.merkleize", "1a. merkleize (js)", { "deploy.directory": directoryPath }, async () => {
|
|
789
|
+
return merkleizeJS(directoryPath);
|
|
790
|
+
});
|
|
791
|
+
carContent = result.carBytes;
|
|
792
|
+
ipfsCid = result.cid;
|
|
793
|
+
} else {
|
|
794
|
+
const carPath = path.join(path.dirname(directoryPath), `${path.basename(directoryPath)}.car`);
|
|
795
|
+
const { cid } = await withSpan("deploy.merkleize", "1a. merkleize", { "deploy.directory": directoryPath }, async () => {
|
|
796
|
+
return merkleize(directoryPath, carPath);
|
|
797
|
+
});
|
|
798
|
+
ipfsCid = cid;
|
|
799
|
+
carContent = new Uint8Array(fs.readFileSync(carPath));
|
|
800
|
+
}
|
|
787
801
|
if (password) {
|
|
788
802
|
console.log(` Encrypting CAR file...`);
|
|
789
803
|
carContent = await encryptContent(carContent, password);
|
|
@@ -867,7 +881,7 @@ Or deploy with the original account, or use a different domain name.`);
|
|
|
867
881
|
console.log(`
|
|
868
882
|
Mode: Directory`);
|
|
869
883
|
console.log(` Path: ${contentPath}`);
|
|
870
|
-
const dirResult = await storeDirectory(contentPath, providerWithReconnect, options.password);
|
|
884
|
+
const dirResult = await storeDirectory(contentPath, providerWithReconnect, options.password, options.jsMerkle);
|
|
871
885
|
cid = dirResult.storageCid;
|
|
872
886
|
ipfsCid = dirResult.ipfsCid;
|
|
873
887
|
} else {
|
|
@@ -907,6 +921,11 @@ Or deploy with the original account, or use a different domain name.`);
|
|
|
907
921
|
}
|
|
908
922
|
});
|
|
909
923
|
setDeployAttribute("deploy.cid", cid);
|
|
924
|
+
if (options.attributes) {
|
|
925
|
+
for (const [key, value] of Object.entries(options.attributes)) {
|
|
926
|
+
setDeployAttribute(key, value);
|
|
927
|
+
}
|
|
928
|
+
}
|
|
910
929
|
console.log("\n" + "=".repeat(60));
|
|
911
930
|
console.log("DotNS");
|
|
912
931
|
console.log("=".repeat(60));
|
|
@@ -6,7 +6,7 @@ import * as path from "path";
|
|
|
6
6
|
// package.json
|
|
7
7
|
var package_default = {
|
|
8
8
|
name: "bulletin-deploy",
|
|
9
|
-
version: "0.6.
|
|
9
|
+
version: "0.6.7-rc.0",
|
|
10
10
|
private: false,
|
|
11
11
|
repository: {
|
|
12
12
|
type: "git",
|
|
@@ -34,12 +34,13 @@ var package_default = {
|
|
|
34
34
|
"cdm.json"
|
|
35
35
|
],
|
|
36
36
|
scripts: {
|
|
37
|
-
build: "tsup src/index.ts src/deploy.ts src/dotns.ts src/pool.ts src/telemetry.ts --format esm --dts --clean --target node22",
|
|
37
|
+
build: "tsup src/index.ts src/deploy.ts src/dotns.ts src/pool.ts src/telemetry.ts src/merkle.ts --format esm --dts --clean --target node22",
|
|
38
38
|
test: "npm run build && node --test test/test.js",
|
|
39
39
|
benchmark: "npm run build && node benchmark.js"
|
|
40
40
|
},
|
|
41
41
|
dependencies: {
|
|
42
42
|
"@dotdm/cdm": "^0.5.1",
|
|
43
|
+
"@ipld/car": "^5.4.3",
|
|
43
44
|
"@ipld/dag-pb": "^4.1.3",
|
|
44
45
|
"@noble/hashes": "^1.7.2",
|
|
45
46
|
"@polkadot-api/substrate-bindings": "^0.16.5",
|
|
@@ -48,7 +49,9 @@ var package_default = {
|
|
|
48
49
|
"@polkadot/keyring": "^13.0.0",
|
|
49
50
|
"@polkadot/util-crypto": "^13.0.0",
|
|
50
51
|
"@sentry/node": "^9.14.0",
|
|
52
|
+
"blockstore-core": "^6.1.3",
|
|
51
53
|
"ipfs-unixfs": "^11.2.0",
|
|
54
|
+
"ipfs-unixfs-importer": "^16.1.4",
|
|
52
55
|
multiformats: "^13.4.1",
|
|
53
56
|
"polkadot-api": "^1.23.1",
|
|
54
57
|
viem: "^2.30.5"
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
// src/merkle.ts
|
|
2
|
+
import * as fs from "fs";
|
|
3
|
+
import * as path from "path";
|
|
4
|
+
import { importer } from "ipfs-unixfs-importer";
|
|
5
|
+
import { MemoryBlockstore } from "blockstore-core/memory";
|
|
6
|
+
import { CarWriter } from "@ipld/car/writer";
|
|
7
|
+
function walkDirectory(dirPath, prefix = "") {
|
|
8
|
+
let dirents;
|
|
9
|
+
try {
|
|
10
|
+
dirents = fs.readdirSync(dirPath, { withFileTypes: true });
|
|
11
|
+
} catch (err) {
|
|
12
|
+
const code = err.code;
|
|
13
|
+
if (code === "ENOENT") throw new Error(`Directory not found: ${dirPath}`);
|
|
14
|
+
if (code === "ENOTDIR") throw new Error(`Not a directory: ${dirPath}`);
|
|
15
|
+
throw err;
|
|
16
|
+
}
|
|
17
|
+
const entries = [];
|
|
18
|
+
for (const entry of dirents) {
|
|
19
|
+
const fullPath = path.join(dirPath, entry.name);
|
|
20
|
+
const relativePath = prefix ? `${prefix}/${entry.name}` : entry.name;
|
|
21
|
+
if (entry.isDirectory()) {
|
|
22
|
+
entries.push(...walkDirectory(fullPath, relativePath));
|
|
23
|
+
} else if (entry.isFile()) {
|
|
24
|
+
entries.push({ path: relativePath, content: fs.readFileSync(fullPath) });
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
return entries;
|
|
28
|
+
}
|
|
29
|
+
async function collectBytes(iter) {
|
|
30
|
+
const parts = [];
|
|
31
|
+
for await (const chunk of iter) {
|
|
32
|
+
parts.push(chunk);
|
|
33
|
+
}
|
|
34
|
+
const totalLength = parts.reduce((sum, p) => sum + p.length, 0);
|
|
35
|
+
const result = new Uint8Array(totalLength);
|
|
36
|
+
let offset = 0;
|
|
37
|
+
for (const part of parts) {
|
|
38
|
+
result.set(part, offset);
|
|
39
|
+
offset += part.length;
|
|
40
|
+
}
|
|
41
|
+
return result;
|
|
42
|
+
}
|
|
43
|
+
async function merkleizeJS(directoryPath) {
|
|
44
|
+
console.log(` Merkleizing (JS): ${directoryPath}`);
|
|
45
|
+
const files = walkDirectory(directoryPath);
|
|
46
|
+
const blockstore = new MemoryBlockstore();
|
|
47
|
+
const source = files.map((file) => ({
|
|
48
|
+
path: file.path,
|
|
49
|
+
content: (async function* () {
|
|
50
|
+
yield file.content;
|
|
51
|
+
})()
|
|
52
|
+
}));
|
|
53
|
+
let rootCid;
|
|
54
|
+
for await (const entry of importer(source, blockstore, {
|
|
55
|
+
cidVersion: 1,
|
|
56
|
+
rawLeaves: true,
|
|
57
|
+
wrapWithDirectory: true
|
|
58
|
+
})) {
|
|
59
|
+
rootCid = entry.cid;
|
|
60
|
+
}
|
|
61
|
+
if (!rootCid) {
|
|
62
|
+
throw new Error("Merkleization produced no root CID");
|
|
63
|
+
}
|
|
64
|
+
const { writer, out } = CarWriter.create([rootCid]);
|
|
65
|
+
const collectPromise = collectBytes(out);
|
|
66
|
+
for await (const { cid, bytes } of blockstore.getAll()) {
|
|
67
|
+
await writer.put({ cid, bytes: await collectBytes(bytes) });
|
|
68
|
+
}
|
|
69
|
+
await writer.close();
|
|
70
|
+
const carBytes = await collectPromise;
|
|
71
|
+
console.log(` CAR (JS): ${(carBytes.length / 1024 / 1024).toFixed(2)} MB`);
|
|
72
|
+
return { carBytes, cid: rootCid.toString() };
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export {
|
|
76
|
+
merkleizeJS
|
|
77
|
+
};
|
package/dist/deploy.d.ts
CHANGED
|
@@ -49,7 +49,7 @@ declare function merkleize(directoryPath: string, outputCarPath: string): Promis
|
|
|
49
49
|
carPath: string;
|
|
50
50
|
cid: string;
|
|
51
51
|
}>;
|
|
52
|
-
declare function storeDirectory(directoryPath: string, provider?: ExistingProvider, password?: string): Promise<{
|
|
52
|
+
declare function storeDirectory(directoryPath: string, provider?: ExistingProvider, password?: string, jsMerkle?: boolean): Promise<{
|
|
53
53
|
storageCid: string;
|
|
54
54
|
ipfsCid: string;
|
|
55
55
|
}>;
|
|
@@ -63,6 +63,10 @@ interface DeployOptions {
|
|
|
63
63
|
rpc?: string;
|
|
64
64
|
poolSize?: number;
|
|
65
65
|
password?: string;
|
|
66
|
+
/** Use pure-JS merkleization instead of Kubo CLI. Required for WebContainer environments. */
|
|
67
|
+
jsMerkle?: boolean;
|
|
68
|
+
/** Custom telemetry attributes, merged into the deploy span. Overrides auto-detected values. */
|
|
69
|
+
attributes?: Record<string, string>;
|
|
66
70
|
}
|
|
67
71
|
declare function deploy(content: DeployContent, domainName?: string | null, options?: DeployOptions): Promise<DeployResult>;
|
|
68
72
|
|
package/dist/deploy.js
CHANGED
|
@@ -21,10 +21,11 @@ import {
|
|
|
21
21
|
storeChunkedContent,
|
|
22
22
|
storeDirectory,
|
|
23
23
|
storeFile
|
|
24
|
-
} from "./chunk-
|
|
25
|
-
import "./chunk-
|
|
24
|
+
} from "./chunk-5B6UCUSH.js";
|
|
25
|
+
import "./chunk-HMCNHEMO.js";
|
|
26
|
+
import "./chunk-GZ5UUECB.js";
|
|
26
27
|
import "./chunk-LGPTJYA3.js";
|
|
27
|
-
import "./chunk-
|
|
28
|
+
import "./chunk-DOBGWPA3.js";
|
|
28
29
|
import "./chunk-QGM4M3NI.js";
|
|
29
30
|
export {
|
|
30
31
|
DEFAULT_BULLETIN_RPC,
|
package/dist/dotns.js
CHANGED
|
@@ -19,8 +19,8 @@ import {
|
|
|
19
19
|
sanitizeDomainLabel,
|
|
20
20
|
stripTrailingDigits,
|
|
21
21
|
validateDomainLabel
|
|
22
|
-
} from "./chunk-
|
|
23
|
-
import "./chunk-
|
|
22
|
+
} from "./chunk-HMCNHEMO.js";
|
|
23
|
+
import "./chunk-DOBGWPA3.js";
|
|
24
24
|
import "./chunk-QGM4M3NI.js";
|
|
25
25
|
export {
|
|
26
26
|
CONNECTION_TIMEOUT_MS,
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export { DeployContent, DeployOptions, DeployResult, deploy } from './deploy.js';
|
|
2
2
|
export { PoolAccount, PoolAuthorization, bootstrapPool, derivePoolAccounts, ensureAuthorized, fetchPoolAuthorizations, selectAccount } from './pool.js';
|
|
3
3
|
export { DotNS, DotNSConnectOptions, OwnershipResult, PriceValidationResult } from './dotns.js';
|
|
4
|
+
export { MerkleizeResult, merkleizeJS } from './merkle.js';
|
|
4
5
|
import 'multiformats/cid';
|
|
5
6
|
import 'polkadot-api';
|
package/dist/index.js
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
import {
|
|
2
2
|
deploy
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-5B6UCUSH.js";
|
|
4
4
|
import {
|
|
5
5
|
DotNS
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-HMCNHEMO.js";
|
|
7
|
+
import {
|
|
8
|
+
merkleizeJS
|
|
9
|
+
} from "./chunk-GZ5UUECB.js";
|
|
7
10
|
import {
|
|
8
11
|
bootstrapPool,
|
|
9
12
|
derivePoolAccounts,
|
|
@@ -11,7 +14,7 @@ import {
|
|
|
11
14
|
fetchPoolAuthorizations,
|
|
12
15
|
selectAccount
|
|
13
16
|
} from "./chunk-LGPTJYA3.js";
|
|
14
|
-
import "./chunk-
|
|
17
|
+
import "./chunk-DOBGWPA3.js";
|
|
15
18
|
import "./chunk-QGM4M3NI.js";
|
|
16
19
|
export {
|
|
17
20
|
DotNS,
|
|
@@ -20,5 +23,6 @@ export {
|
|
|
20
23
|
derivePoolAccounts,
|
|
21
24
|
ensureAuthorized,
|
|
22
25
|
fetchPoolAuthorizations,
|
|
26
|
+
merkleizeJS,
|
|
23
27
|
selectAccount
|
|
24
28
|
};
|
package/dist/merkle.d.ts
ADDED
package/dist/merkle.js
ADDED
package/dist/telemetry.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "bulletin-deploy",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.7-rc.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -28,12 +28,13 @@
|
|
|
28
28
|
"cdm.json"
|
|
29
29
|
],
|
|
30
30
|
"scripts": {
|
|
31
|
-
"build": "tsup src/index.ts src/deploy.ts src/dotns.ts src/pool.ts src/telemetry.ts --format esm --dts --clean --target node22",
|
|
31
|
+
"build": "tsup src/index.ts src/deploy.ts src/dotns.ts src/pool.ts src/telemetry.ts src/merkle.ts --format esm --dts --clean --target node22",
|
|
32
32
|
"test": "npm run build && node --test test/test.js",
|
|
33
33
|
"benchmark": "npm run build && node benchmark.js"
|
|
34
34
|
},
|
|
35
35
|
"dependencies": {
|
|
36
36
|
"@dotdm/cdm": "^0.5.1",
|
|
37
|
+
"@ipld/car": "^5.4.3",
|
|
37
38
|
"@ipld/dag-pb": "^4.1.3",
|
|
38
39
|
"@noble/hashes": "^1.7.2",
|
|
39
40
|
"@polkadot-api/substrate-bindings": "^0.16.5",
|
|
@@ -42,7 +43,9 @@
|
|
|
42
43
|
"@polkadot/keyring": "^13.0.0",
|
|
43
44
|
"@polkadot/util-crypto": "^13.0.0",
|
|
44
45
|
"@sentry/node": "^9.14.0",
|
|
46
|
+
"blockstore-core": "^6.1.3",
|
|
45
47
|
"ipfs-unixfs": "^11.2.0",
|
|
48
|
+
"ipfs-unixfs-importer": "^16.1.4",
|
|
46
49
|
"multiformats": "^13.4.1",
|
|
47
50
|
"polkadot-api": "^1.23.1",
|
|
48
51
|
"viem": "^2.30.5"
|