@@ -10,7 +10,7 @@ import type {
1010 TemporaryAccountStorage ,
1111 TemporaryPreviewAccount ,
1212} from "./config-file/temporary" ;
13- import type { OAuthFlowLogger } from "./context" ;
13+ import type { OAuthFlowLogger , TemporaryAccountRequest } from "./context" ;
1414import type { PowSolution } from "./pow" ;
1515
1616export const TEMPORARY_TERMS_URLS = {
@@ -37,12 +37,115 @@ type TemporaryAccountPayload = {
3737 url ?: string ;
3838 expiresAt ?: string ;
3939 } ;
40+ eventCodeAccepted ?: boolean ;
4041} ;
4142
4243type TemporaryAccountResponse = {
4344 result ?: TemporaryAccountPayload ;
4445} ;
4546
47+ const EVENT_ACCOUNT_ERRORS = new Map <
48+ number ,
49+ { message : string ; telemetryMessage : string ; fatal ?: true }
50+ > ( [
51+ [
52+ 1035 ,
53+ {
54+ message : "The event code is malformed. Check it and try again." ,
55+ telemetryMessage : "deploy temporary event code invalid" ,
56+ } ,
57+ ] ,
58+ [
59+ 1036 ,
60+ {
61+ message : "The event code was not found. Check it and try again." ,
62+ telemetryMessage : "deploy temporary event not found" ,
63+ } ,
64+ ] ,
65+ [
66+ 1037 ,
67+ {
68+ message : "This event has not started yet." ,
69+ telemetryMessage : "deploy temporary event not started" ,
70+ } ,
71+ ] ,
72+ [
73+ 1038 ,
74+ {
75+ message : "This event has ended." ,
76+ telemetryMessage : "deploy temporary event expired" ,
77+ } ,
78+ ] ,
79+ [
80+ 1039 ,
81+ {
82+ message : "This event is disabled. Contact the event organizer." ,
83+ telemetryMessage : "deploy temporary event disabled" ,
84+ } ,
85+ ] ,
86+ [
87+ 1040 ,
88+ {
89+ message : "This event has no temporary accounts remaining." ,
90+ telemetryMessage : "deploy temporary event exhausted" ,
91+ } ,
92+ ] ,
93+ [
94+ 1041 ,
95+ {
96+ message :
97+ "The event account could not be prepared. Try again later or contact the event organizer." ,
98+ telemetryMessage : "deploy temporary event provisioning unavailable" ,
99+ fatal : true ,
100+ } ,
101+ ] ,
102+ ] ) ;
103+
104+ function getResponseErrorCode ( body : unknown ) : number | undefined {
105+ if ( typeof body !== "object" || body === null || ! ( "errors" in body ) ) {
106+ return undefined ;
107+ }
108+
109+ const { errors } = body ;
110+ if ( ! Array . isArray ( errors ) || errors . length === 0 ) {
111+ return undefined ;
112+ }
113+
114+ const [ error ] = errors ;
115+ if ( typeof error !== "object" || error === null || ! ( "code" in error ) ) {
116+ return undefined ;
117+ }
118+
119+ return typeof error . code === "number" ? error . code : undefined ;
120+ }
121+
122+ async function getEventAccountError (
123+ response : Response
124+ ) : Promise < UserError | FatalError | undefined > {
125+ let body : unknown ;
126+ try {
127+ body = await response . json ( ) ;
128+ } catch {
129+ return undefined ;
130+ }
131+
132+ const errorCode = getResponseErrorCode ( body ) ;
133+ if ( errorCode === undefined ) {
134+ return undefined ;
135+ }
136+
137+ const eventError = EVENT_ACCOUNT_ERRORS . get ( errorCode ) ;
138+ if ( ! eventError ) {
139+ return undefined ;
140+ }
141+
142+ const options = { telemetryMessage : eventError . telemetryMessage } ;
143+ if ( eventError . fatal ) {
144+ return new FatalError ( eventError . message , options ) ;
145+ }
146+ return new UserError ( eventError . message , options ) ;
147+ }
148+
46149function getTemporaryPreviewUrl ( ) : string {
47150 return `${ getCloudflareApiBaseUrl ( COMPLIANCE_REGION_CONFIG_PUBLIC ) } /provisioning/previews` ;
48151}
@@ -166,7 +269,8 @@ async function requestPowSolution(
166269 * endpoint
167270 */
168271export async function createTemporaryPreviewAccount (
169- logger : OAuthFlowLogger
272+ logger : OAuthFlowLogger ,
273+ request ?: TemporaryAccountRequest
170274) : Promise < TemporaryPreviewAccount > {
171275 const pow = await requestPowSolution ( logger ) ;
172276
@@ -179,10 +283,17 @@ export async function createTemporaryPreviewAccount(
179283 acceptTermsOfService : "yes" ,
180284 challengeToken : pow . challengeToken ,
181285 solution : pow . solution ,
286+ ...( request ?. eventCode ? { eventCode : request . eventCode } : { } ) ,
182287 } ) ,
183288 } ) ;
184289
185290 if ( ! response . ok ) {
291+ if ( request ?. eventCode ) {
292+ const eventError = await getEventAccountError ( response ) ;
293+ if ( eventError ) {
294+ throw eventError ;
295+ }
296+ }
186297 throw new FatalError (
187298 `Failed to create a temporary preview account (${ response . status } ${ response . statusText } ).` ,
188299 { telemetryMessage : "deploy temporary account create failed" }
@@ -207,6 +318,7 @@ export async function createTemporaryPreviewAccount(
207318 const accountExpiresAt = previewAccount ?. account ?. expiresAt ;
208319 const claimUrl = previewAccount ?. claim ?. url ;
209320 const claimExpiresAt = previewAccount ?. claim ?. expiresAt ;
321+ const eventCodeAccepted = previewAccount ?. eventCodeAccepted ;
210322
211323 if (
212324 accountId === undefined ||
@@ -222,6 +334,15 @@ export async function createTemporaryPreviewAccount(
222334 ) ;
223335 }
224336
337+ if ( request ?. eventCode && eventCodeAccepted !== true ) {
338+ throw new FatalError (
339+ "Failed to create a temporary preview account because the response did not acknowledge the event code." ,
340+ {
341+ telemetryMessage : "deploy temporary event acknowledgement missing" ,
342+ }
343+ ) ;
344+ }
345+
225346 return {
226347 account : {
227348 id : accountId ,
@@ -245,6 +366,7 @@ export async function getOrCreateTemporaryPreviewAccount(options: {
245366 storage : TemporaryAccountStorage ;
246367 prompt : ( question : string , notice : string ) => Promise < boolean > ;
247368 logger : OAuthFlowLogger ;
369+ request ?: TemporaryAccountRequest ;
248370} ) : Promise < {
249371 account : TemporaryPreviewAccount ;
250372 cached : boolean ;
@@ -253,6 +375,14 @@ export async function getOrCreateTemporaryPreviewAccount(options: {
253375 options . storage
254376 ) ;
255377 if ( cachedPreviewAccount ) {
378+ if ( options . request ?. eventCode ) {
379+ throw new UserError (
380+ "A temporary account is already cached. Rerun without --event-code to reuse it, or run `wrangler logout` and retry to create an account for this event." ,
381+ {
382+ telemetryMessage : "deploy temporary event cache conflict" ,
383+ }
384+ ) ;
385+ }
256386 return { account : cachedPreviewAccount , cached : true } ;
257387 }
258388
@@ -268,7 +398,8 @@ export async function getOrCreateTemporaryPreviewAccount(options: {
268398 }
269399
270400 const temporaryPreviewAccount = await createTemporaryPreviewAccount (
271- options . logger
401+ options . logger ,
402+ options . request
272403 ) ;
273404 options . storage . write ( temporaryPreviewAccount ) ;
274405
0 commit comments