@basaltbytes/odoo-agentic-dev 0.1.0-beta.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/README.md +464 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +73 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/compose.d.ts +19 -0
- package/dist/commands/compose.js +29 -0
- package/dist/commands/compose.js.map +1 -0
- package/dist/commands/doctor.d.ts +35 -0
- package/dist/commands/doctor.js +209 -0
- package/dist/commands/doctor.js.map +1 -0
- package/dist/commands/down.d.ts +23 -0
- package/dist/commands/down.js +46 -0
- package/dist/commands/down.js.map +1 -0
- package/dist/commands/info.d.ts +10 -0
- package/dist/commands/info.js +42 -0
- package/dist/commands/info.js.map +1 -0
- package/dist/commands/json-report.d.ts +45 -0
- package/dist/commands/json-report.js +55 -0
- package/dist/commands/json-report.js.map +1 -0
- package/dist/commands/link-source.d.ts +33 -0
- package/dist/commands/link-source.js +116 -0
- package/dist/commands/link-source.js.map +1 -0
- package/dist/commands/list.d.ts +29 -0
- package/dist/commands/list.js +117 -0
- package/dist/commands/list.js.map +1 -0
- package/dist/commands/logs.d.ts +17 -0
- package/dist/commands/logs.js +28 -0
- package/dist/commands/logs.js.map +1 -0
- package/dist/commands/prune.d.ts +54 -0
- package/dist/commands/prune.js +118 -0
- package/dist/commands/prune.js.map +1 -0
- package/dist/commands/psql.d.ts +8 -0
- package/dist/commands/psql.js +24 -0
- package/dist/commands/psql.js.map +1 -0
- package/dist/commands/reset-db.d.ts +34 -0
- package/dist/commands/reset-db.js +86 -0
- package/dist/commands/reset-db.js.map +1 -0
- package/dist/commands/resolve-context.d.ts +17 -0
- package/dist/commands/resolve-context.js +30 -0
- package/dist/commands/resolve-context.js.map +1 -0
- package/dist/commands/run.d.ts +31 -0
- package/dist/commands/run.js +83 -0
- package/dist/commands/run.js.map +1 -0
- package/dist/commands/setup.d.ts +46 -0
- package/dist/commands/setup.js +93 -0
- package/dist/commands/setup.js.map +1 -0
- package/dist/commands/shell.d.ts +20 -0
- package/dist/commands/shell.js +46 -0
- package/dist/commands/shell.js.map +1 -0
- package/dist/commands/state-hooks.d.ts +28 -0
- package/dist/commands/state-hooks.js +86 -0
- package/dist/commands/state-hooks.js.map +1 -0
- package/dist/commands/test.d.ts +24 -0
- package/dist/commands/test.js +70 -0
- package/dist/commands/test.js.map +1 -0
- package/dist/commands/trailing-args.d.ts +10 -0
- package/dist/commands/trailing-args.js +14 -0
- package/dist/commands/trailing-args.js.map +1 -0
- package/dist/commands/up.d.ts +23 -0
- package/dist/commands/up.js +62 -0
- package/dist/commands/up.js.map +1 -0
- package/dist/commands/update.d.ts +7 -0
- package/dist/commands/update.js +31 -0
- package/dist/commands/update.js.map +1 -0
- package/dist/commands/worktree.d.ts +97 -0
- package/dist/commands/worktree.js +355 -0
- package/dist/commands/worktree.js.map +1 -0
- package/dist/config/load-recipe.d.ts +14 -0
- package/dist/config/load-recipe.js +75 -0
- package/dist/config/load-recipe.js.map +1 -0
- package/dist/config/schema.d.ts +9 -0
- package/dist/config/schema.js +190 -0
- package/dist/config/schema.js.map +1 -0
- package/dist/core/command-plan.d.ts +34 -0
- package/dist/core/command-plan.js +112 -0
- package/dist/core/command-plan.js.map +1 -0
- package/dist/core/compose-model.d.ts +18 -0
- package/dist/core/compose-model.js +80 -0
- package/dist/core/compose-model.js.map +1 -0
- package/dist/core/compose-project.d.ts +3 -0
- package/dist/core/compose-project.js +15 -0
- package/dist/core/compose-project.js.map +1 -0
- package/dist/core/database-name.d.ts +15 -0
- package/dist/core/database-name.js +59 -0
- package/dist/core/database-name.js.map +1 -0
- package/dist/core/environment.d.ts +84 -0
- package/dist/core/environment.js +78 -0
- package/dist/core/environment.js.map +1 -0
- package/dist/core/port-allocator.d.ts +30 -0
- package/dist/core/port-allocator.js +58 -0
- package/dist/core/port-allocator.js.map +1 -0
- package/dist/core/project-recipe.d.ts +163 -0
- package/dist/core/project-recipe.js +13 -0
- package/dist/core/project-recipe.js.map +1 -0
- package/dist/core/safety.d.ts +11 -0
- package/dist/core/safety.js +16 -0
- package/dist/core/safety.js.map +1 -0
- package/dist/core/worktree-context.d.ts +32 -0
- package/dist/core/worktree-context.js +94 -0
- package/dist/core/worktree-context.js.map +1 -0
- package/dist/errors/errors.d.ts +124 -0
- package/dist/errors/errors.js +129 -0
- package/dist/errors/errors.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -0
- package/dist/platform/command-runner.d.ts +30 -0
- package/dist/platform/command-runner.js +65 -0
- package/dist/platform/command-runner.js.map +1 -0
- package/dist/platform/docker-compose.d.ts +69 -0
- package/dist/platform/docker-compose.js +239 -0
- package/dist/platform/docker-compose.js.map +1 -0
- package/dist/platform/git.d.ts +10 -0
- package/dist/platform/git.js +35 -0
- package/dist/platform/git.js.map +1 -0
- package/dist/platform/odoo-lifecycle.d.ts +30 -0
- package/dist/platform/odoo-lifecycle.js +109 -0
- package/dist/platform/odoo-lifecycle.js.map +1 -0
- package/dist/platform/port-probe.d.ts +7 -0
- package/dist/platform/port-probe.js +13 -0
- package/dist/platform/port-probe.js.map +1 -0
- package/dist/platform/process-supervisor.d.ts +16 -0
- package/dist/platform/process-supervisor.js +23 -0
- package/dist/platform/process-supervisor.js.map +1 -0
- package/dist/platform/state-store.d.ts +37 -0
- package/dist/platform/state-store.js +122 -0
- package/dist/platform/state-store.js.map +1 -0
- package/dist/suppress-sqlite-warning.d.ts +1 -0
- package/dist/suppress-sqlite-warning.js +18 -0
- package/dist/suppress-sqlite-warning.js.map +1 -0
- package/dist/testing/fake-adapters.d.ts +34 -0
- package/dist/testing/fake-adapters.js +90 -0
- package/dist/testing/fake-adapters.js.map +1 -0
- package/package.json +78 -0
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { Effect } from "effect";
|
|
2
|
+
import { Command } from "effect/unstable/cli";
|
|
3
|
+
import type { EnvironmentRow, EnvStatus } from "../core/environment.js";
|
|
4
|
+
import type { StateError } from "../errors/errors.js";
|
|
5
|
+
import type { DockerComposeApi } from "../platform/docker-compose.js";
|
|
6
|
+
import type { StateStoreApi } from "../platform/state-store.js";
|
|
7
|
+
export type ListEntry = {
|
|
8
|
+
readonly row: EnvironmentRow;
|
|
9
|
+
readonly status: EnvStatus;
|
|
10
|
+
};
|
|
11
|
+
/** Coarse relative age for table output; unparseable timestamps read as fresh. */
|
|
12
|
+
export declare const relativeAge: (iso: string, nowIso: string) => string;
|
|
13
|
+
/** Plain padded-column table (no table dependency). */
|
|
14
|
+
export declare const buildListTable: (entries: ReadonlyArray<ListEntry>, nowIso: string) => string;
|
|
15
|
+
/**
|
|
16
|
+
* State rows reconciled against docker reality. Labeled stacks unknown to the
|
|
17
|
+
* registry are adopted (inserted best-effort from their labels) before
|
|
18
|
+
* listing. When docker itself is unreachable the registry is still listed,
|
|
19
|
+
* with every stack necessarily reading as `vanished` — callers should warn.
|
|
20
|
+
*/
|
|
21
|
+
export declare const collectListEntries: (projectId: string | undefined) => Effect.Effect<{
|
|
22
|
+
readonly entries: ReadonlyArray<ListEntry>;
|
|
23
|
+
readonly dockerAvailable: boolean;
|
|
24
|
+
}, StateError, StateStoreApi | DockerComposeApi>;
|
|
25
|
+
export declare const listCommand: Command.Command<"list", {
|
|
26
|
+
readonly allProjects: boolean;
|
|
27
|
+
readonly json: boolean;
|
|
28
|
+
readonly config: import("effect/Option").Option<string>;
|
|
29
|
+
}, {}, import("../errors/errors.js").ConfigLoadError | import("../errors/errors.js").ConfigValidationError | StateError, DockerComposeApi | StateStoreApi>;
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import { basename } from "node:path";
|
|
2
|
+
import { Console, Effect } from "effect";
|
|
3
|
+
import { Command, Flag } from "effect/unstable/cli";
|
|
4
|
+
import { classifyEnvironments } from "../core/environment.js";
|
|
5
|
+
import { DockerCompose } from "../platform/docker-compose.js";
|
|
6
|
+
import { StateStore } from "../platform/state-store.js";
|
|
7
|
+
import { resolveProjectId } from "./resolve-context.js";
|
|
8
|
+
/** Coarse relative age for table output; unparseable timestamps read as fresh. */
|
|
9
|
+
export const relativeAge = (iso, nowIso) => {
|
|
10
|
+
const ms = Date.parse(nowIso) - Date.parse(iso);
|
|
11
|
+
if (!Number.isFinite(ms) || ms < 60_000)
|
|
12
|
+
return "just now";
|
|
13
|
+
const minutes = Math.floor(ms / 60_000);
|
|
14
|
+
if (minutes < 60)
|
|
15
|
+
return `${minutes}m ago`;
|
|
16
|
+
const hours = Math.floor(minutes / 60);
|
|
17
|
+
if (hours < 24)
|
|
18
|
+
return `${hours}h ago`;
|
|
19
|
+
return `${Math.floor(hours / 24)}d ago`;
|
|
20
|
+
};
|
|
21
|
+
const flagsCell = (row) => {
|
|
22
|
+
const flags = [row.shared ? "shared" : null, row.templateDb !== null ? "template" : null].filter((flag) => flag !== null);
|
|
23
|
+
return flags.length === 0 ? "-" : flags.join(" ");
|
|
24
|
+
};
|
|
25
|
+
/** Plain padded-column table (no table dependency). */
|
|
26
|
+
export const buildListTable = (entries, nowIso) => {
|
|
27
|
+
const header = ["WORKTREE", "DATABASE", "PORT", "STATUS", "LAST USED", "FLAGS"];
|
|
28
|
+
const body = entries.map(({ row, status }) => [
|
|
29
|
+
row.worktreeName,
|
|
30
|
+
row.databaseName,
|
|
31
|
+
// adopted rows carry port 0: the labels do not record the port
|
|
32
|
+
row.odooHttpPort === 0 ? "?" : String(row.odooHttpPort),
|
|
33
|
+
status,
|
|
34
|
+
relativeAge(row.lastUsedAt, nowIso),
|
|
35
|
+
flagsCell(row),
|
|
36
|
+
]);
|
|
37
|
+
const widths = header.map((cell, i) => Math.max(cell.length, ...body.map((r) => r[i].length)));
|
|
38
|
+
return [header, ...body]
|
|
39
|
+
.map((cells) => cells
|
|
40
|
+
.map((cell, i) => cell.padEnd(widths[i]))
|
|
41
|
+
.join(" ")
|
|
42
|
+
.trimEnd())
|
|
43
|
+
.join("\n");
|
|
44
|
+
};
|
|
45
|
+
const adoptionUpsert = (stack) => stack.projectId === null || stack.database === null || stack.rootDir === null
|
|
46
|
+
? null
|
|
47
|
+
: {
|
|
48
|
+
composeProject: stack.composeProject,
|
|
49
|
+
projectId: stack.projectId,
|
|
50
|
+
databaseName: stack.database,
|
|
51
|
+
rootDir: stack.rootDir,
|
|
52
|
+
// the branch label is "" for "no branch" — map it back to null
|
|
53
|
+
worktreeName: stack.branch !== null && stack.branch !== "" ? stack.branch : basename(stack.rootDir),
|
|
54
|
+
branch: stack.branch === "" ? null : stack.branch,
|
|
55
|
+
odooHttpPort: 0,
|
|
56
|
+
shared: false,
|
|
57
|
+
};
|
|
58
|
+
/**
|
|
59
|
+
* State rows reconciled against docker reality. Labeled stacks unknown to the
|
|
60
|
+
* registry are adopted (inserted best-effort from their labels) before
|
|
61
|
+
* listing. When docker itself is unreachable the registry is still listed,
|
|
62
|
+
* with every stack necessarily reading as `vanished` — callers should warn.
|
|
63
|
+
*/
|
|
64
|
+
export const collectListEntries = (projectId) => Effect.gen(function* () {
|
|
65
|
+
const store = yield* StateStore;
|
|
66
|
+
const compose = yield* DockerCompose;
|
|
67
|
+
const docker = yield* Effect.all([
|
|
68
|
+
compose.listProjects(),
|
|
69
|
+
compose.listLabeledContainers(),
|
|
70
|
+
]).pipe(Effect.map(([projects, labeled]) => ({ projects, labeled, available: true })), Effect.catch(() => Effect.succeed({
|
|
71
|
+
projects: [],
|
|
72
|
+
labeled: [],
|
|
73
|
+
available: false,
|
|
74
|
+
})));
|
|
75
|
+
const known = new Set((yield* store.list({})).map((row) => row.composeProject));
|
|
76
|
+
for (const stack of docker.labeled) {
|
|
77
|
+
if (known.has(stack.composeProject))
|
|
78
|
+
continue;
|
|
79
|
+
const upsert = adoptionUpsert(stack);
|
|
80
|
+
if (upsert !== null)
|
|
81
|
+
yield* store.upsert(upsert);
|
|
82
|
+
}
|
|
83
|
+
const rows = yield* store.list({ projectId });
|
|
84
|
+
const classified = classifyEnvironments({
|
|
85
|
+
rows,
|
|
86
|
+
dockerProjects: docker.projects,
|
|
87
|
+
probes: new Map(),
|
|
88
|
+
olderThanDays: null,
|
|
89
|
+
allowShared: true,
|
|
90
|
+
now: new Date().toISOString(),
|
|
91
|
+
});
|
|
92
|
+
return {
|
|
93
|
+
entries: classified.map(({ row, status }) => ({ row, status })),
|
|
94
|
+
dockerAvailable: docker.available,
|
|
95
|
+
};
|
|
96
|
+
});
|
|
97
|
+
export const listCommand = Command.make("list", {
|
|
98
|
+
allProjects: Flag.boolean("all-projects").pipe(Flag.withDescription("every project in the registry (works without a config)")),
|
|
99
|
+
json: Flag.boolean("json").pipe(Flag.withDescription("print machine-readable JSON")),
|
|
100
|
+
config: Flag.string("config").pipe(Flag.optional),
|
|
101
|
+
}, (flags) => Effect.gen(function* () {
|
|
102
|
+
const projectId = yield* resolveProjectId(flags.config, flags.allProjects);
|
|
103
|
+
const { dockerAvailable, entries } = yield* collectListEntries(projectId);
|
|
104
|
+
if (!dockerAvailable) {
|
|
105
|
+
yield* Console.error("warning: docker is unreachable — every stack reads as vanished");
|
|
106
|
+
}
|
|
107
|
+
if (flags.json) {
|
|
108
|
+
yield* Console.log(JSON.stringify(entries.map(({ row, status }) => ({ ...row, status })), null, 2));
|
|
109
|
+
}
|
|
110
|
+
else if (entries.length === 0) {
|
|
111
|
+
yield* Console.log("No environments recorded.");
|
|
112
|
+
}
|
|
113
|
+
else {
|
|
114
|
+
yield* Console.log(buildListTable(entries, new Date().toISOString()));
|
|
115
|
+
}
|
|
116
|
+
}));
|
|
117
|
+
//# sourceMappingURL=list.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"list.js","sourceRoot":"","sources":["../../src/commands/list.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { Effect, Option } from "effect";
|
|
2
|
+
import { Command } from "effect/unstable/cli";
|
|
3
|
+
import type { OdooAgenticDevConfig } from "../core/project-recipe.js";
|
|
4
|
+
import type { WorktreeContext } from "../core/worktree-context.js";
|
|
5
|
+
import type { ComposeCommandError, DockerUnavailableError } from "../errors/errors.js";
|
|
6
|
+
import type { DockerComposeApi } from "../platform/docker-compose.js";
|
|
7
|
+
export declare const buildLogsArgs: (serviceName: string, follow: boolean) => Array<string>;
|
|
8
|
+
/** Stream `docker compose logs` for one service (default: the odoo service). */
|
|
9
|
+
export declare const runLogs: (recipe: OdooAgenticDevConfig, ctx: WorktreeContext, options: {
|
|
10
|
+
readonly service: string | undefined;
|
|
11
|
+
readonly follow: boolean;
|
|
12
|
+
}) => Effect.Effect<void, ComposeCommandError | DockerUnavailableError, DockerComposeApi>;
|
|
13
|
+
export declare const logsCommand: Command.Command<"logs", {
|
|
14
|
+
readonly service: Option.Option<string>;
|
|
15
|
+
readonly follow: boolean;
|
|
16
|
+
readonly config: Option.Option<string>;
|
|
17
|
+
}, {}, import("../errors/errors.js").RuntimeError, import("../platform/git.js").GitApi | DockerComposeApi>;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { Effect, Option } from "effect";
|
|
2
|
+
import { Argument, Command, Flag } from "effect/unstable/cli";
|
|
3
|
+
import { DockerCompose } from "../platform/docker-compose.js";
|
|
4
|
+
import { resolveContext } from "./resolve-context.js";
|
|
5
|
+
export const buildLogsArgs = (serviceName, follow) => [
|
|
6
|
+
"logs",
|
|
7
|
+
...(follow ? ["-f"] : []),
|
|
8
|
+
serviceName,
|
|
9
|
+
];
|
|
10
|
+
/** Stream `docker compose logs` for one service (default: the odoo service). */
|
|
11
|
+
export const runLogs = (recipe, ctx, options) => Effect.gen(function* () {
|
|
12
|
+
const compose = yield* DockerCompose;
|
|
13
|
+
yield* compose.ensureAvailable();
|
|
14
|
+
const ref = yield* compose.prepareComposeFile(recipe, ctx);
|
|
15
|
+
yield* compose.stream(ref, buildLogsArgs(options.service ?? recipe.odoo.serviceName, options.follow));
|
|
16
|
+
});
|
|
17
|
+
export const logsCommand = Command.make("logs", {
|
|
18
|
+
service: Argument.string("service").pipe(Argument.optional, Argument.withDescription("compose service (defaults to the odoo service)")),
|
|
19
|
+
follow: Flag.boolean("follow").pipe(Flag.withDescription("follow log output")),
|
|
20
|
+
config: Flag.string("config").pipe(Flag.optional),
|
|
21
|
+
}, (flags) => Effect.gen(function* () {
|
|
22
|
+
const { ctx, recipe } = yield* resolveContext(flags.config);
|
|
23
|
+
yield* runLogs(recipe, ctx, {
|
|
24
|
+
service: Option.getOrUndefined(flags.service),
|
|
25
|
+
follow: flags.follow,
|
|
26
|
+
});
|
|
27
|
+
}));
|
|
28
|
+
//# sourceMappingURL=logs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logs.js","sourceRoot":"","sources":["../../src/commands/logs.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AACxC,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,qBAAqB,CAAC;AAI9D,OAAO,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AAE9D,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAEtD,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,WAAmB,EAAE,MAAe,EAAiB,EAAE,CAAC;IACpF,MAAM;IACN,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IACzB,WAAW;CACZ,CAAC;AAEF,gFAAgF;AAChF,MAAM,CAAC,MAAM,OAAO,GAAG,CACrB,MAA4B,EAC5B,GAAoB,EACpB,OAA2E,EACU,EAAE,CACvF,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;IAClB,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,aAAa,CAAC;IACrC,KAAK,CAAC,CAAC,OAAO,CAAC,eAAe,EAAE,CAAC;IACjC,MAAM,GAAG,GAAG,KAAK,CAAC,CAAC,OAAO,CAAC,kBAAkB,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC3D,KAAK,CAAC,CAAC,OAAO,CAAC,MAAM,CACnB,GAAG,EACH,aAAa,CAAC,OAAO,CAAC,OAAO,IAAI,MAAM,CAAC,IAAI,CAAC,WAAW,EAAE,OAAO,CAAC,MAAM,CAAC,CAC1E,CAAC;AACJ,CAAC,CAAC,CAAC;AAEL,MAAM,CAAC,MAAM,WAAW,GAAG,OAAO,CAAC,IAAI,CACrC,MAAM,EACN;IACE,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,IAAI,CACtC,QAAQ,CAAC,QAAQ,EACjB,QAAQ,CAAC,eAAe,CAAC,gDAAgD,CAAC,CAC3E;IACD,MAAM,EAAE,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,eAAe,CAAC,mBAAmB,CAAC,CAAC;IAC9E,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC;CAClD,EACD,CAAC,KAAK,EAAE,EAAE,CACR,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;IAClB,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,KAAK,CAAC,CAAC,cAAc,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IAC5D,KAAK,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,EAAE;QAC1B,OAAO,EAAE,MAAM,CAAC,cAAc,CAAC,KAAK,CAAC,OAAO,CAAC;QAC7C,MAAM,EAAE,KAAK,CAAC,MAAM;KACrB,CAAC,CAAC;AACL,CAAC,CAAC,CACL,CAAC"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { Effect, Option } from "effect";
|
|
2
|
+
import { Command } from "effect/unstable/cli";
|
|
3
|
+
import type { ClassifiedEnvironment, EnvironmentProbe, EnvironmentRow, PruneReason } from "../core/environment.js";
|
|
4
|
+
import type { ComposeCommandError, StateError } from "../errors/errors.js";
|
|
5
|
+
import type { DockerComposeApi } from "../platform/docker-compose.js";
|
|
6
|
+
import type { GitApi } from "../platform/git.js";
|
|
7
|
+
import type { StateStoreApi } from "../platform/state-store.js";
|
|
8
|
+
/**
|
|
9
|
+
* Filesystem/git facts per registry row. A probe failure (root dir exists but
|
|
10
|
+
* is no longer a repo, odd git states) maps to `branchExists: null` — the
|
|
11
|
+
* conservative "branch rule does not apply" answer — never to a prune.
|
|
12
|
+
*/
|
|
13
|
+
export declare const buildProbes: (rows: ReadonlyArray<EnvironmentRow>) => Effect.Effect<ReadonlyMap<string, EnvironmentProbe>, never, GitApi>;
|
|
14
|
+
export type PruneOptions = {
|
|
15
|
+
/** stale threshold; null = staleness never makes a row a candidate */
|
|
16
|
+
readonly olderThanDays: number | null;
|
|
17
|
+
/** without it the run is a dry run: candidates are computed, nothing acts */
|
|
18
|
+
readonly yes: boolean;
|
|
19
|
+
readonly allowShared: boolean;
|
|
20
|
+
/** undefined = all projects */
|
|
21
|
+
readonly projectId: string | undefined;
|
|
22
|
+
/** auto-clean shield: the environment the calling command runs in is never a candidate */
|
|
23
|
+
readonly excludeComposeProject?: string | undefined;
|
|
24
|
+
};
|
|
25
|
+
export type PruneRemoval = {
|
|
26
|
+
readonly composeProject: string;
|
|
27
|
+
readonly reason: PruneReason;
|
|
28
|
+
};
|
|
29
|
+
export type PruneReport = {
|
|
30
|
+
readonly candidates: ReadonlyArray<ClassifiedEnvironment>;
|
|
31
|
+
readonly removed: ReadonlyArray<PruneRemoval>;
|
|
32
|
+
};
|
|
33
|
+
/**
|
|
34
|
+
* The prune routine shared by the `prune` command and `cleanup.auto`. Unlike
|
|
35
|
+
* the auto-clean warning path this has no notion of a "current" environment;
|
|
36
|
+
* callers that have one pass `excludeComposeProject`.
|
|
37
|
+
*/
|
|
38
|
+
export declare const runPrune: (options: PruneOptions) => Effect.Effect<PruneReport, StateError | ComposeCommandError, StateStoreApi | DockerComposeApi | GitApi>;
|
|
39
|
+
/**
|
|
40
|
+
* Render a prune report and apply the exit-code contract: a dry run that
|
|
41
|
+
* found candidates exits 1 (via process.exitCode — the Effect still succeeds).
|
|
42
|
+
*/
|
|
43
|
+
export declare const reportPrune: (report: PruneReport, options: {
|
|
44
|
+
readonly yes: boolean;
|
|
45
|
+
readonly json: boolean;
|
|
46
|
+
}) => Effect.Effect<void>;
|
|
47
|
+
export declare const pruneCommand: Command.Command<"prune", {
|
|
48
|
+
readonly olderThan: Option.Option<number>;
|
|
49
|
+
readonly allProjects: boolean;
|
|
50
|
+
readonly yes: boolean;
|
|
51
|
+
readonly allowShared: boolean;
|
|
52
|
+
readonly json: boolean;
|
|
53
|
+
readonly config: Option.Option<string>;
|
|
54
|
+
}, {}, import("../errors/errors.js").ConfigLoadError | import("../errors/errors.js").ConfigValidationError | ComposeCommandError | StateError, GitApi | DockerComposeApi | StateStoreApi>;
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import { existsSync } from "node:fs";
|
|
2
|
+
import { Console, Effect, Option } from "effect";
|
|
3
|
+
import { Command, Flag } from "effect/unstable/cli";
|
|
4
|
+
import { classifyEnvironments } from "../core/environment.js";
|
|
5
|
+
import { DockerCompose } from "../platform/docker-compose.js";
|
|
6
|
+
import { Git } from "../platform/git.js";
|
|
7
|
+
import { StateStore } from "../platform/state-store.js";
|
|
8
|
+
import { relativeAge } from "./list.js";
|
|
9
|
+
import { resolveProjectId } from "./resolve-context.js";
|
|
10
|
+
/**
|
|
11
|
+
* Filesystem/git facts per registry row. A probe failure (root dir exists but
|
|
12
|
+
* is no longer a repo, odd git states) maps to `branchExists: null` — the
|
|
13
|
+
* conservative "branch rule does not apply" answer — never to a prune.
|
|
14
|
+
*/
|
|
15
|
+
export const buildProbes = (rows) => Effect.gen(function* () {
|
|
16
|
+
const git = yield* Git;
|
|
17
|
+
const probes = new Map();
|
|
18
|
+
for (const row of rows) {
|
|
19
|
+
const rootDirExists = existsSync(row.rootDir);
|
|
20
|
+
const branchExists = rootDirExists && row.branch !== null
|
|
21
|
+
? yield* git
|
|
22
|
+
.branchExists(row.rootDir, row.branch)
|
|
23
|
+
.pipe(Effect.catch(() => Effect.succeed(null)))
|
|
24
|
+
: null;
|
|
25
|
+
probes.set(row.composeProject, { rootDirExists, branchExists });
|
|
26
|
+
}
|
|
27
|
+
return probes;
|
|
28
|
+
});
|
|
29
|
+
/**
|
|
30
|
+
* The prune routine shared by the `prune` command and `cleanup.auto`. Unlike
|
|
31
|
+
* the auto-clean warning path this has no notion of a "current" environment;
|
|
32
|
+
* callers that have one pass `excludeComposeProject`.
|
|
33
|
+
*/
|
|
34
|
+
export const runPrune = (options) => Effect.gen(function* () {
|
|
35
|
+
const store = yield* StateStore;
|
|
36
|
+
const compose = yield* DockerCompose;
|
|
37
|
+
const rows = yield* store.list({ projectId: options.projectId });
|
|
38
|
+
// an empty registry can have no candidates: skip docker discovery entirely
|
|
39
|
+
// so `prune` still works (and exits 0) where docker is absent or down
|
|
40
|
+
if (rows.length === 0)
|
|
41
|
+
return { candidates: [], removed: [] };
|
|
42
|
+
const dockerProjects = yield* compose.listProjects();
|
|
43
|
+
const probes = yield* buildProbes(rows);
|
|
44
|
+
const classified = classifyEnvironments({
|
|
45
|
+
rows,
|
|
46
|
+
dockerProjects,
|
|
47
|
+
probes,
|
|
48
|
+
olderThanDays: options.olderThanDays,
|
|
49
|
+
allowShared: options.allowShared,
|
|
50
|
+
now: new Date().toISOString(),
|
|
51
|
+
});
|
|
52
|
+
const candidates = classified.filter((c) => c.reason !== "keep" &&
|
|
53
|
+
c.reason !== "shared-skipped" &&
|
|
54
|
+
c.row.composeProject !== options.excludeComposeProject);
|
|
55
|
+
if (!options.yes)
|
|
56
|
+
return { candidates, removed: [] };
|
|
57
|
+
const removed = [];
|
|
58
|
+
for (const candidate of candidates) {
|
|
59
|
+
// teardown order: docker resources first, then the row — failing midway
|
|
60
|
+
// leaves the row behind for the next run instead of orphaning containers.
|
|
61
|
+
// vanished rows are swept too: a manual `docker compose down` removes
|
|
62
|
+
// the containers but can leave labeled volumes behind (no-op otherwise)
|
|
63
|
+
yield* compose.removeByLabel(candidate.row.composeProject);
|
|
64
|
+
yield* store.remove(candidate.row.composeProject);
|
|
65
|
+
removed.push({ composeProject: candidate.row.composeProject, reason: candidate.reason });
|
|
66
|
+
}
|
|
67
|
+
return { candidates, removed };
|
|
68
|
+
});
|
|
69
|
+
/**
|
|
70
|
+
* Render a prune report and apply the exit-code contract: a dry run that
|
|
71
|
+
* found candidates exits 1 (via process.exitCode — the Effect still succeeds).
|
|
72
|
+
*/
|
|
73
|
+
export const reportPrune = (report, options) => Effect.gen(function* () {
|
|
74
|
+
if (options.json) {
|
|
75
|
+
yield* Console.log(JSON.stringify({
|
|
76
|
+
applied: options.yes,
|
|
77
|
+
candidates: report.candidates.map((c) => ({
|
|
78
|
+
...c.row,
|
|
79
|
+
status: c.status,
|
|
80
|
+
reason: c.reason,
|
|
81
|
+
})),
|
|
82
|
+
removed: report.removed,
|
|
83
|
+
}, null, 2));
|
|
84
|
+
}
|
|
85
|
+
else if (report.candidates.length === 0) {
|
|
86
|
+
yield* Console.log("Nothing to prune.");
|
|
87
|
+
}
|
|
88
|
+
else {
|
|
89
|
+
const now = new Date().toISOString();
|
|
90
|
+
for (const c of report.candidates) {
|
|
91
|
+
yield* Console.log(`${c.row.composeProject} ${c.row.databaseName} ${relativeAge(c.row.lastUsedAt, now)} ${c.reason}`);
|
|
92
|
+
}
|
|
93
|
+
yield* options.yes
|
|
94
|
+
? Console.log(`Removed ${report.removed.length} environment(s).`)
|
|
95
|
+
: Console.log("Dry run — re-run with --yes to remove these environments.");
|
|
96
|
+
}
|
|
97
|
+
if (!options.yes && report.candidates.length > 0) {
|
|
98
|
+
process.exitCode = 1;
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
export const pruneCommand = Command.make("prune", {
|
|
102
|
+
olderThan: Flag.integer("older-than").pipe(Flag.optional, Flag.withDescription("also prune environments unused for more than <days>")),
|
|
103
|
+
allProjects: Flag.boolean("all-projects").pipe(Flag.withDescription("every project in the registry (works without a config)")),
|
|
104
|
+
yes: Flag.boolean("yes").pipe(Flag.withDescription("actually remove (without it: dry run, exit 1 when candidates exist)")),
|
|
105
|
+
allowShared: Flag.boolean("allow-shared"),
|
|
106
|
+
json: Flag.boolean("json").pipe(Flag.withDescription("print machine-readable JSON")),
|
|
107
|
+
config: Flag.string("config").pipe(Flag.optional),
|
|
108
|
+
}, (flags) => Effect.gen(function* () {
|
|
109
|
+
const projectId = yield* resolveProjectId(flags.config, flags.allProjects);
|
|
110
|
+
const report = yield* runPrune({
|
|
111
|
+
olderThanDays: Option.getOrUndefined(flags.olderThan) ?? null,
|
|
112
|
+
yes: flags.yes,
|
|
113
|
+
allowShared: flags.allowShared,
|
|
114
|
+
projectId,
|
|
115
|
+
});
|
|
116
|
+
yield* reportPrune(report, { yes: flags.yes, json: flags.json });
|
|
117
|
+
}));
|
|
118
|
+
//# sourceMappingURL=prune.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prune.js","sourceRoot":"","sources":["../../src/commands/prune.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { Command } from "effect/unstable/cli";
|
|
2
|
+
import type { OdooAgenticDevConfig } from "../core/project-recipe.js";
|
|
3
|
+
import type { WorktreeContext } from "../core/worktree-context.js";
|
|
4
|
+
export declare const buildPsqlArgs: (recipe: OdooAgenticDevConfig, ctx: WorktreeContext, extraArgs: ReadonlyArray<string>) => Array<string>;
|
|
5
|
+
export declare const psqlCommand: Command.Command<"psql", {
|
|
6
|
+
readonly args: readonly string[];
|
|
7
|
+
readonly config: import("effect/Option").Option<string>;
|
|
8
|
+
}, {}, import("../errors/errors.js").RuntimeError, import("../platform/command-runner.js").CommandRunnerApi | import("../platform/git.js").GitApi | import("../platform/docker-compose.js").DockerComposeApi | import("../platform/state-store.js").StateStoreApi>;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { Effect } from "effect";
|
|
2
|
+
import { Argument, Command, Flag } from "effect/unstable/cli";
|
|
3
|
+
import { resolveContext } from "./resolve-context.js";
|
|
4
|
+
import { runInteractivePassthrough } from "./shell.js";
|
|
5
|
+
import { trailingOperands } from "./trailing-args.js";
|
|
6
|
+
export const buildPsqlArgs = (recipe, ctx, extraArgs) => [
|
|
7
|
+
"exec",
|
|
8
|
+
recipe.odoo.databaseServiceName,
|
|
9
|
+
"psql",
|
|
10
|
+
"-U",
|
|
11
|
+
"odoo",
|
|
12
|
+
"-d",
|
|
13
|
+
ctx.databaseName,
|
|
14
|
+
...extraArgs,
|
|
15
|
+
];
|
|
16
|
+
export const psqlCommand = Command.make("psql", {
|
|
17
|
+
args: Argument.string("args").pipe(Argument.variadic(), Argument.withDescription("extra psql arguments (pass them after --)")),
|
|
18
|
+
config: Flag.string("config").pipe(Flag.optional),
|
|
19
|
+
}, (flags) => Effect.gen(function* () {
|
|
20
|
+
const { ctx, recipe } = yield* resolveContext(flags.config);
|
|
21
|
+
const extraArgs = [...flags.args, ...trailingOperands()];
|
|
22
|
+
yield* runInteractivePassthrough(recipe, ctx, buildPsqlArgs(recipe, ctx, extraArgs));
|
|
23
|
+
}));
|
|
24
|
+
//# sourceMappingURL=psql.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"psql.js","sourceRoot":"","sources":["../../src/commands/psql.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAChC,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,qBAAqB,CAAC;AAG9D,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,yBAAyB,EAAE,MAAM,YAAY,CAAC;AACvD,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAEtD,MAAM,CAAC,MAAM,aAAa,GAAG,CAC3B,MAA4B,EAC5B,GAAoB,EACpB,SAAgC,EACjB,EAAE,CAAC;IAClB,MAAM;IACN,MAAM,CAAC,IAAI,CAAC,mBAAmB;IAC/B,MAAM;IACN,IAAI;IACJ,MAAM;IACN,IAAI;IACJ,GAAG,CAAC,YAAY;IAChB,GAAG,SAAS;CACb,CAAC;AAEF,MAAM,CAAC,MAAM,WAAW,GAAG,OAAO,CAAC,IAAI,CACrC,MAAM,EACN;IACE,IAAI,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAChC,QAAQ,CAAC,QAAQ,EAAE,EACnB,QAAQ,CAAC,eAAe,CAAC,2CAA2C,CAAC,CACtE;IACD,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC;CAClD,EACD,CAAC,KAAK,EAAE,EAAE,CACR,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;IAClB,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,KAAK,CAAC,CAAC,cAAc,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IAC5D,MAAM,SAAS,GAAG,CAAC,GAAG,KAAK,CAAC,IAAI,EAAE,GAAG,gBAAgB,EAAE,CAAC,CAAC;IACzD,KAAK,CAAC,CAAC,yBAAyB,CAAC,MAAM,EAAE,GAAG,EAAE,aAAa,CAAC,MAAM,EAAE,GAAG,EAAE,SAAS,CAAC,CAAC,CAAC;AACvF,CAAC,CAAC,CACL,CAAC"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { Effect, Option } from "effect";
|
|
2
|
+
import { Command } from "effect/unstable/cli";
|
|
3
|
+
import type { OdooAgenticDevConfig } from "../core/project-recipe.js";
|
|
4
|
+
import type { WorktreeContext } from "../core/worktree-context.js";
|
|
5
|
+
import type { ResetPath } from "../core/environment.js";
|
|
6
|
+
import type { OdooLifecycleApi } from "../platform/odoo-lifecycle.js";
|
|
7
|
+
import type { StateStoreApi } from "../platform/state-store.js";
|
|
8
|
+
import type { RuntimeError, SharedDatabaseProtectionError } from "../errors/errors.js";
|
|
9
|
+
export declare const guardReset: (recipe: OdooAgenticDevConfig, ctx: WorktreeContext, allowShared: boolean) => Effect.Effect<void, SharedDatabaseProtectionError>;
|
|
10
|
+
export declare const parseModulesFlag: (value: string | undefined) => Array<string> | undefined;
|
|
11
|
+
export type ResetFlowOptions = {
|
|
12
|
+
readonly noTemplate: boolean;
|
|
13
|
+
readonly refreshTemplate: boolean;
|
|
14
|
+
readonly modules: ReadonlyArray<string> | undefined;
|
|
15
|
+
readonly withoutDemo: string | undefined;
|
|
16
|
+
/** decorative-output sink; defaults to Console.log (json mode passes a recorder) */
|
|
17
|
+
readonly say?: ((line: string) => Effect.Effect<void>) | undefined;
|
|
18
|
+
};
|
|
19
|
+
/**
|
|
20
|
+
* The shared reset-db flow (used by `reset-db` and `setup`): decide between a
|
|
21
|
+
* fast template restore and a full init, run it, and snapshot after the
|
|
22
|
+
* post-init hooks when the decision calls for it. The pre-action line is
|
|
23
|
+
* printed before any destructive work on every path.
|
|
24
|
+
*/
|
|
25
|
+
export declare const runResetFlow: (recipe: OdooAgenticDevConfig, ctx: WorktreeContext, options: ResetFlowOptions) => Effect.Effect<ResetPath, RuntimeError, OdooLifecycleApi | StateStoreApi>;
|
|
26
|
+
export declare const resetDbCommand: Command.Command<"reset-db", {
|
|
27
|
+
readonly allowShared: boolean;
|
|
28
|
+
readonly modules: Option.Option<string>;
|
|
29
|
+
readonly withoutDemo: Option.Option<string>;
|
|
30
|
+
readonly noTemplate: boolean;
|
|
31
|
+
readonly refreshTemplate: boolean;
|
|
32
|
+
readonly json: boolean;
|
|
33
|
+
readonly config: Option.Option<string>;
|
|
34
|
+
}, {}, RuntimeError, import("../platform/git.js").GitApi | OdooLifecycleApi | StateStoreApi>;
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { Console, Effect, Option } from "effect";
|
|
2
|
+
import { Command, Flag } from "effect/unstable/cli";
|
|
3
|
+
import { assertSharedDatabaseAllowed } from "../core/safety.js";
|
|
4
|
+
import { computeTemplateKey, decideResetPath, templateDbName } from "../core/environment.js";
|
|
5
|
+
import { OdooLifecycle } from "../platform/odoo-lifecycle.js";
|
|
6
|
+
import { StateStore } from "../platform/state-store.js";
|
|
7
|
+
import { resolveContext } from "./resolve-context.js";
|
|
8
|
+
import { recordEnvironment } from "./state-hooks.js";
|
|
9
|
+
import { resetPathActions, withJsonReport } from "./json-report.js";
|
|
10
|
+
export const guardReset = (recipe, ctx, allowShared) => assertSharedDatabaseAllowed({
|
|
11
|
+
databaseName: ctx.databaseName,
|
|
12
|
+
sharedDatabase: recipe.project.sharedDatabase,
|
|
13
|
+
allowShared,
|
|
14
|
+
action: "reset-db",
|
|
15
|
+
});
|
|
16
|
+
export const parseModulesFlag = (value) => value
|
|
17
|
+
?.split(",")
|
|
18
|
+
.map((m) => m.trim())
|
|
19
|
+
.filter((m) => m.length > 0);
|
|
20
|
+
/**
|
|
21
|
+
* The shared reset-db flow (used by `reset-db` and `setup`): decide between a
|
|
22
|
+
* fast template restore and a full init, run it, and snapshot after the
|
|
23
|
+
* post-init hooks when the decision calls for it. The pre-action line is
|
|
24
|
+
* printed before any destructive work on every path.
|
|
25
|
+
*/
|
|
26
|
+
export const runResetFlow = (recipe, ctx, options) => Effect.gen(function* () {
|
|
27
|
+
const say = options.say ?? Console.log;
|
|
28
|
+
const store = yield* StateStore;
|
|
29
|
+
const lifecycle = yield* OdooLifecycle;
|
|
30
|
+
const expectedKey = computeTemplateKey(recipe);
|
|
31
|
+
const row = yield* store.get(ctx.composeProjectName);
|
|
32
|
+
const path = decideResetPath({
|
|
33
|
+
row,
|
|
34
|
+
expectedKey,
|
|
35
|
+
databaseName: ctx.databaseName,
|
|
36
|
+
noTemplate: options.noTemplate,
|
|
37
|
+
refreshTemplate: options.refreshTemplate,
|
|
38
|
+
hasOverrides: options.modules !== undefined || options.withoutDemo !== undefined,
|
|
39
|
+
});
|
|
40
|
+
if (path === "restore") {
|
|
41
|
+
yield* say(`Restoring database: ${ctx.databaseName} (from template ${templateDbName(ctx.databaseName)})`);
|
|
42
|
+
yield* lifecycle.restoreFromTemplate(recipe, ctx);
|
|
43
|
+
yield* say("Restored from template (post-init hooks already baked in).");
|
|
44
|
+
return path;
|
|
45
|
+
}
|
|
46
|
+
yield* say(`Resetting database: ${ctx.databaseName}`);
|
|
47
|
+
yield* say(`Compose project: ${ctx.composeProjectName}`);
|
|
48
|
+
yield* lifecycle.resetDatabase(recipe, ctx, {
|
|
49
|
+
modules: options.modules,
|
|
50
|
+
withoutDemo: options.withoutDemo,
|
|
51
|
+
});
|
|
52
|
+
yield* lifecycle.runPostInitHooks(recipe, ctx);
|
|
53
|
+
if (path === "full-then-snapshot") {
|
|
54
|
+
yield* lifecycle.snapshotTemplate(recipe, ctx);
|
|
55
|
+
yield* store.setTemplate(ctx.composeProjectName, {
|
|
56
|
+
databaseName: templateDbName(ctx.databaseName),
|
|
57
|
+
key: expectedKey,
|
|
58
|
+
});
|
|
59
|
+
yield* say(`Template snapshot saved: ${templateDbName(ctx.databaseName)}`);
|
|
60
|
+
}
|
|
61
|
+
return path;
|
|
62
|
+
});
|
|
63
|
+
export const resetDbCommand = Command.make("reset-db", {
|
|
64
|
+
allowShared: Flag.boolean("allow-shared"),
|
|
65
|
+
modules: Flag.string("modules").pipe(Flag.optional, Flag.withDescription("comma-separated module list (defaults to recipe initialModules)")),
|
|
66
|
+
withoutDemo: Flag.string("without-demo").pipe(Flag.optional),
|
|
67
|
+
noTemplate: Flag.boolean("no-template").pipe(Flag.withDescription("full init even when a template snapshot exists (template kept)")),
|
|
68
|
+
refreshTemplate: Flag.boolean("refresh-template").pipe(Flag.withDescription("full init and take a fresh template snapshot")),
|
|
69
|
+
json: Flag.boolean("json").pipe(Flag.withDescription("suppress decorative output; print one final JSON report line")),
|
|
70
|
+
config: Flag.string("config").pipe(Flag.optional),
|
|
71
|
+
}, (flags) => withJsonReport("reset-db", flags.json, (report) => Effect.gen(function* () {
|
|
72
|
+
const { ctx, recipe } = yield* resolveContext(flags.config);
|
|
73
|
+
yield* report.setContext(ctx);
|
|
74
|
+
yield* guardReset(recipe, ctx, flags.allowShared);
|
|
75
|
+
yield* recordEnvironment(recipe, ctx);
|
|
76
|
+
const path = yield* runResetFlow(recipe, ctx, {
|
|
77
|
+
noTemplate: flags.noTemplate,
|
|
78
|
+
refreshTemplate: flags.refreshTemplate,
|
|
79
|
+
modules: parseModulesFlag(Option.getOrUndefined(flags.modules)),
|
|
80
|
+
withoutDemo: Option.getOrUndefined(flags.withoutDemo),
|
|
81
|
+
say: report.say,
|
|
82
|
+
});
|
|
83
|
+
yield* Effect.forEach(resetPathActions(path), report.action);
|
|
84
|
+
yield* report.say(`Done. Odoo URL: ${ctx.odooBaseUrl}/web?db=${ctx.databaseName}`);
|
|
85
|
+
})));
|
|
86
|
+
//# sourceMappingURL=reset-db.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reset-db.js","sourceRoot":"","sources":["../../src/commands/reset-db.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { Effect, Option } from "effect";
|
|
2
|
+
import type { WorktreeContext } from "../core/worktree-context.js";
|
|
3
|
+
import type { OdooAgenticDevConfig } from "../core/project-recipe.js";
|
|
4
|
+
import type { GitApi } from "../platform/git.js";
|
|
5
|
+
import type { ConfigLoadError, ConfigValidationError, RuntimeError } from "../errors/errors.js";
|
|
6
|
+
export type ResolvedContext = {
|
|
7
|
+
readonly recipe: OdooAgenticDevConfig;
|
|
8
|
+
readonly ctx: WorktreeContext;
|
|
9
|
+
};
|
|
10
|
+
/** Shared preamble for every command: config + git -> context. */
|
|
11
|
+
export declare const resolveContext: (configFlag: Option.Option<string>) => Effect.Effect<ResolvedContext, RuntimeError, GitApi>;
|
|
12
|
+
/**
|
|
13
|
+
* Project scope for `list`/`prune`: `--all-projects` means "no filter" and
|
|
14
|
+
* deliberately skips config discovery entirely, so these commands work from
|
|
15
|
+
* any directory; otherwise the discovered recipe's project id is the scope.
|
|
16
|
+
*/
|
|
17
|
+
export declare const resolveProjectId: (configFlag: Option.Option<string>, allProjects: boolean) => Effect.Effect<string | undefined, ConfigLoadError | ConfigValidationError>;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { Effect, Option } from "effect";
|
|
2
|
+
import { loadRecipe } from "../config/load-recipe.js";
|
|
3
|
+
import { buildWorktreeContext } from "../core/worktree-context.js";
|
|
4
|
+
import { Git } from "../platform/git.js";
|
|
5
|
+
/** Shared preamble for every command: config + git -> context. */
|
|
6
|
+
export const resolveContext = (configFlag) => Effect.gen(function* () {
|
|
7
|
+
const env = process.env;
|
|
8
|
+
const { recipe, rootDir } = yield* loadRecipe({
|
|
9
|
+
cwd: process.cwd(),
|
|
10
|
+
explicitPath: Option.getOrUndefined(configFlag),
|
|
11
|
+
env,
|
|
12
|
+
});
|
|
13
|
+
const git = yield* Git;
|
|
14
|
+
const gitState = yield* git.state(rootDir);
|
|
15
|
+
const ctx = yield* buildWorktreeContext({ rootDir, recipe, env, git: gitState });
|
|
16
|
+
return { recipe, ctx };
|
|
17
|
+
});
|
|
18
|
+
/**
|
|
19
|
+
* Project scope for `list`/`prune`: `--all-projects` means "no filter" and
|
|
20
|
+
* deliberately skips config discovery entirely, so these commands work from
|
|
21
|
+
* any directory; otherwise the discovered recipe's project id is the scope.
|
|
22
|
+
*/
|
|
23
|
+
export const resolveProjectId = (configFlag, allProjects) => allProjects
|
|
24
|
+
? Effect.succeed(undefined)
|
|
25
|
+
: loadRecipe({
|
|
26
|
+
cwd: process.cwd(),
|
|
27
|
+
explicitPath: Option.getOrUndefined(configFlag),
|
|
28
|
+
env: process.env,
|
|
29
|
+
}).pipe(Effect.map(({ recipe }) => recipe.project.id));
|
|
30
|
+
//# sourceMappingURL=resolve-context.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolve-context.js","sourceRoot":"","sources":["../../src/commands/resolve-context.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AACxC,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AACtD,OAAO,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AAGnE,OAAO,EAAE,GAAG,EAAE,MAAM,oBAAoB,CAAC;AASzC,kEAAkE;AAClE,MAAM,CAAC,MAAM,cAAc,GAAG,CAC5B,UAAiC,EACqB,EAAE,CACxD,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;IAClB,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC;IACxB,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,KAAK,CAAC,CAAC,UAAU,CAAC;QAC5C,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE;QAClB,YAAY,EAAE,MAAM,CAAC,cAAc,CAAC,UAAU,CAAC;QAC/C,GAAG;KACJ,CAAC,CAAC;IACH,MAAM,GAAG,GAAG,KAAK,CAAC,CAAC,GAAG,CAAC;IACvB,MAAM,QAAQ,GAAG,KAAK,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAC3C,MAAM,GAAG,GAAG,KAAK,CAAC,CAAC,oBAAoB,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,GAAG,EAAE,QAAQ,EAAE,CAAC,CAAC;IACjF,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC;AACzB,CAAC,CAAC,CAAC;AAEL;;;;GAIG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAC9B,UAAiC,EACjC,WAAoB,EACwD,EAAE,CAC9E,WAAW;IACT,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC;IAC3B,CAAC,CAAC,UAAU,CAAC;QACT,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE;QAClB,YAAY,EAAE,MAAM,CAAC,cAAc,CAAC,UAAU,CAAC;QAC/C,GAAG,EAAE,OAAO,CAAC,GAAG;KACjB,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC"}
|