mirror of
https://github.com/marcogll/passkit-generator.git
synced 2026-03-15 21:25:26 +00:00
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:
@@ -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;
|
||||||
|
|||||||
47
src/pass.js
47
src/pass.js
@@ -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));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user