From 2d3ba356b5052eb7df0d766fd7b534f3f283113c Mon Sep 17 00:00:00 2001 From: Endeavorance Date: Fri, 4 Apr 2025 16:14:17 -0400 Subject: [PATCH] Update plugin shape again --- README.md | 61 ++++++++++++++++++++++++++++++++------------- package.json | 2 +- src/core/binding.ts | 8 ++---- src/exports.ts | 7 ++++-- src/muse.ts | 20 --------------- 5 files changed, 52 insertions(+), 46 deletions(-) delete mode 100644 src/muse.ts diff --git a/README.md b/README.md index df86874..d122169 100644 --- a/README.md +++ b/README.md @@ -1,20 +1,17 @@ # Muse -A CLI for wrangling directories of source files. - -Like a static generator, but for whatever. +_Bind data into anything_ ## Overview -**Muse** is a CLI and toolchain for operating on directories of -json, yaml, toml, and markdown files. Each file can specify any shape -of data. Muse scans included files, parses them into data, and streams -the loaded data through processors and plugins. +**Muse** is a CLI and toolchain for operating on data collected from +json, yaml, toml, and markdown files. -Each processor can modify the data at compile time, as well as enact -side effects such as writing files to disk. +Muse scans included files, parses them into data, and streams +the loaded data through plugins. -Muse does not edit source files, it only reads them in. +Each plugin can modify the data as well as enact side effects +such as writing files to disk. ## Usage @@ -32,10 +29,9 @@ Options: Each Muse project should specify a `binding` file with the following shape: ```yaml -include: - - ../another-project # Optional -files: # Optional - - "**/*.yaml" +sources: # Optional + - file: "**/*.yaml" + - web: "https://example.com/data.json" contentKey: "content" # Optional options: # Optional someOption: someValue @@ -44,9 +40,9 @@ processors: - second-processor ``` -The `binding` file can be any of the supported file types for Muse. If -the CLI is invoked with a directory instead of a file, Muse will look -for a binding file in the directory with the following order: +The `binding` file can be any of the supported file types for Muse and can +be named anything. If the CLI is invoked with a directory instead of a file, +Muse will look for a binding file in the directory with the following order: 1. `binding.json` 2. `binding.yaml` @@ -68,3 +64,34 @@ Your markdown content here When loading markdown files, Muse will load the content of the file into a key called `content` by default. This can be changed in the binding configuration by setting a `contentKey` value as an override. + +## Plugin API + +Muse plugins are written in TypeScript/JavaScript and expose information +describing the plugin, as well as the functions to operate with: + +```typescript +export const name = "Plugin Name"; +export const description = "Plugin Description"; +export async function step(binding: Binding): Promise {} +``` + +The main function of a plugin is `step`, which takes a `Binding` object +and returns a modified `Binding` object. + +When returning a new Binding object, it is best practice to make immutable +changes: + +```typescript +export async function step(binding: Binding): Promise { + const newBinding = { ...binding }; + newBinding.options.someOption = "newValue"; + return { + ...binding, + meta: { + ...binding.meta, + customValue: true, + } + }; +} +``` diff --git a/package.json b/package.json index 36bf54a..e7e1428 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@endeavorance/muse", - "version": "0.2.0", + "version": "0.3.0", "module": "dist/index.js", "exports": { ".": { diff --git a/src/core/binding.ts b/src/core/binding.ts index 1a768e5..7652c0a 100644 --- a/src/core/binding.ts +++ b/src/core/binding.ts @@ -22,7 +22,7 @@ const BindingSchema = z.object({ }, ]), options: z.record(z.string(), z.any()).default({}), - processors: z.array(z.string()).default([]), + plugins: z.array(z.string()).default([]), }); /** @@ -31,9 +31,6 @@ const BindingSchema = z.object({ * the project, and a list of entries to be processed */ export interface Binding { - /** The raw data read from the binding file */ - readonly _raw: z.infer; - /** Information about the sources used to load entries */ readonly sources: MuseSource[]; @@ -133,11 +130,10 @@ export async function loadBinding(initialPath: string): Promise { // Load and check plugins const plugins: MusePlugin[] = await Promise.all( - parsedBinding.processors.map(loadPlugin.bind(null, bindingDirname)), + parsedBinding.plugins.map(loadPlugin.bind(null, bindingDirname)), ); return { - _raw: parsedBinding, sources, bindingPath, contentKey: parsedBinding.contentKey, diff --git a/src/exports.ts b/src/exports.ts index f520a46..451c4f8 100644 --- a/src/exports.ts +++ b/src/exports.ts @@ -5,5 +5,8 @@ export * from "#errors"; export const DEFAULT_CONTENT_KEY = "content"; // Types -export type * from "#types"; -export type { MusePlugin } from "#core/plugins"; +export type * from "#core/binding"; +export type * from "#core/plugins"; +export type * from "#core/sources"; +export type * from "#core/records"; +export type * from "#core/files"; diff --git a/src/muse.ts b/src/muse.ts deleted file mode 100644 index 814dc78..0000000 --- a/src/muse.ts +++ /dev/null @@ -1,20 +0,0 @@ -import type { Binding } from "#core/binding"; - -export class Muse { - bindingLoaded = false; - preliminaryBinding: Partial = {}; - additionalSources: string[] = []; - additionalPluginPaths: string[] = []; - - constructor(bindingConfig: Partial) { - this.preliminaryBinding = bindingConfig; - } - - source(newSource: string) { - this.additionalSources.push(newSource); - } - - plugin(pluginPath: string) { - this.additionalPluginPaths.push(pluginPath); - } -}