@merchantduo/code 0.1.0-beta.0 → 0.2.0-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +132 -99
- package/dist/app/runtime.d.ts +30 -0
- package/dist/app/runtime.js +56 -0
- package/dist/app/status.d.ts +3 -0
- package/dist/app/status.js +9 -0
- package/dist/app/system-prompt.d.ts +2 -0
- package/dist/{skills.js → app/system-prompt.js} +3 -32
- package/dist/cli/arguments.d.ts +10 -0
- package/dist/cli/arguments.js +34 -0
- package/dist/cli/commands/agent.d.ts +1 -0
- package/dist/cli/commands/agent.js +33 -0
- package/dist/cli/commands/doctor.d.ts +3 -0
- package/dist/cli/commands/doctor.js +14 -0
- package/dist/cli/commands/init.d.ts +9 -0
- package/dist/cli/commands/init.js +68 -0
- package/dist/cli/commands/provision.d.ts +6 -0
- package/dist/cli/commands/provision.js +35 -0
- package/dist/cli/main.js +31 -0
- package/dist/config/index.d.ts +11 -0
- package/dist/config/index.js +15 -0
- package/dist/config/loader.d.ts +10 -0
- package/dist/config/loader.js +61 -0
- package/dist/config/paths.d.ts +1 -0
- package/dist/config/paths.js +7 -0
- package/dist/config/project-store.d.ts +2 -0
- package/dist/config/project-store.js +12 -0
- package/dist/config/schema.d.ts +210 -0
- package/dist/config/schema.js +36 -0
- package/dist/config/trust-store.d.ts +3 -0
- package/dist/config/trust-store.js +29 -0
- package/dist/environments/adapter.d.ts +5 -0
- package/dist/environments/adapters/local.d.ts +12 -0
- package/dist/environments/adapters/local.js +14 -0
- package/dist/environments/adapters/ssh.d.ts +11 -0
- package/dist/environments/adapters/ssh.js +24 -0
- package/dist/environments/adapters/warden.d.ts +13 -0
- package/dist/environments/adapters/warden.js +24 -0
- package/dist/environments/backend.d.ts +13 -0
- package/dist/environments/backend.js +73 -0
- package/dist/environments/executor.d.ts +23 -0
- package/dist/environments/factory.d.ts +3 -0
- package/dist/environments/factory.js +13 -0
- package/dist/environments/model.d.ts +28 -0
- package/dist/environments/model.js +3 -0
- package/dist/environments/path-policy.d.ts +1 -0
- package/dist/environments/path-policy.js +8 -0
- package/dist/{mage2gen.d.ts → features/mage2gen/service.d.ts} +0 -1
- package/dist/{mage2gen.js → features/mage2gen/service.js} +8 -3
- package/dist/integrations/pi/context.d.ts +2 -0
- package/dist/integrations/pi/context.js +46 -0
- package/dist/integrations/pi/mage2gen.d.ts +2 -0
- package/dist/integrations/pi/mage2gen.js +19 -0
- package/dist/integrations/pi/permissions.d.ts +6 -0
- package/dist/integrations/pi/permissions.js +36 -0
- package/dist/integrations/pi/session.d.ts +12 -0
- package/dist/integrations/pi/session.js +9 -0
- package/dist/integrations/pi/testing.d.ts +2 -0
- package/dist/integrations/pi/testing.js +88 -0
- package/dist/integrations/pi/theme.d.ts +2 -0
- package/dist/integrations/pi/theme.js +6 -0
- package/dist/integrations/pi/workflows.d.ts +2 -0
- package/dist/integrations/pi/workflows.js +26 -0
- package/dist/integrations/pi/workspace.d.ts +5 -0
- package/dist/integrations/pi/workspace.js +33 -0
- package/dist/magento/deploy-mode.d.ts +2 -0
- package/dist/magento/deploy-mode.js +10 -0
- package/dist/magento/index.d.ts +5 -0
- package/dist/magento/index.js +4 -0
- package/dist/magento/inspector.d.ts +9 -0
- package/dist/magento/inspector.js +56 -0
- package/dist/magento/model.d.ts +25 -0
- package/dist/magento/prompt.d.ts +2 -0
- package/dist/magento/prompt.js +3 -0
- package/dist/magento/themes.d.ts +3 -0
- package/dist/magento/themes.js +46 -0
- package/dist/provision/advisor.d.ts +12 -0
- package/dist/provision/advisor.js +28 -0
- package/dist/provision/discovery.d.ts +12 -0
- package/dist/provision/discovery.js +61 -0
- package/dist/provision/interview.d.ts +9 -0
- package/dist/provision/interview.js +29 -0
- package/dist/provision/model.d.ts +82 -0
- package/dist/provision/model.js +5 -0
- package/dist/provision/planner.d.ts +4 -0
- package/dist/provision/planner.js +51 -0
- package/dist/provision/runner.d.ts +35 -0
- package/dist/provision/runner.js +98 -0
- package/dist/shared/package-paths.d.ts +3 -0
- package/dist/shared/package-paths.js +10 -0
- package/dist/testing/discovery.d.ts +10 -0
- package/dist/testing/discovery.js +68 -0
- package/dist/testing/host.d.ts +29 -0
- package/dist/testing/host.js +50 -0
- package/dist/testing/index.d.ts +5 -0
- package/dist/testing/index.js +5 -0
- package/dist/testing/magerun.d.ts +8 -0
- package/dist/testing/magerun.js +73 -0
- package/dist/testing/model.d.ts +18 -0
- package/dist/testing/url.d.ts +4 -0
- package/dist/testing/url.js +26 -0
- package/dist/workflows/builtins.d.ts +2 -0
- package/dist/workflows/builtins.js +38 -0
- package/dist/workflows/change-tracker.d.ts +9 -0
- package/dist/workflows/change-tracker.js +38 -0
- package/dist/workflows/definition.d.ts +7 -0
- package/dist/workflows/index.d.ts +4 -0
- package/dist/workflows/index.js +3 -0
- package/dist/workflows/runner.d.ts +7 -0
- package/dist/workflows/runner.js +28 -0
- package/package.json +32 -9
- package/skills/magento-testing/SKILL.md +10 -0
- package/dist/backend.d.ts +0 -24
- package/dist/backend.js +0 -103
- package/dist/cli.js +0 -89
- package/dist/config.d.ts +0 -127
- package/dist/config.js +0 -170
- package/dist/config.test.js +0 -51
- package/dist/constants.d.ts +0 -20
- package/dist/constants.js +0 -15
- package/dist/mage2gen.test.js +0 -6
- package/dist/magento.d.ts +0 -40
- package/dist/magento.js +0 -119
- package/dist/magento.test.js +0 -31
- package/dist/skills.d.ts +0 -11
- package/dist/skills.test.js +0 -34
- package/dist/workflow.d.ts +0 -20
- package/dist/workflow.js +0 -67
- package/dist/workflow.test.js +0 -17
- package/extensions/merchantduo.js +0 -311
- /package/dist/{cli.d.ts → cli/main.d.ts} +0 -0
- /package/dist/{config.test.d.ts → environments/adapter.js} +0 -0
- /package/dist/{mage2gen.test.d.ts → environments/executor.js} +0 -0
- /package/dist/{magento.test.d.ts → magento/model.js} +0 -0
- /package/dist/{skills.test.d.ts → testing/model.js} +0 -0
- /package/dist/{workflow.test.d.ts → workflows/definition.js} +0 -0
package/dist/backend.js
DELETED
|
@@ -1,103 +0,0 @@
|
|
|
1
|
-
import { spawn } from "node:child_process";
|
|
2
|
-
import { relative, resolve } from "node:path";
|
|
3
|
-
const MAX_OUTPUT = 64 * 1024;
|
|
4
|
-
export function contain(root, candidate) {
|
|
5
|
-
const full = resolve(root, candidate);
|
|
6
|
-
if (relative(root, full).startsWith(".."))
|
|
7
|
-
throw new Error(`Path escapes configured root: ${candidate}`);
|
|
8
|
-
return full;
|
|
9
|
-
}
|
|
10
|
-
export class Backend {
|
|
11
|
-
environment;
|
|
12
|
-
localRoot;
|
|
13
|
-
constructor(environment, localRoot) {
|
|
14
|
-
this.environment = environment;
|
|
15
|
-
this.localRoot = localRoot;
|
|
16
|
-
}
|
|
17
|
-
path(path) {
|
|
18
|
-
if (this.environment.type === "local")
|
|
19
|
-
return contain(resolve(this.localRoot, this.environment.root), path);
|
|
20
|
-
if (!path.startsWith("/"))
|
|
21
|
-
return `${this.environment.root}/${path}`;
|
|
22
|
-
return contain(this.environment.root, path);
|
|
23
|
-
}
|
|
24
|
-
command(argv, target) {
|
|
25
|
-
if (this.environment.type === "local")
|
|
26
|
-
return {
|
|
27
|
-
file: argv[0],
|
|
28
|
-
args: argv.slice(1),
|
|
29
|
-
cwd: resolve(this.localRoot, this.environment.root),
|
|
30
|
-
};
|
|
31
|
-
if (this.environment.type === "warden") {
|
|
32
|
-
const service = target
|
|
33
|
-
? this.environment.targets[target]
|
|
34
|
-
: this.environment.filesService;
|
|
35
|
-
if (!service)
|
|
36
|
-
throw new Error(`Unknown Warden target: ${target}`);
|
|
37
|
-
return {
|
|
38
|
-
file: "warden",
|
|
39
|
-
args: ["env", "exec", "-T", service, ...argv],
|
|
40
|
-
cwd: resolve(this.localRoot, this.environment.projectRoot),
|
|
41
|
-
};
|
|
42
|
-
}
|
|
43
|
-
return {
|
|
44
|
-
file: "ssh",
|
|
45
|
-
args: [
|
|
46
|
-
this.environment.host,
|
|
47
|
-
`cd ${shell(this.environment.root)} && ${argv.map(shell).join(" ")}`,
|
|
48
|
-
],
|
|
49
|
-
};
|
|
50
|
-
}
|
|
51
|
-
async run(argv, options = {}) {
|
|
52
|
-
const spec = this.command(argv, options.target);
|
|
53
|
-
return new Promise((resolveResult) => {
|
|
54
|
-
const child = spawn(spec.file, spec.args, {
|
|
55
|
-
cwd: spec.cwd,
|
|
56
|
-
signal: options.signal,
|
|
57
|
-
detached: process.platform !== "win32",
|
|
58
|
-
});
|
|
59
|
-
let out = "", err = "", truncated = false, settled = false;
|
|
60
|
-
const finish = (result) => {
|
|
61
|
-
if (!settled) {
|
|
62
|
-
settled = true;
|
|
63
|
-
resolveResult(result);
|
|
64
|
-
}
|
|
65
|
-
};
|
|
66
|
-
const add = (old, buf) => {
|
|
67
|
-
const next = old + buf.toString();
|
|
68
|
-
if (next.length > MAX_OUTPUT) {
|
|
69
|
-
truncated = true;
|
|
70
|
-
return next.slice(0, MAX_OUTPUT);
|
|
71
|
-
}
|
|
72
|
-
return next;
|
|
73
|
-
};
|
|
74
|
-
child.stdout.on("data", (b) => {
|
|
75
|
-
out = add(out, b);
|
|
76
|
-
});
|
|
77
|
-
child.stderr.on("data", (b) => {
|
|
78
|
-
err = add(err, b);
|
|
79
|
-
});
|
|
80
|
-
const timer = options.timeoutMs
|
|
81
|
-
? setTimeout(() => child.kill("SIGTERM"), options.timeoutMs)
|
|
82
|
-
: undefined;
|
|
83
|
-
child.on("error", (error) => {
|
|
84
|
-
if (timer)
|
|
85
|
-
clearTimeout(timer);
|
|
86
|
-
finish({
|
|
87
|
-
stdout: out,
|
|
88
|
-
stderr: error.message,
|
|
89
|
-
exitCode: 127,
|
|
90
|
-
truncated,
|
|
91
|
-
});
|
|
92
|
-
});
|
|
93
|
-
child.on("close", (code) => {
|
|
94
|
-
if (timer)
|
|
95
|
-
clearTimeout(timer);
|
|
96
|
-
finish({ stdout: out, stderr: err, exitCode: code ?? 1, truncated });
|
|
97
|
-
});
|
|
98
|
-
});
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
function shell(value) {
|
|
102
|
-
return `'${value.replace(/'/g, "'\\''")}'`;
|
|
103
|
-
}
|
package/dist/cli.js
DELETED
|
@@ -1,89 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import { spawn } from "node:child_process";
|
|
3
|
-
import { access, mkdir, writeFile } from "node:fs/promises";
|
|
4
|
-
import { dirname, resolve } from "node:path";
|
|
5
|
-
import { Backend } from "./backend.js";
|
|
6
|
-
import { isTrusted, loadConfig, merchantHome, selectEnvironment, starterYaml, trustProject, } from "./config.js";
|
|
7
|
-
import { snapshot } from "./magento.js";
|
|
8
|
-
import { KNOWLEDGE_MCP_URL } from "./constants.js";
|
|
9
|
-
const args = process.argv.slice(2);
|
|
10
|
-
const command = args[0];
|
|
11
|
-
const flag = (name) => {
|
|
12
|
-
const i = args.indexOf(name);
|
|
13
|
-
return i >= 0 ? args[i + 1] : undefined;
|
|
14
|
-
};
|
|
15
|
-
async function main() {
|
|
16
|
-
if (command === "init") {
|
|
17
|
-
const path = resolve(process.cwd(), ".merchantduo.yaml");
|
|
18
|
-
try {
|
|
19
|
-
await access(path);
|
|
20
|
-
throw new Error(`${path} already exists`);
|
|
21
|
-
}
|
|
22
|
-
catch (e) {
|
|
23
|
-
if (!e.code || e.code !== "ENOENT")
|
|
24
|
-
throw e;
|
|
25
|
-
}
|
|
26
|
-
await writeFile(path, starterYaml(), { mode: 0o600 });
|
|
27
|
-
console.log(`Created ${path}`);
|
|
28
|
-
return;
|
|
29
|
-
}
|
|
30
|
-
const { config, configPath } = await loadConfig(process.cwd(), {
|
|
31
|
-
config: flag("--config"),
|
|
32
|
-
});
|
|
33
|
-
const chosen = selectEnvironment(config, process.cwd(), flag("--env"));
|
|
34
|
-
if (configPath && !(await isTrusted(configPath))) {
|
|
35
|
-
if (process.env.MERCHANTDUO_TRUST_CONFIG === "1")
|
|
36
|
-
await trustProject(configPath);
|
|
37
|
-
else if (!process.stdin.isTTY)
|
|
38
|
-
throw new Error(`Untrusted MerchantDuo configuration: ${configPath}. Review it and run with MERCHANTDUO_TRUST_CONFIG=1 once.`);
|
|
39
|
-
else {
|
|
40
|
-
process.stderr.write(`Trust MerchantDuo config ${configPath}? Set MERCHANTDUO_TRUST_CONFIG=1 to approve.\n`);
|
|
41
|
-
process.exitCode = 2;
|
|
42
|
-
return;
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
const backend = new Backend(chosen.environment, process.cwd());
|
|
46
|
-
if (command === "doctor") {
|
|
47
|
-
const magento = await snapshot(backend);
|
|
48
|
-
const diagnostics = {
|
|
49
|
-
environment: chosen.name,
|
|
50
|
-
type: chosen.environment.type,
|
|
51
|
-
writable: chosen.environment.type !== "ssh" || chosen.environment.writable,
|
|
52
|
-
magento,
|
|
53
|
-
activeTheme: config.activeTheme,
|
|
54
|
-
mcp: {
|
|
55
|
-
url: KNOWLEDGE_MCP_URL,
|
|
56
|
-
tokenConfigured: Boolean(process.env.MERCHANTDUO_MCP_TOKEN),
|
|
57
|
-
},
|
|
58
|
-
};
|
|
59
|
-
console.log(JSON.stringify(diagnostics, null, 2));
|
|
60
|
-
return;
|
|
61
|
-
}
|
|
62
|
-
const extension = resolve(dirname(new URL(import.meta.url).pathname), "../extensions/merchantduo.js");
|
|
63
|
-
const piArgs = args.filter((_, i) => args[i - 1] !== "--env" &&
|
|
64
|
-
args[i - 1] !== "--config" &&
|
|
65
|
-
!["--env", "--config"].includes(args[i]));
|
|
66
|
-
const state = merchantHome();
|
|
67
|
-
await mkdir(state, { recursive: true, mode: 0o700 });
|
|
68
|
-
const child = spawn("npx", [
|
|
69
|
-
"--yes",
|
|
70
|
-
`@earendil-works/pi-coding-agent@0.84.1`,
|
|
71
|
-
"--extension",
|
|
72
|
-
extension,
|
|
73
|
-
...piArgs,
|
|
74
|
-
], {
|
|
75
|
-
stdio: "inherit",
|
|
76
|
-
env: {
|
|
77
|
-
...process.env,
|
|
78
|
-
PI_CODING_AGENT_DIR: resolve(state, "pi"),
|
|
79
|
-
MERCHANTDUO_SELECTED_ENV: chosen.name,
|
|
80
|
-
MERCHANTDUO_CONFIG_PATH: configPath ?? "",
|
|
81
|
-
MERCHANTDUO_PACKAGE_VERSION: "0.1.0-beta.0",
|
|
82
|
-
},
|
|
83
|
-
});
|
|
84
|
-
child.on("exit", (code) => process.exit(code ?? 1));
|
|
85
|
-
}
|
|
86
|
-
main().catch((error) => {
|
|
87
|
-
console.error(`merchantduo: ${error.message}`);
|
|
88
|
-
process.exitCode = 1;
|
|
89
|
-
});
|
package/dist/config.d.ts
DELETED
|
@@ -1,127 +0,0 @@
|
|
|
1
|
-
import { z } from "zod";
|
|
2
|
-
export declare const ConfigSchema: z.ZodObject<{
|
|
3
|
-
version: z.ZodLiteral<1>;
|
|
4
|
-
defaultEnvironment: z.ZodOptional<z.ZodString>;
|
|
5
|
-
activeTheme: z.ZodDefault<z.ZodString>;
|
|
6
|
-
automation: z.ZodDefault<z.ZodObject<{
|
|
7
|
-
syntaxChecks: z.ZodDefault<z.ZodEnum<["auto", "off"]>>;
|
|
8
|
-
cacheClean: z.ZodDefault<z.ZodEnum<["auto", "off"]>>;
|
|
9
|
-
}, "strict", z.ZodTypeAny, {
|
|
10
|
-
syntaxChecks: "auto" | "off";
|
|
11
|
-
cacheClean: "auto" | "off";
|
|
12
|
-
}, {
|
|
13
|
-
syntaxChecks?: "auto" | "off" | undefined;
|
|
14
|
-
cacheClean?: "auto" | "off" | undefined;
|
|
15
|
-
}>>;
|
|
16
|
-
environments: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodUnion<[z.ZodObject<{
|
|
17
|
-
type: z.ZodLiteral<"local">;
|
|
18
|
-
root: z.ZodString;
|
|
19
|
-
}, "strict", z.ZodTypeAny, {
|
|
20
|
-
type: "local";
|
|
21
|
-
root: string;
|
|
22
|
-
}, {
|
|
23
|
-
type: "local";
|
|
24
|
-
root: string;
|
|
25
|
-
}>, z.ZodObject<{
|
|
26
|
-
type: z.ZodLiteral<"warden">;
|
|
27
|
-
projectRoot: z.ZodString;
|
|
28
|
-
root: z.ZodString;
|
|
29
|
-
filesService: z.ZodDefault<z.ZodString>;
|
|
30
|
-
targets: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
31
|
-
}, "strict", z.ZodTypeAny, {
|
|
32
|
-
type: "warden";
|
|
33
|
-
root: string;
|
|
34
|
-
projectRoot: string;
|
|
35
|
-
filesService: string;
|
|
36
|
-
targets: Record<string, string>;
|
|
37
|
-
}, {
|
|
38
|
-
type: "warden";
|
|
39
|
-
root: string;
|
|
40
|
-
projectRoot: string;
|
|
41
|
-
filesService?: string | undefined;
|
|
42
|
-
targets?: Record<string, string> | undefined;
|
|
43
|
-
}>, z.ZodObject<{
|
|
44
|
-
type: z.ZodLiteral<"ssh">;
|
|
45
|
-
host: z.ZodString;
|
|
46
|
-
root: z.ZodString;
|
|
47
|
-
writable: z.ZodDefault<z.ZodBoolean>;
|
|
48
|
-
}, "strict", z.ZodTypeAny, {
|
|
49
|
-
type: "ssh";
|
|
50
|
-
root: string;
|
|
51
|
-
host: string;
|
|
52
|
-
writable: boolean;
|
|
53
|
-
}, {
|
|
54
|
-
type: "ssh";
|
|
55
|
-
root: string;
|
|
56
|
-
host: string;
|
|
57
|
-
writable?: boolean | undefined;
|
|
58
|
-
}>]>>>;
|
|
59
|
-
}, "strict", z.ZodTypeAny, {
|
|
60
|
-
version: 1;
|
|
61
|
-
activeTheme: string;
|
|
62
|
-
automation: {
|
|
63
|
-
syntaxChecks: "auto" | "off";
|
|
64
|
-
cacheClean: "auto" | "off";
|
|
65
|
-
};
|
|
66
|
-
environments: Record<string, {
|
|
67
|
-
type: "local";
|
|
68
|
-
root: string;
|
|
69
|
-
} | {
|
|
70
|
-
type: "warden";
|
|
71
|
-
root: string;
|
|
72
|
-
projectRoot: string;
|
|
73
|
-
filesService: string;
|
|
74
|
-
targets: Record<string, string>;
|
|
75
|
-
} | {
|
|
76
|
-
type: "ssh";
|
|
77
|
-
root: string;
|
|
78
|
-
host: string;
|
|
79
|
-
writable: boolean;
|
|
80
|
-
}>;
|
|
81
|
-
defaultEnvironment?: string | undefined;
|
|
82
|
-
}, {
|
|
83
|
-
version: 1;
|
|
84
|
-
defaultEnvironment?: string | undefined;
|
|
85
|
-
activeTheme?: string | undefined;
|
|
86
|
-
automation?: {
|
|
87
|
-
syntaxChecks?: "auto" | "off" | undefined;
|
|
88
|
-
cacheClean?: "auto" | "off" | undefined;
|
|
89
|
-
} | undefined;
|
|
90
|
-
environments?: Record<string, {
|
|
91
|
-
type: "local";
|
|
92
|
-
root: string;
|
|
93
|
-
} | {
|
|
94
|
-
type: "warden";
|
|
95
|
-
root: string;
|
|
96
|
-
projectRoot: string;
|
|
97
|
-
filesService?: string | undefined;
|
|
98
|
-
targets?: Record<string, string> | undefined;
|
|
99
|
-
} | {
|
|
100
|
-
type: "ssh";
|
|
101
|
-
root: string;
|
|
102
|
-
host: string;
|
|
103
|
-
writable?: boolean | undefined;
|
|
104
|
-
}> | undefined;
|
|
105
|
-
}>;
|
|
106
|
-
export type MerchantConfig = z.infer<typeof ConfigSchema>;
|
|
107
|
-
export type Environment = MerchantConfig["environments"][string];
|
|
108
|
-
export declare const template: MerchantConfig;
|
|
109
|
-
export declare function merchantHome(env?: NodeJS.ProcessEnv): string;
|
|
110
|
-
export declare function interpolate(value: string, env?: NodeJS.ProcessEnv): string;
|
|
111
|
-
export declare function loadConfig(cwd: string, options?: {
|
|
112
|
-
config?: string;
|
|
113
|
-
env?: NodeJS.ProcessEnv;
|
|
114
|
-
}): Promise<{
|
|
115
|
-
config: MerchantConfig;
|
|
116
|
-
configPath?: string;
|
|
117
|
-
}>;
|
|
118
|
-
/** Persist only the project-scoped theme selection and preserve all other YAML data. */
|
|
119
|
-
export declare function setActiveTheme(configPath: string, activeTheme: string, env?: NodeJS.ProcessEnv): Promise<MerchantConfig>;
|
|
120
|
-
export declare function selectEnvironment(config: MerchantConfig, cwd: string, requested?: string, env?: NodeJS.ProcessEnv): {
|
|
121
|
-
name: string;
|
|
122
|
-
environment: Environment;
|
|
123
|
-
};
|
|
124
|
-
export declare function configDigest(content: string): string;
|
|
125
|
-
export declare function trustProject(configPath: string, env?: NodeJS.ProcessEnv): Promise<void>;
|
|
126
|
-
export declare function isTrusted(configPath: string, env?: NodeJS.ProcessEnv): Promise<boolean>;
|
|
127
|
-
export declare function starterYaml(): string;
|
package/dist/config.js
DELETED
|
@@ -1,170 +0,0 @@
|
|
|
1
|
-
import { createHash } from "node:crypto";
|
|
2
|
-
import { mkdir, readFile, writeFile } from "node:fs/promises";
|
|
3
|
-
import { homedir } from "node:os";
|
|
4
|
-
import { dirname, resolve } from "node:path";
|
|
5
|
-
import { parse, stringify } from "yaml";
|
|
6
|
-
import { z } from "zod";
|
|
7
|
-
const automation = z
|
|
8
|
-
.object({
|
|
9
|
-
syntaxChecks: z.enum(["auto", "off"]).default("auto"),
|
|
10
|
-
cacheClean: z.enum(["auto", "off"]).default("auto"),
|
|
11
|
-
})
|
|
12
|
-
.strict()
|
|
13
|
-
.default({});
|
|
14
|
-
const local = z.object({ type: z.literal("local"), root: z.string() }).strict();
|
|
15
|
-
const warden = z
|
|
16
|
-
.object({
|
|
17
|
-
type: z.literal("warden"),
|
|
18
|
-
projectRoot: z.string(),
|
|
19
|
-
root: z.string(),
|
|
20
|
-
filesService: z.string().default("php-fpm"),
|
|
21
|
-
targets: z.record(z.string()).default({ default: "php-fpm" }),
|
|
22
|
-
})
|
|
23
|
-
.strict();
|
|
24
|
-
const ssh = z
|
|
25
|
-
.object({
|
|
26
|
-
type: z.literal("ssh"),
|
|
27
|
-
host: z.string().min(1),
|
|
28
|
-
root: z.string(),
|
|
29
|
-
writable: z.boolean().default(false),
|
|
30
|
-
})
|
|
31
|
-
.strict();
|
|
32
|
-
export const ConfigSchema = z
|
|
33
|
-
.object({
|
|
34
|
-
version: z.literal(1),
|
|
35
|
-
defaultEnvironment: z.string().optional(),
|
|
36
|
-
activeTheme: z.string().default("all"),
|
|
37
|
-
automation,
|
|
38
|
-
environments: z.record(z.union([local, warden, ssh])).default({}),
|
|
39
|
-
})
|
|
40
|
-
.strict();
|
|
41
|
-
export const template = {
|
|
42
|
-
version: 1,
|
|
43
|
-
defaultEnvironment: "default",
|
|
44
|
-
activeTheme: "all",
|
|
45
|
-
automation: { syntaxChecks: "auto", cacheClean: "auto" },
|
|
46
|
-
environments: {
|
|
47
|
-
default: { type: "local", root: "." },
|
|
48
|
-
warden: {
|
|
49
|
-
type: "warden",
|
|
50
|
-
projectRoot: ".",
|
|
51
|
-
root: "/var/www/html",
|
|
52
|
-
filesService: "php-fpm",
|
|
53
|
-
targets: { default: "php-fpm", debug: "php-debug" },
|
|
54
|
-
},
|
|
55
|
-
remote: {
|
|
56
|
-
type: "ssh",
|
|
57
|
-
host: "example1-stage",
|
|
58
|
-
root: "/var/www/html",
|
|
59
|
-
writable: false,
|
|
60
|
-
},
|
|
61
|
-
},
|
|
62
|
-
};
|
|
63
|
-
export function merchantHome(env = process.env) {
|
|
64
|
-
return env.MERCHANTDUO_HOME
|
|
65
|
-
? resolve(env.MERCHANTDUO_HOME)
|
|
66
|
-
: resolve(homedir(), ".merchantduo");
|
|
67
|
-
}
|
|
68
|
-
export function interpolate(value, env = process.env) {
|
|
69
|
-
return value.replace(/\$\{([A-Z][A-Z0-9_]*)\}/g, (_, name) => {
|
|
70
|
-
if (!env[name])
|
|
71
|
-
throw new Error(`Missing required environment variable: ${name}`);
|
|
72
|
-
return env[name];
|
|
73
|
-
});
|
|
74
|
-
}
|
|
75
|
-
function expand(value, env) {
|
|
76
|
-
if (typeof value === "string")
|
|
77
|
-
return interpolate(value, env);
|
|
78
|
-
if (Array.isArray(value))
|
|
79
|
-
return value.map((v) => expand(v, env));
|
|
80
|
-
if (value && typeof value === "object")
|
|
81
|
-
return Object.fromEntries(Object.entries(value).map(([k, v]) => [k, expand(v, env)]));
|
|
82
|
-
return value;
|
|
83
|
-
}
|
|
84
|
-
async function readYaml(path, env) {
|
|
85
|
-
try {
|
|
86
|
-
return parse(await readFile(path, "utf8"));
|
|
87
|
-
}
|
|
88
|
-
catch (e) {
|
|
89
|
-
if (e.code === "ENOENT")
|
|
90
|
-
return undefined;
|
|
91
|
-
throw new Error(`Cannot load ${path}: ${e.message}`);
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
export async function loadConfig(cwd, options = {}) {
|
|
95
|
-
const env = options.env ?? process.env;
|
|
96
|
-
const home = merchantHome(env);
|
|
97
|
-
const global = await readYaml(resolve(home, "config.yaml"), env);
|
|
98
|
-
const configPath = options.config ??
|
|
99
|
-
env.MERCHANTDUO_CONFIG ??
|
|
100
|
-
resolve(cwd, ".merchantduo.yaml");
|
|
101
|
-
const project = await readYaml(configPath, env);
|
|
102
|
-
const raw = {
|
|
103
|
-
...(global ?? {}),
|
|
104
|
-
...(project ?? {}),
|
|
105
|
-
environments: {
|
|
106
|
-
...(global?.environments ?? {}),
|
|
107
|
-
...(project?.environments ?? {}),
|
|
108
|
-
},
|
|
109
|
-
};
|
|
110
|
-
if (!project && !global)
|
|
111
|
-
return {
|
|
112
|
-
config: ConfigSchema.parse({
|
|
113
|
-
version: 1,
|
|
114
|
-
environments: { local: { type: "local", root: "." } },
|
|
115
|
-
}),
|
|
116
|
-
};
|
|
117
|
-
return {
|
|
118
|
-
config: ConfigSchema.parse(expand(raw, env)),
|
|
119
|
-
configPath: project ? resolve(configPath) : undefined,
|
|
120
|
-
};
|
|
121
|
-
}
|
|
122
|
-
/** Persist only the project-scoped theme selection and preserve all other YAML data. */
|
|
123
|
-
export async function setActiveTheme(configPath, activeTheme, env = process.env) {
|
|
124
|
-
const source = await readFile(configPath, "utf8");
|
|
125
|
-
const raw = parse(source);
|
|
126
|
-
if (!raw || typeof raw !== "object" || Array.isArray(raw))
|
|
127
|
-
throw new Error(`Cannot update ${configPath}: expected a YAML object`);
|
|
128
|
-
const updated = { ...raw, activeTheme };
|
|
129
|
-
const config = ConfigSchema.parse(expand(updated, env));
|
|
130
|
-
await writeFile(configPath, stringify(updated), { mode: 0o600 });
|
|
131
|
-
return config;
|
|
132
|
-
}
|
|
133
|
-
export function selectEnvironment(config, cwd, requested, env = process.env) {
|
|
134
|
-
const name = requested ?? env.MERCHANTDUO_ENV ?? config.defaultEnvironment;
|
|
135
|
-
if (name) {
|
|
136
|
-
const environment = config.environments[name];
|
|
137
|
-
if (!environment)
|
|
138
|
-
throw new Error(`Unknown MerchantDuo environment: ${name}`);
|
|
139
|
-
return { name, environment };
|
|
140
|
-
}
|
|
141
|
-
return { name: "local", environment: { type: "local", root: cwd } };
|
|
142
|
-
}
|
|
143
|
-
export function configDigest(content) {
|
|
144
|
-
return createHash("sha256").update(content).digest("hex");
|
|
145
|
-
}
|
|
146
|
-
export async function trustProject(configPath, env = process.env) {
|
|
147
|
-
const digest = configDigest(await readFile(configPath, "utf8"));
|
|
148
|
-
const path = resolve(merchantHome(env), "trust.json");
|
|
149
|
-
await mkdir(dirname(path), { recursive: true, mode: 0o700 });
|
|
150
|
-
let trust = {};
|
|
151
|
-
try {
|
|
152
|
-
trust = JSON.parse(await readFile(path, "utf8"));
|
|
153
|
-
}
|
|
154
|
-
catch { }
|
|
155
|
-
trust[resolve(configPath)] = digest;
|
|
156
|
-
await writeFile(path, JSON.stringify(trust, null, 2), { mode: 0o600 });
|
|
157
|
-
}
|
|
158
|
-
export async function isTrusted(configPath, env = process.env) {
|
|
159
|
-
try {
|
|
160
|
-
const trust = JSON.parse(await readFile(resolve(merchantHome(env), "trust.json"), "utf8"));
|
|
161
|
-
return (trust[resolve(configPath)] ===
|
|
162
|
-
configDigest(await readFile(configPath, "utf8")));
|
|
163
|
-
}
|
|
164
|
-
catch {
|
|
165
|
-
return false;
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
export function starterYaml() {
|
|
169
|
-
return stringify(template);
|
|
170
|
-
}
|
package/dist/config.test.js
DELETED
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
import assert from "node:assert/strict";
|
|
2
|
-
import test from "node:test";
|
|
3
|
-
import { mkdtemp, writeFile } from "node:fs/promises";
|
|
4
|
-
import { tmpdir } from "node:os";
|
|
5
|
-
import { join } from "node:path";
|
|
6
|
-
import { configDigest, loadConfig, selectEnvironment, setActiveTheme } from "./config.js";
|
|
7
|
-
import { contain, Backend } from "./backend.js";
|
|
8
|
-
test("project environments replace global names and environment precedence is deterministic", async () => {
|
|
9
|
-
const root = await mkdtemp(join(tmpdir(), "merchantduo-"));
|
|
10
|
-
const home = join(root, "home");
|
|
11
|
-
await writeFile(join(root, ".merchantduo.yaml"), "version: 1\ndefaultEnvironment: stage\nenvironments:\n stage:\n type: local\n root: app\n");
|
|
12
|
-
const { config } = await loadConfig(root, {
|
|
13
|
-
env: { MERCHANTDUO_HOME: home },
|
|
14
|
-
});
|
|
15
|
-
assert.equal(selectEnvironment(config, root, "stage").environment.type, "local");
|
|
16
|
-
assert.equal(selectEnvironment(config, root, undefined, { MERCHANTDUO_ENV: "stage" })
|
|
17
|
-
.name, "stage");
|
|
18
|
-
});
|
|
19
|
-
test("activeTheme defaults to all and persists without dropping other project settings", async () => {
|
|
20
|
-
const root = await mkdtemp(join(tmpdir(), "merchantduo-"));
|
|
21
|
-
const path = join(root, ".merchantduo.yaml");
|
|
22
|
-
await writeFile(path, "version: 1\ndefaultEnvironment: default\nenvironments:\n default:\n type: local\n root: .\n");
|
|
23
|
-
assert.equal((await loadConfig(root)).config.activeTheme, "all");
|
|
24
|
-
const updated = await setActiveTheme(path, "Acme/store");
|
|
25
|
-
assert.equal(updated.activeTheme, "Acme/store");
|
|
26
|
-
assert.equal((await loadConfig(root)).config.defaultEnvironment, "default");
|
|
27
|
-
});
|
|
28
|
-
test("interpolation rejects missing variables and config digests are stable", async () => {
|
|
29
|
-
const root = await mkdtemp(join(tmpdir(), "merchantduo-"));
|
|
30
|
-
await writeFile(join(root, ".merchantduo.yaml"), "version: 1\nenvironments:\n default:\n type: local\n root: ${MISSING}\n");
|
|
31
|
-
await assert.rejects(() => loadConfig(root, { env: {} }), /Missing required/);
|
|
32
|
-
assert.equal(configDigest("x"), configDigest("x"));
|
|
33
|
-
assert.notEqual(configDigest("x"), configDigest("y"));
|
|
34
|
-
});
|
|
35
|
-
test("backend contains local paths and constructs Warden target execution", () => {
|
|
36
|
-
assert.throws(() => contain("/project", "../outside"));
|
|
37
|
-
const b = new Backend({
|
|
38
|
-
type: "warden",
|
|
39
|
-
projectRoot: ".",
|
|
40
|
-
root: "/var/www/html",
|
|
41
|
-
filesService: "php-fpm",
|
|
42
|
-
targets: { debug: "php-debug" },
|
|
43
|
-
}, "/project");
|
|
44
|
-
assert.deepEqual(b.command(["php", "-v"], "debug").args.slice(0, 5), [
|
|
45
|
-
"env",
|
|
46
|
-
"exec",
|
|
47
|
-
"-T",
|
|
48
|
-
"php-debug",
|
|
49
|
-
"php",
|
|
50
|
-
]);
|
|
51
|
-
});
|
package/dist/constants.d.ts
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
/** The only v1 location for intentionally non-production provider values. */
|
|
2
|
-
export declare const PROVIDER: {
|
|
3
|
-
readonly id: "merchantduo";
|
|
4
|
-
readonly baseUrl: "https://merchantduo.invalid/v1";
|
|
5
|
-
readonly model: "merchantduo-mock";
|
|
6
|
-
readonly contextWindow: 32768;
|
|
7
|
-
readonly maxTokens: 4096;
|
|
8
|
-
readonly input: readonly ["text"];
|
|
9
|
-
readonly reasoning: false;
|
|
10
|
-
readonly cost: {
|
|
11
|
-
readonly input: 0;
|
|
12
|
-
readonly output: 0;
|
|
13
|
-
readonly cacheRead: 0;
|
|
14
|
-
readonly cacheWrite: 0;
|
|
15
|
-
};
|
|
16
|
-
};
|
|
17
|
-
export declare const PI_VERSION = "0.84.1";
|
|
18
|
-
/** Replace this single beta placeholder with the production knowledge MCP endpoint. */
|
|
19
|
-
export declare const KNOWLEDGE_MCP_URL = "https://merchantduo.invalid/mcp";
|
|
20
|
-
export declare const KNOWLEDGE_MCP_TOKEN_ENV = "MERCHANTDUO_MCP_TOKEN";
|
package/dist/constants.js
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
/** The only v1 location for intentionally non-production provider values. */
|
|
2
|
-
export const PROVIDER = {
|
|
3
|
-
id: "merchantduo",
|
|
4
|
-
baseUrl: "https://merchantduo.invalid/v1",
|
|
5
|
-
model: "merchantduo-mock",
|
|
6
|
-
contextWindow: 32_768,
|
|
7
|
-
maxTokens: 4_096,
|
|
8
|
-
input: ["text"],
|
|
9
|
-
reasoning: false,
|
|
10
|
-
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
|
|
11
|
-
};
|
|
12
|
-
export const PI_VERSION = "0.84.1";
|
|
13
|
-
/** Replace this single beta placeholder with the production knowledge MCP endpoint. */
|
|
14
|
-
export const KNOWLEDGE_MCP_URL = "https://merchantduo.invalid/mcp";
|
|
15
|
-
export const KNOWLEDGE_MCP_TOKEN_ENV = "MERCHANTDUO_MCP_TOKEN";
|
package/dist/mage2gen.test.js
DELETED
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
import assert from "node:assert/strict";
|
|
2
|
-
import test from "node:test";
|
|
3
|
-
import { mage2genDestination } from "./mage2gen.js";
|
|
4
|
-
test("Mage2Gen module destinations stay under the selected project app/code root", () => {
|
|
5
|
-
assert.equal(mage2genDestination("/project", "Perspective", "FreshStocks"), "/project/app/code/Perspective/FreshStocks");
|
|
6
|
-
});
|
package/dist/magento.d.ts
DELETED
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
import type { Backend } from "./backend.js";
|
|
2
|
-
export type MagentoSnapshot = {
|
|
3
|
-
version?: string;
|
|
4
|
-
edition?: "Open Source" | "Adobe Commerce";
|
|
5
|
-
phpVersion?: string;
|
|
6
|
-
mode?: MagentoDeployMode;
|
|
7
|
-
cacheTypes: string[];
|
|
8
|
-
modulesEnabled?: number;
|
|
9
|
-
warnings: string[];
|
|
10
|
-
evidence: string[];
|
|
11
|
-
themes: MagentoTheme[];
|
|
12
|
-
};
|
|
13
|
-
export type MagentoDeployMode = "default" | "developer" | "production";
|
|
14
|
-
export type MagentoTheme = {
|
|
15
|
-
code: string;
|
|
16
|
-
title?: string;
|
|
17
|
-
path: string;
|
|
18
|
-
parentChain: string[];
|
|
19
|
-
kind: "luma" | "hyva" | "other";
|
|
20
|
-
};
|
|
21
|
-
type RawTheme = {
|
|
22
|
-
code: string;
|
|
23
|
-
path: string;
|
|
24
|
-
title?: string;
|
|
25
|
-
parent?: string;
|
|
26
|
-
};
|
|
27
|
-
/**
|
|
28
|
-
* Build a registered-theme graph. Metadata is accepted only from registration.php
|
|
29
|
-
* locations and theme.xml values; malformed/missing parents remain non-fatal.
|
|
30
|
-
*/
|
|
31
|
-
export declare function resolveThemes(themes: RawTheme[]): MagentoTheme[];
|
|
32
|
-
export declare function parseRegisteredThemes(output: string): RawTheme[];
|
|
33
|
-
/**
|
|
34
|
-
* Accept only successful Magento CLI output that names one known deployment mode.
|
|
35
|
-
* A failed or unrecognised probe must not influence operational recommendations.
|
|
36
|
-
*/
|
|
37
|
-
export declare function parseDeployMode(output: string, exitCode: number): MagentoDeployMode | undefined;
|
|
38
|
-
export declare function snapshot(backend: Backend): Promise<MagentoSnapshot>;
|
|
39
|
-
export declare function snapshotPrompt(envName: string, writable: boolean, status: string, s: MagentoSnapshot): string;
|
|
40
|
-
export {};
|