mirror of
https://github.com/marcogll/passkit-generator.git
synced 2026-03-16 03:25:32 +00:00
Added first version of serverless-based implementation example
This commit is contained in:
43
examples/serverless/src/functions/barcodes.ts
Normal file
43
examples/serverless/src/functions/barcodes.ts
Normal file
@@ -0,0 +1,43 @@
|
||||
import { ALBEvent, ALBResult } from "aws-lambda";
|
||||
import { PKPass } from "../../../../lib";
|
||||
import { finish400WithoutModelName, createPassGenerator } from "../shared";
|
||||
|
||||
/**
|
||||
* Lambda for barcodes example
|
||||
*/
|
||||
|
||||
export async function barcodes(event: ALBEvent) {
|
||||
finish400WithoutModelName(event);
|
||||
|
||||
const { modelName, alt, ...passOptions } = event.queryStringParameters;
|
||||
|
||||
const passGenerator = createPassGenerator(modelName, passOptions);
|
||||
|
||||
const pass = (await passGenerator.next()).value as PKPass;
|
||||
|
||||
if (alt === "true") {
|
||||
// After this, pass.props["barcodes"] will have support for all the formats
|
||||
pass.setBarcodes("Thank you for using this package <3");
|
||||
|
||||
console.log(
|
||||
"Barcodes support is autocompleted:",
|
||||
pass.props["barcodes"],
|
||||
);
|
||||
} else {
|
||||
// After this, pass.props["barcodes"] will have support for just two of three
|
||||
// of the passed format (the valid ones);
|
||||
|
||||
pass.setBarcodes(
|
||||
{
|
||||
message: "Thank you for using this package <3",
|
||||
format: "PKBarcodeFormatCode128",
|
||||
},
|
||||
{
|
||||
message: "Thank you for using this package <3",
|
||||
format: "PKBarcodeFormatPDF417",
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
return (await passGenerator.next(pass as PKPass)).value as ALBResult;
|
||||
}
|
||||
31
examples/serverless/src/functions/expirationDate.ts
Normal file
31
examples/serverless/src/functions/expirationDate.ts
Normal file
@@ -0,0 +1,31 @@
|
||||
import { ALBEvent, ALBResult } from "aws-lambda";
|
||||
import { Context } from "vm";
|
||||
import { PKPass } from "passkit-generator";
|
||||
import { finish400WithoutModelName, createPassGenerator } from "../shared";
|
||||
|
||||
/**
|
||||
* Lambda for expirationDate example
|
||||
*/
|
||||
|
||||
export async function expirationDate(event: ALBEvent, context: Context) {
|
||||
finish400WithoutModelName(event);
|
||||
|
||||
const { modelName, ...passOptions } = event.queryStringParameters;
|
||||
|
||||
const passGenerator = createPassGenerator(modelName, passOptions);
|
||||
|
||||
const pass = (await passGenerator.next()).value as PKPass;
|
||||
|
||||
// 2 minutes later...
|
||||
const d = new Date();
|
||||
d.setMinutes(d.getMinutes() + 2);
|
||||
|
||||
// setting the expiration
|
||||
(pass as PKPass).setExpirationDate(d);
|
||||
console.log(
|
||||
"EXPIRATION DATE EXPECTED:",
|
||||
(pass as PKPass).props["expirationDate"],
|
||||
);
|
||||
|
||||
return (await passGenerator.next(pass as PKPass)).value as ALBResult;
|
||||
}
|
||||
160
examples/serverless/src/functions/fields.ts
Normal file
160
examples/serverless/src/functions/fields.ts
Normal file
@@ -0,0 +1,160 @@
|
||||
import { ALBEvent, ALBResult } from "aws-lambda";
|
||||
import { PKPass } from "passkit-generator";
|
||||
import { createPassGenerator } from "../shared";
|
||||
|
||||
/**
|
||||
* Lambda for fields example
|
||||
*/
|
||||
|
||||
export async function fields(event: ALBEvent) {
|
||||
const { modelName, ...passOptions } = event.queryStringParameters;
|
||||
|
||||
const passGenerator = createPassGenerator("exampleBooking", passOptions);
|
||||
|
||||
const pass = (await passGenerator.next()).value as PKPass;
|
||||
|
||||
pass.transitType = "PKTransitTypeAir";
|
||||
|
||||
pass.headerFields.push(
|
||||
{
|
||||
key: "header1",
|
||||
label: "Data",
|
||||
value: "25 mag",
|
||||
textAlignment: "PKTextAlignmentCenter",
|
||||
},
|
||||
{
|
||||
key: "header2",
|
||||
label: "Volo",
|
||||
value: "EZY997",
|
||||
textAlignment: "PKTextAlignmentCenter",
|
||||
},
|
||||
);
|
||||
|
||||
pass.primaryFields.push(
|
||||
{
|
||||
key: "IATA-source",
|
||||
value: "NAP",
|
||||
label: "Napoli",
|
||||
textAlignment: "PKTextAlignmentLeft",
|
||||
},
|
||||
{
|
||||
key: "IATA-destination",
|
||||
value: "VCE",
|
||||
label: "Venezia Marco Polo",
|
||||
textAlignment: "PKTextAlignmentRight",
|
||||
},
|
||||
);
|
||||
|
||||
pass.secondaryFields.push(
|
||||
{
|
||||
key: "secondary1",
|
||||
label: "Imbarco chiuso",
|
||||
value: "18:40",
|
||||
textAlignment: "PKTextAlignmentCenter",
|
||||
},
|
||||
{
|
||||
key: "sec2",
|
||||
label: "Partenze",
|
||||
value: "19:10",
|
||||
textAlignment: "PKTextAlignmentCenter",
|
||||
},
|
||||
{
|
||||
key: "sec3",
|
||||
label: "SB",
|
||||
value: "Sì",
|
||||
textAlignment: "PKTextAlignmentCenter",
|
||||
},
|
||||
{
|
||||
key: "sec4",
|
||||
label: "Imbarco",
|
||||
value: "Anteriore",
|
||||
textAlignment: "PKTextAlignmentCenter",
|
||||
},
|
||||
);
|
||||
|
||||
pass.auxiliaryFields.push(
|
||||
{
|
||||
key: "aux1",
|
||||
label: "Passeggero",
|
||||
value: "MR. WHO KNOWS",
|
||||
textAlignment: "PKTextAlignmentLeft",
|
||||
},
|
||||
{
|
||||
key: "aux2",
|
||||
label: "Posto",
|
||||
value: "1A*",
|
||||
textAlignment: "PKTextAlignmentCenter",
|
||||
},
|
||||
);
|
||||
|
||||
pass.backFields.push(
|
||||
{
|
||||
key: "document number",
|
||||
label: "Numero documento:",
|
||||
value: "- -",
|
||||
textAlignment: "PKTextAlignmentLeft",
|
||||
},
|
||||
{
|
||||
key: "You're checked in, what next",
|
||||
label: "Hai effettuato il check-in, Quali sono le prospettive",
|
||||
value: "",
|
||||
textAlignment: "PKTextAlignmentLeft",
|
||||
},
|
||||
{
|
||||
key: "Check In",
|
||||
label: "1. check-in✓",
|
||||
value: "",
|
||||
textAlignment: "PKTextAlignmentLeft",
|
||||
},
|
||||
{
|
||||
key: "checkIn",
|
||||
label: "",
|
||||
value: "Le uscite d'imbarco chiudono 30 minuti prima della partenza, quindi sii puntuale. In questo aeroporto puoi utilizzare la corsia Fast Track ai varchi di sicurezza.",
|
||||
textAlignment: "PKTextAlignmentLeft",
|
||||
},
|
||||
{
|
||||
key: "2. Bags",
|
||||
label: "2. Bagaglio",
|
||||
value: "",
|
||||
textAlignment: "PKTextAlignmentLeft",
|
||||
},
|
||||
{
|
||||
key: "Require special assistance",
|
||||
label: "Assistenza speciale",
|
||||
value: "Se hai richiesto assistenza speciale, presentati a un membro del personale nell'area di Consegna bagagli almeno 90 minuti prima del volo.",
|
||||
textAlignment: "PKTextAlignmentLeft",
|
||||
},
|
||||
{
|
||||
key: "3. Departures",
|
||||
label: "3. Partenze",
|
||||
value: "",
|
||||
textAlignment: "PKTextAlignmentLeft",
|
||||
},
|
||||
{
|
||||
key: "photoId",
|
||||
label: "Un documento d’identità corredato di fotografia",
|
||||
value: "è obbligatorio su TUTTI i voli. Per un viaggio internazionale è necessario un passaporto valido o, dove consentita, una carta d’identità.",
|
||||
textAlignment: "PKTextAlignmentLeft",
|
||||
},
|
||||
{
|
||||
key: "yourSeat",
|
||||
label: "Il tuo posto:",
|
||||
value: "verifica il tuo numero di posto nella parte superiore. Durante l’imbarco utilizza le scale anteriori e posteriori: per le file 1-10 imbarcati dalla parte anteriore; per le file 11-31 imbarcati dalla parte posteriore. Colloca le borse di dimensioni ridotte sotto il sedile davanti a te.",
|
||||
textAlignment: "PKTextAlignmentLeft",
|
||||
},
|
||||
{
|
||||
key: "Pack safely",
|
||||
label: "Bagaglio sicuro",
|
||||
value: "Fai clic http://easyjet.com/it/articoli-pericolosi per maggiori informazioni sulle merci pericolose oppure visita il sito CAA http://www.caa.co.uk/default.aspx?catid=2200",
|
||||
textAlignment: "PKTextAlignmentLeft",
|
||||
},
|
||||
{
|
||||
key: "Thank you for travelling easyJet",
|
||||
label: "Grazie per aver viaggiato con easyJet",
|
||||
value: "",
|
||||
textAlignment: "PKTextAlignmentLeft",
|
||||
},
|
||||
);
|
||||
|
||||
return (await passGenerator.next(pass as PKPass)).value as ALBResult;
|
||||
}
|
||||
6
examples/serverless/src/functions/index.ts
Normal file
6
examples/serverless/src/functions/index.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
export * from "./barcodes";
|
||||
export * from "./expirationDate";
|
||||
export * from "./fields";
|
||||
export * from "./localize";
|
||||
export * from "./pkpasses";
|
||||
export * from "./scratch";
|
||||
45
examples/serverless/src/functions/localize.ts
Normal file
45
examples/serverless/src/functions/localize.ts
Normal file
@@ -0,0 +1,45 @@
|
||||
import { finish400WithoutModelName, createPassGenerator } from "../shared";
|
||||
import type { ALBEvent, ALBResult } from "aws-lambda";
|
||||
import type { PKPass } from "passkit-generator";
|
||||
import { localizationSymbol } from "passkit-generator/lib/PKPass";
|
||||
|
||||
/**
|
||||
* Lambda for localize example
|
||||
*/
|
||||
|
||||
export async function localize(event: ALBEvent) {
|
||||
finish400WithoutModelName(event);
|
||||
|
||||
const { modelName, ...passOptions } = event.queryStringParameters;
|
||||
|
||||
const passGenerator = createPassGenerator(modelName, passOptions);
|
||||
|
||||
const pass = (await passGenerator.next()).value as PKPass;
|
||||
|
||||
/**
|
||||
* Italian and German already has an .lproj which gets included
|
||||
* but it doesn't have translations
|
||||
*/
|
||||
pass.localize("it", {
|
||||
EVENT: "Evento",
|
||||
LOCATION: "Dove",
|
||||
});
|
||||
|
||||
pass.localize("de", {
|
||||
EVENT: "Ereignis",
|
||||
LOCATION: "Ort",
|
||||
});
|
||||
|
||||
// ...while Norwegian doesn't, so it gets created
|
||||
pass.localize("nn", {
|
||||
EVENT: "Begivenhet",
|
||||
LOCATION: "plassering",
|
||||
});
|
||||
|
||||
console.log(
|
||||
"Added languages",
|
||||
Object.keys(pass[localizationSymbol]).join(", "),
|
||||
);
|
||||
|
||||
return (await passGenerator.next(pass as PKPass)).value as ALBResult;
|
||||
}
|
||||
115
examples/serverless/src/functions/pkpasses.ts
Normal file
115
examples/serverless/src/functions/pkpasses.ts
Normal file
@@ -0,0 +1,115 @@
|
||||
import { ALBEvent } from "aws-lambda";
|
||||
import { PKPass } from "passkit-generator";
|
||||
import {
|
||||
getCertificates,
|
||||
getSpecificFileInModel,
|
||||
getS3Instance,
|
||||
getRandomColorPart,
|
||||
finish400WithoutModelName,
|
||||
} from "../shared";
|
||||
import config from "../../config.json";
|
||||
|
||||
/**
|
||||
* Lambda for PkPasses example
|
||||
*/
|
||||
|
||||
export async function pkpasses(event: ALBEvent) {
|
||||
finish400WithoutModelName(event);
|
||||
|
||||
const [certificates, iconFromModel, s3] = await Promise.all([
|
||||
getCertificates(),
|
||||
getSpecificFileInModel(
|
||||
"icon.png",
|
||||
event.queryStringParameters.modelName,
|
||||
),
|
||||
getS3Instance(),
|
||||
]);
|
||||
|
||||
function createPass() {
|
||||
const pass = new PKPass({}, certificates, {
|
||||
description: "Example Apple Wallet Pass",
|
||||
passTypeIdentifier: "pass.com.passkitgenerator",
|
||||
serialNumber: "nmyuxofgna",
|
||||
organizationName: `Test Organization ${Math.random()}`,
|
||||
teamIdentifier: "F53WB8AE67",
|
||||
foregroundColor: `rgb(${getRandomColorPart()}, ${getRandomColorPart()}, ${getRandomColorPart()})`,
|
||||
labelColor: `rgb(${getRandomColorPart()}, ${getRandomColorPart()}, ${getRandomColorPart()})`,
|
||||
backgroundColor: `rgb(${getRandomColorPart()}, ${getRandomColorPart()}, ${getRandomColorPart()})`,
|
||||
});
|
||||
|
||||
pass.type = "boardingPass";
|
||||
pass.transitType = "PKTransitTypeAir";
|
||||
|
||||
pass.headerFields.push(
|
||||
{
|
||||
key: "header-field-test-1",
|
||||
value: "Unknown",
|
||||
},
|
||||
{
|
||||
key: "header-field-test-2",
|
||||
value: "unknown",
|
||||
},
|
||||
);
|
||||
|
||||
pass.primaryFields.push(
|
||||
{
|
||||
key: "primaryField-1",
|
||||
value: "NAP",
|
||||
},
|
||||
{
|
||||
key: "primaryField-2",
|
||||
value: "VCE",
|
||||
},
|
||||
);
|
||||
|
||||
/**
|
||||
* Required by Apple. If one is not available, a
|
||||
* pass might be openable on a Mac but not on a
|
||||
* specific iPhone model
|
||||
*/
|
||||
|
||||
pass.addBuffer("icon.png", iconFromModel);
|
||||
pass.addBuffer("icon@2x.png", iconFromModel);
|
||||
pass.addBuffer("icon@3x.png", iconFromModel);
|
||||
|
||||
return pass;
|
||||
}
|
||||
|
||||
const passes = await Promise.all([
|
||||
Promise.resolve(createPass()),
|
||||
Promise.resolve(createPass()),
|
||||
Promise.resolve(createPass()),
|
||||
Promise.resolve(createPass()),
|
||||
]);
|
||||
|
||||
const pkpasses = PKPass.pack(...passes);
|
||||
|
||||
const buffer = pkpasses.getAsBuffer();
|
||||
const passName = `GeneratedPass-${Math.random()}.pkpass`;
|
||||
|
||||
const { Location } = await s3
|
||||
.upload({
|
||||
Bucket: config.PASSES_S3_TEMP_BUCKET,
|
||||
Key: passName,
|
||||
ContentType: pkpasses.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,
|
||||
},
|
||||
};
|
||||
}
|
||||
71
examples/serverless/src/functions/scratch.ts
Normal file
71
examples/serverless/src/functions/scratch.ts
Normal file
@@ -0,0 +1,71 @@
|
||||
import { ALBEvent, ALBResult } from "aws-lambda";
|
||||
import { PKPass } from "passkit-generator";
|
||||
import {
|
||||
createPassGenerator,
|
||||
getRandomColorPart,
|
||||
getSpecificFileInModel,
|
||||
} from "../shared";
|
||||
|
||||
/**
|
||||
* Lambda for scratch example
|
||||
*/
|
||||
|
||||
export async function scratch(event: ALBEvent) {
|
||||
const passGenerator = createPassGenerator(undefined, {
|
||||
description: "Example Apple Wallet Pass",
|
||||
passTypeIdentifier: "pass.com.passkitgenerator",
|
||||
serialNumber: "nmyuxofgna",
|
||||
organizationName: `Test Organization ${Math.random()}`,
|
||||
teamIdentifier: "F53WB8AE67",
|
||||
foregroundColor: `rgb(${getRandomColorPart()}, ${getRandomColorPart()}, ${getRandomColorPart()})`,
|
||||
labelColor: `rgb(${getRandomColorPart()}, ${getRandomColorPart()}, ${getRandomColorPart()})`,
|
||||
backgroundColor: `rgb(${getRandomColorPart()}, ${getRandomColorPart()}, ${getRandomColorPart()})`,
|
||||
});
|
||||
|
||||
const [{ value }, iconFromModel] = await Promise.all([
|
||||
passGenerator.next(),
|
||||
getSpecificFileInModel(
|
||||
"icon.png",
|
||||
event.queryStringParameters.modelName,
|
||||
),
|
||||
]);
|
||||
|
||||
const pass = value as PKPass;
|
||||
|
||||
pass.type = "boardingPass";
|
||||
pass.transitType = "PKTransitTypeAir";
|
||||
|
||||
pass.headerFields.push(
|
||||
{
|
||||
key: "header-field-test-1",
|
||||
value: "Unknown",
|
||||
},
|
||||
{
|
||||
key: "header-field-test-2",
|
||||
value: "unknown",
|
||||
},
|
||||
);
|
||||
|
||||
pass.primaryFields.push(
|
||||
{
|
||||
key: "primaryField-1",
|
||||
value: "NAP",
|
||||
},
|
||||
{
|
||||
key: "primaryField-2",
|
||||
value: "VCE",
|
||||
},
|
||||
);
|
||||
|
||||
/**
|
||||
* Required by Apple. If one is not available, a
|
||||
* pass might be openable on a Mac but not on a
|
||||
* specific iPhone model
|
||||
*/
|
||||
|
||||
pass.addBuffer("icon.png", iconFromModel);
|
||||
pass.addBuffer("icon@2x.png", iconFromModel);
|
||||
pass.addBuffer("icon@3x.png", iconFromModel);
|
||||
|
||||
return (await passGenerator.next(pass as PKPass)).value as ALBResult;
|
||||
}
|
||||
Reference in New Issue
Block a user