@effected/templates 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ManagedSection.js +1 -1
- package/README.md +79 -0
- package/SectionDialect.js +1 -1
- package/SectionDocument.js +1 -1
- package/package.json +2 -2
package/ManagedSection.js
CHANGED
|
@@ -18,7 +18,7 @@ import { Context, Effect, FileSystem, Layer, Schema } from "effect";
|
|
|
18
18
|
*
|
|
19
19
|
* @public
|
|
20
20
|
*/
|
|
21
|
-
var SectionFileError = class extends Schema.
|
|
21
|
+
var SectionFileError = class extends Schema.TaggedError()("SectionFileError", {
|
|
22
22
|
/** The file the operation was against. */
|
|
23
23
|
path: Schema.String,
|
|
24
24
|
/** Which half of the read-modify-write failed. */
|
package/README.md
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
# @effected/templates
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/@effected/templates)
|
|
4
|
+
[](https://opensource.org/licenses/MIT)
|
|
5
|
+
[](https://nodejs.org/)
|
|
6
|
+
[](https://www.typescriptlang.org/)
|
|
7
|
+
|
|
8
|
+
Managed sections: delimited `BEGIN`/`END` blocks inside files whose surrounding content belongs to the user. A tool owns the block, the user owns everything else, and neither destroys the other — the mechanism behind a generated hook, a managed config fragment, or any file your tool and your user both need to edit.
|
|
9
|
+
|
|
10
|
+
> **Pre-release.** This package is part of the `@effected/*` kit, in pre-`1.0.0`
|
|
11
|
+
> development against a single pinned Effect v4 beta. Packages graduate to
|
|
12
|
+
> `1.0.0` once Effect `4.0.0` ships. To hold your own `effect` versions at
|
|
13
|
+
> exactly the ones the kit is built and tested against, install
|
|
14
|
+
> [`@effected/pnpm-plugin-effect`](https://www.npmjs.com/package/@effected/pnpm-plugin-effect).
|
|
15
|
+
>
|
|
16
|
+
> **Stability: unstable.** This package's API surface is not yet considered
|
|
17
|
+
> complete and may change across `0.x` releases. Pin an exact version — even a
|
|
18
|
+
> package marked *stable* before `1.0.0` can introduce a breaking change by
|
|
19
|
+
> accident, and an exact pin turns that into a type-check error rather than a
|
|
20
|
+
> runtime surprise. Full policy: [release strategy](https://github.com/spencerbeggs/effected#release-strategy).
|
|
21
|
+
|
|
22
|
+
## Why @effected/templates
|
|
23
|
+
|
|
24
|
+
Most "managed section" implementations put the whole algorithm inside a service that also does file IO, so the hardest logic — deciding what changed, and where a new block belongs — can only be tested by writing files to disk. This package splits the two apart. `SectionDocument` is a pure string-to-string core with no `Effect`, no IO and no runtime: parse a document, compare a declared section against what is already there, reconcile a whole set of them, render the result. `ManagedSection` is a thin service that reads a file, calls the pure core, and writes back only when the text actually changed.
|
|
25
|
+
|
|
26
|
+
Ambiguity fails typed rather than being resolved by guessing: an unterminated marker, an orphaned `END`, two overlapping sections, or the same identity declared twice are all a typed `SectionParseError` naming the line, never a silent skip that leaves a duplicate block on the next run. Line endings are a first-class invariant too — the document's dominant EOL is detected at parse and every comparison is EOL-normalized, so a CRLF file does not report drift forever.
|
|
27
|
+
|
|
28
|
+
## Install
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
npm install @effected/templates effect
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
pnpm add @effected/templates effect
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Requires Node.js >=24.11.0. `effect` v4 is the only peer dependency, and the only dependency of any kind.
|
|
39
|
+
|
|
40
|
+
All `@effected/*` packages are ESM-only: the exports maps publish only `import` conditions, so `require()` — including tools that resolve in CJS mode — fails with Node's `ERR_PACKAGE_PATH_NOT_EXPORTED` rather than loading a CJS build that does not exist. Import from an ES module.
|
|
41
|
+
|
|
42
|
+
`FileSystem` comes from `effect` core, not from a platform package, so a consumer provides it once at the edge (`NodeFileSystem.layer` from `@effect/platform-node` on Node). `Path` is deliberately not required — this package treats every path as an opaque string handed straight to `FileSystem`.
|
|
43
|
+
|
|
44
|
+
## Quick start
|
|
45
|
+
|
|
46
|
+
Declare two sections and sync them into a file in one call. Declared order becomes file order, so `base` always precedes `tool`, however a user may have reordered the file by hand:
|
|
47
|
+
|
|
48
|
+
```ts
|
|
49
|
+
import { CommentStyle, ManagedSection, SectionId } from "@effected/templates";
|
|
50
|
+
import { NodeFileSystem } from "@effect/platform-node";
|
|
51
|
+
import { Effect } from "effect";
|
|
52
|
+
|
|
53
|
+
const Base = SectionId.make({ key: "base", commentStyle: CommentStyle.hash });
|
|
54
|
+
const Tool = SectionId.make({ key: "tool", commentStyle: CommentStyle.hash });
|
|
55
|
+
|
|
56
|
+
const program = Effect.gen(function* () {
|
|
57
|
+
const sections = yield* ManagedSection;
|
|
58
|
+
return yield* sections.syncAll(".husky/pre-commit", [Base.section("#!/usr/bin/env sh"), Tool.section("npx tool run")]);
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
Effect.runPromise(program.pipe(Effect.provide(ManagedSection.layer), Effect.provide(NodeFileSystem.layer))).then((outcomes) =>
|
|
62
|
+
console.log(outcomes.map((o) => o._tag)),
|
|
63
|
+
);
|
|
64
|
+
// example output on a fresh file: [ "Created", "Created" ]
|
|
65
|
+
// example output on a second, identical run: [ "Unchanged", "Unchanged" ]
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## Features
|
|
69
|
+
|
|
70
|
+
- `SectionDocument` — the pure core: `parse` / `read` / `has` / `check` / `reconcile` / `remove` over a plain string, with no `Effect`, no IO and no runtime needed to test it.
|
|
71
|
+
- `ManagedSection` — the service: `read`, `readAll`, `isManaged`, `sync`, `syncAll`, `check`, `checkAll` and `remove`, each writing back only when the text changed.
|
|
72
|
+
- `CommentStyle` — an open set of `{prefix, suffix?}` presets (`hash`, `slash`, `semicolon`, `dash`, `html`, `block`) covering both line comments and wrapped ones like `<!-- … -->`, so a managed section can live in Markdown or HTML, not just source files.
|
|
73
|
+
- `SyncOutcome` / `CheckOutcome` — tagged results (`Created` / `Updated` / `Unchanged`, `Absent` / `UpToDate` / `Drifted`) that carry the sections involved rather than a diff, so a caller renders exactly the comparison it needs.
|
|
74
|
+
- Byte-preserving outside managed blocks: every character outside a declared section's span survives a sync, in order, including a leading BOM.
|
|
75
|
+
- Idempotent by construction: syncing an already-up-to-date document writes nothing and touches no mtime.
|
|
76
|
+
|
|
77
|
+
## License
|
|
78
|
+
|
|
79
|
+
[MIT](LICENSE)
|
package/SectionDialect.js
CHANGED
|
@@ -12,7 +12,7 @@ import { Equal, Result, Schema } from "effect";
|
|
|
12
12
|
*
|
|
13
13
|
* @public
|
|
14
14
|
*/
|
|
15
|
-
var SectionRenderError = class extends Schema.
|
|
15
|
+
var SectionRenderError = class extends Schema.TaggedError()("SectionRenderError", {
|
|
16
16
|
/**
|
|
17
17
|
* `markerInContent` — the content carries a line the scanner would read as
|
|
18
18
|
* a marker, which would move the block boundary and let the next sync
|
package/SectionDocument.js
CHANGED
|
@@ -20,7 +20,7 @@ import { Effect, Equal, Option, Result, Schema } from "effect";
|
|
|
20
20
|
*
|
|
21
21
|
* @public
|
|
22
22
|
*/
|
|
23
|
-
var SectionParseError = class SectionParseError extends Schema.
|
|
23
|
+
var SectionParseError = class SectionParseError extends Schema.TaggedError()("SectionParseError", {
|
|
24
24
|
/** Which ambiguity was found. */
|
|
25
25
|
reason: Schema.Literals(SCAN_FAILURE_REASONS),
|
|
26
26
|
/** 1-based line of the offending marker. */
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@effected/templates",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Managed-section blocks in user-editable files: parse, reconcile, sync and check delimited regions.",
|
|
6
6
|
"keywords": [
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
"./package.json": "./package.json"
|
|
38
38
|
},
|
|
39
39
|
"peerDependencies": {
|
|
40
|
-
"effect": "4.0.0-beta.
|
|
40
|
+
"effect": "4.0.0-beta.107"
|
|
41
41
|
},
|
|
42
42
|
"engines": {
|
|
43
43
|
"node": ">=24.11.0"
|