@projitect/cli-internals 0.0.0-stage → 1.0.1

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.
Files changed (173) hide show
  1. package/LICENSE +21 -0
  2. package/dist/applier.d.ts +12 -0
  3. package/dist/applier.d.ts.map +1 -0
  4. package/dist/applier.js +69 -0
  5. package/dist/applier.js.map +1 -0
  6. package/dist/commands/add.d.ts +34 -0
  7. package/dist/commands/add.d.ts.map +1 -0
  8. package/dist/commands/add.js +64 -0
  9. package/dist/commands/add.js.map +1 -0
  10. package/dist/commands/build.d.ts +39 -0
  11. package/dist/commands/build.d.ts.map +1 -0
  12. package/dist/commands/build.js +108 -0
  13. package/dist/commands/build.js.map +1 -0
  14. package/dist/commands/dispatch.d.ts +5 -0
  15. package/dist/commands/dispatch.d.ts.map +1 -0
  16. package/dist/commands/dispatch.js +211 -0
  17. package/dist/commands/dispatch.js.map +1 -0
  18. package/dist/commands/explain.d.ts +10 -0
  19. package/dist/commands/explain.d.ts.map +1 -0
  20. package/dist/commands/explain.js +46 -0
  21. package/dist/commands/explain.js.map +1 -0
  22. package/dist/commands/init.d.ts +34 -0
  23. package/dist/commands/init.d.ts.map +1 -0
  24. package/dist/commands/init.js +153 -0
  25. package/dist/commands/init.js.map +1 -0
  26. package/dist/commands/inspect-json.d.ts +51 -0
  27. package/dist/commands/inspect-json.d.ts.map +1 -0
  28. package/dist/commands/inspect-json.js +58 -0
  29. package/dist/commands/inspect-json.js.map +1 -0
  30. package/dist/commands/inspect.d.ts +41 -0
  31. package/dist/commands/inspect.d.ts.map +1 -0
  32. package/dist/commands/inspect.js +74 -0
  33. package/dist/commands/inspect.js.map +1 -0
  34. package/dist/commands/remodel.d.ts +22 -0
  35. package/dist/commands/remodel.d.ts.map +1 -0
  36. package/dist/commands/remodel.js +49 -0
  37. package/dist/commands/remodel.js.map +1 -0
  38. package/dist/config-cascade.d.ts +25 -0
  39. package/dist/config-cascade.d.ts.map +1 -0
  40. package/dist/config-cascade.js +45 -0
  41. package/dist/config-cascade.js.map +1 -0
  42. package/dist/differ.d.ts +31 -0
  43. package/dist/differ.d.ts.map +1 -0
  44. package/dist/differ.js +134 -0
  45. package/dist/differ.js.map +1 -0
  46. package/dist/edit-pjt.d.ts +19 -0
  47. package/dist/edit-pjt.d.ts.map +1 -0
  48. package/dist/edit-pjt.js +40 -0
  49. package/dist/edit-pjt.js.map +1 -0
  50. package/dist/filesystem-impl.d.ts +25 -0
  51. package/dist/filesystem-impl.d.ts.map +1 -0
  52. package/dist/filesystem-impl.js +153 -0
  53. package/dist/filesystem-impl.js.map +1 -0
  54. package/dist/git.d.ts +29 -0
  55. package/dist/git.d.ts.map +1 -0
  56. package/dist/git.js +63 -0
  57. package/dist/git.js.map +1 -0
  58. package/dist/index.d.ts +22 -0
  59. package/dist/index.d.ts.map +1 -0
  60. package/dist/index.js +21 -0
  61. package/dist/index.js.map +1 -0
  62. package/dist/ipc/client.d.ts +11 -0
  63. package/dist/ipc/client.d.ts.map +1 -0
  64. package/dist/ipc/client.js +45 -0
  65. package/dist/ipc/client.js.map +1 -0
  66. package/dist/ipc/index.d.ts +5 -0
  67. package/dist/ipc/index.d.ts.map +1 -0
  68. package/dist/ipc/index.js +5 -0
  69. package/dist/ipc/index.js.map +1 -0
  70. package/dist/ipc/protocol.d.ts +251 -0
  71. package/dist/ipc/protocol.d.ts.map +1 -0
  72. package/dist/ipc/protocol.js +41 -0
  73. package/dist/ipc/protocol.js.map +1 -0
  74. package/dist/ipc/server.d.ts +9 -0
  75. package/dist/ipc/server.d.ts.map +1 -0
  76. package/dist/ipc/server.js +23 -0
  77. package/dist/ipc/server.js.map +1 -0
  78. package/dist/ipc/transport.d.ts +12 -0
  79. package/dist/ipc/transport.d.ts.map +1 -0
  80. package/dist/ipc/transport.js +19 -0
  81. package/dist/ipc/transport.js.map +1 -0
  82. package/dist/loader.d.ts +45 -0
  83. package/dist/loader.d.ts.map +1 -0
  84. package/dist/loader.js +65 -0
  85. package/dist/loader.js.map +1 -0
  86. package/dist/lockfile.d.ts +22 -0
  87. package/dist/lockfile.d.ts.map +1 -0
  88. package/dist/lockfile.js +59 -0
  89. package/dist/lockfile.js.map +1 -0
  90. package/dist/permissions.d.ts +20 -0
  91. package/dist/permissions.d.ts.map +1 -0
  92. package/dist/permissions.js +86 -0
  93. package/dist/permissions.js.map +1 -0
  94. package/dist/plan.d.ts +278 -0
  95. package/dist/plan.d.ts.map +1 -0
  96. package/dist/plan.js +212 -0
  97. package/dist/plan.js.map +1 -0
  98. package/dist/platform/file-system.d.ts +3 -0
  99. package/dist/platform/file-system.d.ts.map +1 -0
  100. package/dist/platform/file-system.js +109 -0
  101. package/dist/platform/file-system.js.map +1 -0
  102. package/dist/platform/index.d.ts +17 -0
  103. package/dist/platform/index.d.ts.map +1 -0
  104. package/dist/platform/index.js +20 -0
  105. package/dist/platform/index.js.map +1 -0
  106. package/dist/platform/process-runner.d.ts +41 -0
  107. package/dist/platform/process-runner.d.ts.map +1 -0
  108. package/dist/platform/process-runner.js +120 -0
  109. package/dist/platform/process-runner.js.map +1 -0
  110. package/dist/platform/stdio.d.ts +9 -0
  111. package/dist/platform/stdio.d.ts.map +1 -0
  112. package/dist/platform/stdio.js +11 -0
  113. package/dist/platform/stdio.js.map +1 -0
  114. package/dist/platform/terminal.d.ts +3 -0
  115. package/dist/platform/terminal.d.ts.map +1 -0
  116. package/dist/platform/terminal.js +81 -0
  117. package/dist/platform/terminal.js.map +1 -0
  118. package/dist/pm.d.ts +36 -0
  119. package/dist/pm.d.ts.map +1 -0
  120. package/dist/pm.js +95 -0
  121. package/dist/pm.js.map +1 -0
  122. package/dist/post-apply.d.ts +20 -0
  123. package/dist/post-apply.d.ts.map +1 -0
  124. package/dist/post-apply.js +29 -0
  125. package/dist/post-apply.js.map +1 -0
  126. package/dist/project-file.d.ts +8 -0
  127. package/dist/project-file.d.ts.map +1 -0
  128. package/dist/project-file.js +12 -0
  129. package/dist/project-file.js.map +1 -0
  130. package/dist/region.d.ts +105 -0
  131. package/dist/region.d.ts.map +1 -0
  132. package/dist/region.js +94 -0
  133. package/dist/region.js.map +1 -0
  134. package/dist/remover.d.ts +16 -0
  135. package/dist/remover.d.ts.map +1 -0
  136. package/dist/remover.js +88 -0
  137. package/dist/remover.js.map +1 -0
  138. package/package.json +52 -3
  139. package/src/applier.ts +91 -0
  140. package/src/commands/add.ts +88 -0
  141. package/src/commands/build.ts +156 -0
  142. package/src/commands/dispatch.ts +345 -0
  143. package/src/commands/explain.ts +81 -0
  144. package/src/commands/init.ts +233 -0
  145. package/src/commands/inspect-json.ts +68 -0
  146. package/src/commands/inspect.ts +106 -0
  147. package/src/commands/remodel.ts +72 -0
  148. package/src/config-cascade.ts +60 -0
  149. package/src/differ.ts +188 -0
  150. package/src/edit-pjt.ts +56 -0
  151. package/src/filesystem-impl.ts +230 -0
  152. package/src/git.ts +87 -0
  153. package/src/index.ts +54 -0
  154. package/src/ipc/client.ts +108 -0
  155. package/src/ipc/index.ts +12 -0
  156. package/src/ipc/protocol.ts +48 -0
  157. package/src/ipc/server.ts +62 -0
  158. package/src/ipc/transport.ts +28 -0
  159. package/src/loader.ts +115 -0
  160. package/src/lockfile.ts +81 -0
  161. package/src/permissions.ts +106 -0
  162. package/src/plan.ts +459 -0
  163. package/src/platform/file-system.ts +155 -0
  164. package/src/platform/index.ts +26 -0
  165. package/src/platform/process-runner.ts +150 -0
  166. package/src/platform/stdio.ts +11 -0
  167. package/src/platform/terminal.ts +89 -0
  168. package/src/pm.ts +163 -0
  169. package/src/post-apply.ts +45 -0
  170. package/src/project-file.ts +15 -0
  171. package/src/region.ts +139 -0
  172. package/src/remover.ts +127 -0
  173. package/README.md +0 -3
