passkit-generator
Version:
The easiest way to generate custom Apple Wallet passes in Node.js
351 lines • 18.8 kB
JavaScript
export * from "./Barcode.js";
export * from "./Beacon.js";
export * from "./Location.js";
export * from "./Field.js";
export * from "./NFC.js";
export * from "./Semantics.js";
export * from "./PassFields.js";
export * from "./Personalize.js";
export * from "./Certificates.js";
import Joi from "joi";
import { Barcode } from "./Barcode.js";
import { Location } from "./Location.js";
import { Beacon } from "./Beacon.js";
import { NFC } from "./NFC.js";
import { PassFields } from "./PassFields.js";
import { Semantics } from "./Semantics.js";
import * as Messages from "../messages.js";
import { RGB_HEX_COLOR_REGEX, URL_REGEX } from "./regexps.js";
export const PreferredStyleSchemes = Joi.array().items("posterEventTicket", "eventTicket");
export const RelevantDate = Joi.alternatives(Joi.object().keys({
startDate: Joi.alternatives(Joi.string().isoDate(), Joi.date().iso()).required(),
endDate: Joi.alternatives(Joi.string().isoDate(), Joi.date().iso()).required(),
}), Joi.object().keys({
relevantDate: Joi.alternatives(Joi.string().isoDate(), Joi.date().iso()).required(),
}));
export const PassPropsFromMethods = Joi.object({
nfc: NFC,
beacons: Joi.array().items(Beacon),
barcodes: Joi.array().items(Barcode),
relevantDate: Joi.string().isoDate(),
relevantDates: Joi.array().items(RelevantDate),
expirationDate: Joi.string().isoDate(),
locations: Joi.array().items(Location),
preferredStyleSchemes: PreferredStyleSchemes,
});
export const PassKindsProps = Joi.object({
coupon: PassFields.disallow("transitType"),
generic: PassFields.disallow("transitType"),
storeCard: PassFields.disallow("transitType"),
eventTicket: PassFields.disallow("transitType"),
boardingPass: PassFields,
});
export const PassType = Joi.string().regex(/(boardingPass|coupon|eventTicket|storeCard|generic)/);
export const OverridablePassProps = Joi.object({
formatVersion: Joi.number().default(1),
semantics: Semantics,
voided: Joi.boolean(),
logoText: Joi.string(),
description: Joi.string(),
serialNumber: Joi.string(),
appLaunchURL: Joi.string(),
teamIdentifier: Joi.string(),
organizationName: Joi.string(),
passTypeIdentifier: Joi.string(),
sharingProhibited: Joi.boolean(),
groupingIdentifier: Joi.string(),
suppressStripShine: Joi.boolean(),
maxDistance: Joi.number().positive(),
authenticationToken: Joi.string().min(16),
labelColor: Joi.string().regex(RGB_HEX_COLOR_REGEX),
stripColor: Joi.string().regex(RGB_HEX_COLOR_REGEX),
backgroundColor: Joi.string().regex(RGB_HEX_COLOR_REGEX),
foregroundColor: Joi.string().regex(RGB_HEX_COLOR_REGEX),
associatedStoreIdentifiers: Joi.array().items(Joi.number()),
userInfo: Joi.alternatives(Joi.object().unknown(), Joi.array()),
webServiceURL: Joi.string().regex(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.string().regex(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.
*/
orderFoodURL: Joi.string().regex(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.string().regex(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.string(),
/**
* @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.string(),
/**
* @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.string(),
/**
* @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.string(),
/**
* @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.string(),
/**
* @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.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.
*/
contactVenueEmail: Joi.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.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.string(),
/**
* @iOSVersion 18
* @passStyle eventTicket (new layout)
*
* @description
*
* Will add a button among options near "share"
*/
transferURL: Joi.string(),
/**
* @iOSVersion 18
* @passStyle eventTicket (new layout)
*
* @description
*
* Will add a button among options near "share"
*/
sellURL: Joi.string(),
/**
* @iOSVersion 18
* @passStyle eventTicket (new layout)
*
* @description
*
* Will remove an automatic shadow in the new
* event ticket layouts.
*/
suppressHeaderDarkening: Joi.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.string().regex(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.
*/
useAutomaticColor: Joi.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.array().items(Joi.number()),
}).with("webServiceURL", "authenticationToken");
export const PassProps = Joi.object()
.concat(OverridablePassProps)
.concat(PassKindsProps)
.concat(PassPropsFromMethods);
export const Template = Joi.object({
model: Joi.string().required(),
certificates: Joi.object().required(),
});
// --------- UTILITIES ---------- //
/**
* Performs validation of a schema on an object.
* If it fails, will throw an error.
*
* @param schema
* @param data
*/
export 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
*/
export function validate(schema, options) {
const validationResult = schema.validate(options, {
stripUnknown: true,
abortEarly: true,
});
if (validationResult.error) {
throw validationResult.error;
}
return validationResult.value;
}
export 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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvc2NoZW1hcy9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxjQUFjLGNBQWMsQ0FBQztBQUM3QixjQUFjLGFBQWEsQ0FBQztBQUM1QixjQUFjLGVBQWUsQ0FBQztBQUM5QixjQUFjLFlBQVksQ0FBQztBQUMzQixjQUFjLFVBQVUsQ0FBQztBQUN6QixjQUFjLGdCQUFnQixDQUFDO0FBQy9CLGNBQWMsaUJBQWlCLENBQUM7QUFDaEMsY0FBYyxrQkFBa0IsQ0FBQztBQUNqQyxjQUFjLG1CQUFtQixDQUFDO0FBRWxDLE9BQU8sR0FBRyxNQUFNLEtBQUssQ0FBQztBQUd0QixPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0sY0FBYyxDQUFDO0FBQ3ZDLE9BQU8sRUFBRSxRQUFRLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDekMsT0FBTyxFQUFFLE1BQU0sRUFBRSxNQUFNLGFBQWEsQ0FBQztBQUNyQyxPQUFPLEVBQUUsR0FBRyxFQUFFLE1BQU0sVUFBVSxDQUFDO0FBQy9CLE9BQU8sRUFBRSxVQUFVLEVBQWUsTUFBTSxpQkFBaUIsQ0FBQztBQUMxRCxPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFHM0MsT0FBTyxLQUFLLFFBQVEsTUFBTSxnQkFBZ0IsQ0FBQztBQUMzQyxPQUFPLEVBQUUsbUJBQW1CLEVBQUUsU0FBUyxFQUFFLE1BQU0sY0FBYyxDQUFDO0FBSTlELE1BQU0sQ0FBQyxNQUFNLHFCQUFxQixHQUFHLEdBQUcsQ0FBQyxLQUFLLEVBQUUsQ0FBQyxLQUFLLENBQ3JELG1CQUFtQixFQUNuQixhQUFhLENBQytCLENBQUM7QUEwQjlDLE1BQU0sQ0FBQyxNQUFNLFlBQVksR0FBRyxHQUFHLENBQUMsWUFBWSxDQUMzQyxHQUFHLENBQUMsTUFBTSxFQUFxQixDQUFDLElBQUksQ0FBQztJQUNwQyxTQUFTLEVBQUUsR0FBRyxDQUFDLFlBQVks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