permaweb-deploy 3.0.1 → 3.2.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.
@@ -1,231 +0,0 @@
1
- import { Readable } from 'node:stream';
2
- import * as mime from 'mime-types';
3
- import crypto from 'node:crypto';
4
- import fs from 'node:fs';
5
- import path from 'node:path';
6
- import { C as CACHE_DIR, a as CACHE_FILE } from './cache-BssFyqB-.js';
7
-
8
- function getCachePath() {
9
- return path.join(process.cwd(), CACHE_DIR, CACHE_FILE);
10
- }
11
- function loadCache() {
12
- const cachePath = getCachePath();
13
- try {
14
- if (!fs.existsSync(cachePath)) {
15
- return {};
16
- }
17
- const content = fs.readFileSync(cachePath, "utf8");
18
- return JSON.parse(content);
19
- } catch {
20
- return {};
21
- }
22
- }
23
- function saveCache(cache) {
24
- const cachePath = getCachePath();
25
- const cacheDir = path.dirname(cachePath);
26
- if (!fs.existsSync(cacheDir)) {
27
- fs.mkdirSync(cacheDir, { recursive: true });
28
- }
29
- fs.writeFileSync(cachePath, JSON.stringify(cache, null, 2), "utf8");
30
- }
31
- async function hashFile(filePath) {
32
- return new Promise((resolve, reject) => {
33
- const hash = crypto.createHash("sha256");
34
- const stream = fs.createReadStream(filePath);
35
- stream.on("data", (chunk) => hash.update(chunk));
36
- stream.on("end", () => resolve(hash.digest("hex")));
37
- stream.on("error", reject);
38
- });
39
- }
40
- function getAllFiles(dirPath, basePath = dirPath) {
41
- const files = [];
42
- for (const item of fs.readdirSync(dirPath)) {
43
- const fullPath = path.join(dirPath, item);
44
- const stats = fs.statSync(fullPath);
45
- if (stats.isDirectory()) {
46
- files.push(...getAllFiles(fullPath, basePath));
47
- } else {
48
- files.push(path.relative(basePath, fullPath));
49
- }
50
- }
51
- return files;
52
- }
53
- async function hashFolder(folderPath) {
54
- const files = getAllFiles(folderPath).sort();
55
- const combinedHash = crypto.createHash("sha256");
56
- for (const relativePath of files) {
57
- const fullPath = path.join(folderPath, relativePath);
58
- const fileHash = await hashFile(fullPath);
59
- combinedHash.update(`${relativePath}:${fileHash}
60
- `);
61
- }
62
- return combinedHash.digest("hex");
63
- }
64
- function getCachedTransaction(cache, hash) {
65
- return cache[hash];
66
- }
67
- function setCachedTransaction(cache, hash, transactionId) {
68
- const now = Date.now();
69
- const existing = cache[hash];
70
- return {
71
- ...cache,
72
- [hash]: {
73
- createdAtTimestamp: existing?.createdAtTimestamp ?? now,
74
- lastUsedTimestamp: now,
75
- transactionId
76
- }
77
- };
78
- }
79
- function touchCacheEntry(cache, hash) {
80
- const existing = cache[hash];
81
- if (!existing) {
82
- return cache;
83
- }
84
- return {
85
- ...cache,
86
- [hash]: {
87
- ...existing,
88
- lastUsedTimestamp: Date.now()
89
- }
90
- };
91
- }
92
- function cleanupCache(cache, maxEntries) {
93
- const entries = Object.entries(cache);
94
- if (entries.length <= maxEntries) {
95
- return cache;
96
- }
97
- const sorted = entries.sort(([, a], [, b]) => b.lastUsedTimestamp - a.lastUsedTimestamp);
98
- const kept = sorted.slice(0, maxEntries);
99
- return Object.fromEntries(kept);
100
- }
101
-
102
- async function uploadFile(turbo, filePath, options) {
103
- const mimeType = mime.lookup(filePath) || "application/octet-stream";
104
- const fileHash = options?.cache ? await hashFile(filePath) : void 0;
105
- if (fileHash && options?.cache) {
106
- const cached = getCachedTransaction(options.cache, fileHash);
107
- if (cached) {
108
- const updatedCache = touchCacheEntry(options.cache, fileHash);
109
- return {
110
- cacheHit: true,
111
- transactionId: cached.transactionId,
112
- updatedCache
113
- };
114
- }
115
- }
116
- const uploadResult = await turbo.uploadFile({
117
- dataItemOpts: {
118
- tags: [
119
- {
120
- name: "App-Name",
121
- value: "Permaweb-Deploy"
122
- },
123
- {
124
- name: "anchor",
125
- value: (/* @__PURE__ */ new Date()).toISOString()
126
- },
127
- {
128
- name: "Content-Type",
129
- value: mimeType
130
- }
131
- ]
132
- },
133
- file: filePath,
134
- ...options?.fundingMode && { fundingMode: options.fundingMode }
135
- });
136
- if (!uploadResult?.id) {
137
- throw new Error("Failed to upload file: upload result missing transaction ID");
138
- }
139
- if (fileHash && options?.cache) {
140
- const updatedCache = setCachedTransaction(options.cache, fileHash, uploadResult.id);
141
- return {
142
- cacheHit: false,
143
- transactionId: uploadResult.id,
144
- updatedCache
145
- };
146
- }
147
- return {
148
- cacheHit: false,
149
- transactionId: uploadResult.id
150
- };
151
- }
152
- async function uploadFolder(turbo, folderPath, options) {
153
- const folderHash = options?.cache ? await hashFolder(folderPath) : void 0;
154
- if (folderHash && options?.cache) {
155
- const cached = getCachedTransaction(options.cache, folderHash);
156
- if (cached) {
157
- const updatedCache = touchCacheEntry(options.cache, folderHash);
158
- return {
159
- cacheHit: true,
160
- transactionId: cached.transactionId,
161
- updatedCache
162
- };
163
- }
164
- }
165
- const uploadResult = await turbo.uploadFolder({
166
- dataItemOpts: {
167
- tags: [
168
- {
169
- name: "App-Name",
170
- value: "Permaweb-Deploy"
171
- },
172
- {
173
- name: "anchor",
174
- value: (/* @__PURE__ */ new Date()).toISOString()
175
- }
176
- ]
177
- },
178
- folderPath,
179
- ...options?.fundingMode && {
180
- fundingMode: options.fundingMode,
181
- throwOnFailure: options.throwOnFailure
182
- }
183
- });
184
- let txOrManifestId = uploadResult.manifestResponse?.id;
185
- const origPaths = uploadResult.manifest?.paths || {};
186
- const newPaths = {};
187
- let replaceManifest = false;
188
- for (const [key, value] of Object.entries(origPaths)) {
189
- newPaths[key] = value;
190
- if (key.endsWith("/index.html")) {
191
- const newKey = key.replace(/\/index\.html$/, "");
192
- newPaths[newKey] = value;
193
- replaceManifest = true;
194
- }
195
- }
196
- if (replaceManifest && uploadResult.manifest) {
197
- console.info("Replacing manifest to support directory indexes");
198
- const newManifest = { ...uploadResult.manifest, paths: newPaths };
199
- const buffer = Buffer.from(JSON.stringify(newManifest));
200
- const manifestUploadResult = await turbo.uploadFile({
201
- dataItemOpts: {
202
- tags: [{ name: "Content-Type", value: "application/x.arweave-manifest+json" }]
203
- },
204
- fileSizeFactory: () => buffer.length,
205
- fileStreamFactory: () => Readable.from(buffer),
206
- ...options?.fundingMode && { fundingMode: options.fundingMode }
207
- });
208
- if (!manifestUploadResult?.id) {
209
- throw new Error("Failed to upload manifest: upload result missing transaction ID");
210
- }
211
- txOrManifestId = manifestUploadResult.id;
212
- }
213
- if (!txOrManifestId) {
214
- throw new Error("Failed to upload folder");
215
- }
216
- if (folderHash && options?.cache) {
217
- const updatedCache = setCachedTransaction(options.cache, folderHash, txOrManifestId);
218
- return {
219
- cacheHit: false,
220
- transactionId: txOrManifestId,
221
- updatedCache
222
- };
223
- }
224
- return {
225
- cacheHit: false,
226
- transactionId: txOrManifestId
227
- };
228
- }
229
-
230
- export { uploadFolder as a, cleanupCache as c, loadCache as l, saveCache as s, uploadFile as u };
231
- //# sourceMappingURL=uploader-DifbCz3u.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"uploader-DifbCz3u.js","sources":["../../src/utils/cache.ts","../../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 */\nfunction 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 * Compute a combined SHA-256 hash of all files in a folder\n * Files are sorted by relative path for consistent ordering\n */\nexport async function hashFolder(folderPath: string): Promise<string> {\n const files = getAllFiles(folderPath).sort()\n const combinedHash = crypto.createHash('sha256')\n\n for (const relativePath of files) {\n const fullPath = path.join(folderPath, relativePath)\n const fileHash = await hashFile(fullPath)\n // Include both the relative path and file hash for uniqueness\n combinedHash.update(`${relativePath}:${fileHash}\\n`)\n }\n\n return combinedHash.digest('hex')\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","import { Readable } from 'node:stream'\n\nimport { OnDemandFunding, type TurboAuthenticatedClient } from '@ardrive/turbo-sdk'\nimport * as mime from 'mime-types'\n\nimport {\n getCachedTransaction,\n hashFile,\n hashFolder,\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 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\nexport async function uploadFolder(\n turbo: TurboAuthenticatedClient,\n folderPath: string,\n options?: {\n cache?: TransactionCache\n fundingMode?: OnDemandFunding\n throwOnFailure?: boolean\n },\n): Promise<UploadResult> {\n // Compute hash if cache is provided\n const folderHash = options?.cache ? await hashFolder(folderPath) : undefined\n\n // Check cache for hit\n if (folderHash && options?.cache) {\n const cached = getCachedTransaction(options.cache, folderHash)\n if (cached) {\n const updatedCache = touchCacheEntry(options.cache, folderHash)\n return {\n cacheHit: true,\n transactionId: cached.transactionId,\n updatedCache,\n }\n }\n }\n\n const uploadResult = await turbo.uploadFolder({\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 },\n folderPath,\n ...(options?.fundingMode && {\n fundingMode: options.fundingMode,\n throwOnFailure: options.throwOnFailure,\n }),\n })\n\n let txOrManifestId = uploadResult.manifestResponse?.id\n\n // Make default folder paths work by adding extra path entries\n const origPaths = uploadResult.manifest?.paths || {}\n const newPaths: Record<string, { id: string }> = {}\n let replaceManifest = false\n\n for (const [key, value] of Object.entries(origPaths)) {\n newPaths[key] = value\n if (key.endsWith('/index.html')) {\n const newKey = key.replace(/\\/index\\.html$/, '')\n newPaths[newKey] = value\n replaceManifest = true\n }\n }\n\n if (replaceManifest && uploadResult.manifest) {\n console.info('Replacing manifest to support directory indexes')\n const newManifest = { ...uploadResult.manifest, paths: newPaths }\n const buffer = Buffer.from(JSON.stringify(newManifest))\n const manifestUploadResult = await turbo.uploadFile({\n dataItemOpts: {\n tags: [{ name: 'Content-Type', value: 'application/x.arweave-manifest+json' }],\n },\n fileSizeFactory: () => buffer.length,\n fileStreamFactory: () => Readable.from(buffer),\n ...(options?.fundingMode && { fundingMode: options.fundingMode }),\n })\n if (!manifestUploadResult?.id) {\n throw new Error('Failed to upload manifest: upload result missing transaction ID')\n }\n\n txOrManifestId = manifestUploadResult.id\n }\n\n if (!txOrManifestId) {\n throw new Error('Failed to upload folder')\n }\n\n // Store in cache if provided\n if (folderHash && options?.cache) {\n const updatedCache = setCachedTransaction(options.cache, folderHash, txOrManifestId)\n return {\n cacheHit: false,\n transactionId: txOrManifestId,\n updatedCache,\n }\n }\n\n return {\n cacheHit: false,\n transactionId: txOrManifestId,\n }\n}\n"],"names":[],"mappings":"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"}