@@ -8,7 +8,7 @@ import { join, resolve, relative } from 'pathe'
8
8
import { execa } from 'execa'
9
9
import { setupDotenv } from 'c12'
10
10
import { $api , fetchUser , selectTeam , selectProject , projectPath , fetchProject , linkProject , gitInfo , getPackageJson } from '../utils/index.mjs'
11
- import { getStorage , getPathsToDeploy , getFile , uploadAssetsToCloudflare , isMetaPath , isServerPath , getPublicFiles } from '../utils/deploy.mjs'
11
+ import { getStorage , getPathsToDeploy , getFile , uploadAssetsToCloudflare , uploadWorkersAssetsToCloudflare , isMetaPath , isWorkerMetaPath , isServerPath , isWorkerServerPath , getPublicFiles , getWorkerPublicFiles } from '../utils/deploy.mjs'
12
12
import { createMigrationsTable , fetchRemoteMigrations , queryDatabase } from '../utils/database.mjs'
13
13
import login from './login.mjs'
14
14
@@ -137,6 +137,7 @@ export default defineCommand({
137
137
const fileKeys = await storage . getKeys ( )
138
138
const pathsToDeploy = getPathsToDeploy ( fileKeys )
139
139
const config = await storage . getItem ( 'hub.config.json' )
140
+ const isWorkerPreset = [ 'cloudflare_module' , 'cloudflare_durable' ] . includes ( config . nitroPreset )
140
141
const { format : formatNumber } = new Intl . NumberFormat ( 'en-US' )
141
142
142
143
let spinner = ora ( `Preparing ${ colors . blueBright ( linkedProject . slug ) } deployment for ${ deployEnvColored } ...` ) . start ( )
@@ -147,40 +148,64 @@ export default defineCommand({
147
148
spinnerColorIndex = ( spinnerColorIndex + 1 ) % spinnerColors . length
148
149
} , 2500 )
149
150
150
- let deploymentKey , serverFiles , metaFiles
151
+ let deploymentKey , serverFiles , metaFiles , completionToken
151
152
try {
152
- const publicFiles = await getPublicFiles ( storage , pathsToDeploy )
153
+ let url = `/teams/${ linkedProject . teamSlug } /projects/${ linkedProject . slug } /${ deployEnv } /deploy/prepare`
154
+ let publicFiles , publicManifest
153
155
154
- const deploymentInfo = await $api ( `/teams/${ linkedProject . teamSlug } /projects/${ linkedProject . slug } /${ deployEnv } /deploy/prepare` , {
156
+ if ( isWorkerPreset ) {
157
+ url = `/teams/${ linkedProject . teamSlug } /projects/${ linkedProject . slug } /${ deployEnv } /deploy/worker/prepare`
158
+ publicFiles = await getWorkerPublicFiles ( storage , pathsToDeploy )
159
+ /**
160
+ * { "/index.html": { hash: "hash", size: 30 }
161
+ */
162
+ publicManifest = publicFiles . reduce ( ( acc , file ) => {
163
+ acc [ file . path ] = {
164
+ hash : file . hash ,
165
+ size : file . size
166
+ }
167
+ return acc
168
+ } , { } )
169
+ } else {
170
+ publicFiles = await getPublicFiles ( storage , pathsToDeploy )
171
+ /**
172
+ * { "/index.html": "hash" }
173
+ */
174
+ publicManifest = publicFiles . reduce ( ( acc , file ) => {
175
+ acc [ file . path ] = file . hash
176
+ return acc
177
+ } , { } )
178
+ }
179
+ // Get deployment info by preparing the deployment
180
+ const deploymentInfo = await $api ( url , {
155
181
method : 'POST' ,
156
182
body : {
157
183
config,
158
- /**
159
- * Public manifest is a map of file paths to their unique hash (SHA256 sliced to 32 characters).
160
- * @example
161
- * {
162
- * "/index.html": "hash",
163
- * "/assets/image.png": "hash"
164
- * }
165
- */
166
- publicManifest : publicFiles . reduce ( ( acc , file ) => {
167
- acc [ file . path ] = file . hash
168
- return acc
169
- } , { } )
184
+ publicManifest
170
185
}
171
186
} )
172
187
spinner . succeed ( `${ colors . blueBright ( linkedProject . slug ) } ready to deploy.` )
173
- const { missingPublicHashes, cloudflareUploadJwt } = deploymentInfo
174
188
deploymentKey = deploymentInfo . deploymentKey
189
+
190
+ const { cloudflareUploadJwt, buckets, accountId } = deploymentInfo
191
+ // missingPublicHash is sent for pages & buckets for worker
192
+ let missingPublicHashes = deploymentInfo . missingPublicHashes || buckets . flat ( )
175
193
const publicFilesToUpload = publicFiles . filter ( file => missingPublicHashes . includes ( file . hash ) )
176
194
177
195
if ( publicFilesToUpload . length ) {
178
196
const totalSizeToUpload = publicFilesToUpload . reduce ( ( acc , file ) => acc + file . size , 0 )
179
197
spinner = ora ( `Uploading ${ colors . blueBright ( formatNumber ( publicFilesToUpload . length ) ) } new static assets (${ colors . blueBright ( prettyBytes ( totalSizeToUpload ) ) } )...` ) . start ( )
180
- await uploadAssetsToCloudflare ( publicFilesToUpload , cloudflareUploadJwt , ( { progressSize, totalSize } ) => {
181
- const percentage = Math . round ( ( progressSize / totalSize ) * 100 )
182
- spinner . text = `${ percentage } % uploaded (${ prettyBytes ( progressSize ) } /${ prettyBytes ( totalSize ) } )...`
183
- } )
198
+ if ( linkedProject . type === 'pages' ) {
199
+ await uploadAssetsToCloudflare ( publicFilesToUpload , cloudflareUploadJwt , ( { progressSize, totalSize } ) => {
200
+ const percentage = Math . round ( ( progressSize / totalSize ) * 100 )
201
+ spinner . text = `${ percentage } % uploaded (${ prettyBytes ( progressSize ) } /${ prettyBytes ( totalSize ) } )...`
202
+ } )
203
+ } else {
204
+ completionToken = await uploadWorkersAssetsToCloudflare ( accountId , publicFilesToUpload , cloudflareUploadJwt , ( { progressSize, totalSize } ) => {
205
+ const percentage = Math . round ( ( progressSize / totalSize ) * 100 )
206
+ spinner . text = `${ percentage } % uploaded (${ prettyBytes ( progressSize ) } /${ prettyBytes ( totalSize ) } )...`
207
+ } )
208
+ }
184
209
spinner . succeed ( `${ colors . blueBright ( formatNumber ( publicFilesToUpload . length ) ) } new static assets uploaded (${ colors . blueBright ( prettyBytes ( totalSizeToUpload ) ) } )` )
185
210
}
186
211
@@ -190,8 +215,14 @@ export default defineCommand({
190
215
consola . info ( `${ colors . blueBright ( formatNumber ( publicFiles . length ) ) } static assets (${ colors . blueBright ( prettyBytes ( totalSize ) ) } / ${ colors . blueBright ( prettyBytes ( totalGzipSize ) ) } gzip)` )
191
216
}
192
217
193
- metaFiles = await Promise . all ( pathsToDeploy . filter ( isMetaPath ) . map ( p => getFile ( storage , p , 'base64' ) ) )
194
- serverFiles = await Promise . all ( pathsToDeploy . filter ( isServerPath ) . map ( p => getFile ( storage , p , 'base64' ) ) )
218
+ metaFiles = await Promise . all ( pathsToDeploy . filter ( isWorkerPreset ? isWorkerMetaPath : isMetaPath ) . map ( p => getFile ( storage , p , 'base64' ) ) )
219
+ serverFiles = await Promise . all ( pathsToDeploy . filter ( isWorkerPreset ? isWorkerServerPath : isServerPath ) . map ( p => getFile ( storage , p , 'base64' ) ) )
220
+ if ( isWorkerPreset ) {
221
+ serverFiles = serverFiles . map ( file => ( {
222
+ ...file ,
223
+ path : file . path . replace ( '/server/' , '/' )
224
+ } ) )
225
+ }
195
226
const serverFilesSize = serverFiles . reduce ( ( acc , file ) => acc + file . size , 0 )
196
227
const serverFilesGzipSize = serverFiles . reduce ( ( acc , file ) => acc + file . gzipSize , 0 )
197
228
consola . info ( `${ colors . blueBright ( formatNumber ( serverFiles . length ) ) } server files (${ colors . blueBright ( prettyBytes ( serverFilesSize ) ) } / ${ colors . blueBright ( prettyBytes ( serverFilesGzipSize ) ) } gzip)...` )
@@ -286,13 +317,14 @@ export default defineCommand({
286
317
287
318
// #region Complete deployment
288
319
spinner = ora ( `Deploying ${ colors . blueBright ( linkedProject . slug ) } to ${ deployEnvColored } ...` ) . start ( )
289
- const deployment = await $api ( `/teams/${ linkedProject . teamSlug } /projects/${ linkedProject . slug } /${ deployEnv } /deploy/complete` , {
320
+ const deployment = await $api ( `/teams/${ linkedProject . teamSlug } /projects/${ linkedProject . slug } /${ deployEnv } /deploy/${ isWorkerPreset ? 'worker/ complete' : 'complete' } ` , {
290
321
method : 'POST' ,
291
322
body : {
292
323
deploymentKey,
293
324
git,
294
325
serverFiles,
295
- metaFiles
326
+ metaFiles,
327
+ completionToken
296
328
} ,
297
329
} ) . catch ( ( err ) => {
298
330
spinner . fail ( `Failed to deploy ${ colors . blueBright ( linkedProject . slug ) } to ${ deployEnvColored } .` )
0 commit comments