@projitect/core 0.0.0-stage → 1.0.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/LICENSE +21 -0
- package/dist/blueprint-filesystem.d.ts +33 -0
- package/dist/blueprint-filesystem.d.ts.map +1 -0
- package/dist/blueprint-filesystem.js +4 -0
- package/dist/blueprint-filesystem.js.map +1 -0
- package/dist/blueprint.d.ts +27 -0
- package/dist/blueprint.d.ts.map +1 -0
- package/dist/blueprint.js +2 -0
- package/dist/blueprint.js.map +1 -0
- package/dist/change-set.d.ts +166 -0
- package/dist/change-set.d.ts.map +1 -0
- package/dist/change-set.js +79 -0
- package/dist/change-set.js.map +1 -0
- package/dist/config.d.ts +36 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +44 -0
- package/dist/config.js.map +1 -0
- package/dist/errors/index.d.ts +279 -0
- package/dist/errors/index.d.ts.map +1 -0
- package/dist/errors/index.js +317 -0
- package/dist/errors/index.js.map +1 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +14 -0
- package/dist/index.js.map +1 -0
- package/dist/lockfile.d.ts +113 -0
- package/dist/lockfile.d.ts.map +1 -0
- package/dist/lockfile.js +46 -0
- package/dist/lockfile.js.map +1 -0
- package/dist/permissions.d.ts +33 -0
- package/dist/permissions.d.ts.map +1 -0
- package/dist/permissions.js +20 -0
- package/dist/permissions.js.map +1 -0
- package/package.json +39 -3
- package/src/blueprint-filesystem.ts +39 -0
- package/src/blueprint.ts +27 -0
- package/src/change-set.ts +106 -0
- package/src/config.ts +51 -0
- package/src/errors/index.ts +430 -0
- package/src/index.ts +14 -0
- package/src/lockfile.ts +61 -0
- package/src/permissions.ts +28 -0
- package/README.md +0 -3
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Kapil Easwar
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { Context } from "effect";
|
|
2
|
+
import type { Effect } from "effect";
|
|
3
|
+
import type { FsPermissionDenied, FsReadFailed, FsWriteFailed } from "./errors/index.js";
|
|
4
|
+
/**
|
|
5
|
+
* The sandboxed file system blueprints receive. The real `@effect/platform` `FileSystem` is
|
|
6
|
+
* never provided to blueprint code — `cli-internals` wires a permission-gated implementation
|
|
7
|
+
* here.
|
|
8
|
+
*
|
|
9
|
+
* The interface lives in `@projitect/core` so it can be referenced from both `@projitect/blueprint`
|
|
10
|
+
* (which exposes helpers built on it) and `@projitect/cli-internals` (which implements it).
|
|
11
|
+
*
|
|
12
|
+
* The current implementation is a soft sandbox: it enforces permissions at the Effect layer but
|
|
13
|
+
* runs in the same process as the CLI. A worker-process implementation is a tracked v2 follow-up;
|
|
14
|
+
* the interface is shaped so the swap is transparent to blueprint authors.
|
|
15
|
+
*/
|
|
16
|
+
export interface BlueprintFileSystemShape {
|
|
17
|
+
readonly readFile: (path: string) => Effect.Effect<string, FsReadFailed | FsPermissionDenied>;
|
|
18
|
+
readonly writeFile: (path: string, content: string) => Effect.Effect<void, FsWriteFailed | FsPermissionDenied>;
|
|
19
|
+
readonly exists: (path: string) => Effect.Effect<boolean, FsPermissionDenied>;
|
|
20
|
+
readonly remove: (path: string) => Effect.Effect<void, FsWriteFailed | FsPermissionDenied>;
|
|
21
|
+
/**
|
|
22
|
+
* Remove a directory only if it is empty — never recursive. Fails with `FsWriteFailed` when the
|
|
23
|
+
* directory is missing or holds any entry, so an entry that appears concurrently survives.
|
|
24
|
+
*/
|
|
25
|
+
readonly removeEmptyDir: (path: string) => Effect.Effect<void, FsWriteFailed | FsPermissionDenied>;
|
|
26
|
+
readonly mkdir: (path: string) => Effect.Effect<void, FsWriteFailed | FsPermissionDenied>;
|
|
27
|
+
readonly listDir: (path: string) => Effect.Effect<readonly string[], FsReadFailed | FsPermissionDenied>;
|
|
28
|
+
}
|
|
29
|
+
declare const BlueprintFileSystem_base: Context.ServiceClass<BlueprintFileSystem, "@projitect/core/BlueprintFileSystem", BlueprintFileSystemShape>;
|
|
30
|
+
export declare class BlueprintFileSystem extends BlueprintFileSystem_base {
|
|
31
|
+
}
|
|
32
|
+
export {};
|
|
33
|
+
//# sourceMappingURL=blueprint-filesystem.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"blueprint-filesystem.d.ts","sourceRoot":"","sources":["../src/blueprint-filesystem.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAA;AAChC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AACpC,OAAO,KAAK,EAAE,kBAAkB,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAA;AAExF;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,wBAAwB;IACvC,QAAQ,CAAC,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,YAAY,GAAG,kBAAkB,CAAC,CAAA;IAC7F,QAAQ,CAAC,SAAS,EAAE,CAClB,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,KACZ,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,aAAa,GAAG,kBAAkB,CAAC,CAAA;IAC5D,QAAQ,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,kBAAkB,CAAC,CAAA;IAC7E,QAAQ,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,aAAa,GAAG,kBAAkB,CAAC,CAAA;IAC1F;;;OAGG;IACH,QAAQ,CAAC,cAAc,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,aAAa,GAAG,kBAAkB,CAAC,CAAA;IAClG,QAAQ,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,aAAa,GAAG,kBAAkB,CAAC,CAAA;IACzF,QAAQ,CAAC,OAAO,EAAE,CAChB,IAAI,EAAE,MAAM,KACT,MAAM,CAAC,MAAM,CAAC,SAAS,MAAM,EAAE,EAAE,YAAY,GAAG,kBAAkB,CAAC,CAAA;CACzE;;AAED,qBAAa,mBAAoB,SAAQ,wBAGC;CAAG"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"blueprint-filesystem.js","sourceRoot":"","sources":["../src/blueprint-filesystem.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAA;AAmChC,MAAM,OAAO,mBAAoB,SAAQ,OAAO,CAAC,OAAO,EAGrD,CAAC,qCAAqC,CAAC;CAAG"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { Effect } from "effect";
|
|
2
|
+
import type { ChangeSet } from "./change-set.js";
|
|
3
|
+
import type { BlueprintFileSystem } from "./blueprint-filesystem.js";
|
|
4
|
+
import type { Permission } from "./permissions.js";
|
|
5
|
+
import type { BlueprintError } from "./errors/index.js";
|
|
6
|
+
/**
|
|
7
|
+
* A `Blueprint` is a unit of project scaffolding. The CLI plans every blueprint by running its
|
|
8
|
+
* `plan` Effect to produce a `ChangeSet`, then either applies the union of changes (`build`,
|
|
9
|
+
* `remodel`) or compares them against the current project state (`inspect`).
|
|
10
|
+
*
|
|
11
|
+
* Blueprints **never** import `FileSystem` from `@effect/platform`. They use the
|
|
12
|
+
* `BlueprintFileSystem` service from `@projitect/blueprint`, which is gated by the `permissions`
|
|
13
|
+
* the blueprint declares. This is enforced by an ESLint rule.
|
|
14
|
+
*/
|
|
15
|
+
export interface Blueprint {
|
|
16
|
+
/** Stable kebab-case identifier, e.g. `pjt:gitignore:macos`. Used as ownership key in regions and merges. */
|
|
17
|
+
readonly id: string;
|
|
18
|
+
/** Semver string of the blueprint version. Used for change-tracking across upgrades. */
|
|
19
|
+
readonly version: string;
|
|
20
|
+
/** Human-readable, one-line description shown in `pjt inspect` output. */
|
|
21
|
+
readonly description?: string;
|
|
22
|
+
/** Declared capabilities. The CLI rejects FS operations not covered by this set. */
|
|
23
|
+
readonly permissions: readonly Permission[];
|
|
24
|
+
/** The Effect that produces this blueprint's change set when planned. */
|
|
25
|
+
readonly plan: Effect.Effect<ChangeSet, BlueprintError, BlueprintFileSystem>;
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=blueprint.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"blueprint.d.ts","sourceRoot":"","sources":["../src/blueprint.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AACpC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAChD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAA;AACpE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAClD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAA;AAEvD;;;;;;;;GAQG;AACH,MAAM,WAAW,SAAS;IACxB,6GAA6G;IAC7G,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;IACnB,wFAAwF;IACxF,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,0EAA0E;IAC1E,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAA;IAC7B,oFAAoF;IACpF,QAAQ,CAAC,WAAW,EAAE,SAAS,UAAU,EAAE,CAAA;IAC3C,yEAAyE;IACzE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,CAAC,SAAS,EAAE,cAAc,EAAE,mBAAmB,CAAC,CAAA;CAC7E"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"blueprint.js","sourceRoot":"","sources":["../src/blueprint.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
import { Reducer as ReducerLib, Schema } from "effect";
|
|
2
|
+
/**
|
|
3
|
+
* A `ChangeSet` is the data a blueprint produces when planning. The CLI reduces all blueprints'
|
|
4
|
+
* ChangeSets into a single project-wide plan, detects conflicts, and either applies it (`build`,
|
|
5
|
+
* `remodel`) or reports it (`inspect`).
|
|
6
|
+
*
|
|
7
|
+
* Each operation declares its **ownership mode** via its `_tag`:
|
|
8
|
+
*
|
|
9
|
+
* - `Region` — comment-fenced section inside a shared text file (e.g. `.gitignore`)
|
|
10
|
+
* - `Merge` — deep-merge intent for a structured file (e.g. `package.json`)
|
|
11
|
+
* - `Owned` — single blueprint owns the whole file content
|
|
12
|
+
* - `Seed` — written once at first build; never enforced after
|
|
13
|
+
*
|
|
14
|
+
* `Exec` is not a file ownership mode: it names a post-apply command that `build` and `remodel`
|
|
15
|
+
* run in a final phase, after every file operation has succeeded.
|
|
16
|
+
*/
|
|
17
|
+
export declare const RegionOp: Schema.TaggedStruct<"Region", {
|
|
18
|
+
readonly ownerId: Schema.String;
|
|
19
|
+
readonly path: Schema.String;
|
|
20
|
+
readonly commentPrefix: Schema.String;
|
|
21
|
+
/**
|
|
22
|
+
* Optional comment suffix for prefix/suffix-pair comment styles (HTML/MDX/XML). When omitted
|
|
23
|
+
* (the default), the marker terminates at end-of-line — that's the right shape for `#`, `//`,
|
|
24
|
+
* `--`, and other single-prefix comment syntaxes. Set to `" -->"` for HTML/markdown.
|
|
25
|
+
*/
|
|
26
|
+
readonly commentSuffix: Schema.optional<Schema.String>;
|
|
27
|
+
readonly content: Schema.String;
|
|
28
|
+
}>;
|
|
29
|
+
export declare const MergeOp: Schema.TaggedStruct<"Merge", {
|
|
30
|
+
readonly ownerId: Schema.String;
|
|
31
|
+
readonly path: Schema.String;
|
|
32
|
+
/** Dotted-path keys this blueprint owns inside the JSON tree (e.g. "scripts.pjt"). */
|
|
33
|
+
readonly ownedKeys: Schema.$Array<Schema.String>;
|
|
34
|
+
/** Partial JSON value to deep-merge under those keys. */
|
|
35
|
+
readonly value: Schema.Unknown;
|
|
36
|
+
}>;
|
|
37
|
+
export declare const OwnedOp: Schema.TaggedStruct<"Owned", {
|
|
38
|
+
readonly ownerId: Schema.String;
|
|
39
|
+
readonly path: Schema.String;
|
|
40
|
+
readonly content: Schema.String;
|
|
41
|
+
/**
|
|
42
|
+
* Directory this owner manages. When the file is removed, empty directories are pruned from the
|
|
43
|
+
* file's parent up to and including this one — never above it. Absent: no pruning.
|
|
44
|
+
*/
|
|
45
|
+
readonly ownedDir: Schema.optional<Schema.String>;
|
|
46
|
+
}>;
|
|
47
|
+
export declare const SeedOp: Schema.TaggedStruct<"Seed", {
|
|
48
|
+
readonly ownerId: Schema.String;
|
|
49
|
+
readonly path: Schema.String;
|
|
50
|
+
readonly content: Schema.String;
|
|
51
|
+
}>;
|
|
52
|
+
export declare const ExecOp: Schema.TaggedStruct<"Exec", {
|
|
53
|
+
readonly ownerId: Schema.String;
|
|
54
|
+
/** The command line to run from the project root; it must be covered by an `exec` permission. */
|
|
55
|
+
readonly command: Schema.String;
|
|
56
|
+
/**
|
|
57
|
+
* The command that reports whether `command` still has work to do. Carried in the plan for
|
|
58
|
+
* `pjt inspect`; build and remodel run only `command`, never `check`.
|
|
59
|
+
*/
|
|
60
|
+
readonly check: Schema.optional<Schema.String>;
|
|
61
|
+
}>;
|
|
62
|
+
export declare const Operation: Schema.Union<readonly [Schema.TaggedStruct<"Region", {
|
|
63
|
+
readonly ownerId: Schema.String;
|
|
64
|
+
readonly path: Schema.String;
|
|
65
|
+
readonly commentPrefix: Schema.String;
|
|
66
|
+
/**
|
|
67
|
+
* Optional comment suffix for prefix/suffix-pair comment styles (HTML/MDX/XML). When omitted
|
|
68
|
+
* (the default), the marker terminates at end-of-line — that's the right shape for `#`, `//`,
|
|
69
|
+
* `--`, and other single-prefix comment syntaxes. Set to `" -->"` for HTML/markdown.
|
|
70
|
+
*/
|
|
71
|
+
readonly commentSuffix: Schema.optional<Schema.String>;
|
|
72
|
+
readonly content: Schema.String;
|
|
73
|
+
}>, Schema.TaggedStruct<"Merge", {
|
|
74
|
+
readonly ownerId: Schema.String;
|
|
75
|
+
readonly path: Schema.String;
|
|
76
|
+
/** Dotted-path keys this blueprint owns inside the JSON tree (e.g. "scripts.pjt"). */
|
|
77
|
+
readonly ownedKeys: Schema.$Array<Schema.String>;
|
|
78
|
+
/** Partial JSON value to deep-merge under those keys. */
|
|
79
|
+
readonly value: Schema.Unknown;
|
|
80
|
+
}>, Schema.TaggedStruct<"Owned", {
|
|
81
|
+
readonly ownerId: Schema.String;
|
|
82
|
+
readonly path: Schema.String;
|
|
83
|
+
readonly content: Schema.String;
|
|
84
|
+
/**
|
|
85
|
+
* Directory this owner manages. When the file is removed, empty directories are pruned from the
|
|
86
|
+
* file's parent up to and including this one — never above it. Absent: no pruning.
|
|
87
|
+
*/
|
|
88
|
+
readonly ownedDir: Schema.optional<Schema.String>;
|
|
89
|
+
}>, Schema.TaggedStruct<"Seed", {
|
|
90
|
+
readonly ownerId: Schema.String;
|
|
91
|
+
readonly path: Schema.String;
|
|
92
|
+
readonly content: Schema.String;
|
|
93
|
+
}>, Schema.TaggedStruct<"Exec", {
|
|
94
|
+
readonly ownerId: Schema.String;
|
|
95
|
+
/** The command line to run from the project root; it must be covered by an `exec` permission. */
|
|
96
|
+
readonly command: Schema.String;
|
|
97
|
+
/**
|
|
98
|
+
* The command that reports whether `command` still has work to do. Carried in the plan for
|
|
99
|
+
* `pjt inspect`; build and remodel run only `command`, never `check`.
|
|
100
|
+
*/
|
|
101
|
+
readonly check: Schema.optional<Schema.String>;
|
|
102
|
+
}>]>;
|
|
103
|
+
export declare const ChangeSet: Schema.Struct<{
|
|
104
|
+
readonly operations: Schema.$Array<Schema.Union<readonly [Schema.TaggedStruct<"Region", {
|
|
105
|
+
readonly ownerId: Schema.String;
|
|
106
|
+
readonly path: Schema.String;
|
|
107
|
+
readonly commentPrefix: Schema.String;
|
|
108
|
+
/**
|
|
109
|
+
* Optional comment suffix for prefix/suffix-pair comment styles (HTML/MDX/XML). When omitted
|
|
110
|
+
* (the default), the marker terminates at end-of-line — that's the right shape for `#`, `//`,
|
|
111
|
+
* `--`, and other single-prefix comment syntaxes. Set to `" -->"` for HTML/markdown.
|
|
112
|
+
*/
|
|
113
|
+
readonly commentSuffix: Schema.optional<Schema.String>;
|
|
114
|
+
readonly content: Schema.String;
|
|
115
|
+
}>, Schema.TaggedStruct<"Merge", {
|
|
116
|
+
readonly ownerId: Schema.String;
|
|
117
|
+
readonly path: Schema.String;
|
|
118
|
+
/** Dotted-path keys this blueprint owns inside the JSON tree (e.g. "scripts.pjt"). */
|
|
119
|
+
readonly ownedKeys: Schema.$Array<Schema.String>;
|
|
120
|
+
/** Partial JSON value to deep-merge under those keys. */
|
|
121
|
+
readonly value: Schema.Unknown;
|
|
122
|
+
}>, Schema.TaggedStruct<"Owned", {
|
|
123
|
+
readonly ownerId: Schema.String;
|
|
124
|
+
readonly path: Schema.String;
|
|
125
|
+
readonly content: Schema.String;
|
|
126
|
+
/**
|
|
127
|
+
* Directory this owner manages. When the file is removed, empty directories are pruned from the
|
|
128
|
+
* file's parent up to and including this one — never above it. Absent: no pruning.
|
|
129
|
+
*/
|
|
130
|
+
readonly ownedDir: Schema.optional<Schema.String>;
|
|
131
|
+
}>, Schema.TaggedStruct<"Seed", {
|
|
132
|
+
readonly ownerId: Schema.String;
|
|
133
|
+
readonly path: Schema.String;
|
|
134
|
+
readonly content: Schema.String;
|
|
135
|
+
}>, Schema.TaggedStruct<"Exec", {
|
|
136
|
+
readonly ownerId: Schema.String;
|
|
137
|
+
/** The command line to run from the project root; it must be covered by an `exec` permission. */
|
|
138
|
+
readonly command: Schema.String;
|
|
139
|
+
/**
|
|
140
|
+
* The command that reports whether `command` still has work to do. Carried in the plan for
|
|
141
|
+
* `pjt inspect`; build and remodel run only `command`, never `check`.
|
|
142
|
+
*/
|
|
143
|
+
readonly check: Schema.optional<Schema.String>;
|
|
144
|
+
}>]>>;
|
|
145
|
+
}>;
|
|
146
|
+
export type RegionOp = typeof RegionOp.Type;
|
|
147
|
+
export type MergeOp = typeof MergeOp.Type;
|
|
148
|
+
export type OwnedOp = typeof OwnedOp.Type;
|
|
149
|
+
export type SeedOp = typeof SeedOp.Type;
|
|
150
|
+
export type ExecOp = typeof ExecOp.Type;
|
|
151
|
+
export type Operation = typeof Operation.Type;
|
|
152
|
+
export type ChangeSet = typeof ChangeSet.Type;
|
|
153
|
+
export declare const empty: ChangeSet;
|
|
154
|
+
export declare const concat: {
|
|
155
|
+
(that: ChangeSet): (self: ChangeSet) => ChangeSet;
|
|
156
|
+
(self: ChangeSet, that: ChangeSet): ChangeSet;
|
|
157
|
+
};
|
|
158
|
+
export declare const of: (...ops: readonly Operation[]) => ChangeSet;
|
|
159
|
+
/**
|
|
160
|
+
* `ChangeSet` is a monoid: {@link empty} is the identity and {@link concat} combines associatively
|
|
161
|
+
* (operation arrays append). Exposed as a `Reducer` so composite blueprints fold their parts'
|
|
162
|
+
* ChangeSets with `ChangeSet.Reducer.combineAll(parts)` — the same universal merge pattern the
|
|
163
|
+
* config cascade uses — instead of hand-rolling the concat.
|
|
164
|
+
*/
|
|
165
|
+
export declare const Reducer: ReducerLib.Reducer<ChangeSet>;
|
|
166
|
+
//# sourceMappingURL=change-set.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"change-set.d.ts","sourceRoot":"","sources":["../src/change-set.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AAGtD;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,QAAQ;;;;IAInB;;;;OAIG;;;EAGH,CAAA;AAEF,eAAO,MAAM,OAAO;;;IAGlB,sFAAsF;;IAEtF,yDAAyD;;EAEzD,CAAA;AAEF,eAAO,MAAM,OAAO;;;;IAIlB;;;OAGG;;EAEH,CAAA;AAEF,eAAO,MAAM,MAAM;;;;EAIjB,CAAA;AAEF,eAAO,MAAM,MAAM;;IAEjB,iGAAiG;;IAEjG;;;OAGG;;EAEH,CAAA;AAEF,eAAO,MAAM,SAAS;;;;IA9CpB;;;;OAIG;;;;;;IAQH,sFAAsF;;IAEtF,yDAAyD;;;;;;IAQzD;;;OAGG;;;;;;;;IAYH,iGAAiG;;IAEjG;;;OAGG;;IAI8E,CAAA;AAEnF,eAAO,MAAM,SAAS;;;;;QAhDpB;;;;WAIG;;;;;;QAQH,sFAAsF;;QAEtF,yDAAyD;;;;;;QAQzD;;;WAGG;;;;;;;;QAYH,iGAAiG;;QAEjG;;;WAGG;;;EAQH,CAAA;AAEF,MAAM,MAAM,QAAQ,GAAG,OAAO,QAAQ,CAAC,IAAI,CAAA;AAC3C,MAAM,MAAM,OAAO,GAAG,OAAO,OAAO,CAAC,IAAI,CAAA;AACzC,MAAM,MAAM,OAAO,GAAG,OAAO,OAAO,CAAC,IAAI,CAAA;AACzC,MAAM,MAAM,MAAM,GAAG,OAAO,MAAM,CAAC,IAAI,CAAA;AACvC,MAAM,MAAM,MAAM,GAAG,OAAO,MAAM,CAAC,IAAI,CAAA;AACvC,MAAM,MAAM,SAAS,GAAG,OAAO,SAAS,CAAC,IAAI,CAAA;AAC7C,MAAM,MAAM,SAAS,GAAG,OAAO,SAAS,CAAC,IAAI,CAAA;AAE7C,eAAO,MAAM,KAAK,EAAE,SAA8B,CAAA;AAElD,eAAO,MAAM,MAAM,EAAE;IACnB,CAAC,IAAI,EAAE,SAAS,GAAG,CAAC,IAAI,EAAE,SAAS,KAAK,SAAS,CAAA;IACjD,CAAC,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,SAAS,GAAG,SAAS,CAAA;CAM9C,CAAA;AAED,eAAO,MAAM,EAAE,GAAI,GAAG,KAAK,SAAS,SAAS,EAAE,KAAG,SAAkC,CAAA;AAEpF;;;;;GAKG;AACH,eAAO,MAAM,OAAO,EAAE,UAAU,CAAC,OAAO,CAAC,SAAS,CAGjD,CAAA"}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { Reducer as ReducerLib, Schema } from "effect";
|
|
2
|
+
import { dual } from "effect/Function";
|
|
3
|
+
/**
|
|
4
|
+
* A `ChangeSet` is the data a blueprint produces when planning. The CLI reduces all blueprints'
|
|
5
|
+
* ChangeSets into a single project-wide plan, detects conflicts, and either applies it (`build`,
|
|
6
|
+
* `remodel`) or reports it (`inspect`).
|
|
7
|
+
*
|
|
8
|
+
* Each operation declares its **ownership mode** via its `_tag`:
|
|
9
|
+
*
|
|
10
|
+
* - `Region` — comment-fenced section inside a shared text file (e.g. `.gitignore`)
|
|
11
|
+
* - `Merge` — deep-merge intent for a structured file (e.g. `package.json`)
|
|
12
|
+
* - `Owned` — single blueprint owns the whole file content
|
|
13
|
+
* - `Seed` — written once at first build; never enforced after
|
|
14
|
+
*
|
|
15
|
+
* `Exec` is not a file ownership mode: it names a post-apply command that `build` and `remodel`
|
|
16
|
+
* run in a final phase, after every file operation has succeeded.
|
|
17
|
+
*/
|
|
18
|
+
export const RegionOp = Schema.TaggedStruct("Region", {
|
|
19
|
+
ownerId: Schema.String,
|
|
20
|
+
path: Schema.String,
|
|
21
|
+
commentPrefix: Schema.String,
|
|
22
|
+
/**
|
|
23
|
+
* Optional comment suffix for prefix/suffix-pair comment styles (HTML/MDX/XML). When omitted
|
|
24
|
+
* (the default), the marker terminates at end-of-line — that's the right shape for `#`, `//`,
|
|
25
|
+
* `--`, and other single-prefix comment syntaxes. Set to `" -->"` for HTML/markdown.
|
|
26
|
+
*/
|
|
27
|
+
commentSuffix: Schema.optional(Schema.String),
|
|
28
|
+
content: Schema.String,
|
|
29
|
+
});
|
|
30
|
+
export const MergeOp = Schema.TaggedStruct("Merge", {
|
|
31
|
+
ownerId: Schema.String,
|
|
32
|
+
path: Schema.String,
|
|
33
|
+
/** Dotted-path keys this blueprint owns inside the JSON tree (e.g. "scripts.pjt"). */
|
|
34
|
+
ownedKeys: Schema.Array(Schema.String),
|
|
35
|
+
/** Partial JSON value to deep-merge under those keys. */
|
|
36
|
+
value: Schema.Unknown,
|
|
37
|
+
});
|
|
38
|
+
export const OwnedOp = Schema.TaggedStruct("Owned", {
|
|
39
|
+
ownerId: Schema.String,
|
|
40
|
+
path: Schema.String,
|
|
41
|
+
content: Schema.String,
|
|
42
|
+
/**
|
|
43
|
+
* Directory this owner manages. When the file is removed, empty directories are pruned from the
|
|
44
|
+
* file's parent up to and including this one — never above it. Absent: no pruning.
|
|
45
|
+
*/
|
|
46
|
+
ownedDir: Schema.optional(Schema.String),
|
|
47
|
+
});
|
|
48
|
+
export const SeedOp = Schema.TaggedStruct("Seed", {
|
|
49
|
+
ownerId: Schema.String,
|
|
50
|
+
path: Schema.String,
|
|
51
|
+
content: Schema.String,
|
|
52
|
+
});
|
|
53
|
+
export const ExecOp = Schema.TaggedStruct("Exec", {
|
|
54
|
+
ownerId: Schema.String,
|
|
55
|
+
/** The command line to run from the project root; it must be covered by an `exec` permission. */
|
|
56
|
+
command: Schema.String,
|
|
57
|
+
/**
|
|
58
|
+
* The command that reports whether `command` still has work to do. Carried in the plan for
|
|
59
|
+
* `pjt inspect`; build and remodel run only `command`, never `check`.
|
|
60
|
+
*/
|
|
61
|
+
check: Schema.optional(Schema.String),
|
|
62
|
+
});
|
|
63
|
+
export const Operation = Schema.Union([RegionOp, MergeOp, OwnedOp, SeedOp, ExecOp]);
|
|
64
|
+
export const ChangeSet = Schema.Struct({
|
|
65
|
+
operations: Schema.Array(Operation),
|
|
66
|
+
});
|
|
67
|
+
export const empty = { operations: [] };
|
|
68
|
+
export const concat = dual(2, (self, that) => ({
|
|
69
|
+
operations: [...self.operations, ...that.operations],
|
|
70
|
+
}));
|
|
71
|
+
export const of = (...ops) => ({ operations: ops });
|
|
72
|
+
/**
|
|
73
|
+
* `ChangeSet` is a monoid: {@link empty} is the identity and {@link concat} combines associatively
|
|
74
|
+
* (operation arrays append). Exposed as a `Reducer` so composite blueprints fold their parts'
|
|
75
|
+
* ChangeSets with `ChangeSet.Reducer.combineAll(parts)` — the same universal merge pattern the
|
|
76
|
+
* config cascade uses — instead of hand-rolling the concat.
|
|
77
|
+
*/
|
|
78
|
+
export const Reducer = ReducerLib.make((self, that) => concat(self, that), empty);
|
|
79
|
+
//# sourceMappingURL=change-set.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"change-set.js","sourceRoot":"","sources":["../src/change-set.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AACtD,OAAO,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAA;AAEtC;;;;;;;;;;;;;;GAcG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAG,MAAM,CAAC,YAAY,CAAC,QAAQ,EAAE;IACpD,OAAO,EAAE,MAAM,CAAC,MAAM;IACtB,IAAI,EAAE,MAAM,CAAC,MAAM;IACnB,aAAa,EAAE,MAAM,CAAC,MAAM;IAC5B;;;;OAIG;IACH,aAAa,EAAE,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC;IAC7C,OAAO,EAAE,MAAM,CAAC,MAAM;CACvB,CAAC,CAAA;AAEF,MAAM,CAAC,MAAM,OAAO,GAAG,MAAM,CAAC,YAAY,CAAC,OAAO,EAAE;IAClD,OAAO,EAAE,MAAM,CAAC,MAAM;IACtB,IAAI,EAAE,MAAM,CAAC,MAAM;IACnB,sFAAsF;IACtF,SAAS,EAAE,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC;IACtC,yDAAyD;IACzD,KAAK,EAAE,MAAM,CAAC,OAAO;CACtB,CAAC,CAAA;AAEF,MAAM,CAAC,MAAM,OAAO,GAAG,MAAM,CAAC,YAAY,CAAC,OAAO,EAAE;IAClD,OAAO,EAAE,MAAM,CAAC,MAAM;IACtB,IAAI,EAAE,MAAM,CAAC,MAAM;IACnB,OAAO,EAAE,MAAM,CAAC,MAAM;IACtB;;;OAGG;IACH,QAAQ,EAAE,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC;CACzC,CAAC,CAAA;AAEF,MAAM,CAAC,MAAM,MAAM,GAAG,MAAM,CAAC,YAAY,CAAC,MAAM,EAAE;IAChD,OAAO,EAAE,MAAM,CAAC,MAAM;IACtB,IAAI,EAAE,MAAM,CAAC,MAAM;IACnB,OAAO,EAAE,MAAM,CAAC,MAAM;CACvB,CAAC,CAAA;AAEF,MAAM,CAAC,MAAM,MAAM,GAAG,MAAM,CAAC,YAAY,CAAC,MAAM,EAAE;IAChD,OAAO,EAAE,MAAM,CAAC,MAAM;IACtB,iGAAiG;IACjG,OAAO,EAAE,MAAM,CAAC,MAAM;IACtB;;;OAGG;IACH,KAAK,EAAE,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC;CACtC,CAAC,CAAA;AAEF,MAAM,CAAC,MAAM,SAAS,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC,CAAA;AAEnF,MAAM,CAAC,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,CAAC;IACrC,UAAU,EAAE,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC;CACpC,CAAC,CAAA;AAUF,MAAM,CAAC,MAAM,KAAK,GAAc,EAAE,UAAU,EAAE,EAAE,EAAE,CAAA;AAElD,MAAM,CAAC,MAAM,MAAM,GAGf,IAAI,CACN,CAAC,EACD,CAAC,IAAe,EAAE,IAAe,EAAa,EAAE,CAAC,CAAC;IAChD,UAAU,EAAE,CAAC,GAAG,IAAI,CAAC,UAAU,EAAE,GAAG,IAAI,CAAC,UAAU,CAAC;CACrD,CAAC,CACH,CAAA;AAED,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,GAAyB,EAAa,EAAE,CAAC,CAAC,EAAE,UAAU,EAAE,GAAG,EAAE,CAAC,CAAA;AAEpF;;;;;GAKG;AACH,MAAM,CAAC,MAAM,OAAO,GAAkC,UAAU,CAAC,IAAI,CACnE,CAAC,IAAe,EAAE,IAAe,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,EACxD,KAAK,CACN,CAAA"}
|
package/dist/config.d.ts
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { Reducer, Schema } from "effect";
|
|
2
|
+
/**
|
|
3
|
+
* `ProjitectConfig` resolves through a four-layer reducer:
|
|
4
|
+
*
|
|
5
|
+
* defaults → env (`PJT_*`) → `.pjt.ts` `config:` field → CLI args
|
|
6
|
+
*
|
|
7
|
+
* Each layer's value is a partial config; layers later in the chain override earlier ones. The
|
|
8
|
+
* final resolved value is what every command consumes.
|
|
9
|
+
*/
|
|
10
|
+
export declare const ProjitectConfig: Schema.Struct<{
|
|
11
|
+
/** Absolute path to the project root. Defaults to the directory containing `.pjt.ts`. */
|
|
12
|
+
readonly projectRoot: Schema.String;
|
|
13
|
+
/** Path to the user's blueprint file, relative to projectRoot. Defaults to `.pjt.ts`. */
|
|
14
|
+
readonly blueprintFile: Schema.String;
|
|
15
|
+
/** Whether `build` requires a clean git working tree before destroying the project. Default true. */
|
|
16
|
+
readonly requireCleanGit: Schema.Boolean;
|
|
17
|
+
/** Whether to emit JSON output for `inspect` / `remodel` (machine-readable). Default false. */
|
|
18
|
+
readonly jsonOutput: Schema.Boolean;
|
|
19
|
+
/** Verbosity. 0=quiet, 1=normal, 2=verbose, 3=debug. */
|
|
20
|
+
readonly verbosity: Schema.Number;
|
|
21
|
+
}>;
|
|
22
|
+
export type ProjitectConfig = typeof ProjitectConfig.Type;
|
|
23
|
+
export declare const defaults: ProjitectConfig;
|
|
24
|
+
/**
|
|
25
|
+
* The config cascade as one algebraic fold: partial layers combine right-biased (a later layer's
|
|
26
|
+
* defined keys win), with the empty config `{}` as the identity — so a missing layer combines as a
|
|
27
|
+
* no-op. This is the universal "merge a list of things" pattern, named once rather than
|
|
28
|
+
* re-implemented per call site.
|
|
29
|
+
*/
|
|
30
|
+
export declare const Overrides: Reducer.Reducer<Partial<ProjitectConfig>>;
|
|
31
|
+
/**
|
|
32
|
+
* Reduce a list of partial overrides into a single resolved config, applying them left-to-right
|
|
33
|
+
* over the {@link defaults}. Later overrides win.
|
|
34
|
+
*/
|
|
35
|
+
export declare const resolve: (...overrides: readonly Partial<ProjitectConfig>[]) => ProjitectConfig;
|
|
36
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AAExC;;;;;;;GAOG;AACH,eAAO,MAAM,eAAe;IAC1B,yFAAyF;;IAEzF,yFAAyF;;IAEzF,qGAAqG;;IAErG,+FAA+F;;IAE/F,wDAAwD;;EAExD,CAAA;AAEF,MAAM,MAAM,eAAe,GAAG,OAAO,eAAe,CAAC,IAAI,CAAA;AAEzD,eAAO,MAAM,QAAQ,EAAE,eAMtB,CAAA;AAED;;;;;GAKG;AACH,eAAO,MAAM,SAAS,EAAE,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,eAAe,CAAC,CAEX,CAAA;AAErD;;;GAGG;AACH,eAAO,MAAM,OAAO,GAAI,GAAG,WAAW,SAAS,OAAO,CAAC,eAAe,CAAC,EAAE,KAAG,eAG1E,CAAA"}
|
package/dist/config.js
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { Reducer, Schema } from "effect";
|
|
2
|
+
/**
|
|
3
|
+
* `ProjitectConfig` resolves through a four-layer reducer:
|
|
4
|
+
*
|
|
5
|
+
* defaults → env (`PJT_*`) → `.pjt.ts` `config:` field → CLI args
|
|
6
|
+
*
|
|
7
|
+
* Each layer's value is a partial config; layers later in the chain override earlier ones. The
|
|
8
|
+
* final resolved value is what every command consumes.
|
|
9
|
+
*/
|
|
10
|
+
export const ProjitectConfig = Schema.Struct({
|
|
11
|
+
/** Absolute path to the project root. Defaults to the directory containing `.pjt.ts`. */
|
|
12
|
+
projectRoot: Schema.String,
|
|
13
|
+
/** Path to the user's blueprint file, relative to projectRoot. Defaults to `.pjt.ts`. */
|
|
14
|
+
blueprintFile: Schema.String,
|
|
15
|
+
/** Whether `build` requires a clean git working tree before destroying the project. Default true. */
|
|
16
|
+
requireCleanGit: Schema.Boolean,
|
|
17
|
+
/** Whether to emit JSON output for `inspect` / `remodel` (machine-readable). Default false. */
|
|
18
|
+
jsonOutput: Schema.Boolean,
|
|
19
|
+
/** Verbosity. 0=quiet, 1=normal, 2=verbose, 3=debug. */
|
|
20
|
+
verbosity: Schema.Number,
|
|
21
|
+
});
|
|
22
|
+
export const defaults = {
|
|
23
|
+
projectRoot: process.cwd(),
|
|
24
|
+
blueprintFile: ".pjt.ts",
|
|
25
|
+
requireCleanGit: true,
|
|
26
|
+
jsonOutput: false,
|
|
27
|
+
verbosity: 1,
|
|
28
|
+
};
|
|
29
|
+
/**
|
|
30
|
+
* The config cascade as one algebraic fold: partial layers combine right-biased (a later layer's
|
|
31
|
+
* defined keys win), with the empty config `{}` as the identity — so a missing layer combines as a
|
|
32
|
+
* no-op. This is the universal "merge a list of things" pattern, named once rather than
|
|
33
|
+
* re-implemented per call site.
|
|
34
|
+
*/
|
|
35
|
+
export const Overrides = Reducer.make((earlier, later) => ({ ...earlier, ...later }), {});
|
|
36
|
+
/**
|
|
37
|
+
* Reduce a list of partial overrides into a single resolved config, applying them left-to-right
|
|
38
|
+
* over the {@link defaults}. Later overrides win.
|
|
39
|
+
*/
|
|
40
|
+
export const resolve = (...overrides) => ({
|
|
41
|
+
...defaults,
|
|
42
|
+
...Overrides.combineAll(overrides),
|
|
43
|
+
});
|
|
44
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AAExC;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,MAAM,CAAC,MAAM,CAAC;IAC3C,yFAAyF;IACzF,WAAW,EAAE,MAAM,CAAC,MAAM;IAC1B,yFAAyF;IACzF,aAAa,EAAE,MAAM,CAAC,MAAM;IAC5B,qGAAqG;IACrG,eAAe,EAAE,MAAM,CAAC,OAAO;IAC/B,+FAA+F;IAC/F,UAAU,EAAE,MAAM,CAAC,OAAO;IAC1B,wDAAwD;IACxD,SAAS,EAAE,MAAM,CAAC,MAAM;CACzB,CAAC,CAAA;AAIF,MAAM,CAAC,MAAM,QAAQ,GAAoB;IACvC,WAAW,EAAE,OAAO,CAAC,GAAG,EAAE;IAC1B,aAAa,EAAE,SAAS;IACxB,eAAe,EAAE,IAAI;IACrB,UAAU,EAAE,KAAK;IACjB,SAAS,EAAE,CAAC;CACb,CAAA;AAED;;;;;GAKG;AACH,MAAM,CAAC,MAAM,SAAS,GAA8C,OAAO,CAAC,IAAI,CAE9E,CAAC,OAAO,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,OAAO,EAAE,GAAG,KAAK,EAAE,CAAC,EAAE,EAAE,CAAC,CAAA;AAErD;;;GAGG;AACH,MAAM,CAAC,MAAM,OAAO,GAAG,CAAC,GAAG,SAA8C,EAAmB,EAAE,CAAC,CAAC;IAC9F,GAAG,QAAQ;IACX,GAAG,SAAS,CAAC,UAAU,CAAC,SAAS,CAAC;CACnC,CAAC,CAAA"}
|