๏ปฟ

Saved searches

Use saved searches to filter your results more quickly

Cancel Create saved search Sign up Reseting focus

You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session. You switched accounts on another tab or window. Reload to refresh your session.

API Documentation Reference

Alexander Cerutti edited this page Sep 9, 2023 ยท 7 revisions

The flow of execution is really easy (once everything is set up):

const  PKPass > = require("passkit-generator");

Creating a Pass

constructor()

const pass = new PKPass( . >,  . >,  . >);

Returns:

Description:

PKPass extends an internal class Bundle , which gives it some props. Only the exposed ones will be listed below.

Arguments:

Key Type Description Optional Default Value
buffers object The initial files buffers to compose a pass. They must be in form path: Buffer . Set to empty object if none is available yet. false -
certificates object The certificates object. false -
certificates.wwdr string | Buffer The content of Apple WWDR certificate. false -
certificates.signerCert string | Buffer The content of Developer certificate file. false -
certificates.signerKey string | Buffer The content of developer certificate's key. false -
certificates.signerKeyPassphrase string The passphrase to decrypt the developer signerKey true -
props object Some pass props that will get merged with the ones in pass.json true

Creating a pass from a different source.

A pass can be created through its constructor (creating from scratch) or from another pass or from a template. A "template" here is a model saved on disk. Both can be created by using the static method PKPass.from() .

PKPass.from(source: PKPass | PKPass.Template, props?: Schemas.OverridableProps): Promisetypeof PKPass>;

Throws if the pass source is not valid.

In both cases, additional props can be passed as the second parameter through an object.

Below you can see a few example functions that will be used in the following ways to use PKPass.from .

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 **/, >; >

. 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.

Example:

const passRuntimeTemplate = new PKPass( getBuffersSomehow(), getCertificatesSomehow(), getSomeProps(), ); // later. const passToBeServed = await PKPass.from( passRuntimeTemplate, getAdditionalPropsForThisPassSomehow(), );

. from a 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.

Arguments:

The following are the arguments to be passed in the object in the first position:

Key Type Description Optional Default Value
model string (path) The path to your model on File System false -
certificates object The object containing certificates data. Refer to PKPass's constructor for all the keys false -

Example:

const passFromDisk = await PKPass.from(  model: "../../path/to/your/disk/model", certificates: getCertificatesSomehow(), >, getAdditionalPropsForThisPassSomehow(), );

Adding files to your pass

.addBuffer()

pass.addBuffer(filePath: string, buffer: Buffer): void;

Description:

This method allows later additions of files to your pass. It has no filters about the type of file you may want to add but for:

In these cases, addBuffer will perform additional checks and might not add the file as-is or at all.

Throws if pass is frozen due to a previous export.

Arguments:

Key Type Description Optional Default Value
filePath string (path) The path, local to your pass.json, where the file should be added (if it is a localization file, it will be like en.lproj/pass.strings , otherwise just the name, like personalization.json ) false -
buffer Buffer The content of your file false -

Localizing Passes

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 code (e.g. en.lproj ).

There are three ways to include a language in this package:

If you are designing your pass for a language only, you can directly replace the placeholders in pass.json with translation.

.localize()

pass.localize(lang: string, translations:  [key: string]: string >): void;

Returns:

Description:

Use this method to add some translations. Existing translations will be merged with the newly added.

Calling .localize is the same as calling .addBuffer for a pass.strings file, except for the parsing phase. Pass null to translations param to delete everything of a language (translations and files).

Throws if pass is frozen due to a previous export, if the last is not a string or if no translations are provided.

Arguments:

Key Type Description Optional Default Value
lang String The ISO-3166-1 language code false -
translations Object | null Translations in format < : "TRANSLATED-VALUE"> . Pass null to delete everything of a language false -

Example:

pass.localize("it",  EVENT: "Evento", LOCATION: "Posizione", >); pass.localize("de",  EVENT: "Ereignis", LOCATION: "Ort", >);

Setting barcodes

.setBarcodes()

pass.setBarcodes(message: string): void; pass.setBarcodes(. barcodes: schema.Barcodes[ ]): void;

Returns:

Description:

Setting barcodes can happen in two ways: controlled and uncontrolled (autogenerated), which means how many barcode structures you will have in your pass.

Passing a string to the method will lead to an uncontrolled way: starting from the message (content), all the structures will be generated. Any further parameters will be ignored.

Passing N barcode structures (see below), will only validate them and push only the valid ones.

Setting barcodes will overwrite previously set barcodes (no matter the source). Pass null to delete all the barcodes.

Throws if pass is frozen due to a previous export.

Please note that, as the barcode property is deprecated, this is the only method available for setting barcodes.

Arguments:

Key Type Description Optional
message String | Barcode first value of barcodes false
. rest Barcode[] the other barcode values true

Examples:

pass.setBarcodes("11424771526"); // or pass.setBarcodes( message: "11424771526", format: "PKBarcodeFormatCode128", altText: "11424771526" >,  message: "11424771526", format: "PKBarcodeFormatQR", altText: "11424771526" >,  message: "11424771526", format: "PKBarcodeFormatPDF417", altText: "11424771526" >);

Setting expiration

.setExpirationDate()

pass.setExpirationDate(date: Date): void;

Returns:

Description:

It sets the date of expiration to the passed argument. Pass null as the parameter to remove the value from props. If date parsing fails, an error will be thrown.

Throws if pass is frozen due to a previous export.

Arguments:

Key Type Description Optional
date String/date The date on which the pass will expire false

Setting relevance

.setBeacons()

pass.setBeacons(. data: schema.Beacons[ ]): void;

Returns:

Description:

