Fixed problem in error message resolving on multiple %s;

Added debug messages in messages.js;
Added more comments;
Moved literal debug messages to messages.js;
Edited formatMessage (was formatError) to check also among debugMessages
This commit is contained in:
alexandercerutti
2018-12-29 02:00:57 +01:00
parent 27339bfdac
commit 9a9d883d3f
2 changed files with 55 additions and 31 deletions

View File

@@ -1,28 +1,51 @@
let errors = { const errors = {
PASSFILE_VALIDATION_FAILED: "Validation of pass type failed. Pass file is not a valid buffer or (more probabily) does not respect the schema. Refer to https://apple.co/2Nvshvn to build a correct pass.", PASSFILE_VALIDATION_FAILED: "Validation of pass type failed. Pass file is not a valid buffer or (more probabily) does not respect the schema. Refer to https://apple.co/2Nvshvn to build a correct pass.",
REQUIR_VALID_FAILED: "The options passed to Pass constructor does not meet the requirements. Refer to the documentation to compile them correctly.", REQUIR_VALID_FAILED: "The options passed to Pass constructor does not meet the requirements. Refer to the documentation to compile them correctly.",
MODEL_UNINITIALIZED: "Provided model ( %s ) matched but unitialized or may not contain icon. Refer to https://apple.co/2IhJr0Q, https://apple.co/2Nvshvn and documentation to fill the model correctly.", MODEL_UNINITIALIZED: "Provided model ( %s ) matched but unitialized or may not contain icon. Refer to https://apple.co/2IhJr0Q, https://apple.co/2Nvshvn and documentation to fill the model correctly.",
MODEL_NOT_STRING: "A string model name must be provided in order to continue.", MODEL_NOT_STRING: "A string model name must be provided in order to continue.",
MODEL_NOT_FOUND: "Model %s not found. Provide a valid one to continue.", MODEL_NOT_FOUND: "Model %s not found. Provide a valid one to continue.",
INVALID_CERTS: "Invalid certificate(s) loaded: %s. Please provide valid WWDR certificates and developer signer certificate and key (with passphrase). Refer to docs to obtain them.", INVALID_CERTS: "Invalid certificate(s) loaded: %s. Please provide valid WWDR certificates and developer signer certificate and key (with passphrase). Refer to docs to obtain them.",
INVALID_CERT_PATH: "Invalid certificate loaded. %s does not exist." INVALID_CERT_PATH: "Invalid certificate loaded. %s does not exist.",
TRSTYPE_REQUIRED: "Cannot proceed with pass creation. transitType field is required for boardingPasses.",
}; };
function format(errorName, ...values) { const debugMessages = {
TRSTYPE_NOT_VALID: "Transit type changing rejected as not compliant with Apple Specifications. Transit type would become \"%s\" but should be in [PKTransitTypeAir, PKTransitTypeBoat, PKTransitTypeBus, PKTransitTypeGeneric, PKTransitTypeTrain]",
BRC_NOT_SUPPORTED: "Format not found among barcodes. Cannot set backward compatibility.",
BRC_FORMATTYPE_UNMATCH: "Format must be a string or null. Cannot set backward compatibility.",
BRC_AUTC_MISSING_DATA: "Unable to autogenerate barcodes. Data is not an object or has not message field.",
DATE_FORMAT_UNMATCH: "%s was not set due to incorrect date format.",
LOAD_TYPES_UNMATCH: "Resource and name are not valid strings. No action will be taken for the specified medias.",
LOAD_MIME: "Picture MIME-type: %s",
LOAD_NORES: "Was not able to fetch resource %s. Error: %s"
};
/**
* Creates a message with replaced values
* @param {string} messageName
* @param {any[]} values
*/
function format(messageName, ...values) {
// reversing because it is better popping than shifting. // reversing because it is better popping than shifting.
let replaceValues = values.reverse(); let replaceValues = values.reverse();
return resolveErrorName(errorName).replace(/%s/, () => { return resolveMessageName(messageName).replace(/%s/g, () => {
let next = replaceValues.pop(); let next = replaceValues.pop();
return next !== undefined ? next : "<passedValueIsUndefined>"; return next !== undefined ? next : "<passedValueIsUndefined>";
}); });
} }
function resolveErrorName(name) { /**
if (!errors[name]) { * Looks among errors and debugMessages for the specified message name
return `<ErrorName ${name} is not linked to any error messages>`; * @param {string} name
*/
function resolveMessageName(name) {
if (!errors[name] && !debugMessages[name]) {
return `<ErrorName "${name}" is not linked to any error messages>`;
} }
return errors[name]; return errors[name] || debugMessages[name];
} }
module.exports = format; module.exports = format;