package/dist/loader.js ADDED
@@ -0,0 +1,65 @@
1
+ import path from "node:path";
2
+ import { promises as fs } from "node:fs";
3
+ import { pathToFileURL } from "node:url";
4
+ import { Array, Effect, Match, Predicate } from "effect";
5
+ import { PredicateX, StructX } from "@nunofyobiz/effect-extras";
6
+ import { Errors } from "@projitect/core";
7
+ /**
8
+ * The user calls this in `.pjt.ts`:
9
+ *
10
+ * export default pjt({ blueprints: [...] })
11
+ *
12
+ * It's an identity tag — we only inspect the default export for the `_tag` marker so we can
13
+ * distinguish accidental other exports from a real projitect config.
14
+ */
15
+ export const pjt = (input) => ({
16
+ _tag: "ProjitectConfig",
17
+ blueprints: input.blueprints,
18
+ ...StructX.defined("config", input.config),
19
+ });
20
+ /** Type guard: did the user pass an Effect, or a literal array? */
21
+ export const isEffectTree = (v) => !Array.isArray(v);
22
+ /**
23
+ * Dynamic-import the user's `.pjt.ts` and return the typed default export.
24
+ *
25
+ * The user's file is TypeScript. On Node 23.6+ with `--experimental-strip-types`, the import
26
+ * succeeds natively. On older Node, the binary shim in `packages/projitect` registers `tsx` as
27
+ * a loader before reaching this function. Either way, by the time we get here, `import(path)`
28
+ * Just Works.
29
+ */
30
+ export const loadBlueprintFile = (params) => {
31
+ const { blueprintFile, projectRoot } = params;
32
+ const full = path.resolve(projectRoot, blueprintFile);
33
+ return Effect.gen(function* () {
34
+ const exists = yield* Effect.promise(() => fs.access(full).then(() => true, () => false));
35
+ if (!exists) {
36
+ return yield* new Errors.ConfigBlueprintFileNotFound({
37
+ id: "pjt.config.blueprint-file-not-found",
38
+ blueprintFile,
39
+ message: `No blueprint file found at ${full}. Run \`pjt init\` to create one.`,
40
+ });
41
+ }
42
+ const module_ = yield* Effect.tryPromise({
43
+ try: () => import(pathToFileURL(full).href),
44
+ catch: (e) => new Errors.LoaderImportFailed({
45
+ id: "pjt.loader.import-failed",
46
+ blueprintFile,
47
+ cause: e instanceof Error ? e.message : String(e),
48
+ message: `Failed to import ${blueprintFile}: ${e instanceof Error ? e.message : String(e)}`,
49
+ }),
50
+ });
51
+ const value = module_.default;
52
+ if (!isProjitectFile(value)) {
53
+ return yield* new Errors.LoaderInvalidDefaultExport({
54
+ id: "pjt.loader.invalid-default-export",
55
+ blueprintFile,
56
+ received: describe(value),
57
+ message: `${blueprintFile} must \`export default pjt({...})\`. Received ${describe(value)}.`,
58
+ });
59
+ }
60
+ return value;
61
+ });
62
+ };
63
+ const isProjitectFile = (v) => PredicateX.unsafeIsRecord(v) && v["_tag"] === "ProjitectConfig";
64
+ const describe = (v) => Match.value(v).pipe(Match.when(Predicate.isUndefined, () => "undefined"), Match.when(Predicate.isNull, () => "null"), Match.when(Array.isArray, () => "Array"), Match.when(PredicateX.unsafeIsRecord, () => 'object without `_tag: "ProjitectConfig"`'), Match.orElse((value) => typeof value));
65
+ //# sourceMappingURL=loader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loader.js","sourceRoot":"","sources":["../src/loader.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ import { Effect } from "effect";
2
+ import { BlueprintFileSystem, Errors, PjtLock } from "@projitect/core";
3
+ /**
4
+ * Read `.pjt.lock` from the project root of the provided `BlueprintFileSystem`. Returns `null` if the file doesn't exist (fresh project).
5
+ * Fails with `pjt.lock.parse-failed` on JSON or schema errors, `pjt.lock.version-mismatch` if
6
+ * the lockfile was written by a newer projitect.
7
+ */
8
+ export declare const readLockfile: Effect.Effect<PjtLock.PjtLock | null, Errors.LockParseFailed | Errors.LockVersionMismatch, BlueprintFileSystem>;
9
+ /**
10
+ * Write `.pjt.lock` through the provided `BlueprintFileSystem`. Always writes the current schema
11
+ * version.
12
+ */
13
+ export declare const writeLockfile: (params: {
14
+ readonly lock: PjtLock.PjtLock;
15
+ }) => Effect.Effect<void, Errors.FsWriteFailed | Errors.FsPermissionDenied, BlueprintFileSystem>;
16
+ /**
17
+ * Build the set of blueprint ids currently expected to be present from a lockfile. Used by the
18
+ * planner to compute which blueprints have left the tree (their ops will be turned into
19
+ * removals on next apply).
20
+ */
21
+ export declare const blueprintIds: (lock: PjtLock.PjtLock | null) => ReadonlySet<string>;
22
+ //# sourceMappingURL=lockfile.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lockfile.d.ts","sourceRoot":"","sources":["../src/lockfile.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAU,MAAM,QAAQ,CAAA;AACvC,OAAO,EAAE,mBAAmB,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAA;AAMtE;;;;GAIG;AACH,eAAO,MAAM,YAAY,EAAE,MAAM,CAAC,MAAM,CACtC,OAAO,CAAC,OAAO,GAAG,IAAI,EACtB,MAAM,CAAC,eAAe,GAAG,MAAM,CAAC,mBAAmB,EACnD,mBAAmB,CA6CnB,CAAA;AAEF;;;GAGG;AACH,eAAO,MAAM,aAAa,GAAI,QAAQ;IACpC,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC,OAAO,CAAA;CAC/B,KAAG,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,aAAa,GAAG,MAAM,CAAC,kBAAkB,EAAE,mBAAmB,CAIzF,CAAA;AAEJ;;;;GAIG;AACH,eAAO,MAAM,YAAY,GAAI,MAAM,OAAO,CAAC,OAAO,GAAG,IAAI,KAAG,WAAW,CAAC,MAAM,CAClB,CAAA"}
@@ -0,0 +1,59 @@
1
+ import { Effect, Schema } from "effect";
2
+ import { BlueprintFileSystem, Errors, PjtLock } from "@projitect/core";
3
+ import { readIfExists } from "./project-file.js";
4
+ const LOCKFILE_NAME = ".pjt.lock";
5
+ const CURRENT_VERSION = 1;
6
+ /**
7
+ * Read `.pjt.lock` from the project root of the provided `BlueprintFileSystem`. Returns `null` if the file doesn't exist (fresh project).
8
+ * Fails with `pjt.lock.parse-failed` on JSON or schema errors, `pjt.lock.version-mismatch` if
9
+ * the lockfile was written by a newer projitect.
10
+ */
11
+ export const readLockfile = Effect.gen(function* () {
12
+ const file = LOCKFILE_NAME;
13
+ const raw = yield* readIfExists(file);
14
+ if (raw === null) {
15
+ return null;
16
+ }
17
+ const parsed = yield* Effect.try({
18
+ try: () => JSON.parse(raw),
19
+ catch: (e) => new Errors.LockParseFailed({
20
+ id: "pjt.lock.parse-failed",
21
+ path: file,
22
+ cause: e instanceof Error ? e.message : String(e),
23
+ message: `Could not parse ${LOCKFILE_NAME}. The file is corrupted — delete it and rerun \`pjt remodel\` to rebuild.`,
24
+ }),
25
+ });
26
+ if (typeof parsed === "object" &&
27
+ parsed !== null &&
28
+ "version" in parsed &&
29
+ typeof parsed.version === "number" &&
30
+ parsed.version > CURRENT_VERSION) {
31
+ return yield* new Errors.LockVersionMismatch({
32
+ id: "pjt.lock.version-mismatch",
33
+ found: parsed.version,
34
+ expected: CURRENT_VERSION,
35
+ message: `${LOCKFILE_NAME} was written by a newer projitect (version ${parsed.version}). Upgrade the \`projitect\` devDep.`,
36
+ });
37
+ }
38
+ return yield* Schema.decodeUnknownEffect(PjtLock.PjtLock)(parsed).pipe(Effect.mapError((e) => new Errors.LockParseFailed({
39
+ id: "pjt.lock.parse-failed",
40
+ path: file,
41
+ cause: String(e),
42
+ message: `${LOCKFILE_NAME} does not match the expected schema. Delete it and rerun \`pjt remodel\` to rebuild.`,
43
+ })));
44
+ });
45
+ /**
46
+ * Write `.pjt.lock` through the provided `BlueprintFileSystem`. Always writes the current schema
47
+ * version.
48
+ */
49
+ export const writeLockfile = (params) => Effect.gen(function* () {
50
+ const fs = yield* BlueprintFileSystem;
51
+ yield* fs.writeFile(LOCKFILE_NAME, `${JSON.stringify(params.lock, null, 2)}\n`);
52
+ });
53
+ /**
54
+ * Build the set of blueprint ids currently expected to be present from a lockfile. Used by the
55
+ * planner to compute which blueprints have left the tree (their ops will be turned into
56
+ * removals on next apply).
57
+ */
58
+ export const blueprintIds = (lock) => new Set(lock === null ? [] : Object.keys(lock.blueprints));
59
+ //# sourceMappingURL=lockfile.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lockfile.js","sourceRoot":"","sources":["../src/lockfile.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ import type { Permission } from "@projitect/core";
2
+ export type FsOp = "read" | "write" | "exists" | "remove" | "removeEmptyDir" | "mkdir" | "listDir";
3
+ /**
4
+ * Returns `true` if the declared permissions cover the requested operation on the given path.
5
+ * `read`-permissioned globs cover `read | exists | listDir`. `write`-permissioned globs cover all
6
+ * write-side operations (`write | remove | removeEmptyDir | mkdir`) **and implicitly** the read operations on the
7
+ * same path — a blueprint that writes a file naturally needs to read it back for region updates.
8
+ */
9
+ export declare const isPermitted: (permissions: readonly Permission.Permission[], op: FsOp, path: string) => boolean;
10
+ /**
11
+ * Returns `true` if some declared `exec` permission names `command`.
12
+ *
13
+ * Decision: the permission's `command` matches by **exact string** against the full command line —
14
+ * no glob, no normalisation. A glob such as `pnpm *` would let a blueprint run any subcommand,
15
+ * which defeats declaring the permission; exact matching fails closed, so `pnpm lint:fix` is denied
16
+ * when only `pnpm lint` is declared. Relaxing to globs later is additive (the schema stores a plain
17
+ * string). `read`/`write` permissions never grant exec, and `exec` never grants file access.
18
+ */
19
+ export declare const isCommandPermitted: (permissions: readonly Permission.Permission[], command: string) => boolean;
20
+ //# sourceMappingURL=permissions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"permissions.d.ts","sourceRoot":"","sources":["../src/permissions.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA;AAkEjD,MAAM,MAAM,IAAI,GAAG,MAAM,GAAG,OAAO,GAAG,QAAQ,GAAG,QAAQ,GAAG,gBAAgB,GAAG,OAAO,GAAG,SAAS,CAAA;AAKlG;;;;;GAKG;AACH,eAAO,MAAM,WAAW,GACtB,aAAa,SAAS,UAAU,CAAC,UAAU,EAAE,EAC7C,IAAI,IAAI,EACR,MAAM,MAAM,KACX,OASF,CAAA;AAED;;;;;;;;GAQG;AACH,eAAO,MAAM,kBAAkB,GAC7B,aAAa,SAAS,UAAU,CAAC,UAAU,EAAE,EAC7C,SAAS,MAAM,KACd,OAAqF,CAAA"}
@@ -0,0 +1,86 @@
1
+ import { Array } from "effect";
2
+ /**
3
+ * Finds the `}` closing the group opened at `open`, and the top-level comma positions between them.
4
+ * Returns `undefined` when the group is unbalanced or has no top-level comma (so `{a}` stays literal).
5
+ */
6
+ const parseBraceGroup = (glob, open) => {
7
+ const commas = [];
8
+ let depth = 0;
9
+ for (let index = open; index < glob.length; index++) {
10
+ const ch = glob.charAt(index);
11
+ if (ch === "{") {
12
+ depth++;
13
+ }
14
+ else if (ch === "}") {
15
+ depth--;
16
+ if (depth === 0) {
17
+ return Array.isArrayNonEmpty(commas) ? { close: index, commas } : undefined;
18
+ }
19
+ }
20
+ else if (ch === "," && depth === 1) {
21
+ commas.push(index);
22
+ }
23
+ }
24
+ return undefined;
25
+ };
26
+ /**
27
+ * Minimal glob matcher for permission globs. Supports asterisk (any non-slash chars), double
28
+ * asterisk (any chars including slashes) and `{a,b}` alternation (alternatives may be empty or
29
+ * nested). A brace group needs a closing brace and at least one top-level comma; otherwise the
30
+ * braces and commas match literally. No character classes, `?`, negation or extglobs.
31
+ *
32
+ * Examples that match `src/(double-star)/*.{ts,tsx}`: `src/a.ts`, `src/foo/b.tsx`.
33
+ */
34
+ const globToPattern = (glob) => {
35
+ let pattern = "";
36
+ for (let index = 0; index < glob.length; index++) {
37
+ const ch = glob.charAt(index);
38
+ const group = ch === "{" ? parseBraceGroup(glob, index) : undefined;
39
+ if (group !== undefined) {
40
+ const bounds = [index, ...group.commas, group.close];
41
+ const alternatives = Array.zipWith(bounds, bounds.slice(1), (start, end) => globToPattern(glob.slice(start + 1, end)));
42
+ pattern = `${pattern}(?:${alternatives.join("|")})`;
43
+ index = group.close;
44
+ }
45
+ else if (ch === "*" && glob.charAt(index + 1) === "*") {
46
+ pattern = `${pattern}.*`;
47
+ index++;
48
+ }
49
+ else if (ch === "*") {
50
+ pattern = `${pattern}[^/]*`;
51
+ }
52
+ else if (".+^${}()|[]\\".includes(ch)) {
53
+ pattern = `${pattern}\\${ch}`;
54
+ }
55
+ else {
56
+ pattern = pattern + ch;
57
+ }
58
+ }
59
+ return pattern;
60
+ };
61
+ const globToRegex = (glob) => new RegExp(`^${globToPattern(glob)}$`, "u");
62
+ const matchesGlob = (path, glob) => globToRegex(glob).test(path);
63
+ const opCategory = (op) => op === "read" || op === "exists" || op === "listDir" ? "read" : "write";
64
+ /**
65
+ * Returns `true` if the declared permissions cover the requested operation on the given path.
66
+ * `read`-permissioned globs cover `read | exists | listDir`. `write`-permissioned globs cover all
67
+ * write-side operations (`write | remove | removeEmptyDir | mkdir`) **and implicitly** the read operations on the
68
+ * same path — a blueprint that writes a file naturally needs to read it back for region updates.
69
+ */
70
+ export const isPermitted = (permissions, op, path) => {
71
+ const category = opCategory(op);
72
+ // A permission grants the op when its glob matches and it's a write (writes imply reads) or
73
+ // it's a read covering a read-category op.
74
+ return Array.some(permissions, (p) => p.kind !== "exec" && matchesGlob(path, p.glob) && (p.kind === "write" || category === "read"));
75
+ };
76
+ /**
77
+ * Returns `true` if some declared `exec` permission names `command`.
78
+ *
79
+ * Decision: the permission's `command` matches by **exact string** against the full command line —
80
+ * no glob, no normalisation. A glob such as `pnpm *` would let a blueprint run any subcommand,
81
+ * which defeats declaring the permission; exact matching fails closed, so `pnpm lint:fix` is denied
82
+ * when only `pnpm lint` is declared. Relaxing to globs later is additive (the schema stores a plain
83
+ * string). `read`/`write` permissions never grant exec, and `exec` never grants file access.
84
+ */
85
+ export const isCommandPermitted = (permissions, command) => Array.some(permissions, (p) => p.kind === "exec" && p.command === command);
86
+ //# sourceMappingURL=permissions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"permissions.js","sourceRoot":"","sources":["../src/permissions.ts"],"names":[],"mappings":"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"}
package/dist/plan.d.ts ADDED
@@ -0,0 +1,278 @@
1
+ import { Data, Effect } from "effect";
2
+ import { Errors, PjtLock } from "@projitect/core";
3
+ import type { Blueprint, Permission } from "@projitect/core";
4
+ import type { DirectoryBlueprint } from "@projitect/blueprint";
5
+ export type FilePlan = Data.TaggedEnum<{
6
+ readonly Region: {
7
+ readonly path: string;
8
+ readonly commentPrefix: string;
9
+ /** Optional closing delimiter for HTML/MDX comments. Empty for `#`/`//`-style regions. */
10
+ readonly commentSuffix: string;
11
+ readonly regions: readonly {
12
+ readonly ownerId: string;
13
+ readonly content: string;
14
+ }[];
15
+ };
16
+ readonly Merge: {
17
+ readonly path: string;
18
+ readonly value: unknown;
19
+ /** Dotted-key → ownerId. Conflicts on identical keys are caught at reduction time. */
20
+ readonly ownership: ReadonlyMap<string, string>;
21
+ };
22
+ readonly Owned: {
23
+ readonly path: string;
24
+ readonly ownerId: string;
25
+ readonly content: string;
26
+ };
27
+ readonly Seed: {
28
+ readonly path: string;
29
+ readonly ownerId: string;
30
+ readonly content: string;
31
+ };
32
+ }>;
33
+ export declare const FilePlan: {
34
+ readonly Region: Data.TaggedEnum.ConstructorFrom<{
35
+ readonly _tag: "Region";
36
+ readonly path: string;
37
+ readonly commentPrefix: string;
38
+ readonly commentSuffix: string;
39
+ readonly regions: readonly {
40
+ readonly ownerId: string;
41
+ readonly content: string;
42
+ }[];
43
+ }, "_tag">;
44
+ readonly Merge: Data.TaggedEnum.ConstructorFrom<{
45
+ readonly _tag: "Merge";
46
+ readonly path: string;
47
+ readonly value: unknown;
48
+ readonly ownership: ReadonlyMap<string, string>;
49
+ }, "_tag">;
50
+ readonly Owned: Data.TaggedEnum.ConstructorFrom<{
51
+ readonly _tag: "Owned";
52
+ readonly path: string;
53
+ readonly ownerId: string;
54
+ readonly content: string;
55
+ }, "_tag">;
56
+ readonly Seed: Data.TaggedEnum.ConstructorFrom<{
57
+ readonly _tag: "Seed";
58
+ readonly path: string;
59
+ readonly ownerId: string;
60
+ readonly content: string;
61
+ }, "_tag">;
62
+ readonly $is: <Tag extends "Region" | "Merge" | "Owned" | "Seed">(tag: Tag) => (u: unknown) => u is Extract<{
63
+ readonly _tag: "Region";
64
+ readonly path: string;
65
+ readonly commentPrefix: string;
66
+ readonly commentSuffix: string;
67
+ readonly regions: readonly {
68
+ readonly ownerId: string;
69
+ readonly content: string;
70
+ }[];
71
+ }, {
72
+ readonly _tag: Tag;
73
+ }> | Extract<{
74
+ readonly _tag: "Merge";
75
+ readonly path: string;
76
+ readonly value: unknown;
77
+ readonly ownership: ReadonlyMap<string, string>;
78
+ }, {
79
+ readonly _tag: Tag;
80
+ }> | Extract<{
81
+ readonly _tag: "Owned";
82
+ readonly path: string;
83
+ readonly ownerId: string;
84
+ readonly content: string;
85
+ }, {
86
+ readonly _tag: Tag;
87
+ }> | Extract<{
88
+ readonly _tag: "Seed";
89
+ readonly path: string;
90
+ readonly ownerId: string;
91
+ readonly content: string;
92
+ }, {
93
+ readonly _tag: Tag;
94
+ }>;
95
+ readonly $match: {
96
+ <Cases extends {
97
+ readonly Region: (args: {
98
+ readonly _tag: "Region";
99
+ readonly path: string;
100
+ readonly commentPrefix: string;
101
+ readonly commentSuffix: string;
102
+ readonly regions: readonly {
103
+ readonly ownerId: string;
104
+ readonly content: string;
105
+ }[];
106
+ }) => any;
107
+ readonly Merge: (args: {
108
+ readonly _tag: "Merge";
109
+ readonly path: string;
110
+ readonly value: unknown;
111
+ readonly ownership: ReadonlyMap<string, string>;
112
+ }) => any;
113
+ readonly Owned: (args: {
114
+ readonly _tag: "Owned";
115
+ readonly path: string;
116
+ readonly ownerId: string;
117
+ readonly content: string;
118
+ }) => any;
119
+ readonly Seed: (args: {
120
+ readonly _tag: "Seed";
121
+ readonly path: string;
122
+ readonly ownerId: string;
123
+ readonly content: string;
124
+ }) => any;
125
+ }>(cases: Cases): (value: {
126
+ readonly _tag: "Region";
127
+ readonly path: string;
128
+ readonly commentPrefix: string;
129
+ readonly commentSuffix: string;
130
+ readonly regions: readonly {
131
+ readonly ownerId: string;
132
+ readonly content: string;
133
+ }[];
134
+ } | {
135
+ readonly _tag: "Merge";
136
+ readonly path: string;
137
+ readonly value: unknown;
138
+ readonly ownership: ReadonlyMap<string, string>;
139
+ } | {
140
+ readonly _tag: "Owned";
141
+ readonly path: string;
142
+ readonly ownerId: string;
143
+ readonly content: string;
144
+ } | {
145
+ readonly _tag: "Seed";
146
+ readonly path: string;
147
+ readonly ownerId: string;
148
+ readonly content: string;
149
+ }) => import("effect/Unify").Unify<ReturnType<Cases["Region" | "Merge" | "Owned" | "Seed"]>>;
150
+ <Cases extends {
151
+ readonly Region: (args: {
152
+ readonly _tag: "Region";
153
+ readonly path: string;
154
+ readonly commentPrefix: string;
155
+ readonly commentSuffix: string;
156
+ readonly regions: readonly {
157
+ readonly ownerId: string;
158
+ readonly content: string;
159
+ }[];
160
+ }) => any;
161
+ readonly Merge: (args: {
162
+ readonly _tag: "Merge";
163
+ readonly path: string;
164
+ readonly value: unknown;
165
+ readonly ownership: ReadonlyMap<string, string>;
166
+ }) => any;
167
+ readonly Owned: (args: {
168
+ readonly _tag: "Owned";
169
+ readonly path: string;
170
+ readonly ownerId: string;
171
+ readonly content: string;
172
+ }) => any;
173
+ readonly Seed: (args: {
174
+ readonly _tag: "Seed";
175
+ readonly path: string;
176
+ readonly ownerId: string;
177
+ readonly content: string;
178
+ }) => any;
179
+ }>(value: {
180
+ readonly _tag: "Region";
181
+ readonly path: string;
182
+ readonly commentPrefix: string;
183
+ readonly commentSuffix: string;
184
+ readonly regions: readonly {
185
+ readonly ownerId: string;
186
+ readonly content: string;
187
+ }[];
188
+ } | {
189
+ readonly _tag: "Merge";
190
+ readonly path: string;
191
+ readonly value: unknown;
192
+ readonly ownership: ReadonlyMap<string, string>;
193
+ } | {
194
+ readonly _tag: "Owned";
195
+ readonly path: string;
196
+ readonly ownerId: string;
197
+ readonly content: string;
198
+ } | {
199
+ readonly _tag: "Seed";
200
+ readonly path: string;
201
+ readonly ownerId: string;
202
+ readonly content: string;
203
+ }, cases: Cases): import("effect/Unify").Unify<ReturnType<Cases["Region" | "Merge" | "Owned" | "Seed"]>>;
204
+ };
205
+ };
206
+ export type RegionPlanFile = Extract<FilePlan, {
207
+ readonly _tag: "Region";
208
+ }>;
209
+ export type MergePlanFile = Extract<FilePlan, {
210
+ readonly _tag: "Merge";
211
+ }>;
212
+ export type OwnedPlanFile = Extract<FilePlan, {
213
+ readonly _tag: "Owned";
214
+ }>;
215
+ export type SeedPlanFile = Extract<FilePlan, {
216
+ readonly _tag: "Seed";
217
+ }>;
218
+ /**
219
+ * A post-apply command declared by a blueprint's `Exec` op, with the declaring blueprint's
220
+ * permissions so the final phase can check it before anything starts. Listed in tree order, then
221
+ * op order; duplicates are kept here and collapsed when the phase runs.
222
+ */
223
+ export interface PlannedCommand {
224
+ readonly ownerId: string;
225
+ readonly command: string;
226
+ /** The op's check command; carried for `pjt inspect`, never run by build or remodel. */
227
+ readonly check?: string;
228
+ readonly permissions: readonly Permission.Permission[];
229
+ }
230
+ export interface ProjectPlan {
231
+ readonly files: readonly FilePlan[];
232
+ readonly commands: readonly PlannedCommand[];
233
+ }
234
+ /**
235
+ * Per-blueprint lockfile entries, derived from the same ops that fed the plan. Written to
236
+ * `.pjt.lock` after every successful apply.
237
+ */
238
+ export type ByBlueprint = Readonly<Record<string, PjtLock.BlueprintLockEntry>>;
239
+ /**
240
+ * Removal computed by diffing the previous lockfile against the current `byBlueprint` map.
241
+ * A blueprint that appears in the previous lockfile but not in the current map is "left the
242
+ * tree"; each of its prior operations becomes a removal target.
243
+ */
244
+ export interface UpgradeRecord {
245
+ readonly blueprintId: string;
246
+ readonly from: string;
247
+ readonly to: string;
248
+ }
249
+ type RawTree = readonly (Blueprint.Blueprint | DirectoryBlueprint)[];
250
+ /**
251
+ * Build the project plan by running every blueprint, collecting their ops, reducing them with
252
+ * conflict detection, and producing the per-blueprint lockfile entries.
253
+ */
254
+ export declare const buildPlan: (params: {
255
+ readonly tree: RawTree;
256
+ readonly projectRoot: string;
257
+ }) => Effect.Effect<{
258
+ readonly plan: ProjectPlan;
259
+ readonly byBlueprint: ByBlueprint;
260
+ }, Errors.ProjitectError>;
261
+ /**
262
+ * Diff the previous lockfile against the current blueprint set. Returns:
263
+ * - `removals`: ops from blueprints present in the lockfile but absent from the current tree,
264
+ * plus owned files a still-present blueprint no longer ships (a new version dropping a file).
265
+ * The applier deletes the matching regions / merge keys / owned files in a follow-up step.
266
+ * - `upgrades`: blueprints present in both, with different versions. Informational only — the
267
+ * actual content is regenerated from the current blueprint, so applying handles upgrade
268
+ * content automatically; this list is for `inspect`'s human output.
269
+ */
270
+ export declare const diffLockfile: (params: {
271
+ readonly previous: PjtLock.PjtLock | null;
272
+ readonly current: ByBlueprint;
273
+ }) => {
274
+ readonly removals: readonly PjtLock.LockOperation[];
275
+ readonly upgrades: readonly UpgradeRecord[];
276
+ };
277
+ export {};
278
+ //# sourceMappingURL=plan.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plan.d.ts","sourceRoot":"","sources":["../src/plan.ts"],"names":[],"mappings":"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"}