UNPKG

passkit-generator

Version:

The easiest way to generate custom Apple Wallet passes in Node.js

494 lines 26.4 kB
"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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