View File

@@ -13,7 +13,7 @@ const genericDebug = debug("passkit:generic");
const loadDebug = debug("passkit:load"); const loadDebug = debug("passkit:load");
const schema = require("./schema"); const schema = require("./schema");
const formatError = require("./messages"); const formatMessage = require("./messages");
const FieldsContainer = require("./fields"); const FieldsContainer = require("./fields");
const readdir = promisify(fs.readdir); const readdir = promisify(fs.readdir);
@@ -58,7 +58,7 @@ class Pass {
// May have not used this catch but ENOENT error is not enough self-explanatory // May have not used this catch but ENOENT error is not enough self-explanatory
// in the case of internal usage () // in the case of internal usage ()
if (err.code && err.code === "ENOENT") { if (err.code && err.code === "ENOENT") {
throw new Error(formatError("MODEL_NOT_FOUND", this.model)); throw new Error(formatMessage("MODEL_NOT_FOUND", this.model));
} }
throw new Error(err); throw new Error(err);
@@ -71,20 +71,20 @@ class Pass {
let buffersPromise = this._remoteResources.map((r) => { let buffersPromise = this._remoteResources.map((r) => {
return got(r[0], { encoding: null }) return got(r[0], { encoding: null })
.then(response => { .then(response => {
loadDebug(`Picture MIME-type: ${response.headers["content-type"]}`); loadDebug(formatMessage("LOAD_MIME", response.headers["content-type"]));
if (!Buffer.isBuffer(response.body)) { if (!Buffer.isBuffer(response.body)) {
throw "NOTABUFFER"; throw "LOADED_RESOURCE_NOT_A_BUFFER";
} }
if (!response.headers["content-type"].includes("image/")) { if (!response.headers["content-type"].includes("image/")) {
throw "NOTAPICTURE"; throw "LOADED_RESOURCE_NOT_A_PICTURE";
} }
return response.body; return response.body;
}) })
.catch(e => { .catch(e => {
loadDebug(`Was not able to fetch resource ${r[1]}. Error: ${e}`); loadDebug(formatMessage("LOAD_NORES", r[1], e));
// here we are adding undefined values, that will be removed later. // here we are adding undefined values, that will be removed later.
return undefined; return undefined;
}); });
@@ -102,7 +102,7 @@ class Pass {
let noDynList = removeHidden(modelFileList).filter(f => !/(manifest|signature|pass)/i.test(f)); let noDynList = removeHidden(modelFileList).filter(f => !/(manifest|signature|pass)/i.test(f));
if (!noDynList.length || ![...noDynList, ...remoteFilesList].some(f => f.toLowerCase().includes("icon"))) { if (!noDynList.length || ![...noDynList, ...remoteFilesList].some(f => f.toLowerCase().includes("icon"))) {
let eMessage = formatError("MODEL_UNINITIALIZED", path.parse(this.model).name); let eMessage = formatMessage("MODEL_UNINITIALIZED", path.parse(this.model).name);
throw new Error(eMessage); throw new Error(eMessage);
} }
@@ -123,7 +123,7 @@ class Pass {
return readFile(path.resolve(this.model, "pass.json")) return readFile(path.resolve(this.model, "pass.json"))
.then(passStructBuffer => { .then(passStructBuffer => {
if (!this._validateType(passStructBuffer)) { if (!this._validateType(passStructBuffer)) {
let eMessage = formatError("PASSFILE_VALIDATION_FAILED"); let eMessage = formatMessage("PASSFILE_VALIDATION_FAILED");
throw new Error(eMessage); throw new Error(eMessage);
} }
@@ -251,7 +251,7 @@ class Pass {
let dateParse = dateToW3CString(date, format); let dateParse = dateToW3CString(date, format);
if (!dateParse) { if (!dateParse) {
genericDebug("Expiration Date was not set due to invalid format."); genericDebug(formatMessage("DATE_FORMAT_UNMATCH", "Expiration date"));
} else { } else {
this._props.expirationDate = dateParse; this._props.expirationDate = dateParse;
} }
@@ -320,7 +320,7 @@ class Pass {
let dateParse = dateToW3CString(data, relevanceDateFormat); let dateParse = dateToW3CString(data, relevanceDateFormat);
if (!dateParse) { if (!dateParse) {
genericDebug("Relevant Date was not set due to incorrect date format."); genericDebug(formatMessage("DATE_FORMAT_UNMATCH", "Relevant Date"));
} else { } else {
this._props[type] = dateParse; this._props[type] = dateParse;
} }
@@ -402,7 +402,7 @@ class Pass {
__barcodeAutogen(data) { __barcodeAutogen(data) {
if (!data || !(data instanceof Object) || !data.message) { if (!data || !(data instanceof Object) || !data.message) {
barcodeDebug("Unable to autogenerate barcodes. Data is not an object or has not message field."); barcodeDebug(formatMessage("BRC_AUTC_MISSING_DATA"));
return []; return [];
} }
@@ -459,7 +459,7 @@ class Pass {
} }
if (typeof format !== "string") { if (typeof format !== "string") {
barcodeDebug("format must be a string or null. Cannot set backward compatibility."); barcodeDebug(formatMessage("BRC_FORMAT_UNMATCH"));
return this; return this;
} }
@@ -467,7 +467,7 @@ class Pass {
let index = this._props["barcodes"].findIndex(b => b.format.toLowerCase().includes(format.toLowerCase())); let index = this._props["barcodes"].findIndex(b => b.format.toLowerCase().includes(format.toLowerCase()));
if (index === -1) { if (index === -1) {
barcodeDebug("format not found among barcodes. Cannot set backward compatibility."); barcodeDebug(formatMessage("BRC_NOT_SUPPORTED"));
return this; return this;
} }
@@ -506,7 +506,7 @@ class Pass {
load(resource, name) { load(resource, name) {
if (typeof resource !== "string" && typeof name !== "string") { if (typeof resource !== "string" && typeof name !== "string") {
loadDebug("resource and name are not valid strings. No action will be taken."); loadDebug(formatMessage("LOAD_TYPES_UNMATCH"));
return; return;
} }
@@ -644,8 +644,8 @@ class Pass {
} }
}); });
if (!this.transitType && this.type === "boardingPass") { if (this.type === "boardingPass" && !this.transitType) {
throw new Error("Cannot proceed with pass creation. transitType field is required for boardingPasses."); throw new Error(formatMessage("TRSTYPE_REQUIRED"));
} }
passFile[this.type]["transitType"] = this.transitType; passFile[this.type]["transitType"] = this.transitType;
@@ -662,15 +662,12 @@ class Pass {
*/ */
_parseSettings(options) { _parseSettings(options) {
let eMessage = null;
if (!schema.isValid(options, "instance")) { if (!schema.isValid(options, "instance")) {
eMessage = formatError("REQUIR_VALID_FAILED"); throw new Error(formatMessage("REQUIR_VALID_FAILED"));
throw new Error(eMessage);
} }
if (!options.model || typeof options.model !== "string") { if (!options.model || typeof options.model !== "string") {
eMessage = formatError("MODEL_NOT_STRING"); throw new Error(formatMessage("MODEL_NOT_STRING"));
throw new Error(eMessage);
} }
let modelPath = path.resolve(options.model) + (!!options.model && !path.extname(options.model) ? ".pass" : ""); let modelPath = path.resolve(options.model) + (!!options.model && !path.extname(options.model) ? ".pass" : "");
@@ -687,6 +684,7 @@ class Pass {
if (schema.isValid(v, "transitType")) { if (schema.isValid(v, "transitType")) {
this._transitType = v; this._transitType = v;
} else { } else {
genericDebug(formatMessage("TRSTYPE_NOT_VALID", v));
this._transitType = this._transitType || ""; this._transitType = this._transitType || "";
} }
} }
@@ -723,13 +721,16 @@ function readCertificates(certificates) {
return Promise.all(certPaths) return Promise.all(certPaths)
.then(contents => { .then(contents => {
// Mapping each file content to a PEM structure, returned in form of one-key-object
// which is conjoint later with the other pems
return Object.assign( return Object.assign(
...contents.map((file, index) => { ...contents.map((file, index) => {
const certName = optCertsNames[index]; const certName = optCertsNames[index];
const pem = parsePEM(certName, file, raw[certName].passphrase); const pem = parsePEM(certName, file, raw[certName].passphrase);
if (!pem) { if (!pem) {
throw new Error(formatError("INVALID_CERTS", certName)); throw new Error(formatMessage("INVALID_CERTS", certName));
} }
return { [certName]: pem }; return { [certName]: pem };
@@ -741,7 +742,7 @@ function readCertificates(certificates) {
throw err; throw err;
} }
throw new Error(formatError("INVALID_CERT_PATH", path.parse(err.path).base)); throw new Error(formatMessage("INVALID_CERT_PATH", path.parse(err.path).base));
}); });
} }