permaweb-deploy 3.2.1 → 3.4.1

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 CHANGED
@@ -118,6 +118,16 @@ Deploy a single file:
118
118
  permaweb-deploy deploy --arns-name my-app --wallet ./wallet.json --deploy-file ./path/to/file.txt
119
119
  ```
120
120
 
121
+ ### Upload only (no ArNS)
122
+
123
+ To upload a folder or file to Arweave **without** updating an ArNS name, use the `upload` command (same Turbo upload, dedupe cache, and payment options as deploy, minus ArNS flags):
124
+
125
+ ```bash
126
+ permaweb-deploy upload --wallet ./wallet.json --deploy-folder ./dist
127
+ permaweb-deploy upload --wallet ./wallet.json --deploy-file ./dist/index.html
128
+ DEPLOY_KEY=$(base64 -i wallet.json) permaweb-deploy upload --deploy-folder ./dist
129
+ ```
130
+
121
131
  ### Advanced Usage
122
132
 
123
133
  Deploy to an undername (subdomain):
@@ -177,8 +187,35 @@ permaweb-deploy deploy --arns-name my-app --sig-type ethereum --private-key "0x.
177
187
  - **ARIO**: Works with Arweave signer
178
188
  - **Base-ETH**: Works with Ethereum signer (Base Network)
179
189
 
190
+ ### Bundler service
191
+
192
+ Uploads go through a [Turbo](https://docs.ardrive.io/docs/turbo/) **bundler service** (HTTP API that bundles data for Arweave). By default, permaweb-deploy uses 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
+
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 Turbo bundler protocol |
200
+
201
+ **Examples:**
202
+
203
+ ```bash
204
+ # Deploy using Arweave’s bundler service
205
+ permaweb-deploy deploy --arns-name my-app --wallet ./wallet.json --uploader https://up.arweave.net
206
+
207
+ permaweb-deploy upload --wallet ./wallet.json --deploy-folder ./dist --uploader https://up.arweave.net
208
+ ```
209
+
210
+ **Notes:**
211
+
212
+ - Billing and signer behavior still follow Turbo; if an alternate bundler has different rules, check that provider’s docs.
213
+ - Use a **base URL only** (e.g. `https://up.arweave.net`), not a path to a specific file or route.
214
+
180
215
  ### Command Options
181
216
 
217
+ **`deploy`** (ArNS update):
218
+
182
219
  - `--arns-name, -n` (required): The ArNS name to update
183
220
  - `--ario-process, -p`: ARIO process to use (`mainnet`, `testnet`, or a custom process ID). Default: `mainnet`
184
221
  - `--deploy-folder, -d`: Folder to deploy. Default: `./dist`
@@ -192,6 +229,9 @@ permaweb-deploy deploy --arns-name my-app --sig-type ethereum --private-key "0x.
192
229
  - `--max-token-amount`: Maximum token amount for on-demand payment (used with `--on-demand`)
193
230
  - `--no-dedupe`: Disable deduplication (do not cache or reuse previous uploads)
194
231
  - `--dedupe-cache-max-entries`: Maximum number of entries to keep in the dedupe cache (LRU). Default: `10000`
