permaweb-deploy 2.3.0 → 2.4.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/README.md +74 -54
- package/dist/index.js +105 -37
- package/package.json +3 -3
- package/src/index.js +129 -32
- package/src/turbo/index.js +0 -121
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Permaweb Deployment Package
|
|
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
|
|
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 updates ArNS (Arweave Name Service) records via ANT (Arweave Name Token) with the transaction ID.
|
|
4
4
|
|
|
5
5
|
### Features
|
|
6
6
|
|
|
@@ -11,6 +11,7 @@ Inspired by the [cookbook github action deployment guide](https://cookbook.arwea
|
|
|
11
11
|
- **Git Hash Tagging:** Automatically tags deployments with Git commit hashes
|
|
12
12
|
- **404 Fallback Detection:** Automatically detects and sets 404.html as fallback
|
|
13
13
|
- **Network Support:** Supports mainnet, testnet, and custom ARIO process IDs
|
|
14
|
+
- **Flexible Deployment:** Supports deploying a folder or a single file
|
|
14
15
|
|
|
15
16
|
### Installation
|
|
16
17
|
|
|
@@ -34,32 +35,17 @@ yarn add permaweb-deploy --dev --ignore-engines
|
|
|
34
35
|
|
|
35
36
|
### Prerequisites
|
|
36
37
|
|
|
37
|
-
|
|
38
|
+
1. **For Arweave signer (default):** Encode your Arweave wallet key in base64 format and set it as a GitHub secret:
|
|
38
39
|
|
|
39
|
-
1. **Arweave Wallet:** Have an Arweave wallet with Turbo Credits for uploading
|
|
40
|
-
2. **ArNS Name:** Own or control an ArNS name (which has an associated ANT process)
|
|
41
|
-
3. **Wallet Encoding:** Encode your Arweave wallet key in base64 format:
|
|
42
40
|
```bash
|
|
43
41
|
base64 -i wallet.json | pbcopy
|
|
44
42
|
```
|
|
45
|
-
4. **GitHub Secret:** Set the encoded wallet as a GitHub secret named `DEPLOY_KEY`
|
|
46
43
|
|
|
47
|
-
|
|
44
|
+
2. **For Ethereum/Polygon/KYVE signers:** Use your raw private key (no encoding needed) as the `DEPLOY_KEY`.
|
|
48
45
|
|
|
49
|
-
|
|
46
|
+
3. Ensure that the secret name for the encoded wallet or private key is `DEPLOY_KEY`.
|
|
50
47
|
|
|
51
|
-
|
|
52
|
-
permaweb-deploy [options]
|
|
53
|
-
```
|
|
54
|
-
|
|
55
|
-
| Option | Alias | Description | Default | Required |
|
|
56
|
-
| ----------------- | ----- | -------------------------------------- | --------- | -------- |
|
|
57
|
-
| `--arns-name` | `-n` | ArNS name for deployment | - | ✅ |
|
|
58
|
-
| `--ario-process` | `-p` | ARIO process ID or "mainnet"/"testnet" | `mainnet` | ❌ |
|
|
59
|
-
| `--deploy-folder` | `-d` | Folder to deploy | `./dist` | ❌ |
|
|
60
|
-
| `--deploy-file` | `-f` | File to deploy | `./dist` | ❌ |
|
|
61
|
-
| `--undername` | `-u` | ANT undername to update | `@` | ❌ |
|
|
62
|
-
| `--ttl-seconds` | `-t` | ArNS TTL Seconds | `3600` | ❌ |
|
|
48
|
+
⚠️ **Important:** Use a dedicated wallet for deployments to minimize security risks. Ensure your wallet has sufficient Turbo Credits for uploads.
|
|
63
49
|
|
|
64
50
|
### Usage
|
|
65
51
|
|
|
@@ -68,73 +54,107 @@ To deploy your application, ensure you have a build script and a deployment scri
|
|
|
68
54
|
```json
|
|
69
55
|
"scripts": {
|
|
70
56
|
"build": "your-build-command",
|
|
71
|
-
"deploy
|
|
57
|
+
"deploy": "npm run build && permaweb-deploy --arns-name <ARNS_NAME>"
|
|
72
58
|
}
|
|
73
59
|
```
|
|
74
60
|
|
|
75
|
-
|
|
61
|
+
Replace `<ARNS_NAME>` with your ArNS name. To deploy to an undername, add `--undername <UNDERNAME>`.
|
|
76
62
|
|
|
77
|
-
|
|
78
|
-
|
|
63
|
+
#### CLI Options
|
|
64
|
+
|
|
65
|
+
- `--arns-name, -n` (required): The ArNS name to update.
|
|
66
|
+
- `--ario-process, -p`: ARIO process to use (`mainnet`, `testnet`, or a custom process ID). Default: mainnet.
|
|
67
|
+
- `--deploy-folder, -d`: Folder to deploy. Default: `./dist`.
|
|
68
|
+
- `--deploy-file, -f`: Deploy a single file instead of a folder.
|
|
69
|
+
- `--undername, -u`: ANT undername to update. Default: `@`.
|
|
70
|
+
- `--ttl-seconds, -t`: TTL in seconds for the ANT record (60-86400). Default: `3600`.
|
|
71
|
+
- `--sig-type, -s`: Signer type for deployment. Choices: `arweave`, `ethereum`, `polygon`, `kyve`. Default: `arweave`.
|
|
72
|
+
- `--help`: Show all available options and usage examples.
|
|
73
|
+
- `--version`: Show the current version number.
|
|
74
|
+
|
|
75
|
+
#### Example CLI Usage
|
|
76
|
+
|
|
77
|
+
Deploy a folder (default):
|
|
78
|
+
|
|
79
|
+
```sh
|
|
80
|
+
DEPLOY_KEY=$(base64 -i wallet.json) npx permaweb-deploy --arns-name my-app
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
Deploy a specific folder:
|
|
84
|
+
|
|
85
|
+
```sh
|
|
86
|
+
DEPLOY_KEY=$(base64 -i wallet.json) npx permaweb-deploy --arns-name my-app --deploy-folder ./build
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
Deploy a single file:
|
|
90
|
+
|
|
91
|
+
```sh
|
|
92
|
+
DEPLOY_KEY=$(base64 -i wallet.json) npx permaweb-deploy --arns-name my-app --deploy-file ./path/to/file.txt
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
Deploy to an undername:
|
|
96
|
+
|
|
97
|
+
```sh
|
|
98
|
+
DEPLOY_KEY=$(base64 -i wallet.json) npx permaweb-deploy --arns-name my-app --undername staging
|
|
79
99
|
```
|
|
80
100
|
|
|
81
|
-
|
|
101
|
+
Deploy with a custom TTL:
|
|
82
102
|
|
|
83
|
-
|
|
103
|
+
```sh
|
|
104
|
+
DEPLOY_KEY=$(base64 -i wallet.json) npx permaweb-deploy --arns-name my-app --ttl-seconds 7200
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
Deploy using a different signer (e.g., Ethereum):
|
|
108
|
+
|
|
109
|
+
```sh
|
|
110
|
+
DEPLOY_KEY=<ETH_PRIVATE_KEY> npx permaweb-deploy --arns-name my-app --sig-type ethereum
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
#### Example `package.json` Scripts
|
|
84
114
|
|
|
85
115
|
```json
|
|
86
116
|
"scripts": {
|
|
87
|
-
"build": "
|
|
88
|
-
"deploy
|
|
117
|
+
"build": "vite build",
|
|
118
|
+
"deploy": "npm run build && permaweb-deploy --arns-name <ARNS_NAME>"
|
|
89
119
|
}
|
|
90
120
|
```
|
|
91
121
|
|
|
92
|
-
|
|
122
|
+
#### ARIO Process Examples
|
|
123
|
+
|
|
124
|
+
**Mainnet (default):**
|
|
93
125
|
|
|
94
126
|
```json
|
|
95
127
|
"scripts": {
|
|
96
|
-
"
|
|
97
|
-
"deploy-main": "npm run build && permaweb-deploy --arns-name <ARNS_NAME> --ario-process testnet"
|
|
128
|
+
"deploy-main": "npm run build && permaweb-deploy --arns-name <ARNS_NAME>"
|
|
98
129
|
}
|
|
99
130
|
```
|
|
100
131
|
|
|
101
|
-
**
|
|
132
|
+
**Testnet:**
|
|
102
133
|
|
|
103
134
|
```json
|
|
104
135
|
"scripts": {
|
|
105
|
-
"
|
|
106
|
-
"deploy-main": "npm run build && permaweb-deploy --arns-name <ARNS_NAME> --ario-process GaQrvEMKBpkjofgnBi_B3IgIDmY_XYelVLB6GcRGrHc"
|
|
136
|
+
"deploy-test": "npm run build && permaweb-deploy --arns-name <ARNS_NAME> --ario-process testnet"
|
|
107
137
|
}
|
|
108
138
|
```
|
|
109
139
|
|
|
110
|
-
|
|
140
|
+
**Custom process ID:**
|
|
111
141
|
|
|
112
|
-
```
|
|
113
|
-
|
|
142
|
+
```json
|
|
143
|
+
"scripts": {
|
|
144
|
+
"deploy-custom": "npm run build && permaweb-deploy --arns-name <ARNS_NAME> --ario-process <PROCESS_ID>"
|
|
145
|
+
}
|
|
114
146
|
```
|
|
115
147
|
|
|
116
|
-
### Technical Details
|
|
117
|
-
|
|
118
|
-
- **Upload Service:** Uses Turbo SDK for fast, reliable file uploads to Arweave
|
|
119
|
-
- **Manifest Format:** Creates Arweave manifests using version 0.2.0 specification
|
|
120
|
-
- **Fallback Support:** Automatically detects `404.html` and sets it as fallback, otherwise uses `index.html`
|
|
121
|
-
- **Upload Timeout:** 10-second timeout per file upload for reliability
|
|
122
|
-
- **ArNS Record TTL:** Sets 3600 seconds (1 hour) TTL for ArNS records via ANT
|
|
123
|
-
- **Deployment Tags:** Automatically adds `App-Name: Permaweb-Deploy` and Git hash tags
|
|
124
|
-
- **Network Support:** Supports mainnet, testnet, and custom ARIO process IDs
|
|
125
|
-
|
|
126
148
|
### GitHub Actions Workflow
|
|
127
149
|
|
|
128
150
|
To automate the deployment, set up a GitHub Actions workflow as follows:
|
|
129
151
|
|
|
130
152
|
```yaml
|
|
131
|
-
name:
|
|
132
|
-
|
|
153
|
+
name: Deploy to Permaweb
|
|
133
154
|
on:
|
|
134
155
|
push:
|
|
135
156
|
branches:
|
|
136
|
-
-
|
|
137
|
-
|
|
157
|
+
- main
|
|
138
158
|
jobs:
|
|
139
159
|
publish:
|
|
140
160
|
runs-on: ubuntu-latest
|
|
@@ -144,15 +164,16 @@ jobs:
|
|
|
144
164
|
with:
|
|
145
165
|
node-version: 20.x
|
|
146
166
|
- run: npm install
|
|
147
|
-
- run: npm run deploy
|
|
167
|
+
- run: npm run deploy
|
|
148
168
|
env:
|
|
149
169
|
DEPLOY_KEY: ${{ secrets.DEPLOY_KEY }}
|
|
150
170
|
```
|
|
151
171
|
|
|
172
|
+
|
|
152
173
|
### Security & Best Practices
|
|
153
174
|
|
|
154
175
|
- **Dedicated Wallet:** Always use a dedicated wallet for deployments to minimize security risks
|
|
155
|
-
- **Wallet Encoding:**
|
|
176
|
+
- **Wallet Encoding:** Arweave wallets must be base64 encoded to be used in the deployment script
|
|
156
177
|
- **ArNS Name:** The ArNS Name must be passed so that the ANT Process can be resolved to update the target undername or root record
|
|
157
178
|
- **Turbo Credits:** Ensure your wallet has sufficient Turbo Credits before deployment
|
|
158
179
|
- **Secret Management:** Keep your `DEPLOY_KEY` secret secure and never commit it to your repository
|
|
@@ -173,5 +194,4 @@ jobs:
|
|
|
173
194
|
- **@ar.io/sdk:** - For ANT operations and ArNS management
|
|
174
195
|
- **@ardrive/turbo-sdk:** - For fast file uploads to Arweave
|
|
175
196
|
- **@permaweb/aoconnect:** - For AO network connectivity
|
|
176
|
-
- **mime-types:** - For automatic content type detection
|
|
177
197
|
- **yargs:** - For CLI argument parsing
|
package/dist/index.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
"use strict";
|
|
3
3
|
|
|
4
|
+
var _turboSdk = require("@ardrive/turbo-sdk");
|
|
4
5
|
var _fs = _interopRequireDefault(require("fs"));
|
|
5
6
|
var _yargs = _interopRequireDefault(require("yargs"));
|
|
6
7
|
var _helpers = require("yargs/helpers");
|
|
8
|
+
var _mimeTypes = _interopRequireDefault(require("mime-types"));
|
|
7
9
|
var _sdk = require("@ar.io/sdk");
|
|
8
|
-
var _turboSdk = require("@ardrive/turbo-sdk");
|
|
9
10
|
var _aoconnect = require("@permaweb/aoconnect");
|
|
10
|
-
var _turbo = require("./turbo");
|
|
11
11
|
function _interopRequireDefault(e) { return e && e.__esModule ? e : { "default": e }; }
|
|
12
12
|
function _regenerator() { /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/babel/babel/blob/main/packages/babel-helpers/LICENSE */ var e, t, r = "function" == typeof Symbol ? Symbol : {}, n = r.iterator || "@@iterator", o = r.toStringTag || "@@toStringTag"; function i(r, n, o, i) { var c = n && n.prototype instanceof Generator ? n : Generator, u = Object.create(c.prototype); return _regeneratorDefine2(u, "_invoke", function (r, n, o) { var i, c, u, f = 0, p = o || [], y = !1, G = { p: 0, n: 0, v: e, a: d, f: d.bind(e, 4), d: function d(t, r) { return i = t, c = 0, u = e, G.n = r, a; } }; function d(r, n) { for (c = r, u = n, t = 0; !y && f && !o && t < p.length; t++) { var o, i = p[t], d = G.p, l = i[2]; r > 3 ? (o = l === n) && (u = i[(c = i[4]) ? 5 : (c = 3, 3)], i[4] = i[5] = e) : i[0] <= d && ((o = r < 2 && d < i[1]) ? (c = 0, G.v = n, G.n = i[1]) : d < l && (o = r < 3 || i[0] > n || n > l) && (i[4] = r, i[5] = n, G.n = l, c = 0)); } if (o || r > 1) return a; throw y = !0, n; } return function (o, p, l) { if (f > 1) throw TypeError("Generator is already running"); for (y && 1 === p && d(p, l), c = p, u = l; (t = c < 2 ? e : u) || !y;) { i || (c ? c < 3 ? (c > 1 && (G.n = -1), d(c, u)) : G.n = u : G.v = u); try { if (f = 2, i) { if (c || (o = "next"), t = i[o]) { if (!(t = t.call(i, u))) throw TypeError("iterator result is not an object"); if (!t.done) return t; u = t.value, c < 2 && (c = 0); } else 1 === c && (t = i["return"]) && t.call(i), c < 2 && (u = TypeError("The iterator does not provide a '" + o + "' method"), c = 1); i = e; } else if ((t = (y = G.n < 0) ? u : r.call(n, G)) !== a) break; } catch (t) { i = e, c = 1, u = t; } finally { f = 1; } } return { value: t, done: y }; }; }(r, o, i), !0), u; } var a = {}; function Generator() {} function GeneratorFunction() {} function GeneratorFunctionPrototype() {} t = Object.getPrototypeOf; var c = [][n] ? t(t([][n]())) : (_regeneratorDefine2(t = {}, n, function () { return this; }), t), u = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(c); function f(e) { return Object.setPrototypeOf ? Object.setPrototypeOf(e, GeneratorFunctionPrototype) : (e.__proto__ = GeneratorFunctionPrototype, _regeneratorDefine2(e, o, "GeneratorFunction")), e.prototype = Object.create(u), e; } return GeneratorFunction.prototype = GeneratorFunctionPrototype, _regeneratorDefine2(u, "constructor", GeneratorFunctionPrototype), _regeneratorDefine2(GeneratorFunctionPrototype, "constructor", GeneratorFunction), GeneratorFunction.displayName = "GeneratorFunction", _regeneratorDefine2(GeneratorFunctionPrototype, o, "GeneratorFunction"), _regeneratorDefine2(u), _regeneratorDefine2(u, o, "Generator"), _regeneratorDefine2(u, n, function () { return this; }), _regeneratorDefine2(u, "toString", function () { return "[object Generator]"; }), (_regenerator = function _regenerator() { return { w: i, m: f }; })(); }
|
|
13
13
|
function _regeneratorDefine2(e, r, n, t) { var i = Object.defineProperty; try { i({}, "", {}); } catch (e) { i = 0; } _regeneratorDefine2 = function _regeneratorDefine(e, r, n, t) { if (r) i ? i(e, r, { value: n, enumerable: !t, configurable: !t, writable: !t }) : e[r] = n;else { var o = function o(r, n) { _regeneratorDefine2(e, r, function (e) { return this._invoke(r, n, e); }); }; o("next", 0), o("throw", 1), o("return", 2); } }, _regeneratorDefine2(e, r, n, t); }
|
|
@@ -20,7 +20,7 @@ function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length)
|
|
|
20
20
|
function asyncGeneratorStep(n, t, e, r, o, a, c) { try { var i = n[a](c), u = i.value; } catch (n) { return void e(n); } i.done ? t(u) : Promise.resolve(u).then(r, o); }
|
|
21
21
|
function _asyncToGenerator(n) { return function () { var t = this, e = arguments; return new Promise(function (r, o) { var a = n.apply(t, e); function _next(n) { asyncGeneratorStep(a, r, o, _next, _throw, "next", n); } function _throw(n) { asyncGeneratorStep(a, r, o, _next, _throw, "throw", n); } _next(void 0); }); }; }
|
|
22
22
|
var arweaveTxIdRegex = /^[a-zA-Z0-9-_]{43}$/;
|
|
23
|
-
var argv = (0, _yargs["default"])((0, _helpers.hideBin)(process.argv)).option('ario-process', {
|
|
23
|
+
var argv = (0, _yargs["default"])((0, _helpers.hideBin)(process.argv)).version('2.1.0').help().usage('Usage: $0 --arns-name <name> [options]').example('$0 --arns-name my-app', 'Deploy to my-app.arweave.dev').example('$0 --arns-name my-app --undername staging', 'Deploy to staging.my-app.arweave.dev').option('ario-process', {
|
|
24
24
|
alias: 'p',
|
|
25
25
|
type: 'string',
|
|
26
26
|
description: 'The ARIO process to use',
|
|
@@ -50,18 +50,31 @@ var argv = (0, _yargs["default"])((0, _helpers.hideBin)(process.argv)).option('a
|
|
|
50
50
|
type: 'string',
|
|
51
51
|
description: 'ANT undername to update.',
|
|
52
52
|
"default": '@'
|
|
53
|
+
}).option('sig-type', {
|
|
54
|
+
alias: 's',
|
|
55
|
+
type: 'string',
|
|
56
|
+
description: 'The type of signer to be used for deployment.',
|
|
57
|
+
choices: ['arweave', 'ethereum', 'polygon',
|
|
58
|
+
// 'solana',
|
|
59
|
+
'kyve'],
|
|
60
|
+
"default": 'arweave'
|
|
61
|
+
}).check(function (argv) {
|
|
62
|
+
if (argv.ttl < 60 || argv.ttl > 86400) {
|
|
63
|
+
throw new Error('TTL must be between 60 seconds (1 minute) and 86400 seconds (1 day)');
|
|
64
|
+
}
|
|
65
|
+
return true;
|
|
53
66
|
}).argv;
|
|
54
67
|
var DEPLOY_KEY = process.env.DEPLOY_KEY;
|
|
55
|
-
var ARNS_NAME = argv
|
|
56
|
-
var
|
|
57
|
-
var
|
|
68
|
+
var ARNS_NAME = argv['arns-name'];
|
|
69
|
+
var ARIO_PROCESS = argv['ario-process'];
|
|
70
|
+
var TTL_SECONDS = argv['ttl-seconds'];
|
|
58
71
|
if (ARIO_PROCESS === 'mainnet') {
|
|
59
72
|
ARIO_PROCESS = _sdk.ARIO_MAINNET_PROCESS_ID;
|
|
60
73
|
} else if (ARIO_PROCESS === 'testnet') {
|
|
61
74
|
ARIO_PROCESS = _sdk.ARIO_TESTNET_PROCESS_ID;
|
|
62
75
|
}
|
|
63
76
|
_asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee() {
|
|
64
|
-
var
|
|
77
|
+
var ario, arnsNameRecord, signer, token, jwk, turbo, uploadResult, txOrManifestId, mimeType, ant, _t, _t2;
|
|
65
78
|
return _regenerator().w(function (_context) {
|
|
66
79
|
while (1) switch (_context.n) {
|
|
67
80
|
case 0:
|
|
@@ -94,7 +107,6 @@ _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee() {
|
|
|
94
107
|
console.error('undername must be set');
|
|
95
108
|
process.exit(1);
|
|
96
109
|
}
|
|
97
|
-
jwk = JSON.parse(Buffer.from(DEPLOY_KEY, 'base64').toString('utf-8'));
|
|
98
110
|
ario = _sdk.ARIO.init({
|
|
99
111
|
process: new _sdk.AOProcess({
|
|
100
112
|
processId: ARIO_PROCESS,
|
|
@@ -114,43 +126,99 @@ _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee() {
|
|
|
114
126
|
case 1:
|
|
115
127
|
arnsNameRecord = _context.v;
|
|
116
128
|
_context.p = 2;
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
break;
|
|
120
|
-
}
|
|
121
|
-
turbo = _turboSdk.TurboFactory.authenticated({
|
|
122
|
-
privateKey: jwk
|
|
123
|
-
});
|
|
124
|
-
_context.n = 3;
|
|
125
|
-
return (0, _turbo.uploadFile)(argv.deployFile, turbo);
|
|
126
|
-
case 3:
|
|
127
|
-
txId = _context.v.id;
|
|
128
|
-
_context.n = 6;
|
|
129
|
+
_t = argv['sig-type'];
|
|
130
|
+
_context.n = _t === 'ethereum' ? 3 : _t === 'polygon' ? 4 : _t === 'arweave' ? 5 : _t === 'kyve' ? 6 : 7;
|
|
129
131
|
break;
|
|
132
|
+
case 3:
|
|
133
|
+
signer = new _turboSdk.EthereumSigner(DEPLOY_KEY);
|
|
134
|
+
token = 'ethereum';
|
|
135
|
+
return _context.a(3, 8);
|
|
130
136
|
case 4:
|
|
131
|
-
|
|
132
|
-
|
|
137
|
+
signer = new _turboSdk.EthereumSigner(DEPLOY_KEY);
|
|
138
|
+
token = 'pol';
|
|
139
|
+
return _context.a(3, 8);
|
|
133
140
|
case 5:
|
|
134
|
-
|
|
141
|
+
jwk = JSON.parse(Buffer.from(DEPLOY_KEY, 'base64').toString('utf-8'));
|
|
142
|
+
signer = new _sdk.ArweaveSigner(jwk);
|
|
143
|
+
token = 'arweave';
|
|
144
|
+
return _context.a(3, 8);
|
|
135
145
|
case 6:
|
|
146
|
+
signer = new _turboSdk.EthereumSigner(DEPLOY_KEY);
|
|
147
|
+
token = 'kyve';
|
|
148
|
+
return _context.a(3, 8);
|
|
149
|
+
case 7:
|
|
150
|
+
throw new Error("Invalid sig-type provided: ".concat(argv['sig-type'], ". Allowed values are 'arweave', 'ethereum', 'polygon', or 'kyve'."));
|
|
151
|
+
case 8:
|
|
152
|
+
turbo = _turboSdk.TurboFactory.authenticated({
|
|
153
|
+
signer: signer,
|
|
154
|
+
token: token
|
|
155
|
+
});
|
|
156
|
+
if (!argv['deploy-file']) {
|
|
157
|
+
_context.n = 10;
|
|
158
|
+
break;
|
|
159
|
+
}
|
|
160
|
+
// Detect MIME type for the file
|
|
161
|
+
mimeType = _mimeTypes["default"].lookup(argv['deploy-file']) || 'application/octet-stream';
|
|
162
|
+
_context.n = 9;
|
|
163
|
+
return turbo.uploadFile({
|
|
164
|
+
file: argv['deploy-file'],
|
|
165
|
+
dataItemOpts: {
|
|
166
|
+
tags: [{
|
|
167
|
+
name: 'App-Name',
|
|
168
|
+
value: 'Permaweb-Deploy'
|
|
169
|
+
},
|
|
170
|
+
// prevents identical transaction Ids from eth wallets
|
|
171
|
+
{
|
|
172
|
+
name: 'anchor',
|
|
173
|
+
value: new Date().toISOString()
|
|
174
|
+
}, {
|
|
175
|
+
name: 'Content-Type',
|
|
176
|
+
value: mimeType
|
|
177
|
+
}]
|
|
178
|
+
}
|
|
179
|
+
});
|
|
180
|
+
case 9:
|
|
181
|
+
uploadResult = _context.v;
|
|
182
|
+
txOrManifestId = uploadResult.id;
|
|
183
|
+
_context.n = 12;
|
|
184
|
+
break;
|
|
185
|
+
case 10:
|
|
186
|
+
_context.n = 11;
|
|
187
|
+
return turbo.uploadFolder({
|
|
188
|
+
folderPath: argv['deploy-folder'],
|
|
189
|
+
dataItemOpts: {
|
|
190
|
+
tags: [{
|
|
191
|
+
name: 'App-Name',
|
|
192
|
+
value: 'Permaweb-Deploy'
|
|
193
|
+
},
|
|
194
|
+
// prevents identical transaction Ids from eth wallets
|
|
195
|
+
{
|
|
196
|
+
name: 'anchor',
|
|
197
|
+
value: new Date().toISOString()
|
|
198
|
+
}]
|
|
199
|
+
}
|
|
200
|
+
});
|
|
201
|
+
case 11:
|
|
202
|
+
uploadResult = _context.v;
|
|
203
|
+
txOrManifestId = uploadResult.manifestResponse.id;
|
|
204
|
+
case 12:
|
|
136
205
|
console.log('-------------------- DEPLOY DETAILS --------------------');
|
|
137
|
-
console.log("Tx ID: ".concat(
|
|
206
|
+
console.log("Tx ID: ".concat(txOrManifestId));
|
|
138
207
|
console.log("ArNS Name: ".concat(ARNS_NAME));
|
|
139
208
|
console.log("Undername: ".concat(argv.undername));
|
|
140
209
|
console.log("ANT: ".concat(arnsNameRecord.processId));
|
|
141
210
|
console.log("AR IO Process: ".concat(ARIO_PROCESS));
|
|
142
211
|
console.log("TTL Seconds: ".concat(TTL_SECONDS));
|
|
143
212
|
console.log('--------------------------------------------------------');
|
|
144
|
-
signer = new _sdk.ArweaveSigner(jwk);
|
|
145
213
|
ant = _sdk.ANT.init({
|
|
146
214
|
processId: arnsNameRecord.processId,
|
|
147
215
|
signer: signer
|
|
148
216
|
}); // Update the ANT record (assumes the JWK is a controller or owner)
|
|
149
|
-
_context.n =
|
|
217
|
+
_context.n = 13;
|
|
150
218
|
return ant.setRecord({
|
|
151
219
|
undername: argv.undername,
|
|
152
|
-
transactionId:
|
|
153
|
-
ttlSeconds:
|
|
220
|
+
transactionId: txOrManifestId,
|
|
221
|
+
ttlSeconds: argv['ttl-seconds']
|
|
154
222
|
}, {
|
|
155
223
|
tags: [{
|
|
156
224
|
name: 'App-Name',
|
|
@@ -160,17 +228,17 @@ _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee() {
|
|
|
160
228
|
value: process.env.GITHUB_SHA
|
|
161
229
|
}] : []))
|
|
162
230
|
});
|
|
163
|
-
case
|
|
164
|
-
console.log("Deployed TxId [".concat(
|
|
165
|
-
_context.n =
|
|
231
|
+
case 13:
|
|
232
|
+
console.log("Deployed TxId [".concat(txOrManifestId, "] to name [").concat(ARNS_NAME, "] for ANT [").concat(arnsNameRecord.processId, "] using undername [").concat(argv.undername, "]"));
|
|
233
|
+
_context.n = 15;
|
|
166
234
|
break;
|
|
167
|
-
case
|
|
168
|
-
_context.p =
|
|
169
|
-
|
|
170
|
-
console.error('Deployment failed:',
|
|
235
|
+
case 14:
|
|
236
|
+
_context.p = 14;
|
|
237
|
+
_t2 = _context.v;
|
|
238
|
+
console.error('Deployment failed:', _t2);
|
|
171
239
|
process.exit(1); // Exit with error code
|
|
172
|
-
case
|
|
240
|
+
case 15:
|
|
173
241
|
return _context.a(2);
|
|
174
242
|
}
|
|
175
|
-
}, _callee, null, [[2,
|
|
243
|
+
}, _callee, null, [[2, 14]]);
|
|
176
244
|
}))();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "permaweb-deploy",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.4.0",
|
|
4
4
|
"description": "Permaweb App Deployment Package",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -11,9 +11,9 @@
|
|
|
11
11
|
},
|
|
12
12
|
"dependencies": {
|
|
13
13
|
"@ar.io/sdk": "^3.10.1",
|
|
14
|
-
"@ardrive/turbo-sdk": "^1.
|
|
14
|
+
"@ardrive/turbo-sdk": "^1.28.2",
|
|
15
15
|
"@permaweb/aoconnect": "^0.0.85",
|
|
16
|
-
"mime-types": "^
|
|
16
|
+
"mime-types": "^3.0.1",
|
|
17
17
|
"yargs": "17.7.2"
|
|
18
18
|
},
|
|
19
19
|
"devDependencies": {
|
package/src/index.js
CHANGED
|
@@ -1,24 +1,27 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
|
|
2
|
+
import { EthereumSigner, TurboFactory } from '@ardrive/turbo-sdk';
|
|
3
3
|
import fs from 'fs';
|
|
4
4
|
import yargs from 'yargs';
|
|
5
5
|
import { hideBin } from 'yargs/helpers';
|
|
6
|
+
import mime from 'mime-types';
|
|
6
7
|
|
|
7
8
|
import { ANT, AOProcess, ARIO, ARIO_MAINNET_PROCESS_ID, ARIO_TESTNET_PROCESS_ID, ArweaveSigner } from '@ar.io/sdk';
|
|
8
|
-
import { TurboFactory } from '@ardrive/turbo-sdk';
|
|
9
9
|
import { connect } from '@permaweb/aoconnect';
|
|
10
10
|
|
|
11
|
-
import { uploadDirectory, uploadFile } from './turbo';
|
|
12
|
-
|
|
13
11
|
const arweaveTxIdRegex = /^[a-zA-Z0-9-_]{43}$/;
|
|
14
12
|
|
|
15
13
|
const argv = yargs(hideBin(process.argv))
|
|
14
|
+
.version('2.1.0')
|
|
15
|
+
.help()
|
|
16
|
+
.usage('Usage: $0 --arns-name <name> [options]')
|
|
17
|
+
.example('$0 --arns-name my-app', 'Deploy to my-app.arweave.dev')
|
|
18
|
+
.example('$0 --arns-name my-app --undername staging', 'Deploy to staging.my-app.arweave.dev')
|
|
16
19
|
.option('ario-process', {
|
|
17
20
|
alias: 'p',
|
|
18
21
|
type: 'string',
|
|
19
22
|
description: 'The ARIO process to use',
|
|
20
23
|
demandOption: true,
|
|
21
|
-
default: ARIO_MAINNET_PROCESS_ID
|
|
24
|
+
default: ARIO_MAINNET_PROCESS_ID,
|
|
22
25
|
})
|
|
23
26
|
.option('arns-name', {
|
|
24
27
|
alias: 'n',
|
|
@@ -35,25 +38,45 @@ const argv = yargs(hideBin(process.argv))
|
|
|
35
38
|
.option('deploy-file', {
|
|
36
39
|
alias: 'f',
|
|
37
40
|
type: 'string',
|
|
38
|
-
description: 'File to deploy.'
|
|
41
|
+
description: 'File to deploy.',
|
|
39
42
|
})
|
|
40
43
|
.option('ttl-seconds', {
|
|
41
44
|
alias: 't',
|
|
42
45
|
type: 'number',
|
|
43
46
|
description: 'ArNS TTL Seconds',
|
|
44
|
-
default: 3600
|
|
47
|
+
default: 3600,
|
|
45
48
|
})
|
|
46
49
|
.option('undername', {
|
|
47
50
|
alias: 'u',
|
|
48
51
|
type: 'string',
|
|
49
52
|
description: 'ANT undername to update.',
|
|
50
53
|
default: '@',
|
|
54
|
+
})
|
|
55
|
+
.option('sig-type', {
|
|
56
|
+
alias: 's',
|
|
57
|
+
type: 'string',
|
|
58
|
+
description: 'The type of signer to be used for deployment.',
|
|
59
|
+
choices: [
|
|
60
|
+
'arweave',
|
|
61
|
+
'ethereum',
|
|
62
|
+
'polygon',
|
|
63
|
+
// 'solana',
|
|
64
|
+
'kyve',
|
|
65
|
+
],
|
|
66
|
+
default: 'arweave',
|
|
67
|
+
})
|
|
68
|
+
.check((argv) => {
|
|
69
|
+
if (argv.ttl < 60 || argv.ttl > 86400) {
|
|
70
|
+
throw new Error('TTL must be between 60 seconds (1 minute) and 86400 seconds (1 day)');
|
|
71
|
+
}
|
|
72
|
+
return true;
|
|
51
73
|
}).argv;
|
|
52
74
|
|
|
53
75
|
const DEPLOY_KEY = process.env.DEPLOY_KEY;
|
|
54
|
-
const ARNS_NAME = argv
|
|
55
|
-
|
|
56
|
-
|
|
76
|
+
const ARNS_NAME = argv['arns-name'];
|
|
77
|
+
let ARIO_PROCESS = argv['ario-process'];
|
|
78
|
+
const TTL_SECONDS = argv['ttl-seconds'];
|
|
79
|
+
|
|
57
80
|
if (ARIO_PROCESS === 'mainnet') {
|
|
58
81
|
ARIO_PROCESS = ARIO_MAINNET_PROCESS_ID;
|
|
59
82
|
} else if (ARIO_PROCESS === 'testnet') {
|
|
@@ -84,8 +107,7 @@ if (ARIO_PROCESS === 'mainnet') {
|
|
|
84
107
|
if (argv.deployFile && !fs.existsSync(argv.deployFile)) {
|
|
85
108
|
console.error(`deploy-file [${argv.deployFolder}] does not exist`);
|
|
86
109
|
process.exit(1);
|
|
87
|
-
}
|
|
88
|
-
else {
|
|
110
|
+
} else {
|
|
89
111
|
if (!fs.existsSync(argv.deployFolder)) {
|
|
90
112
|
console.error(`deploy-folder [${argv.deployFolder}] does not exist`);
|
|
91
113
|
process.exit(1);
|
|
@@ -97,15 +119,14 @@ if (ARIO_PROCESS === 'mainnet') {
|
|
|
97
119
|
process.exit(1);
|
|
98
120
|
}
|
|
99
121
|
|
|
100
|
-
const jwk = JSON.parse(Buffer.from(DEPLOY_KEY, 'base64').toString('utf-8'));
|
|
101
122
|
const ario = ARIO.init({
|
|
102
123
|
process: new AOProcess({
|
|
103
124
|
processId: ARIO_PROCESS,
|
|
104
125
|
ao: connect({
|
|
105
126
|
MODE: 'legacy',
|
|
106
|
-
CU_URL: 'https://cu.ardrive.io'
|
|
107
|
-
})
|
|
108
|
-
})
|
|
127
|
+
CU_URL: 'https://cu.ardrive.io',
|
|
128
|
+
}),
|
|
129
|
+
}),
|
|
109
130
|
});
|
|
110
131
|
|
|
111
132
|
const arnsNameRecord = await ario.getArNSRecord({ name: ARNS_NAME }).catch((e) => {
|
|
@@ -114,17 +135,88 @@ if (ARIO_PROCESS === 'mainnet') {
|
|
|
114
135
|
});
|
|
115
136
|
|
|
116
137
|
try {
|
|
117
|
-
let
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
138
|
+
let signer;
|
|
139
|
+
let token;
|
|
140
|
+
|
|
141
|
+
// Creates the proper signer based on the sig-type value
|
|
142
|
+
switch (argv['sig-type']) {
|
|
143
|
+
case 'ethereum':
|
|
144
|
+
signer = new EthereumSigner(DEPLOY_KEY);
|
|
145
|
+
token = 'ethereum';
|
|
146
|
+
break;
|
|
147
|
+
case 'polygon':
|
|
148
|
+
signer = new EthereumSigner(DEPLOY_KEY);
|
|
149
|
+
token = 'pol';
|
|
150
|
+
break;
|
|
151
|
+
case 'arweave':
|
|
152
|
+
const jwk = JSON.parse(Buffer.from(DEPLOY_KEY, 'base64').toString('utf-8'));
|
|
153
|
+
signer = new ArweaveSigner(jwk);
|
|
154
|
+
token = 'arweave';
|
|
155
|
+
break;
|
|
156
|
+
case 'kyve':
|
|
157
|
+
signer = new EthereumSigner(DEPLOY_KEY);
|
|
158
|
+
token = 'kyve';
|
|
159
|
+
break;
|
|
160
|
+
default:
|
|
161
|
+
throw new Error(
|
|
162
|
+
`Invalid sig-type provided: ${argv['sig-type']}. Allowed values are 'arweave', 'ethereum', 'polygon', or 'kyve'.`
|
|
163
|
+
);
|
|
121
164
|
}
|
|
122
|
-
|
|
123
|
-
|
|
165
|
+
|
|
166
|
+
const turbo = TurboFactory.authenticated({
|
|
167
|
+
signer: signer,
|
|
168
|
+
token: token,
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
let uploadResult;
|
|
172
|
+
let txOrManifestId;
|
|
173
|
+
if (argv['deploy-file']) {
|
|
174
|
+
// Detect MIME type for the file
|
|
175
|
+
const mimeType = mime.lookup(argv['deploy-file']) || 'application/octet-stream';
|
|
176
|
+
|
|
177
|
+
uploadResult = await turbo.uploadFile({
|
|
178
|
+
file: argv['deploy-file'],
|
|
179
|
+
dataItemOpts: {
|
|
180
|
+
tags: [
|
|
181
|
+
{
|
|
182
|
+
name: 'App-Name',
|
|
183
|
+
value: 'Permaweb-Deploy',
|
|
184
|
+
},
|
|
185
|
+
// prevents identical transaction Ids from eth wallets
|
|
186
|
+
{
|
|
187
|
+
name: 'anchor',
|
|
188
|
+
value: new Date().toISOString(),
|
|
189
|
+
},
|
|
190
|
+
{
|
|
191
|
+
name: 'Content-Type',
|
|
192
|
+
value: mimeType,
|
|
193
|
+
},
|
|
194
|
+
],
|
|
195
|
+
},
|
|
196
|
+
});
|
|
197
|
+
txOrManifestId = uploadResult.id;
|
|
198
|
+
} else {
|
|
199
|
+
uploadResult = await turbo.uploadFolder({
|
|
200
|
+
folderPath: argv['deploy-folder'],
|
|
201
|
+
dataItemOpts: {
|
|
202
|
+
tags: [
|
|
203
|
+
{
|
|
204
|
+
name: 'App-Name',
|
|
205
|
+
value: 'Permaweb-Deploy',
|
|
206
|
+
},
|
|
207
|
+
// prevents identical transaction Ids from eth wallets
|
|
208
|
+
{
|
|
209
|
+
name: 'anchor',
|
|
210
|
+
value: new Date().toISOString(),
|
|
211
|
+
},
|
|
212
|
+
],
|
|
213
|
+
},
|
|
214
|
+
});
|
|
215
|
+
txOrManifestId = uploadResult.manifestResponse.id;
|
|
124
216
|
}
|
|
125
217
|
|
|
126
218
|
console.log('-------------------- DEPLOY DETAILS --------------------');
|
|
127
|
-
console.log(`Tx ID: ${
|
|
219
|
+
console.log(`Tx ID: ${txOrManifestId}`);
|
|
128
220
|
console.log(`ArNS Name: ${ARNS_NAME}`);
|
|
129
221
|
console.log(`Undername: ${argv.undername}`);
|
|
130
222
|
console.log(`ANT: ${arnsNameRecord.processId}`);
|
|
@@ -132,15 +224,14 @@ if (ARIO_PROCESS === 'mainnet') {
|
|
|
132
224
|
console.log(`TTL Seconds: ${TTL_SECONDS}`);
|
|
133
225
|
console.log('--------------------------------------------------------');
|
|
134
226
|
|
|
135
|
-
const signer = new ArweaveSigner(jwk);
|
|
136
227
|
const ant = ANT.init({ processId: arnsNameRecord.processId, signer });
|
|
137
228
|
|
|
138
229
|
// Update the ANT record (assumes the JWK is a controller or owner)
|
|
139
230
|
await ant.setRecord(
|
|
140
231
|
{
|
|
141
232
|
undername: argv.undername,
|
|
142
|
-
transactionId:
|
|
143
|
-
ttlSeconds:
|
|
233
|
+
transactionId: txOrManifestId,
|
|
234
|
+
ttlSeconds: argv['ttl-seconds'],
|
|
144
235
|
},
|
|
145
236
|
{
|
|
146
237
|
tags: [
|
|
@@ -148,15 +239,21 @@ if (ARIO_PROCESS === 'mainnet') {
|
|
|
148
239
|
name: 'App-Name',
|
|
149
240
|
value: 'Permaweb-Deploy',
|
|
150
241
|
},
|
|
151
|
-
...(process.env.GITHUB_SHA
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
242
|
+
...(process.env.GITHUB_SHA
|
|
243
|
+
? [
|
|
244
|
+
{
|
|
245
|
+
name: 'GIT-HASH',
|
|
246
|
+
value: process.env.GITHUB_SHA,
|
|
247
|
+
},
|
|
248
|
+
]
|
|
249
|
+
: []),
|
|
250
|
+
],
|
|
156
251
|
}
|
|
157
252
|
);
|
|
158
253
|
|
|
159
|
-
console.log(
|
|
254
|
+
console.log(
|
|
255
|
+
`Deployed TxId [${txOrManifestId}] to name [${ARNS_NAME}] for ANT [${arnsNameRecord.processId}] using undername [${argv.undername}]`
|
|
256
|
+
);
|
|
160
257
|
} catch (e) {
|
|
161
258
|
console.error('Deployment failed:', e);
|
|
162
259
|
process.exit(1); // Exit with error code
|
package/src/turbo/index.js
DELETED
|
@@ -1,121 +0,0 @@
|
|
|
1
|
-
import fs from 'fs';
|
|
2
|
-
import mime from 'mime-types';
|
|
3
|
-
import path from 'path';
|
|
4
|
-
import { Readable } from 'stream';
|
|
5
|
-
|
|
6
|
-
import { TurboFactory } from '@ardrive/turbo-sdk';
|
|
7
|
-
|
|
8
|
-
// Gets MIME types for each file to tag the upload
|
|
9
|
-
function getContentType(filePath) {
|
|
10
|
-
const res = mime.lookup(filePath);
|
|
11
|
-
return res || 'application/octet-stream';
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
export async function uploadFile(path, turbo) {
|
|
15
|
-
console.log(`Uploading file: ${path}...`);
|
|
16
|
-
try {
|
|
17
|
-
const fileSize = fs.statSync(path).size;
|
|
18
|
-
const contentType = getContentType(path);
|
|
19
|
-
const uploadResult = await turbo.uploadFile({
|
|
20
|
-
fileStreamFactory: () => fs.createReadStream(path),
|
|
21
|
-
fileSizeFactory: () => fileSize,
|
|
22
|
-
signal: AbortSignal.timeout(10_000), // Cancel the upload after 10 seconds
|
|
23
|
-
dataItemOpts: {
|
|
24
|
-
tags: [
|
|
25
|
-
{ name: 'Content-Type', value: contentType },
|
|
26
|
-
{ name: 'App-Name', value: 'Permaweb-Deploy' },
|
|
27
|
-
],
|
|
28
|
-
},
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
console.log(`Uploaded ${path} with id:`, uploadResult.id);
|
|
32
|
-
|
|
33
|
-
return uploadResult;
|
|
34
|
-
} catch (err) {
|
|
35
|
-
console.error(`Error uploading file ${path}:`, err);
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
export async function uploadDirectory(argv, jwk) {
|
|
40
|
-
const turbo = TurboFactory.authenticated({ privateKey: jwk });
|
|
41
|
-
|
|
42
|
-
const deployFolder = argv.deployFolder;
|
|
43
|
-
|
|
44
|
-
// Uses Arweave manifest version 0.2.0, which supports fallbacks
|
|
45
|
-
let newManifest = {
|
|
46
|
-
manifest: 'arweave/paths',
|
|
47
|
-
version: '0.2.0',
|
|
48
|
-
index: { path: 'index.html' },
|
|
49
|
-
fallback: {},
|
|
50
|
-
paths: {},
|
|
51
|
-
};
|
|
52
|
-
|
|
53
|
-
async function processFiles(dir) {
|
|
54
|
-
const files = fs.readdirSync(dir);
|
|
55
|
-
|
|
56
|
-
for (const file of files) {
|
|
57
|
-
try {
|
|
58
|
-
const filePath = path.join(dir, file);
|
|
59
|
-
const relativePath = path.relative(deployFolder, filePath);
|
|
60
|
-
|
|
61
|
-
if (fs.statSync(filePath).isDirectory()) {
|
|
62
|
-
// Recursively process all files in a directory
|
|
63
|
-
await processFiles(filePath);
|
|
64
|
-
} else {
|
|
65
|
-
const uploadResult = await uploadFile(filePath, turbo);
|
|
66
|
-
|
|
67
|
-
// Adds uploaded file txId to the new manifest json
|
|
68
|
-
newManifest.paths[relativePath] = { id: uploadResult.id };
|
|
69
|
-
|
|
70
|
-
if (file === '404.html') {
|
|
71
|
-
// Sets manifest fallback to 404.html if found
|
|
72
|
-
newManifest.fallback.id = uploadResult.id;
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
} catch (err) {
|
|
76
|
-
console.error('ERROR:', err);
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
async function uploadManifest(manifest) {
|
|
82
|
-
try {
|
|
83
|
-
const manifestString = JSON.stringify(manifest);
|
|
84
|
-
const uploadResult = await turbo.uploadFile({
|
|
85
|
-
fileStreamFactory: () => Readable.from(Buffer.from(manifestString)),
|
|
86
|
-
fileSizeFactory: () => Buffer.byteLength(manifestString),
|
|
87
|
-
signal: AbortSignal.timeout(10_000),
|
|
88
|
-
dataItemOpts: {
|
|
89
|
-
tags: [
|
|
90
|
-
{
|
|
91
|
-
name: 'Content-Type',
|
|
92
|
-
value: 'application/x.arweave-manifest+json',
|
|
93
|
-
},
|
|
94
|
-
{
|
|
95
|
-
name: 'App-Name',
|
|
96
|
-
value: 'Permaweb-Deploy',
|
|
97
|
-
},
|
|
98
|
-
],
|
|
99
|
-
},
|
|
100
|
-
});
|
|
101
|
-
return uploadResult.id;
|
|
102
|
-
} catch (error) {
|
|
103
|
-
console.error('Error uploading manifest:', error);
|
|
104
|
-
return null;
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
// Starts processing files in the selected directory
|
|
109
|
-
await processFiles(deployFolder);
|
|
110
|
-
|
|
111
|
-
if (!newManifest.fallback.id) {
|
|
112
|
-
// If no 404.html file is found, manifest fallback is set to the txId of index.html
|
|
113
|
-
newManifest.fallback.id = newManifest.paths['index.html'].id;
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
const manifestId = await uploadManifest(newManifest);
|
|
117
|
-
if (manifestId) {
|
|
118
|
-
console.log(`Manifest uploaded with Id: ${manifestId}`);
|
|
119
|
-
return manifestId;
|
|
120
|
-
}
|
|
121
|
-
}
|