mirror of
https://github.com/marcogll/passkit-generator.git
synced 2026-03-15 19:25:23 +00:00
Updated Schemas
This commit is contained in:
@@ -32,9 +32,9 @@ type TransitTypes = `PKTransitType${
|
|||||||
const LOCALIZED_FILE_REGEX_BASE = "(?<lang>[a-zA-Z-]{2,}).lproj/";
|
const LOCALIZED_FILE_REGEX_BASE = "(?<lang>[a-zA-Z-]{2,}).lproj/";
|
||||||
|
|
||||||
export default class PKPass extends Bundle {
|
export default class PKPass extends Bundle {
|
||||||
private certificates: Schemas.Certificates;
|
private certificates: Schemas.CertificatesSchema;
|
||||||
private [fieldKeysPoolSymbol] = new Set<string>();
|
private [fieldKeysPoolSymbol] = new Set<string>();
|
||||||
private [propsSymbol]: Schemas.ValidPass = {};
|
private [propsSymbol]: Schemas.PassProps = {};
|
||||||
private [localizationSymbol]: {
|
private [localizationSymbol]: {
|
||||||
[lang: string]: {
|
[lang: string]: {
|
||||||
[placeholder: string]: string;
|
[placeholder: string]: string;
|
||||||
@@ -129,7 +129,11 @@ export default class PKPass extends Bundle {
|
|||||||
// *** INSTANCE *** //
|
// *** INSTANCE *** //
|
||||||
// **************** //
|
// **************** //
|
||||||
|
|
||||||
constructor(buffers: NamedBuffers, certificates: Certificates) {
|
constructor(
|
||||||
|
buffers: NamedBuffers,
|
||||||
|
certificates: Schemas.CertificatesSchema,
|
||||||
|
overrides: Schemas.OverridablePassProps,
|
||||||
|
) {
|
||||||
super("application/vnd.apple.pkpass");
|
super("application/vnd.apple.pkpass");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -153,7 +157,7 @@ export default class PKPass extends Bundle {
|
|||||||
* that are composing your pass instance.
|
* that are composing your pass instance.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public get props(): Readonly<Schemas.ValidPass> {
|
public get props(): Readonly<Schemas.PassProps> {
|
||||||
return freezeRecusive(this[propsSymbol]);
|
return freezeRecusive(this[propsSymbol]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -322,7 +326,7 @@ export default class PKPass extends Bundle {
|
|||||||
return super.addBuffer(pathName, buffer);
|
return super.addBuffer(pathName, buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
private [importMetadataSymbol](data: Schemas.ValidPass) {
|
private [importMetadataSymbol](data: Schemas.PassProps) {
|
||||||
const possibleTypes = [
|
const possibleTypes = [
|
||||||
"boardingPass",
|
"boardingPass",
|
||||||
"coupon",
|
"coupon",
|
||||||
@@ -768,11 +772,11 @@ function readPassMetadata(buffer: Buffer) {
|
|||||||
try {
|
try {
|
||||||
const contentAsJSON = JSON.parse(
|
const contentAsJSON = JSON.parse(
|
||||||
buffer.toString("utf8"),
|
buffer.toString("utf8"),
|
||||||
) as Schemas.ValidPass;
|
) as Schemas.PassProps;
|
||||||
|
|
||||||
const validation = Schemas.getValidated(
|
const validation = Schemas.getValidated(
|
||||||
contentAsJSON,
|
contentAsJSON,
|
||||||
Schemas.ValidPass,
|
Schemas.PassProps,
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ export interface Manifest {
|
|||||||
[key: string]: string;
|
[key: string]: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Certificates {
|
/* export interface Certificates {
|
||||||
wwdr?: string;
|
wwdr?: string;
|
||||||
signerCert?: string;
|
signerCert?: string;
|
||||||
signerKey?:
|
signerKey?:
|
||||||
@@ -34,54 +34,28 @@ export interface Certificates {
|
|||||||
passphrase?: string;
|
passphrase?: string;
|
||||||
}
|
}
|
||||||
| string;
|
| string;
|
||||||
}
|
}*/
|
||||||
|
|
||||||
export interface FactoryOptions {
|
|
||||||
model: BundleUnit | string;
|
|
||||||
certificates: Certificates;
|
|
||||||
overrides?: OverridesSupportedOptions;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface BundleUnit {
|
|
||||||
[key: string]: Buffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface PartitionedBundle {
|
|
||||||
bundle: BundleUnit;
|
|
||||||
l10nBundle: {
|
|
||||||
[key: string]: BundleUnit;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface CertificatesSchema {
|
export interface CertificatesSchema {
|
||||||
wwdr: string;
|
wwdr: string | Buffer;
|
||||||
signerCert: string;
|
signerCert: string | Buffer;
|
||||||
signerKey: string;
|
signerKey: string | Buffer;
|
||||||
|
signerKeyPassphrase?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const CertificatesSchema = Joi.object<CertificatesSchema>()
|
export const CertificatesSchema = Joi.object<CertificatesSchema>()
|
||||||
.keys({
|
.keys({
|
||||||
wwdr: Joi.alternatives(Joi.binary(), Joi.string()).required(),
|
wwdr: Joi.alternatives(Joi.binary(), Joi.string()).required(),
|
||||||
signerCert: Joi.alternatives(Joi.binary(), Joi.string()).required(),
|
signerCert: Joi.alternatives(Joi.binary(), Joi.string()).required(),
|
||||||
signerKey: Joi.alternatives()
|
signerKey: Joi.alternatives(Joi.binary(), Joi.string()).required(),
|
||||||
.try(
|
signerKeyPassphrase: Joi.string(),
|
||||||
Joi.object().keys({
|
|
||||||
keyFile: Joi.alternatives(
|
|
||||||
Joi.binary(),
|
|
||||||
Joi.string(),
|
|
||||||
).required(),
|
|
||||||
passphrase: Joi.string().required(),
|
|
||||||
}),
|
|
||||||
Joi.alternatives(Joi.binary(), Joi.string()),
|
|
||||||
)
|
|
||||||
.required(),
|
|
||||||
})
|
})
|
||||||
.required();
|
.required();
|
||||||
|
|
||||||
export interface Template {
|
export interface Template {
|
||||||
model: string;
|
model: string;
|
||||||
certificates: CertificatesSchema;
|
certificates: CertificatesSchema;
|
||||||
overrides?: OverridesSupportedOptions;
|
overrides?: OverridablePassProps;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const Template = Joi.object<Template>({
|
export const Template = Joi.object<Template>({
|
||||||
@@ -90,56 +64,37 @@ export const Template = Joi.object<Template>({
|
|||||||
overrides: Joi.object(),
|
overrides: Joi.object(),
|
||||||
});
|
});
|
||||||
|
|
||||||
export interface OverridesSupportedOptions {
|
export interface PassProps {
|
||||||
serialNumber?: string;
|
serialNumber?: string;
|
||||||
description?: string;
|
description?: string;
|
||||||
organizationName?: string;
|
organizationName?: string;
|
||||||
passTypeIdentifier?: string;
|
passTypeIdentifier?: string;
|
||||||
teamIdentifier?: string;
|
teamIdentifier?: string;
|
||||||
appLaunchURL?: string;
|
appLaunchURL?: string;
|
||||||
associatedStoreIdentifiers?: Array<number>;
|
voided?: boolean;
|
||||||
userInfo?: { [key: string]: any };
|
userInfo?: { [key: string]: any };
|
||||||
webServiceURL?: string;
|
|
||||||
authenticationToken?: string;
|
|
||||||
sharingProhibited?: boolean;
|
sharingProhibited?: boolean;
|
||||||
backgroundColor?: string;
|
|
||||||
foregroundColor?: string;
|
|
||||||
labelColor?: string;
|
|
||||||
groupingIdentifier?: string;
|
groupingIdentifier?: string;
|
||||||
suppressStripShine?: boolean;
|
suppressStripShine?: boolean;
|
||||||
logoText?: string;
|
logoText?: string;
|
||||||
maxDistance?: number;
|
maxDistance?: number;
|
||||||
semantics?: Semantics;
|
semantics?: Semantics;
|
||||||
}
|
|
||||||
|
|
||||||
export const OverridesSupportedOptions = Joi.object<OverridesSupportedOptions>()
|
webServiceURL?: string;
|
||||||
.keys({
|
associatedStoreIdentifiers?: Array<number>;
|
||||||
serialNumber: Joi.string(),
|
authenticationToken?: string;
|
||||||
description: Joi.string(),
|
|
||||||
organizationName: Joi.string(),
|
backgroundColor?: string;
|
||||||
passTypeIdentifier: Joi.string(),
|
foregroundColor?: string;
|
||||||
teamIdentifier: Joi.string(),
|
labelColor?: string;
|
||||||
appLaunchURL: Joi.string(),
|
|
||||||
associatedStoreIdentifiers: Joi.array().items(Joi.number()),
|
nfc?: NFC;
|
||||||
userInfo: Joi.alternatives(Joi.object().unknown(), Joi.array()),
|
beacons?: Beacon[];
|
||||||
// parsing url as set of words and nums followed by dots, optional port and any possible path after
|
barcodes?: Barcode[];
|
||||||
webServiceURL: Joi.string().regex(
|
relevantDate?: string;
|
||||||
/https?:\/\/(?:[a-z0-9]+\.?)+(?::\d{2,})?(?:\/[\S]+)*/,
|
expirationDate?: string;
|
||||||
),
|
locations?: Location[];
|
||||||
authenticationToken: Joi.string().min(16),
|
|
||||||
sharingProhibited: Joi.boolean(),
|
|
||||||
backgroundColor: Joi.string().min(10).max(16),
|
|
||||||
foregroundColor: Joi.string().min(10).max(16),
|
|
||||||
labelColor: Joi.string().min(10).max(16),
|
|
||||||
groupingIdentifier: Joi.string(),
|
|
||||||
suppressStripShine: Joi.boolean(),
|
|
||||||
logoText: Joi.string(),
|
|
||||||
maxDistance: Joi.number().positive(),
|
|
||||||
semantics: Semantics,
|
|
||||||
})
|
|
||||||
.with("webServiceURL", "authenticationToken");
|
|
||||||
|
|
||||||
export interface ValidPassType {
|
|
||||||
boardingPass?: PassFields & { transitType: TransitType };
|
boardingPass?: PassFields & { transitType: TransitType };
|
||||||
eventTicket?: PassFields;
|
eventTicket?: PassFields;
|
||||||
coupon?: PassFields;
|
coupon?: PassFields;
|
||||||
@@ -147,29 +102,89 @@ export interface ValidPassType {
|
|||||||
storeCard?: PassFields;
|
storeCard?: PassFields;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface PassInterfacesProps {
|
/**
|
||||||
barcode?: Barcode;
|
* These are the properties passkit-generator will
|
||||||
barcodes?: Barcode[];
|
* handle through its methods
|
||||||
beacons?: Beacon[];
|
*/
|
||||||
locations?: Location[];
|
|
||||||
maxDistance?: number;
|
type PassMethodsProps =
|
||||||
relevantDate?: string;
|
| "nfc"
|
||||||
nfc?: NFC;
|
| "beacons"
|
||||||
expirationDate?: string;
|
| "barcodes"
|
||||||
voided?: boolean;
|
| "relevantDate"
|
||||||
}
|
| "expirationDate"
|
||||||
|
| "locations";
|
||||||
|
|
||||||
|
export type PassTypesProps =
|
||||||
|
| "boardingPass"
|
||||||
|
| "eventTicket"
|
||||||
|
| "coupon"
|
||||||
|
| "generic"
|
||||||
|
| "storeCard";
|
||||||
|
|
||||||
|
export type OverridablePassProps = Omit<
|
||||||
|
PassProps,
|
||||||
|
PassMethodsProps | PassTypesProps
|
||||||
|
>;
|
||||||
|
export type PassPropsFromMethods = { [K in PassMethodsProps]: PassProps[K] };
|
||||||
|
export type PassKindsProps = { [K in PassTypesProps]: PassProps[K] };
|
||||||
|
|
||||||
type AllPassProps = PassInterfacesProps &
|
|
||||||
ValidPassType &
|
|
||||||
OverridesSupportedOptions;
|
|
||||||
export type ValidPass = {
|
|
||||||
[K in keyof AllPassProps]: AllPassProps[K];
|
|
||||||
};
|
|
||||||
export type PassColors = Pick<
|
export type PassColors = Pick<
|
||||||
OverridesSupportedOptions,
|
OverridablePassProps,
|
||||||
"backgroundColor" | "foregroundColor" | "labelColor"
|
"backgroundColor" | "foregroundColor" | "labelColor"
|
||||||
>;
|
>;
|
||||||
|
|
||||||
|
export const PassPropsFromMethods = Joi.object<PassPropsFromMethods>({
|
||||||
|
nfc: NFC,
|
||||||
|
beacons: Joi.array().items(Beacon),
|
||||||
|
barcodes: Joi.array().items(Barcode),
|
||||||
|
relevantDate: Joi.string().isoDate(),
|
||||||
|
expirationDate: Joi.string().isoDate(),
|
||||||
|
locations: Joi.array().items(Location),
|
||||||
|
});
|
||||||
|
|
||||||
|
export const PassKindsProps = Joi.object<PassKindsProps>({
|
||||||
|
coupon: Joi.array().items(Field),
|
||||||
|
generic: Joi.array().items(Field),
|
||||||
|
storeCard: Joi.array().items(Field),
|
||||||
|
eventTicket: Joi.array().items(Field),
|
||||||
|
boardingPass: Joi.array().items(
|
||||||
|
Field.concat(Joi.object({ transitType: TransitType })),
|
||||||
|
),
|
||||||
|
});
|
||||||
|
|
||||||
|
export const OverridablePassProps = Joi.object<OverridablePassProps>({
|
||||||
|
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(),
|
||||||
|
labelColor: Joi.string().min(10).max(16),
|
||||||
|
authenticationToken: Joi.string().min(16),
|
||||||
|
backgroundColor: Joi.string().min(10).max(16),
|
||||||
|
foregroundColor: Joi.string().min(10).max(16),
|
||||||
|
associatedStoreIdentifiers: Joi.array().items(Joi.number()),
|
||||||
|
userInfo: Joi.alternatives(Joi.object().unknown(), Joi.array()),
|
||||||
|
// parsing url as set of words and nums followed by dots, optional port and any possible path after
|
||||||
|
webServiceURL: Joi.string().regex(
|
||||||
|
/https?:\/\/(?:[a-z0-9]+\.?)+(?::\d{2,})?(?:\/[\S]+)*/,
|
||||||
|
),
|
||||||
|
}).with("webServiceURL", "authenticationToken");
|
||||||
|
|
||||||
|
export const PassProps = Joi.object({
|
||||||
|
...OverridablePassProps,
|
||||||
|
...PassKindsProps,
|
||||||
|
...PassPropsFromMethods,
|
||||||
|
});
|
||||||
|
|
||||||
// --------- UTILITIES ---------- //
|
// --------- UTILITIES ---------- //
|
||||||
|
|
||||||
type AvailableSchemas =
|
type AvailableSchemas =
|
||||||
@@ -183,7 +198,7 @@ type AvailableSchemas =
|
|||||||
| typeof TransitType
|
| typeof TransitType
|
||||||
| typeof Template
|
| typeof Template
|
||||||
| typeof CertificatesSchema
|
| typeof CertificatesSchema
|
||||||
| typeof OverridesSupportedOptions;
|
| typeof OverridablePassProps;
|
||||||
|
|
||||||
export type ArrayPassSchema = Beacon | Location | Barcode;
|
export type ArrayPassSchema = Beacon | Location | Barcode;
|
||||||
|
|
||||||
|
|||||||
@@ -20,8 +20,18 @@ export function create(
|
|||||||
"utf8",
|
"utf8",
|
||||||
);
|
);
|
||||||
|
|
||||||
signature.addCertificate(certificates.wwdr);
|
const { wwdr, signerCert, signerKey, signerKeyPassphrase } = certificates;
|
||||||
signature.addCertificate(certificates.signerCert);
|
|
||||||
|
const wwdrString = wwdr instanceof Buffer ? wwdr.toString("utf-8") : wwdr;
|
||||||
|
const signerCertString =
|
||||||
|
signerCert instanceof Buffer
|
||||||
|
? signerCert.toString("utf-8")
|
||||||
|
: signerCert;
|
||||||
|
const signerKeyString =
|
||||||
|
signerKey instanceof Buffer ? signerKey.toString("utf-8") : signerKey;
|
||||||
|
|
||||||
|
signature.addCertificate(wwdrString);
|
||||||
|
signature.addCertificate(signerCertString);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* authenticatedAttributes belong to PKCS#9 standard.
|
* authenticatedAttributes belong to PKCS#9 standard.
|
||||||
@@ -33,8 +43,8 @@ export function create(
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
signature.addSigner({
|
signature.addSigner({
|
||||||
key: certificates.signerKey,
|
key: signerKeyString,
|
||||||
certificate: certificates.signerCert,
|
certificate: signerCertString,
|
||||||
digestAlgorithm: forge.pki.oids.sha1,
|
digestAlgorithm: forge.pki.oids.sha1,
|
||||||
authenticatedAttributes: [
|
authenticatedAttributes: [
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user