From f642ddc4443c1365985b27bb0b79f375ec33a176 Mon Sep 17 00:00:00 2001 From: Alexander Cerutti Date: Tue, 10 Dec 2019 22:10:45 +0100 Subject: [PATCH 1/5] Improved splitBufferBundle with early return --- src/utils.ts | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/src/utils.ts b/src/utils.ts index 610d3e2..1e42384 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -90,19 +90,18 @@ export function generateStringFile(lang: { [index: string]: string }): Buffer { */ export function splitBufferBundle(origin: Object): [PartitionedBundle["l10nBundle"], PartitionedBundle["bundle"]] { - const keys = Object.keys(origin); - return keys.reduce(([ l10n, bundle ], current) => { - if (current.includes(".lproj")) { - const pathComponents = current.split(sep); - const lang = pathComponents[0]; - const file = pathComponents.slice(1).join("/"); - - (l10n[lang] || (l10n[lang] = {}))[file] = origin[current]; - - return [ l10n, bundle ]; - } else { + return Object.keys(origin).reduce(([ l10n, bundle ], current) => { + if (!current.includes(".lproj")) { return [ l10n, { ...bundle, [current]: origin[current] }]; } + + const pathComponents = current.split(sep); + const lang = pathComponents[0]; + const file = pathComponents.slice(1).join("/"); + + (l10n[lang] || (l10n[lang] = {}))[file] = origin[current]; + + return [ l10n, bundle ]; }, [{},{}]); } From 7ed8bf52aa0597484fd324c8c4f47e80bc1d5bd8 Mon Sep 17 00:00:00 2001 From: Alexander Cerutti Date: Tue, 10 Dec 2019 22:11:40 +0100 Subject: [PATCH 2/5] Added pool declaration for FieldsArray --- src/fieldsArray.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/fieldsArray.ts b/src/fieldsArray.ts index 5cbda83..2258701 100644 --- a/src/fieldsArray.ts +++ b/src/fieldsArray.ts @@ -11,6 +11,8 @@ const fieldsDebug = debug("passkit:fields"); const poolSymbol = Symbol("pool"); export default class FieldsArray extends Array { + private [poolSymbol]: Set; + constructor(pool: Set, ...args: any[]) { super(...args); this[poolSymbol] = pool; From 54865f537b50fdd5f4973b7b79492f41767c4e39 Mon Sep 17 00:00:00 2001 From: Alexander Cerutti Date: Tue, 10 Dec 2019 22:21:18 +0100 Subject: [PATCH 3/5] Fixed non-existing this context --- src/parser.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/parser.ts b/src/parser.ts index 1a1748e..ec2fcac 100644 --- a/src/parser.ts +++ b/src/parser.ts @@ -107,7 +107,7 @@ export async function getModelFolderContents(model: string): Promise Date: Thu, 12 Dec 2019 23:04:15 +0100 Subject: [PATCH 4/5] Improved types for readCertificatesFromOptions --- src/parser.ts | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/parser.ts b/src/parser.ts index ec2fcac..cc9821a 100644 --- a/src/parser.ts +++ b/src/parser.ts @@ -231,6 +231,8 @@ export function getModelBufferContents(model: BundleUnit): PartitionedBundle { * @param options */ +type flatCertificates = Omit & { signerKey: string; [key: string]: string }; + export async function readCertificatesFromOptions(options: Certificates): Promise { if (!(options && Object.keys(options).length && isValid(options, "certificatesSchema"))) { throw new Error(formatMessage("CP_NO_CERTS")); @@ -240,11 +242,13 @@ export async function readCertificatesFromOptions(options: Certificates): Promis // all the real contents and don't care of passphrase const flattenedDocs = Object.assign({}, options, { signerKey: ( - typeof options.signerKey === "string" - ? options.signerKey - : options.signerKey.keyFile + options.signerKey && typeof options.signerKey === "string" && + options.signerKey || ( + options.signerKey && + options.signerKey.keyFile + ) ) - }); + }) as flatCertificates; // We read the contents const rawContentsPromises = Object.keys(flattenedDocs) From 93684948effa81e1476c6d2ccf65c7bd2007383c Mon Sep 17 00:00:00 2001 From: Alexander Cerutti Date: Sat, 14 Dec 2019 15:59:11 +0100 Subject: [PATCH 5/5] Strict mode-fixes --- src/pass.ts | 34 ++++++++++++++++++++-------------- src/schema.ts | 17 ++++++++++++++--- src/utils.ts | 8 +++++--- 3 files changed, 39 insertions(+), 20 deletions(-) diff --git a/src/pass.ts b/src/pass.ts index c4c8c64..15d571f 100644 --- a/src/pass.ts +++ b/src/pass.ts @@ -30,13 +30,15 @@ export class Pass { private [passProps]: schema.ValidPass = {}; private type: keyof schema.ValidPassType; private fieldsKeys: Set = new Set(); - private passCore: schema.ValidPass = {}; + private passCore: schema.ValidPass; - public headerFields: FieldsArray; - public primaryFields: FieldsArray; - public secondaryFields: FieldsArray; - public auxiliaryFields: FieldsArray; - public backFields: FieldsArray; + // Setting these as possibly undefined because we set + // them all in an loop later + public headerFields: FieldsArray | undefined; + public primaryFields: FieldsArray | undefined; + public secondaryFields: FieldsArray | undefined; + public auxiliaryFields: FieldsArray | undefined; + public backFields: FieldsArray | undefined; private Certificates: schema.FinalCertificates; private [transitType]: string = ""; @@ -72,7 +74,8 @@ export class Pass { } // Parsing and validating pass.json keys - const validatedPassKeys = Object.keys(this.passCore).reduce((acc, current) => { + const passCoreKeys = Object.keys(this.passCore) as (keyof schema.ValidPass)[]; + const validatedPassKeys = passCoreKeys.reduce((acc, current) => { if (this.type === current) { // We want to exclude type keys (eventTicket, // boardingPass, ecc.) and their content @@ -86,10 +89,13 @@ export class Pass { return { ...acc, [current]: this.passCore[current] }; } - const currentSchema = propsSchemaMap.get(current); + const currentSchema = propsSchemaMap.get(current)!; if (Array.isArray(this.passCore[current])) { - const valid = getValidInArray(currentSchema, this.passCore[current]); + const valid = getValidInArray( + currentSchema, + this.passCore[current] as schema.ArrayPassSchema[] + ); return { ...acc, [current]: valid }; } else { return { @@ -201,7 +207,7 @@ export class Pass { * and returning the compiled manifest */ const archive = new ZipFile(); - const manifest = Object.keys(finalBundle).reduce((acc, current) => { + const manifest = Object.keys(finalBundle).reduce((acc, current) => { let hashFlow = forge.md.sha1.create(); hashFlow.update(finalBundle[current].toString("binary")); @@ -504,7 +510,7 @@ export class Pass { * @returns {Buffer} */ - private _sign(manifest: { [key: string]: string }): Buffer { + private _sign(manifest: schema.Manifest): Buffer { const signature = forge.pkcs7.createSignedData(); signature.content = forge.util.createBuffer(JSON.stringify(manifest), "utf8"); @@ -577,8 +583,8 @@ export class Pass { * and then delete it from the passFile. */ - ["backgroundColor", "foregroundColor", "labelColor"] - .filter(v => this[passProps][v] && !isValidRGB(this[passProps][v])) + const passColors = ["backgroundColor", "foregroundColor", "labelColor"] as Array; + passColors.filter(v => this[passProps][v] && !isValidRGB(this[passProps][v])) .forEach(v => delete this[passProps][v]); Object.assign(passFile, this[passProps]); @@ -630,7 +636,7 @@ function barcodesFromUncompleteData(message: string): schema.Barcode[] { "PKBarcodeFormatPDF417", "PKBarcodeFormatAztec", "PKBarcodeFormatCode128" - ].map(format => schema.getValidated({ format, message }, "barcode")); + ].map(format => schema.getValidated({ format, message }, "barcode") as schema.Barcode); } function processRelevancySet(key: string, data: T[]): T[] { diff --git a/src/schema.ts b/src/schema.ts index a4eec48..bbf57ac 100644 --- a/src/schema.ts +++ b/src/schema.ts @@ -3,6 +3,10 @@ import debug from "debug"; const schemaDebug = debug("Schema"); +export interface Manifest { + [key: string]: string; +} + export interface Certificates { wwdr?: string; signerCert?: string; @@ -71,7 +75,7 @@ export interface OverridesSupportedOptions { teamIdentifier?: string; appLaunchURL?: string; associatedStoreIdentifiers?: Array; - userInfo?: Object | Array; + userInfo?: { [key: string]: any }; webServiceURL?: string; authenticationToken?: string; sharingProhibited?: boolean; @@ -294,7 +298,7 @@ export interface ValidPassType { storeCard?: PassFields; } -export interface ValidPass extends OverridesSupportedOptions, ValidPassType { +interface PassInterfacesProps { barcode?: Barcode; barcodes?: Barcode[]; beacons?: Beacon[]; @@ -306,6 +310,12 @@ export interface ValidPass extends OverridesSupportedOptions, ValidPassType { voided?: boolean; } +type AllPassProps = PassInterfacesProps & ValidPassType & OverridesSupportedOptions; +export type ValidPass = { + [K in keyof AllPassProps]: AllPassProps[K]; +}; +export type PassColors = Pick; + export interface Barcode { altText?: string; messageEncoding?: string; @@ -464,6 +474,7 @@ const schemas = { }; export type Schema = keyof typeof schemas; +export type ArrayPassSchema = Beacon | Location | Barcode; function resolveSchemaName(name: Schema) { return schemas[name] || undefined; @@ -500,7 +511,7 @@ export function isValid(opts: any, schemaName: Schema): boolean { * @returns {object} the filtered value or empty object */ -export function getValidated(opts: any, schemaName: Schema): T { +export function getValidated(opts: any, schemaName: Schema): T | null { const resolvedSchema = resolveSchemaName(schemaName); if (!resolvedSchema) { diff --git a/src/utils.ts b/src/utils.ts index 1e42384..539f471 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -11,7 +11,7 @@ import { sep } from "path"; * @returns {Boolean} True if valid rgb, false otherwise */ -export function isValidRGB(value: string): boolean { +export function isValidRGB(value?: string): boolean { if (!value || typeof value !== "string") { return false; } @@ -89,8 +89,10 @@ export function generateStringFile(lang: { [index: string]: string }): Buffer { * @param origin */ -export function splitBufferBundle(origin: Object): [PartitionedBundle["l10nBundle"], PartitionedBundle["bundle"]] { - return Object.keys(origin).reduce(([ l10n, bundle ], current) => { +type PartitionedBundleElements = [PartitionedBundle["l10nBundle"], PartitionedBundle["bundle"]]; + +export function splitBufferBundle(origin: any): PartitionedBundleElements { + return Object.keys(origin).reduce(([ l10n, bundle ], current) => { if (!current.includes(".lproj")) { return [ l10n, { ...bundle, [current]: origin[current] }]; }