Sets the beacons information in the passes. Setting beacons will overwrite previously setted beacons. Pass null to delete all the beacons.

Throws if pass is frozen due to a previous export.

Arguments:

Key Type Description Optional Default Value
. beacons Beacons[] | null The beacons structures false -

Example:

pass.setBeacons(  major: 55, minor: 0, proximityUUID: "59da0f96-3fb5-43aa-9028-2bc796c3d0c5", >,  major: 65, minor: 46, proximityUUID: "fdcbbf48-a4ae-4ffb-9200-f8a373c5c18e", >, );

.setLocations()

pass.setLocations(. data: schema.Locations[ ]): void;

Returns:

Description:

Sets the location-relevance information in the passes. Setting locations will overwrite previously setted locations (no matter the source). Pass null to delete all the locations.

Throws if pass is frozen due to a previous export.

Arguments:

Key Type Description Optional Default Value
. locations schema.Locations[] | null The location structures false -

Example:

pass.setLocations(  latitude: 66.45725212, longitude: 33.01000442, >,  longitude: 4.42634523, latitude: 5.344233323352, >, );

.setRelevantDate()

pass.setRelevantDate(date: Date): void;

Returns:

Description:

It sets the date of relevance to the passed argument. Pass null as the parameter to remove the value from props. If date parsing fails, an error will be thrown.

Throws if pass is frozen due to a previous export.

Arguments:

Key Type Description Optional Default Value
date Date | null The relevant date false -

Setting NFC Support

.setNFC()

pass.setNFC(data: schema.NFC): void

Returns:

Description:

It sets NFC info for the current pass. Pass null as a parameter to remove its value from props.

Throws if pass is frozen due to a previous export or if parameter validation fails.

Arguments:

Key Type Description Optional
data NFC Dictionary | null NFC structure false

See: NFC

Personalization / Reward Enrollment passes

Personalization (or Reward Enrollment passes) is supported only if:

If these conditions are not met, personalization files will get removed from the output pass or not be accepted as an input file.

Notice: There is no way I could test this feature on any real pass 'cause Apple would never give me an encryptionKey for NFC. Also, I don't have an NFC reader. If you need it and this won't work, feel free to contact me and we will investigate together ๐Ÿ˜„

The opposite is valid as well: if you try to use it and it works, feel free to report it to me, so this warning can be removed

Setting Pass Fields (primaryFields, secondaryFields, headerFields, auxiliaryFields, backFields)

Unlike method-set properties or initialization props, to set fields inside the right property, some getters have been created, one per property. Each extends native Arrays, to let you perform all the operations you need on the fields. Fields already available in pass.json, will be automatically loaded in props.

Please note that they are strictly and directly linked to the pass type property (boardingPass, storeCard, etc. ). This means that if pass type is not available, accessing them will throw an error. Changing the type on runtime will clean all them up.

All the fields are linked together through a keys pool: each key must be unique among all the fields of the whole pass.

Each getter will throw if pass is frozen due to a previous export, when a new element is attempted to be added to the related array.

Examples:

pass.headerFields.push(  key: "header1", label: "Data", value: "25 mag", textAlignment: "PKTextAlignmentCenter", >,  key: "header2", label: "Volo", value: "EZY997", textAlignment: "PKTextAlignmentCenter", >, ); pass.primaryFields.pop(); pass.auxiliaryFields.push(/*. */); pass.secondaryFields.push(/*. */); pass.backFields.push(/*. */);

.transitType (getter + setter)

pass.transitType = "PKTransitTypeAir";

Description:

Since this property belongs to the "Field Keys" but is not an "array of field dictionaries" like its sibling keys, a setter, and a getter got included to select it.

Allowed values: PKTransitTypeAir, PKTransitTypeBoat, PKTransitTypeBus, PKTransitTypeGeneric, PKTransitTypeTrain", as described in Passkit Package Format Reference.

Please note that it is strictly and directly linked to the pass type property (only boardingPass).

This means that if pass type is not available or is not a boardingPass, accessing or setting it will throw an error. Changing the type on runtime will clean it up.

Pass exporting will throw an error if a boardingPass is exported without transitType .

Setter throws if pass is frozen due to a previous export, if an invalid pass type is invalid, or if current type is not a boardingPass .

Getting the signed Pass

Generating the pass is the last step of the process (before enjoying ๐ŸŽ‰). Generating might happen in three ways: getting a Buffer, a Stream, or Raw files.

All the three ways available, will lock the pass instance to not accept anymore files or props.

.getAsBuffer()

pass.getAsBuffer(): Buffer;

Description:

Creates a buffer of the zipped pass. This is useful when passkit-generator is used in contexts where using Streams is not possible, like cloud functions.

Examples:

const passBuffer = pass.getAsBuffer(); doSomethingWithPassBuffer(Buffer);

.getAsStream()

pass.getAsStream(): Stream;

Description:

Creates a stream for the zipped pass.

Examples:

const passStream = pass.getAsStream(); doSomethingWithPassStream(stream);

.getAsRaw()

pass.getAsRaw(): Readonly [path: string]: Buffer >>;

Description:

Returns a frozen object containing all the files along with their buffers (with compiled signature and manifest).

The purpose of this stands in how zips are created. In passkit-generator v2.x.x, a different and asynchronous library was being used to create zips. Due to a worse API, it was replaced by do-not-zip, which acts more like a buffers concatenator instead of a compressor. This compromise improved the creation of zips by making zips generation synchronous, through a very-lightweight package, but with possibly incremented final archives size.

For this reason, if the developer is already using a different zip library and is providing quite large files, better results in terms of pass weight might be obtained by manipulating the list of files provided by this method and feeding them to the already-available zip library.

Examples:

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));