### Run the example web server Source: https://github.com/alexandercerutti/passkit-generator/blob/master/examples/self-hosted/README.md Command to start the local development server for the examples. ```sh $ pnpm example; ``` -------------------------------- ### Install Dependencies and Run Serverless Example Source: https://github.com/alexandercerutti/passkit-generator/blob/master/examples/serverless/README.md These shell commands are used to install project dependencies and run the serverless examples locally. Ensure passkit-generator is built and linked in the parent workspace for changes to be reflected. ```sh $ pnpm install; $ pnpm example; ``` -------------------------------- ### Configuration for Serverless Examples Source: https://github.com/alexandercerutti/passkit-generator/blob/master/examples/serverless/README.md This JSON configuration file allows customization of constants for local execution of serverless examples. It includes settings for signer key passphrase, temporary S3 bucket, S3 access keys, and the bucket for pass models. ```json /** Passkit signerKey passphrase **/ "SIGNER_KEY_PASSPHRASE": "123456", /** Bucket name where a pass is saved before being served. **/ "PASSES_S3_TEMP_BUCKET": "pkge-test", /** S3 Access key ID - "S3RVER" is default for `serverless-s3-local`. If this example is run offline, "S3RVER" will always be used. **/ "ACCESS_KEY_ID": "S3RVER", /** S3 Secret - "S3RVER" is default for `serverless-s3-local` **/ "SECRET_ACCESS_KEY": "S3RVER", /** Bucket that contains pass models **/ "MODELS_S3_BUCKET": "pkge-mdbk" ``` -------------------------------- ### Install Passkit-Generator Source: https://github.com/alexandercerutti/passkit-generator/blob/master/README.md Install the passkit-generator package using npm. This command adds the library as a dependency to your project. ```sh $ npm install passkit-generator --save ``` -------------------------------- ### Packing Multiple PKPass Instances Source: https://github.com/alexandercerutti/passkit-generator/wiki/API-Documentation-Reference Example usage of PKPass.pack() to bundle multiple pass instances for serving. ```typescript const [passInstance1, passInstance2, passInstance3] = getThreePassesSomehow(); const pkpassesBundle = PKPass.pack(passInstance1, passInstance2, passInstance3); serveBufferWithMimeTypeSomehow( pkPassesBundle.getAsBuffer(), pkPassesBundle.mimeType /** -> application/vnd.apple.pkpasses **/, ); ``` -------------------------------- ### Run Firebase Emulator Source: https://github.com/alexandercerutti/passkit-generator/blob/master/examples/firebase/README.md Command to start the local Firebase Cloud Function emulator. ```sh $ pnpm serve ``` -------------------------------- ### Check OpenSSL Version Source: https://github.com/alexandercerutti/passkit-generator/wiki/Generating-Certificates Verify the installed version of OpenSSL or LibreSSL to determine compatibility with legacy encryption algorithms. ```sh $ openssl version -a ``` -------------------------------- ### Defining Helper Functions for Pass Creation Source: https://github.com/alexandercerutti/passkit-generator/wiki/API-Documentation-Reference Example helper functions to retrieve properties and certificates required for pass generation. ```typescript function getAdditionalPropsForThisPassSomehow() { // get your additional props for THIS pass return { serialNumber: "12356222", /** moar props ... */ }; } function getSomeProps() { /** Set your base props for all your passes **/ return { description: "Pass for some business activity", webServiceURL: "https://example.com/passkit", /** moar props ... */ }; } function getCertificatesSomehow() { return { signerCert: "" /** string or Buffer **/, signerKey: "" /** string or Buffer **/, wwdr: "" /** string or Buffer **/, signerKeyPassphrase: "" /** string **/, }; } ``` -------------------------------- ### Pass Request Payload Source: https://github.com/alexandercerutti/passkit-generator/blob/master/examples/firebase/README.md Example JSON body for a POST request to the local function URL. ```json { "passModel": "exampleBooking", "serialNumber": "unnannasyg1341", "transitType": "PKTransitTypeAir", "textColor": "rgb(255,255,255)", "backgroundColor": "rgb(10,10,10)", "labelColor": "rgb(255,255,255)", "logoFile": "logo.png", "header": [ { "label": "When", "value": "10/10/2023" } ], "primary": [ { "label": "Napoli Capodichino", "value": "NAP" }, { "label": "Amsterdam Schiphol", "value": "AMS" } ] } ``` -------------------------------- ### Cloudflare Workers Pass Generation Source: https://context7.com/alexandercerutti/passkit-generator/llms.txt Deploy this example on Cloudflare Workers for serverless pass generation. It requires assets like icons and logos to be imported via the Wrangler bundler. ```typescript import { PKPass } from "passkit-generator"; import { Buffer } from "node:buffer"; // Assets imported via Wrangler bundler import icon from "./assets/icon.png"; import icon2x from "./assets/icon@2x.png"; import logo from "./assets/logo.png"; export interface Env { WWDR: string; SIGNER_CERT: string; SIGNER_KEY: string; SIGNER_PASSPHRASE: string; } export default { async fetch(request: Request, env: Env): Promise { const url = new URL(request.url); const customerId = url.searchParams.get("id") || "GUEST"; const pass = new PKPass( { "icon.png": Buffer.from(icon), "icon@2x.png": Buffer.from(icon2x), "logo.png": Buffer.from(logo), }, { signerCert: env.SIGNER_CERT, signerKey: env.SIGNER_KEY, signerKeyPassphrase: env.SIGNER_PASSPHRASE, wwdr: env.WWDR, }, { description: "Loyalty Card", serialNumber: `LOYALTY-${customerId}`, passTypeIdentifier: "pass.com.example.loyalty", teamIdentifier: "ABCDE12345", organizationName: "Coffee Shop", foregroundColor: "rgb(255, 255, 255)", backgroundColor: "rgb(139, 69, 19)", } ); pass.type = "storeCard"; pass.setBarcodes(customerId); pass.primaryFields.push({ key: "points", label: "POINTS", value: "0", }); pass.secondaryFields.push({ key: "member", label: "MEMBER", value: customerId, }); return new Response(pass.getAsBuffer(), { headers: { "Content-Type": pass.mimeType, "Content-Disposition": `attachment; filename=loyalty-${customerId}.pkpass`, }, }); }, }; ``` -------------------------------- ### Enable Debugging in Bash-like Consoles Source: https://github.com/alexandercerutti/passkit-generator/wiki/Troubleshooting-(Self-help) To enable debugging for Passkit-generator in macOS, Linux, or WSL, prepend the DEBUG environment variable to your application's start command. Be aware that enabling this may produce a large volume of logs if many packages use the debug system. ```bash $ DEBUG=* node app.js ``` -------------------------------- ### Get Raw Pass Files as Buffers Source: https://github.com/alexandercerutti/passkit-generator/wiki/API-Documentation-Reference Retrieves a frozen object containing all pass files with their compiled signatures and manifests as Buffer objects. Useful for custom zip creation with external libraries. ```typescript pass.getAsRaw(): Readonly<{ [path: string]: Buffer }>; ``` ```typescript import { toBuffer as doNotZip } from "do-not-zip"; const passFiles = pass.getAsRaw(); const crunchedData = Object.entries(passFiles).map(([path, data]) => ({ path, data, })); doSomethingWithCustomZippedPass(doNotZip(chunchedData)); ``` -------------------------------- ### PKPass.from() - Creating from Filesystem Template Source: https://context7.com/alexandercerutti/passkit-generator/llms.txt Demonstrates how to load a pre-designed pass model from the filesystem and apply dynamic runtime customizations. ```APIDOC ## PKPass.from() ### Description Loads a pass model from the filesystem, ideal for using pre-designed templates with dynamic customization at runtime. ### Request Example ```typescript const pass = await PKPass.from( { model: "./models/boardingPass", certificates }, { serialNumber: "FLIGHT-123", description: "Boarding Pass" } ); ``` ``` -------------------------------- ### Get Pass as Stream Source: https://github.com/alexandercerutti/passkit-generator/wiki/API-Documentation-Reference Generates a stream for the zipped pass. ```typescript pass.getAsStream(): Stream; ``` ```javascript const passStream = pass.getAsStream(); doSomethingWithPassStream(passStream); ``` -------------------------------- ### PKPass Constructor - Creating a Pass from Buffers Source: https://context7.com/alexandercerutti/passkit-generator/llms.txt Demonstrates how to instantiate a new PKPass object using raw buffer data for assets and certificates, providing full control over the pass structure. ```APIDOC ## PKPass Constructor ### Description Creates a new PKPass instance directly from buffer data, allowing complete control over pass contents without filesystem dependencies. ### Request Example ```typescript const pass = new PKPass( { "icon.png": iconBuffer, "logo.png": logoBuffer }, { wwdr, signerCert, signerKey, signerKeyPassphrase: "passphrase" }, { description: "Ticket", passTypeIdentifier: "pass.id", serialNumber: "123", teamIdentifier: "ABC", organizationName: "Org" } ); ``` ``` -------------------------------- ### Configure Time-Based Relevance for Pass Notifications Source: https://context7.com/alexandercerutti/passkit-generator/llms.txt Use `setRelevantDates()` for iOS 18+ to define start and end times for pass notifications. For older iOS versions, `setRelevantDate()` can be used with a single date. This is useful for events with specific start and end times or multiple date options. ```typescript import { PKPass } from "passkit-generator"; const pass = await PKPass.from( { model: "./models/eventTicket.pass", certificates }, { serialNumber: "CONCERT-2024-001" } ); pass.type = "eventTicket"; // iOS 18+ preferred: setRelevantDates with start and end times pass.setRelevantDates([ { startDate: "2024-12-15T18:00:00-05:00", endDate: "2024-12-15T23:00:00-05:00", }, ]); // For backwards compatibility with iOS 17 and earlier pass.setRelevantDate(new Date("2024-12-15T19:00:00-05:00")); // For event ticket with multiple date options const multiDayPass = await PKPass.from( { model: "./models/eventTicket.pass", certificates }, { serialNumber: "FESTIVAL-2024" } ); multiDayPass.setRelevantDates([ { startDate: "2024-07-15T12:00:00Z", endDate: "2024-07-15T23:59:00Z" }, { startDate: "2024-07-16T12:00:00Z", endDate: "2024-07-16T23:59:00Z" }, { startDate: "2024-07-17T12:00:00Z", endDate: "2024-07-17T23:59:00Z" }, ]); const buffer = pass.getAsBuffer(); ``` -------------------------------- ### PKPass Constructor Source: https://github.com/alexandercerutti/passkit-generator/wiki/API-Documentation-Reference Initializes a new PKPass instance with required file buffers and Apple certificates. ```APIDOC ## constructor(buffers, certificates, props) ### Description Creates a new PKPass instance. This class extends an internal Bundle class to manage pass data and files. ### Arguments - **buffers** (object) - Required - Initial file buffers in format { path: Buffer }. - **certificates** (object) - Required - Object containing Apple certificates. - **wwdr** (string|Buffer) - Required - Apple WWDR certificate content. - **signerCert** (string|Buffer) - Required - Developer certificate content. - **signerKey** (string|Buffer) - Required - Developer certificate key content. - **signerKeyPassphrase** (string) - Optional - Passphrase for the signerKey. - **props** (object) - Optional - Pass properties to merge with pass.json. ### Request Example const pass = new PKPass({ "icon.png": buffer }, { wwdr: "...", signerCert: "...", signerKey: "..." }, { description: "My Pass" }); ``` -------------------------------- ### Instantiating a PKPass Source: https://github.com/alexandercerutti/passkit-generator/wiki/API-Documentation-Reference Create a new pass instance by providing initial file buffers, certificates, and optional properties. ```typescript const pass = new PKPass({ ... }, { ... }, { ... }); ``` -------------------------------- ### Clone and Extend a PKPass Instance Source: https://github.com/alexandercerutti/passkit-generator/wiki/Migrating-from-v2-to-v3 Demonstrates cloning an existing pass instance to serve as a template for a new pass. ```diff - const pass = await createPass(aPreviouslyCreatedAbstractModel, { }, { }); + const pass = await PKPass.from( + new PKPass( + { }, + { }, + { } + ), + { } + ); ``` -------------------------------- ### PKPass.pack() Source: https://github.com/alexandercerutti/passkit-generator/wiki/API-Documentation-Reference This method accepts a series of PKPass instances and returns a new Bundle instance, allowing you to serve all the passes together. It internally invokes `.getAsBuffer()` on each pass instance and locks the passes, assuming they won't be edited further. ```APIDOC ## PKPass.pack() ### Description Accepts a series of PKPass instances and returns a new Bundle instance, allowing you to serve all the passes together. Internally invokes `.getAsBuffer()` on each pass instance and locks the passes, assuming they won't be edited further. ### Method Static method of PKPass class ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Parameters - **args** (PKPass[]) - Required - A variable number of PKPass instances to be bundled. ### Request Example ```typescript const [passInstance1, passInstance2, passInstance3] = getThreePassesSomehow(); const pkpassesBundle = PKPass.pack(passInstance1, passInstance2, passInstance3); serveBufferWithMimeTypeSomehow( pkpassesBundle.getAsBuffer(), pkpassesBundle.mimeType /** -> application/vnd.apple.pkpasses **/ ); ``` ### Response #### Success Response (200) - **Bundle** (object) - A Bundle instance containing all provided PKPass instances, ready for distribution. #### Response Example ```json { "mimeType": "application/vnd.apple.pkpasses", "getAsBuffer": "" } ``` ### Throws Throws if not all the args are instances of PKPass. ``` -------------------------------- ### PKPass.from Static Method Source: https://github.com/alexandercerutti/passkit-generator/wiki/API-Documentation-Reference Creates a new PKPass instance from an existing pass or a template saved on disk. ```APIDOC ## PKPass.from(source, props) ### Description Creates a new PKPass instance based on an existing PKPass object or a template. Throws an error if the source is invalid. ### Parameters - **source** (PKPass|PKPass.Template) - Required - The source object or template to create the pass from. - **props** (Schemas.OverridableProps) - Optional - Additional properties to override or set for the new pass. ### Response - **Returns** (Promise) - A promise that resolves to a new PKPass instance. ``` -------------------------------- ### Get Available Languages Source: https://github.com/alexandercerutti/passkit-generator/wiki/API-Documentation-Reference Retrieves an array of language keys currently added to the pass, such as ['en', 'it']. ```typescript pass.languages ``` -------------------------------- ### Get Pass as Buffer Source: https://github.com/alexandercerutti/passkit-generator/wiki/API-Documentation-Reference Generates a buffer of the zipped pass, suitable for environments like cloud functions where streams are not supported. ```typescript pass.getAsBuffer(): Buffer; ``` ```javascript const passBuffer = pass.getAsBuffer(); doSomethingWithPassBuffer(passBuffer); ``` -------------------------------- ### Get Pass Mime Type Source: https://github.com/alexandercerutti/passkit-generator/wiki/API-Documentation-Reference Abstracts the mime type of the generated PKPass archive ('application/vnd.apple.pkpass') or PKPasses archive ('application/vnd.apple.pkpasses'). Automatically set during creation or packing. ```typescript pass.mimeType; ``` -------------------------------- ### Import Pass from External Source Source: https://github.com/alexandercerutti/passkit-generator/wiki/Migrating-from-v2-to-v3 Uses the static PKPass.from method to load a pass model from the file system. ```diff - await createPass({ - model: "path/to/your/model/fs.pass", - certificates: { ... }, - overrides: { ... } - }); + await PKPass.from({ + model: "path/to/your/model/fs.pass", + certificates: { ... } + }, { }); ``` -------------------------------- ### Generate Pass as Stream Source: https://github.com/alexandercerutti/passkit-generator/wiki/API-Documentation-Reference Creates a stream for the zipped pass. This method locks the pass instance, preventing further modifications. This is the standard way to get the generated pass. ```APIDOC ## GET PASS AS STREAM ### Description Creates a stream for the zipped pass. This method locks the pass instance. ### Method `pass.getAsStream(): Stream;` ### Parameters None ### Request Example ```typescript const passStream = pass.getAsStream(); doSomethingWithPassStream(passStream); ``` ### Response #### Success Response (200) - **Stream** - A stream representing the zipped pass. #### Response Example ```javascript // Example of a stream object (actual content is streamed) PassStream { readable: true, writable: false, ... } ``` ``` -------------------------------- ### Create and Clone Passes with PKPass.from() Source: https://context7.com/alexandercerutti/passkit-generator/llms.txt Use PKPass.from() to create a template pass and then clone it for multiple users. This is efficient for passes with shared assets and configurations. Ensure all necessary assets and certificates are loaded before creating the template. ```typescript import { PKPass } from "passkit-generator"; // Create a base template pass (loaded once at startup) const passTemplate = new PKPass( { "icon.png": await fs.readFile("./assets/icon.png"), "icon@2x.png": await fs.readFile("./assets/icon@2x.png"), "logo.png": await fs.readFile("./assets/logo.png"), "logo@2x.png": await fs.readFile("./assets/logo@2x.png"), "background.png": await fs.readFile("./assets/background.png"), }, { wwdr: await fs.readFile("./certs/WWDR.pem"), signerCert: await fs.readFile("./certs/signerCert.pem"), signerKey: await fs.readFile("./certs/signerKey.pem"), signerKeyPassphrase: "passphrase", }, { passTypeIdentifier: "pass.com.example.loyalty", teamIdentifier: "ABCDE12345", organizationName: "Coffee Shop", description: "Loyalty Card", foregroundColor: "rgb(255, 255, 255)", backgroundColor: "rgb(139, 69, 19)", } ); passTemplate.type = "storeCard"; // Clone template for each customer async function generateLoyaltyCard(customerId: string, customerName: string, points: number) { const pass = await PKPass.from(passTemplate, { serialNumber: `LOYALTY-${customerId}`, }); pass.primaryFields.push({ key: "points", label: "POINTS", value: points, }); pass.secondaryFields.push({ key: "name", label: "MEMBER", value: customerName, }); pass.auxiliaryFields.push({ key: "memberId", label: "MEMBER ID", value: customerId, }); pass.setBarcodes(customerId); return pass.getAsBuffer(); } // Generate passes for multiple customers const card1 = await generateLoyaltyCard("C001", "Alice Smith", 1250); const card2 = await generateLoyaltyCard("C002", "Bob Johnson", 890); ``` -------------------------------- ### Create PKPass from Buffers Source: https://context7.com/alexandercerutti/passkit-generator/llms.txt Initialize a pass instance using raw buffer data for assets and certificates, allowing for complete programmatic control. ```typescript import { PKPass } from "passkit-generator"; import fs from "node:fs/promises"; // Load certificates const [signerCert, signerKey, wwdr] = await Promise.all([ fs.readFile("./certs/signerCert.pem", "utf-8"), fs.readFile("./certs/signerKey.pem", "utf-8"), fs.readFile("./certs/WWDR.pem", "utf-8"), ]); // Load pass assets const iconBuffer = await fs.readFile("./assets/icon.png"); const logoBuffer = await fs.readFile("./assets/logo.png"); // Create pass from buffers const pass = new PKPass( { "icon.png": iconBuffer, "icon@2x.png": iconBuffer, "logo.png": logoBuffer, "logo@2x.png": logoBuffer, }, { wwdr, signerCert, signerKey, signerKeyPassphrase: "your-passphrase", }, { description: "Concert Ticket", passTypeIdentifier: "pass.com.example.ticket", serialNumber: "E5982H-I2", teamIdentifier: "ABCDE12345", organizationName: "Awesome Events Inc.", foregroundColor: "rgb(255, 255, 255)", backgroundColor: "rgb(60, 65, 76)", labelColor: "rgb(200, 200, 200)", } ); // Set pass type and add fields pass.type = "eventTicket"; pass.headerFields.push({ key: "date", label: "DATE", value: "Dec 15, 2024", }); pass.primaryFields.push({ key: "event", label: "EVENT", value: "Rock Concert 2024", }); pass.secondaryFields.push( { key: "location", label: "VENUE", value: "Madison Square Garden" }, { key: "time", label: "DOORS OPEN", value: "7:00 PM" } ); pass.setBarcodes("TICKET-E5982H-I2"); // Generate pass const buffer = pass.getAsBuffer(); await fs.writeFile("concert-ticket.pkpass", buffer); ``` -------------------------------- ### Access Current Pass Properties Source: https://github.com/alexandercerutti/passkit-generator/wiki/API-Documentation-Reference Gets a nested clone of the current pass properties, organized similarly to the pass.json structure. Useful for reading existing configurations like locations. ```typescript const currentProps = pass.props; ``` ```typescript const currentLocations = pass.props["locations"]; pass.locations( { latitude: 66.45725212, longitude: 33.01000442, }, { longitude: 4.42634523, latitude: 5.344233323352, }, ...currentLocations, ); ``` -------------------------------- ### Export Pass as Stream using getAsStream() Source: https://context7.com/alexandercerutti/passkit-generator/llms.txt Use getAsStream() to get the signed pass as a Readable Stream. This is ideal for direct HTTP responses or piping the output to files. The pass is locked after export. ```typescript // Method 2: getAsStream() - Returns a Readable Stream // Best for: Direct HTTP responses, piping to files const stream = pass.getAsStream(); // Pipe to file const writeStream = createWriteStream("pass.pkpass"); stream.pipe(writeStream); ``` ```typescript // Use in Express.js with stream app.get("/pass-stream", async (req, res) => { const pass = await generatePass(); const stream = pass.getAsStream(); res.set({ "Content-Type": pass.mimeType, "Content-Disposition": "attachment; filename=pass.pkpass", }); stream.pipe(res); }); ``` -------------------------------- ### Create PKPass from Filesystem Template Source: https://context7.com/alexandercerutti/passkit-generator/llms.txt Load a pre-designed pass model from the filesystem to populate dynamic fields at runtime. ```typescript import { PKPass } from "passkit-generator"; import path from "node:path"; import fs from "node:fs/promises"; const certificates = { wwdr: await fs.readFile("./certs/WWDR.pem", "utf-8"), signerCert: await fs.readFile("./certs/signerCert.pem", "utf-8"), signerKey: await fs.readFile("./certs/signerKey.pem", "utf-8"), signerKeyPassphrase: "123456", }; // Create pass from filesystem model (.pass extension is auto-appended) const pass = await PKPass.from( { model: path.resolve(__dirname, "./models/boardingPass"), certificates, }, { serialNumber: "FLIGHT-" + Date.now(), description: "Boarding Pass - Flight EZY997", } ); // Configure boarding pass specifics pass.transitType = "PKTransitTypeAir"; pass.headerFields.push( { key: "date", label: "Date", value: "25 May", textAlignment: "PKTextAlignmentCenter" }, { key: "flight", label: "Flight", value: "EZY997", textAlignment: "PKTextAlignmentCenter" } ); pass.primaryFields.push( { key: "origin", value: "NAP", label: "Naples", textAlignment: "PKTextAlignmentLeft" }, { key: "destination", value: "VCE", label: "Venice", textAlignment: "PKTextAlignmentRight" } ); pass.secondaryFields.push( { key: "gate", label: "Gate", value: "A12" }, { key: "boarding", label: "Boarding", value: "18:40" }, { key: "departure", label: "Departure", value: "19:10" } ); pass.auxiliaryFields.push( { key: "passenger", label: "Passenger", value: "John Doe" }, { key: "seat", label: "Seat", value: "14A" } ); pass.setBarcodes({ message: "M1DOE/JOHN E5982H NAPVCE EZY997 125 14A", format: "PKBarcodeFormatPDF417", altText: "Scan at gate", }); const stream = pass.getAsStream(); ``` -------------------------------- ### Migrate from createPass to PKPass Constructor Source: https://github.com/alexandercerutti/passkit-generator/wiki/Migrating-from-v2-to-v3 Replaces the asynchronous factory function with a synchronous constructor approach and renames the class to PKPass. ```diff - await createPass({ - model: { }, - certificates: { } - }); + new PKPass( + { }, + { }, + { } + ); ``` -------------------------------- ### Generate manifest.json using bash script Source: https://github.com/alexandercerutti/passkit-generator/wiki/Generating-Certificates A bash script to automatically create the manifest.json file by finding all files, calculating their SHA-1 hashes, and formatting them as key-value pairs. It handles subdirectories and ensures correct JSON formatting. ```sh $ echo "{$(RESULT=\"\"; for i in $(find * -type f); do RESULT+=$(openssl sha1 -binary $i | xxd -p | awk -v filename=\"$i\" '{print \"\" filename \"\": ``` -------------------------------- ### Set and Get Pass Type Source: https://github.com/alexandercerutti/passkit-generator/wiki/API-Documentation-Reference Allows specifying or retrieving the pass type (e.g., 'coupon', 'storeCard'). Setting the type resets fields and transitType, as they are type-dependent. Throws an error for invalid types or if the pass is frozen. ```typescript pass.type = "coupon"; pass.type !== undefined; ``` ```typescript const pass = new PKPass({ ... }, { ... }, { ... }); // Assuming a pass.json with a type inside has been added first and it has 5 valid primaryFields. console.log(pass.primaryFields.length); // 5 pass.type = "storeCard"; console.log(pass.primaryFields.length); // 0 console.log("Pass type is", pass.type); // "Pass type is storeCard" ``` -------------------------------- ### Setting Barcodes with Options Objects Source: https://github.com/alexandercerutti/passkit-generator/wiki/Migrating-from-v1-to-v2 Shows how to use the `barcodes` method by passing multiple options objects for configuring barcodes. ```typescript .barcodes({ ... }, { ... }, { ... }, ...); ``` -------------------------------- ### PKPass.from() - From Template Source: https://github.com/alexandercerutti/passkit-generator/wiki/API-Documentation-Reference Loads a pass from a template file on the file system. Requires the path to the model and certificate data. ```APIDOC ## PKPass.from() - From Template ### Description Use this if you have a saved model on your File System and want to read it and use it as the source for your pass. ### Method `PKPass.from(template: { model: string, certificates: object }, additionalProps?: object): Promise ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body - **template** (object) - Required - An object containing the template details. - **model** (string) - Required - The path to your model on File System. - **certificates** (object) - Required - The object containing certificates data. Refer to PKPass's constructor for all the keys. - **additionalProps** (object) - Optional - Additional properties to merge into the new pass. ### Request Example ```typescript const passFromDisk = await PKPass.from( { model: "../../path/to/your/disk/model", certificates: getCertificatesSomehow(), }, getAdditionalPropsForThisPassSomehow(), ); ``` ### Response #### Success Response (200) - **PKPass** (object) - The newly created PKPass object. #### Response Example ```json { "pass": "newly created PKPass object" } ``` ``` -------------------------------- ### Generate signature file for pass Source: https://github.com/alexandercerutti/passkit-generator/wiki/Generating-Certificates Use openssl smime to sign the manifest.json file using your WWDR certificate, signer certificate, and private key. The output is saved to a file named 'signature'. ```sh $ openssl smime -binary -sign -certfile WWDR.pem -signer signerCert.pem -inkey signerKey.pem -in manifest.json -out signature -outform DER -passin pass: ``` -------------------------------- ### Authenticate with Firebase Source: https://github.com/alexandercerutti/passkit-generator/blob/master/examples/firebase/README.md Initiate the login process to authenticate the local environment with Firebase services. ```sh $ pnpm firebase login ``` -------------------------------- ### Export Methods (getAsBuffer, getAsStream, getAsRaw) Source: https://context7.com/alexandercerutti/passkit-generator/llms.txt Methods to export a signed PKPass object into different formats for storage, streaming, or debugging. ```APIDOC ## Export Methods ### Description Exports the signed pass in various formats. Note: After calling any of these methods, the pass is locked and cannot be modified further. ### Methods - **getAsBuffer()**: Returns a Buffer. Ideal for cloud functions, database storage, or API responses. - **getAsStream()**: Returns a Readable Stream. Ideal for direct HTTP responses or piping to files. - **getAsRaw()**: Returns an object containing raw file buffers (e.g., pass.json, signature). Ideal for custom compression or debugging. ### Response - **getAsBuffer()**: Buffer - **getAsStream()**: ReadableStream - **getAsRaw()**: Object ``` -------------------------------- ### Deploy Firebase Function Source: https://github.com/alexandercerutti/passkit-generator/blob/master/examples/firebase/README.md Command to deploy the function to Firebase. ```sh $ pnpm deploy ``` -------------------------------- ### Creating a Pass from Source Source: https://github.com/alexandercerutti/passkit-generator/wiki/API-Documentation-Reference Use the static from method to create a pass from an existing PKPass instance or a template. ```typescript PKPass.from(source: PKPass | PKPass.Template, props?: Schemas.OverridableProps): Promise; ``` -------------------------------- ### PKPass.pack() Method Signature Source: https://github.com/alexandercerutti/passkit-generator/wiki/API-Documentation-Reference The method signature for packing multiple PKPass instances. ```typescript PKPass.pack(...args: PKPass[]): Bundle; ``` -------------------------------- ### Loading Pass Model from Physical Path Source: https://github.com/alexandercerutti/passkit-generator/wiki/Migrating-from-v1-to-v2 Shows how to specify the pass model using a file path when creating a pass with the `createPass` factory method. ```typescript await createPass({ model: "../myExamplePass.pass", ... }); ``` -------------------------------- ### Setting a Specific Barcode Format Source: https://github.com/alexandercerutti/passkit-generator/wiki/Migrating-from-v1-to-v2 Illustrates how to set a specific barcode format using the `barcode` method after barcodes have already been configured. Note that `PKBarcodeFormatCode128` is not supported. ```typescript pass .barcodes(...) .barcode("PKBarcodeFormatPDF417"); ``` -------------------------------- ### Importing PKPass Source: https://github.com/alexandercerutti/passkit-generator/wiki/API-Documentation-Reference Import the PKPass class using either CommonJS or ESM syntax. ```javascript // CJS const { PKPass } = require("passkit-generator"); // ESM import { PKPass } from "passkit-generator"; ``` -------------------------------- ### Time-Based Relevance Configuration Source: https://context7.com/alexandercerutti/passkit-generator/llms.txt Methods to configure when a pass should appear on the lock screen based on time intervals. ```APIDOC ## setRelevantDates() and setRelevantDate() ### Description Configures date/time triggers for pass notification display. `setRelevantDates` is preferred for iOS 18+ supporting start and end times, while `setRelevantDate` provides backwards compatibility for iOS 17 and earlier. ### Parameters #### Request Body - **dates** (Array) - Required - An array of objects containing `startDate` and `endDate` strings for `setRelevantDates`. - **date** (Date|String) - Required - A single date object or string for `setRelevantDate`. ``` -------------------------------- ### Localizing Passes Source: https://github.com/alexandercerutti/passkit-generator/wiki/API-Documentation-Reference Information on how to localize passes using .lproj folders, adding localized files, or using the .localize method. ```APIDOC ## Localizing Passes ### Description According to Apple Developer Documentation, localization (L10N) is done by creating a `.lproj` folder for each language you want to translate your pass, each named with the relative [ISO-3166-1 alpha-2](https://it.wikipedia.org/wiki/ISO_3166-1_alpha-2) code (e.g. `en.lproj`). There are three ways to include a language in this package: - By importing a localized buffer or a localized model when creating the instance; - By adding a file (media or pass.strings) for that specific language through `.addBuffer` method (like `.addBuffer("en.lproj/thumbnail@2x.png", Buffer.from([...]))`); - By specifying translations for a language through `.localize` method below; > If you are designing your pass for a language only, you can directly replace the placeholders in `pass.json` with translation. ### Method `pass.localize(language: string, translations: object): void; ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body - **language** (string) - Required - The ISO-3166-1 alpha-2 code for the language (e.g., 'en'). - **translations** (object) - Required - An object containing key-value pairs for localized strings. ### Request Example ```typescript pass.localize('en', { 'eventTicket.eventName': 'My Awesome Concert', 'eventTicket.locationName': 'The Grand Arena' }); ``` ### Response #### Success Response (200) None (void method). #### Response Example None. ``` -------------------------------- ### PKPass.from() - Cloning from Another Pass Source: https://context7.com/alexandercerutti/passkit-generator/llms.txt Creates a runtime template pass that can be efficiently cloned for generating multiple passes with shared assets. This is useful for the template pattern where a base pass is created once and then cloned for each user. ```APIDOC ## PKPass.from() - Cloning from Another Pass (Template Pattern) ### Description Creates a runtime template pass that can be efficiently cloned for generating multiple passes with shared assets. ### Method `PKPass.from(templatePass, options)` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```typescript // Assuming passTemplate is already created as shown in the library's documentation const pass = await PKPass.from(passTemplate, { serialNumber: `LOYALTY-${customerId}`, }); pass.primaryFields.push({ key: "points", label: "POINTS", value: points, }); // ... other field additions return pass.getAsBuffer(); ``` ### Response #### Success Response (200) Returns a `PKPass` object that is a clone of the template pass, with specified overrides. #### Response Example (The method returns a `PKPass` object, which is then used to generate a buffer.) ``` -------------------------------- ### Loading Pass Model from Preprocessed Buffers Source: https://github.com/alexandercerutti/passkit-generator/wiki/Migrating-from-v1-to-v2 Illustrates how to provide a preprocessed pass model as an object containing Buffers for different pass components when using `createPass`. ```typescript await createPass({ model: { "thumbnail": Buffer.from([ ... ]), "pass.json": Buffer.from([ ... ]), "it.lproj/pass.strings": Buffer.from([ ... ]) } }); ``` -------------------------------- ### Setting Barcodes with a String Message Source: https://github.com/alexandercerutti/passkit-generator/wiki/Migrating-from-v1-to-v2 Demonstrates the new usage of the `barcodes` method, which can accept a string message to automatically generate barcode structures. ```typescript .barcodes("your-pass-message"); ``` -------------------------------- ### Properties: Getters and Setters Source: https://github.com/alexandercerutti/passkit-generator/wiki/API-Documentation-Reference Access and modify pass properties, certificates, languages, and types. ```APIDOC ## Properties ### .props (getter) Returns a nested clone of the current pass properties. ### .certificates (setter) Updates the certificates used for the pass. Throws if the pass is frozen or validation fails. ### .languages (getter) Returns an array of currently added language keys (e.g., ["en", "it"]). ### .type (getter/setter) Specifies or retrieves the pass type. Note: Setting this resets all fields and transitType. ### .mimeType (getter) Returns the mimeType of the archive (e.g., application/vnd.apple.pkpass). ``` -------------------------------- ### PKPass.pack() Source: https://context7.com/alexandercerutti/passkit-generator/llms.txt Bundles multiple PKPass objects into a single .pkpasses file for iOS 15+ support. ```APIDOC ## PKPass.pack() ### Description Creates a .pkpasses bundle containing multiple passes. This is useful for grouping related passes, such as family boarding passes. ### Parameters - **...passes** (PKPass[]) - Required - A list of PKPass objects to include in the bundle. ### Response - **Returns**: A bundle object with a mimeType of 'application/vnd.apple.pkpasses'. ``` -------------------------------- ### Extracting Certificates and Keys via OpenSSL Source: https://github.com/alexandercerutti/passkit-generator/wiki/Generating-Certificates Use these commands to convert a PKCS#12 file into PEM format for use with passkit-generator. Ensure you replace placeholders with your actual P12 password and chosen secret passphrase. ```sh # Creating and changing dir $ mkdir "certs" && cd $_ # Extracting key and cert from pkcs12 # for -passin is the pass for the P12 $ openssl pkcs12 -in .p12 -clcerts -nokeys -out signerCert.pem -passin pass: # for -passin is the pass for the P12. is the pass you'll pass to passkit-generator to decrypt privateKey. $ openssl pkcs12 -in .p12 -nocerts -out signerKey.pem -passin pass: -passout pass: ``` -------------------------------- ### Execute Firebase CLI commands Source: https://github.com/alexandercerutti/passkit-generator/blob/master/examples/firebase/README.md Use the local Firebase CLI tools via pnpm to manage cloud functions. ```sh $ pnpm firebase ``` -------------------------------- ### Base64 Encoding for Serverless PKPass Source: https://github.com/alexandercerutti/passkit-generator/wiki/Troubleshooting-(Self-help) This code snippet demonstrates how to encode a PKPass file as a base64 string, which can be a solution for PKZipArchiver errors encountered in serverless environments. ```typescript const pkpassBase64 = Buffer.from(pkpass).toString("base64"); return pkpassBase64; ``` -------------------------------- ### Updated Certificate and Key Structure Source: https://github.com/alexandercerutti/passkit-generator/wiki/Migrating-from-v2-to-v3 Certificates and keys can now be provided as strings or Buffers. The signerKeyPassphrase is now an optional parameter. ```diff -{ - wwdr: string; - signerCert: string; - signerKey: string | { - keyFile: string; - passphrase?: string; - } -} +{ + wwdr: string | Buffer; + signerCert: string | Buffer; + signerKey: string | Buffer; + signerKeyPassphrase?: string; +} ``` -------------------------------- ### PKPass.from() - From Another Pass Source: https://github.com/alexandercerutti/passkit-generator/wiki/API-Documentation-Reference Clones an existing PKPass object, copying all properties and files except manifest and signature. Useful for creating runtime templates. ```APIDOC ## PKPass.from() - From Another Pass ### Description Pass another `PKPass` as the source of `PKPass.from` to make it clone every property and file in the source object (except manifest and signature). This is useful if you want to create a runtime template with your buffers and then always use it as a base. ### Method `PKPass.from(sourcePass: PKPass, additionalProps?: object): Promise ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body - **sourcePass** (PKPass) - Required - The PKPass object to clone. - **additionalProps** (object) - Optional - Additional properties to merge into the new pass. ### Request Example ```typescript const passRuntimeTemplate = new PKPass( getBuffersSomehow(), getCertificatesSomehow(), getSomeProps(), ); // later... const passToBeServed = await PKPass.from( passRuntimeTemplate, getAdditionalPropsForThisPassSomehow(), ); ``` ### Response #### Success Response (200) - **PKPass** (object) - The newly created PKPass object. #### Response Example ```json { "pass": "newly created PKPass object" } ``` ``` -------------------------------- ### Analyze Certificate Details Source: https://github.com/alexandercerutti/passkit-generator/wiki/Generating-Certificates Display detailed information for PEM or DER formatted certificates to verify identifiers. ```sh # for PEM certificates $ openssl x509 -inform PEM -in .pem -noout -text # for CER certificates $ openssl x509 -inform DER -in .cer -noout -text ``` -------------------------------- ### Create a pass from a disk model Source: https://github.com/alexandercerutti/passkit-generator/wiki/API-Documentation-Reference Reads a saved model from the file system to use as a source for a new pass. ```typescript const passFromDisk = await PKPass.from( { model: "../../path/to/your/disk/model", certificates: getCertificatesSomehow(), }, getAdditionalPropsForThisPassSomehow(), ); ``` -------------------------------- ### Create Pass using Factory Method Source: https://github.com/alexandercerutti/passkit-generator/wiki/Migrating-from-v1-to-v2 Compares the old synchronous pass generation flow with the new asynchronous factory method `createPass`. The new method reads the model and certificates once upon creation. ```javascript const pass = new Pass({ ... }); pass.localize("en", { ... }); try { const stream = await pass.generate(); doSomethingWithStream(stream); } catch (err) { doSomethingWithError(err); } ``` ```typescript try { const pass = await createPass({ ... }); pass.localize("en", { ... }); const stream = pass.generate(); doSomethingWithStream(stream); } catch (err) { doSomethingWithError(err); } ``` -------------------------------- ### Pass Exporting with New Methods Source: https://github.com/alexandercerutti/passkit-generator/wiki/Migrating-from-v2-to-v3 Demonstrates the replacement of the old .generate() method with the new .getAsStream() method for exporting pass data. ```typescript pass.getAsStream() pass.getAsBuffer() pass.getAsRaw() ``` -------------------------------- ### Bundle Multiple Passes using PKPass.pack() Source: https://context7.com/alexandercerutti/passkit-generator/llms.txt Use PKPass.pack() to create a .pkpasses bundle containing multiple passes, compatible with iOS 15+. All individual passes within the bundle are locked after packing. ```typescript import { PKPass } from "passkit-generator"; async function generateBoardingPass(passenger: string, seat: string, serialNum: string) { const pass = await PKPass.from( { model: "./models/boardingPass.pass", certificates }, { serialNumber: serialNum, description: `Boarding Pass - ${passenger}`, } ); pass.transitType = "PKTransitTypeAir"; pass.primaryFields.push( { key: "origin", value: "LAX", label: "Los Angeles" }, { key: "dest", value: "JFK", label: "New York" } ); pass.auxiliaryFields.push( { key: "passenger", label: "PASSENGER", value: passenger }, { key: "seat", label: "SEAT", value: seat } ); pass.setBarcodes(`PASS-${serialNum}`); return pass; } // Generate passes for a family traveling together const familyPasses = await Promise.all([ generateBoardingPass("John Smith", "14A", "FLIGHT-001-A"), generateBoardingPass("Jane Smith", "14B", "FLIGHT-001-B"), generateBoardingPass("Tom Smith", "14C", "FLIGHT-001-C"), generateBoardingPass("Sarah Smith", "14D", "FLIGHT-001-D"), ]); // Bundle all passes together const pkpassesBundle = PKPass.pack(...familyPasses); ``` ```typescript // Express.js endpoint for bundled passes app.get("/family-boarding-passes", async (req, res) => { const passes = await Promise.all([/* generate passes */]); const bundle = PKPass.pack(...passes); res.set({ "Content-Type": bundle.mimeType, // "application/vnd.apple.pkpasses" "Content-Disposition": "attachment; filename=family-passes.pkpasses", }); // Can use getAsBuffer() or getAsStream() const stream = bundle.getAsStream(); stream.pipe(res); }); // Note: PKPass.pack() calls getAsBuffer() on each pass internally // All passes become locked after packing ``` -------------------------------- ### Generate Pass from Folder Model Source: https://github.com/alexandercerutti/passkit-generator/blob/master/README.md Use this method to create a pass file from a folder structure. Ensure certificates are correctly loaded. ```typescript try { /** Each, but last, can be either a string or a Buffer. See API Documentation for more */ const { wwdr, signerCert, signerKey, signerKeyPassphrase } = getCertificatesContentsSomehow(); const pass = await PKPass.from({ /** * Note: .pass extension is enforced when reading a * model from FS, even if not specified here below */ model: "./passModels/myFirstModel.pass", certificates: { wwdr, signerCert, signerKey, signerKeyPassphrase }, }, { // keys to be added or overridden serialNumber: "AAGH44625236dddaffbda" }); // Adding some settings to be written inside pass.json pass.localize("en", { ... }); pass.setBarcodes("36478105430"); // Random value // Generate the stream .pkpass file stream const stream = pass.getAsStream(); doSomethingWithTheStream(stream); // or const buffer = pass.getAsBuffer(); doSomethingWithTheBuffer(buffer); } catch (err) { doSomethingWithTheError(err); } ```