import { ALBEvent , ALBResult } from "aws-lambda" ; import AWS from "aws-sdk" ; import { promises as fs } from "fs" ; import path from "path" ; import config from "../config.json" ; import { PKPass } from "passkit-generator" ; const S3 = { instance : undefined } ; export function throwClientErrorWithoutModelName ( event ) { if ( ! event . queryStringParameters ?. modelName ) { throw { statusCode : 400 , body : JSON . stringify ( { message : "modelName is missing in query params" , } ) , } ; } } export function getRandomColorPart ( ) { return Math . floor ( Math . random ( ) * 255 ) ; } export async function getModel ( modelName ) { if ( process . env . IS_OFFLINE === "true" ) { console . log ( "model offline retrieving" ) ; const standardModelName = modelName . endsWith ( ".pass" ) ? modelName : `${ modelName }.pass` ; return path . resolve ( __dirname , "../../../" , `models/${ standardModelName }` ) ; } const s3 = await getS3Instance ( ) ; const result = await s3 . getObject ( { Bucket : config . MODELS_S3_BUCKET , Key : modelName } ) . promise ( ) ; return { } ; } export async function getCertificates ( ) { let signerCert ; let signerKey ; let wwdr ; let signerKeyPassphrase ; if ( process . env . IS_OFFLINE ) { console . log ( "Fetching Certificates locally" ) ; [ signerCert , signerKey , wwdr , signerKeyPassphrase ] = await Promise . all ( [ fs . readFile ( path . resolve ( __dirname , "../../../../" , "certificates/signerCert.pem" ) , "utf-8" ) , fs . readFile ( path . resolve ( __dirname , "../../../../" , "certificates/signerKey.pem" ) , "utf-8" ) , fs . readFile ( path . resolve ( __dirname , "../../../../" , "certificates/WWDR.pem" ) , "utf-8" ) , Promise . resolve ( config . SIGNER_KEY_PASSPHRASE ) , ] ) ; } else { } return { signerCert , signerKey , wwdr , signerKeyPassphrase , } ; } export async function getS3Instance ( ) { if ( S3 . instance ) { return S3 . instance ; } const instance = new AWS . S3 ( { s3ForcePathStyle : true , accessKeyId : process . env . IS_OFFLINE ? "S3RVER" : config . ACCESS_KEY_ID , secretAccessKey : config . SECRET_ACCESS_KEY , endpoint : new AWS . Endpoint ( "http://localhost:4569" ) , } ) ; S3 . instance = instance ; try { /** Trying to create a new bucket. If it fails, it already exists (at least in theory) */ await instance . createBucket ( { Bucket : config . PASSES_S3_TEMP_BUCKET } ) . promise ( ) ; } catch ( err ) { } return instance ; } export async function getSpecificFileInModel ( fileName , modelName ) { const model = await getModel ( modelName ) ; if ( typeof model === "string" ) { return fs . readFile ( path . resolve ( model , fileName ) ) ; } return model [ fileName ] ; } export async function * createPassGenerator ( modelName ? , passOptions ? ) { const [ template , certificates , s3 ] = await Promise . all ( [ modelName ? getModel ( modelName ) : Promise . resolve ( { } ) , getCertificates ( ) , getS3Instance ( ) , ] ) ; let pass ; if ( template instanceof Object ) { pass = new PKPass ( template , certificates , passOptions ) ; } else if ( typeof template === "string" ) { pass = await PKPass . from ( { model : template , certificates , } , passOptions ) ; } if ( pass . type === "boardingPass" && ! pass . transitType ) { pass . transitType = "PKTransitTypeAir" ; } pass = yield pass ; const buffer = pass . getAsBuffer ( ) ; const passName = `GeneratedPass-${ Math . random ( ) }.pkpass` ; const { Location } = await s3 . upload ( { Bucket : config . PASSES_S3_TEMP_BUCKET , Key : passName , ContentType : pass . mimeType , /** Marking it as expiring in 5 minutes, because passes should not be stored */ Expires : new Date ( Date . now ( ) + 5 * 60 * 1000 ) , Body : buffer , } ) . promise ( ) ; /**
     * Please note that redirection to `Location` does not work
     * if you open this code in another device if this is run
     * offline. This because `Location` is on localhost. Didn't
     * find yet a way to solve this.
     */ return { statusCode : 302 , headers : { "Content-Type" : "application/vnd.apple.pkpass" , Location : Location , } , } ; }