@@ -107,6 +107,184 @@ program
107107 ) ;
108108 } ) ;
109109
110+ program
111+ . command ( "library" )
112+ . alias ( "lib" )
113+ . description ( "Deploy a public file library to Cloudflare Pages" )
114+ . option (
115+ "-n, --name <name>" ,
116+ "Project name for Cloudflare Pages" ,
117+ "quick-share-library" ,
118+ )
119+ . option ( "-d, --domain <domain>" , "Custom domain (optional)" )
120+ . action ( async ( options ) => {
121+ console . log ( chalk . blue ( "⚡ Deploying File Library...\n" ) ) ;
122+
123+ // Check for wrangler
124+ try {
125+ execSync ( "which wrangler" , { stdio : "ignore" } ) ;
126+ } catch ( e ) {
127+ console . log ( chalk . yellow ( "Installing wrangler..." ) ) ;
128+ execSync ( "npm install -g wrangler" , { stdio : "inherit" } ) ;
129+ }
130+
131+ // Check if logged in
132+ try {
133+ execSync ( "wrangler whoami" , { stdio : "ignore" } ) ;
134+ } catch ( e ) {
135+ console . log ( chalk . red ( "Please run: wrangler login" ) ) ;
136+ process . exit ( 1 ) ;
137+ }
138+
139+ // Create temp directory
140+ const tempDir = require ( "os" ) . tmpdir ( ) ;
141+ const libDir = path . join ( __dirname , ".." , "assets" , "library" ) ;
142+ const deployDir = path . join ( tempDir , "quick-share-lib-deploy" ) ;
143+
144+ // Copy library files
145+ execSync ( `rm -rf "${ deployDir } " && cp -r "${ libDir } " "${ deployDir } "` ) ;
146+
147+ // Update config in index.html
148+ const config = validateConfig ( ) ;
149+ const indexPath = path . join ( deployDir , "index.html" ) ;
150+ let indexHtml = fs . readFileSync ( indexPath , "utf8" ) ;
151+ indexHtml = indexHtml . replace (
152+ / c o n s t P U B L I C _ U R L = ' .* ' ; / ,
153+ `const PUBLIC_URL = '${ config . publicUrl } ';` ,
154+ ) ;
155+ fs . writeFileSync ( indexPath , indexHtml ) ;
156+
157+ console . log ( chalk . blue ( "Deploying to Cloudflare Pages..." ) ) ;
158+
159+ try {
160+ execSync (
161+ `cd "${ deployDir } " && wrangler pages project list 2>/dev/null | grep -q "${ options . name } " || wrangler pages project create "${ options . name } "` ,
162+ { stdio : "pipe" } ,
163+ ) ;
164+ } catch ( e ) {
165+ // Project might already exist
166+ }
167+
168+ execSync (
169+ `cd "${ deployDir } " && wrangler pages deploy . --project-name="${ options . name } "` ,
170+ { stdio : "inherit" } ,
171+ ) ;
172+
173+ console . log ( chalk . green ( "\n✓ Library deployed!" ) ) ;
174+ console . log ( chalk . blue ( "\nYour library is live at:" ) ) ;
175+ console . log ( chalk . white ( ` https://${ options . name } .pages.dev` ) ) ;
176+
177+ if ( options . domain ) {
178+ console . log ( chalk . blue ( "\nAdding custom domain..." ) ) ;
179+ execSync (
180+ `wrangler pages domain add "${ options . name } " "${ options . domain } "` ,
181+ { stdio : "inherit" } ,
182+ ) ;
183+ console . log ( chalk . green ( `✓ Domain ${ options . domain } connected!` ) ) ;
184+ }
185+
186+ // Cleanup
187+ execSync ( `rm -rf "${ deployDir } "` ) ;
188+
189+ console . log ( chalk . blue ( "\nNext steps:" ) ) ;
190+ console . log (
191+ " 1. Deploy a Worker to list R2 files (see: quick-share library --worker)" ,
192+ ) ;
193+ console . log ( " 2. Update WORKER_URL in your library to use the worker" ) ;
194+ } ) ;
195+
196+ program
197+ . command ( "worker" )
198+ . description ( "Deploy a Cloudflare Worker that lists R2 files" )
199+ . option ( "-n, --name <name>" , "Worker name" , "quick-share-api" )
200+ . action ( async ( options ) => {
201+ console . log ( chalk . blue ( "⚡ Deploying API Worker...\n" ) ) ;
202+
203+ // Check for wrangler
204+ try {
205+ execSync ( "which wrangler" , { stdio : "ignore" } ) ;
206+ } catch ( e ) {
207+ console . log ( chalk . yellow ( "Installing wrangler..." ) ) ;
208+ execSync ( "npm install -g wrangler" , { stdio : "inherit" } ) ;
209+ }
210+
211+ const config = validateConfig ( ) ;
212+ const workerContent = `addEventListener("fetch", (event) => {
213+ event.respondWith(handleRequest(event.request));
214+ });
215+
216+ async function handleRequest(request) {
217+ const url = new URL(request.url);
218+
219+ const corsHeaders = {
220+ "Access-Control-Allow-Origin": "*",
221+ "Access-Control-Allow-Methods": "GET, OPTIONS",
222+ };
223+
224+ if (request.method === "OPTIONS") {
225+ return new Response(null, { headers: corsHeaders });
226+ }
227+
228+ if (url.pathname !== "/files" && url.pathname !== "/files.json") {
229+ return new Response("Not Found", { status: 404 });
230+ }
231+
232+ try {
233+ const list = await R2_BUCKET.list({ limit: 1000 });
234+
235+ const files = list.objects.map(obj => ({
236+ name: obj.key,
237+ size: obj.size,
238+ uploadedAt: obj.uploaded,
239+ }));
240+
241+ return new Response(JSON.stringify({ files }, null, 2), {
242+ headers: { "Content-Type": "application/json", ...corsHeaders },
243+ });
244+ } catch (error) {
245+ return new Response(JSON.stringify({ error: error.message }), {
246+ status: 500,
247+ headers: { "Content-Type": "application/json" },
248+ });
249+ }
250+ }` ;
251+
252+ // Write wrangler.toml
253+ const tempDir = require ( "os" ) . tmpdir ( ) ;
254+ const workerDir = path . join ( tempDir , "quick-share-worker" ) ;
255+ execSync ( `rm -rf "${ workerDir } " && mkdir -p "${ workerDir } "` ) ;
256+
257+ const wranglerToml = `
258+ name = "${ options . name } "
259+ main = "index.js"
260+ compatibility_date = "2023-12-01"
261+
262+ [[r2_buckets]]
263+ binding = "R2_BUCKET"
264+ bucket_name = "${ config . bucketName } "
265+ ` ;
266+
267+ fs . writeFileSync ( path . join ( workerDir , "wrangler.toml" ) , wranglerToml ) ;
268+ fs . writeFileSync ( path . join ( workerDir , "index.js" ) , workerContent ) ;
269+
270+ console . log ( chalk . blue ( "Deploying worker..." ) ) ;
271+ execSync ( `cd "${ workerDir } " && wrangler deploy` , { stdio : "inherit" } ) ;
272+
273+ console . log ( chalk . green ( "\n✓ Worker deployed!" ) ) ;
274+ console . log ( chalk . blue ( "\nWorker URL:" ) ) ;
275+ console . log (
276+ chalk . white (
277+ ` https://${ options . name } .${ config . accountId } .workers.dev/files` ,
278+ ) ,
279+ ) ;
280+
281+ // Cleanup
282+ execSync ( `rm -rf "${ workerDir } "` ) ;
283+
284+ console . log ( chalk . blue ( "\nNow update your library:" ) ) ;
285+ console . log ( chalk . white ( ` quick-share library` ) ) ;
286+ } ) ;
287+
110288// Default action - if just a file path is provided
111289program
112290 . arguments ( "<file>" )
0 commit comments