Moved to async/await approach for generate()

This commit is contained in:
Alexander Cerutti
2019-04-26 11:18:03 +02:00
parent 279c74c506
commit 18893ac742

View File

@@ -56,29 +56,18 @@ class Pass {
* @return {Promise<Stream>} A Promise containing the stream of the generated pass.
*/
generate() {
let archive = archiver("zip");
async generate() {
try {
// Reading the model
const modelFilesList = await readdir(this.model);
return readCertificates(this.Certificates)
.then((certs) => Object.assign(this.Certificates, certs))
.then(() => readdir(this.model))
.catch((err) => {
// May have not used this catch but ENOENT error is not enough self-explanatory
// in the case of internal usage ()
if (err.code && err.code === "ENOENT") {
throw new Error(formatMessage("MODEL_NOT_FOUND", this.model));
}
/**
* Getting the buffers for remote files
*/
throw new Error(err);
})
.then(filesList => {
if (!this._remoteResources.length) {
return [filesList, [], []];
}
let buffersPromise = this._remoteResources.map((r) => {
return got(r[0], { encoding: null })
.then(response => {
const buffersPromise = this._remoteResources.reduce(async (acc, current) => {
try {
const response = await got(current[0], { encoding: null });
loadDebug(formatMessage("LOAD_MIME", response.headers["content-type"]));
if (!Buffer.isBuffer(response.body)) {
@@ -89,25 +78,17 @@ class Pass {
throw "LOADED_RESOURCE_NOT_A_PICTURE";
}
return response.body;
})
.catch(e => {
loadDebug(formatMessage("LOAD_NORES", r[1], e));
// here we are adding undefined values, that will be removed later.
return undefined;
});
});
return [...acc, response.body];
} catch (err) {
loadDebug(formatMessage("LOAD_NORES", current[1], err));
return acc;
}
}, []);
const remoteFilesList = buffersPromise.length ? this._remoteResources.map(r => r[1]): [];
// forwarding model files list, remote files list and remote buffers.
return [
filesList,
buffersPromise.length ? this._remoteResources.map(r => r[1]) : [],
buffersPromise
];
})
.then(([modelFileList, remoteFilesList, remoteBuffers]) => {
// list without dynamic components like manifest, signature or pass files (will be added later in the flow) and hidden files.
let noDynList = removeHidden(modelFileList).filter(f => !/(manifest|signature|pass)/i.test(f));
const noDynList = removeHidden(modelFilesList).filter(f => !/(manifest|signature|pass)/i.test(f));
const hasAssets = noDynList.length || remoteFilesList.length;
if (!hasAssets || ![...noDynList, ...remoteFilesList].some(f => f.toLowerCase().includes("icon"))) {
@@ -116,7 +97,7 @@ class Pass {
}
// list without localization files (they will be added later in the flow)
let bundle = noDynList.filter(f => !f.includes(".lproj"));
const bundle = noDynList.filter(f => !f.includes(".lproj"));
// Localization folders only
const L10N = noDynList.filter(f => f.includes(".lproj") && Object.keys(this.l10n).includes(path.parse(f).name));
@@ -128,30 +109,39 @@ class Pass {
* @return {Promise<Buffer>} The patched pass.json buffer
*/
let passExtractor = (() => {
return readFile(path.resolve(this.model, "pass.json"))
.then(passStructBuffer => {
const passExtractor = async () => {
const passStructBuffer = await readFile(path.resolve(this.model, "pass.json"))
if (!this._validateType(passStructBuffer)) {
let eMessage = formatMessage("PASSFILE_VALIDATION_FAILED");
const eMessage = formatMessage("PASSFILE_VALIDATION_FAILED");
throw new Error(eMessage);
}
bundle.push("pass.json");
return this._patch(passStructBuffer);
});
});
};
/*
* Reading all the localization selected folders and removing hidden files (the ones that starts with ".")
* from the list. Returning a Promise containing all those files
* from the list.
*/
return Promise.all(L10N.map(f => readdir(path.join(this.model, f)).then(removeHidden)))
.then(listByFolder => {
/* Each localization file name is joined with its own path and pushed to the bundle files array. */
const listByFolder = await Promise.all(
L10N.map(async f =>
removeHidden(await readdir(
path.join(this.model, f)
))
)
);
listByFolder.forEach((folder, index) => bundle.push(...folder.map(f => path.join(L10N[index], f))));
// Pushing into the bundle the composed paths for localization files
listByFolder.forEach((folder, index) =>
bundle.push(
...folder.map(f => path.join(L10N[index], f))
)
);
/* Getting all bundle file buffers, pass.json included, and appending path */
@@ -161,12 +151,11 @@ class Pass {
bundle = bundle.filter(file => !remoteFilesList.includes(file));
}
let bundleBuffers = bundle.map(f => readFile(path.resolve(this.model, f)));
let passBuffer = passExtractor();
const bundleBuffers = bundle.map(f => readFile(path.resolve(this.model, f)));
const passBuffer = passExtractor();
const buffers = await Promise.all([...bundleBuffers, passBuffer, ...buffersPromise]);
// Resolving all the buffers promises
return Promise.all([...bundleBuffers, passBuffer, ...remoteBuffers])
.then(buffers => {
Object.keys(this.l10n).forEach(l => {
const strings = generateStringFile(this.l10n[l]);
@@ -191,7 +180,6 @@ class Pass {
if (stringFileIndex > -1) {
buffers[stringFileIndex] = Buffer.concat([
buffers[stringFileIndex],
Buffer.from(EOL),
strings
]);
} else {
@@ -200,21 +188,15 @@ class Pass {
}
});
return [
// removing undefined values
buffers.filter(b => !!b),
[...bundle, ...remoteFilesList]
];
});
});
})
.then(([buffers, bundle]) => {
// Pushing the remote files into the bundle
bundle.push(...remoteFilesList);
/*
* Parsing the buffers, pushing them into the archive
* and returning the compiled manifest
*/
return buffers.reduce((acc, current, index) => {
const archive = archiver("zip");
const manifest = buffers.reduce((acc, current, index) => {
let filename = bundle[index];
let hashFlow = forge.md.sha1.create();
@@ -225,21 +207,31 @@ class Pass {
return acc;
}, {});
})
.then((manifest) => {
let signatureBuffer = this._sign(manifest);
// Reading the certificates,
// signing the manifest, appending signature an manifest to the archive
// and returning the generated pass stream.
Object.assign(this.Certificates, await readCertificates(this.Certificates));
const signatureBuffer = this._sign(manifest);
archive.append(signatureBuffer, { name: "signature" });
archive.append(JSON.stringify(manifest), { name: "manifest.json" });
let passStream = new stream.PassThrough();
const passStream = new stream.PassThrough();
archive.pipe(passStream);
FieldsArray.emptyUnique();
return archive.finalize().then(() => passStream);
});
} catch (err) {
if (err.code && err.code === "ENOENT") {
// No model available at this path - renaming the error
throw new Error(formatMessage("MODEL_NOT_FOUND", this.model));
}
}
}
/**
@@ -763,7 +755,6 @@ function readCertificates(certificates) {
);
}).catch(err => {
if (!err.path) {
// Catching error from '.then()';
throw err;
}