mirror of
https://github.com/marcogll/passkit-generator.git
synced 2026-03-15 11:25:17 +00:00
Merge branch 'feature/iOS18-changes'
This commit is contained in:
@@ -30,6 +30,7 @@
|
||||
"node": ">=14.18.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@jest/globals": "^29.7.0",
|
||||
"@types/do-not-zip": "^1.0.2",
|
||||
"@types/node": "^16.11.26",
|
||||
"@types/node-forge": "^1.3.11",
|
||||
|
||||
2762
pnpm-lock.yaml
generated
2762
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@@ -87,6 +87,11 @@ const modelFiles = {};
|
||||
|
||||
const EXAMPLE_PATH_RELATIVE = "../examples/models/examplePass.pass";
|
||||
|
||||
/**
|
||||
* @param {string} folder
|
||||
* @returns
|
||||
*/
|
||||
|
||||
function unpackFolder(folder) {
|
||||
const entryList = fs.readdirSync(path.resolve(__dirname, folder));
|
||||
|
||||
@@ -859,35 +864,107 @@ describe("PKPass", () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe("relevant date", () => {
|
||||
it("should set pass relevant date", () => {
|
||||
pkpass.setRelevantDate(new Date("2023-04-11T00:15+10:00"));
|
||||
describe("Date relevancy", () => {
|
||||
describe("(deprecated iOS 18) (root).relevantDate", () => {
|
||||
it("should set pass relevant date", () => {
|
||||
pkpass.setRelevantDate(new Date("2023-04-11T00:15+10:00"));
|
||||
|
||||
const passjsonGenerated = getGeneratedPassJson(pkpass);
|
||||
const passjsonGenerated = getGeneratedPassJson(pkpass);
|
||||
|
||||
expect(passjsonGenerated.relevantDate).toBe(
|
||||
"2023-04-10T14:15:00.000Z",
|
||||
);
|
||||
expect(passjsonGenerated.relevantDate).toBe(
|
||||
"2023-04-10T14:15:00.000Z",
|
||||
);
|
||||
});
|
||||
|
||||
it("should reset relevant date", () => {
|
||||
pkpass.setRelevantDate(new Date(2023, 3, 10, 14, 15));
|
||||
pkpass.setRelevantDate(null);
|
||||
|
||||
const passjsonGenerated = getGeneratedPassJson(pkpass);
|
||||
|
||||
expect(passjsonGenerated.relevantDate).toBeUndefined();
|
||||
});
|
||||
|
||||
it("should throw if an invalid date is received", () => {
|
||||
expect(() =>
|
||||
// @ts-expect-error
|
||||
pkpass.setRelevantDate("32/18/228317"),
|
||||
).toThrowError();
|
||||
// @ts-expect-error
|
||||
expect(() => pkpass.setRelevantDate(undefined)).toThrowError();
|
||||
// @ts-expect-error
|
||||
expect(() => pkpass.setRelevantDate(5)).toThrowError();
|
||||
// @ts-expect-error
|
||||
expect(() => pkpass.setRelevantDate({})).toThrowError();
|
||||
});
|
||||
});
|
||||
|
||||
it("should reset relevant date", () => {
|
||||
pkpass.setRelevantDate(new Date(2023, 3, 10, 14, 15));
|
||||
pkpass.setRelevantDate(null);
|
||||
describe("setRelevantDates", () => {
|
||||
it("should accept strings", () => {
|
||||
pkpass.setRelevantDates([
|
||||
{
|
||||
startDate: "2025-01-08T22:17:30.000Z",
|
||||
endDate: "2025-01-08T23:58:25.000Z",
|
||||
},
|
||||
{
|
||||
relevantDate: "2025-01-08T22:17:30.000Z",
|
||||
},
|
||||
]);
|
||||
|
||||
const passjsonGenerated = getGeneratedPassJson(pkpass);
|
||||
const passjsonGenerated = getGeneratedPassJson(pkpass);
|
||||
|
||||
expect(passjsonGenerated.relevantDate).toBeUndefined();
|
||||
});
|
||||
expect(passjsonGenerated.relevantDates).toMatchObject([
|
||||
{
|
||||
startDate: "2025-01-08T22:17:30.000Z",
|
||||
endDate: "2025-01-08T23:58:25.000Z",
|
||||
},
|
||||
{
|
||||
relevantDate: "2025-01-08T22:17:30.000Z",
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it("should throw if an invalid date is received", () => {
|
||||
// @ts-expect-error
|
||||
expect(() => pkpass.setRelevantDate("32/18/228317")).toThrowError();
|
||||
// @ts-expect-error
|
||||
expect(() => pkpass.setRelevantDate(undefined)).toThrowError();
|
||||
// @ts-expect-error
|
||||
expect(() => pkpass.setRelevantDate(5)).toThrowError();
|
||||
// @ts-expect-error
|
||||
expect(() => pkpass.setRelevantDate({})).toThrowError();
|
||||
it("should accept dates", () => {
|
||||
pkpass.setRelevantDates([
|
||||
{
|
||||
startDate: new Date(2025, 1, 8, 23, 58, 25),
|
||||
endDate: new Date(2025, 1, 8, 23, 58, 25),
|
||||
},
|
||||
{
|
||||
relevantDate: new Date(2025, 1, 8, 23, 58, 25),
|
||||
},
|
||||
]);
|
||||
|
||||
const passjsonGenerated = getGeneratedPassJson(pkpass);
|
||||
|
||||
expect(passjsonGenerated.relevantDates).toMatchObject([
|
||||
{
|
||||
startDate: "2025-02-08T22:58:25.000Z",
|
||||
endDate: "2025-02-08T22:58:25.000Z",
|
||||
},
|
||||
{
|
||||
relevantDate: "2025-02-08T22:58:25.000Z",
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it("should allow resetting", () => {
|
||||
pkpass.setRelevantDates([
|
||||
{
|
||||
startDate: "2025-01-08T22:17:30.000Z",
|
||||
endDate: "2025-01-08T23:58:25.000Z",
|
||||
},
|
||||
{
|
||||
relevantDate: "2025-01-08T22:17:30.000Z",
|
||||
},
|
||||
]);
|
||||
|
||||
pkpass.setRelevantDates(null);
|
||||
|
||||
const passjsonGenerated = getGeneratedPassJson(pkpass);
|
||||
|
||||
expect(passjsonGenerated.relevantDates).toBeUndefined();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -956,6 +956,54 @@ export default class PKPass extends Bundle {
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows setting a series of relevancy intervals or
|
||||
* relevancy entries for the pass.
|
||||
*
|
||||
* @param {Schemas.RelevantDate[] | null} relevancyEntries
|
||||
* @returns {void}
|
||||
*/
|
||||
|
||||
public setRelevantDates(
|
||||
relevancyEntries: Schemas.RelevantDate[] | null,
|
||||
): void {
|
||||
Utils.assertUnfrozen(this);
|
||||
|
||||
if (relevancyEntries === null) {
|
||||
this[propsSymbol]["relevantDates"] = undefined;
|
||||
return;
|
||||
}
|
||||
|
||||
const processedDateEntries = relevancyEntries.reduce<
|
||||
Schemas.RelevantDate[]
|
||||
>((acc, entry) => {
|
||||
try {
|
||||
Schemas.validate(Schemas.RelevantDate, entry);
|
||||
|
||||
if (isRelevantEntry(entry)) {
|
||||
acc.push({
|
||||
relevantDate: Utils.processDate(
|
||||
new Date(entry.relevantDate),
|
||||
),
|
||||
});
|
||||
|
||||
return acc;
|
||||
}
|
||||
|
||||
acc.push({
|
||||
startDate: Utils.processDate(new Date(entry.startDate)),
|
||||
endDate: Utils.processDate(new Date(entry.endDate)),
|
||||
});
|
||||
} catch (err) {
|
||||
console.warn(new TypeError(Messages.RELEVANT_DATE.INVALID));
|
||||
}
|
||||
|
||||
return acc;
|
||||
}, []);
|
||||
|
||||
this[propsSymbol]["relevantDates"] = processedDateEntries;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows setting a relevant date in which the OS
|
||||
* should show this pass.
|
||||
@@ -964,6 +1012,13 @@ export default class PKPass extends Bundle {
|
||||
*
|
||||
* @param {Date | null} date
|
||||
* @throws if pass is frozen due to previous export
|
||||
*
|
||||
* @warning `relevantDate` property has been deprecated in iOS 18
|
||||
* in order to get replaced by `relevantDates` array of intervals
|
||||
* (`relevantDates[].startDate` + `relevantDates[].endDate`)
|
||||
* or single date (`relevantDates[].relevantDate`). This method will
|
||||
* set both the original, as the new one will get ignored in older
|
||||
* iOS versions.
|
||||
*/
|
||||
|
||||
public setRelevantDate(date: Date | null): void {
|
||||
@@ -1086,3 +1141,9 @@ function validateJSONBuffer(
|
||||
|
||||
return Schemas.validate(schema, contentAsJSON);
|
||||
}
|
||||
|
||||
function isRelevantEntry(
|
||||
entry: Schemas.RelevantDate,
|
||||
): entry is Schemas.RelevancyEntry {
|
||||
return Object.prototype.hasOwnProperty.call(entry, "relevantDate");
|
||||
}
|
||||
|
||||
@@ -43,6 +43,10 @@ export const FIELDS = {
|
||||
"Cannot add field with key '%s': another field already owns this key. Ignored.",
|
||||
} as const;
|
||||
|
||||
export const RELEVANT_DATE = {
|
||||
INVALID: "Cannot set relevant date. Date format is invalid",
|
||||
} as const;
|
||||
|
||||
export const DATE = {
|
||||
INVALID: "Cannot set %s. Invalid date %s",
|
||||
} as const;
|
||||
|
||||
@@ -19,6 +19,14 @@ export interface PassFields {
|
||||
primaryFields: Field[];
|
||||
secondaryFields: Field[];
|
||||
transitType?: TransitType;
|
||||
|
||||
/**
|
||||
* @iOSVersion 18
|
||||
* @passStyle eventTicket (new layout)
|
||||
* @passDomain dashboard
|
||||
*
|
||||
* @see \<undiclosed>
|
||||
*/
|
||||
additionalInfoFields?: Field[];
|
||||
}
|
||||
|
||||
@@ -29,5 +37,13 @@ export const PassFields = Joi.object<PassFields>().keys({
|
||||
primaryFields: Joi.array().items(Field),
|
||||
secondaryFields: Joi.array().items(Field),
|
||||
transitType: TransitType,
|
||||
|
||||
/**
|
||||
* @iOSVersion 18
|
||||
* @passStyle eventTicket (new layout)
|
||||
* @passDomain dashboard
|
||||
*
|
||||
* @see \<undiclosed>
|
||||
*/
|
||||
additionalInfoFields: Joi.array().items(Field),
|
||||
});
|
||||
|
||||
147
src/schemas/SemanticTagType.ts
Normal file
147
src/schemas/SemanticTagType.ts
Normal file
@@ -0,0 +1,147 @@
|
||||
import Joi from "joi";
|
||||
import { RGB_HEX_COLOR_REGEX } from "./regexps";
|
||||
|
||||
/**
|
||||
* These couple of structures are organized alphabetically,
|
||||
* according to the order on the developer documentation.
|
||||
*
|
||||
* @see https://developer.apple.com/documentation/walletpasses/semantictagtype
|
||||
*/
|
||||
|
||||
/**
|
||||
* @see https://developer.apple.com/documentation/walletpasses/semantictagtype/currencyamount-data.dictionary
|
||||
*/
|
||||
export interface CurrencyAmount {
|
||||
currencyCode?: string; // ISO 4217 currency code
|
||||
amount?: string;
|
||||
}
|
||||
|
||||
export const CurrencyAmount = Joi.object<CurrencyAmount>().keys({
|
||||
currencyCode: Joi.string(),
|
||||
amount: Joi.string(),
|
||||
});
|
||||
|
||||
/**
|
||||
* @iOSVersion 18
|
||||
* @passStyle eventTicket (new layout)
|
||||
*
|
||||
* @see \<undiclosed>
|
||||
*/
|
||||
|
||||
export interface EventDateInfo {
|
||||
date: string;
|
||||
ignoreTimeComponents?: boolean;
|
||||
timeZone?: string;
|
||||
}
|
||||
|
||||
export const EventDateInfo = Joi.object<EventDateInfo>().keys({
|
||||
date: Joi.string().isoDate().required(),
|
||||
ignoreTimeComponents: Joi.boolean(),
|
||||
timeZone: Joi.string(),
|
||||
});
|
||||
|
||||
/**
|
||||
* @see https://developer.apple.com/documentation/walletpasses/semantictagtype/location-data.dictionary
|
||||
*/
|
||||
export interface Location {
|
||||
latitude: number;
|
||||
longitude: number;
|
||||
}
|
||||
|
||||
export const Location = Joi.object<Location>().keys({
|
||||
latitude: Joi.number().required(),
|
||||
longitude: Joi.number().required(),
|
||||
});
|
||||
|
||||
/**
|
||||
* @see https://developer.apple.com/documentation/walletpasses/semantictagtype/personnamecomponents-data.dictionary
|
||||
*/
|
||||
export interface PersonNameComponents {
|
||||
familyName?: string;
|
||||
givenName?: string;
|
||||
middleName?: string;
|
||||
namePrefix?: string;
|
||||
nameSuffix?: string;
|
||||
nickname?: string;
|
||||
phoneticRepresentation?: string;
|
||||
}
|
||||
|
||||
export const PersonNameComponents = Joi.object<PersonNameComponents>().keys({
|
||||
givenName: Joi.string(),
|
||||
familyName: Joi.string(),
|
||||
middleName: Joi.string(),
|
||||
namePrefix: Joi.string(),
|
||||
nameSuffix: Joi.string(),
|
||||
nickname: Joi.string(),
|
||||
phoneticRepresentation: Joi.string(),
|
||||
});
|
||||
|
||||
/**
|
||||
* @see https://developer.apple.com/documentation/walletpasses/semantictagtype/seat-data.dictionary
|
||||
*/
|
||||
export interface Seat {
|
||||
seatSection?: string;
|
||||
seatRow?: string;
|
||||
seatNumber?: string;
|
||||
seatIdentifier?: string;
|
||||
seatType?: string;
|
||||
seatDescription?: string;
|
||||
|
||||
/**
|
||||
* @iOSVersion 18
|
||||
* @passStyle eventTicket (new layout)
|
||||
*/
|
||||
seatAisle?: string;
|
||||
|
||||
/**
|
||||
* @iOSVersion 18
|
||||
* @passStyle eventTicket (new layout)
|
||||
*/
|
||||
seatLevel?: string;
|
||||
|
||||
/**
|
||||
* @iOSVersion 18
|
||||
* @passStyle eventTicket (new layout)
|
||||
*/
|
||||
seatSectionColor?: string;
|
||||
}
|
||||
|
||||
export const Seat = Joi.object<Seat>().keys({
|
||||
seatSection: Joi.string(),
|
||||
seatRow: Joi.string(),
|
||||
seatNumber: Joi.string(),
|
||||
seatIdentifier: Joi.string(),
|
||||
seatType: Joi.string(),
|
||||
seatDescription: Joi.string(),
|
||||
|
||||
/**
|
||||
* @iOSVersion 18
|
||||
* @passStyle eventTicket (new layout)
|
||||
*/
|
||||
seatAisle: Joi.string(),
|
||||
|
||||
/**
|
||||
* @iOSVersion 18
|
||||
* @passStyle eventTicket (new layout)
|
||||
*/
|
||||
seatLevel: Joi.string(),
|
||||
|
||||
/**
|
||||
* @iOSVersion 18
|
||||
* @passStyle eventTicket (new layout)
|
||||
*/
|
||||
seatSectionColor: Joi.string().regex(RGB_HEX_COLOR_REGEX),
|
||||
});
|
||||
|
||||
/**
|
||||
* @see https://developer.apple.com/documentation/walletpasses/semantictagtype/wifinetwork-data.dictionary
|
||||
*/
|
||||
export interface WifiNetwork {
|
||||
password: string;
|
||||
ssid: string;
|
||||
}
|
||||
|
||||
export const WifiNetwork = Joi.object<WifiNetwork>().keys({
|
||||
password: Joi.string().required(),
|
||||
ssid: Joi.string().required(),
|
||||
});
|
||||
@@ -1,5 +1,5 @@
|
||||
import Joi from "joi";
|
||||
import { RGB_HEX_COLOR_REGEX } from "./regexps";
|
||||
import * as SemanticTagType from "./SemanticTagType";
|
||||
|
||||
/**
|
||||
* For a better description of every single field,
|
||||
@@ -8,117 +8,6 @@ import { RGB_HEX_COLOR_REGEX } from "./regexps";
|
||||
* @see https://developer.apple.com/documentation/walletpasses/semantictags
|
||||
*/
|
||||
|
||||
/**
|
||||
* @see https://developer.apple.com/documentation/walletpasses/semantictagtype
|
||||
*/
|
||||
|
||||
declare namespace SemanticTagType {
|
||||
interface PersonNameComponents {
|
||||
familyName?: string;
|
||||
givenName?: string;
|
||||
middleName?: string;
|
||||
namePrefix?: string;
|
||||
nameSuffix?: string;
|
||||
nickname?: string;
|
||||
phoneticRepresentation?: string;
|
||||
}
|
||||
|
||||
interface CurrencyAmount {
|
||||
currencyCode?: string; // ISO 4217 currency code
|
||||
amount?: string;
|
||||
}
|
||||
|
||||
interface Location {
|
||||
latitude: number;
|
||||
longitude: number;
|
||||
}
|
||||
|
||||
interface Seat {
|
||||
seatSection?: string;
|
||||
seatRow?: string;
|
||||
seatNumber?: string;
|
||||
seatIdentifier?: string;
|
||||
seatType?: string;
|
||||
seatDescription?: string;
|
||||
|
||||
/**
|
||||
* For newly-introduced event tickets
|
||||
* in iOS 18
|
||||
*/
|
||||
seatAisle?: string;
|
||||
|
||||
/**
|
||||
* For newly-introduced event tickets
|
||||
* in iOS 18
|
||||
*/
|
||||
seatLevel?: string;
|
||||
|
||||
/**
|
||||
* For newly-introduced event tickets
|
||||
* in iOS 18
|
||||
*/
|
||||
seatSectionColor?: string;
|
||||
}
|
||||
|
||||
interface WifiNetwork {
|
||||
password: string;
|
||||
ssid: string;
|
||||
}
|
||||
}
|
||||
|
||||
const CurrencyAmount = Joi.object<SemanticTagType.CurrencyAmount>().keys({
|
||||
currencyCode: Joi.string(),
|
||||
amount: Joi.string(),
|
||||
});
|
||||
|
||||
const PersonNameComponent =
|
||||
Joi.object<SemanticTagType.PersonNameComponents>().keys({
|
||||
givenName: Joi.string(),
|
||||
familyName: Joi.string(),
|
||||
middleName: Joi.string(),
|
||||
namePrefix: Joi.string(),
|
||||
nameSuffix: Joi.string(),
|
||||
nickname: Joi.string(),
|
||||
phoneticRepresentation: Joi.string(),
|
||||
});
|
||||
|
||||
const SeatSemantics = Joi.object<SemanticTagType.Seat>().keys({
|
||||
seatSection: Joi.string(),
|
||||
seatRow: Joi.string(),
|
||||
seatNumber: Joi.string(),
|
||||
seatIdentifier: Joi.string(),
|
||||
seatType: Joi.string(),
|
||||
seatDescription: Joi.string(),
|
||||
|
||||
/**
|
||||
* Newly-introduced in iOS 18
|
||||
* Used in poster event tickets
|
||||
*/
|
||||
seatAisle: Joi.string(),
|
||||
|
||||
/**
|
||||
* Newly-introduced in iOS 18
|
||||
* Used in poster event tickets
|
||||
*/
|
||||
seatLevel: Joi.string(),
|
||||
|
||||
/**
|
||||
* For newly-introduced event tickets
|
||||
* in iOS 18
|
||||
*/
|
||||
seatSectionColor: Joi.string().regex(RGB_HEX_COLOR_REGEX),
|
||||
});
|
||||
|
||||
const LocationSemantics = Joi.object<SemanticTagType.Location>().keys({
|
||||
latitude: Joi.number().required(),
|
||||
longitude: Joi.number().required(),
|
||||
});
|
||||
|
||||
const WifiNetwork = Joi.object<SemanticTagType.WifiNetwork>().keys({
|
||||
password: Joi.string().required(),
|
||||
ssid: Joi.string().required(),
|
||||
});
|
||||
|
||||
/**
|
||||
* Alphabetical order
|
||||
* @see https://developer.apple.com/documentation/walletpasses/semantictags
|
||||
@@ -126,14 +15,14 @@ const WifiNetwork = Joi.object<SemanticTagType.WifiNetwork>().keys({
|
||||
|
||||
export interface Semantics {
|
||||
/**
|
||||
* For newly-introduced event tickets
|
||||
* in iOS 18
|
||||
* @iOSVersion 18
|
||||
* @passStyle eventTicket (new layout)
|
||||
*/
|
||||
admissionLevel?: string;
|
||||
|
||||
/**
|
||||
* For newly-introduced event tickets
|
||||
* in iOS 18
|
||||
* @iOSVersion 18
|
||||
* @passStyle eventTicket (new layout)
|
||||
*/
|
||||
admissionLevelAbbreviation?: string;
|
||||
|
||||
@@ -141,22 +30,22 @@ export interface Semantics {
|
||||
artistIDs?: string[];
|
||||
|
||||
/**
|
||||
* For newly-introduced event tickets
|
||||
* in iOS 18
|
||||
* @iOSVersion 18
|
||||
* @passStyle eventTicket (new layout)
|
||||
*/
|
||||
albumIDs?: string[];
|
||||
|
||||
/**
|
||||
* For newly-introduced event tickets
|
||||
* in iOS 18
|
||||
* @iOSVersion 18
|
||||
* @passStyle eventTicket (new layout)
|
||||
*/
|
||||
airplay?: {
|
||||
airPlayDeviceGroupToken: string;
|
||||
}[];
|
||||
|
||||
/**
|
||||
* For newly-introduced event tickets
|
||||
* in iOS 18
|
||||
* @iOSVersion 18
|
||||
* @passStyle eventTicket (new layout)
|
||||
*/
|
||||
attendeeName?: string;
|
||||
|
||||
@@ -165,8 +54,8 @@ export interface Semantics {
|
||||
awayTeamName?: string;
|
||||
|
||||
/**
|
||||
* For newly-introduced event tickets
|
||||
* in iOS 18
|
||||
* @iOSVersion 18
|
||||
* @passStyle eventTicket (new layout)
|
||||
*/
|
||||
additionalTicketAttributes?: string;
|
||||
|
||||
@@ -199,33 +88,64 @@ export interface Semantics {
|
||||
duration?: number;
|
||||
|
||||
/**
|
||||
* For newly-introduced event tickets
|
||||
* in iOS 18
|
||||
* @iOSVersion 18
|
||||
* @passStyle eventTicket (new layout)
|
||||
*/
|
||||
entranceDescription?: string;
|
||||
|
||||
eventEndDate?: string;
|
||||
|
||||
/**
|
||||
* For newly-introduced event tickets
|
||||
* in iOS 18
|
||||
* @iOSVersion 18
|
||||
* @passStyle eventTicket (new layout)
|
||||
*
|
||||
* This seem to exists but it is not
|
||||
* known yet what it does...
|
||||
* Shows a message in the live activity
|
||||
* when the activity starts.
|
||||
*/
|
||||
eventLiveMessage?: string;
|
||||
|
||||
eventName?: string;
|
||||
eventStartDate?: string;
|
||||
|
||||
/**
|
||||
* @iOSVersion 18
|
||||
* @passStyle eventTicket (new layout).
|
||||
*
|
||||
* Can be used as an alternative way to
|
||||
* show show start date, with more control
|
||||
* on time and timeZone details and as
|
||||
* a way to show the event guide, both
|
||||
* instead of `eventStartDate`.
|
||||
*/
|
||||
eventStartDateInfo?: SemanticTagType.EventDateInfo;
|
||||
|
||||
/**
|
||||
* @iOSVersion < 18
|
||||
* Since iOS 18, for the event tickets these determine
|
||||
* the template to be used when rendering the pass.
|
||||
*
|
||||
* - Generic Template
|
||||
* - "PKEventTypeGeneric"
|
||||
* - "PKEventTypeMovie"
|
||||
* - "PKEventTypeConference"
|
||||
* - "PKEventTypeConvention"
|
||||
* - "PKEventTypeWorkshop"
|
||||
* - "PKEventTypeSocialGathering"
|
||||
* - Sport Template
|
||||
* - "PKEventTypeSports"
|
||||
* - Live Performance Template
|
||||
* - "PKEventTypeLivePerformance";
|
||||
*/
|
||||
|
||||
eventType?:
|
||||
| "PKEventTypeGeneric"
|
||||
| "PKEventTypeLivePerformance"
|
||||
| "PKEventTypeMovie"
|
||||
| "PKEventTypeSports"
|
||||
| "PKEventTypeConference"
|
||||
| "PKEventTypeConvention"
|
||||
| "PKEventTypeWorkshop"
|
||||
| "PKEventTypeSocialGathering";
|
||||
| "PKEventTypeSocialGathering"
|
||||
| "PKEventTypeSports"
|
||||
| "PKEventTypeLivePerformance";
|
||||
|
||||
flightCode?: string;
|
||||
flightNumber?: number;
|
||||
@@ -250,8 +170,8 @@ export interface Semantics {
|
||||
priorityStatus?: string;
|
||||
|
||||
/**
|
||||
* For newly-introduced event tickets
|
||||
* in iOS 18
|
||||
* @iOSVersion 18
|
||||
* @passStyle eventTicket (new layout)
|
||||
*/
|
||||
playlistIDs?: string[];
|
||||
|
||||
@@ -261,8 +181,8 @@ export interface Semantics {
|
||||
sportName?: string;
|
||||
|
||||
/**
|
||||
* For newly-introduced event tickets
|
||||
* in iOS 18
|
||||
* @iOSVersion 18
|
||||
* @passStyle eventTicket (new layout)
|
||||
*/
|
||||
tailgatingAllowed?: boolean;
|
||||
|
||||
@@ -279,40 +199,46 @@ export interface Semantics {
|
||||
venueLocation?: SemanticTagType.Location;
|
||||
|
||||
/**
|
||||
* For newly-introduced event tickets
|
||||
* in iOS 18
|
||||
* @iOSVersion 18
|
||||
* @passStyle eventTicket (new layout)
|
||||
*/
|
||||
venueGatesOpenDate?: string;
|
||||
|
||||
venueName?: string;
|
||||
|
||||
/**
|
||||
* For newly-introduced event tickets
|
||||
* in iOS 18
|
||||
* @iOSVersion 18
|
||||
* @passStyle eventTicket (new layout)
|
||||
*/
|
||||
venueParkingLotsOpenDate?: string;
|
||||
|
||||
/**
|
||||
* For newly-introduced event tickets
|
||||
* in iOS 18
|
||||
* @iOSVersion 18
|
||||
* @passStyle eventTicket (new layout)
|
||||
*/
|
||||
venueBoxOfficeOpenDate?: string;
|
||||
|
||||
/**
|
||||
* For newly-introduced event tickets
|
||||
* in iOS 18
|
||||
* @iOSVersion 18
|
||||
* @passStyle eventTicket (new layout)
|
||||
*/
|
||||
venueDoorsOpenDate?: string;
|
||||
|
||||
/**
|
||||
* For newly-introduced event tickets
|
||||
* in iOS 18
|
||||
* @iOSVersion 18
|
||||
* @passStyle eventTicket (new layout)
|
||||
*/
|
||||
venueFanZoneOpenDate?: string;
|
||||
|
||||
/**
|
||||
* For newly-introduced event tickets
|
||||
* in iOS 18
|
||||
* @iOSVersion 18
|
||||
* @passStyle eventTicket (new layout)
|
||||
*/
|
||||
venueOpenDate?: string;
|
||||
|
||||
/**
|
||||
* @iOSVersion 18
|
||||
* @passStyle eventTicket (new layout)
|
||||
*/
|
||||
venueCloseDate?: string;
|
||||
|
||||
@@ -320,26 +246,26 @@ export interface Semantics {
|
||||
venueRoom?: string;
|
||||
|
||||
/**
|
||||
* For newly-introduced event tickets
|
||||
* in iOS 18
|
||||
* @iOSVersion 18
|
||||
* @passStyle eventTicket (new layout)
|
||||
*/
|
||||
venueRegionName?: string;
|
||||
|
||||
/**
|
||||
* For newly-introduced event tickets
|
||||
* in iOS 18
|
||||
* @iOSVersion 18
|
||||
* @passStyle eventTicket (new layout)
|
||||
*/
|
||||
venueEntranceGate?: string;
|
||||
|
||||
/**
|
||||
* For newly-introduced event tickets
|
||||
* in iOS 18
|
||||
* @iOSVersion 18
|
||||
* @passStyle eventTicket (new layout)
|
||||
*/
|
||||
venueEntranceDoor?: string;
|
||||
|
||||
/**
|
||||
* For newly-introduced event tickets
|
||||
* in iOS 18
|
||||
* @iOSVersion 18
|
||||
* @passStyle eventTicket (new layout)
|
||||
*/
|
||||
venueEntrancePortal?: string;
|
||||
|
||||
@@ -348,14 +274,14 @@ export interface Semantics {
|
||||
|
||||
export const Semantics = Joi.object<Semantics>().keys({
|
||||
/**
|
||||
* For newly-introduced event tickets
|
||||
* in iOS 18
|
||||
* @iOSVersion 18
|
||||
* @passStyle eventTicket (new layout)
|
||||
*/
|
||||
admissionLevel: Joi.string(),
|
||||
|
||||
/**
|
||||
* For newly-introduced event tickets
|
||||
* in iOS 18
|
||||
* @iOSVersion 18
|
||||
* @passStyle eventTicket (new layout)
|
||||
*/
|
||||
admissionLevelAbbreviation: Joi.string(),
|
||||
|
||||
@@ -363,22 +289,22 @@ export const Semantics = Joi.object<Semantics>().keys({
|
||||
artistIDs: Joi.array().items(Joi.string()),
|
||||
|
||||
/**
|
||||
* For newly-introduced event tickets
|
||||
* in iOS 18
|
||||
* @iOSVersion 18
|
||||
* @passStyle eventTicket (new layout)
|
||||
*/
|
||||
albumIDs: Joi.array().items(Joi.string()),
|
||||
|
||||
/**
|
||||
* For newly-introduced event tickets
|
||||
* in iOS 18
|
||||
* @iOSVersion 18
|
||||
* @passStyle eventTicket (new layout)
|
||||
*/
|
||||
airplay: Joi.array().items({
|
||||
airplayDeviceGroupToken: Joi.string(),
|
||||
}),
|
||||
|
||||
/**
|
||||
* For newly-introduced event tickets
|
||||
* in iOS 18
|
||||
* @iOSVersion 18
|
||||
* @passStyle eventTicket (new layout)
|
||||
*/
|
||||
attendeeName: Joi.string(),
|
||||
|
||||
@@ -388,7 +314,7 @@ export const Semantics = Joi.object<Semantics>().keys({
|
||||
|
||||
additionalTicketAttributes: Joi.string(),
|
||||
|
||||
balance: CurrencyAmount,
|
||||
balance: SemanticTagType.CurrencyAmount,
|
||||
boardingGroup: Joi.string(),
|
||||
boardingSequenceNumber: Joi.string(),
|
||||
|
||||
@@ -401,7 +327,7 @@ export const Semantics = Joi.object<Semantics>().keys({
|
||||
departureAirportCode: Joi.string(),
|
||||
departureAirportName: Joi.string(),
|
||||
departureGate: Joi.string(),
|
||||
departureLocation: LocationSemantics,
|
||||
departureLocation: SemanticTagType.Location,
|
||||
departureLocationDescription: Joi.string(),
|
||||
departurePlatform: Joi.string(),
|
||||
departureStationName: Joi.string(),
|
||||
@@ -409,7 +335,7 @@ export const Semantics = Joi.object<Semantics>().keys({
|
||||
destinationAirportCode: Joi.string(),
|
||||
destinationAirportName: Joi.string(),
|
||||
destinationGate: Joi.string(),
|
||||
destinationLocation: LocationSemantics,
|
||||
destinationLocation: SemanticTagType.Location,
|
||||
destinationLocationDescription: Joi.string(),
|
||||
destinationPlatform: Joi.string(),
|
||||
destinationStationName: Joi.string(),
|
||||
@@ -417,8 +343,8 @@ export const Semantics = Joi.object<Semantics>().keys({
|
||||
duration: Joi.number(),
|
||||
|
||||
/**
|
||||
* For newly-introduced event tickets
|
||||
* in iOS 18
|
||||
* @iOSVersion 18
|
||||
* @passStyle eventTicket (new layout)
|
||||
*/
|
||||
entranceDescription: Joi.string(),
|
||||
|
||||
@@ -426,14 +352,26 @@ export const Semantics = Joi.object<Semantics>().keys({
|
||||
eventName: Joi.string(),
|
||||
|
||||
/**
|
||||
* For newly-introduced event tickets
|
||||
* in iOS 18
|
||||
* @iOSVersion 18
|
||||
* @passStyle eventTicket (new layout)
|
||||
*
|
||||
* This seem to exists but it is not
|
||||
* known yet what it does...
|
||||
* Shows a message in the live activity
|
||||
* when the activity starts.
|
||||
*/
|
||||
eventLiveMessage: Joi.string(),
|
||||
|
||||
/**
|
||||
* @iOSVersion 18
|
||||
* @passStyle eventTicket (new layout).
|
||||
*
|
||||
* Can be used as an alternative way to
|
||||
* show show start date, with more control
|
||||
* on time and timeZone details and as
|
||||
* a way to show the event guide, both
|
||||
* instead of `eventStartDate`.
|
||||
*/
|
||||
eventStartDateInfo: SemanticTagType.EventDateInfo,
|
||||
|
||||
eventStartDate: Joi.string(),
|
||||
eventType: Joi.string().regex(
|
||||
/(PKEventTypeGeneric|PKEventTypeLivePerformance|PKEventTypeMovie|PKEventTypeSports|PKEventTypeConference|PKEventTypeConvention|PKEventTypeWorkshop|PKEventTypeSocialGathering)/,
|
||||
@@ -457,20 +395,20 @@ export const Semantics = Joi.object<Semantics>().keys({
|
||||
originalBoardingDate: Joi.string(),
|
||||
originalDepartureDate: Joi.string(),
|
||||
|
||||
passengerName: PersonNameComponent,
|
||||
passengerName: SemanticTagType.PersonNameComponents,
|
||||
performerNames: Joi.array().items(Joi.string()),
|
||||
priorityStatus: Joi.string(),
|
||||
|
||||
playlistIDs: Joi.array().items(Joi.string()),
|
||||
|
||||
seats: Joi.array().items(SeatSemantics),
|
||||
seats: Joi.array().items(SemanticTagType.Seat),
|
||||
securityScreening: Joi.string(),
|
||||
silenceRequested: Joi.boolean(),
|
||||
sportName: Joi.string(),
|
||||
|
||||
tailgatingAllowed: Joi.boolean(),
|
||||
|
||||
totalPrice: CurrencyAmount,
|
||||
totalPrice: SemanticTagType.CurrencyAmount,
|
||||
transitProvider: Joi.string(),
|
||||
transitStatus: Joi.string(),
|
||||
transitStatusReason: Joi.string(),
|
||||
@@ -482,41 +420,47 @@ export const Semantics = Joi.object<Semantics>().keys({
|
||||
venueEntrance: Joi.string(),
|
||||
|
||||
/**
|
||||
* For newly-introduced event tickets
|
||||
* in iOS 18
|
||||
* @iOSVersion 18
|
||||
* @passStyle eventTicket (new layout)
|
||||
*/
|
||||
venueGatesOpenDate: Joi.string(),
|
||||
|
||||
venueLocation: LocationSemantics,
|
||||
venueLocation: SemanticTagType.Location,
|
||||
venueName: Joi.string(),
|
||||
|
||||
/**
|
||||
* For newly-introduced event tickets
|
||||
* in iOS 18
|
||||
* @iOSVersion 18
|
||||
* @passStyle eventTicket (new layout)
|
||||
*/
|
||||
venueParkingLotsOpenDate: Joi.string(),
|
||||
|
||||
/**
|
||||
* For newly-introduced event tickets
|
||||
* in iOS 18
|
||||
* @iOSVersion 18
|
||||
* @passStyle eventTicket (new layout)
|
||||
*/
|
||||
venueBoxOfficeOpenDate: Joi.string(),
|
||||
|
||||
/**
|
||||
* For newly-introduced event tickets
|
||||
* in iOS 18
|
||||
* @iOSVersion 18
|
||||
* @passStyle eventTicket (new layout)
|
||||
*/
|
||||
venueDoorsOpenDate: Joi.string(),
|
||||
|
||||
/**
|
||||
* For newly-introduced event tickets
|
||||
* in iOS 18
|
||||
* @iOSVersion 18
|
||||
* @passStyle eventTicket (new layout)
|
||||
*/
|
||||
venueFanZoneOpenDate: Joi.string(),
|
||||
|
||||
/**
|
||||
* For newly-introduced event tickets
|
||||
* in iOS 18
|
||||
* @iOSVersion 18
|
||||
* @passStyle eventTicket (new layout)
|
||||
*/
|
||||
venueOpenDate: Joi.string(),
|
||||
|
||||
/**
|
||||
* @iOSVersion 18
|
||||
* @passStyle eventTicket (new layout)
|
||||
*/
|
||||
venueCloseDate: Joi.string(),
|
||||
|
||||
@@ -524,28 +468,28 @@ export const Semantics = Joi.object<Semantics>().keys({
|
||||
venueRoom: Joi.string(),
|
||||
|
||||
/**
|
||||
* For newly-introduced event tickets
|
||||
* in iOS 18
|
||||
* @iOSVersion 18
|
||||
* @passStyle eventTicket (new layout)
|
||||
*/
|
||||
venueRegionName: Joi.string(),
|
||||
|
||||
/**
|
||||
* For newly-introduced event tickets
|
||||
* in iOS 18
|
||||
* @iOSVersion 18
|
||||
* @passStyle eventTicket (new layout)
|
||||
*/
|
||||
venueEntranceGate: Joi.string(),
|
||||
|
||||
/**
|
||||
* For newly-introduced event tickets
|
||||
* in iOS 18
|
||||
* @iOSVersion 18
|
||||
* @passStyle eventTicket (new layout)
|
||||
*/
|
||||
venueEntranceDoor: Joi.string(),
|
||||
|
||||
/**
|
||||
* For newly-introduced event tickets
|
||||
* in iOS 18
|
||||
* @iOSVersion 18
|
||||
* @passStyle eventTicket (new layout)
|
||||
*/
|
||||
venueEntrancePortal: Joi.string(),
|
||||
|
||||
wifiAccess: Joi.array().items(WifiNetwork),
|
||||
wifiAccess: Joi.array().items(SemanticTagType.WifiNetwork),
|
||||
});
|
||||
|
||||
@@ -30,23 +30,47 @@ export const PreferredStyleSchemes = Joi.array().items(
|
||||
) satisfies Joi.Schema<PreferredStyleSchemes>;
|
||||
|
||||
/**
|
||||
* For newly-introduced event tickets
|
||||
* in iOS 18
|
||||
* A single interval can span at most 24 hours
|
||||
*/
|
||||
export interface RelevancyInterval {
|
||||
startDate: string | Date;
|
||||
endDate: string | Date;
|
||||
}
|
||||
|
||||
interface RelevantDate {
|
||||
startDate: string;
|
||||
endDate: string;
|
||||
export interface RelevancyEntry {
|
||||
relevantDate: string | Date;
|
||||
}
|
||||
|
||||
/**
|
||||
* Minimum supported version: iOS 18
|
||||
* @iOSVersion 18
|
||||
*
|
||||
* Using a RelevancyInterval, will trigger a live activity on
|
||||
* new event ticket passes.
|
||||
*
|
||||
* Using a RelevancyEntry, will match the behavior of the
|
||||
* currently deprecated property `relevantDate`.
|
||||
*/
|
||||
|
||||
const RelevantDate = Joi.object<RelevantDate>().keys({
|
||||
startDate: Joi.string().required(),
|
||||
endDate: Joi.string().required(),
|
||||
});
|
||||
export type RelevantDate = RelevancyInterval | RelevancyEntry;
|
||||
|
||||
export const RelevantDate = Joi.alternatives(
|
||||
Joi.object<RelevancyInterval>().keys({
|
||||
startDate: Joi.alternatives(
|
||||
Joi.string().isoDate(),
|
||||
Joi.date().iso(),
|
||||
).required(),
|
||||
endDate: Joi.alternatives(
|
||||
Joi.string().isoDate(),
|
||||
Joi.date().iso(),
|
||||
).required(),
|
||||
}),
|
||||
Joi.object<RelevancyEntry>().keys({
|
||||
relevantDate: Joi.alternatives(
|
||||
Joi.string().isoDate(),
|
||||
Joi.date().iso(),
|
||||
).required(),
|
||||
}),
|
||||
);
|
||||
|
||||
export interface FileBuffers {
|
||||
[key: string]: Buffer;
|
||||
@@ -80,6 +104,11 @@ export interface PassProps {
|
||||
nfc?: NFC;
|
||||
beacons?: Beacon[];
|
||||
barcodes?: Barcode[];
|
||||
|
||||
/**
|
||||
* @deprecated starting from iOS 18
|
||||
* Use `relevantDates`
|
||||
*/
|
||||
relevantDate?: string;
|
||||
|
||||
relevantDates?: RelevantDate[];
|
||||
@@ -94,142 +123,248 @@ export interface PassProps {
|
||||
storeCard?: PassFields;
|
||||
|
||||
/**
|
||||
* New field for iOS 18
|
||||
* Event Ticket
|
||||
* @iOSVersion 18
|
||||
* @passStyle eventTicket (new layout)
|
||||
*/
|
||||
preferredStyleSchemes?: PreferredStyleSchemes;
|
||||
|
||||
/**
|
||||
* New field for iOS 18 Event Ticket.
|
||||
* @domain event guide
|
||||
* @iOSVersion 18
|
||||
* @passStyle eventTicket (new layout)
|
||||
* @passDomain Event Guide
|
||||
*
|
||||
* To show buttons in the event guide,
|
||||
* at least two among those marked with
|
||||
* "@domain event guide" must be used.
|
||||
* "@passDomain event guide" must be used.
|
||||
*/
|
||||
bagPolicyURL?: string;
|
||||
|
||||
/**
|
||||
* New field for iOS 18 Event Ticket.
|
||||
* @domain event guide
|
||||
* @iOSVersion 18
|
||||
* @passStyle eventTicket (new layout)
|
||||
* @passDomain Event Guide
|
||||
*
|
||||
* To show buttons in the event guide,
|
||||
* at least two among those marked with
|
||||
* "@domain event guide" must be used.
|
||||
* "@passDomain Event Guide" must be used.
|
||||
*/
|
||||
orderFoodURL?: string;
|
||||
|
||||
/**
|
||||
* New field for iOS 18 Event Ticket.
|
||||
* @domain event guide
|
||||
* @iOSVersion 18
|
||||
* @passStyle eventTicket (new layout)
|
||||
* @passDomain Event Guide
|
||||
*
|
||||
* To show buttons in the event guide,
|
||||
* at least two among those marked with
|
||||
* "@domain event guide" must be used.
|
||||
* "@passDomain Event Guide" must be used.
|
||||
*/
|
||||
parkingInformationURL?: string;
|
||||
|
||||
/**
|
||||
* New field for iOS 18 Event Ticket.
|
||||
* @domain event guide
|
||||
* @iOSVersion 18
|
||||
* @passStyle eventTicket (new layout)
|
||||
* @passDomain Event Guide
|
||||
*
|
||||
* To show buttons in the event guide,
|
||||
* at least two among those marked with
|
||||
* "@domain event guide" must be used.
|
||||
* "@passDomain Event Guide" must be used.
|
||||
*/
|
||||
directionsInformationURL?: string;
|
||||
|
||||
/**
|
||||
* New field for iOS 18 Event Ticket.
|
||||
* @domain event guide
|
||||
* @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
|
||||
* "@domain event guide" must be used.
|
||||
*/
|
||||
contactVenueEmail?: string;
|
||||
|
||||
/**
|
||||
* New field for iOS 18 Event Ticket.
|
||||
* @domain event guide
|
||||
*
|
||||
* To show buttons in the event guide,
|
||||
* at least two among those marked with
|
||||
* "@domain event guide" must be used.
|
||||
*/
|
||||
contactVenuePhoneNumber?: string;
|
||||
|
||||
/**
|
||||
* New field for iOS 18 Event Ticket.
|
||||
* @domain event guide
|
||||
*
|
||||
* To show buttons in the event guide,
|
||||
* at least two among those marked with
|
||||
* "@domain event guide" must be used.
|
||||
*/
|
||||
contactVenueWebsite?: string;
|
||||
|
||||
/**
|
||||
* New field for iOS 18 Event Ticket.
|
||||
* @domain event guide
|
||||
*
|
||||
* To show buttons in the event guide,
|
||||
* at least two among those marked with
|
||||
* "@domain event guide" must be used.
|
||||
* "@passDomain Event Guide" must be used.
|
||||
*/
|
||||
purchaseParkingURL?: string;
|
||||
|
||||
/**
|
||||
* New field for iOS 18 Event Ticket.
|
||||
* @domain event guide
|
||||
* @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
|
||||
* "@domain event guide" must be used.
|
||||
* "@passDomain Event Guide" must be used.
|
||||
*/
|
||||
merchandiseURL?: string;
|
||||
|
||||
/**
|
||||
* New field for iOS 18 Event Ticket.
|
||||
* @domain event guide
|
||||
* @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
|
||||
* "@domain event guide" must be used.
|
||||
* "@passDomain Event Guide" must be used.
|
||||
*/
|
||||
transitInformationURL?: string;
|
||||
|
||||
/**
|
||||
* New field for iOS 18 Event Ticket.
|
||||
* @domain event guide
|
||||
* @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
|
||||
* "@domain event guide" must be used.
|
||||
* "@passDomain Event Guide" must be used.
|
||||
*/
|
||||
accessibilityURL?: string;
|
||||
|
||||
/**
|
||||
* New field for iOS 18 Event Ticket.
|
||||
* @domain event guide
|
||||
* @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
|
||||
* "@domain event guide" must be used.
|
||||
* "@passDomain Event Guide" must be used.
|
||||
*/
|
||||
addOnURL?: string;
|
||||
|
||||
/**
|
||||
* New field for iOS 18 Event Ticket.
|
||||
* @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.
|
||||
*/
|
||||
contactVenueEmail?: string;
|
||||
|
||||
/**
|
||||
* @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.
|
||||
*/
|
||||
contactVenuePhoneNumber?: string;
|
||||
|
||||
/**
|
||||
* @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.
|
||||
*/
|
||||
contactVenueWebsite?: string;
|
||||
|
||||
/**
|
||||
* @iOSVersion 18
|
||||
* @passStyle eventTicket (new layout)
|
||||
* @passDomain Menu dropdown
|
||||
*
|
||||
* @description
|
||||
*
|
||||
* Will add a button among options near "share"
|
||||
*/
|
||||
transferURL?: string;
|
||||
|
||||
/**
|
||||
* New field for iOS 18 Event Ticket.
|
||||
* @iOSVersion 18
|
||||
* @passStyle eventTicket (new layout)
|
||||
* @passDomain Menu dropdown
|
||||
*
|
||||
* @description
|
||||
*
|
||||
* Will add a button among options near "share"
|
||||
*/
|
||||
sellURL?: string;
|
||||
|
||||
/**
|
||||
* @iOSVersion 18
|
||||
* @passStyle eventTicket (new layout)
|
||||
*
|
||||
* @description
|
||||
*
|
||||
* Will remove an automatic shadow in the new
|
||||
* event ticket layouts.
|
||||
*/
|
||||
suppressHeaderDarkening?: 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?: string;
|
||||
|
||||
/**
|
||||
* @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?: 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?: number[];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -313,136 +448,246 @@ export const OverridablePassProps = Joi.object<OverridablePassProps>({
|
||||
webServiceURL: Joi.string().regex(URL_REGEX),
|
||||
|
||||
/**
|
||||
* New field for iOS 18 Event Ticket.
|
||||
* @domain event guide
|
||||
* @iOSVersion 18
|
||||
* @passStyle eventTicket (new layout)
|
||||
* @passDomain Event Guide
|
||||
*
|
||||
* To show buttons in the event guide,
|
||||
* at least two among those marked with
|
||||
* "@domain event guide" must be used.
|
||||
* "@passDomain Event Guide" must be used.
|
||||
*/
|
||||
bagPolicyURL: Joi.string().regex(URL_REGEX),
|
||||
|
||||
/**
|
||||
* New field for iOS 18 Event Ticket.
|
||||
* @domain event guide
|
||||
* @iOSVersion 18
|
||||
* @passStyle eventTicket (new layout)
|
||||
* @passDomain Event Guide
|
||||
*
|
||||
* To show buttons in the event guide,
|
||||
* at least two among those marked with
|
||||
* "@domain event guide" must be used.
|
||||
* "@passDomain Event Guide" must be used.
|
||||
*/
|
||||
orderFoodURL: Joi.string().regex(URL_REGEX),
|
||||
|
||||
/**
|
||||
* New field for iOS 18 Event Ticket.
|
||||
* @domain event guide
|
||||
* @iOSVersion 18
|
||||
* @passStyle eventTicket (new layout)
|
||||
* @passDomain Event Guide
|
||||
*
|
||||
* To show buttons in the event guide,
|
||||
* at least two among those marked with
|
||||
* "@domain event guide" must be used.
|
||||
* "@passDomain Event Guide" must be used.
|
||||
*/
|
||||
parkingInformationURL: Joi.string().regex(URL_REGEX),
|
||||
|
||||
/**
|
||||
* New field for iOS 18 Event Ticket.
|
||||
* @domain event guide
|
||||
* @iOSVersion 18
|
||||
* @passStyle eventTicket (new layout)
|
||||
* @passDomain Event Guide
|
||||
*
|
||||
* To show buttons in the event guide,
|
||||
* at least two among those marked with
|
||||
* "@domain event guide" must be used.
|
||||
* "@passDomain Event Guide" must be used.
|
||||
*/
|
||||
directionsInformationURL: Joi.string(),
|
||||
|
||||
/**
|
||||
* New field for iOS 18 Event Ticket.
|
||||
* @domain event guide
|
||||
* @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
|
||||
* "@domain event guide" must be used.
|
||||
*/
|
||||
contactVenueEmail: Joi.string(),
|
||||
|
||||
/**
|
||||
* New field for iOS 18 Event Ticket.
|
||||
* @domain event guide
|
||||
*
|
||||
* To show buttons in the event guide,
|
||||
* at least two among those marked with
|
||||
* "@domain event guide" must be used.
|
||||
*/
|
||||
contactVenuePhoneNumber: Joi.string(),
|
||||
|
||||
/**
|
||||
* New field for iOS 18 Event Ticket.
|
||||
* @domain event guide
|
||||
*
|
||||
* To show buttons in the event guide,
|
||||
* at least two among those marked with
|
||||
* "@domain event guide" must be used.
|
||||
*/
|
||||
contactVenueWebsite: Joi.string(),
|
||||
|
||||
/**
|
||||
* New field for iOS 18 Event Ticket.
|
||||
* @domain event guide
|
||||
*
|
||||
* To show buttons in the event guide,
|
||||
* at least two among those marked with
|
||||
* "@domain event guide" must be used.
|
||||
* "@passDomain Event Guide" must be used.
|
||||
*/
|
||||
purchaseParkingURL: Joi.string(),
|
||||
|
||||
/**
|
||||
* New field for iOS 18 Event Ticket.
|
||||
* @domain event guide
|
||||
* @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
|
||||
* "@domain event guide" must be used.
|
||||
* "@passDomain Event Guide" must be used.
|
||||
*/
|
||||
merchandiseURL: Joi.string(),
|
||||
|
||||
/**
|
||||
* New field for iOS 18 Event Ticket.
|
||||
* @domain event guide
|
||||
* @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
|
||||
* "@domain event guide" must be used.
|
||||
* "@passDomain Event Guide" must be used.
|
||||
*/
|
||||
transitInformationURL: Joi.string(),
|
||||
|
||||
/**
|
||||
* New field for iOS 18 Event Ticket.
|
||||
* @domain event guide
|
||||
* @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
|
||||
* "@domain event guide" must be used.
|
||||
* "@passDomain Event Guide" must be used.
|
||||
*/
|
||||
accessibilityURL: Joi.string(),
|
||||
|
||||
/**
|
||||
* New field for iOS 18 Event Ticket.
|
||||
* @domain event guide
|
||||
* @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
|
||||
* "@domain event guide" must be used.
|
||||
* "@passDomain Event Guide" must be used.
|
||||
*/
|
||||
addOnURL: Joi.string(),
|
||||
|
||||
/**
|
||||
* New field for iOS 18 Event Ticket.
|
||||
* @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(),
|
||||
|
||||
/**
|
||||
* New field for iOS 18 Event Ticket.
|
||||
* @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<
|
||||
@@ -473,7 +718,7 @@ export const Template = Joi.object<Template>({
|
||||
*/
|
||||
|
||||
export function assertValidity<T>(
|
||||
schema: Joi.ObjectSchema<T> | Joi.StringSchema | Joi.Schema<T>,
|
||||
schema: Joi.Schema<T>,
|
||||
data: T,
|
||||
customErrorMessage?: string,
|
||||
): void {
|
||||
@@ -505,7 +750,7 @@ export function assertValidity<T>(
|
||||
*/
|
||||
|
||||
export function validate<T extends Object>(
|
||||
schema: Joi.ObjectSchema<T> | Joi.StringSchema,
|
||||
schema: Joi.Schema<T>,
|
||||
options: T,
|
||||
): T {
|
||||
const validationResult = schema.validate(options, {
|
||||
|
||||
Reference in New Issue
Block a user