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. * @return {Promise<Stream>} A Promise containing the stream of the generated pass.
*/ */
generate() { async generate() {
let archive = archiver("zip"); try {
// Reading the model
const modelFilesList = await readdir(this.model);
return readCertificates(this.Certificates) /**
.then((certs) => Object.assign(this.Certificates, certs)) * Getting the buffers for remote files
.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));
}
throw new Error(err); const buffersPromise = this._remoteResources.reduce(async (acc, current) => {
}) try {
.then(filesList => { const response = await got(current[0], { encoding: null });
if (!this._remoteResources.length) {
return [filesList, [], []];
}
let buffersPromise = this._remoteResources.map((r) => {
return got(r[0], { encoding: null })
.then(response => {
loadDebug(formatMessage("LOAD_MIME", response.headers["content-type"])); loadDebug(formatMessage("LOAD_MIME", response.headers["content-type"]));
if (!Buffer.isBuffer(response.body)) { if (!Buffer.isBuffer(response.body)) {
@@ -89,25 +78,17 @@ class Pass {
throw "LOADED_RESOURCE_NOT_A_PICTURE"; throw "LOADED_RESOURCE_NOT_A_PICTURE";
} }
return response.body; return [...acc, response.body];
}) } catch (err) {
.catch(e => { loadDebug(formatMessage("LOAD_NORES", current[1], err));
loadDebug(formatMessage("LOAD_NORES", r[1], e)); return acc;
// here we are adding undefined values, that will be removed later. }
return undefined; }, []);
});
}); 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. // 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; const hasAssets = noDynList.length || remoteFilesList.length;
if (!hasAssets || ![...noDynList, ...remoteFilesList].some(f => f.toLowerCase().includes("icon"))) { 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) // 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 // Localization folders only
const L10N = noDynList.filter(f => f.includes(".lproj") && Object.keys(this.l10n).includes(path.parse(f).name)); 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 * @return {Promise<Buffer>} The patched pass.json buffer
*/ */
let passExtractor = (() => { const passExtractor = async () => {
return readFile(path.resolve(this.model, "pass.json")) const passStructBuffer = await readFile(path.resolve(this.model, "pass.json"))
.then(passStructBuffer => {
if (!this._validateType(passStructBuffer)) { if (!this._validateType(passStructBuffer)) {
let eMessage = formatMessage("PASSFILE_VALIDATION_FAILED"); const eMessage = formatMessage("PASSFILE_VALIDATION_FAILED");
throw new Error(eMessage); throw new Error(eMessage);
} }
bundle.push("pass.json"); bundle.push("pass.json");
return this._patch(passStructBuffer); return this._patch(passStructBuffer);
}); };
});
/* /*
* Reading all the localization selected folders and removing hidden files (the ones that starts with ".") * 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))) const listByFolder = await Promise.all(
.then(listByFolder => { L10N.map(async f =>
/* Each localization file name is joined with its own path and pushed to the bundle files array. */ 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 */ /* Getting all bundle file buffers, pass.json included, and appending path */
@@ -161,12 +151,11 @@ class Pass {
bundle = bundle.filter(file => !remoteFilesList.includes(file)); bundle = bundle.filter(file => !remoteFilesList.includes(file));
} }
let bundleBuffers = bundle.map(f => readFile(path.resolve(this.model, f))); const bundleBuffers = bundle.map(f => readFile(path.resolve(this.model, f)));
let passBuffer = passExtractor(); 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 => { Object.keys(this.l10n).forEach(l => {
const strings = generateStringFile(this.l10n[l]); const strings = generateStringFile(this.l10n[l]);
@@ -191,7 +180,6 @@ class Pass {
if (stringFileIndex > -1) { if (stringFileIndex > -1) {
buffers[stringFileIndex] = Buffer.concat([ buffers[stringFileIndex] = Buffer.concat([
buffers[stringFileIndex], buffers[stringFileIndex],
Buffer.from(EOL),
strings strings
]); ]);
} else { } else {
@@ -200,21 +188,15 @@ class Pass {
} }
}); });
return [ // Pushing the remote files into the bundle
// removing undefined values bundle.push(...remoteFilesList);
buffers.filter(b => !!b),
[...bundle, ...remoteFilesList]
];
});
});
})
.then(([buffers, bundle]) => {
/* /*
* Parsing the buffers, pushing them into the archive * Parsing the buffers, pushing them into the archive
* and returning the compiled manifest * and returning the compiled manifest
*/ */
const archive = archiver("zip");
return buffers.reduce((acc, current, index) => { const manifest = buffers.reduce((acc, current, index) => {
let filename = bundle[index]; let filename = bundle[index];
let hashFlow = forge.md.sha1.create(); let hashFlow = forge.md.sha1.create();
@@ -225,21 +207,31 @@ class Pass {
return acc; return acc;
}, {}); }, {});
})
.then((manifest) => { // Reading the certificates,
let signatureBuffer = this._sign(manifest); // 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(signatureBuffer, { name: "signature" });
archive.append(JSON.stringify(manifest), { name: "manifest.json" }); archive.append(JSON.stringify(manifest), { name: "manifest.json" });
let passStream = new stream.PassThrough(); const passStream = new stream.PassThrough();
archive.pipe(passStream); archive.pipe(passStream);
FieldsArray.emptyUnique(); FieldsArray.emptyUnique();
return archive.finalize().then(() => passStream); 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 => { }).catch(err => {
if (!err.path) { if (!err.path) {
// Catching error from '.then()';
throw err; throw err;
} }