@stratware/reglet
v0.1.2
Published
Reglet is a custom pattern matching DSL. Making regex easier to work with
Readme
Author - Team Stratware
Reglet
Composable matcher DSL + plugin registry for building readable command routers, feature switches, and domain-specific languages without hand-coding brittle RegExp chains.
- Declarative matchers – chain literal/token/regex helpers, or use higher-level flows to describe your protocol in almost-English.
- Named features – convert matcher definitions directly into executable plugins via
Builder.feature(...).withImpl(...)or thebuilder.auto()shortcut. - Runtime registry – register plugins, search/match targets, and safely dispatch implementations with policy guards.
Reglet ships with the same builders used across
scope/andreglet/example/. Anything demonstrated there works identically in your own packages.
Installation
Reglet is published internally via Pathify aliases:
const { Builder, PluginRegistry, builtins } = require('stratware@reglet')When consuming directly from the repo (without Pathify), point to src/reglet.
Quick Start
const { Builder, PluginRegistry } = require('stratware@reglet')
const builder = new Builder()
const deployFeature = builder
.feature('deploy.ecs')
.ifMatch(
builder.seq(
builder.lit('deploy::'),
builder.token({ allowDots: true })
)
)
.withImpl(({ target }) => ({ ok: true, message: `shipping ${target}` }))
const registry = new PluginRegistry()
registry.register(deployFeature)
// Later in your CLI/router
const result = registry.dispatch('deploy::api.us-east-1')DSL Building Blocks
Tokens, literals, aliases
builder.lit('deploy::')– literal match.builder.token({ allowDots: true })– generic segment matcher.- Built-in aliases:
dotted,namespace,register,path. You can create your own viabuilder.alias('service', a => a.define('::').multi(true))and then referencebuilder.service()inside flows. builder.slug(opts)– convenience wrapper aroundbuilder.tokenthat accepts slug-style characters (letters, digits,_,-) without writing custom regexes; tweak casing viaallowUpper/allowLowerflags.
Matcher helpers
Reglet exposes a rich set of matchers (builder.alpha, number, alnum, version, regex, length, range, caseInsensitive, capture, optional, repeat, oneOf, listOf, predicate, sequence). All of them produce composable matcher objects, so you can mix and match as needed.
Flow builder
builder.flow() (and convenience wrappers like builder.if(...).then(...)) let you chain readable matcher segments:
const artifactFlow = builder.flow()
.if('register')
.then(builder.token())
.finally(builder.optional(builder.lit('#latest')))
.release()Use flows when you want imperative-looking composition that still yields a single matcher at the end.
Feature Builders & Plugins
builder.feature(name) returns a FeatureBuilder so you can bind metadata + implementations:
const publish = builder.feature('publish.image')
.ifMatch(artifactFlow)
.withPluginName('publish:image')
.withImpl(({ target, imageTag }) => pushImage(target, imageTag))
.withPrefix('publish::')
.allowDots()
.withTemplate('publish::<repo>[dotted]')
.build()The resulting object already conforms to what PluginRegistry.register() expects. Alternatively, call builder.auto({ prefix, impl, allowDots }) for a minimal plugin spec – Reglet generates the matcher for you.
Plugin Registry
PluginRegistry tracks plugins by name and prefix, and exposes multiple execution paths:
register(plugin | feature | factory)– accepts feature definitions, builder factories, or legacy specs.match(target)/findMatching(target)– locate plugins by string input.dispatch(target, ctx, options)– run the matched plugin, enforcing policies (allowPlugins,denyPlugins,requireTrusted,guard).call(target, ctx, options)– safe wrapper returning{ ok, result, reason }instead of throwing.invoke(pluginName, ctx, options)– run by plugin identifier.search(query, { by })– fuzzy match by name/prefix/template.
Example Scripts
See src/reglet/example/index.builtin.js for a runnable demo that wires Pathify, builtin functions, and Reglet features together. There are also markdown notes in src/reglet/example/builder-flow-vs.md that compare flow-style builders vs direct matcher composition.
Tips
- Prefer aliases for repeated token shapes. They keep flows legible and reduce mistakes.
- Keep plugins pure when possible;
registry.dispatchcan pass contextual data (like env or IO clients) via thectxobject instead of relying on globals. - Use
builder.capture('name', matcher)when you need to plumb matching values into your plugin implementations. - Wrap untrusted plugins with
trusted: falseand enforcerequireTrusted: truefor production dispatch paths.
Roadmap
- CLI helpers for auditing registered prefixes.
- Type definitions for Builder/Match interfaces.
- Additional builtin aliases (hex, slug, cloud region shortcuts).
Contributions welcome. Open an issue or drop a note in the main workspace if you add new matcher primitives or registry policies.
Updates
We do not update based on time, but rather when we see fit. See the CHANGELOG.md for recent changes and upcoming plans.