232
+ - `--uploader`: Base URL of the Turbo **bundler service** to use (default: `https://upload.ardrive.io`). See [Bundler service](#bundler-service) above.
233
+
234
+ **`upload`** (no ArNS): accepts `--deploy-folder`, `--deploy-file`, wallet/signer flags, `--uploader`, `--on-demand` / `--max-token-amount`, and dedupe flags only.
195
235
 
196
236
  ### Deduplication
197
237
 
@@ -504,7 +544,8 @@ pnpm format
504
544
  permaweb-deploy/
505
545
  ├── src/
506
546
  │ ├── commands/ # oclif commands
507
- │ │ └── deploy.ts
547
+ │ │ ├── deploy.ts
548
+ │ │ └── upload.ts
508
549
  │ ├── types/ # TypeScript type definitions
509
550
  │ │ └── index.ts
510
551
  │ ├── utils/ # Utility functions
@@ -180,8 +180,18 @@ class Queue {
180
180
  }
181
181
 
182
182
  function pLimit(concurrency) {
183
+ let rejectOnClear = false;
184
+
185
+ if (typeof concurrency === 'object') {
186
+ ({concurrency, rejectOnClear = false} = concurrency);
187
+ }
188
+
183
189
  validateConcurrency(concurrency);
184
190
 
191
+ if (typeof rejectOnClear !== 'boolean') {
192
+ throw new TypeError('Expected `rejectOnClear` to be a boolean');
193
+ }
194
+
185
195
  const queue = new Queue();
186
196
  let activeCount = 0;
187
197
 
@@ -189,7 +199,7 @@ function pLimit(concurrency) {
189
199
  // Process the next queued function if we're under the concurrency limit
190
200
  if (activeCount < concurrency && queue.size > 0) {
191
201
  activeCount++;
192
- queue.dequeue()();
202
+ queue.dequeue().run();
193
203
  }
194
204
  };
195
205
 
@@ -216,11 +226,14 @@ function pLimit(concurrency) {
216
226
  next();
217
227
  };
218
228
 
219
- const enqueue = (function_, resolve, arguments_) => {
229
+ const enqueue = (function_, resolve, reject, arguments_) => {
230
+ const queueItem = {reject};
231
+
220
232
  // Queue the internal resolve function instead of the run function
221
233
  // to preserve the asynchronous execution context.
222
234
  new Promise(internalResolve => { // eslint-disable-line promise/param-names
223
- queue.enqueue(internalResolve);
235
+ queueItem.run = internalResolve;
236
+ queue.enqueue(queueItem);
224
237
  }).then(run.bind(undefined, function_, resolve, arguments_)); // eslint-disable-line promise/prefer-await-to-then
225
238
 
226
239
  // Start processing immediately if we haven't reached the concurrency limit
@@ -229,8 +242,8 @@ function pLimit(concurrency) {
229
242
  }
230
243
  };
231
244
 
232
- const generator = (function_, ...arguments_) => new Promise(resolve => {
233
- enqueue(function_, resolve, arguments_);
245
+ const generator = (function_, ...arguments_) => new Promise((resolve, reject) => {
246
+ enqueue(function_, resolve, reject, arguments_);
234
247
  });
235
248
 
236
249
  Object.defineProperties(generator, {
@@ -242,7 +255,16 @@ function pLimit(concurrency) {
242
255
  },
243
256
  clearQueue: {
244
257
  value() {
245
- queue.clear();
258
+ if (!rejectOnClear) {
259
+ queue.clear();
260
+ return;
261
+ }
262
+
263
+ const abortError = AbortSignal.abort().reason;
264
+
265
+ while (queue.size > 0) {
266
+ queue.dequeue().reject(abortError);
267
+ }
246
268
  },
247
269
  },
248
270
  concurrency: {
@@ -441,4 +463,4 @@ async function uploadFolder(turbo, folderPath, options) {
441
463
  }
442
464
 
443
465
  export { uploadFolder as a, cleanupCache as c, loadCache as l, saveCache as s, uploadFile as u };
444
- //# sourceMappingURL=uploader-d40K7e4Z.js.map
466
+ //# sourceMappingURL=uploader-DDS_d-O_.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"uploader-DDS_d-O_.js","sources":["../../src/utils/cache.ts","../../node_modules/.pnpm/yocto-queue@1.2.2/node_modules/yocto-queue/index.js","../../node_modules/.pnpm/p-limit@7.3.0/node_modules/p-limit/index.js","../../src/utils/uploader.ts"],"sourcesContent":["import crypto from 'node:crypto'\nimport fs from 'node:fs'\nimport path from 'node:path'\n\nimport { CACHE_DIR, CACHE_FILE } from '../constants/cache.js'\n\nexport interface TransactionCacheEntry {\n createdAtTimestamp: number\n lastUsedTimestamp: number\n transactionId: string\n}\n\nexport type TransactionCache = Record<string, TransactionCacheEntry>\n\n/**\n * Get the path to the cache file in the current working directory\n */\nexport function getCachePath(): string {\n return path.join(process.cwd(), CACHE_DIR, CACHE_FILE)\n}\n\n/**\n * Load the transaction cache from disk\n * Returns an empty object if the cache file doesn't exist or is invalid\n */\nexport function loadCache(): TransactionCache {\n const cachePath = getCachePath()\n\n try {\n if (!fs.existsSync(cachePath)) {\n return {}\n }\n\n const content = fs.readFileSync(cachePath, 'utf8')\n return JSON.parse(content) as TransactionCache\n } catch {\n // If the cache is corrupted or unreadable, start fresh\n return {}\n }\n}\n\n/**\n * Save the transaction cache to disk\n * Creates the cache directory if it doesn't exist\n */\nexport function saveCache(cache: TransactionCache): void {\n const cachePath = getCachePath()\n const cacheDir = path.dirname(cachePath)\n\n if (!fs.existsSync(cacheDir)) {\n fs.mkdirSync(cacheDir, { recursive: true })\n }\n\n fs.writeFileSync(cachePath, JSON.stringify(cache, null, 2), 'utf8')\n}\n\n/**\n * Compute the SHA-256 hash of a file using streaming\n */\nexport async function hashFile(filePath: string): Promise<string> {\n return new Promise((resolve, reject) => {\n const hash = crypto.createHash('sha256')\n const stream = fs.createReadStream(filePath)\n\n stream.on('data', (chunk) => hash.update(chunk))\n stream.on('end', () => resolve(hash.digest('hex')))\n stream.on('error', reject)\n })\n}\n\n/**\n * Recursively get all files in a directory\n * Returns relative paths from the base directory\n */\nexport function getAllFiles(dirPath: string, basePath: string = dirPath): string[] {\n const files: string[] = []\n\n for (const item of fs.readdirSync(dirPath)) {\n const fullPath = path.join(dirPath, item)\n const stats = fs.statSync(fullPath)\n\n if (stats.isDirectory()) {\n files.push(...getAllFiles(fullPath, basePath))\n } else {\n // Store relative path for consistent hashing\n files.push(path.relative(basePath, fullPath))\n }\n }\n\n return files\n}\n\n/**\n * Get a cached transaction entry by its file hash\n */\nexport function getCachedTransaction(\n cache: TransactionCache,\n hash: string,\n): TransactionCacheEntry | undefined {\n return cache[hash]\n}\n\n/**\n * Add or update a cache entry for a file hash\n * Updates lastUsedTimestamp if the entry already exists\n */\nexport function setCachedTransaction(\n cache: TransactionCache,\n hash: string,\n transactionId: string,\n): TransactionCache {\n const now = Date.now()\n const existing = cache[hash]\n\n return {\n ...cache,\n [hash]: {\n createdAtTimestamp: existing?.createdAtTimestamp ?? now,\n lastUsedTimestamp: now,\n transactionId,\n },\n }\n}\n\n/**\n * Update the lastUsedTimestamp for an existing cache entry\n */\nexport function touchCacheEntry(cache: TransactionCache, hash: string): TransactionCache {\n const existing = cache[hash]\n if (!existing) {\n return cache\n }\n\n return {\n ...cache,\n [hash]: {\n ...existing,\n lastUsedTimestamp: Date.now(),\n },\n }\n}\n\n/**\n * Clean up the cache by keeping only the most recently used entries\n * Entries are sorted by lastUsedTimestamp descending, keeping the newest maxEntries\n */\nexport function cleanupCache(cache: TransactionCache, maxEntries: number): TransactionCache {\n const entries = Object.entries(cache)\n\n if (entries.length <= maxEntries) {\n return cache\n }\n\n // Sort by lastUsedTimestamp descending (newest first)\n const sorted = entries.sort(([, a], [, b]) => b.lastUsedTimestamp - a.lastUsedTimestamp)\n\n // Keep only the newest maxEntries\n const kept = sorted.slice(0, maxEntries)\n\n return Object.fromEntries(kept)\n}\n","/*\nHow it works:\n`this.#head` is an instance of `Node` which keeps track of its current value and nests another instance of `Node` that keeps the value that comes after it. When a value is provided to `.enqueue()`, the code needs to iterate through `this.#head`, going deeper and deeper to find the last value. However, iterating through every single item is slow. This problem is solved by saving a reference to the last value as `this.#tail` so that it can reference it to add a new value.\n*/\n\nclass Node {\n\tvalue;\n\tnext;\n\n\tconstructor(value) {\n\t\tthis.value = value;\n\t}\n}\n\nexport default class Queue {\n\t#head;\n\t#tail;\n\t#size;\n\n\tconstructor() {\n\t\tthis.clear();\n\t}\n\n\tenqueue(value) {\n\t\tconst node = new Node(value);\n\n\t\tif (this.#head) {\n\t\t\tthis.#tail.next = node;\n\t\t\tthis.#tail = node;\n\t\t} else {\n\t\t\tthis.#head = node;\n\t\t\tthis.#tail = node;\n\t\t}\n\n\t\tthis.#size++;\n\t}\n\n\tdequeue() {\n\t\tconst current = this.#head;\n\t\tif (!current) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.#head = this.#head.next;\n\t\tthis.#size--;\n\n\t\t// Clean up tail reference when queue becomes empty\n\t\tif (!this.#head) {\n\t\t\tthis.#tail = undefined;\n\t\t}\n\n\t\treturn current.value;\n\t}\n\n\tpeek() {\n\t\tif (!this.#head) {\n\t\t\treturn;\n\t\t}\n\n\t\treturn this.#head.value;\n\n\t\t// TODO: Node.js 18.\n\t\t// return this.#head?.value;\n\t}\n\n\tclear() {\n\t\tthis.#head = undefined;\n\t\tthis.#tail = undefined;\n\t\tthis.#size = 0;\n\t}\n\n\tget size() {\n\t\treturn this.#size;\n\t}\n\n\t* [Symbol.iterator]() {\n\t\tlet current = this.#head;\n\n\t\twhile (current) {\n\t\t\tyield current.value;\n\t\t\tcurrent = current.next;\n\t\t}\n\t}\n\n\t* drain() {\n\t\twhile (this.#head) {\n\t\t\tyield this.dequeue();\n\t\t}\n\t}\n}\n","import Queue from 'yocto-queue';\n\nexport default function pLimit(concurrency) {\n\tlet rejectOnClear = false;\n\n\tif (typeof concurrency === 'object') {\n\t\t({concurrency, rejectOnClear = false} = concurrency);\n\t}\n\n\tvalidateConcurrency(concurrency);\n\n\tif (typeof rejectOnClear !== 'boolean') {\n\t\tthrow new TypeError('Expected `rejectOnClear` to be a boolean');\n\t}\n\n\tconst queue = new Queue();\n\tlet activeCount = 0;\n\n\tconst resumeNext = () => {\n\t\t// Process the next queued function if we're under the concurrency limit\n\t\tif (activeCount < concurrency && queue.size > 0) {\n\t\t\tactiveCount++;\n\t\t\tqueue.dequeue().run();\n\t\t}\n\t};\n\n\tconst next = () => {\n\t\tactiveCount--;\n\t\tresumeNext();\n\t};\n\n\tconst run = async (function_, resolve, arguments_) => {\n\t\t// Execute the function and capture the result promise\n\t\tconst result = (async () => function_(...arguments_))();\n\n\t\t// Resolve immediately with the promise (don't wait for completion)\n\t\tresolve(result);\n\n\t\t// Wait for the function to complete (success or failure)\n\t\t// We catch errors here to prevent unhandled rejections,\n\t\t// but the original promise rejection is preserved for the caller\n\t\ttry {\n\t\t\tawait result;\n\t\t} catch {}\n\n\t\t// Decrement active count and process next queued function\n\t\tnext();\n\t};\n\n\tconst enqueue = (function_, resolve, reject, arguments_) => {\n\t\tconst queueItem = {reject};\n\n\t\t// Queue the internal resolve function instead of the run function\n\t\t// to preserve the asynchronous execution context.\n\t\tnew Promise(internalResolve => { // eslint-disable-line promise/param-names\n\t\t\tqueueItem.run = internalResolve;\n\t\t\tqueue.enqueue(queueItem);\n\t\t}).then(run.bind(undefined, function_, resolve, arguments_)); // eslint-disable-line promise/prefer-await-to-then\n\n\t\t// Start processing immediately if we haven't reached the concurrency limit\n\t\tif (activeCount < concurrency) {\n\t\t\tresumeNext();\n\t\t}\n\t};\n\n\tconst generator = (function_, ...arguments_) => new Promise((resolve, reject) => {\n\t\tenqueue(function_, resolve, reject, arguments_);\n\t});\n\n\tObject.defineProperties(generator, {\n\t\tactiveCount: {\n\t\t\tget: () => activeCount,\n\t\t},\n\t\tpendingCount: {\n\t\t\tget: () => queue.size,\n\t\t},\n\t\tclearQueue: {\n\t\t\tvalue() {\n\t\t\t\tif (!rejectOnClear) {\n\t\t\t\t\tqueue.clear();\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tconst abortError = AbortSignal.abort().reason;\n\n\t\t\t\twhile (queue.size > 0) {\n\t\t\t\t\tqueue.dequeue().reject(abortError);\n\t\t\t\t}\n\t\t\t},\n\t\t},\n\t\tconcurrency: {\n\t\t\tget: () => concurrency,\n\n\t\t\tset(newConcurrency) {\n\t\t\t\tvalidateConcurrency(newConcurrency);\n\t\t\t\tconcurrency = newConcurrency;\n\n\t\t\t\tqueueMicrotask(() => {\n\t\t\t\t\t// eslint-disable-next-line no-unmodified-loop-condition\n\t\t\t\t\twhile (activeCount < concurrency && queue.size > 0) {\n\t\t\t\t\t\tresumeNext();\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t},\n\t\t},\n\t\tmap: {\n\t\t\tasync value(iterable, function_) {\n\t\t\t\tconst promises = Array.from(iterable, (value, index) => this(function_, value, index));\n\t\t\t\treturn Promise.all(promises);\n\t\t\t},\n\t\t},\n\t});\n\n\treturn generator;\n}\n\nexport function limitFunction(function_, options) {\n\tconst limit = pLimit(options);\n\n\treturn (...arguments_) => limit(() => function_(...arguments_));\n}\n\nfunction validateConcurrency(concurrency) {\n\tif (!((Number.isInteger(concurrency) || concurrency === Number.POSITIVE_INFINITY) && concurrency > 0)) {\n\t\tthrow new TypeError('Expected `concurrency` to be a number from 1 and up');\n\t}\n}\n","import path from 'node:path'\nimport { Readable } from 'node:stream'\n\nimport { OnDemandFunding, type TurboAuthenticatedClient } from '@ardrive/turbo-sdk'\nimport * as mime from 'mime-types'\nimport pLimit from 'p-limit'\n\nimport {\n getAllFiles,\n getCachedTransaction,\n hashFile,\n setCachedTransaction,\n touchCacheEntry,\n type TransactionCache,\n} from './cache.js'\n\nexport interface UploadResult {\n cacheHit: boolean\n transactionId: string\n updatedCache?: TransactionCache\n}\n\nexport interface FolderUploadResult extends UploadResult {\n /** Number of files that were cache hits (not re-uploaded) */\n cacheHits: number\n /** Total number of files in the folder */\n totalFiles: number\n /** Number of files that were uploaded */\n uploaded: number\n}\n\nexport async function uploadFile(\n turbo: TurboAuthenticatedClient,\n filePath: string,\n options?: {\n cache?: TransactionCache\n fundingMode?: OnDemandFunding\n },\n): Promise<UploadResult> {\n const mimeType = mime.lookup(filePath) || 'application/octet-stream'\n\n // Compute hash if cache is provided\n const fileHash = options?.cache ? await hashFile(filePath) : undefined\n\n // Check cache for hit\n if (fileHash && options?.cache) {\n const cached = getCachedTransaction(options.cache, fileHash)\n if (cached) {\n const updatedCache = touchCacheEntry(options.cache, fileHash)\n return {\n cacheHit: true,\n transactionId: cached.transactionId,\n updatedCache,\n }\n }\n }\n\n // Upload file\n const uploadResult = await turbo.uploadFile({\n dataItemOpts: {\n tags: [\n {\n name: 'App-Name',\n value: 'Permaweb-Deploy',\n },\n {\n name: 'anchor',\n value: new Date().toISOString(),\n },\n {\n name: 'Content-Type',\n value: mimeType,\n },\n ],\n },\n file: filePath,\n ...(options?.fundingMode && { fundingMode: options.fundingMode }),\n })\n\n if (!uploadResult?.id) {\n throw new Error('Failed to upload file: upload result missing transaction ID')\n }\n\n // Store in cache if provided\n if (fileHash && options?.cache) {\n const updatedCache = setCachedTransaction(options.cache, fileHash, uploadResult.id)\n return {\n cacheHit: false,\n transactionId: uploadResult.id,\n updatedCache,\n }\n }\n\n return {\n cacheHit: false,\n transactionId: uploadResult.id,\n }\n}\n\n/** Default concurrency for parallel file uploads */\nconst DEFAULT_UPLOAD_CONCURRENCY = 10\n\ninterface FileUploadTask {\n cached?: { transactionId: string }\n fullPath: string\n hash: string\n relativePath: string\n}\n\n/**\n * Upload a folder with per-file deduplication.\n * Each file is checked against the cache individually, and only uncached files are uploaded.\n * A manifest is then constructed and uploaded to create the folder structure.\n */\nexport async function uploadFolder(\n turbo: TurboAuthenticatedClient,\n folderPath: string,\n options?: {\n cache?: TransactionCache\n concurrency?: number\n fundingMode?: OnDemandFunding\n throwOnFailure?: boolean\n },\n): Promise<FolderUploadResult> {\n const concurrency = options?.concurrency ?? DEFAULT_UPLOAD_CONCURRENCY\n const useCache = options?.cache !== undefined\n\n // Get all files in the folder\n const relativePaths = getAllFiles(folderPath)\n\n if (relativePaths.length === 0) {\n throw new Error('Folder is empty, nothing to upload')\n }\n\n // Prepare file tasks with hashes (if caching is enabled)\n const tasks: FileUploadTask[] = await Promise.all(\n relativePaths.map(async (relativePath) => {\n const fullPath = path.join(folderPath, relativePath)\n const hash = useCache ? await hashFile(fullPath) : ''\n return { fullPath, hash, relativePath }\n }),\n )\n\n // Check cache for each file\n let cache = options?.cache ?? {}\n let cacheHits = 0\n\n for (const task of tasks) {\n if (useCache && task.hash) {\n const cached = getCachedTransaction(cache, task.hash)\n if (cached) {\n task.cached = { transactionId: cached.transactionId }\n cache = touchCacheEntry(cache, task.hash)\n cacheHits++\n }\n }\n }\n\n // If all files are cached, we still need to build and upload a new manifest\n // (because the manifest itself has a unique transaction ID each time)\n const uncachedTasks = tasks.filter((t) => !t.cached)\n\n // Upload uncached files with concurrency control using p-limit\n const limit = pLimit(concurrency)\n\n const uploadResults = await Promise.all(\n uncachedTasks.map((task) =>\n limit(async () => {\n const mimeType = mime.lookup(task.fullPath) || 'application/octet-stream'\n\n const uploadResult = await turbo.uploadFile({\n dataItemOpts: {\n tags: [\n { name: 'App-Name', value: 'Permaweb-Deploy' },\n { name: 'Content-Type', value: mimeType },\n ],\n },\n file: task.fullPath,\n ...(options?.fundingMode && { fundingMode: options.fundingMode }),\n })\n\n if (!uploadResult?.id) {\n if (options?.throwOnFailure) {\n throw new Error(`Failed to upload file: ${task.relativePath}`)\n }\n\n return { hash: task.hash, task, transactionId: null }\n }\n\n return { hash: task.hash, task, transactionId: uploadResult.id }\n }),\n ),\n )\n\n // Update cache with all successful uploads (done sequentially to avoid race conditions)\n for (const result of uploadResults) {\n if (useCache && result.hash && result.transactionId) {\n cache = setCachedTransaction(cache, result.hash, result.transactionId)\n }\n }\n\n // Check for any failed uploads\n const failedUploads = uploadResults.filter((r) => r.transactionId === null)\n if (failedUploads.length > 0 && options?.throwOnFailure) {\n throw new Error(\n `Failed to upload ${failedUploads.length} file(s): ${failedUploads.map((f) => f.task.relativePath).join(', ')}`,\n )\n }\n\n // Build manifest paths from cached and newly uploaded files\n const manifestPaths: Record<string, { id: string }> = {}\n\n for (const task of tasks) {\n let transactionId: string | null = null\n\n if (task.cached) {\n transactionId = task.cached.transactionId\n } else {\n const uploadResult = uploadResults.find((r) => r.task === task)\n transactionId = uploadResult?.transactionId ?? null\n }\n\n if (transactionId) {\n manifestPaths[task.relativePath] = { id: transactionId }\n\n // Add directory index support: if file is dir/index.html, also add dir → same ID\n if (task.relativePath.endsWith('/index.html')) {\n const dirPath = task.relativePath.replace(/\\/index\\.html$/, '')\n manifestPaths[dirPath] = { id: transactionId }\n }\n }\n }\n\n // Determine the index path (root index.html)\n const indexPath = relativePaths.includes('index.html') ? 'index.html' : undefined\n\n // Build the manifest\n const manifest = {\n manifest: 'arweave/paths',\n version: '0.2.0',\n ...(indexPath && { index: { path: indexPath } }),\n paths: manifestPaths,\n }\n\n // Upload the manifest\n const manifestBuffer = Buffer.from(JSON.stringify(manifest))\n const manifestUploadResult = await turbo.uploadFile({\n dataItemOpts: {\n tags: [\n { name: 'App-Name', value: 'Permaweb-Deploy' },\n { name: 'Content-Type', value: 'application/x.arweave-manifest+json' },\n ],\n },\n fileSizeFactory: () => manifestBuffer.length,\n fileStreamFactory: () => Readable.from(manifestBuffer),\n ...(options?.fundingMode && { fundingMode: options.fundingMode }),\n })\n\n if (!manifestUploadResult?.id) {\n throw new Error('Failed to upload manifest: upload result missing transaction ID')\n }\n\n return {\n cacheHit: cacheHits === tasks.length,\n cacheHits,\n totalFiles: tasks.length,\n transactionId: manifestUploadResult.id,\n updatedCache: useCache ? cache : undefined,\n uploaded: uncachedTasks.length - failedUploads.length,\n }\n}\n"],"names":[],"mappings":"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","x_google_ignoreList":[1,2]}
@@ -1,7 +1,5 @@
1
1
  import fs from 'node:fs';
2
- import path from 'node:path';
3
2
  import { ARIO, AOProcess, ANT } from '@ar.io/sdk';
4
- import { TurboFactory, ETHToTokenAmount, ARIOToTokenAmount, OnDemandFunding } from '@ardrive/turbo-sdk';
5
3
  import { Command } from '@oclif/core';
6
4
  import { connect } from '@permaweb/aoconnect';
7
5
  import boxen from 'boxen';
@@ -11,20 +9,11 @@ import ora from 'ora';
11
9
  import { deployFlagConfigs } from '../constants/flags.js';
12
10
  import { promptAdvancedOptions } from '../prompts/arns.js';
13
11
  import { getWalletConfig } from '../prompts/wallet.js';
14
- import { l as loadCache, u as uploadFile, c as cleanupCache, s as saveCache, a as uploadFolder } from '../chunks/uploader-d40K7e4Z.js';
15
12
  import { extractFlags, resolveConfig } from '../utils/config-resolver.js';
16
13
  import { expandPath } from '../utils/path.js';
17
14
  import { createSigner } from '../utils/signer.js';
15
+ import { runUploadWorkflow } from '../workflows/upload-workflow.js';
18
16
 
19
- function getFolderSize(folderPath) {
20
- let totalSize = 0;
21
- for (const item of fs.readdirSync(folderPath)) {
22
- const fullPath = path.join(folderPath, item);
23
- const stats = fs.statSync(fullPath);
24
- totalSize += stats.isDirectory() ? getFolderSize(fullPath) : stats.size;
25
- }
26
- return totalSize;
27
- }
28
17
  class Deploy extends Command {
29
18
  static args = {};
30
19
  static description = "Deploy your application to the permaweb";
@@ -36,7 +25,9 @@ class Deploy extends Command {
36
25
  "<%= config.bin %> deploy --arns-name my-app --deploy-file ./dist/index.html",
37
26
  "<%= config.bin %> deploy --arns-name my-app --sig-type ethereum --wallet ./private-key.txt",
38
27
  '<%= config.bin %> deploy --arns-name my-app --sig-type ethereum --private-key "0x..."',
39
- "<%= config.bin %> deploy --arns-name my-app --on-demand ario --max-token-amount 1000"
28
+ "<%= config.bin %> deploy --arns-name my-app --on-demand ario --max-token-amount 1000",
29
+ "<%= config.bin %> deploy --arns-name my-app --uploader https://up.arweave.net",
30
+ "<%= config.bin %> upload --wallet ./wallet.json # Upload only (no ArNS update)"
40
31
  ];
41
32
  static flags = extractFlags(deployFlagConfigs);
42
33
  async run() {
@@ -44,7 +35,7 @@ class Deploy extends Command {
44
35
  const { flags } = await this.parse(Deploy);
45
36
  const interactive = !flags["arns-name"];
46
37
  if (interactive) {
47
- this.log(chalk.cyan.bold("\n🎯 Interactive Deployment Mode\n"));
38
+ this.log(chalk.cyan.bold("\nInteractive Deployment Mode\n"));
48
39
  }
49
40
  const baseConfig = await resolveConfig(deployFlagConfigs, flags, {
50
41
  interactive
@@ -79,6 +70,7 @@ class Deploy extends Command {
79
70
  "sig-type": baseConfig["sig-type"],
80
71
  "ttl-seconds": advancedOptions?.ttlSeconds || baseConfig["ttl-seconds"],
81
72
  undername: advancedOptions?.undername || baseConfig.undername,
73
+ uploader: baseConfig.uploader,
82
74
  wallet: walletConfig.wallet
83
75
  };
84
76
  if (interactive) {
@@ -103,9 +95,10 @@ class Deploy extends Command {
103
95
  }
104
96
  }
105
97
  const arioProcess = deployConfig["ario-process"];
106
- this.log(chalk.cyan.bold("\n🚀 Starting deployment...\n"));
98
+ this.log(chalk.cyan.bold("\nStarting deployment...\n"));
107
99
  try {
108
- const spinner = ora("Initializing ARIO").start();
100
+ const spinner = ora();
101
+ spinner.start("Initializing ARIO");
109
102
  const ao = connect({
110
103
  CU_URL: "https://cu.ardrive.io",
111
104
  MODE: "legacy",
@@ -124,139 +117,12 @@ class Deploy extends Command {
124
117
  this.error(`ArNS name [${deployConfig["arns-name"]}] does not exist`);
125
118
  });
126
119
  spinner.succeed(`ArNS record fetched for ${chalk.green(deployConfig["arns-name"])}`);
127
- spinner.start("Creating signer");
128
- const { signer, token } = createSigner(deployConfig["sig-type"], deployKey);
129
- spinner.succeed(`Signer created (${chalk.cyan(deployConfig["sig-type"])})`);
130
- spinner.start("Initializing Turbo");
131
- const turbo = TurboFactory.authenticated({
132
- signer,
133
- token
120
+ const txOrManifestId = await runUploadWorkflow(deployKey, deployConfig, {
121
+ error: (msg) => this.error(msg)
134
122
  });
135
- spinner.succeed("Turbo initialized");
136
- let fundingMode;
137
- if (deployConfig["on-demand"] && deployConfig["max-token-amount"]) {
138
- const tokenType = deployConfig["on-demand"];
139
- const maxAmount = Number.parseFloat(deployConfig["max-token-amount"]);
140
- let maxTokenAmount;
141
- switch (tokenType) {
142
- case "ario": {
143
- maxTokenAmount = ARIOToTokenAmount(maxAmount);
144
- break;
145
- }
146
- case "base-eth": {
147
- maxTokenAmount = ETHToTokenAmount(maxAmount);
148
- break;
149
- }
150
- default: {
151
- throw new Error(`Unsupported on-demand token type: ${tokenType}`);
152
- }
153
- }
154
- fundingMode = new OnDemandFunding({
155
- maxTokenAmount,
156
- topUpBufferMultiplier: 1.1
157
- });
158
- }
159
- if (!fundingMode) {
160
- spinner.start("Checking Turbo credits for upload");
161
- try {
162
- const uploadBytes = deployConfig["deploy-file"] ? (() => {
163
- const filePath = expandPath(deployConfig["deploy-file"]);
164
- return fs.statSync(filePath).size;
165
- })() : (() => {
166
- const folderPath = expandPath(deployConfig["deploy-folder"]);
167
- return getFolderSize(folderPath);
168
- })();
169
- const FREE_THRESHOLD_BYTES = 107520;
170
- if (uploadBytes >= FREE_THRESHOLD_BYTES) {
171
- const [uploadCost] = await turbo.getUploadCosts({ bytes: [uploadBytes] });
172
- const balance = await turbo.getBalance();
173
- const requiredWinc = BigInt(uploadCost.winc);
174
- const currentWinc = BigInt(balance.winc);
175
- if (requiredWinc > currentWinc) {
176
- spinner.fail("Insufficient Turbo credits");
177
- this.error(
178
- [
179
- "Insufficient Turbo credits for this upload.",
180
- `Required: ${requiredWinc.toString()} winc, available: ${currentWinc.toString()} winc.`,
181
- "",
182
- "Top up your Turbo balance (or re-run with --on-demand and --max-token-amount)."
183
- ].join(" ")
184
- );
185
- }
186
- }
187
- spinner.succeed("Turbo credits check passed");
188
- } catch (balanceError) {
189
- spinner.fail("Failed to check Turbo credits");
190
- const errorMessage = balanceError instanceof Error ? balanceError.message : String(balanceError);
191
- this.error(`Failed to check Turbo credits: ${errorMessage}`);
192
- }
193
- }
194
- let txOrManifestId;
195
- try {
196
- if (deployConfig["deploy-file"]) {
197
- const filePath = expandPath(deployConfig["deploy-file"]);
198
- spinner.start(`Uploading file ${chalk.yellow(deployConfig["deploy-file"])}`);
199
- let cache = deployConfig["dedupe-cache-max-entries"] > 0 ? loadCache() : {};
200
- const uploadResult = await uploadFile(turbo, filePath, { cache, fundingMode });
201
- if (!uploadResult.transactionId) {
202
- spinner.fail("File upload failed: no transaction ID returned");
203
- this.error("File upload failed: no transaction ID returned");
204
- }
205
- txOrManifestId = uploadResult.transactionId;
206
- if (uploadResult.updatedCache && deployConfig["dedupe-cache-max-entries"] > 0) {
207
- cache = cleanupCache(
208
- uploadResult.updatedCache,
209
- deployConfig["dedupe-cache-max-entries"]
210
- );
211
- saveCache(cache);
212
- }
213
- if (uploadResult.cacheHit) {
214
- spinner.succeed(`File cache hit - reusing transaction ${chalk.green(txOrManifestId)}`);
215
- } else {
216
- const cacheMsg = deployConfig["dedupe-cache-max-entries"] > 0 ? chalk.gray("(cached for future deployments)") : "";
217
- spinner.succeed(`File uploaded: ${chalk.green(txOrManifestId)} ${cacheMsg}`.trim());
218
- }
219
- } else {
220
- const folderPath = expandPath(deployConfig["deploy-folder"]);
221
- spinner.start(`Uploading folder ${chalk.yellow(deployConfig["deploy-folder"])}`);
222
- let cache = deployConfig["dedupe-cache-max-entries"] > 0 ? loadCache() : {};
223
- const uploadResult = await uploadFolder(turbo, folderPath, {
224
- cache,
225
- fundingMode,
226
- throwOnFailure: true
227
- });
228
- if (!uploadResult.transactionId) {
229
- spinner.fail("Folder upload failed: no transaction ID returned");
230
- this.error("Folder upload failed: no transaction ID returned");
231
- }
232
- txOrManifestId = uploadResult.transactionId;
233
- if (uploadResult.updatedCache && deployConfig["dedupe-cache-max-entries"] > 0) {
234
- cache = cleanupCache(
235
- uploadResult.updatedCache,
236
- deployConfig["dedupe-cache-max-entries"]
237
- );
238
- saveCache(cache);
239
- }
240
- const { cacheHits, totalFiles, uploaded } = uploadResult;
241
- const statsMsg = cacheHits > 0 ? chalk.gray(` (${cacheHits}/${totalFiles} files cached, ${uploaded} uploaded)`) : "";
242
- if (uploadResult.cacheHit) {
243
- spinner.succeed(
244
- `All ${totalFiles} files cached - manifest: ${chalk.green(txOrManifestId)}`
245
- );
246
- } else {
247
- const cacheMsg = deployConfig["dedupe-cache-max-entries"] > 0 ? chalk.gray(" (files cached for future deployments)") : "";
248
- spinner.succeed(
249
- `Folder uploaded: ${chalk.green(txOrManifestId)}${statsMsg}${cacheMsg}`
250
- );
251
- }
252
- }
253
- } catch (uploadError) {
254
- spinner.fail("Upload failed");
255
- const errorMessage = uploadError instanceof Error ? uploadError.message : String(uploadError);
256
- this.error(`Upload failed: ${errorMessage}`);
257
- }
258
123
  this.log("");
259
124
  spinner.start("Updating ANT record");
125
+ const { signer } = createSigner(deployConfig["sig-type"], deployKey);
260
126
  const ant = ANT.init({ processId: arnsNameRecord.processId, signer });
261
127
  await ant.setRecord(
262
128
  {
@@ -288,21 +154,25 @@ class Deploy extends Command {
288
154
  });
289
155
  table.push(
290
156
  ["Tx ID", chalk.green(txOrManifestId)],
157
+ ...deployConfig.uploader ? [["Bundler service", chalk.cyan(deployConfig.uploader)]] : [],
291
158
  ["ArNS Name", chalk.yellow(deployConfig["arns-name"])],
292
159
  ["Undername", chalk.yellow(deployConfig.undername)],
293
160
  ["ANT", chalk.cyan(arnsNameRecord.processId)],
294
161
  ["ARIO Process", chalk.gray(arioProcess)],
295
- ["TTL Seconds", chalk.blue(deployConfig["ttl-seconds"])]
162
+ ["TTL Seconds", chalk.blue(deployConfig["ttl-seconds"])],
163
+ ["Arweave URL", chalk.yellow(`https://arweave.net/${txOrManifestId}`)]
296
164
  );
165
+ const isCI = Boolean(process.env.CI);
297
166
  const successMessage = boxen(
298
- `${chalk.green.bold("Deployment Successful!")}
167
+ `${chalk.green.bold("Deployment Successful!")}
299
168
 
300
169
  ${table.toString()}`,
301
170
  {
302
171
  borderColor: "green",
303
- borderStyle: "round",
172
+ borderStyle: isCI ? "single" : "round",
173
+ fullscreen: isCI ? (width) => [width, 0] : void 0,
304
174
  padding: 1,
305
- title: chalk.bold("🚀 Permaweb Deploy"),
175
+ title: chalk.bold("Permaweb Deploy"),
306
176
  titleAlignment: "center"
307
177
  }
308
178
  );
@@ -315,7 +185,7 @@ ${successMessage}`);
315
185
  }
316
186
  } catch (error) {
317
187
  if (error instanceof Error && error.name === "ExitPromptError") {
318
- this.log(chalk.yellow("\n\n👋 Deployment cancelled"));
188
+ this.log(chalk.yellow("\n\nDeployment cancelled"));
319
189
  this.exit(0);
320
190
  }
321
191
  throw error;
@@ -1 +1 @@
1
- {"version":3,"file":"deploy.js","sources":["../../src/commands/deploy.ts"],"sourcesContent":["import fs from 'node:fs'\nimport path from 'node:path'\n\nimport { ANT, AOProcess, ARIO } from '@ar.io/sdk'\nimport {\n ARIOToTokenAmount,\n ETHToTokenAmount,\n OnDemandFunding,\n TurboFactory,\n} from '@ardrive/turbo-sdk'\nimport { Command } from '@oclif/core'\nimport { connect } from '@permaweb/aoconnect'\nimport boxen from 'boxen'\nimport chalk from 'chalk'\nimport Table from 'cli-table3'\nimport ora from 'ora'\n\nimport { type DeployConfig, deployFlagConfigs } from '../constants/flags.js'\nimport { promptAdvancedOptions } from '../prompts/arns.js'\nimport { getWalletConfig } from '../prompts/wallet.js'\nimport type { SignerType } from '../types/index.js'\nimport { cleanupCache, loadCache, saveCache } from '../utils/cache.js'\nimport { extractFlags, resolveConfig } from '../utils/config-resolver.js'\nimport { expandPath } from '../utils/path.js'\nimport { createSigner } from '../utils/signer.js'\nimport { type FolderUploadResult, uploadFile, uploadFolder } from '../utils/uploader.js'\n\nfunction getFolderSize(folderPath: string): number {\n let totalSize = 0\n\n for (const item of fs.readdirSync(folderPath)) {\n const fullPath = path.join(folderPath, item)\n const stats = fs.statSync(fullPath)\n\n totalSize += stats.isDirectory() ? getFolderSize(fullPath) : stats.size\n }\n\n return totalSize\n}\n\nexport default class Deploy extends Command {\n static override args = {}\n\n static override description = 'Deploy your application to the permaweb'\n\n static override examples = [\n '<%= config.bin %> deploy # Interactive mode',\n '<%= config.bin %> deploy --arns-name my-app --wallet ./wallet.json',\n '<%= config.bin %> deploy --arns-name my-app --private-key \"$(cat wallet.json)\"',\n '<%= config.bin %> deploy --arns-name my-app --undername staging',\n '<%= config.bin %> deploy --arns-name my-app --deploy-file ./dist/index.html',\n '<%= config.bin %> deploy --arns-name my-app --sig-type ethereum --wallet ./private-key.txt',\n '<%= config.bin %> deploy --arns-name my-app --sig-type ethereum --private-key \"0x...\"',\n '<%= config.bin %> deploy --arns-name my-app --on-demand ario --max-token-amount 1000',\n ]\n\n static override flags = extractFlags(deployFlagConfigs)\n\n public async run(): Promise<void> {\n try {\n const { flags } = await this.parse(Deploy)\n\n // Check if we need interactive mode (no arns-name provided)\n const interactive = !flags['arns-name']\n\n if (interactive) {\n this.log(chalk.cyan.bold('\\n🎯 Interactive Deployment Mode\\n'))\n }\n\n // Resolve base configuration - prompts will run automatically in interactive mode\n const baseConfig = (await resolveConfig<typeof deployFlagConfigs>(deployFlagConfigs, flags, {\n interactive,\n })) as DeployConfig\n\n // Handle wallet configuration (shared between wallet and privateKey)\n let walletConfig: { privateKey?: string; wallet?: string } = {\n privateKey: baseConfig['private-key'],\n wallet: baseConfig.wallet,\n }\n\n if (interactive && !baseConfig.wallet && !baseConfig['private-key']) {\n const config = await getWalletConfig()\n walletConfig = {\n privateKey: config.privateKey,\n wallet: config.wallet,\n }\n }\n\n // Handle advanced options (shared between ttlSeconds, undername, arioProcess, onDemand, maxTokenAmount)\n let advancedOptions:\n | {\n arioProcess: string\n maxTokenAmount?: string\n onDemand?: string\n ttlSeconds: string\n undername: string\n }\n | undefined\n\n if (interactive) {\n const options = await promptAdvancedOptions()\n advancedOptions = options || undefined\n }\n\n // Build final config with shared prompt results\n // When --no-dedupe is set, use 0 for max entries to disable caching\n const effectiveCacheMaxEntries = baseConfig['no-dedupe']\n ? 0\n : baseConfig['dedupe-cache-max-entries']\n\n const deployConfig: DeployConfig = {\n 'ario-process': advancedOptions?.arioProcess || baseConfig['ario-process'],\n 'arns-name': baseConfig['arns-name'],\n 'dedupe-cache-max-entries': effectiveCacheMaxEntries,\n 'deploy-file': baseConfig['deploy-file'],\n 'deploy-folder': baseConfig['deploy-folder'],\n 'max-token-amount': advancedOptions?.maxTokenAmount || baseConfig['max-token-amount'],\n 'no-dedupe': baseConfig['no-dedupe'],\n 'on-demand': advancedOptions?.onDemand || baseConfig['on-demand'],\n 'private-key': walletConfig.privateKey,\n 'sig-type': baseConfig['sig-type'],\n 'ttl-seconds': advancedOptions?.ttlSeconds || baseConfig['ttl-seconds'],\n undername: advancedOptions?.undername || baseConfig.undername,\n wallet: walletConfig.wallet,\n }\n\n if (interactive) {\n this.log('')\n }\n\n // Get deploy key from wallet file, private-key flag, or environment variable\n let deployKey: string\n if (deployConfig.wallet) {\n const walletPath = expandPath(deployConfig.wallet)\n if (!fs.existsSync(walletPath)) {\n this.error(`Wallet file [${deployConfig.wallet}] does not exist`)\n }\n\n const walletContent = fs.readFileSync(walletPath, 'utf8')\n // For Arweave wallets (JWK), encode to base64. For others (private keys), use as-is\n deployKey =\n deployConfig['sig-type'] === 'arweave'\n ? Buffer.from(walletContent).toString('base64')\n : walletContent.trim()\n } else if (deployConfig['private-key']) {\n // For Arweave wallets (JWK JSON), encode to base64. For others, use as-is\n deployKey =\n deployConfig['sig-type'] === 'arweave'\n ? Buffer.from(deployConfig['private-key']).toString('base64')\n : deployConfig['private-key'].trim()\n } else {\n deployKey = process.env.DEPLOY_KEY || ''\n if (!deployKey) {\n this.error(\n 'DEPLOY_KEY environment variable not set. Use --wallet, --private-key, or set DEPLOY_KEY',\n )\n }\n }\n\n // All validation is now handled in resolveDeployConfig\n const arioProcess = deployConfig['ario-process']\n\n this.log(chalk.cyan.bold('\\n🚀 Starting deployment...\\n'))\n try {\n // Initialize ARIO\n const spinner = ora('Initializing ARIO').start()\n\n const ao = connect({\n CU_URL: 'https://cu.ardrive.io',\n MODE: 'legacy',\n MU_URL: 'https://mu.ao-testnet.xyz',\n })\n\n const ario = ARIO.init({\n process: new AOProcess({\n ao,\n processId: arioProcess,\n }),\n })\n\n spinner.succeed('ARIO initialized')\n\n // Get ArNS record\n spinner.start(`Fetching ArNS record for ${chalk.yellow(deployConfig['arns-name'])}`)\n const arnsNameRecord = await ario\n .getArNSRecord({ name: deployConfig['arns-name'] })\n .catch(() => {\n spinner.fail(`ArNS name ${chalk.red(deployConfig['arns-name'])} does not exist`)\n this.error(`ArNS name [${deployConfig['arns-name']}] does not exist`)\n })\n\n spinner.succeed(`ArNS record fetched for ${chalk.green(deployConfig['arns-name'])}`)\n\n // Create signer\n spinner.start('Creating signer')\n const { signer, token } = createSigner(deployConfig['sig-type'] as SignerType, deployKey)\n spinner.succeed(`Signer created (${chalk.cyan(deployConfig['sig-type'])})`)\n\n // Initialize Turbo\n spinner.start('Initializing Turbo')\n const turbo = TurboFactory.authenticated({\n signer,\n token,\n })\n spinner.succeed('Turbo initialized')\n\n // Create on-demand funding mode if specified\n let fundingMode: OnDemandFunding | undefined\n if (deployConfig['on-demand'] && deployConfig['max-token-amount']) {\n const tokenType = deployConfig['on-demand']\n const maxAmount = Number.parseFloat(deployConfig['max-token-amount'])\n\n let maxTokenAmount: ReturnType<typeof ARIOToTokenAmount>\n switch (tokenType) {\n case 'ario': {\n maxTokenAmount = ARIOToTokenAmount(maxAmount)\n break\n }\n\n case 'base-eth': {\n maxTokenAmount = ETHToTokenAmount(maxAmount)\n break\n }\n\n default: {\n throw new Error(`Unsupported on-demand token type: ${tokenType}`)\n }\n }\n\n fundingMode = new OnDemandFunding({\n maxTokenAmount,\n topUpBufferMultiplier: 1.1,\n })\n }\n\n if (!fundingMode) {\n spinner.start('Checking Turbo credits for upload')\n\n try {\n // Figure out how many bytes we're about to upload\n const uploadBytes = deployConfig['deploy-file']\n ? (() => {\n const filePath = expandPath(deployConfig['deploy-file']!)\n return fs.statSync(filePath).size\n })()\n : (() => {\n const folderPath = expandPath(deployConfig['deploy-folder']!)\n return getFolderSize(folderPath)\n })()\n\n const FREE_THRESHOLD_BYTES = 107_520 // ~105 KiB\n\n if (uploadBytes >= FREE_THRESHOLD_BYTES) {\n // Ask Turbo how many winc this upload will cost, and compare to current balance\n const [uploadCost] = await turbo.getUploadCosts({ bytes: [uploadBytes] })\n const balance = await turbo.getBalance()\n\n // These come back as strings; treat them as big integers\n const requiredWinc = BigInt(uploadCost.winc)\n const currentWinc = BigInt(balance.winc)\n\n if (requiredWinc > currentWinc) {\n spinner.fail('Insufficient Turbo credits')\n\n this.error(\n [\n 'Insufficient Turbo credits for this upload.',\n `Required: ${requiredWinc.toString()} winc, available: ${currentWinc.toString()} winc.`,\n '',\n 'Top up your Turbo balance (or re-run with --on-demand and --max-token-amount).',\n ].join(' '),\n )\n }\n }\n\n spinner.succeed('Turbo credits check passed')\n } catch (balanceError) {\n spinner.fail('Failed to check Turbo credits')\n const errorMessage =\n balanceError instanceof Error ? balanceError.message : String(balanceError)\n this.error(`Failed to check Turbo credits: ${errorMessage}`)\n }\n }\n\n // Upload file or folder\n let txOrManifestId: string\n try {\n if (deployConfig['deploy-file']) {\n const filePath = expandPath(deployConfig['deploy-file'])\n spinner.start(`Uploading file ${chalk.yellow(deployConfig['deploy-file'])}`)\n\n // Load cache for file uploads (skip if dedupe is disabled)\n let cache = deployConfig['dedupe-cache-max-entries'] > 0 ? loadCache() : {}\n const uploadResult = await uploadFile(turbo, filePath, { cache, fundingMode })\n\n if (!uploadResult.transactionId) {\n spinner.fail('File upload failed: no transaction ID returned')\n this.error('File upload failed: no transaction ID returned')\n }\n\n txOrManifestId = uploadResult.transactionId\n\n // Update cache if it was modified and dedupe is enabled\n if (uploadResult.updatedCache && deployConfig['dedupe-cache-max-entries'] > 0) {\n cache = cleanupCache(\n uploadResult.updatedCache,\n deployConfig['dedupe-cache-max-entries'],\n )\n saveCache(cache)\n }\n\n if (uploadResult.cacheHit) {\n spinner.succeed(`File cache hit - reusing transaction ${chalk.green(txOrManifestId)}`)\n } else {\n const cacheMsg =\n deployConfig['dedupe-cache-max-entries'] > 0\n ? chalk.gray('(cached for future deployments)')\n : ''\n spinner.succeed(`File uploaded: ${chalk.green(txOrManifestId)} ${cacheMsg}`.trim())\n }\n } else {\n const folderPath = expandPath(deployConfig['deploy-folder'])\n spinner.start(`Uploading folder ${chalk.yellow(deployConfig['deploy-folder'])}`)\n\n // Load cache for folder uploads (skip if dedupe is disabled)\n let cache = deployConfig['dedupe-cache-max-entries'] > 0 ? loadCache() : {}\n const uploadResult: FolderUploadResult = await uploadFolder(turbo, folderPath, {\n cache,\n fundingMode,\n throwOnFailure: true,\n })\n\n if (!uploadResult.transactionId) {\n spinner.fail('Folder upload failed: no transaction ID returned')\n this.error('Folder upload failed: no transaction ID returned')\n }\n\n txOrManifestId = uploadResult.transactionId\n\n // Update cache if it was modified and dedupe is enabled\n if (uploadResult.updatedCache && deployConfig['dedupe-cache-max-entries'] > 0) {\n cache = cleanupCache(\n uploadResult.updatedCache,\n deployConfig['dedupe-cache-max-entries'],\n )\n saveCache(cache)\n }\n\n // Build the success message with cache stats\n const { cacheHits, totalFiles, uploaded } = uploadResult\n const statsMsg =\n cacheHits > 0\n ? chalk.gray(` (${cacheHits}/${totalFiles} files cached, ${uploaded} uploaded)`)\n : ''\n\n if (uploadResult.cacheHit) {\n // All files were cache hits\n spinner.succeed(\n `All ${totalFiles} files cached - manifest: ${chalk.green(txOrManifestId)}`,\n )\n } else {\n const cacheMsg =\n deployConfig['dedupe-cache-max-entries'] > 0\n ? chalk.gray(' (files cached for future deployments)')\n : ''\n spinner.succeed(\n `Folder uploaded: ${chalk.green(txOrManifestId)}${statsMsg}${cacheMsg}`,\n )\n }\n }\n } catch (uploadError) {\n spinner.fail('Upload failed')\n const errorMessage =\n uploadError instanceof Error ? uploadError.message : String(uploadError)\n this.error(`Upload failed: ${errorMessage}`)\n }\n\n this.log('')\n\n // Initialize ANT and update record\n spinner.start('Updating ANT record')\n const ant = ANT.init({ processId: arnsNameRecord.processId, signer })\n\n await ant.setRecord(\n {\n transactionId: txOrManifestId,\n ttlSeconds: Number.parseInt(deployConfig['ttl-seconds'], 10),\n undername: deployConfig.undername,\n },\n {\n tags: [\n {\n name: 'App-Name',\n value: 'Permaweb-Deploy',\n },\n ...(process.env.GITHUB_SHA\n ? [\n {\n name: 'GIT-HASH',\n value: process.env.GITHUB_SHA,\n },\n ]\n : []),\n ],\n },\n )\n\n spinner.succeed('ANT record updated')\n\n // Display deployment details in a table inside a success box\n const table = new Table({\n head: [chalk.cyan.bold('Property'), chalk.cyan.bold('Value')],\n style: {\n head: [],\n },\n })\n\n table.push(\n ['Tx ID', chalk.green(txOrManifestId)],\n ['ArNS Name', chalk.yellow(deployConfig['arns-name'])],\n ['Undername', chalk.yellow(deployConfig.undername)],\n ['ANT', chalk.cyan(arnsNameRecord.processId)],\n ['ARIO Process', chalk.gray(arioProcess)],\n ['TTL Seconds', chalk.blue(deployConfig['ttl-seconds'])],\n )\n\n const successMessage = boxen(\n `${chalk.green.bold('✨ Deployment Successful!')}\\n\\n${table.toString()}`,\n {\n borderColor: 'green',\n borderStyle: 'round',\n padding: 1,\n title: chalk.bold('🚀 Permaweb Deploy'),\n titleAlignment: 'center',\n },\n )\n\n this.log(`\\n${successMessage}`)\n } catch (error) {\n this.error(\n chalk.red(`Deployment failed: ${error instanceof Error ? error.message : String(error)}`),\n )\n }\n } catch (error) {\n // Handle user cancellation (Ctrl+C)\n if (error instanceof Error && error.name === 'ExitPromptError') {\n this.log(chalk.yellow('\\n\\n👋 Deployment cancelled'))\n this.exit(0)\n }\n\n throw error\n }\n }\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"deploy.js","sources":["../../src/commands/deploy.ts"],"sourcesContent":["import fs from 'node:fs'\n\nimport { ANT, AOProcess, ARIO } from '@ar.io/sdk'\nimport { Command } from '@oclif/core'\nimport { connect } from '@permaweb/aoconnect'\nimport boxen from 'boxen'\nimport chalk from 'chalk'\n// eslint-disable-next-line import/no-named-as-default\nimport Table from 'cli-table3'\nimport ora from 'ora'\n\nimport { type DeployConfig, deployFlagConfigs } from '../constants/flags.js'\nimport { promptAdvancedOptions } from '../prompts/arns.js'\nimport { getWalletConfig } from '../prompts/wallet.js'\nimport type { SignerType } from '../types/index.js'\nimport { extractFlags, resolveConfig } from '../utils/config-resolver.js'\nimport { expandPath } from '../utils/path.js'\nimport { createSigner } from '../utils/signer.js'\nimport { runUploadWorkflow } from '../workflows/upload-workflow.js'\n\nexport default class Deploy extends Command {\n static override args = {}\n\n static override description = 'Deploy your application to the permaweb'\n\n static override examples = [\n '<%= config.bin %> deploy # Interactive mode',\n '<%= config.bin %> deploy --arns-name my-app --wallet ./wallet.json',\n '<%= config.bin %> deploy --arns-name my-app --private-key \"$(cat wallet.json)\"',\n '<%= config.bin %> deploy --arns-name my-app --undername staging',\n '<%= config.bin %> deploy --arns-name my-app --deploy-file ./dist/index.html',\n '<%= config.bin %> deploy --arns-name my-app --sig-type ethereum --wallet ./private-key.txt',\n '<%= config.bin %> deploy --arns-name my-app --sig-type ethereum --private-key \"0x...\"',\n '<%= config.bin %> deploy --arns-name my-app --on-demand ario --max-token-amount 1000',\n '<%= config.bin %> deploy --arns-name my-app --uploader https://up.arweave.net',\n '<%= config.bin %> upload --wallet ./wallet.json # Upload only (no ArNS update)',\n ]\n\n static override flags = extractFlags(deployFlagConfigs)\n\n public async run(): Promise<void> {\n try {\n const { flags } = await this.parse(Deploy)\n\n const interactive = !flags['arns-name']\n\n if (interactive) {\n this.log(chalk.cyan.bold('\\nInteractive Deployment Mode\\n'))\n }\n\n const baseConfig = (await resolveConfig<typeof deployFlagConfigs>(deployFlagConfigs, flags, {\n interactive,\n })) as DeployConfig\n\n let walletConfig: { privateKey?: string; wallet?: string } = {\n privateKey: baseConfig['private-key'],\n wallet: baseConfig.wallet,\n }\n\n if (interactive && !baseConfig.wallet && !baseConfig['private-key']) {\n const config = await getWalletConfig()\n walletConfig = {\n privateKey: config.privateKey,\n wallet: config.wallet,\n }\n }\n\n let advancedOptions:\n | {\n arioProcess: string\n maxTokenAmount?: string\n onDemand?: string\n ttlSeconds: string\n undername: string\n }\n | undefined\n\n if (interactive) {\n const options = await promptAdvancedOptions()\n advancedOptions = options || undefined\n }\n\n const effectiveCacheMaxEntries = baseConfig['no-dedupe']\n ? 0\n : baseConfig['dedupe-cache-max-entries']\n\n const deployConfig: DeployConfig = {\n 'ario-process': advancedOptions?.arioProcess || baseConfig['ario-process'],\n 'arns-name': baseConfig['arns-name'],\n 'dedupe-cache-max-entries': effectiveCacheMaxEntries,\n 'deploy-file': baseConfig['deploy-file'],\n 'deploy-folder': baseConfig['deploy-folder'],\n 'max-token-amount': advancedOptions?.maxTokenAmount || baseConfig['max-token-amount'],\n 'no-dedupe': baseConfig['no-dedupe'],\n 'on-demand': advancedOptions?.onDemand || baseConfig['on-demand'],\n 'private-key': walletConfig.privateKey,\n 'sig-type': baseConfig['sig-type'],\n 'ttl-seconds': advancedOptions?.ttlSeconds || baseConfig['ttl-seconds'],\n undername: advancedOptions?.undername || baseConfig.undername,\n uploader: baseConfig.uploader,\n wallet: walletConfig.wallet,\n }\n\n if (interactive) {\n this.log('')\n }\n\n let deployKey: string\n if (deployConfig.wallet) {\n const walletPath = expandPath(deployConfig.wallet)\n if (!fs.existsSync(walletPath)) {\n this.error(`Wallet file [${deployConfig.wallet}] does not exist`)\n }\n\n const walletContent = fs.readFileSync(walletPath, 'utf8')\n deployKey =\n deployConfig['sig-type'] === 'arweave'\n ? Buffer.from(walletContent).toString('base64')\n : walletContent.trim()\n } else if (deployConfig['private-key']) {\n deployKey =\n deployConfig['sig-type'] === 'arweave'\n ? Buffer.from(deployConfig['private-key']).toString('base64')\n : deployConfig['private-key'].trim()\n } else {\n deployKey = process.env.DEPLOY_KEY || ''\n if (!deployKey) {\n this.error(\n 'DEPLOY_KEY environment variable not set. Use --wallet, --private-key, or set DEPLOY_KEY',\n )\n }\n }\n\n const arioProcess = deployConfig['ario-process']\n\n this.log(chalk.cyan.bold('\\nStarting deployment...\\n'))\n try {\n const spinner = ora()\n\n spinner.start('Initializing ARIO')\n\n const ao = connect({\n CU_URL: 'https://cu.ardrive.io',\n MODE: 'legacy',\n MU_URL: 'https://mu.ao-testnet.xyz',\n })\n\n const ario = ARIO.init({\n process: new AOProcess({\n ao,\n processId: arioProcess,\n }),\n })\n\n spinner.succeed('ARIO initialized')\n\n spinner.start(`Fetching ArNS record for ${chalk.yellow(deployConfig['arns-name'])}`)\n const arnsNameRecord = await ario\n .getArNSRecord({ name: deployConfig['arns-name'] })\n .catch(() => {\n spinner.fail(`ArNS name ${chalk.red(deployConfig['arns-name'])} does not exist`)\n this.error(`ArNS name [${deployConfig['arns-name']}] does not exist`)\n })\n\n spinner.succeed(`ArNS record fetched for ${chalk.green(deployConfig['arns-name'])}`)\n\n const txOrManifestId = await runUploadWorkflow(deployKey, deployConfig, {\n error: (msg) => this.error(msg),\n })\n\n this.log('')\n\n spinner.start('Updating ANT record')\n const { signer } = createSigner(deployConfig['sig-type'] as SignerType, deployKey)\n const ant = ANT.init({ processId: arnsNameRecord.processId, signer })\n\n await ant.setRecord(\n {\n transactionId: txOrManifestId,\n ttlSeconds: Number.parseInt(deployConfig['ttl-seconds'], 10),\n undername: deployConfig.undername,\n },\n {\n tags: [\n {\n name: 'App-Name',\n value: 'Permaweb-Deploy',\n },\n ...(process.env.GITHUB_SHA\n ? [\n {\n name: 'GIT-HASH',\n value: process.env.GITHUB_SHA,\n },\n ]\n : []),\n ],\n },\n )\n\n spinner.succeed('ANT record updated')\n\n const table = new Table({\n head: [chalk.cyan.bold('Property'), chalk.cyan.bold('Value')],\n style: {\n head: [],\n },\n })\n\n table.push(\n ['Tx ID', chalk.green(txOrManifestId)],\n ...(deployConfig.uploader\n ? ([['Bundler service', chalk.cyan(deployConfig.uploader)]] as [string, string][])\n : []),\n ['ArNS Name', chalk.yellow(deployConfig['arns-name'])],\n ['Undername', chalk.yellow(deployConfig.undername)],\n ['ANT', chalk.cyan(arnsNameRecord.processId)],\n ['ARIO Process', chalk.gray(arioProcess)],\n ['TTL Seconds', chalk.blue(deployConfig['ttl-seconds'])],\n ['Arweave URL', chalk.yellow(`https://arweave.net/${txOrManifestId}`)],\n )\n\n const isCI = Boolean(process.env.CI)\n const successMessage = boxen(\n `${chalk.green.bold('Deployment Successful!')}\\n\\n${table.toString()}`,\n {\n borderColor: 'green',\n borderStyle: isCI ? 'single' : 'round',\n fullscreen: isCI ? (width: number) => [width, 0] : undefined,\n padding: 1,\n title: chalk.bold('Permaweb Deploy'),\n titleAlignment: 'center',\n },\n )\n\n this.log(`\\n${successMessage}`)\n } catch (error) {\n this.error(\n chalk.red(`Deployment failed: ${error instanceof Error ? error.message : String(error)}`),\n )\n }\n } catch (error) {\n if (error instanceof Error && error.name === 'ExitPromptError') {\n this.log(chalk.yellow('\\n\\nDeployment cancelled'))\n this.exit(0)\n }\n\n throw error\n }\n }\n}\n"],"names":[],"mappings":"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"}