Updated examples

This commit is contained in:
Alexander Cerutti
2021-10-20 00:28:49 +02:00
parent 1735a3824a
commit 158ee4221a
8 changed files with 190 additions and 143 deletions

View File

@@ -5,7 +5,7 @@
* examples, creation through templates is already shown
*/
import app from "./webserver";
import app, { getCertificates } from "./webserver";
import path from "path";
import { promises as fs } from "fs";
import { PKPass } from "passkit-generator";
@@ -62,7 +62,11 @@ async function readDirectory(filePath: string) {
return dirContent.map(async (fileName) => {
const content = await fs.readFile(path.resolve(filePath, fileName));
return getObjectFromModelFile(filePath, content, 1);
return getObjectFromModelFile(
path.resolve(filePath, fileName),
content,
2,
);
});
}
@@ -70,42 +74,43 @@ async function readDirectory(filePath: string) {
// *** EXAMPLE FROM NOW ON *** //
// *************************** //
/**
* Reading model before answering. Maybe we need to do
* something else with it.
*/
const passTemplate = new Promise<PKPass>(async (resolve) => {
const modelPath = path.resolve(__dirname, `../models/examplePass.pass`);
const [modelFilesList, certificates] = await Promise.all([
fs.readdir(modelPath),
getCertificates(),
]);
const modelPath = path.resolve(__dirname, `../models/examplePass.pass`);
const modelRecords = (
await Promise.all(
/**
* Obtaining flattened array of buffer records
* containing file name and the buffer itself.
*
* This goes also to read every nested l10n
* subfolder.
*/
const modelFilesList = await fs.readdir(modelPath);
modelFilesList.map((fileOrDirectoryPath) => {
const fullPath = path.resolve(modelPath, fileOrDirectoryPath);
const modelRecords = (
await Promise.all(
/**
* Obtaining flattened array of buffer records
* containing file name and the buffer itself.
*
* This goes also to read every nested l10n
* subfolder.
*/
modelFilesList.map((fileOrDirectoryPath) => {
const fullPath = path.resolve(modelPath, fileOrDirectoryPath);
return readFileOrDirectory(fullPath);
}),
return readFileOrDirectory(fullPath);
}),
)
)
)
.flat(1)
.reduce((acc, current) => ({ ...acc, ...current }), {});
.flat(1)
.reduce((acc, current) => ({ ...acc, ...current }), {});
/** Creating a PKPass Template */
/** Creating a PKPass Template */
const templatePass = new PKPass(modelRecords, {
wwdr: path.resolve(__dirname, "../../certificates/WWDR.pem"),
signerCert: path.resolve(__dirname, "../../certificates/signerCert.pem"),
signerKey: path.resolve(__dirname, "../../certificates/signerKey.pem"),
signerKeyPassphrase: "123456",
return resolve(
new PKPass(modelRecords, {
wwdr: certificates.wwdr,
signerCert: certificates.signerCert,
signerKey: certificates.signerKey,
signerKeyPassphrase: certificates.signerKeyPassphrase,
}),
);
});
app.all(async function manageRequest(request, response) {
@@ -114,6 +119,8 @@ app.all(async function manageRequest(request, response) {
"_" +
new Date().toISOString().split("T")[0].replace(/-/gi, "");
const templatePass = await passTemplate;
try {
const pass = await PKPass.from(
templatePass,

View File

@@ -4,42 +4,78 @@
* Here it is showed manual model reading and
* creating through another PKPass because in the other
* examples, creation through templates is already shown
*
* PLEASE NOTE THAT, AT TIME OF WRITING, THIS EXAMPLE WORKS
* ONLY IF PASSES ARE DOWNLOADED FROM SAFARI, due to the
* support of PKPasses archives. To test this, you might
* need to open a tunnel through NGROK if you cannot access
* to your local machine (in my personal case, developing
* under WSL is a pretty big limitation sometimes).
*
* @TODO test again this example with next iOS 15 versions.
* Currently, pass viewer seems to be soooo bugged.
*
* https://imgur.com/bDTbcDg.jpg
* https://imgur.com/Y4GpuHT.jpg
* https://i.imgur.com/qbJMy1d.jpg
*
* Alberto, come to look at APPLE.
*
* MAMMA MIA!
*
* A feedback to Apple have been sent for this.
*/
import app from "./webserver";
import app, { getCertificates } from "./webserver";
import path from "path";
import { promises as fs } from "fs";
import { PKPass } from "passkit-generator";
const iconFromModel = await fs.readFile(
path.resolve(__dirname, "models/exampleBooking.pass/icon.png"),
);
// *************************** //
// *** EXAMPLE FROM NOW ON *** //
// *************************** //
function getRandomColorPart() {
return Math.floor(Math.random() * 255);
}
async function generatePass(props: Object) {
const [iconFromModel, certificates] = await Promise.all([
fs.readFile(
path.resolve(__dirname, "../models/exampleBooking.pass/icon.png"),
),
getCertificates(),
]);
const pass = new PKPass(
{},
{
wwdr: path.resolve(__dirname, "../../certificates/WWDR.pem"),
signerCert: path.resolve(
__dirname,
"../../certificates/signerCert.pem",
),
signerKey: path.resolve(
__dirname,
"../../certificates/signerKey.pem",
),
signerKeyPassphrase: "123456",
wwdr: certificates.wwdr,
signerCert: certificates.signerCert,
signerKey: certificates.signerKey,
signerKeyPassphrase: certificates.signerKeyPassphrase,
},
{
...props,
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()})`,
},
props,
);
pass.type = "boardingPass";
pass.transitType = "PKTransitTypeAir";
pass.setBarcodes({
message: "123456789",
format: "PKBarcodeFormatQR",
});
pass.headerFields.push(
{
key: "header-field-test-1",
@@ -93,7 +129,7 @@ app.all(async function manageRequest(request, response) {
response.set({
"Content-type": pkpasses.mimeType,
"Content-disposition": `attachment; filename=${passName}.pkpass`,
"Content-disposition": `attachment; filename=${passName}.pkpasses`,
});
const stream = pkpasses.getAsStream();

View File

@@ -9,7 +9,7 @@
* @Author: Alexander P. Cerutti
*/
import app from "./webserver";
import app, { getCertificates } from "./webserver";
import path from "path";
import { PKPass } from "passkit-generator";
@@ -19,24 +19,17 @@ app.all(async function manageRequest(request, response) {
"_" +
new Date().toISOString().split("T")[0].replace(/-/gi, "");
const certificates = await getCertificates();
try {
const pass = await PKPass.from(
{
model: path.resolve(__dirname, "../models/exampleBooking"),
certificates: {
wwdr: path.resolve(
__dirname,
"../../certificates/WWDR.pem",
),
signerCert: path.resolve(
__dirname,
"../../certificates/signerCert.pem",
),
signerKey: path.resolve(
__dirname,
"../../certificates/signerKey.pem",
),
signerKeyPassphrase: "123456",
wwdr: certificates.wwdr,
signerCert: certificates.signerCert,
signerKey: certificates.signerKey,
signerKeyPassphrase: certificates.signerKeyPassphrase,
},
},
request.body || request.params || request.query,

View File

@@ -4,7 +4,7 @@
* .pkpass file and check for .lproj folders
*/
import app from "./webserver";
import app, { getCertificates } from "./webserver";
import path from "path";
import { PKPass } from "passkit-generator";
/** Symbols are exported just for tests and examples. Replicate only if really needed. */
@@ -16,6 +16,8 @@ app.all(async function manageRequest(request, response) {
"_" +
new Date().toISOString().split("T")[0].replace(/-/gi, "");
const certificates = await getCertificates();
try {
const pass = await PKPass.from(
{
@@ -24,42 +26,15 @@ app.all(async function manageRequest(request, response) {
`../models/${request.params.modelName}`,
),
certificates: {
wwdr: path.resolve(
__dirname,
"../../certificates/WWDR.pem",
),
signerCert: path.resolve(
__dirname,
"../../certificates/signerCert.pem",
),
signerKey: path.resolve(
__dirname,
"../../certificates/signerKey.pem",
),
signerKeyPassphrase: "123456",
wwdr: certificates.wwdr,
signerCert: certificates.signerCert,
signerKey: certificates.signerKey,
signerKeyPassphrase: certificates.signerKeyPassphrase,
},
},
request.body || request.params || request.query,
);
/**
* For each language you include, an .lproj folder in pass bundle
* is created or included. You may not want to add translations
* but only images for a specific language. So you create manually
* an .lproj folder in your pass model then add the language here
* below. If no translations does not get added, the folder is
* included or created but without pass.strings file.
*
*
* In this example, English does not have an .lproj folder yet and
* doesn't have nor receive translations.
*
* Text placeholders may not be showed for the english language
* (e.g. "Event" and "Location" as literal) and another language may be used instead
*/
pass.localize("en");
// Italian, already has an .lproj which gets included...
pass.localize("it", {
EVENT: "Evento",

View File

@@ -3,14 +3,14 @@
* by adding files later and not adding pass.json
*/
import app from "./webserver";
import app, { getCertificates } from "./webserver";
import path from "path";
import { promises as fs } from "fs";
import { PKPass } from "passkit-generator";
const iconFromModel = await fs.readFile(
path.resolve(__dirname, "models/exampleBooking.pass/icon.png"),
);
function getRandomColorPart() {
return Math.floor(Math.random() * 255);
}
app.all(async function manageRequest(request, response) {
const passName =
@@ -18,22 +18,33 @@ app.all(async function manageRequest(request, response) {
"_" +
new Date().toISOString().split("T")[0].replace(/-/gi, "");
const [iconFromModel, certificates] = await Promise.all([
fs.readFile(
path.resolve(__dirname, "../models/exampleBooking.pass/icon.png"),
),
await getCertificates(),
]);
try {
const pass = new PKPass(
{},
{
wwdr: path.resolve(__dirname, "../../certificates/WWDR.pem"),
signerCert: path.resolve(
__dirname,
"../../certificates/signerCert.pem",
),
signerKey: path.resolve(
__dirname,
"../../certificates/signerKey.pem",
),
signerKeyPassphrase: "123456",
wwdr: certificates.wwdr,
signerCert: certificates.signerCert,
signerKey: certificates.signerKey,
signerKeyPassphrase: certificates.signerKeyPassphrase,
},
{
...(request.body || request.params || request.query),
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()})`,
},
request.body || request.params || request.query,
);
pass.type = "boardingPass";

View File

@@ -8,7 +8,7 @@
* by a string
*/
import app from "./webserver";
import app, { getCertificates } from "./webserver";
import { PKPass } from "passkit-generator";
import path from "path";
@@ -18,6 +18,8 @@ app.all(async function manageRequest(request, response) {
"_" +
new Date().toISOString().split("T")[0].replace(/-/gi, "");
const certificates = await getCertificates();
try {
const pass = await PKPass.from(
{
@@ -26,19 +28,10 @@ app.all(async function manageRequest(request, response) {
`../models/${request.params.modelName}`,
),
certificates: {
wwdr: path.resolve(
__dirname,
"../../certificates/WWDR.pem",
),
signerCert: path.resolve(
__dirname,
"../../certificates/signerCert.pem",
),
signerKey: path.resolve(
__dirname,
"../../certificates/signerKey.pem",
),
signerKeyPassphrase: "123456",
wwdr: certificates.wwdr,
signerCert: certificates.signerCert,
signerKey: certificates.signerKey,
signerKeyPassphrase: certificates.signerKeyPassphrase,
},
},
request.body || request.params || request.query || {},
@@ -65,11 +58,6 @@ app.all(async function manageRequest(request, response) {
message: "Thank you for using this package <3",
format: "PKBarcodeFormatPDF417",
},
{
message: "Thank you for using this package <3",
// @ts-expect-error
format: "PKBarcodeFormatMock44617",
},
);
}

View File

@@ -7,7 +7,7 @@
* have to wait two minutes.
*/
import app from "./webserver";
import app, { getCertificates } from "./webserver";
import path from "path";
import { PKPass } from "passkit-generator";
@@ -19,6 +19,8 @@ app.all(async function manageRequest(request, response) {
return;
}
const certificates = await getCertificates();
const passName =
request.params.modelName +
"_" +
@@ -32,19 +34,10 @@ app.all(async function manageRequest(request, response) {
`../models/${request.params.modelName}`,
),
certificates: {
wwdr: path.resolve(
__dirname,
"../../certificates/WWDR.pem",
),
signerCert: path.resolve(
__dirname,
"../../certificates/signerCert.pem",
),
signerKey: path.resolve(
__dirname,
"../../certificates/signerKey.pem",
),
signerKeyPassphrase: "123456",
wwdr: certificates.wwdr,
signerCert: certificates.signerCert,
signerKey: certificates.signerKey,
signerKeyPassphrase: certificates.signerKeyPassphrase,
},
},
Object.assign(
@@ -62,6 +55,10 @@ app.all(async function manageRequest(request, response) {
// setting the expiration
pass.setExpirationDate(d);
console.log(
"EXPIRATION DATE EXPECTED:",
pass.props["expirationDate"],
);
}
const stream = pass.getAsStream();

View File

@@ -5,6 +5,8 @@
*/
import express from "express";
import { promises as fs } from "fs";
import path from "path";
export const app = express();
app.use(express.json());
@@ -25,3 +27,41 @@ app.route("/gen").all((req, res) => {
});
export default app.route("/gen/:modelName");
const certificatesCache: Partial<{
signerCert: Buffer;
signerKey: Buffer;
wwdr: Buffer;
signerKeyPassphrase: string;
}> = {};
export async function getCertificates(): Promise<typeof certificatesCache> {
if (Object.keys(certificatesCache).length) {
return certificatesCache;
}
const [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("123456"),
]);
Object.assign(certificatesCache, {
signerCert,
signerKey,
wwdr,
signerKeyPassphrase,
});
return certificatesCache;
}