Update plugin shape again

This commit is contained in:
Endeavorance 2025-04-04 16:14:17 -04:00
parent dfc65dacfa
commit 2d3ba356b5
5 changed files with 52 additions and 46 deletions

View file

@ -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<Binding> {}
```
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<Binding> {
const newBinding = { ...binding };
newBinding.options.someOption = "newValue";
return {
...binding,
meta: {
...binding.meta,
customValue: true,
}
};
}
```

View file

@ -1,6 +1,6 @@
{
"name": "@endeavorance/muse",
"version": "0.2.0",
"version": "0.3.0",
"module": "dist/index.js",
"exports": {
".": {

View file

@ -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<MetaShape = UnknownRecord> {
/** The raw data read from the binding file */
readonly _raw: z.infer<typeof BindingSchema>;
/** Information about the sources used to load entries */
readonly sources: MuseSource[];
@ -133,11 +130,10 @@ export async function loadBinding(initialPath: string): Promise<Binding> {
// 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,

View file

@ -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";

View file

@ -1,20 +0,0 @@
import type { Binding } from "#core/binding";
export class Muse {
bindingLoaded = false;
preliminaryBinding: Partial<Binding> = {};
additionalSources: string[] = [];
additionalPluginPaths: string[] = [];
constructor(bindingConfig: Partial<Binding>) {
this.preliminaryBinding = bindingConfig;
}
source(newSource: string) {
this.additionalSources.push(newSource);
}
plugin(pluginPath: string) {
this.additionalPluginPaths.push(pluginPath);
}
}