@aaac/contracts 0.1.10 → 0.1.11
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/dist/cli/index.js
CHANGED
|
@@ -10,11 +10,11 @@ import {
|
|
|
10
10
|
parseComponentFile,
|
|
11
11
|
validateComponent,
|
|
12
12
|
writeGeneratedFiles
|
|
13
|
-
} from "../chunk-
|
|
13
|
+
} from "../chunk-LGJKAZ4B.js";
|
|
14
14
|
|
|
15
15
|
// src/cli/index.ts
|
|
16
16
|
import { readFileSync } from "fs";
|
|
17
|
-
import { dirname as
|
|
17
|
+
import { dirname as dirname3, resolve as resolve3 } from "path";
|
|
18
18
|
import { fileURLToPath } from "url";
|
|
19
19
|
|
|
20
20
|
// ../../node_modules/commander/lib/error.js
|
|
@@ -3714,6 +3714,18 @@ function createProgram(handlers2, version) {
|
|
|
3714
3714
|
}
|
|
3715
3715
|
await handlers2.introspect(file, opts, globalOpts);
|
|
3716
3716
|
});
|
|
3717
|
+
program3.command("init").description("Initialize a project: copy the CLI binary, scaffold project.yaml, and materialize git hooks").argument("[projectRoot]", "Project root directory (default: current directory)").option("--project-yaml <value>", "Path to project.yaml relative to projectRoot (default: project.yaml)").action(async (projectRoot, opts, cmd) => {
|
|
3718
|
+
const globalOpts = cmd.optsWithGlobals();
|
|
3719
|
+
await handlers2.init(projectRoot, opts, globalOpts);
|
|
3720
|
+
});
|
|
3721
|
+
program3.command("update").description("Re-read project.yaml and re-materialize git hooks").argument("[projectRoot]", "Project root directory (default: current directory)").option("--project-yaml <value>", "Path to project.yaml relative to projectRoot (default: project.yaml)").action(async (projectRoot, opts, cmd) => {
|
|
3722
|
+
const globalOpts = cmd.optsWithGlobals();
|
|
3723
|
+
await handlers2.update(projectRoot, opts, globalOpts);
|
|
3724
|
+
});
|
|
3725
|
+
program3.command("uninstall").description("Remove all managed hook blocks recorded in governance-manifest.lock").argument("[projectRoot]", "Project root directory (default: current directory)").action(async (projectRoot, opts, cmd) => {
|
|
3726
|
+
const globalOpts = cmd.optsWithGlobals();
|
|
3727
|
+
await handlers2.uninstall(projectRoot, opts, globalOpts);
|
|
3728
|
+
});
|
|
3717
3729
|
program3.command("extract").description("Extract contract specification for this CLI tool.").argument("[commands...]", "Command IDs to extract. Use dot notation.").option("-a, --all", "Extract all commands.", false).option("--include-meta", "Include extraction metadata.", true).option("-F, --format <format>", "Output format (yaml or json).", "yaml").action(async (commands, opts, cmd) => {
|
|
3718
3730
|
if (commands.length === 0 && !opts.all) {
|
|
3719
3731
|
process.stderr.write(JSON.stringify({ code: "INVALID_ARGS", message: "Specify command IDs or use --all" }) + "\n");
|
|
@@ -3731,7 +3743,7 @@ function createProgram(handlers2, version) {
|
|
|
3731
3743
|
type: "cli-contracts/extract",
|
|
3732
3744
|
extractedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
3733
3745
|
specVersion: doc.cli_contracts ?? "0.1.0",
|
|
3734
|
-
commands: ["aaac.compile", "aaac.generate", "aaac.validate", "aaac.introspect"]
|
|
3746
|
+
commands: ["aaac.compile", "aaac.generate", "aaac.validate", "aaac.introspect", "aaac.init", "aaac.update", "aaac.uninstall"]
|
|
3735
3747
|
};
|
|
3736
3748
|
}
|
|
3737
3749
|
Object.assign(out, doc);
|
|
@@ -3748,7 +3760,7 @@ function createProgram(handlers2, version) {
|
|
|
3748
3760
|
yamlLines.push("extractedAt: " + (/* @__PURE__ */ new Date()).toISOString());
|
|
3749
3761
|
yamlLines.push("spec_version: " + (doc.cli_contracts ?? "0.1.0"));
|
|
3750
3762
|
yamlLines.push("commands:");
|
|
3751
|
-
for (const id of ["aaac.compile", "aaac.generate", "aaac.validate", "aaac.introspect"]) {
|
|
3763
|
+
for (const id of ["aaac.compile", "aaac.generate", "aaac.validate", "aaac.introspect", "aaac.init", "aaac.update", "aaac.uninstall"]) {
|
|
3752
3764
|
yamlLines.push(" - " + id);
|
|
3753
3765
|
}
|
|
3754
3766
|
}
|
|
@@ -3788,9 +3800,260 @@ function createProgram(handlers2, version) {
|
|
|
3788
3800
|
}
|
|
3789
3801
|
|
|
3790
3802
|
// src/cli/handlers.ts
|
|
3791
|
-
import {
|
|
3792
|
-
import {
|
|
3803
|
+
import { existsSync as existsSync2 } from "fs";
|
|
3804
|
+
import { mkdir as mkdir2, writeFile as writeFile2 } from "fs/promises";
|
|
3805
|
+
import { dirname as dirname2, join as join2, resolve as resolve2 } from "path";
|
|
3793
3806
|
import { stringify as stringifyYaml } from "yaml";
|
|
3807
|
+
|
|
3808
|
+
// src/cli/governance.ts
|
|
3809
|
+
import { createHash } from "crypto";
|
|
3810
|
+
import { existsSync } from "fs";
|
|
3811
|
+
import { chmod, mkdir, readFile, writeFile } from "fs/promises";
|
|
3812
|
+
import { dirname, join, resolve } from "path";
|
|
3813
|
+
import { parse as parseYaml } from "yaml";
|
|
3814
|
+
import { z } from "zod";
|
|
3815
|
+
var MANAGED_BLOCK_START = "# >>> aaac-governance:managed (do not edit) >>>";
|
|
3816
|
+
var MANAGED_BLOCK_END = "# <<< aaac-governance:managed <<<";
|
|
3817
|
+
var GOVERNANCE_LOCK_PATH = ".agent-logs/governance-manifest.lock";
|
|
3818
|
+
var DEFAULT_RECORDER = ".cursor/hooks/observ-record.sh";
|
|
3819
|
+
var DEFAULT_CURSOR_HOOKS_JSON = ".cursor/hooks.json";
|
|
3820
|
+
var DEFAULT_BINARY_DEST = "bin/aaac.js";
|
|
3821
|
+
var EnvironmentsSchema = z.object({
|
|
3822
|
+
git: z.object({ hooks: z.array(z.string()).optional() }).optional(),
|
|
3823
|
+
cursor: z.object({ hooks_json: z.string().optional() }).optional()
|
|
3824
|
+
}).optional();
|
|
3825
|
+
var BindingsObservabilitySchema = z.object({
|
|
3826
|
+
event_mapping: z.string().optional(),
|
|
3827
|
+
recorder: z.string().optional()
|
|
3828
|
+
}).optional();
|
|
3829
|
+
var BindingsSchema = z.object({
|
|
3830
|
+
observability: BindingsObservabilitySchema
|
|
3831
|
+
}).optional();
|
|
3832
|
+
var InitProjectConfigSchema = z.object({
|
|
3833
|
+
environments: EnvironmentsSchema,
|
|
3834
|
+
bindings: BindingsSchema
|
|
3835
|
+
});
|
|
3836
|
+
async function loadInitConfig(configPath) {
|
|
3837
|
+
const absPath = resolve(configPath);
|
|
3838
|
+
const raw = await readFile(absPath, "utf8");
|
|
3839
|
+
const parsed = parseYaml(raw);
|
|
3840
|
+
return InitProjectConfigSchema.parse(parsed ?? {});
|
|
3841
|
+
}
|
|
3842
|
+
function escapeRegex(value) {
|
|
3843
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
3844
|
+
}
|
|
3845
|
+
function createManagedBlockRegex() {
|
|
3846
|
+
return new RegExp(
|
|
3847
|
+
`${escapeRegex(MANAGED_BLOCK_START)}[\\s\\S]*?${escapeRegex(MANAGED_BLOCK_END)}\\n?`,
|
|
3848
|
+
"g"
|
|
3849
|
+
);
|
|
3850
|
+
}
|
|
3851
|
+
function buildManagedBlock(blockContent) {
|
|
3852
|
+
return `${MANAGED_BLOCK_START}
|
|
3853
|
+
${blockContent.trimEnd()}
|
|
3854
|
+
${MANAGED_BLOCK_END}
|
|
3855
|
+
`;
|
|
3856
|
+
}
|
|
3857
|
+
function injectManagedBlock(existingContent, blockContent) {
|
|
3858
|
+
const managedBlock = buildManagedBlock(blockContent);
|
|
3859
|
+
const re = createManagedBlockRegex();
|
|
3860
|
+
if (re.test(existingContent)) {
|
|
3861
|
+
return existingContent.replace(createManagedBlockRegex(), managedBlock);
|
|
3862
|
+
}
|
|
3863
|
+
const trimmed = existingContent.replace(/\s+$/, "");
|
|
3864
|
+
if (trimmed.length === 0) {
|
|
3865
|
+
return `#!/bin/sh
|
|
3866
|
+
${managedBlock}`;
|
|
3867
|
+
}
|
|
3868
|
+
const separator = trimmed.endsWith("\n") ? "" : "\n";
|
|
3869
|
+
return `${trimmed}${separator}${managedBlock}`;
|
|
3870
|
+
}
|
|
3871
|
+
function removeManagedBlock(existingContent) {
|
|
3872
|
+
if (!existingContent.includes(MANAGED_BLOCK_START)) {
|
|
3873
|
+
return existingContent;
|
|
3874
|
+
}
|
|
3875
|
+
const withoutBlock = existingContent.replace(createManagedBlockRegex(), "");
|
|
3876
|
+
const meaningful = withoutBlock.split("\n").filter((line) => {
|
|
3877
|
+
const t = line.trim();
|
|
3878
|
+
return t.length > 0 && t !== "#!/bin/sh" && t !== "#!/bin/bash";
|
|
3879
|
+
});
|
|
3880
|
+
if (meaningful.length === 0) {
|
|
3881
|
+
return "";
|
|
3882
|
+
}
|
|
3883
|
+
return withoutBlock.replace(/\n{3,}/g, "\n\n").replace(/\s+$/, "\n");
|
|
3884
|
+
}
|
|
3885
|
+
function mergeCursorHooks(existing, newEntries) {
|
|
3886
|
+
const byCommand = /* @__PURE__ */ new Map();
|
|
3887
|
+
for (const entry of existing) byCommand.set(entry.command, entry);
|
|
3888
|
+
for (const entry of newEntries) byCommand.set(entry.command, entry);
|
|
3889
|
+
return Array.from(byCommand.values());
|
|
3890
|
+
}
|
|
3891
|
+
function removeCursorHooks(existing, commands) {
|
|
3892
|
+
const removeSet = new Set(commands);
|
|
3893
|
+
return existing.filter((entry) => !removeSet.has(entry.command));
|
|
3894
|
+
}
|
|
3895
|
+
function buildDefaultCursorHooks(recorder) {
|
|
3896
|
+
return [
|
|
3897
|
+
{ event: "beforeSubmitPrompt", command: `${recorder} beforeSubmitPrompt` },
|
|
3898
|
+
{ event: "afterShellExecution", command: `${recorder} afterShellExecution` }
|
|
3899
|
+
];
|
|
3900
|
+
}
|
|
3901
|
+
async function ensureParentDir(filePath) {
|
|
3902
|
+
await mkdir(dirname(filePath), { recursive: true });
|
|
3903
|
+
}
|
|
3904
|
+
async function readTextFileIfExists(filePath) {
|
|
3905
|
+
if (!existsSync(filePath)) return void 0;
|
|
3906
|
+
return readFile(filePath, "utf8");
|
|
3907
|
+
}
|
|
3908
|
+
async function writeGovernanceLock(projectRoot, entries) {
|
|
3909
|
+
const lockPath = join(projectRoot, GOVERNANCE_LOCK_PATH);
|
|
3910
|
+
const lock = {
|
|
3911
|
+
materialized_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
3912
|
+
entries
|
|
3913
|
+
};
|
|
3914
|
+
await ensureParentDir(lockPath);
|
|
3915
|
+
await writeFile(lockPath, JSON.stringify(lock, null, 2) + "\n", "utf8");
|
|
3916
|
+
return GOVERNANCE_LOCK_PATH;
|
|
3917
|
+
}
|
|
3918
|
+
async function readGovernanceLock(projectRoot) {
|
|
3919
|
+
const lockPath = join(projectRoot, GOVERNANCE_LOCK_PATH);
|
|
3920
|
+
if (!existsSync(lockPath)) return void 0;
|
|
3921
|
+
const raw = await readFile(lockPath, "utf8");
|
|
3922
|
+
if (!raw.trim()) return void 0;
|
|
3923
|
+
return JSON.parse(raw);
|
|
3924
|
+
}
|
|
3925
|
+
async function materializeHooks(options) {
|
|
3926
|
+
const projectRoot = resolve(options.projectRoot);
|
|
3927
|
+
const result = { materialized: [], lockEntries: [] };
|
|
3928
|
+
const recorder = options.observabilityBinding?.recorder ?? DEFAULT_RECORDER;
|
|
3929
|
+
if (options.environments.git?.hooks?.length) {
|
|
3930
|
+
for (const hookName of options.environments.git.hooks) {
|
|
3931
|
+
const relPath = join(".git/hooks", hookName);
|
|
3932
|
+
const absPath = join(projectRoot, relPath);
|
|
3933
|
+
const blockContent = `exec ${recorder} ${hookName} "$@"`;
|
|
3934
|
+
const existing = await readTextFileIfExists(absPath) ?? "";
|
|
3935
|
+
const updated = injectManagedBlock(existing, blockContent);
|
|
3936
|
+
let action = "unchanged";
|
|
3937
|
+
if (!existsSync(absPath)) {
|
|
3938
|
+
action = "created";
|
|
3939
|
+
} else if (updated !== existing) {
|
|
3940
|
+
action = "updated";
|
|
3941
|
+
}
|
|
3942
|
+
if (action !== "unchanged") {
|
|
3943
|
+
await ensureParentDir(absPath);
|
|
3944
|
+
await writeFile(absPath, updated, "utf8");
|
|
3945
|
+
await chmod(absPath, 493);
|
|
3946
|
+
}
|
|
3947
|
+
result.materialized.push({ path: relPath, action });
|
|
3948
|
+
result.lockEntries.push({ path: relPath, type: "git-hook" });
|
|
3949
|
+
}
|
|
3950
|
+
}
|
|
3951
|
+
if (options.environments.cursor) {
|
|
3952
|
+
const rawHooksJsonValue = options.environments.cursor.hooks_json;
|
|
3953
|
+
const hooksJsonPath = rawHooksJsonValue ? resolve(projectRoot, rawHooksJsonValue) : join(projectRoot, DEFAULT_CURSOR_HOOKS_JSON);
|
|
3954
|
+
const relPath = hooksJsonPath.startsWith(projectRoot + "/") ? hooksJsonPath.slice(projectRoot.length + 1) : DEFAULT_CURSOR_HOOKS_JSON;
|
|
3955
|
+
const newEntries = buildDefaultCursorHooks(recorder);
|
|
3956
|
+
const existingRaw = await readTextFileIfExists(hooksJsonPath);
|
|
3957
|
+
const existing = existingRaw ? JSON.parse(existingRaw) : [];
|
|
3958
|
+
const merged = mergeCursorHooks(existing, newEntries);
|
|
3959
|
+
const serialized = JSON.stringify(merged, null, 2) + "\n";
|
|
3960
|
+
let action = "unchanged";
|
|
3961
|
+
if (!existsSync(hooksJsonPath)) {
|
|
3962
|
+
action = "created";
|
|
3963
|
+
} else if (serialized !== existingRaw) {
|
|
3964
|
+
action = "updated";
|
|
3965
|
+
}
|
|
3966
|
+
if (action !== "unchanged") {
|
|
3967
|
+
await ensureParentDir(hooksJsonPath);
|
|
3968
|
+
await writeFile(hooksJsonPath, serialized, "utf8");
|
|
3969
|
+
}
|
|
3970
|
+
result.materialized.push({ path: relPath, action });
|
|
3971
|
+
result.lockEntries.push({ path: relPath, type: "cursor-hook" });
|
|
3972
|
+
}
|
|
3973
|
+
if (result.lockEntries.length > 0) {
|
|
3974
|
+
const lockExisted = existsSync(join(projectRoot, GOVERNANCE_LOCK_PATH));
|
|
3975
|
+
await writeGovernanceLock(projectRoot, result.lockEntries);
|
|
3976
|
+
result.materialized.push({
|
|
3977
|
+
path: GOVERNANCE_LOCK_PATH,
|
|
3978
|
+
action: lockExisted ? "updated" : "created"
|
|
3979
|
+
});
|
|
3980
|
+
result.lockEntries.push({ path: GOVERNANCE_LOCK_PATH, type: "generated" });
|
|
3981
|
+
}
|
|
3982
|
+
return result;
|
|
3983
|
+
}
|
|
3984
|
+
async function unmaterializeHooks(projectRoot, lockEntries) {
|
|
3985
|
+
const root = resolve(projectRoot);
|
|
3986
|
+
for (const entry of lockEntries) {
|
|
3987
|
+
if (entry.type === "generated") {
|
|
3988
|
+
const absPath = join(root, entry.path);
|
|
3989
|
+
if (existsSync(absPath)) {
|
|
3990
|
+
await writeFile(absPath, "", "utf8");
|
|
3991
|
+
}
|
|
3992
|
+
continue;
|
|
3993
|
+
}
|
|
3994
|
+
if (entry.type === "git-hook") {
|
|
3995
|
+
const absPath = join(root, entry.path);
|
|
3996
|
+
const existing = await readTextFileIfExists(absPath);
|
|
3997
|
+
if (existing === void 0) continue;
|
|
3998
|
+
const updated = removeManagedBlock(existing);
|
|
3999
|
+
await writeFile(absPath, updated, "utf8");
|
|
4000
|
+
continue;
|
|
4001
|
+
}
|
|
4002
|
+
if (entry.type === "cursor-hook") {
|
|
4003
|
+
const absPath = join(root, entry.path);
|
|
4004
|
+
const existingRaw = await readTextFileIfExists(absPath);
|
|
4005
|
+
if (existingRaw === void 0) continue;
|
|
4006
|
+
const existing = JSON.parse(existingRaw);
|
|
4007
|
+
const commandsToRemove = buildDefaultCursorHooks(DEFAULT_RECORDER).map((h) => h.command);
|
|
4008
|
+
const updated = removeCursorHooks(existing, commandsToRemove);
|
|
4009
|
+
await writeFile(
|
|
4010
|
+
absPath,
|
|
4011
|
+
updated.length === 0 ? "[]\n" : JSON.stringify(updated, null, 2) + "\n",
|
|
4012
|
+
"utf8"
|
|
4013
|
+
);
|
|
4014
|
+
}
|
|
4015
|
+
}
|
|
4016
|
+
const lockPath = join(root, GOVERNANCE_LOCK_PATH);
|
|
4017
|
+
if (existsSync(lockPath)) {
|
|
4018
|
+
await writeFile(lockPath, "", "utf8");
|
|
4019
|
+
}
|
|
4020
|
+
}
|
|
4021
|
+
async function copyCLIBinary(srcPath, projectRoot, destRelPath = DEFAULT_BINARY_DEST) {
|
|
4022
|
+
const dstPath = join(projectRoot, destRelPath);
|
|
4023
|
+
const srcContent = await readFile(srcPath);
|
|
4024
|
+
const srcHash = createHash("sha256").update(srcContent).digest("hex");
|
|
4025
|
+
if (existsSync(dstPath)) {
|
|
4026
|
+
const dstContent = await readFile(dstPath);
|
|
4027
|
+
const dstHash = createHash("sha256").update(dstContent).digest("hex");
|
|
4028
|
+
if (srcHash === dstHash) {
|
|
4029
|
+
return { path: destRelPath, action: "unchanged" };
|
|
4030
|
+
}
|
|
4031
|
+
await writeFile(dstPath, srcContent);
|
|
4032
|
+
await chmod(dstPath, 493);
|
|
4033
|
+
return { path: destRelPath, action: "updated" };
|
|
4034
|
+
}
|
|
4035
|
+
await ensureParentDir(dstPath);
|
|
4036
|
+
await writeFile(dstPath, srcContent);
|
|
4037
|
+
await chmod(dstPath, 493);
|
|
4038
|
+
return { path: destRelPath, action: "created" };
|
|
4039
|
+
}
|
|
4040
|
+
var SCAFFOLD_PROJECT_YAML = `schema: aaac/project/0.1
|
|
4041
|
+
|
|
4042
|
+
# Uncomment and configure to enable git hook governance:
|
|
4043
|
+
#
|
|
4044
|
+
# environments:
|
|
4045
|
+
# git:
|
|
4046
|
+
# hooks: [pre-commit, pre-push, post-commit]
|
|
4047
|
+
# cursor:
|
|
4048
|
+
# hooks_json: .cursor/hooks.json
|
|
4049
|
+
#
|
|
4050
|
+
# bindings:
|
|
4051
|
+
# observability:
|
|
4052
|
+
# event_mapping: ./bindings/observability.yaml
|
|
4053
|
+
# recorder: aaac-observ
|
|
4054
|
+
`;
|
|
4055
|
+
|
|
4056
|
+
// src/cli/handlers.ts
|
|
3794
4057
|
function formatError(err, file) {
|
|
3795
4058
|
if (err instanceof ComponentParseError) {
|
|
3796
4059
|
return err.message;
|
|
@@ -3818,10 +4081,10 @@ function resolveComponentPath(file) {
|
|
|
3818
4081
|
if (!file) {
|
|
3819
4082
|
fail("Error: component file path is required");
|
|
3820
4083
|
}
|
|
3821
|
-
return
|
|
4084
|
+
return resolve2(file);
|
|
3822
4085
|
}
|
|
3823
4086
|
function defaultOutputDir(componentPath) {
|
|
3824
|
-
return
|
|
4087
|
+
return join2(dirname2(componentPath), "generated");
|
|
3825
4088
|
}
|
|
3826
4089
|
function buildIntrospectionDump(ir) {
|
|
3827
4090
|
const operations = {};
|
|
@@ -3856,10 +4119,10 @@ var handleCompile = async (file, options, parentOpts) => {
|
|
|
3856
4119
|
const ir = await compileComponentFile(componentPath);
|
|
3857
4120
|
const json = JSON.stringify(ir, null, 2);
|
|
3858
4121
|
if (options.output) {
|
|
3859
|
-
await
|
|
4122
|
+
await writeFile2(resolve2(options.output), `${json}
|
|
3860
4123
|
`, "utf-8");
|
|
3861
4124
|
if (!parentOpts.quiet) {
|
|
3862
|
-
process.stdout.write(`Wrote IR to ${
|
|
4125
|
+
process.stdout.write(`Wrote IR to ${resolve2(options.output)}
|
|
3863
4126
|
`);
|
|
3864
4127
|
}
|
|
3865
4128
|
return;
|
|
@@ -3874,7 +4137,7 @@ async function resolveEmbeddedDslData(ir, componentPath) {
|
|
|
3874
4137
|
if (!ir.embeddedDslDir || !ir.implementation) {
|
|
3875
4138
|
return void 0;
|
|
3876
4139
|
}
|
|
3877
|
-
const implPath =
|
|
4140
|
+
const implPath = resolve2(dirname2(componentPath), ir.implementation);
|
|
3878
4141
|
const { resolve: resolveDsl } = await import("agent-contracts");
|
|
3879
4142
|
const dslResult = await resolveDsl(implPath);
|
|
3880
4143
|
return dslResult.data;
|
|
@@ -3893,7 +4156,7 @@ function splitGeneratedFiles(files) {
|
|
|
3893
4156
|
}
|
|
3894
4157
|
var handleGenerate = async (file, options, parentOpts) => {
|
|
3895
4158
|
const componentPath = resolveComponentPath(file);
|
|
3896
|
-
const outputDir =
|
|
4159
|
+
const outputDir = resolve2(options.outputDir ?? defaultOutputDir(componentPath));
|
|
3897
4160
|
const dryRun = Boolean(options.dryRun);
|
|
3898
4161
|
try {
|
|
3899
4162
|
const ir = await compileComponentFile(componentPath);
|
|
@@ -3918,10 +4181,10 @@ var handleGenerate = async (file, options, parentOpts) => {
|
|
|
3918
4181
|
}
|
|
3919
4182
|
}
|
|
3920
4183
|
for (const generated of embedded) {
|
|
3921
|
-
const embeddedDir =
|
|
4184
|
+
const embeddedDir = resolve2(dirname2(componentPath), generated.targetDir);
|
|
3922
4185
|
const action = generated.overwrite ? "write" : "create";
|
|
3923
4186
|
process.stdout.write(
|
|
3924
|
-
` ${action}: ${
|
|
4187
|
+
` ${action}: ${join2(embeddedDir, generated.path)} (embedded DSL)
|
|
3925
4188
|
`
|
|
3926
4189
|
);
|
|
3927
4190
|
}
|
|
@@ -3930,10 +4193,10 @@ var handleGenerate = async (file, options, parentOpts) => {
|
|
|
3930
4193
|
}
|
|
3931
4194
|
const result = await writeGeneratedFiles(main, outputDir);
|
|
3932
4195
|
for (const generated of embedded) {
|
|
3933
|
-
const embeddedDir =
|
|
3934
|
-
await
|
|
3935
|
-
await
|
|
3936
|
-
result.written.push(
|
|
4196
|
+
const embeddedDir = resolve2(dirname2(componentPath), generated.targetDir);
|
|
4197
|
+
await mkdir2(embeddedDir, { recursive: true });
|
|
4198
|
+
await writeFile2(join2(embeddedDir, generated.path), generated.content, "utf-8");
|
|
4199
|
+
result.written.push(join2(generated.targetDir, generated.path));
|
|
3937
4200
|
}
|
|
3938
4201
|
if (!parentOpts.quiet) {
|
|
3939
4202
|
if (result.written.length > 0) {
|
|
@@ -3963,7 +4226,7 @@ var handleGenerate = async (file, options, parentOpts) => {
|
|
|
3963
4226
|
};
|
|
3964
4227
|
var handleValidate = async (file, options, parentOpts) => {
|
|
3965
4228
|
const componentPath = resolveComponentPath(file);
|
|
3966
|
-
const basePath =
|
|
4229
|
+
const basePath = dirname2(componentPath);
|
|
3967
4230
|
try {
|
|
3968
4231
|
const dsl = await parseComponentFile(componentPath);
|
|
3969
4232
|
const ir = compileComponent(dsl, { basePath });
|
|
@@ -3995,17 +4258,156 @@ var handleIntrospect = async (file, options, _parentOpts) => {
|
|
|
3995
4258
|
fail(formatError(err, componentPath));
|
|
3996
4259
|
}
|
|
3997
4260
|
};
|
|
4261
|
+
var DEFAULT_PROJECT_YAML = "project.yaml";
|
|
4262
|
+
var handleInit = async (projectRoot, options, parentOpts) => {
|
|
4263
|
+
const root = resolve2(projectRoot ?? ".");
|
|
4264
|
+
const quiet = Boolean(parentOpts.quiet);
|
|
4265
|
+
const projectYamlPath = join2(root, options.projectYaml ?? DEFAULT_PROJECT_YAML);
|
|
4266
|
+
const srcBinary = resolve2(options.binaryPath ?? process.argv[1]);
|
|
4267
|
+
const binaryResult = await copyCLIBinary(srcBinary, root);
|
|
4268
|
+
if (!quiet && binaryResult.action !== "unchanged") {
|
|
4269
|
+
process.stdout.write(` ${binaryResult.action}: ${binaryResult.path}
|
|
4270
|
+
`);
|
|
4271
|
+
}
|
|
4272
|
+
if (!existsSync2(projectYamlPath)) {
|
|
4273
|
+
await writeFile2(projectYamlPath, SCAFFOLD_PROJECT_YAML, "utf8");
|
|
4274
|
+
if (!quiet) {
|
|
4275
|
+
process.stdout.write(` created: ${DEFAULT_PROJECT_YAML}
|
|
4276
|
+
`);
|
|
4277
|
+
}
|
|
4278
|
+
}
|
|
4279
|
+
const gitDir = join2(root, ".git");
|
|
4280
|
+
if (!existsSync2(gitDir)) {
|
|
4281
|
+
process.stderr.write(
|
|
4282
|
+
`Warning: .git/ not found in ${root}; skipping hook materialization
|
|
4283
|
+
`
|
|
4284
|
+
);
|
|
4285
|
+
if (!quiet) {
|
|
4286
|
+
process.stdout.write(`Initialized project at ${root}
|
|
4287
|
+
`);
|
|
4288
|
+
}
|
|
4289
|
+
return;
|
|
4290
|
+
}
|
|
4291
|
+
let config;
|
|
4292
|
+
try {
|
|
4293
|
+
config = await loadInitConfig(projectYamlPath);
|
|
4294
|
+
} catch (err) {
|
|
4295
|
+
process.stderr.write(
|
|
4296
|
+
`Warning: Could not parse ${DEFAULT_PROJECT_YAML}: ${err instanceof Error ? err.message : String(err)}
|
|
4297
|
+
`
|
|
4298
|
+
);
|
|
4299
|
+
if (!quiet) {
|
|
4300
|
+
process.stdout.write(`Initialized project at ${root}
|
|
4301
|
+
`);
|
|
4302
|
+
}
|
|
4303
|
+
return;
|
|
4304
|
+
}
|
|
4305
|
+
if (!config.environments) {
|
|
4306
|
+
if (!quiet) {
|
|
4307
|
+
process.stdout.write(
|
|
4308
|
+
` no environments configured in ${DEFAULT_PROJECT_YAML}; skipping hooks
|
|
4309
|
+
`
|
|
4310
|
+
);
|
|
4311
|
+
process.stdout.write(`Initialized project at ${root}
|
|
4312
|
+
`);
|
|
4313
|
+
}
|
|
4314
|
+
return;
|
|
4315
|
+
}
|
|
4316
|
+
const result = await materializeHooks({
|
|
4317
|
+
projectRoot: root,
|
|
4318
|
+
environments: config.environments,
|
|
4319
|
+
observabilityBinding: config.bindings?.observability
|
|
4320
|
+
});
|
|
4321
|
+
if (!quiet) {
|
|
4322
|
+
for (const m of result.materialized) {
|
|
4323
|
+
if (m.action !== "unchanged") {
|
|
4324
|
+
process.stdout.write(` ${m.action}: ${m.path}
|
|
4325
|
+
`);
|
|
4326
|
+
}
|
|
4327
|
+
}
|
|
4328
|
+
process.stdout.write(`Initialized project at ${root}
|
|
4329
|
+
`);
|
|
4330
|
+
}
|
|
4331
|
+
};
|
|
4332
|
+
var handleUpdate = async (projectRoot, options, parentOpts) => {
|
|
4333
|
+
const root = resolve2(projectRoot ?? ".");
|
|
4334
|
+
const quiet = Boolean(parentOpts.quiet);
|
|
4335
|
+
const projectYamlPath = join2(root, options.projectYaml ?? DEFAULT_PROJECT_YAML);
|
|
4336
|
+
if (!existsSync2(projectYamlPath)) {
|
|
4337
|
+
fail(
|
|
4338
|
+
`Error: ${DEFAULT_PROJECT_YAML} not found at ${root}. Run 'aaac init' first.`
|
|
4339
|
+
);
|
|
4340
|
+
}
|
|
4341
|
+
const gitDir = join2(root, ".git");
|
|
4342
|
+
if (!existsSync2(gitDir)) {
|
|
4343
|
+
process.stderr.write(
|
|
4344
|
+
`Warning: .git/ not found in ${root}; skipping hook materialization
|
|
4345
|
+
`
|
|
4346
|
+
);
|
|
4347
|
+
return;
|
|
4348
|
+
}
|
|
4349
|
+
let config;
|
|
4350
|
+
try {
|
|
4351
|
+
config = await loadInitConfig(projectYamlPath);
|
|
4352
|
+
} catch (err) {
|
|
4353
|
+
fail(
|
|
4354
|
+
`Error: Could not parse ${DEFAULT_PROJECT_YAML}: ${err instanceof Error ? err.message : String(err)}`
|
|
4355
|
+
);
|
|
4356
|
+
}
|
|
4357
|
+
if (!config.environments) {
|
|
4358
|
+
if (!quiet) {
|
|
4359
|
+
process.stdout.write(`No environments configured in ${DEFAULT_PROJECT_YAML}
|
|
4360
|
+
`);
|
|
4361
|
+
}
|
|
4362
|
+
return;
|
|
4363
|
+
}
|
|
4364
|
+
const result = await materializeHooks({
|
|
4365
|
+
projectRoot: root,
|
|
4366
|
+
environments: config.environments,
|
|
4367
|
+
observabilityBinding: config.bindings?.observability
|
|
4368
|
+
});
|
|
4369
|
+
if (!quiet) {
|
|
4370
|
+
for (const m of result.materialized) {
|
|
4371
|
+
process.stdout.write(` ${m.action}: ${m.path}
|
|
4372
|
+
`);
|
|
4373
|
+
}
|
|
4374
|
+
process.stdout.write(`Updated hooks at ${root}
|
|
4375
|
+
`);
|
|
4376
|
+
}
|
|
4377
|
+
};
|
|
4378
|
+
var handleUninstall = async (projectRoot, _options, parentOpts) => {
|
|
4379
|
+
const root = resolve2(projectRoot ?? ".");
|
|
4380
|
+
const quiet = Boolean(parentOpts.quiet);
|
|
4381
|
+
const lock = await readGovernanceLock(root);
|
|
4382
|
+
if (!lock || lock.entries.length === 0) {
|
|
4383
|
+
if (!quiet) {
|
|
4384
|
+
process.stdout.write(
|
|
4385
|
+
`Nothing to uninstall (no governance lock found at ${join2(root, GOVERNANCE_LOCK_PATH)})
|
|
4386
|
+
`
|
|
4387
|
+
);
|
|
4388
|
+
}
|
|
4389
|
+
return;
|
|
4390
|
+
}
|
|
4391
|
+
await unmaterializeHooks(root, lock.entries);
|
|
4392
|
+
if (!quiet) {
|
|
4393
|
+
process.stdout.write(`Uninstalled governance hooks from ${root}
|
|
4394
|
+
`);
|
|
4395
|
+
}
|
|
4396
|
+
};
|
|
3998
4397
|
var handlers = {
|
|
3999
4398
|
compile: handleCompile,
|
|
4000
4399
|
generate: handleGenerate,
|
|
4001
4400
|
validate: handleValidate,
|
|
4002
|
-
introspect: handleIntrospect
|
|
4401
|
+
introspect: handleIntrospect,
|
|
4402
|
+
init: handleInit,
|
|
4403
|
+
update: handleUpdate,
|
|
4404
|
+
uninstall: handleUninstall
|
|
4003
4405
|
};
|
|
4004
4406
|
|
|
4005
4407
|
// src/cli/index.ts
|
|
4006
|
-
var __dirname =
|
|
4408
|
+
var __dirname = dirname3(fileURLToPath(import.meta.url));
|
|
4007
4409
|
var pkg = JSON.parse(
|
|
4008
|
-
readFileSync(
|
|
4410
|
+
readFileSync(resolve3(__dirname, "../../package.json"), "utf8")
|
|
4009
4411
|
);
|
|
4010
4412
|
var program2 = createProgram(handlers, pkg.version);
|
|
4011
4413
|
await program2.parseAsync();
|