@steinnes/snippets
v0.1.2
Published
In-memory snippet store with an LLM-friendly editing API for Office.js and similar generated-code workflows.
Readme
@steinnes/snippets
An in-memory store for named text snippets, with an editing API shaped for
use by LLMs and tooling. Snippets are created, retrieved, and mutated by
name or id; edits specify oldText / newText pairs and apply with
forward-cursor, fuzzy-matched semantics. Also supports single-snippet patches
for multi-chunk updates.
This package is Node ESM, no runtime dependencies, and has no persistence
— all state lives in the SnippetStore instance.
Install
npm install @steinnes/snippetsUsage
import { SnippetStore } from '@steinnes/snippets';
const store = new SnippetStore();
// Create
const snippet = store.create({ name: 'greeting', content: 'hello world\n' });
// Edit (oldText → newText, with a forward cursor across multiple edits)
const edited = store.edit(snippet.id, [
{ oldText: 'world', newText: 'universe' },
]);
console.log(edited.content); // 'hello universe\n'
// Patch (single-snippet, one or more @@ chunks)
const patchText = [
'*** Begin Patch',
'*** Update File: greeting',
'@@',
'-universe',
'+everyone',
'*** End Patch',
'',
].join('\n');
const patched = store.patch(snippet.id, patchText);
console.log(patched.content); // 'hello everyone\n'
// List all snippets
const all = store.list();
// Rename
const renamed = store.rename(snippet.id, 'new-name');
// Replace all content
const fresh = store.replace(snippet.id, 'brand new content');
// Delete
store.delete(snippet.id);Errors
All errors extend Error and carry typed context fields:
SnippetNotFoundError— the given snippet id is not in the store. Fields:snippetId.SnippetNameConflictError— creating or renaming to a name that is already taken. Fields:conflictName.OldTextNotFoundError—oldTextwas not found in the snippet during an edit. Fields:snippetId,oldText,editIndex(for batch edits, the 0-based index of the failing edit).PatchParseError— the patch text is malformed (missing sentinels, multi-file patches, or structurally invalid chunks).PatchApplyError— a chunk'soldTextcould not be matched against the snippet during patch application. Fields:snippetId,chunkIndex,detail(the raw mismatch message).PatchTargetMismatchError— the patch's*** Update File:header names a snippet that does not match the target id. Fields:snippetId,snippetName,patchTargetName.
Fuzzy matching
Text matching for edit and patch runs a four-tier cascade until the
first tier matches (or all fail):
- Exact — literal substring match.
- Rstrip — line-wise, trailing whitespace ignored on both sides.
- Trim — line-wise, leading+trailing whitespace ignored on both sides.
- NFC — line-wise, Unicode-normalized (e.g.
éas\u00e9matchese\u0301).
Returned offsets always point at the original (un-normalized) content, so
replacement is lossless. Pass { fuzzy: false } to edit / patch (or
set fuzzy: false on the SnippetStore constructor options) to restrict
matching to tier 1 only.
Patch format
The patch format is a simple single-snippet text-patching format:
*** Begin Patch
*** Update File: <snippet-name> (optional; triggers strict name validation)
@@
- line to remove
+ line to add
context line (unchanged)
@@
...more chunks...
*** End PatchWhat IS supported:
*** Begin Patch/*** End Patchsentinels- Optional
*** Update File: <name>header — when present,store.patchvalidates that<name>matches the snippet's current name and throwsPatchTargetMismatchErrorif it does not - One or more
@@chunk markers - Lines prefixed with
-(removed),+(added), or(space; context) - Blank lines within a chunk (represented as empty strings in both oldText and newText)
- Fuzzy matching (optional; default on)
What is NOT supported:
@@ <context-string>navigation (the@@line takes no arguments)*** End of Filesentinel*** Add File/*** Delete Filemulti-file headers- Multi-file patches (a single patch with multiple
*** Update File:headers throwsPatchParseError)
