UNPKG

@softwareventures/maintain-project

Version:

Automatically create and maintain TypeScript projects with standard settings for Software Ventures Limited

91 lines 3.28 kB
import { promises as fs } from "fs"; import { resolve } from "path"; import { chain } from "@softwareventures/chain"; import { mapFn } from "@softwareventures/iterable"; import { hasProperty } from "unknown"; import { liftPromises, liftResults, mapValue } from "../collections/maps.js"; import { failure, mapAsyncResultFn, mapResultFn, success } from "../result/result.js"; export async function commit(path, stage) { return open(path, stage).then(mapAsyncResultFn(write)); } async function open(path, stage) { const { root, overwrite = false } = stage; return openDirectory({ path, node: root, overwrite }).then(mapResultFn(openRoot => ({ type: "open-fs-stage", path, openRoot }))); } async function openDirectory(options) { const { overwrite } = options; try { await fs.mkdir(options.path); } catch (reason) { if (!hasProperty(reason, "code") || reason.code !== "EEXIST") { throw reason; } else if (await fs.stat(options.path).then(stat => !stat.isDirectory())) { return failure([{ type: "not-a-directory", path: options.path }]); } else if (!overwrite) { return failure([{ type: "file-exists", path: options.path }]); } } const openEntries = mapValue(options.node.entries, async (node, relativePath) => { const path = resolve(options.path, relativePath); switch (node.type) { case "directory": return openDirectory({ path, node, overwrite }); case "file": return openFile({ path, node, overwrite }); } }); return liftPromises(openEntries) .then(liftResults) .then(mapResultFn(entries => ({ type: "open-directory", entries }))); } async function openFile(options) { const flags = options.overwrite ? "r+" : "wx+"; return fs .open(options.path, flags) .catch(async (reason) => { if (hasProperty(reason, "code") && reason.code === "ENOENT" && options.overwrite) { return fs.open(options.path, "wx+"); } else { throw reason; } }) .then(fileHandle => success({ type: "open-file", fileHandle, data: options.node.data }), reason => { if (hasProperty(reason, "code") && reason.code === "EEXIST") { return failure([{ type: "file-exists", path: options.path }]); } else { throw reason; } }); } async function write(stage) { return writeDirectory(stage.openRoot); } async function writeDirectory(directory) { return chain(directory.entries.values()) .map(mapFn(async (node) => { switch (node.type) { case "open-directory": return writeDirectory(node); case "open-file": return writeFile(node); } })) .map(async (results) => Promise.all(results)) .map(async (promise) => promise.then(() => undefined)).value; } async function writeFile(file) { return fs .writeFile(file.fileHandle, file.data) .then(async () => file.fileHandle.truncate(file.data.byteLength)) .then(async () => file.fileHandle.close()); } //# sourceMappingURL=commit.js.map