mirror of
https://github.com/marcogll/passkit-generator.git
synced 2026-03-15 19:25:23 +00:00
135 lines
3.0 KiB
TypeScript
135 lines
3.0 KiB
TypeScript
import * as path from "path";
|
|
import * as Utils from "./utils";
|
|
import * as Messages from "./messages";
|
|
import { promises as fs } from "fs";
|
|
|
|
/**
|
|
* Reads the model folder contents
|
|
*
|
|
* @param model
|
|
* @returns A promise of an object containing all
|
|
* filePaths and the relative buffer
|
|
*/
|
|
|
|
export default async function getModelFolderContents(
|
|
model: string,
|
|
): Promise<{ [filePath: string]: Buffer }> {
|
|
try {
|
|
const modelPath = `${model}${(!path.extname(model) && ".pass") || ""}`;
|
|
const modelFilesList = await fs.readdir(modelPath);
|
|
|
|
// No dot-starting files, manifest and signature
|
|
const filteredModelRecords = Utils.removeHidden(modelFilesList).filter(
|
|
(f) =>
|
|
!/(manifest|signature)/i.test(f) &&
|
|
/.+$/.test(path.parse(f).ext),
|
|
);
|
|
|
|
const modelRecords = (
|
|
await Promise.all(
|
|
/**
|
|
* Obtaining flattened array of buffer records
|
|
* containing file name and the buffer itself.
|
|
*
|
|
* This goes also to read every nested l10n
|
|
* subfolder.
|
|
*/
|
|
|
|
filteredModelRecords.map((fileOrDirectoryPath) => {
|
|
const fullPath = path.resolve(
|
|
modelPath,
|
|
fileOrDirectoryPath,
|
|
);
|
|
|
|
return readFileOrDirectory(fullPath);
|
|
}),
|
|
)
|
|
)
|
|
.flat(1)
|
|
.reduce((acc, current) => ({ ...acc, ...current }), {});
|
|
|
|
return modelRecords;
|
|
} catch (_err) {
|
|
const err = _err as NodeJS.ErrnoException;
|
|
|
|
if (err?.code === "ENOENT") {
|
|
if (err.syscall === "open") {
|
|
// file opening failed
|
|
throw new Error(
|
|
Messages.format(
|
|
Messages.MODELS.FILE_NO_OPEN,
|
|
JSON.stringify(err),
|
|
),
|
|
);
|
|
} else if (err.syscall === "scandir") {
|
|
// directory reading failed
|
|
throw new Error(
|
|
Messages.format(Messages.MODELS.DIR_NOT_FOUND, err.path),
|
|
);
|
|
}
|
|
}
|
|
|
|
throw err;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Reads sequentially
|
|
* @param filePath
|
|
* @returns
|
|
*/
|
|
|
|
async function readFileOrDirectory(filePath: string) {
|
|
if ((await fs.lstat(filePath)).isDirectory()) {
|
|
return Promise.all(await readDirectory(filePath));
|
|
} else {
|
|
return fs
|
|
.readFile(filePath)
|
|
.then((content) => getObjectFromModelFile(filePath, content, 1));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Returns an object containing the parsed fileName
|
|
* from a path along with its content.
|
|
*
|
|
* @param filePath
|
|
* @param content
|
|
* @param depthFromEnd - used to preserve localization lproj content
|
|
* @returns
|
|
*/
|
|
|
|
function getObjectFromModelFile(
|
|
filePath: string,
|
|
content: Buffer,
|
|
depthFromEnd: number,
|
|
) {
|
|
const fileComponents = filePath.split(path.sep);
|
|
const fileName = fileComponents
|
|
.slice(fileComponents.length - depthFromEnd)
|
|
.join("/");
|
|
|
|
return { [fileName]: content };
|
|
}
|
|
|
|
/**
|
|
* Reads a directory and returns all the files in it
|
|
* as an Array<Promise>
|
|
*
|
|
* @param filePath
|
|
* @returns
|
|
*/
|
|
|
|
async function readDirectory(filePath: string) {
|
|
const dirContent = await fs.readdir(filePath).then(Utils.removeHidden);
|
|
|
|
return dirContent.map(async (fileName) => {
|
|
const content = await fs.readFile(path.resolve(filePath, fileName));
|
|
return getObjectFromModelFile(
|
|
path.resolve(filePath, fileName),
|
|
content,
|
|
2,
|
|
);
|
|
});
|
|
}
|