1- import { mkdir , readdir , readFile , stat , writeFile } from "node:fs/promises" ;
2- import { dirname , join , relative , resolve , sep } from "node:path" ;
1+ import { mkdir , readFile , writeFile } from "node:fs/promises" ;
2+ import { dirname } from "node:path" ;
33import { render , Text } from "ink" ;
44import Spinner from "ink-spinner" ;
5- import { getType } from "mime" ;
6- import { Minimatch } from "minimatch" ;
75import PQueue from "p-queue" ;
8- import prettyBytes from "pretty-bytes" ;
96import React from "react" ;
107import { fetchResult } from "../cfetch" ;
118import { FatalError } from "../errors" ;
129import isInteractive from "../is-interactive" ;
1310import { logger } from "../logger" ;
1411import {
15- MAX_ASSET_COUNT ,
16- MAX_ASSET_SIZE ,
1712 BULK_UPLOAD_CONCURRENCY ,
1813 MAX_BUCKET_FILE_COUNT ,
1914 MAX_BUCKET_SIZE ,
2015 MAX_CHECK_MISSING_ATTEMPTS ,
2116 MAX_UPLOAD_ATTEMPTS ,
2217} from "./constants" ;
23- import { hashFile } from "./hash" ;
2418
19+ import { validate } from "./validate" ;
2520import type {
2621 CommonYargsArgv ,
2722 StrictYargsOptionsToInterface ,
2823} from "../yargs-types" ;
2924import type { UploadPayloadFile } from "./types" ;
25+ import type { FileContainer } from "./validate" ;
3026
3127type UploadArgs = StrictYargsOptionsToInterface < typeof Options > ;
3228
@@ -62,8 +58,10 @@ export const Handler = async ({
6258 throw new FatalError ( "No JWT given." , 1 ) ;
6359 }
6460
61+ const fileMap = await validate ( { directory } ) ;
62+
6563 const manifest = await upload ( {
66- directory ,
64+ fileMap ,
6765 jwt : process . env . CF_PAGES_UPLOAD_JWT ,
6866 skipCaching : skipCaching ?? false ,
6967 } ) ;
@@ -79,12 +77,12 @@ export const Handler = async ({
7977export const upload = async (
8078 args :
8179 | {
82- directory : string ;
80+ fileMap : Map < string , FileContainer > ;
8381 jwt : string ;
8482 skipCaching : boolean ;
8583 }
8684 | {
87- directory : string ;
85+ fileMap : Map < string , FileContainer > ;
8886 accountId : string ;
8987 projectName : string ;
9088 skipCaching : boolean ;
@@ -102,95 +100,7 @@ export const upload = async (
102100 }
103101 }
104102
105- type FileContainer = {
106- path : string ;
107- contentType : string ;
108- sizeInBytes : number ;
109- hash : string ;
110- } ;
111-
112- const IGNORE_LIST = [
113- "_worker.js" ,
114- "_redirects" ,
115- "_headers" ,
116- "_routes.json" ,
117- "functions" ,
118- "**/.DS_Store" ,
119- "**/node_modules" ,
120- "**/.git" ,
121- ] . map ( ( pattern ) => new Minimatch ( pattern ) ) ;
122-
123- const directory = resolve ( args . directory ) ;
124-
125- // TODO(future): Use this to more efficiently load files in and speed up uploading
126- // Limit memory to 1 GB unless more is specified
127- // let maxMemory = 1_000_000_000;
128- // if (process.env.NODE_OPTIONS && (process.env.NODE_OPTIONS.includes('--max-old-space-size=') || process.env.NODE_OPTIONS.includes('--max_old_space_size='))) {
129- // const parsed = parser(process.env.NODE_OPTIONS);
130- // maxMemory = (parsed['max-old-space-size'] ? parsed['max-old-space-size'] : parsed['max_old_space_size']) * 1000 * 1000; // Turn MB into bytes
131- // }
132-
133- const walk = async (
134- dir : string ,
135- fileMap : Map < string , FileContainer > = new Map ( ) ,
136- startingDir : string = dir
137- ) => {
138- const files = await readdir ( dir ) ;
139-
140- await Promise . all (
141- files . map ( async ( file ) => {
142- const filepath = join ( dir , file ) ;
143- const relativeFilepath = relative ( startingDir , filepath ) ;
144- const filestat = await stat ( filepath ) ;
145-
146- for ( const minimatch of IGNORE_LIST ) {
147- if ( minimatch . match ( relativeFilepath ) ) {
148- return ;
149- }
150- }
151-
152- if ( filestat . isSymbolicLink ( ) ) {
153- return ;
154- }
155-
156- if ( filestat . isDirectory ( ) ) {
157- fileMap = await walk ( filepath , fileMap , startingDir ) ;
158- } else {
159- const name = relativeFilepath . split ( sep ) . join ( "/" ) ;
160-
161- if ( filestat . size > MAX_ASSET_SIZE ) {
162- throw new FatalError (
163- `Error: Pages only supports files up to ${ prettyBytes (
164- MAX_ASSET_SIZE
165- ) } in size\n${ name } is ${ prettyBytes ( filestat . size ) } in size`,
166- 1
167- ) ;
168- }
169-
170- // We don't want to hold the content in memory. We instead only want to read it when it's needed
171- fileMap . set ( name , {
172- path : filepath ,
173- contentType : getType ( name ) || "application/octet-stream" ,
174- sizeInBytes : filestat . size ,
175- hash : hashFile ( filepath ) ,
176- } ) ;
177- }
178- } )
179- ) ;
180-
181- return fileMap ;
182- } ;
183-
184- const fileMap = await walk ( directory ) ;
185-
186- if ( fileMap . size > MAX_ASSET_COUNT ) {
187- throw new FatalError (
188- `Error: Pages only supports up to ${ MAX_ASSET_COUNT . toLocaleString ( ) } files in a deployment. Ensure you have specified your build output directory correctly.` ,
189- 1
190- ) ;
191- }
192-
193- const files = [ ...fileMap . values ( ) ] ;
103+ const files = [ ...args . fileMap . values ( ) ] ;
194104
195105 let jwt = await fetchJwt ( ) ;
196106
@@ -274,8 +184,8 @@ export const upload = async (
274184 bucketOffset ++ ;
275185 }
276186
277- let counter = fileMap . size - sortedFiles . length ;
278- const { rerender, unmount } = renderProgress ( counter , fileMap . size ) ;
187+ let counter = args . fileMap . size - sortedFiles . length ;
188+ const { rerender, unmount } = renderProgress ( counter , args . fileMap . size ) ;
279189
280190 const queue = new PQueue ( { concurrency : BULK_UPLOAD_CONCURRENCY } ) ;
281191
@@ -333,7 +243,7 @@ export const upload = async (
333243 doUpload ( ) . then (
334244 ( ) => {
335245 counter += bucket . files . length ;
336- rerender ( counter , fileMap . size ) ;
246+ rerender ( counter , args . fileMap . size ) ;
337247 } ,
338248 ( error ) => {
339249 return Promise . reject (
@@ -355,7 +265,7 @@ export const upload = async (
355265
356266 const uploadMs = Date . now ( ) - start ;
357267
358- const skipped = fileMap . size - missingHashes . length ;
268+ const skipped = args . fileMap . size - missingHashes . length ;
359269 const skippedMessage = skipped > 0 ? `(${ skipped } already uploaded) ` : "" ;
360270
361271 logger . log (
@@ -406,7 +316,7 @@ export const upload = async (
406316 }
407317
408318 return Object . fromEntries (
409- [ ...fileMap . entries ( ) ] . map ( ( [ fileName , file ] ) => [
319+ [ ...args . fileMap . entries ( ) ] . map ( ( [ fileName , file ] ) => [
410320 `/${ fileName } ` ,
411321 file . hash ,
412322 ] )
0 commit comments