permaweb-deploy 3.4.2 → 3.4.4
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/README.md +75 -20
- package/bin/run.js +0 -0
- package/dist/chunks/display-BgIiyBIu.js +60 -0
- package/dist/chunks/display-BgIiyBIu.js.map +1 -0
- package/dist/chunks/upload-workflow-DMKlwZve.js +1067 -0
- package/dist/chunks/upload-workflow-DMKlwZve.js.map +1 -0
- package/dist/chunks/{uploader-DDS_d-O_.js → uploader-CIHu22Fw.js} +5 -1
- package/dist/chunks/uploader-CIHu22Fw.js.map +1 -0
- package/dist/commands/deploy.js +115 -29
- package/dist/commands/deploy.js.map +1 -1
- package/dist/commands/upload.js +49 -7
- package/dist/commands/upload.js.map +1 -1
- package/dist/constants/flags.js +78 -1
- package/dist/constants/flags.js.map +1 -1
- package/dist/src/commands/deploy.d.ts.map +1 -1
- package/dist/src/commands/upload.d.ts.map +1 -1
- package/dist/src/constants/flags.d.ts +40 -1
- package/dist/src/constants/flags.d.ts.map +1 -1
- package/dist/src/types/index.d.ts +1 -1
- package/dist/src/types/index.d.ts.map +1 -1
- package/dist/src/utils/__tests__/display.test.d.ts +2 -0
- package/dist/src/utils/__tests__/display.test.d.ts.map +1 -0
- package/dist/src/utils/__tests__/hyperbeam-uploader.test.d.ts +2 -0
- package/dist/src/utils/__tests__/hyperbeam-uploader.test.d.ts.map +1 -0
- package/dist/src/utils/display.d.ts +5 -0
- package/dist/src/utils/display.d.ts.map +1 -0
- package/dist/src/utils/hyperbeam-uploader.d.ts +93 -0
- package/dist/src/utils/hyperbeam-uploader.d.ts.map +1 -0
- package/dist/src/utils/uploader.d.ts +11 -3
- package/dist/src/utils/uploader.d.ts.map +1 -1
- package/dist/src/workflows/upload-workflow.d.ts +14 -1
- package/dist/src/workflows/upload-workflow.d.ts.map +1 -1
- package/dist/utils/uploader.js +1 -1
- package/dist/workflows/upload-workflow.js +9 -146
- package/dist/workflows/upload-workflow.js.map +1 -1
- package/package.json +27 -24
- package/dist/chunks/uploader-DDS_d-O_.js.map +0 -1
package/README.md
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
# Permaweb Deploy
|
|
2
2
|
|
|
3
|
-
Inspired by the [cookbook github action deployment guide](https://cookbook.arweave.dev/guides/deployment/github-action.html), `permaweb-deploy` is a Node.js command-line tool designed to streamline the deployment of web applications to the permaweb using Arweave. It uploads your build folder or a single file, creates Arweave manifests, and
|
|
3
|
+
Inspired by the [cookbook github action deployment guide](https://cookbook.arweave.dev/guides/deployment/github-action.html), `permaweb-deploy` is a Node.js command-line tool designed to streamline the deployment of web applications to the permaweb using Arweave. It uploads your build folder or a single file, creates Arweave manifests, and can optionally update ArNS (Arweave Name Service) records via ANT (Arweave Name Token) with the transaction ID.
|
|
4
4
|
|
|
5
5
|
## Features
|
|
6
6
|
|
|
7
7
|
- **Turbo SDK Integration:** Uses Turbo SDK for fast, reliable file uploads to Arweave
|
|
8
8
|
- **On-Demand Payment:** Pay with ARIO or Base-ETH tokens on-demand during upload
|
|
9
9
|
- **Arweave Manifest v0.2.0:** Creates manifests with fallback support for SPAs
|
|
10
|
-
- **ArNS Updates:** Updates ArNS records via ANT with new transaction IDs and metadata
|
|
10
|
+
- **Optional ArNS Updates:** Updates ArNS records via ANT with new transaction IDs and metadata
|
|
11
11
|
- **Automated Workflow:** Integrates with GitHub Actions for continuous deployment
|
|
12
12
|
- **Git Hash Tagging:** Automatically tags deployments with Git commit hashes
|
|
13
13
|
- **404 Fallback Detection:** Automatically detects and sets 404.html as fallback
|
|
@@ -77,7 +77,7 @@ Run the deploy command without arguments to be guided through all deployment opt
|
|
|
77
77
|
permaweb-deploy deploy
|
|
78
78
|
```
|
|
79
79
|
|
|
80
|
-
This will prompt you for:
|
|
80
|
+
This uploads to the permaweb by default. Use `--use-arns` or `--arns-name` to run the guided ArNS update flow, which will prompt you for:
|
|
81
81
|
|
|
82
82
|
- ArNS name
|
|
83
83
|
- Wallet method (file, string, or environment variable)
|
|
@@ -91,7 +91,10 @@ Use flags for faster, scriptable deployments:
|
|
|
91
91
|
|
|
92
92
|
```bash
|
|
93
93
|
# Basic deployment with wallet file
|
|
94
|
-
permaweb-deploy deploy --
|
|
94
|
+
permaweb-deploy deploy --wallet ./wallet.json
|
|
95
|
+
|
|
96
|
+
# Deployment with ArNS update
|
|
97
|
+
permaweb-deploy deploy --use-arns --arns-name my-app --wallet ./wallet.json
|
|
95
98
|
```
|
|
96
99
|
|
|
97
100
|
Deploy using private key directly:
|
|
@@ -118,11 +121,12 @@ Deploy a single file:
|
|
|
118
121
|
permaweb-deploy deploy --arns-name my-app --wallet ./wallet.json --deploy-file ./path/to/file.txt
|
|
119
122
|
```
|
|
120
123
|
|
|
121
|
-
### Upload
|
|
124
|
+
### Upload/deploy without ArNS
|
|
122
125
|
|
|
123
|
-
|
|
126
|
+
`deploy` uploads without updating ArNS by default. You can also use the `upload` command explicitly for the same Turbo upload, dedupe cache, and payment options as deploy, minus ArNS flags:
|
|
124
127
|
|
|
125
128
|
```bash
|
|
129
|
+
permaweb-deploy deploy --wallet ./wallet.json --deploy-folder ./dist
|
|
126
130
|
permaweb-deploy upload --wallet ./wallet.json --deploy-folder ./dist
|
|
127
131
|
permaweb-deploy upload --wallet ./wallet.json --deploy-file ./dist/index.html
|
|
128
132
|
DEPLOY_KEY=$(base64 -i wallet.json) permaweb-deploy upload --deploy-folder ./dist
|
|
@@ -189,14 +193,14 @@ permaweb-deploy deploy --arns-name my-app --sig-type ethereum --private-key "0x.
|
|
|
189
193
|
|
|
190
194
|
### Bundler service
|
|
191
195
|
|
|
192
|
-
Uploads go through a
|
|
196
|
+
Uploads go through a bundler service that accepts signed data items and posts them to Arweave. By default, permaweb-deploy uses the [Turbo](https://docs.ardrive.io/docs/turbo/) API and ArDrive’s production bundler (`https://upload.ardrive.io`). **`--uploader`** sets the **base URL** of the bundler service to use (scheme + host; typically no path).
|
|
193
197
|
|
|
194
|
-
| When to use | Example value
|
|
195
|
-
| ------------------------- |
|
|
196
|
-
| **Default** (omit flag) | ArDrive production bundler — same as Turbo CLI defaults
|
|
197
|
-
| **Arweave bundler** | `https://up.arweave.net`
|
|
198
|
-
| **Development / staging** | `https://upload.ardrive.dev`
|
|
199
|
-
| **Custom or self-hosted** | Your own base URL if it implements the
|
|
198
|
+
| When to use | Example value |
|
|
199
|
+
| ------------------------- | ----------------------------------------------------------------- |
|
|
200
|
+
| **Default** (omit flag) | ArDrive production bundler — same as Turbo CLI defaults |
|
|
201
|
+
| **Arweave bundler** | `https://up.arweave.net` |
|
|
202
|
+
| **Development / staging** | `https://upload.ardrive.dev` |
|
|
203
|
+
| **Custom or self-hosted** | Your own base URL if it implements the selected uploader protocol |
|
|
200
204
|
|
|
201
205
|
**Examples:**
|
|
202
206
|
|
|
@@ -207,16 +211,46 @@ permaweb-deploy deploy --arns-name my-app --wallet ./wallet.json --uploader http
|
|
|
207
211
|
permaweb-deploy upload --wallet ./wallet.json --deploy-folder ./dist --uploader https://up.arweave.net
|
|
208
212
|
```
|
|
209
213
|
|
|
214
|
+
To upload through a HyperBEAM bundler, set `--uploader-type hyperbeam` and pass the node URL:
|
|
215
|
+
|
|
216
|
+
```bash
|
|
217
|
+
permaweb-deploy upload \
|
|
218
|
+
--wallet ./wallet.json \
|
|
219
|
+
--deploy-folder ./dist \
|
|
220
|
+
--uploader-type hyperbeam \
|
|
221
|
+
--uploader https://hyperbeam.example.com
|
|
222
|
+
|
|
223
|
+
permaweb-deploy deploy \
|
|
224
|
+
--wallet ./wallet.json \
|
|
225
|
+
--deploy-folder ./dist \
|
|
226
|
+
--uploader-type hyperbeam \
|
|
227
|
+
--uploader https://hyperbeam.example.com
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
If the node follows the standard AO-paid HyperBEAM bundler flow, either command can fund the uploader wallet before uploading:
|
|
231
|
+
|
|
232
|
+
```bash
|
|
233
|
+
permaweb-deploy upload \
|
|
234
|
+
--wallet ./wallet.json \
|
|
235
|
+
--deploy-folder ./dist \
|
|
236
|
+
--uploader-type hyperbeam \
|
|
237
|
+
--uploader https://hyperbeam.example.com \
|
|
238
|
+
--hyperbeam-auto-fund
|
|
239
|
+
```
|
|
240
|
+
|
|
210
241
|
**Notes:**
|
|
211
242
|
|
|
212
|
-
-
|
|
213
|
-
-
|
|
243
|
+
- Turbo billing and signer behavior follow Turbo.
|
|
244
|
+
- HyperBEAM uploads require an Arweave JWK signer. Before uploading, the CLI checks the node address from `/~meta@1.0/info/address` against `https://arweave.net/wallet/<address>/balance` and aborts if the bundler wallet has 0 AR. With `--hyperbeam-auto-fund`, the CLI signs each data item, asks the node's byte-pricing profile for a quote, sends AO to the node deposit address, imports that deposit through `/~ao-payment@1.0/ingest`, and waits for the uploader's balance at `/ledger~node-process@1.0/now/balance/<address>` before uploading. The default route is `/~bundler@1.0/item?codec-device=ans104@1.0`; override it with `--hyperbeam-upload-path` if your node exposes a different bundler route.
|
|
245
|
+
- `--hyperbeam-fund-amount` is an optional override for the minimum local ledger balance to ensure, in AO base units. Without it, `--hyperbeam-auto-fund` uses the node's byte-pricing quote for the signed byte count. Use `--hyperbeam-token-id` only for a non-default AO token process, and `--hyperbeam-ledger-id` only for a non-default local ledger profile.
|
|
246
|
+
- Use a **base URL only** (e.g. `https://up.arweave.net` or `https://hyperbeam.example.com`), not a path to a specific file or route.
|
|
214
247
|
|
|
215
248
|
### Command Options
|
|
216
249
|
|
|
217
|
-
**`deploy`** (ArNS update):
|
|
250
|
+
**`deploy`** (upload by default, optional ArNS update):
|
|
218
251
|
|
|
219
|
-
- `--arns
|
|
252
|
+
- `--use-arns`: Update an ArNS/ANT record after upload
|
|
253
|
+
- `--arns-name, -n`: The ArNS name to update. Required when using `--use-arns`; also implies ArNS mode for backwards compatibility.
|
|
220
254
|
- `--ario-process, -p`: ARIO process to use (`mainnet`, `testnet`, or a custom process ID). Default: `mainnet`
|
|
221
255
|
- `--deploy-folder, -d`: Folder to deploy. Default: `./dist`
|
|
222
256
|
- `--deploy-file, -f`: Deploy a single file instead of a folder
|
|
@@ -229,9 +263,16 @@ permaweb-deploy upload --wallet ./wallet.json --deploy-folder ./dist --uploader
|
|
|
229
263
|
- `--max-token-amount`: Maximum token amount for on-demand payment (used with `--on-demand`)
|
|
230
264
|
- `--no-dedupe`: Disable deduplication (do not cache or reuse previous uploads)
|
|
231
265
|
- `--dedupe-cache-max-entries`: Maximum number of entries to keep in the dedupe cache (LRU). Default: `10000`
|
|
232
|
-
- `--uploader`: Base URL of the
|
|
266
|
+
- `--uploader`: Base URL of the bundler service to use. See [Bundler service](#bundler-service) above.
|
|
267
|
+
- `--uploader-type`: Upload protocol to use (`turbo` or `hyperbeam`). Default: `turbo`
|
|
268
|
+
- `--hyperbeam-upload-path`: HyperBEAM bundler route. Default: `/~bundler@1.0/item?codec-device=ans104@1.0`
|
|
269
|
+
- `--hyperbeam-auto-fund`: Automatically fund the HyperBEAM local ledger before upload
|
|
270
|
+
- `--hyperbeam-fund-amount`: Optional minimum HyperBEAM local ledger balance override, in token base units
|
|
271
|
+
- `--hyperbeam-token-id`: Advanced AO token process ID override
|
|
272
|
+
- `--hyperbeam-ledger-id`: Advanced local HyperBEAM ledger ID override
|
|
273
|
+
- `--hyperbeam-ao-state-url`: AO state endpoint used while waiting for auto-fund transfer assignment. Default: `https://state.forward.computer`
|
|
233
274
|
|
|
234
|
-
**`upload`** (
|
|
275
|
+
**`upload`** (explicit upload without ArNS): accepts `--deploy-folder`, `--deploy-file`, wallet/signer flags, uploader flags, `--on-demand` / `--max-token-amount`, and dedupe flags only.
|
|
235
276
|
|
|
236
277
|
### Deduplication
|
|
237
278
|
|
|
@@ -405,6 +446,20 @@ jobs:
|
|
|
405
446
|
max-token-amount: '2.0'
|
|
406
447
|
```
|
|
407
448
|
|
|
449
|
+
### With HyperBEAM
|
|
450
|
+
|
|
451
|
+
```yaml
|
|
452
|
+
- name: Deploy through a HyperBEAM bundler
|
|
453
|
+
uses: permaweb/permaweb-deploy@v1
|
|
454
|
+
with:
|
|
455
|
+
deploy-key: ${{ secrets.DEPLOY_KEY }}
|
|
456
|
+
arns-name: myapp
|
|
457
|
+
deploy-folder: ./dist
|
|
458
|
+
uploader-type: hyperbeam
|
|
459
|
+
uploader: https://hyperbeam.example.com
|
|
460
|
+
hyperbeam-auto-fund: 'true'
|
|
461
|
+
```
|
|
462
|
+
|
|
408
463
|
### Disabling Deduplication
|
|
409
464
|
|
|
410
465
|
By default, the action caches transaction IDs to avoid re-uploading unchanged files. To disable this:
|
|
@@ -566,7 +621,7 @@ permaweb-deploy/
|
|
|
566
621
|
|
|
567
622
|
- **Dedicated Wallet:** Always use a dedicated wallet for deployments to minimize security risks
|
|
568
623
|
- **Wallet Encoding:** Arweave wallets must be base64 encoded to be used in the deployment script
|
|
569
|
-
- **ArNS Name:**
|
|
624
|
+
- **ArNS Name:** Required only when updating an ANT/ArNS target undername or root record
|
|
570
625
|
- **Turbo Credits:** Ensure your wallet has sufficient Turbo Credits, or use on-demand payment for automatic funding
|
|
571
626
|
- **On-Demand Limits:** Set reasonable `--max-token-amount` limits to prevent unexpected costs
|
|
572
627
|
- **Secret Management:** Keep your `DEPLOY_KEY` secret secure and never commit it to your repository
|
package/bin/run.js
CHANGED
|
File without changes
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import boxen from 'boxen';
|
|
2
|
+
import chalk from 'chalk';
|
|
3
|
+
import Table from 'cli-table3';
|
|
4
|
+
|
|
5
|
+
const AO_BASE_UNITS = 1000000000000n;
|
|
6
|
+
function formatUploadSize(size) {
|
|
7
|
+
return `${(size.signedBytes ?? size.payloadBytes).toLocaleString()} bytes`;
|
|
8
|
+
}
|
|
9
|
+
function formatUploadCost(cost) {
|
|
10
|
+
if (cost.token !== "AO") {
|
|
11
|
+
return `${cost.amount.toString()}`;
|
|
12
|
+
}
|
|
13
|
+
const whole = cost.amount / AO_BASE_UNITS;
|
|
14
|
+
const fraction = cost.amount % AO_BASE_UNITS;
|
|
15
|
+
const decimal = fraction === 0n ? whole.toString() : `${whole.toString()}.${fraction.toString().padStart(12, "0").replaceAll(/0+$/g, "")}`;
|
|
16
|
+
return `${decimal} AO`;
|
|
17
|
+
}
|
|
18
|
+
function fundingDisplay(section) {
|
|
19
|
+
const fundingLine = section.split("\n").map((line) => line.trim()).find((line) => line.startsWith("- "))?.replace(/^- /, "");
|
|
20
|
+
if (!fundingLine) {
|
|
21
|
+
return section;
|
|
22
|
+
}
|
|
23
|
+
return fundingLine.replace(/^AO: send funds to /, "Sending AO to ").replace(/\. Local ledger:.*$/, "");
|
|
24
|
+
}
|
|
25
|
+
function uploadErrorTable(message, title = "Upload failed") {
|
|
26
|
+
const table = new Table({
|
|
27
|
+
style: { head: [] }
|
|
28
|
+
});
|
|
29
|
+
const sections = message.split(/\n{2,}/).map((section) => section.trim()).filter(Boolean);
|
|
30
|
+
for (const [index, section] of sections.entries()) {
|
|
31
|
+
if (index === 0) {
|
|
32
|
+
table.push(["Error", chalk.red(section)]);
|
|
33
|
+
continue;
|
|
34
|
+
}
|
|
35
|
+
if (section.startsWith("Required upload credit:")) {
|
|
36
|
+
table.push([
|
|
37
|
+
"Required upload credit",
|
|
38
|
+
chalk.blue(section.replace(/^Required upload credit:\s*/, ""))
|
|
39
|
+
]);
|
|
40
|
+
continue;
|
|
41
|
+
}
|
|
42
|
+
if (section.startsWith("The HyperBEAM node requires AO")) {
|
|
43
|
+
table.push(["Funding", fundingDisplay(section)]);
|
|
44
|
+
continue;
|
|
45
|
+
}
|
|
46
|
+
table.push(["Note", section]);
|
|
47
|
+
}
|
|
48
|
+
return boxen(`${chalk.red.bold(title)}
|
|
49
|
+
|
|
50
|
+
${table.toString()}`, {
|
|
51
|
+
borderColor: "red",
|
|
52
|
+
borderStyle: "round",
|
|
53
|
+
padding: 1,
|
|
54
|
+
title: chalk.bold("Permaweb Deploy"),
|
|
55
|
+
titleAlignment: "center"
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export { formatUploadCost as a, formatUploadSize as f, uploadErrorTable as u };
|
|
60
|
+
//# sourceMappingURL=display-BgIiyBIu.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"display-BgIiyBIu.js","sources":["../../src/utils/display.ts"],"sourcesContent":["import boxen from 'boxen'\nimport chalk from 'chalk'\n// eslint-disable-next-line import/no-named-as-default\nimport Table from 'cli-table3'\n\nimport type { UploadCost, UploadSize } from './hyperbeam-uploader.js'\n\nconst AO_BASE_UNITS = 1_000_000_000_000n\n\nexport function formatUploadSize(size: UploadSize): string {\n return `${(size.signedBytes ?? size.payloadBytes).toLocaleString()} bytes`\n}\n\nexport function formatUploadCost(cost: UploadCost): string {\n if (cost.token !== 'AO') {\n return `${cost.amount.toString()}`\n }\n\n const whole = cost.amount / AO_BASE_UNITS\n const fraction = cost.amount % AO_BASE_UNITS\n const decimal =\n fraction === 0n\n ? whole.toString()\n : `${whole.toString()}.${fraction.toString().padStart(12, '0').replaceAll(/0+$/g, '')}`\n\n return `${decimal} AO`\n}\n\nfunction fundingDisplay(section: string): string {\n const fundingLine = section\n .split('\\n')\n .map((line) => line.trim())\n .find((line) => line.startsWith('- '))\n ?.replace(/^- /, '')\n\n if (!fundingLine) {\n return section\n }\n\n return fundingLine\n .replace(/^AO: send funds to /, 'Sending AO to ')\n .replace(/\\. Local ledger:.*$/, '')\n}\n\nexport function uploadErrorTable(message: string, title = 'Upload failed'): string {\n const table = new Table({\n style: { head: [] },\n })\n const sections = message\n .split(/\\n{2,}/)\n .map((section) => section.trim())\n .filter(Boolean)\n\n for (const [index, section] of sections.entries()) {\n if (index === 0) {\n table.push(['Error', chalk.red(section)])\n continue\n }\n\n if (section.startsWith('Required upload credit:')) {\n table.push([\n 'Required upload credit',\n chalk.blue(section.replace(/^Required upload credit:\\s*/, '')),\n ])\n continue\n }\n\n if (section.startsWith('The HyperBEAM node requires AO')) {\n table.push(['Funding', fundingDisplay(section)])\n continue\n }\n\n table.push(['Note', section])\n }\n\n return boxen(`${chalk.red.bold(title)}\\n\\n${table.toString()}`, {\n borderColor: 'red',\n borderStyle: 'round',\n padding: 1,\n title: chalk.bold('Permaweb Deploy'),\n titleAlignment: 'center',\n })\n}\n"],"names":[],"mappings":"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"}
|