UNPKG

@walletpass/pass-js

Version:

Apple Wallet Pass generating and pushing updates from Node.js

465 lines 16.3 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const constants_1 = require("../constants"); const pass_color_1 = require("./pass-color"); const images_1 = require("./images"); const localizations_1 = require("./localizations"); const get_geo_point_1 = require("./get-geo-point"); const pass_structure_1 = require("./pass-structure"); const w3cdate_1 = require("./w3cdate"); const STRUCTURE_FIELDS_SET = new Set([...constants_1.STRUCTURE_FIELDS, 'nfc']); class PassBase extends pass_structure_1.PassStructure { constructor(fields = {}, images, localizations, options) { super(fields); this.options = options; // restore via setters for (const [key, value] of Object.entries(fields)) { if (!STRUCTURE_FIELDS_SET.has(key) && key in this) { this[key] = value; } } // copy images this.images = new images_1.PassImages(images); // copy localizations this.localization = new localizations_1.Localizations(localizations); } // Returns the pass.json object (not a string). toJSON() { const res = { formatVersion: 1 }; for (const [field, value] of Object.entries(this.fields)) { res[field] = value instanceof Date ? w3cdate_1.getW3CDateString(value) : value; } return res; } get passTypeIdentifier() { return this.fields.passTypeIdentifier; } set passTypeIdentifier(v) { if (!v) delete this.fields.passTypeIdentifier; else this.fields.passTypeIdentifier = v; } get teamIdentifier() { return this.fields.teamIdentifier; } set teamIdentifier(v) { if (!v) delete this.fields.teamIdentifier; else this.fields.teamIdentifier = v; } get serialNumber() { return this.fields.serialNumber; } set serialNumber(v) { if (!v) delete this.fields.serialNumber; else this.fields.serialNumber = v; } /** * Indicates that the sharing of pass can be prohibited. * * @type {boolean} */ get sharingProhibited() { return this.fields.sharingProhibited; } set sharingProhibited(v) { if (!v) delete this.fields.sharingProhibited; else this.fields.sharingProhibited = true; } /** * Indicates that the pass is void—for example, a one time use coupon that has been redeemed. * * @type {boolean} */ get voided() { return !!this.fields.voided; } set voided(v) { if (v) this.fields.voided = true; else delete this.fields.voided; } /** * Date and time when the pass expires. * */ get expirationDate() { if (typeof this.fields.expirationDate === 'string') return new Date(this.fields.expirationDate); return this.fields.expirationDate; } set expirationDate(v) { if (!v) delete this.fields.expirationDate; else { if (v instanceof Date) { if (!Number.isFinite(v.getTime())) throw new TypeError(`Value for expirationDate must be a valid Date, received ${v}`); this.fields.expirationDate = v; } else if (typeof v === 'string') { if (w3cdate_1.isValidW3CDateString(v)) this.fields.expirationDate = v; else { const date = new Date(v); if (!Number.isFinite(date.getTime())) throw new TypeError(`Value for expirationDate must be a valid Date, received ${v}`); this.fields.expirationDate = date; } } } } /** * Date and time when the pass becomes relevant. For example, the start time of a movie. * Recommended for event tickets and boarding passes; otherwise optional. * * @type {string | Date} */ get relevantDate() { if (typeof this.fields.relevantDate === 'string') return new Date(this.fields.relevantDate); return this.fields.relevantDate; } set relevantDate(v) { if (!v) delete this.fields.relevantDate; else { if (v instanceof Date) { if (!Number.isFinite(v.getTime())) throw new TypeError(`Value for relevantDate must be a valid Date, received ${v}`); this.fields.relevantDate = v; } else if (typeof v === 'string') { if (w3cdate_1.isValidW3CDateString(v)) this.fields.relevantDate = v; else { const date = new Date(v); if (!Number.isFinite(date.getTime())) throw new TypeError(`Value for relevantDate must be a valid Date, received ${v}`); this.fields.relevantDate = date; } } } } /** * A list of iTunes Store item identifiers for the associated apps. * Only one item in the list is used—the first item identifier for an app * compatible with the current device. * If the app is not installed, the link opens the App Store and shows the app. * If the app is already installed, the link launches the app. */ get associatedStoreIdentifiers() { return this.fields.associatedStoreIdentifiers; } set associatedStoreIdentifiers(v) { if (!v) { delete this.fields.associatedStoreIdentifiers; return; } const arrayOfNumbers = v.filter(n => Number.isInteger(n)); if (arrayOfNumbers.length > 0) this.fields.associatedStoreIdentifiers = arrayOfNumbers; else delete this.fields.associatedStoreIdentifiers; } /** * Brief description of the pass, used by the iOS accessibility technologies. * Don’t try to include all of the data on the pass in its description, * just include enough detail to distinguish passes of the same type. */ get description() { return this.fields.description; } set description(v) { if (!v) delete this.fields.description; else this.fields.description = v; } /** * Display name of the organization that originated and signed the pass. */ get organizationName() { return this.fields.organizationName; } set organizationName(v) { if (!v) delete this.fields.organizationName; else this.fields.organizationName = v; } /** * Optional for event tickets and boarding passes; otherwise not allowed. * Identifier used to group related passes. * If a grouping identifier is specified, passes with the same style, * pass type identifier, and grouping identifier are displayed as a group. * Otherwise, passes are grouped automatically. * Use this to group passes that are tightly related, * such as the boarding passes for different connections of the same trip. */ get groupingIdentifier() { return this.fields.groupingIdentifier; } set groupingIdentifier(v) { if (!v) delete this.fields.groupingIdentifier; else this.fields.groupingIdentifier = v; } /** * If true, the strip image is displayed without a shine effect. * The default value prior to iOS 7.0 is false. * In iOS 7.0, a shine effect is never applied, and this key is deprecated. */ get suppressStripShine() { return !!this.fields.suppressStripShine; } set suppressStripShine(v) { if (!v) delete this.fields.suppressStripShine; else this.fields.suppressStripShine = true; } /** * Text displayed next to the logo on the pass. */ get logoText() { return this.fields.logoText; } set logoText(v) { if (!v) delete this.fields.logoText; else this.fields.logoText = v; } /** * The URL of a web service that conforms to the API described in PassKit Web Service Reference. * The web service must use the HTTPS protocol in production; the leading https:// is included in the value of this key. * On devices configured for development, there is UI in Settings to allow HTTP web services. You can use the options * parameter to set allowHTTP to be able to use URLs that use the HTTP protocol. * * @see {@link https://developer.apple.com/library/archive/documentation/PassKit/Reference/PassKit_WebService/WebService.html#//apple_ref/doc/uid/TP40011988} */ get webServiceURL() { return this.fields.webServiceURL; } set webServiceURL(v) { var _a, _b; if (!v) { delete this.fields.webServiceURL; return; } // validating URL, it will throw on bad value const url = v instanceof URL ? v : new URL(v); const allowHttp = (_b = (_a = this.options) === null || _a === void 0 ? void 0 : _a.allowHttp) !== null && _b !== void 0 ? _b : false; if (!allowHttp && url.protocol !== 'https:') { throw new TypeError(`webServiceURL must be on HTTPS!`); } this.fields.webServiceURL = v; } /** * The authentication token to use with the web service. * The token must be 16 characters or longer. */ get authenticationToken() { return this.fields.authenticationToken; } set authenticationToken(v) { if (!v) { delete this.fields.authenticationToken; return; } if (typeof v !== 'string') throw new TypeError(`authenticationToken must be a string, received ${typeof v}`); if (v.length < 16) throw new TypeError(`authenticationToken must must be 16 characters or longer`); this.fields.authenticationToken = v; } /** * Background color of the pass, specified as an CSS-style RGB triple. * * @example rgb(23, 187, 82) */ get backgroundColor() { if (!(this.fields.backgroundColor instanceof pass_color_1.PassColor)) return undefined; return this.fields.backgroundColor; } set backgroundColor(v) { if (!v) { delete this.fields.backgroundColor; return; } if (!(this.fields.backgroundColor instanceof pass_color_1.PassColor)) this.fields.backgroundColor = new pass_color_1.PassColor(v); else this.fields.backgroundColor.set(v); } /** * Foreground color of the pass, specified as a CSS-style RGB triple. * * @example rgb(100, 10, 110) */ get foregroundColor() { if (!(this.fields.foregroundColor instanceof pass_color_1.PassColor)) return undefined; return this.fields.foregroundColor; } set foregroundColor(v) { if (!v) { delete this.fields.foregroundColor; return; } if (!(this.fields.foregroundColor instanceof pass_color_1.PassColor)) this.fields.foregroundColor = new pass_color_1.PassColor(v); else this.fields.foregroundColor.set(v); } /** * Color of the label text, specified as a CSS-style RGB triple. * * @example rgb(255, 255, 255) */ get labelColor() { if (!(this.fields.labelColor instanceof pass_color_1.PassColor)) return undefined; return this.fields.labelColor; } set labelColor(v) { if (!v) { delete this.fields.labelColor; return; } if (!(this.fields.labelColor instanceof pass_color_1.PassColor)) this.fields.labelColor = new pass_color_1.PassColor(v); else this.fields.labelColor.set(v); } /** * Color of the strip text, specified as a CSS-style RGB triple. * * @example rgb(255, 255, 255) */ get stripColor() { if (!(this.fields.stripColor instanceof pass_color_1.PassColor)) return undefined; return this.fields.stripColor; } set stripColor(v) { if (!v) { delete this.fields.stripColor; return; } if (!(this.fields.stripColor instanceof pass_color_1.PassColor)) this.fields.stripColor = new pass_color_1.PassColor(v); else this.fields.stripColor.set(v); } /** * Maximum distance in meters from a relevant latitude and longitude that the pass is relevant. * This number is compared to the pass’s default distance and the smaller value is used. */ get maxDistance() { return this.fields.maxDistance; } set maxDistance(v) { if (!v) { delete this.fields.maxDistance; return; } if (!Number.isInteger(v)) throw new TypeError('maxDistance must be a positive integer distance in meters!'); this.fields.maxDistance = v; } /** * Beacons marking locations where the pass is relevant. */ get beacons() { return this.fields.beacons; } set beacons(v) { if (!v || !Array.isArray(v)) { delete this.fields.beacons; return; } for (const beacon of v) { if (!beacon.proximityUUID) throw new TypeError(`each beacon must contain proximityUUID`); } // copy array this.fields.beacons = [...v]; } /** * Information specific to the pass’s barcode. * The system uses the first valid barcode dictionary in the array. * Additional dictionaries can be added as fallbacks. */ get barcodes() { return this.fields.barcodes; } set barcodes(v) { if (!v) { delete this.fields.barcodes; delete this.fields.barcode; return; } if (!Array.isArray(v)) throw new TypeError(`barcodes must be an Array, received ${typeof v}`); // Barcodes dictionary: https://developer.apple.com/library/content/documentation/UserExperience/Reference/PassKit_Bundle/Chapters/LowerLevel.html#//apple_ref/doc/uid/TP40012026-CH3-SW3 for (const barcode of v) { if (!constants_1.BARCODES_FORMAT.has(barcode.format)) throw new TypeError(`Barcode format value ${barcode.format} is invalid!`); if (typeof barcode.message !== 'string') throw new TypeError('Barcode message string is required'); if (typeof barcode.messageEncoding !== 'string') throw new TypeError('Barcode messageEncoding is required'); } // copy array this.fields.barcodes = [...v]; } /** * Adds a location where a pass is relevant. * * @param {number[] | { lat: number, lng: number, alt?: number } | { longitude: number, latitude: number, altitude?: number }} point * @param {string} [relevantText] * @returns {this} */ addLocation(point, relevantText) { const { longitude, latitude, altitude } = get_geo_point_1.getGeoPoint(point); const location = { longitude, latitude, }; if (altitude) location.altitude = altitude; if (typeof relevantText === 'string') location.relevantText = relevantText; if (!Array.isArray(this.fields.locations)) this.fields.locations = [location]; else this.fields.locations.push(location); return this; } get locations() { return this.fields.locations; } set locations(v) { delete this.fields.locations; if (!v) return; if (!Array.isArray(v)) throw new TypeError(`locations must be an array`); else for (const location of v) this.addLocation(location, location.relevantText); } } exports.PassBase = PassBase; //# sourceMappingURL=base-pass.js.map