UNPKG

note

Version:
117 lines 3.92 kB
#!/usr/bin/env node /** * CLI entry point for the note command. * * @since 0.1.0 */ import { Args, Command } from "@effect/cli"; import { FileSystem, Path } from "@effect/platform"; import { NodeContext, NodeRuntime } from "@effect/platform-node"; import * as Console from "effect/Console"; import * as Data from "effect/Data"; import * as Effect from "effect/Effect"; import * as Match from "effect/Match"; import { makeContent, makeFilename } from "./dist/esm/Note.js"; import { TitleInput } from "./dist/esm/Validate.js"; /** * Error when an argument matches an existing file in the current directory. * * @since 0.1.0 * @category Errors */ export class ExistingArgFile extends /*#__PURE__*/Data.TaggedError("ExistingArgFile") { get message() { return `"${this.word}" matches an existing file. You may have confused this tool with another command.`; } } /** * Error when the target note file already exists. * * @since 0.1.0 * @category Errors */ export class FileAlreadyExists extends /*#__PURE__*/Data.TaggedError("FileAlreadyExists") { get message() { return `File "${this.filename}" already exists. Choose a different title or remove the existing file.`; } } /** * Error when file write fails. * * @since 0.1.0 * @category Errors */ export class WriteError extends /*#__PURE__*/Data.TaggedError("WriteError") { get message() { return `Failed to write "${this.filename}".`; } } /** * Format a NoteError for display. * * @since 0.1.0 * @category Errors */ const formatError = error => Match.value(error).pipe(Match.tag("ExistingArgFile", e => `Error: ${e.message}\nUsage: note <title words...>`), Match.tag("FileAlreadyExists", e => `Error: ${e.message}`), Match.tag("WriteError", e => `Error: ${e.message}`), Match.exhaustive); /** * Handle NoteError by printing pretty message and exiting. * * @since 0.1.0 * @category Errors */ const handleNoteError = error => Console.error(formatError(error)).pipe(Effect.andThen(Effect.sync(() => process.exit(1)))); const titleArgs = /*#__PURE__*/Args.text({ name: "title" }).pipe(/*#__PURE__*/Args.atLeast(1), /*#__PURE__*/Args.withSchema(TitleInput)); const noteCommand = /*#__PURE__*/Command.make("note", { title: titleArgs }, ({ title }) => Effect.gen(function* () { const fs = yield* FileSystem.FileSystem; const path = yield* Path.Path; const cwd = yield* Effect.sync(() => process.cwd()); // Check if any arg matches an existing file for (const word of title.words) { const filePath = path.join(cwd, word); const exists = yield* fs.exists(filePath); if (exists) { return yield* new ExistingArgFile({ word }); } } // Generate filename and check if it already exists const now = new Date(); const filename = makeFilename(title.title, now); const filePath = path.join(cwd, filename); const targetExists = yield* fs.exists(filePath); if (targetExists) { return yield* new FileAlreadyExists({ filename }); } // Create the note const content = makeContent(title.title, now); yield* fs.writeFileString(filePath, content).pipe(Effect.mapError(cause => new WriteError({ filename, cause }))); yield* Console.log(`\u2705 Created: ${filename}`); }).pipe(Effect.catchTag("ExistingArgFile", handleNoteError), Effect.catchTag("FileAlreadyExists", handleNoteError), Effect.catchTag("WriteError", handleNoteError))).pipe(/*#__PURE__*/Command.withDescription("Create a timestamped markdown note")); /** * Run the CLI with the given arguments. * * @since 0.1.0 */ export const run = args => Command.run(noteCommand, { name: "note", version: "0.1.0" })(args); // Run if executed directly (not when imported as module for testing) if (process.argv[1]?.includes("bin")) { run(process.argv).pipe(Effect.provide(NodeContext.layer), NodeRuntime.runMain({ disableErrorReporting: true })); } //# sourceMappingURL=bin.js.map