@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.
- package/LICENSE +21 -0
- package/dist/applier.d.ts +12 -0
- package/dist/applier.d.ts.map +1 -0
- package/dist/applier.js +69 -0
- package/dist/applier.js.map +1 -0
- package/dist/commands/add.d.ts +34 -0
- package/dist/commands/add.d.ts.map +1 -0
- package/dist/commands/add.js +64 -0
- package/dist/commands/add.js.map +1 -0
- package/dist/commands/build.d.ts +39 -0
- package/dist/commands/build.d.ts.map +1 -0
- package/dist/commands/build.js +108 -0
- package/dist/commands/build.js.map +1 -0
- package/dist/commands/dispatch.d.ts +5 -0
- package/dist/commands/dispatch.d.ts.map +1 -0
- package/dist/commands/dispatch.js +211 -0
- package/dist/commands/dispatch.js.map +1 -0
- package/dist/commands/explain.d.ts +10 -0
- package/dist/commands/explain.d.ts.map +1 -0
- package/dist/commands/explain.js +46 -0
- package/dist/commands/explain.js.map +1 -0
- package/dist/commands/init.d.ts +34 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +153 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/inspect-json.d.ts +51 -0
- package/dist/commands/inspect-json.d.ts.map +1 -0
- package/dist/commands/inspect-json.js +58 -0
- package/dist/commands/inspect-json.js.map +1 -0
- package/dist/commands/inspect.d.ts +41 -0
- package/dist/commands/inspect.d.ts.map +1 -0
- package/dist/commands/inspect.js +74 -0
- package/dist/commands/inspect.js.map +1 -0
- package/dist/commands/remodel.d.ts +22 -0
- package/dist/commands/remodel.d.ts.map +1 -0
- package/dist/commands/remodel.js +49 -0
- package/dist/commands/remodel.js.map +1 -0
- package/dist/config-cascade.d.ts +25 -0
- package/dist/config-cascade.d.ts.map +1 -0
- package/dist/config-cascade.js +45 -0
- package/dist/config-cascade.js.map +1 -0
- package/dist/differ.d.ts +31 -0
- package/dist/differ.d.ts.map +1 -0
- package/dist/differ.js +134 -0
- package/dist/differ.js.map +1 -0
- package/dist/edit-pjt.d.ts +19 -0
- package/dist/edit-pjt.d.ts.map +1 -0
- package/dist/edit-pjt.js +40 -0
- package/dist/edit-pjt.js.map +1 -0
- package/dist/filesystem-impl.d.ts +25 -0
- package/dist/filesystem-impl.d.ts.map +1 -0
- package/dist/filesystem-impl.js +153 -0
- package/dist/filesystem-impl.js.map +1 -0
- package/dist/git.d.ts +29 -0
- package/dist/git.d.ts.map +1 -0
- package/dist/git.js +63 -0
- package/dist/git.js.map +1 -0
- package/dist/index.d.ts +22 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +21 -0
- package/dist/index.js.map +1 -0
- package/dist/ipc/client.d.ts +11 -0
- package/dist/ipc/client.d.ts.map +1 -0
- package/dist/ipc/client.js +45 -0
- package/dist/ipc/client.js.map +1 -0
- package/dist/ipc/index.d.ts +5 -0
- package/dist/ipc/index.d.ts.map +1 -0
- package/dist/ipc/index.js +5 -0
- package/dist/ipc/index.js.map +1 -0
- package/dist/ipc/protocol.d.ts +251 -0
- package/dist/ipc/protocol.d.ts.map +1 -0
- package/dist/ipc/protocol.js +41 -0
- package/dist/ipc/protocol.js.map +1 -0
- package/dist/ipc/server.d.ts +9 -0
- package/dist/ipc/server.d.ts.map +1 -0
- package/dist/ipc/server.js +23 -0
- package/dist/ipc/server.js.map +1 -0
- package/dist/ipc/transport.d.ts +12 -0
- package/dist/ipc/transport.d.ts.map +1 -0
- package/dist/ipc/transport.js +19 -0
- package/dist/ipc/transport.js.map +1 -0
- package/dist/loader.d.ts +45 -0
- package/dist/loader.d.ts.map +1 -0
- package/dist/loader.js +65 -0
- package/dist/loader.js.map +1 -0
- package/dist/lockfile.d.ts +22 -0
- package/dist/lockfile.d.ts.map +1 -0
- package/dist/lockfile.js +59 -0
- package/dist/lockfile.js.map +1 -0
- package/dist/permissions.d.ts +20 -0
- package/dist/permissions.d.ts.map +1 -0
- package/dist/permissions.js +86 -0
- package/dist/permissions.js.map +1 -0
- package/dist/plan.d.ts +278 -0
- package/dist/plan.d.ts.map +1 -0
- package/dist/plan.js +212 -0
- package/dist/plan.js.map +1 -0
- package/dist/platform/file-system.d.ts +3 -0
- package/dist/platform/file-system.d.ts.map +1 -0
- package/dist/platform/file-system.js +109 -0
- package/dist/platform/file-system.js.map +1 -0
- package/dist/platform/index.d.ts +17 -0
- package/dist/platform/index.d.ts.map +1 -0
- package/dist/platform/index.js +20 -0
- package/dist/platform/index.js.map +1 -0
- package/dist/platform/process-runner.d.ts +41 -0
- package/dist/platform/process-runner.d.ts.map +1 -0
- package/dist/platform/process-runner.js +120 -0
- package/dist/platform/process-runner.js.map +1 -0
- package/dist/platform/stdio.d.ts +9 -0
- package/dist/platform/stdio.d.ts.map +1 -0
- package/dist/platform/stdio.js +11 -0
- package/dist/platform/stdio.js.map +1 -0
- package/dist/platform/terminal.d.ts +3 -0
- package/dist/platform/terminal.d.ts.map +1 -0
- package/dist/platform/terminal.js +81 -0
- package/dist/platform/terminal.js.map +1 -0
- package/dist/pm.d.ts +36 -0
- package/dist/pm.d.ts.map +1 -0
- package/dist/pm.js +95 -0
- package/dist/pm.js.map +1 -0
- package/dist/post-apply.d.ts +20 -0
- package/dist/post-apply.d.ts.map +1 -0
- package/dist/post-apply.js +29 -0
- package/dist/post-apply.js.map +1 -0
- package/dist/project-file.d.ts +8 -0
- package/dist/project-file.d.ts.map +1 -0
- package/dist/project-file.js +12 -0
- package/dist/project-file.js.map +1 -0
- package/dist/region.d.ts +105 -0
- package/dist/region.d.ts.map +1 -0
- package/dist/region.js +94 -0
- package/dist/region.js.map +1 -0
- package/dist/remover.d.ts +16 -0
- package/dist/remover.d.ts.map +1 -0
- package/dist/remover.js +88 -0
- package/dist/remover.js.map +1 -0
- package/package.json +52 -3
- package/src/applier.ts +91 -0
- package/src/commands/add.ts +88 -0
- package/src/commands/build.ts +156 -0
- package/src/commands/dispatch.ts +345 -0
- package/src/commands/explain.ts +81 -0
- package/src/commands/init.ts +233 -0
- package/src/commands/inspect-json.ts +68 -0
- package/src/commands/inspect.ts +106 -0
- package/src/commands/remodel.ts +72 -0
- package/src/config-cascade.ts +60 -0
- package/src/differ.ts +188 -0
- package/src/edit-pjt.ts +56 -0
- package/src/filesystem-impl.ts +230 -0
- package/src/git.ts +87 -0
- package/src/index.ts +54 -0
- package/src/ipc/client.ts +108 -0
- package/src/ipc/index.ts +12 -0
- package/src/ipc/protocol.ts +48 -0
- package/src/ipc/server.ts +62 -0
- package/src/ipc/transport.ts +28 -0
- package/src/loader.ts +115 -0
- package/src/lockfile.ts +81 -0
- package/src/permissions.ts +106 -0
- package/src/plan.ts +459 -0
- package/src/platform/file-system.ts +155 -0
- package/src/platform/index.ts +26 -0
- package/src/platform/process-runner.ts +150 -0
- package/src/platform/stdio.ts +11 -0
- package/src/platform/terminal.ts +89 -0
- package/src/pm.ts +163 -0
- package/src/post-apply.ts +45 -0
- package/src/project-file.ts +15 -0
- package/src/region.ts +139 -0
- package/src/remover.ts +127 -0
- package/README.md +0 -3
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Effect } from "effect";
|
|
2
|
+
/**
|
|
3
|
+
* `pjt explain <id>` — print a short description of an error id, with a link to the docs page.
|
|
4
|
+
* The full content lives on the marketing site at `/errors/<id>`; this CLI gives the basics
|
|
5
|
+
* without a network call.
|
|
6
|
+
*/
|
|
7
|
+
export declare const explain: (params: {
|
|
8
|
+
readonly errorId: string;
|
|
9
|
+
}) => Effect.Effect<string>;
|
|
10
|
+
//# sourceMappingURL=explain.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"explain.d.ts","sourceRoot":"","sources":["../../src/commands/explain.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAkB,MAAM,QAAQ,CAAA;AAK/C;;;;GAIG;AACH,eAAO,MAAM,OAAO,GAAI,QAAQ;IAAE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;CAAE,KAAG,MAAM,CAAC,MAAM,CAAC,MAAM,CAOhF,CAAA"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { Effect, Option, Schema } from "effect";
|
|
2
|
+
import { Errors } from "@projitect/core";
|
|
3
|
+
const ErrorId = Schema.Literals(Errors.ERROR_IDS);
|
|
4
|
+
/**
|
|
5
|
+
* `pjt explain <id>` — print a short description of an error id, with a link to the docs page.
|
|
6
|
+
* The full content lives on the marketing site at `/errors/<id>`; this CLI gives the basics
|
|
7
|
+
* without a network call.
|
|
8
|
+
*/
|
|
9
|
+
export const explain = (params) => Effect.sync(() => Option.match(Schema.decodeUnknownOption(ErrorId)(params.errorId), {
|
|
10
|
+
onNone: () => `Unknown error id: ${params.errorId}\nSee https://projitect.dev/errors for the full registry.`,
|
|
11
|
+
onSome: (id) => `${id}\n${ERROR_BLURBS[id]}\nMore at: ${Errors.docsUrl(id)}`,
|
|
12
|
+
}));
|
|
13
|
+
const ERROR_BLURBS = {
|
|
14
|
+
"pjt.fs.permission-denied": "A blueprint attempted a filesystem operation outside its declared permissions. Check the blueprint's `permissions` array.",
|
|
15
|
+
"pjt.fs.read-failed": "A read operation failed at the OS level (typically ENOENT or EACCES). The cause is printed alongside.",
|
|
16
|
+
"pjt.fs.write-failed": "A write operation failed at the OS level. The cause is printed alongside.",
|
|
17
|
+
"pjt.loader.import-failed": "The `.pjt.ts` file could not be imported. Check for syntax errors or missing dependencies.",
|
|
18
|
+
"pjt.loader.invalid-default-export": "`.pjt.ts` must `export default pjt({...})`. Found a different shape.",
|
|
19
|
+
"pjt.config.invalid": "A config value failed schema validation. The offending field and source layer are reported.",
|
|
20
|
+
"pjt.config.blueprint-file-not-found": "No `.pjt.ts` at the project root. Run `pjt init` to create one.",
|
|
21
|
+
"pjt.plan.conflict-region": "Two blueprints share the same `ownerId` for a region in the same file. Pick distinct ids.",
|
|
22
|
+
"pjt.plan.conflict-merge": "Two blueprints claim the same JSON key in the same file. Coordinate ownership.",
|
|
23
|
+
"pjt.plan.conflict-owned": "Two blueprints both claim full ownership of one file. Only one `ownFile` per path is allowed.",
|
|
24
|
+
"pjt.skills.invalid-path": "A skill name, target root or file path is empty, absolute, or tries to leave the skills directory — or a skill has no `SKILL.md`.",
|
|
25
|
+
"pjt.region.missing-end": "A region start marker was found without a matching end marker. The file has been hand-edited and the closing marker removed.",
|
|
26
|
+
"pjt.region.duplicate": "Multiple start markers for the same region in one file. Hand-edited?",
|
|
27
|
+
"pjt.apply.dirty-git": "`build` requires a clean git working tree. Commit or stash first, then retry.",
|
|
28
|
+
"pjt.init.git-missing": "`pjt init` requires a git repository. Run `git init` first, or rerun with --yes.",
|
|
29
|
+
"pjt.init.package-json-missing": "`pjt init` requires a `package.json`. Run `npm init -y` first, or rerun with --yes.",
|
|
30
|
+
"pjt.drift.detected": "`pjt inspect` exits nonzero when the project drifts from its blueprints. Run `pjt remodel` to sync.",
|
|
31
|
+
"pjt.lock.parse-failed": "`.pjt.lock` is corrupted or doesn't match the expected schema. Delete it and rerun `pjt remodel` to rebuild.",
|
|
32
|
+
"pjt.lock.version-mismatch": "`.pjt.lock` was written by a newer projitect than the one currently installed. Upgrade the `projitect` devDep.",
|
|
33
|
+
"pjt.git.not-a-repo": "Required a git repository, but `.git/` was missing. Run `git init` first.",
|
|
34
|
+
"pjt.git.command-failed": "A `git` command exited non-zero or git isn't installed. The underlying error is included in the message.",
|
|
35
|
+
"pjt.exec.command-failed": "A command run by projitect exited non-zero or could not be started. Its exit code, stdout and stderr are included.",
|
|
36
|
+
"pjt.exec.command-not-permitted": "A blueprint tried to run a command that none of its declared `exec` permissions names exactly.",
|
|
37
|
+
"pjt.inspect.operation-unsupported": "`pjt inspect` cannot check a project whose blueprints declare post-apply commands, so it fails instead of reporting clean.",
|
|
38
|
+
"pjt.pm.not-detected": "Could not figure out which package manager you're using. Add a lockfile (`pnpm-lock.yaml`, `package-lock.json`, etc.) at your project root.",
|
|
39
|
+
"pjt.pm.install-failed": "The package manager install command exited non-zero. The underlying error is included in the message.",
|
|
40
|
+
"pjt.add.markers-missing": "Your `.pjt.ts` is missing the marker comment pairs `pjt:imports` and `pjt:blueprints`. `pjt add` uses those as splice anchors. Restore them and re-run.",
|
|
41
|
+
"pjt.add.metadata-missing": "The package you added has no `projitect` field in its package.json, so `pjt add` can't splice it. Import it in `.pjt.ts` by hand, then run `pjt remodel`.",
|
|
42
|
+
"pjt.worker.crashed": "The worker process that runs blueprint code crashed before it returned a result. The exit code or signal is included in the message.",
|
|
43
|
+
"pjt.worker.timed-out": "The worker process that runs blueprint code did not finish within its time limit and was stopped. Check for a blueprint that never completes.",
|
|
44
|
+
"pjt.worker.exited-early": "The worker process that runs blueprint code exited before it finished its work. The exit code or signal is included in the message.",
|
|
45
|
+
};
|
|
46
|
+
//# sourceMappingURL=explain.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"explain.js","sourceRoot":"","sources":["../../src/commands/explain.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AAC/C,OAAO,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAA;AAExC,MAAM,OAAO,GAAG,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,SAAS,CAAC,CAAA;AAEjD;;;;GAIG;AACH,MAAM,CAAC,MAAM,OAAO,GAAG,CAAC,MAAoC,EAAyB,EAAE,CACrF,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,CACf,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,mBAAmB,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE;IAChE,MAAM,EAAE,GAAG,EAAE,CACX,qBAAqB,MAAM,CAAC,OAAO,2DAA2D;IAChG,MAAM,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,GAAG,EAAE,KAAK,YAAY,CAAC,EAAE,CAAC,cAAc,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE;CAC7E,CAAC,CACH,CAAA;AAEH,MAAM,YAAY,GAA6C;IAC7D,0BAA0B,EACxB,2HAA2H;IAC7H,oBAAoB,EAClB,uGAAuG;IACzG,qBAAqB,EACnB,2EAA2E;IAC7E,0BAA0B,EACxB,4FAA4F;IAC9F,mCAAmC,EACjC,sEAAsE;IACxE,oBAAoB,EAClB,6FAA6F;IAC/F,qCAAqC,EACnC,iEAAiE;IACnE,0BAA0B,EACxB,2FAA2F;IAC7F,yBAAyB,EACvB,gFAAgF;IAClF,yBAAyB,EACvB,+FAA+F;IACjG,yBAAyB,EACvB,mIAAmI;IACrI,wBAAwB,EACtB,8HAA8H;IAChI,sBAAsB,EAAE,sEAAsE;IAC9F,qBAAqB,EACnB,+EAA+E;IACjF,sBAAsB,EACpB,kFAAkF;IACpF,+BAA+B,EAC7B,qFAAqF;IACvF,oBAAoB,EAClB,qGAAqG;IACvG,uBAAuB,EACrB,8GAA8G;IAChH,2BAA2B,EACzB,gHAAgH;IAClH,oBAAoB,EAAE,2EAA2E;IACjG,wBAAwB,EACtB,0GAA0G;IAC5G,yBAAyB,EACvB,oHAAoH;IACtH,gCAAgC,EAC9B,gGAAgG;IAClG,mCAAmC,EACjC,4HAA4H;IAC9H,qBAAqB,EACnB,6IAA6I;IAC/I,uBAAuB,EACrB,uGAAuG;IACzG,yBAAyB,EACvB,yJAAyJ;IAC3J,0BAA0B,EACxB,2JAA2J;IAC7J,oBAAoB,EAClB,sIAAsI;IACxI,sBAAsB,EACpB,+IAA+I;IACjJ,yBAAyB,EACvB,qIAAqI;CACxI,CAAA"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { Effect } from "effect";
|
|
2
|
+
import { Errors } from "@projitect/core";
|
|
3
|
+
import type { ProjitectConfig } from "@projitect/core";
|
|
4
|
+
import type { RemodelResult } from "./remodel.js";
|
|
5
|
+
export interface InitResult {
|
|
6
|
+
readonly seededBlueprintFile: boolean;
|
|
7
|
+
readonly bootstrappedGit: boolean;
|
|
8
|
+
readonly bootstrappedPackageJson: boolean;
|
|
9
|
+
readonly remodel: RemodelResult;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* `pjt init` — bootstrap projitect in the current project.
|
|
13
|
+
*
|
|
14
|
+
* Verifies the prerequisites (`.git/` and `package.json` both present), seeds an empty
|
|
15
|
+
* `.pjt.ts` with the marker structure if absent, then delegates to `remodel` which runs the
|
|
16
|
+
* standard plan/apply/lockfile-write pipeline. The projitect blueprint (prepended automatically
|
|
17
|
+
* by `@projitect/cli`'s `pjt()`) writes the package.json entries and the `.pjt.ts` import region
|
|
18
|
+
* on its first apply. Before seeding or loading the config, missing local CLI and Effect
|
|
19
|
+
* dependencies are installed so an ephemeral dlx invocation can resolve those imports.
|
|
20
|
+
*
|
|
21
|
+
* With `yes: true`, both prerequisites are auto-bootstrapped instead of erroring:
|
|
22
|
+
* - Missing `.git/` → `git init -q` shell-out.
|
|
23
|
+
* - Missing `package.json` → a minimal stub is written (`{ "name": "<dirname>", ... }`).
|
|
24
|
+
* This is what CI / scripted setups use (`pjt init --yes`); the interactive flow keeps the
|
|
25
|
+
* stricter prerequisite checks so a typo doesn't accidentally create a git repo in `$HOME`.
|
|
26
|
+
*
|
|
27
|
+
* No special-case code for "the projitect bootstrap" lives here — the projitect blueprint owns
|
|
28
|
+
* those concerns and runs through the same pipeline as every other blueprint.
|
|
29
|
+
*/
|
|
30
|
+
export declare const init: (params: {
|
|
31
|
+
readonly config: ProjitectConfig.ProjitectConfig;
|
|
32
|
+
readonly yes?: boolean;
|
|
33
|
+
}) => Effect.Effect<InitResult, Errors.ProjitectError>;
|
|
34
|
+
//# sourceMappingURL=init.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAIA,OAAO,EAAS,MAAM,EAAkB,MAAM,QAAQ,CAAA;AACtD,OAAO,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAA;AACxC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AAGtD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AASjD,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,mBAAmB,EAAE,OAAO,CAAA;IACrC,QAAQ,CAAC,eAAe,EAAE,OAAO,CAAA;IACjC,QAAQ,CAAC,uBAAuB,EAAE,OAAO,CAAA;IACzC,QAAQ,CAAC,OAAO,EAAE,aAAa,CAAA;CAChC;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,IAAI,GAAI,QAAQ;IAC3B,QAAQ,CAAC,MAAM,EAAE,eAAe,CAAC,eAAe,CAAA;IAChD,QAAQ,CAAC,GAAG,CAAC,EAAE,OAAO,CAAA;CACvB,KAAG,MAAM,CAAC,MAAM,CAAC,UAAU,EAAE,MAAM,CAAC,cAAc,CA2B/C,CAAA"}
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
import { promises as fs } from "node:fs";
|
|
2
|
+
import { spawn } from "node:child_process";
|
|
3
|
+
import { createRequire } from "node:module";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
import { Array, Effect, Option, Schema } from "effect";
|
|
6
|
+
import { Errors } from "@projitect/core";
|
|
7
|
+
import { detect, installDev as installDevelopment, installProject } from "../pm.js";
|
|
8
|
+
import { remodel } from "./remodel.js";
|
|
9
|
+
const manifest = Schema.decodeUnknownSync(Schema.Struct({
|
|
10
|
+
version: Schema.String,
|
|
11
|
+
peerDependencies: Schema.Struct({ effect: Schema.String }),
|
|
12
|
+
}))(createRequire(import.meta.url)("../../package.json"));
|
|
13
|
+
/**
|
|
14
|
+
* `pjt init` — bootstrap projitect in the current project.
|
|
15
|
+
*
|
|
16
|
+
* Verifies the prerequisites (`.git/` and `package.json` both present), seeds an empty
|
|
17
|
+
* `.pjt.ts` with the marker structure if absent, then delegates to `remodel` which runs the
|
|
18
|
+
* standard plan/apply/lockfile-write pipeline. The projitect blueprint (prepended automatically
|
|
19
|
+
* by `@projitect/cli`'s `pjt()`) writes the package.json entries and the `.pjt.ts` import region
|
|
20
|
+
* on its first apply. Before seeding or loading the config, missing local CLI and Effect
|
|
21
|
+
* dependencies are installed so an ephemeral dlx invocation can resolve those imports.
|
|
22
|
+
*
|
|
23
|
+
* With `yes: true`, both prerequisites are auto-bootstrapped instead of erroring:
|
|
24
|
+
* - Missing `.git/` → `git init -q` shell-out.
|
|
25
|
+
* - Missing `package.json` → a minimal stub is written (`{ "name": "<dirname>", ... }`).
|
|
26
|
+
* This is what CI / scripted setups use (`pjt init --yes`); the interactive flow keeps the
|
|
27
|
+
* stricter prerequisite checks so a typo doesn't accidentally create a git repo in `$HOME`.
|
|
28
|
+
*
|
|
29
|
+
* No special-case code for "the projitect bootstrap" lives here — the projitect blueprint owns
|
|
30
|
+
* those concerns and runs through the same pipeline as every other blueprint.
|
|
31
|
+
*/
|
|
32
|
+
export const init = (params) => Effect.gen(function* () {
|
|
33
|
+
const bootstrappedGit = yield* ensureGit(params.config.projectRoot, params.yes ?? false);
|
|
34
|
+
const bootstrappedPackageJson = yield* ensurePackageJson(params.config.projectRoot, params.yes ?? false);
|
|
35
|
+
const bootstrapPm = yield* ensureBootstrapDependencies(params.config.projectRoot);
|
|
36
|
+
const seededBlueprintFile = yield* seedBlueprintFileIfAbsent(params.config.projectRoot, params.config.blueprintFile);
|
|
37
|
+
const remodelResult = yield* remodel({ config: params.config });
|
|
38
|
+
yield* Option.match(bootstrapPm, {
|
|
39
|
+
onNone: () => Effect.void,
|
|
40
|
+
onSome: (pm) => installProject({ projectRoot: params.config.projectRoot, pm }),
|
|
41
|
+
});
|
|
42
|
+
return {
|
|
43
|
+
seededBlueprintFile,
|
|
44
|
+
bootstrappedGit,
|
|
45
|
+
bootstrappedPackageJson,
|
|
46
|
+
remodel: remodelResult,
|
|
47
|
+
};
|
|
48
|
+
});
|
|
49
|
+
/** A dlx runner lives outside the project; generated imports must resolve locally first. */
|
|
50
|
+
const ensureBootstrapDependencies = (projectRoot) => Effect.forEach([
|
|
51
|
+
{ name: "@projitect/cli", spec: `@projitect/cli@${manifest.version}` },
|
|
52
|
+
{ name: "effect", spec: `effect@${manifest.peerDependencies.effect}` },
|
|
53
|
+
], ({ name, spec }) => Effect.gen(function* () {
|
|
54
|
+
const installed = yield* Effect.promise(() => fs.access(path.join(projectRoot, "node_modules", name, "package.json")).then(() => true, () => false));
|
|
55
|
+
if (installed) {
|
|
56
|
+
return Option.none();
|
|
57
|
+
}
|
|
58
|
+
const pm = yield* detect({ projectRoot });
|
|
59
|
+
yield* installDevelopment({ projectRoot, pm, pkg: spec });
|
|
60
|
+
return Option.some(pm);
|
|
61
|
+
})).pipe(Effect.map((results) => Array.head(Array.getSomes(results))));
|
|
62
|
+
const ensureGit = (projectRoot, yes) => Effect.gen(function* () {
|
|
63
|
+
const ok = yield* Effect.promise(() => fs.access(path.join(projectRoot, ".git")).then(() => true, () => false));
|
|
64
|
+
if (ok) {
|
|
65
|
+
return false;
|
|
66
|
+
}
|
|
67
|
+
if (!yes) {
|
|
68
|
+
return yield* new Errors.InitGitMissing({
|
|
69
|
+
id: "pjt.init.git-missing",
|
|
70
|
+
message: "No `.git` directory found. Run `git init` and then `pjt init` again, or run `pjt init --yes` to create the repository for you.",
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
yield* Effect.promise(() => new Promise((resolve, reject) => {
|
|
74
|
+
const child = spawn("git", ["init", "-q"], { cwd: projectRoot, stdio: "ignore" });
|
|
75
|
+
child.on("error", reject);
|
|
76
|
+
child.on("close", (code) => {
|
|
77
|
+
if (code === 0) {
|
|
78
|
+
resolve();
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
reject(new Error(`git init exited with ${String(code)}`));
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
}));
|
|
85
|
+
return true;
|
|
86
|
+
});
|
|
87
|
+
const ensurePackageJson = (projectRoot, yes) => Effect.gen(function* () {
|
|
88
|
+
const ok = yield* Effect.promise(() => fs.access(path.join(projectRoot, "package.json")).then(() => true, () => false));
|
|
89
|
+
if (ok) {
|
|
90
|
+
return false;
|
|
91
|
+
}
|
|
92
|
+
if (!yes) {
|
|
93
|
+
return yield* new Errors.InitPackageJsonMissing({
|
|
94
|
+
id: "pjt.init.package-json-missing",
|
|
95
|
+
message: "No `package.json` found. Run `npm init -y` (or your PM equivalent) first, then re-run `pjt init` — or pass `--yes` to auto-bootstrap.",
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
const name = path.basename(projectRoot) || "project";
|
|
99
|
+
const stub = {
|
|
100
|
+
name,
|
|
101
|
+
version: "0.0.0",
|
|
102
|
+
private: true,
|
|
103
|
+
type: "module",
|
|
104
|
+
};
|
|
105
|
+
yield* Effect.tryPromise({
|
|
106
|
+
try: () => fs.writeFile(path.join(projectRoot, "package.json"), `${JSON.stringify(stub, null, 2)}\n`, "utf8"),
|
|
107
|
+
catch: (e) => new Errors.FsWriteFailed({
|
|
108
|
+
id: "pjt.fs.write-failed",
|
|
109
|
+
path: "package.json",
|
|
110
|
+
cause: e instanceof Error ? e.message : String(e),
|
|
111
|
+
message: "Failed to seed package.json during `pjt init --yes`",
|
|
112
|
+
}),
|
|
113
|
+
});
|
|
114
|
+
return true;
|
|
115
|
+
});
|
|
116
|
+
const seedBlueprintFileIfAbsent = (projectRoot, blueprintFile) => Effect.gen(function* () {
|
|
117
|
+
const full = path.join(projectRoot, blueprintFile);
|
|
118
|
+
const exists = yield* Effect.promise(() => fs.access(full).then(() => true, () => false));
|
|
119
|
+
if (exists) {
|
|
120
|
+
return false;
|
|
121
|
+
}
|
|
122
|
+
yield* Effect.tryPromise({
|
|
123
|
+
try: () => fs.writeFile(full, STARTER_PJT_TS, "utf8"),
|
|
124
|
+
catch: (e) => new Errors.FsWriteFailed({
|
|
125
|
+
id: "pjt.fs.write-failed",
|
|
126
|
+
path: blueprintFile,
|
|
127
|
+
cause: e instanceof Error ? e.message : String(e),
|
|
128
|
+
message: `Failed to seed ${blueprintFile}`,
|
|
129
|
+
}),
|
|
130
|
+
});
|
|
131
|
+
return true;
|
|
132
|
+
});
|
|
133
|
+
/**
|
|
134
|
+
* Starter `.pjt.ts` template. Three marker regions: the projitect blueprint owns
|
|
135
|
+
* `pjt:projitect:imports` (it writes the `import { pjt } from "@projitect/cli"` line on first
|
|
136
|
+
* remodel). The other two — `pjt:imports` and `pjt:blueprints` — are **convention anchors**
|
|
137
|
+
* that `pjt add` splices into; they are not managed regions and don't appear in `.pjt.lock`.
|
|
138
|
+
*/
|
|
139
|
+
const STARTER_PJT_TS = `// pjt:projitect:imports start
|
|
140
|
+
import { pjt } from "@projitect/cli"
|
|
141
|
+
// pjt:projitect:imports end
|
|
142
|
+
|
|
143
|
+
// pjt:imports start
|
|
144
|
+
// pjt:imports end
|
|
145
|
+
|
|
146
|
+
export default pjt({
|
|
147
|
+
blueprints: [
|
|
148
|
+
// pjt:blueprints start
|
|
149
|
+
// pjt:blueprints end
|
|
150
|
+
],
|
|
151
|
+
})
|
|
152
|
+
`;
|
|
153
|
+
//# sourceMappingURL=init.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { Schema } from "effect";
|
|
2
|
+
/**
|
|
3
|
+
* Versioned URL for the published `pjt inspect --json` contract. Doubles as the `$id` of the
|
|
4
|
+
* generated JSON Schema document and the `$schema` value every `--json` output carries. Bumps to
|
|
5
|
+
* `inspect.v2.json` only on a breaking change to the output shape, shipped in a major release.
|
|
6
|
+
*/
|
|
7
|
+
export declare const InspectJsonSchemaUrl = "https://projitect.dev/schemas/inspect.v1.json";
|
|
8
|
+
/**
|
|
9
|
+
* Effect Schema for the `pjt inspect --json` output. `renderInspectJson` encodes through this so
|
|
10
|
+
* the TypeScript types it's built from (`FileDiff`, `UpgradeRecord`, `PjtLock.LockOperation`) are
|
|
11
|
+
* checked against it at compile time, and the published JSON Schema file is generated from this
|
|
12
|
+
* same definition — it can't drift from the code that produces the output.
|
|
13
|
+
*/
|
|
14
|
+
export declare const InspectJson: Schema.Struct<{
|
|
15
|
+
readonly $schema: Schema.Literal<"https://projitect.dev/schemas/inspect.v1.json">;
|
|
16
|
+
readonly hasDrift: Schema.Boolean;
|
|
17
|
+
readonly files: Schema.$Array<Schema.Struct<{
|
|
18
|
+
readonly path: Schema.String;
|
|
19
|
+
readonly status: Schema.Literals<readonly ["create", "modify", "ok"]>;
|
|
20
|
+
readonly summary: Schema.String;
|
|
21
|
+
}>>;
|
|
22
|
+
readonly removals: Schema.$Array<Schema.Union<readonly [Schema.TaggedStruct<"Region", {
|
|
23
|
+
readonly path: Schema.String;
|
|
24
|
+
readonly ownerId: Schema.String;
|
|
25
|
+
readonly commentPrefix: Schema.String;
|
|
26
|
+
readonly commentSuffix: Schema.optional<Schema.String>;
|
|
27
|
+
}>, Schema.TaggedStruct<"Merge", {
|
|
28
|
+
readonly path: Schema.String;
|
|
29
|
+
readonly ownedKeys: Schema.$Array<Schema.String>;
|
|
30
|
+
}>, Schema.TaggedStruct<"Owned", {
|
|
31
|
+
readonly path: Schema.String;
|
|
32
|
+
readonly ownerId: Schema.String;
|
|
33
|
+
readonly ownedDir: Schema.optional<Schema.String>;
|
|
34
|
+
}>, Schema.TaggedStruct<"Seed", {
|
|
35
|
+
readonly path: Schema.String;
|
|
36
|
+
readonly ownerId: Schema.String;
|
|
37
|
+
}>]>>;
|
|
38
|
+
readonly upgrades: Schema.$Array<Schema.Struct<{
|
|
39
|
+
readonly blueprintId: Schema.String;
|
|
40
|
+
readonly from: Schema.String;
|
|
41
|
+
readonly to: Schema.String;
|
|
42
|
+
}>>;
|
|
43
|
+
}>;
|
|
44
|
+
export type InspectJson = typeof InspectJson.Type;
|
|
45
|
+
/**
|
|
46
|
+
* The published schema file's contents — generated from {@link InspectJson}, never hand-edited.
|
|
47
|
+
* `additionalProperties: true` keeps the documented promise that new keys may be added within a
|
|
48
|
+
* version without breaking consumers.
|
|
49
|
+
*/
|
|
50
|
+
export declare const inspectJsonSchemaDocument: () => Record<string, unknown>;
|
|
51
|
+
//# sourceMappingURL=inspect-json.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inspect-json.d.ts","sourceRoot":"","sources":["../../src/commands/inspect-json.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AAG/B;;;;GAIG;AACH,eAAO,MAAM,oBAAoB,kDAAkD,CAAA;AAEnF;;;;;GAKG;AACH,eAAO,MAAM,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAiCtB,CAAA;AAEF,MAAM,MAAM,WAAW,GAAG,OAAO,WAAW,CAAC,IAAI,CAAA;AAEjD;;;;GAIG;AACH,eAAO,MAAM,yBAAyB,QAAO,MAAM,CAAC,MAAM,EAAE,OAAO,CASlE,CAAA"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { Schema } from "effect";
|
|
2
|
+
import { PjtLock } from "@projitect/core";
|
|
3
|
+
/**
|
|
4
|
+
* Versioned URL for the published `pjt inspect --json` contract. Doubles as the `$id` of the
|
|
5
|
+
* generated JSON Schema document and the `$schema` value every `--json` output carries. Bumps to
|
|
6
|
+
* `inspect.v2.json` only on a breaking change to the output shape, shipped in a major release.
|
|
7
|
+
*/
|
|
8
|
+
export const InspectJsonSchemaUrl = "https://projitect.dev/schemas/inspect.v1.json";
|
|
9
|
+
/**
|
|
10
|
+
* Effect Schema for the `pjt inspect --json` output. `renderInspectJson` encodes through this so
|
|
11
|
+
* the TypeScript types it's built from (`FileDiff`, `UpgradeRecord`, `PjtLock.LockOperation`) are
|
|
12
|
+
* checked against it at compile time, and the published JSON Schema file is generated from this
|
|
13
|
+
* same definition — it can't drift from the code that produces the output.
|
|
14
|
+
*/
|
|
15
|
+
export const InspectJson = Schema.Struct({
|
|
16
|
+
$schema: Schema.Literal(InspectJsonSchemaUrl).annotate({
|
|
17
|
+
description: "Identifies the published JSON Schema this output conforms to.",
|
|
18
|
+
}),
|
|
19
|
+
hasDrift: Schema.Boolean.annotate({
|
|
20
|
+
description: "Whether the project has drifted from its blueprints or lockfile.",
|
|
21
|
+
}),
|
|
22
|
+
files: Schema.Array(Schema.Struct({
|
|
23
|
+
path: Schema.String,
|
|
24
|
+
status: Schema.Literals(["create", "modify", "ok"]).annotate({
|
|
25
|
+
description: '"create" — file absent, will be created; "modify" — exists but content drifts; "ok" — in sync.',
|
|
26
|
+
}),
|
|
27
|
+
summary: Schema.String,
|
|
28
|
+
})).annotate({ description: "Per-file drift status, one entry per managed file." }),
|
|
29
|
+
removals: Schema.Array(PjtLock.LockOperation).annotate({
|
|
30
|
+
description: "Operations recorded in the lockfile whose owning blueprint has left the tree.",
|
|
31
|
+
}),
|
|
32
|
+
upgrades: Schema.Array(Schema.Struct({
|
|
33
|
+
blueprintId: Schema.String,
|
|
34
|
+
from: Schema.String,
|
|
35
|
+
to: Schema.String,
|
|
36
|
+
})).annotate({
|
|
37
|
+
description: "Blueprints whose locked version differs from the tree's current version.",
|
|
38
|
+
}),
|
|
39
|
+
}).annotate({
|
|
40
|
+
title: "pjt inspect --json output",
|
|
41
|
+
description: "Structured drift report for `pjt inspect --json`. New keys may be added within this version; removing or renaming a key requires a new schema version.",
|
|
42
|
+
});
|
|
43
|
+
/**
|
|
44
|
+
* The published schema file's contents — generated from {@link InspectJson}, never hand-edited.
|
|
45
|
+
* `additionalProperties: true` keeps the documented promise that new keys may be added within a
|
|
46
|
+
* version without breaking consumers.
|
|
47
|
+
*/
|
|
48
|
+
export const inspectJsonSchemaDocument = () => {
|
|
49
|
+
const doc = Schema.toJsonSchemaDocument(InspectJson, { additionalProperties: true });
|
|
50
|
+
const hasDefinitions = Object.keys(doc.definitions).length > 0;
|
|
51
|
+
return {
|
|
52
|
+
$schema: "https://json-schema.org/draft/2020-12/schema",
|
|
53
|
+
$id: InspectJsonSchemaUrl,
|
|
54
|
+
...doc.schema,
|
|
55
|
+
...(hasDefinitions ? { $defs: doc.definitions } : {}),
|
|
56
|
+
};
|
|
57
|
+
};
|
|
58
|
+
//# sourceMappingURL=inspect-json.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inspect-json.js","sourceRoot":"","sources":["../../src/commands/inspect-json.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AAC/B,OAAO,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAA;AAEzC;;;;GAIG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,+CAA+C,CAAA;AAEnF;;;;;GAKG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,MAAM,CAAC,MAAM,CAAC;IACvC,OAAO,EAAE,MAAM,CAAC,OAAO,CAAC,oBAAoB,CAAC,CAAC,QAAQ,CAAC;QACrD,WAAW,EAAE,+DAA+D;KAC7E,CAAC;IACF,QAAQ,EAAE,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC;QAChC,WAAW,EAAE,kEAAkE;KAChF,CAAC;IACF,KAAK,EAAE,MAAM,CAAC,KAAK,CACjB,MAAM,CAAC,MAAM,CAAC;QACZ,IAAI,EAAE,MAAM,CAAC,MAAM;QACnB,MAAM,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC,QAAQ,EAAE,QAAQ,EAAE,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC;YAC3D,WAAW,EACT,gGAAgG;SACnG,CAAC;QACF,OAAO,EAAE,MAAM,CAAC,MAAM;KACvB,CAAC,CACH,CAAC,QAAQ,CAAC,EAAE,WAAW,EAAE,oDAAoD,EAAE,CAAC;IACjF,QAAQ,EAAE,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC,QAAQ,CAAC;QACrD,WAAW,EAAE,+EAA+E;KAC7F,CAAC;IACF,QAAQ,EAAE,MAAM,CAAC,KAAK,CACpB,MAAM,CAAC,MAAM,CAAC;QACZ,WAAW,EAAE,MAAM,CAAC,MAAM;QAC1B,IAAI,EAAE,MAAM,CAAC,MAAM;QACnB,EAAE,EAAE,MAAM,CAAC,MAAM;KAClB,CAAC,CACH,CAAC,QAAQ,CAAC;QACT,WAAW,EAAE,0EAA0E;KACxF,CAAC;CACH,CAAC,CAAC,QAAQ,CAAC;IACV,KAAK,EAAE,2BAA2B;IAClC,WAAW,EACT,wJAAwJ;CAC3J,CAAC,CAAA;AAIF;;;;GAIG;AACH,MAAM,CAAC,MAAM,yBAAyB,GAAG,GAA4B,EAAE;IACrE,MAAM,GAAG,GAAG,MAAM,CAAC,oBAAoB,CAAC,WAAW,EAAE,EAAE,oBAAoB,EAAE,IAAI,EAAE,CAAC,CAAA;IACpF,MAAM,cAAc,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC,MAAM,GAAG,CAAC,CAAA;IAC9D,OAAO;QACL,OAAO,EAAE,8CAA8C;QACvD,GAAG,EAAE,oBAAoB;QACzB,GAAG,GAAG,CAAC,MAAM;QACb,GAAG,CAAC,cAAc,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,GAAG,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KACtD,CAAA;AACH,CAAC,CAAA"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { Effect } from "effect";
|
|
2
|
+
import { Errors } from "@projitect/core";
|
|
3
|
+
import type { PjtLock, ProjitectConfig } from "@projitect/core";
|
|
4
|
+
import type { UpgradeRecord } from "../plan.js";
|
|
5
|
+
import type { FileDiff } from "../differ.js";
|
|
6
|
+
/**
|
|
7
|
+
* Result of `pjt inspect`. `output` is the human-readable rendering; the structured fields
|
|
8
|
+
* (`files`, `removals`, `upgrades`) are what `--json` mode emits. Both representations are
|
|
9
|
+
* always computed — switching modes is just a renderer choice.
|
|
10
|
+
*/
|
|
11
|
+
export interface InspectResult {
|
|
12
|
+
readonly hasDrift: boolean;
|
|
13
|
+
readonly output: string;
|
|
14
|
+
readonly files: readonly FileDiff[];
|
|
15
|
+
readonly removals: readonly PjtLock.LockOperation[];
|
|
16
|
+
readonly upgrades: readonly UpgradeRecord[];
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* `pjt inspect` — load the blueprint file, build the plan, diff against disk + lockfile, and
|
|
20
|
+
* return both a human-readable summary and the structured pieces a `--json` consumer needs.
|
|
21
|
+
*
|
|
22
|
+
* The dispatcher decides which representation to print; the command keeps the `hasDrift`
|
|
23
|
+
* boolean separate so the bin shim can set exit code 1 regardless of output mode (`pjt inspect
|
|
24
|
+
* --json` still exits nonzero on drift, which CI relies on for the "in spec / out of spec"
|
|
25
|
+
* promise).
|
|
26
|
+
*/
|
|
27
|
+
export declare const inspect: (params: {
|
|
28
|
+
readonly config: ProjitectConfig.ProjitectConfig;
|
|
29
|
+
}) => Effect.Effect<InspectResult, Errors.ProjitectError>;
|
|
30
|
+
/**
|
|
31
|
+
* Render the inspect result as a stable JSON object for CI / scripting, conforming to the
|
|
32
|
+
* published JSON Schema at {@link InspectJsonSchemaUrl} (also published at
|
|
33
|
+
* `apps/website/public/schemas/inspect.v1.json`). The `$schema` key names that contract.
|
|
34
|
+
*
|
|
35
|
+
* Stable means: keys won't be renamed or removed without a major bump (and a new schema
|
|
36
|
+
* version). New keys may be added at either level within a version; consumers should ignore
|
|
37
|
+
* unknown keys. Encoding through {@link InspectJson} ties this output to the same definition the
|
|
38
|
+
* schema is generated from, so the two can't drift apart.
|
|
39
|
+
*/
|
|
40
|
+
export declare const renderInspectJson: (result: InspectResult) => string;
|
|
41
|
+
//# sourceMappingURL=inspect.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inspect.d.ts","sourceRoot":"","sources":["../../src/commands/inspect.ts"],"names":[],"mappings":"AAAA,OAAO,EAAS,MAAM,EAAU,MAAM,QAAQ,CAAA;AAC9C,OAAO,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAA;AACxC,OAAO,KAAK,EAAE,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AAI/D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAE/C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAA;AAK5C;;;;GAIG;AACH,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAA;IAC1B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,KAAK,EAAE,SAAS,QAAQ,EAAE,CAAA;IACnC,QAAQ,CAAC,QAAQ,EAAE,SAAS,OAAO,CAAC,aAAa,EAAE,CAAA;IACnD,QAAQ,CAAC,QAAQ,EAAE,SAAS,aAAa,EAAE,CAAA;CAC5C;AAED;;;;;;;;GAQG;AACH,eAAO,MAAM,OAAO,GAAI,QAAQ;IAC9B,QAAQ,CAAC,MAAM,EAAE,eAAe,CAAC,eAAe,CAAA;CACjD,KAAG,MAAM,CAAC,MAAM,CAAC,aAAa,EAAE,MAAM,CAAC,cAAc,CA0ClD,CAAA;AAKJ;;;;;;;;;GASG;AACH,eAAO,MAAM,iBAAiB,GAAI,QAAQ,aAAa,KAAG,MAWnD,CAAA"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { Array, Effect, Schema } from "effect";
|
|
2
|
+
import { Errors } from "@projitect/core";
|
|
3
|
+
import { loadBlueprintFile, isEffectTree } from "../loader.js";
|
|
4
|
+
import { buildPlan, diffLockfile } from "../plan.js";
|
|
5
|
+
import { diffPlan, renderInspectReport } from "../differ.js";
|
|
6
|
+
import { makeProjectRootLayer, makeRealLayer } from "../filesystem-impl.js";
|
|
7
|
+
import { readLockfile } from "../lockfile.js";
|
|
8
|
+
import { InspectJson, InspectJsonSchemaUrl } from "./inspect-json.js";
|
|
9
|
+
/**
|
|
10
|
+
* `pjt inspect` — load the blueprint file, build the plan, diff against disk + lockfile, and
|
|
11
|
+
* return both a human-readable summary and the structured pieces a `--json` consumer needs.
|
|
12
|
+
*
|
|
13
|
+
* The dispatcher decides which representation to print; the command keeps the `hasDrift`
|
|
14
|
+
* boolean separate so the bin shim can set exit code 1 regardless of output mode (`pjt inspect
|
|
15
|
+
* --json` still exits nonzero on drift, which CI relies on for the "in spec / out of spec"
|
|
16
|
+
* promise).
|
|
17
|
+
*/
|
|
18
|
+
export const inspect = (params) => Effect.gen(function* () {
|
|
19
|
+
const file = yield* loadBlueprintFile({
|
|
20
|
+
blueprintFile: params.config.blueprintFile,
|
|
21
|
+
projectRoot: params.config.projectRoot,
|
|
22
|
+
});
|
|
23
|
+
const tree = isEffectTree(file.blueprints)
|
|
24
|
+
? yield* file.blueprints.pipe(Effect.provide(makeRealLayer({
|
|
25
|
+
blueprintId: "pjt:config-loader",
|
|
26
|
+
permissions: [{ kind: "read", glob: "**" }],
|
|
27
|
+
projectRoot: params.config.projectRoot,
|
|
28
|
+
})))
|
|
29
|
+
: file.blueprints;
|
|
30
|
+
const { plan, byBlueprint } = yield* buildPlan({
|
|
31
|
+
tree,
|
|
32
|
+
projectRoot: params.config.projectRoot,
|
|
33
|
+
});
|
|
34
|
+
// Fail closed: commands cannot be diffed yet, so a clean report would be a false one.
|
|
35
|
+
if (Array.isReadonlyArrayNonEmpty(plan.commands)) {
|
|
36
|
+
return yield* new Errors.OperationUnsupportedOnInspect({
|
|
37
|
+
id: "pjt.inspect.operation-unsupported",
|
|
38
|
+
operation: "Exec",
|
|
39
|
+
message: `\`pjt inspect\` cannot check post-apply commands, and ${plan.commands.length === 1 ? "1 is" : `${plan.commands.length} are`} declared (first: \`${plan.commands[0].command}\`).`,
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
return yield* Effect.gen(function* () {
|
|
43
|
+
const previous = yield* readLockfile;
|
|
44
|
+
const { removals, upgrades } = diffLockfile({ previous, current: byBlueprint });
|
|
45
|
+
const diff = yield* diffPlan({ plan });
|
|
46
|
+
const hasDrift = diff.hasDrift || removals.length > 0;
|
|
47
|
+
return {
|
|
48
|
+
hasDrift,
|
|
49
|
+
output: withNextStep(renderInspectReport({ diff, removals, upgrades }), hasDrift),
|
|
50
|
+
files: diff.files,
|
|
51
|
+
removals,
|
|
52
|
+
upgrades,
|
|
53
|
+
};
|
|
54
|
+
}).pipe(Effect.provide(makeProjectRootLayer(params.config.projectRoot)));
|
|
55
|
+
});
|
|
56
|
+
const withNextStep = (report, hasDrift) => hasDrift ? `${report}\n\nDrift detected. Run \`pjt remodel\` to apply the blueprints.` : report;
|
|
57
|
+
/**
|
|
58
|
+
* Render the inspect result as a stable JSON object for CI / scripting, conforming to the
|
|
59
|
+
* published JSON Schema at {@link InspectJsonSchemaUrl} (also published at
|
|
60
|
+
* `apps/website/public/schemas/inspect.v1.json`). The `$schema` key names that contract.
|
|
61
|
+
*
|
|
62
|
+
* Stable means: keys won't be renamed or removed without a major bump (and a new schema
|
|
63
|
+
* version). New keys may be added at either level within a version; consumers should ignore
|
|
64
|
+
* unknown keys. Encoding through {@link InspectJson} ties this output to the same definition the
|
|
65
|
+
* schema is generated from, so the two can't drift apart.
|
|
66
|
+
*/
|
|
67
|
+
export const renderInspectJson = (result) => `${JSON.stringify(Schema.encodeSync(InspectJson)({
|
|
68
|
+
$schema: InspectJsonSchemaUrl,
|
|
69
|
+
hasDrift: result.hasDrift,
|
|
70
|
+
files: result.files,
|
|
71
|
+
removals: result.removals,
|
|
72
|
+
upgrades: result.upgrades,
|
|
73
|
+
}), null, 2)}\n`;
|
|
74
|
+
//# sourceMappingURL=inspect.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inspect.js","sourceRoot":"","sources":["../../src/commands/inspect.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AAC9C,OAAO,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAA;AAExC,OAAO,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,cAAc,CAAA;AAE9D,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAEpD,OAAO,EAAE,QAAQ,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAA;AAE5D,OAAO,EAAE,oBAAoB,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAA;AAC3E,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAA;AAC7C,OAAO,EAAE,WAAW,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAA;AAerE;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,OAAO,GAAG,CAAC,MAEvB,EAAuD,EAAE,CACxD,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;IAClB,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,iBAAiB,CAAC;QACpC,aAAa,EAAE,MAAM,CAAC,MAAM,CAAC,aAAa;QAC1C,WAAW,EAAE,MAAM,CAAC,MAAM,CAAC,WAAW;KACvC,CAAC,CAAA;IACF,MAAM,IAAI,GAAkB,YAAY,CAAC,IAAI,CAAC,UAAU,CAAC;QACvD,CAAC,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CACzB,MAAM,CAAC,OAAO,CACZ,aAAa,CAAC;YACZ,WAAW,EAAE,mBAAmB;YAChC,WAAW,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;YAC3C,WAAW,EAAE,MAAM,CAAC,MAAM,CAAC,WAAW;SACvC,CAAC,CACH,CACF;QACH,CAAC,CAAC,IAAI,CAAC,UAAU,CAAA;IACnB,MAAM,EAAE,IAAI,EAAE,WAAW,EAAE,GAAG,KAAK,CAAC,CAAC,SAAS,CAAC;QAC7C,IAAI;QACJ,WAAW,EAAE,MAAM,CAAC,MAAM,CAAC,WAAW;KACvC,CAAC,CAAA;IACF,sFAAsF;IACtF,IAAI,KAAK,CAAC,uBAAuB,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;QACjD,OAAO,KAAK,CAAC,CAAC,IAAI,MAAM,CAAC,6BAA6B,CAAC;YACrD,EAAE,EAAE,mCAAmC;YACvC,SAAS,EAAE,MAAM;YACjB,OAAO,EAAE,yDAAyD,IAAI,CAAC,QAAQ,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,MAAM,uBAAuB,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,OAAO,MAAM;SAC3L,CAAC,CAAA;IACJ,CAAC;IACD,OAAO,KAAK,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;QAChC,MAAM,QAAQ,GAAG,KAAK,CAAC,CAAC,YAAY,CAAA;QACpC,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,GAAG,YAAY,CAAC,EAAE,QAAQ,EAAE,OAAO,EAAE,WAAW,EAAE,CAAC,CAAA;QAC/E,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,QAAQ,CAAC,EAAE,IAAI,EAAE,CAAC,CAAA;QACtC,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAA;QACrD,OAAO;YACL,QAAQ;YACR,MAAM,EAAE,YAAY,CAAC,mBAAmB,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC,EAAE,QAAQ,CAAC;YACjF,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,QAAQ;YACR,QAAQ;SACT,CAAA;IACH,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,oBAAoB,CAAC,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,CAAA;AAC1E,CAAC,CAAC,CAAA;AAEJ,MAAM,YAAY,GAAG,CAAC,MAAc,EAAE,QAAiB,EAAU,EAAE,CACjE,QAAQ,CAAC,CAAC,CAAC,GAAG,MAAM,kEAAkE,CAAC,CAAC,CAAC,MAAM,CAAA;AAEjG;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,MAAqB,EAAU,EAAE,CACjE,GAAG,IAAI,CAAC,SAAS,CACf,MAAM,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC;IAC7B,OAAO,EAAE,oBAAoB;IAC7B,QAAQ,EAAE,MAAM,CAAC,QAAQ;IACzB,KAAK,EAAE,MAAM,CAAC,KAAK;IACnB,QAAQ,EAAE,MAAM,CAAC,QAAQ;IACzB,QAAQ,EAAE,MAAM,CAAC,QAAQ;CAC1B,CAAC,EACF,IAAI,EACJ,CAAC,CACF,IAAI,CAAA"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { Effect } from "effect";
|
|
2
|
+
import type { Errors, ProjitectConfig } from "@projitect/core";
|
|
3
|
+
import type { ProcessSpawner } from "../platform/process-runner.js";
|
|
4
|
+
export interface RemodelResult {
|
|
5
|
+
readonly written: readonly string[];
|
|
6
|
+
readonly removed: readonly string[];
|
|
7
|
+
/** Post-apply commands that ran, deduplicated, in the order they ran. */
|
|
8
|
+
readonly ran: readonly string[];
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* `pjt remodel` — load blueprints, build the plan, apply changes to disk, rewrite `.pjt.lock`,
|
|
12
|
+
* then run the blueprints' post-apply commands.
|
|
13
|
+
* Non-destructive at the file-tree level: only touches files the plan covers (additions) and
|
|
14
|
+
* files where a blueprint that previously had ownership left the tree (removals). Commands run
|
|
15
|
+
* only after every file operation and the lockfile write have succeeded. `spawner` replaces the
|
|
16
|
+
* real process spawner in tests.
|
|
17
|
+
*/
|
|
18
|
+
export declare const remodel: (params: {
|
|
19
|
+
readonly config: ProjitectConfig.ProjitectConfig;
|
|
20
|
+
readonly spawner?: ProcessSpawner;
|
|
21
|
+
}) => Effect.Effect<RemodelResult, Errors.ProjitectError>;
|
|
22
|
+
//# sourceMappingURL=remodel.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"remodel.d.ts","sourceRoot":"","sources":["../../src/commands/remodel.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AAE/B,OAAO,KAAK,EAAE,MAAM,EAAW,eAAe,EAAE,MAAM,iBAAiB,CAAA;AASvE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAA;AAEnE,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAA;IACnC,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAA;IACnC,yEAAyE;IACzE,QAAQ,CAAC,GAAG,EAAE,SAAS,MAAM,EAAE,CAAA;CAChC;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,OAAO,GAAI,QAAQ;IAC9B,QAAQ,CAAC,MAAM,EAAE,eAAe,CAAC,eAAe,CAAA;IAChD,QAAQ,CAAC,OAAO,CAAC,EAAE,cAAc,CAAA;CAClC,KAAG,MAAM,CAAC,MAAM,CAAC,aAAa,EAAE,MAAM,CAAC,cAAc,CAwClD,CAAA"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { Effect } from "effect";
|
|
2
|
+
import { StructX } from "@nunofyobiz/effect-extras";
|
|
3
|
+
import { loadBlueprintFile, isEffectTree } from "../loader.js";
|
|
4
|
+
import { buildPlan, diffLockfile } from "../plan.js";
|
|
5
|
+
import { applyPlan } from "../applier.js";
|
|
6
|
+
import { applyRemovals } from "../remover.js";
|
|
7
|
+
import { makeProjectRootLayer, makeRealLayer } from "../filesystem-impl.js";
|
|
8
|
+
import { readLockfile, writeLockfile } from "../lockfile.js";
|
|
9
|
+
import { runPostApply } from "../post-apply.js";
|
|
10
|
+
/**
|
|
11
|
+
* `pjt remodel` — load blueprints, build the plan, apply changes to disk, rewrite `.pjt.lock`,
|
|
12
|
+
* then run the blueprints' post-apply commands.
|
|
13
|
+
* Non-destructive at the file-tree level: only touches files the plan covers (additions) and
|
|
14
|
+
* files where a blueprint that previously had ownership left the tree (removals). Commands run
|
|
15
|
+
* only after every file operation and the lockfile write have succeeded. `spawner` replaces the
|
|
16
|
+
* real process spawner in tests.
|
|
17
|
+
*/
|
|
18
|
+
export const remodel = (params) => Effect.gen(function* () {
|
|
19
|
+
const file = yield* loadBlueprintFile({
|
|
20
|
+
blueprintFile: params.config.blueprintFile,
|
|
21
|
+
projectRoot: params.config.projectRoot,
|
|
22
|
+
});
|
|
23
|
+
const tree = isEffectTree(file.blueprints)
|
|
24
|
+
? yield* file.blueprints.pipe(Effect.provide(makeRealLayer({
|
|
25
|
+
blueprintId: "pjt:config-loader",
|
|
26
|
+
permissions: [{ kind: "read", glob: "**" }],
|
|
27
|
+
projectRoot: params.config.projectRoot,
|
|
28
|
+
})))
|
|
29
|
+
: file.blueprints;
|
|
30
|
+
const { plan, byBlueprint } = yield* buildPlan({
|
|
31
|
+
tree,
|
|
32
|
+
projectRoot: params.config.projectRoot,
|
|
33
|
+
});
|
|
34
|
+
return yield* Effect.gen(function* () {
|
|
35
|
+
const previous = yield* readLockfile;
|
|
36
|
+
const { removals } = diffLockfile({ previous, current: byBlueprint });
|
|
37
|
+
const written = yield* applyPlan({ plan });
|
|
38
|
+
const removed = yield* applyRemovals({ removals });
|
|
39
|
+
const nextLock = { version: 1, blueprints: byBlueprint };
|
|
40
|
+
yield* writeLockfile({ lock: nextLock });
|
|
41
|
+
const ran = yield* runPostApply({
|
|
42
|
+
commands: plan.commands,
|
|
43
|
+
projectRoot: params.config.projectRoot,
|
|
44
|
+
...StructX.defined("spawner", params.spawner),
|
|
45
|
+
});
|
|
46
|
+
return { written, removed, ran };
|
|
47
|
+
}).pipe(Effect.provide(makeProjectRootLayer(params.config.projectRoot)));
|
|
48
|
+
});
|
|
49
|
+
//# sourceMappingURL=remodel.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"remodel.js","sourceRoot":"","sources":["../../src/commands/remodel.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AAC/B,OAAO,EAAE,OAAO,EAAE,MAAM,2BAA2B,CAAA;AAEnD,OAAO,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,cAAc,CAAA;AAE9D,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AACpD,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAA;AACzC,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAA;AAC7C,OAAO,EAAE,oBAAoB,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAA;AAC3E,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAA;AAC5D,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAA;AAU/C;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,OAAO,GAAG,CAAC,MAGvB,EAAuD,EAAE,CACxD,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;IAClB,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,iBAAiB,CAAC;QACpC,aAAa,EAAE,MAAM,CAAC,MAAM,CAAC,aAAa;QAC1C,WAAW,EAAE,MAAM,CAAC,MAAM,CAAC,WAAW;KACvC,CAAC,CAAA;IACF,MAAM,IAAI,GAAkB,YAAY,CAAC,IAAI,CAAC,UAAU,CAAC;QACvD,CAAC,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CACzB,MAAM,CAAC,OAAO,CACZ,aAAa,CAAC;YACZ,WAAW,EAAE,mBAAmB;YAChC,WAAW,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;YAC3C,WAAW,EAAE,MAAM,CAAC,MAAM,CAAC,WAAW;SACvC,CAAC,CACH,CACF;QACH,CAAC,CAAC,IAAI,CAAC,UAAU,CAAA;IAEnB,MAAM,EAAE,IAAI,EAAE,WAAW,EAAE,GAAG,KAAK,CAAC,CAAC,SAAS,CAAC;QAC7C,IAAI;QACJ,WAAW,EAAE,MAAM,CAAC,MAAM,CAAC,WAAW;KACvC,CAAC,CAAA;IACF,OAAO,KAAK,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;QAChC,MAAM,QAAQ,GAAG,KAAK,CAAC,CAAC,YAAY,CAAA;QACpC,MAAM,EAAE,QAAQ,EAAE,GAAG,YAAY,CAAC,EAAE,QAAQ,EAAE,OAAO,EAAE,WAAW,EAAE,CAAC,CAAA;QAErE,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,CAAC,CAAA;QAC1C,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,aAAa,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAA;QAElD,MAAM,QAAQ,GAAoB,EAAE,OAAO,EAAE,CAAC,EAAE,UAAU,EAAE,WAAW,EAAE,CAAA;QACzE,KAAK,CAAC,CAAC,aAAa,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAA;QAExC,MAAM,GAAG,GAAG,KAAK,CAAC,CAAC,YAAY,CAAC;YAC9B,QAAQ,EAAE,IAAI,CAAC,QAAQ;YACvB,WAAW,EAAE,MAAM,CAAC,MAAM,CAAC,WAAW;YACtC,GAAG,OAAO,CAAC,OAAO,CAAC,SAAS,EAAE,MAAM,CAAC,OAAO,CAAC;SAC9C,CAAC,CAAA;QAEF,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,CAAA;IAClC,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,oBAAoB,CAAC,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,CAAA;AAC1E,CAAC,CAAC,CAAA"}
|