passkit-generator
Version:
The easiest way to generate custom Apple Wallet passes in Node.js
494 lines • 26.4 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Template = exports.PassProps = exports.OverridablePassProps = exports.PassType = exports.PassKindsProps = exports.PassPropsFromMethods = exports.RelevantDate = exports.PreferredStyleSchemes = void 0;
exports.assertValidity = assertValidity;
exports.validate = validate;
exports.filterValid = filterValid;
const tslib_1 = require("tslib");
tslib_1.__exportStar(require("./Barcode.js"), exports);
tslib_1.__exportStar(require("./Beacon.js"), exports);
tslib_1.__exportStar(require("./Location.js"), exports);
tslib_1.__exportStar(require("./PassFieldContent.js"), exports);
tslib_1.__exportStar(require("./NFC.js"), exports);
tslib_1.__exportStar(require("./Semantics.js"), exports);
tslib_1.__exportStar(require("./PassFields.js"), exports);
tslib_1.__exportStar(require("./Personalize.js"), exports);
tslib_1.__exportStar(require("./Certificates.js"), exports);
tslib_1.__exportStar(require("./UpcomingPassInformation.js"), exports);
const joi_1 = tslib_1.__importDefault(require("joi"));
const Barcode_js_1 = require("./Barcode.js");
const Location_js_1 = require("./Location.js");
const Beacon_js_1 = require("./Beacon.js");
const NFC_js_1 = require("./NFC.js");
const PassFields_js_1 = require("./PassFields.js");
const Semantics_js_1 = require("./Semantics.js");
const UpcomingPassInformation_js_1 = require("./UpcomingPassInformation.js");
const Messages = tslib_1.__importStar(require("../messages.js"));
const regexps_js_1 = require("./regexps.js");
exports.PreferredStyleSchemes = joi_1.default.array().items("posterEventTicket", "eventTicket",
// or, since iOS 26
"boardingPass", "semanticBoardingPass");
exports.RelevantDate = joi_1.default.alternatives(joi_1.default.object().keys({
startDate: joi_1.default.alternatives(joi_1.default.string().isoDate(), joi_1.default.date().iso()).required(),
endDate: joi_1.default.alternatives(joi_1.default.string().isoDate(), joi_1.default.date().iso()).required(),
}), joi_1.default.object().keys({
/**
* Since iOS 26
*/
date: joi_1.default.alternatives(joi_1.default.string().isoDate(), joi_1.default.date().iso()),
/**
* Since iOS 18, then was renamed in
* 'date' in iOS 26 (what a breaking change)
*/
relevantDate: joi_1.default.alternatives(joi_1.default.string().isoDate(), joi_1.default.date().iso()).required(),
}));
exports.PassPropsFromMethods = joi_1.default.object({
nfc: NFC_js_1.NFC,
beacons: joi_1.default.array().items(Beacon_js_1.Beacon),
barcodes: joi_1.default.array().items(Barcode_js_1.Barcode),
relevantDate: joi_1.default.string().isoDate(),
relevantDates: joi_1.default.array().items(exports.RelevantDate),
expirationDate: joi_1.default.string().isoDate(),
locations: joi_1.default.array().items(Location_js_1.Location),
preferredStyleSchemes: exports.PreferredStyleSchemes,
upcomingPassInformation: joi_1.default.array().items(UpcomingPassInformation_js_1.UpcomingPassInformationEntry),
});
exports.PassKindsProps = joi_1.default.object({
coupon: PassFields_js_1.PassFields.disallow("transitType"),
generic: PassFields_js_1.PassFields.disallow("transitType"),
storeCard: PassFields_js_1.PassFields.disallow("transitType"),
eventTicket: PassFields_js_1.PassFields.disallow("transitType"),
boardingPass: PassFields_js_1.PassFields,
});
exports.PassType = joi_1.default.string().regex(/(boardingPass|coupon|eventTicket|storeCard|generic)/);
exports.OverridablePassProps = joi_1.default.object({
formatVersion: joi_1.default.number().default(1),
semantics: Semantics_js_1.Semantics,
voided: joi_1.default.boolean(),
logoText: joi_1.default.string(),
description: joi_1.default.string(),
serialNumber: joi_1.default.string(),
appLaunchURL: joi_1.default.string().uri(),
teamIdentifier: joi_1.default.string(),
organizationName: joi_1.default.string(),
passTypeIdentifier: joi_1.default.string(),
sharingProhibited: joi_1.default.boolean(),
groupingIdentifier: joi_1.default.string(),
suppressStripShine: joi_1.default.boolean(),
maxDistance: joi_1.default.number().positive(),
authenticationToken: joi_1.default.string().min(16),
labelColor: joi_1.default.string().regex(regexps_js_1.RGB_HEX_COLOR_REGEX),
stripColor: joi_1.default.string().regex(regexps_js_1.RGB_HEX_COLOR_REGEX),
backgroundColor: joi_1.default.string().regex(regexps_js_1.RGB_HEX_COLOR_REGEX),
foregroundColor: joi_1.default.string().regex(regexps_js_1.RGB_HEX_COLOR_REGEX),
associatedStoreIdentifiers: joi_1.default.array().items(joi_1.default.number()),
userInfo: joi_1.default.alternatives(joi_1.default.object().unknown(), joi_1.default.array()),
webServiceURL: joi_1.default.string().regex(regexps_js_1.URL_REGEX),
/**
* @iOSVersion 18
* @passStyle eventTicket (new layout)
* @passDomain Event Guide
*
* To show buttons in the event guide,
* at least two among those marked with
* "@passDomain Event Guide" must be used.
*/
bagPolicyURL: joi_1.default.string().regex(regexps_js_1.URL_REGEX),
/**
* @iOSVersion 18
* @passStyle posterEventTicket, semanticBoardingPasses
* @passDomain Event Guide, Semantic Boarding Passes
*
* To show buttons in the event guide,
* at least two among those marked with
* "@passDomain Event Guide" must be used.
*/
orderFoodURL: joi_1.default.string().regex(regexps_js_1.URL_REGEX),
/**
* @iOSVersion 18
* @passStyle eventTicket (new layout)
* @passDomain Event Guide
*
* To show buttons in the event guide,
* at least two among those marked with
* "@passDomain Event Guide" must be used.
*/
parkingInformationURL: joi_1.default.string().regex(regexps_js_1.URL_REGEX),
/**
* @iOSVersion 18
* @passStyle eventTicket (new layout)
* @passDomain Event Guide
*
* To show buttons in the event guide,
* at least two among those marked with
* "@passDomain Event Guide" must be used.
*/
directionsInformationURL: joi_1.default.string().regex(regexps_js_1.URL_REGEX),
/**
* @iOSVersion 18
* @passStyle eventTicket (new layout)
* @passDomain Event Guide
*
* @description
*
* URL to a resource to buy or access
* the parking spot.
*
* To show buttons in the event guide,
* at least two among those marked with
* "@passDomain Event Guide" must be used.
*/
purchaseParkingURL: joi_1.default.string().regex(regexps_js_1.URL_REGEX),
/**
* @iOSVersion 18
* @passStyle eventTicket (new layout)
* @passDomain Event Guide
*
* @description
*
* URL to a resource to buy the
* merchandise.
*
* To show buttons in the event guide,
* at least two among those marked with
* "@passDomain Event Guide" must be used.
*/
merchandiseURL: joi_1.default.string().regex(regexps_js_1.URL_REGEX),
/**
* @iOSVersion 18
* @passStyle eventTicket (new layout)
* @passDomain Event Guide
*
* @description
*
* URL to a resource about public or
* private transportation to reach the
* venue.
*
* To show buttons in the event guide,
* at least two among those marked with
* "@passDomain Event Guide" must be used.
*/
transitInformationURL: joi_1.default.string().regex(regexps_js_1.URL_REGEX),
/**
* @iOSVersion 18
* @passStyle eventTicket (new layout)
* @passDomain Event Guide
*
* @description
*
* URL to a resource about accessibility
* in the events venue.
*
* To show buttons in the event guide,
* at least two among those marked with
* "@passDomain Event Guide" must be used.
*/
accessibilityURL: joi_1.default.string().regex(regexps_js_1.URL_REGEX),
/**
* @iOSVersion 18
* @passStyle eventTicket (new layout)
* @passDomain Event Guide
*
* @description
*
* An URL to link experiences to the
* pass (upgrades and more).
*
* To show buttons in the event guide,
* at least two among those marked with
* "@passDomain Event Guide" must be used.
*/
addOnURL: joi_1.default.string().regex(regexps_js_1.URL_REGEX),
/**
* @iOSVersion 18
* @passStyle eventTicket (new layout)
* @passDomain Event Guide
*
* @description
*
* To show buttons in the event guide,
* at least two among those marked with
* "@passDomain Event Guide" must be used.
*/
contactVenueEmail: joi_1.default.string(),
/**
* @iOSVersion 18
* @passStyle eventTicket (new layout)
* @passDomain Event Guide
*
* @description
*
* To show buttons in the event guide,
* at least two among those marked with
* "@passDomain Event Guide" must be used.
*/
contactVenuePhoneNumber: joi_1.default.string(),
/**
* @iOSVersion 18
* @passStyle eventTicket (new layout)
* @passDomain Event Guide
*
* @description
*
* To show buttons in the event guide,
* at least two among those marked with
* "@passDomain Event Guide" must be used.
*/
contactVenueWebsite: joi_1.default.string().regex(regexps_js_1.URL_REGEX),
/**
* @iOSVersion 18
* @passStyle eventTicket (new layout)
*
* @description
*
* Will add a button among options near "share"
*/
transferURL: joi_1.default.string().regex(regexps_js_1.URL_REGEX),
/**
* @iOSVersion 18
* @passStyle eventTicket (new layout)
*
* @description
*
* Will add a button among options near "share"
*/
sellURL: joi_1.default.string().regex(regexps_js_1.URL_REGEX),
/**
* @iOSVersion 18
* @passStyle eventTicket (new layout)
*
* @description
*
* Will remove an automatic shadow in the new
* event ticket layouts.
*/
suppressHeaderDarkening: joi_1.default.boolean(),
/**
* @iOSVersion 18
* @passStyle eventTicket (new layout)
*
* @description
*
* By default, the chin is colored with a
* blur. Through this option, it is possible
* to specify a different and specific color
* for it.
*/
footerBackgroundColor: joi_1.default.string().regex(regexps_js_1.RGB_HEX_COLOR_REGEX),
/**
* @iOSVersion 18
* @passStyle eventTicket (new layout)
*
* @description
*
* Enables the automatic calculation of the
* `foregroundColor` and `labelColor` based
* on the background image in the new event
* ticket passes.
*
* If enabled, `foregroundColor` and `labelColor`
* are ignored.
*/
useAutomaticColors: joi_1.default.boolean(),
/**
* @iOSVersion 18
* @passStyle eventTicket (new layout)
*
* @description
*
* Applications AppStore Identifiers
* related to the event ticket.
*
* It is not mandatory for the app to
* be related to the pass issuer.
*
* Such applications won't be able to read
* the passes users has (probably differently
* by `associatedStoreIdentifiers`).
*/
auxiliaryStoreIdentifiers: joi_1.default.array().items(joi_1.default.number()),
/**
* @iOSVersion 18.1
*
* The text to display next to the logo on posterEventTicket passes.
*/
eventLogoText: joi_1.default.string(),
/**
* @iOSVersion 26
*
* @description
*
* A URL for changing the seat for the ticket.
* Available only with Enhanced (or semantic) Boarding Passes
*/
changeSeatURL: joi_1.default.string().regex(regexps_js_1.URL_REGEX),
/**
* @iOSVersion 26
*
* @description
*
* A URL for in-flight entertainment.
* Available only with Enhanced (or semantic) Boarding Passes
*/
entertainmentURL: joi_1.default.string().regex(regexps_js_1.URL_REGEX),
/**
* @iOSVersion 26
*
* @description
*
* A URL for adding checked bags for the ticket.
* Available only with Enhanced (or semantic) Boarding Passes
*/
purchaseAdditionalBaggageURL: joi_1.default.string().regex(regexps_js_1.URL_REGEX),
/**
* @iOSVersion 26
*
* @description
*
* A URL that links to information to purchase lounge access.
* Available only with Enhanced (or semantic) Boarding Passes
*/
purchaseLoungeAccessURL: joi_1.default.string().regex(regexps_js_1.URL_REGEX),
/**
* @iOSVersion 26
*
* @description
*
* A URL for purchasing in-flight wifi.
* Available only with Enhanced (or semantic) Boarding Passes
*/
purchaseWifiURL: joi_1.default.string().regex(regexps_js_1.URL_REGEX),
/**
* @iOSVersion 26
*
* @description
*
* A URL for upgrading the flight.
* Available only with Enhanced (or semantic) Boarding Passes
*/
upgradeURL: joi_1.default.string().regex(regexps_js_1.URL_REGEX),
/**
* @iOSVersion 26
*
* @description
*
* A URL for management.
* Available only with Enhanced (or semantic) Boarding Passes
*/
managementURL: joi_1.default.string().regex(regexps_js_1.URL_REGEX),
/**
* @iOSVersion 26
*
* @description
*
* A URL for registering a service animal.
* Available only with Enhanced (or semantic) Boarding Passes
*/
registerServiceAnimalURL: joi_1.default.string().regex(regexps_js_1.URL_REGEX),
/**
* @iOSVersion 26
*
* @description
*
* A URL to report a lost bag.
* Available only with Enhanced (or semantic) Boarding Passes
*/
reportLostBagURL: joi_1.default.string().regex(regexps_js_1.URL_REGEX),
/**
* @iOSVersion 26
*
* @description
*
* A URL to request a wheel chair.
* Available only with Enhanced (or semantic) Boarding Passes
*/
requestWheelchairURL: joi_1.default.string().regex(regexps_js_1.URL_REGEX),
/**
* @iOSVersion 26
*
* @description
*
* The email for the transit provider.
* Available only with Enhanced (or semantic) Boarding Passes
*/
transitProviderEmail: joi_1.default.string(),
/**
* @iOSVersion 26
*
* @description
*
* The phone number for the transit provider.
* Available only with Enhanced (or semantic) Boarding Passes
*/
transitProviderPhoneNumber: joi_1.default.string(),
/**
* @iOSVersion 26
*
* @description
*
* The URL for the transit provider.
* Available only with Enhanced (or semantic) Boarding Passes
*/
transitProviderWebsiteURL: joi_1.default.string().regex(regexps_js_1.URL_REGEX),
}).with("webServiceURL", "authenticationToken");
exports.PassProps = joi_1.default.object()
.concat(exports.OverridablePassProps)
.concat(exports.PassKindsProps)
.concat(exports.PassPropsFromMethods);
exports.Template = joi_1.default.object({
model: joi_1.default.string().required(),
certificates: joi_1.default.object().required(),
});
// --------- UTILITIES ---------- //
/**
* Performs validation of a schema on an object.
* If it fails, will throw an error.
*
* @param schema
* @param data
*/
function assertValidity(schema, data, customErrorMessage) {
const validation = schema.validate(data);
if (validation.error) {
if (customErrorMessage) {
console.warn(validation.error);
throw new TypeError(`${validation.error.name} happened. ${Messages.format(customErrorMessage, validation.error.message)}`);
}
throw new TypeError(validation.error.message);
}
}
/**
* Performs validation and throws the error if there's one.
* Otherwise returns a (possibly patched) version of the specified
* options (it depends on the schema)
*
* @param schema
* @param options
* @returns
*/
function validate(schema, options) {
const validationResult = schema.validate(options, {
stripUnknown: true,
abortEarly: true,
});
if (validationResult.error) {
throw validationResult.error;
}
return validationResult.value;
}
function filterValid(schema, source) {
if (!source) {
return [];
}
return source.reduce((acc, current) => {
try {
return [...acc, validate(schema, current)];
}
catch (err) {
console.warn(Messages.format(Messages.FILTER_VALID.INVALID, err));
return [...acc];
}
}, []);
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvc2NoZW1hcy9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUF5aUNBLHdDQW9CQztBQVlELDRCQWNDO0FBRUQsa0NBZ0JDOztBQXptQ0QsdURBQTZCO0FBQzdCLHNEQUE0QjtBQUM1Qix3REFBOEI7QUFDOUIsZ0VBQXNDO0FBQ3RDLG1EQUF5QjtBQUN6Qix5REFBK0I7QUFDL0IsMERBQWdDO0FBQ2hDLDJEQUFpQztBQUNqQyw0REFBa0M7QUFDbEMsdUVBQTZDO0FBRTdDLHNEQUFzQjtBQUd0Qiw2Q0FBdUM7QUFDdkMsK0NBQXlDO0FBQ3pDLDJDQUFxQztBQUNyQyxxQ0FBK0I7QUFDL0IsbURBQTBEO0FBQzFELGlEQUEyQztBQUUzQyw2RUFBNEU7QUFFNUUsaUVBQTJDO0FBQzNDLDZDQUE4RDtBQU9qRCxRQUFBLHFCQUFxQixHQUFHLGFBQUcsQ0FBQyxLQUFLLEVBQUUsQ0FBQyxLQUFLLENBQ3JELG1CQUFtQixFQUNuQixhQUFhO0FBQ2IsbUJBQW1CO0FBQ25CLGNBQWMsRUFDZCxzQkFBc0IsQ0FDc0IsQ0FBQztBQW9DakMsUUFBQSxZQUFZLEdBQUcsYUFBRyxDQUFDLFlBQVksQ0FDM0MsYUFBRyxDQUFDLE1BQU0sRUFBcUIsQ0FBQyxJQUFJLENBQUM7SUFDcEMsU0FBUyxFQUFFLGFBQUcsQ0FBQyxZQUFZLENBQzFCLGFBQUcsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxPQUFPLEVBQUUsRUFDdEIsYUFBRyxDQUFDLElBQUksRUFBRSxDQUFDLEdBQUcsRUFBRSxDQUNoQixDQUFDLFFBQVEsRUFBRTtJQUNaLE9BQU8sRUFBRSxhQUFHLENBQUMsWUFBWSxDQUN4QixhQUFHLENBQUMsTUFBTSxFQUFFLENBQUMsT0FBTyxFQUFFLEVBQ3RCLGFBQUcsQ0FBQyxJQUFJLEVBQUUsQ0FBQyxHQUFHLEVBQUUsQ0FDaEIsQ0FBQyxRQUFRLEVBQUU7Q0FDWixDQUFDLEVBQ0Ys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