@mozole/cli 1.4.3 → 2.0.0-b
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +16 -4
- package/README.md +85 -112
- package/dist/cli.d.ts +2 -2
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +204 -184
- package/dist/cli.js.map +1 -1
- package/dist/commands/adopt.d.ts +5 -10
- package/dist/commands/adopt.d.ts.map +1 -1
- package/dist/commands/adopt.js +49 -849
- package/dist/commands/adopt.js.map +1 -1
- package/dist/commands/doctor.d.ts +1 -7
- package/dist/commands/doctor.d.ts.map +1 -1
- package/dist/commands/doctor.js +69 -377
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/new.d.ts +8 -10
- package/dist/commands/new.d.ts.map +1 -1
- package/dist/commands/new.js +32 -197
- package/dist/commands/new.js.map +1 -1
- package/dist/commands/phase.d.ts +11 -0
- package/dist/commands/phase.d.ts.map +1 -0
- package/dist/commands/phase.js +106 -0
- package/dist/commands/phase.js.map +1 -0
- package/dist/commands/prototype.d.ts +6 -0
- package/dist/commands/prototype.d.ts.map +1 -0
- package/dist/commands/prototype.js +28 -0
- package/dist/commands/prototype.js.map +1 -0
- package/dist/commands/repomap.d.ts +6 -0
- package/dist/commands/repomap.d.ts.map +1 -0
- package/dist/commands/repomap.js +71 -0
- package/dist/commands/repomap.js.map +1 -0
- package/dist/commands/test.d.ts +6 -0
- package/dist/commands/test.d.ts.map +1 -0
- package/dist/commands/test.js +115 -0
- package/dist/commands/test.js.map +1 -0
- package/dist/commands/ui.d.ts +1 -42
- package/dist/commands/ui.d.ts.map +1 -1
- package/dist/commands/ui.js +74 -466
- package/dist/commands/ui.js.map +1 -1
- package/dist/commands/verify.d.ts +12 -7
- package/dist/commands/verify.d.ts.map +1 -1
- package/dist/commands/verify.js +148 -65
- package/dist/commands/verify.js.map +1 -1
- package/dist/qa/a11y.d.ts +24 -0
- package/dist/qa/a11y.d.ts.map +1 -0
- package/dist/qa/a11y.js +124 -0
- package/dist/qa/a11y.js.map +1 -0
- package/dist/qa/breakpoints.d.ts +16 -0
- package/dist/qa/breakpoints.d.ts.map +1 -0
- package/dist/qa/breakpoints.js +45 -0
- package/dist/qa/breakpoints.js.map +1 -0
- package/dist/qa/contract.d.ts +21 -0
- package/dist/qa/contract.d.ts.map +1 -0
- package/dist/qa/contract.js +116 -0
- package/dist/qa/contract.js.map +1 -0
- package/dist/qa/index.d.ts +6 -0
- package/dist/qa/index.d.ts.map +1 -0
- package/dist/qa/index.js +6 -0
- package/dist/qa/index.js.map +1 -0
- package/dist/qa/probe.d.ts +48 -0
- package/dist/qa/probe.d.ts.map +1 -0
- package/dist/qa/probe.js +206 -0
- package/dist/qa/probe.js.map +1 -0
- package/dist/qa/runner.d.ts +27 -33
- package/dist/qa/runner.d.ts.map +1 -1
- package/dist/qa/runner.js +286 -332
- package/dist/qa/runner.js.map +1 -1
- package/dist/scaffold/agents.d.ts +5 -0
- package/dist/scaffold/agents.d.ts.map +1 -0
- package/dist/scaffold/agents.js +84 -0
- package/dist/scaffold/agents.js.map +1 -0
- package/dist/scaffold/backend.d.ts +6 -8
- package/dist/scaffold/backend.d.ts.map +1 -1
- package/dist/scaffold/backend.js +318 -199
- package/dist/scaffold/backend.js.map +1 -1
- package/dist/scaffold/design.d.ts +4 -3
- package/dist/scaffold/design.d.ts.map +1 -1
- package/dist/scaffold/design.js +38 -47
- package/dist/scaffold/design.js.map +1 -1
- package/dist/scaffold/flagship.d.ts +8 -0
- package/dist/scaffold/flagship.d.ts.map +1 -0
- package/dist/scaffold/flagship.js +337 -0
- package/dist/scaffold/flagship.js.map +1 -0
- package/dist/scaffold/index.d.ts +9 -0
- package/dist/scaffold/index.d.ts.map +1 -0
- package/dist/scaffold/index.js +48 -0
- package/dist/scaffold/index.js.map +1 -0
- package/dist/scaffold/phases.d.ts +10 -0
- package/dist/scaffold/phases.d.ts.map +1 -0
- package/dist/scaffold/phases.js +165 -0
- package/dist/scaffold/phases.js.map +1 -0
- package/dist/scaffold/repomap.d.ts +6 -0
- package/dist/scaffold/repomap.d.ts.map +1 -0
- package/dist/scaffold/repomap.js +89 -0
- package/dist/scaffold/repomap.js.map +1 -0
- package/dist/scaffold/standard.d.ts +13 -0
- package/dist/scaffold/standard.d.ts.map +1 -0
- package/dist/scaffold/standard.js +371 -0
- package/dist/scaffold/standard.js.map +1 -0
- package/dist/scaffold/tokens.d.ts +3 -0
- package/dist/scaffold/tokens.d.ts.map +1 -0
- package/dist/scaffold/tokens.js +126 -0
- package/dist/scaffold/tokens.js.map +1 -0
- package/dist/server/manager.d.ts +23 -0
- package/dist/server/manager.d.ts.map +1 -0
- package/dist/server/manager.js +96 -0
- package/dist/server/manager.js.map +1 -0
- package/dist/utils/ai-trace.d.ts +8 -0
- package/dist/utils/ai-trace.d.ts.map +1 -0
- package/dist/utils/ai-trace.js +69 -0
- package/dist/utils/ai-trace.js.map +1 -0
- package/dist/utils/browser.d.ts +10 -0
- package/dist/utils/browser.d.ts.map +1 -0
- package/dist/utils/browser.js +127 -0
- package/dist/utils/browser.js.map +1 -0
- package/dist/utils/fs.d.ts +11 -0
- package/dist/utils/fs.d.ts.map +1 -0
- package/dist/utils/fs.js +166 -0
- package/dist/utils/fs.js.map +1 -0
- package/dist/utils/git.d.ts +9 -0
- package/dist/utils/git.d.ts.map +1 -0
- package/dist/utils/git.js +69 -0
- package/dist/utils/git.js.map +1 -0
- package/dist/utils/process.d.ts +21 -0
- package/dist/utils/process.d.ts.map +1 -0
- package/dist/utils/process.js +120 -0
- package/dist/utils/process.js.map +1 -0
- package/dist/version.d.ts +21 -36
- package/dist/version.d.ts.map +1 -1
- package/dist/version.js +21 -44
- package/dist/version.js.map +1 -1
- package/package.json +19 -38
- package/CHANGELOG.md +0 -38
- package/dist/commands/cce.d.ts +0 -7
- package/dist/commands/cce.d.ts.map +0 -1
- package/dist/commands/cce.js +0 -37
- package/dist/commands/cce.js.map +0 -1
- package/dist/commands/logs.d.ts +0 -3
- package/dist/commands/logs.d.ts.map +0 -1
- package/dist/commands/logs.js +0 -40
- package/dist/commands/logs.js.map +0 -1
- package/dist/commands/qa.d.ts +0 -12
- package/dist/commands/qa.d.ts.map +0 -1
- package/dist/commands/qa.js +0 -143
- package/dist/commands/qa.js.map +0 -1
- package/dist/commands/stats.d.ts +0 -37
- package/dist/commands/stats.d.ts.map +0 -1
- package/dist/commands/stats.js +0 -169
- package/dist/commands/stats.js.map +0 -1
- package/dist/commands/template.d.ts +0 -8
- package/dist/commands/template.d.ts.map +0 -1
- package/dist/commands/template.js +0 -392
- package/dist/commands/template.js.map +0 -1
- package/dist/config/project.d.ts +0 -54
- package/dist/config/project.d.ts.map +0 -1
- package/dist/config/project.js +0 -100
- package/dist/config/project.js.map +0 -1
- package/dist/context/cce.d.ts +0 -39
- package/dist/context/cce.d.ts.map +0 -1
- package/dist/context/cce.js +0 -455
- package/dist/context/cce.js.map +0 -1
- package/dist/governor/fingerprint.d.ts +0 -7
- package/dist/governor/fingerprint.d.ts.map +0 -1
- package/dist/governor/fingerprint.js +0 -120
- package/dist/governor/fingerprint.js.map +0 -1
- package/dist/governor/hook.d.ts +0 -13
- package/dist/governor/hook.d.ts.map +0 -1
- package/dist/governor/hook.js +0 -389
- package/dist/governor/hook.js.map +0 -1
- package/dist/governor/state.d.ts +0 -45
- package/dist/governor/state.d.ts.map +0 -1
- package/dist/governor/state.js +0 -60
- package/dist/governor/state.js.map +0 -1
- package/dist/integrations/antigravity.d.ts +0 -20
- package/dist/integrations/antigravity.d.ts.map +0 -1
- package/dist/integrations/antigravity.js +0 -153
- package/dist/integrations/antigravity.js.map +0 -1
- package/dist/output-safety.d.ts +0 -3
- package/dist/output-safety.d.ts.map +0 -1
- package/dist/output-safety.js +0 -44
- package/dist/output-safety.js.map +0 -1
- package/dist/output.d.ts +0 -5
- package/dist/output.d.ts.map +0 -1
- package/dist/output.js +0 -2
- package/dist/output.js.map +0 -1
- package/dist/platform/executable.d.ts +0 -11
- package/dist/platform/executable.d.ts.map +0 -1
- package/dist/platform/executable.js +0 -69
- package/dist/platform/executable.js.map +0 -1
- package/dist/platform/process.d.ts +0 -27
- package/dist/platform/process.d.ts.map +0 -1
- package/dist/platform/process.js +0 -189
- package/dist/platform/process.js.map +0 -1
- package/dist/progress.d.ts +0 -44
- package/dist/progress.d.ts.map +0 -1
- package/dist/progress.js +0 -123
- package/dist/progress.js.map +0 -1
- package/dist/qa/artifacts.d.ts +0 -3
- package/dist/qa/artifacts.d.ts.map +0 -1
- package/dist/qa/artifacts.js +0 -15
- package/dist/qa/artifacts.js.map +0 -1
- package/dist/qa/diff.d.ts +0 -10
- package/dist/qa/diff.d.ts.map +0 -1
- package/dist/qa/diff.js +0 -90
- package/dist/qa/diff.js.map +0 -1
- package/dist/qa/server.d.ts +0 -10
- package/dist/qa/server.d.ts.map +0 -1
- package/dist/qa/server.js +0 -127
- package/dist/qa/server.js.map +0 -1
- package/dist/scaffold/adoption.d.ts +0 -17
- package/dist/scaffold/adoption.d.ts.map +0 -1
- package/dist/scaffold/adoption.js +0 -279
- package/dist/scaffold/adoption.js.map +0 -1
- package/dist/scaffold/legacy.d.ts +0 -4
- package/dist/scaffold/legacy.d.ts.map +0 -1
- package/dist/scaffold/legacy.js +0 -139
- package/dist/scaffold/legacy.js.map +0 -1
- package/dist/scaffold/routes.d.ts +0 -3
- package/dist/scaffold/routes.d.ts.map +0 -1
- package/dist/scaffold/routes.js +0 -37
- package/dist/scaffold/routes.js.map +0 -1
- package/dist/scaffold/standalone.d.ts +0 -7
- package/dist/scaffold/standalone.d.ts.map +0 -1
- package/dist/scaffold/standalone.js +0 -374
- package/dist/scaffold/standalone.js.map +0 -1
- package/dist/scaffold/templates.d.ts +0 -9
- package/dist/scaffold/templates.d.ts.map +0 -1
- package/dist/scaffold/templates.js +0 -317
- package/dist/scaffold/templates.js.map +0 -1
- package/dist/scaffold/write.d.ts +0 -2
- package/dist/scaffold/write.d.ts.map +0 -1
- package/dist/scaffold/write.js +0 -38
- package/dist/scaffold/write.js.map +0 -1
- package/dist/telemetry/store.d.ts +0 -33
- package/dist/telemetry/store.d.ts.map +0 -1
- package/dist/telemetry/store.js +0 -75
- package/dist/telemetry/store.js.map +0 -1
- package/dist/template/servers.d.ts +0 -21
- package/dist/template/servers.d.ts.map +0 -1
- package/dist/template/servers.js +0 -193
- package/dist/template/servers.js.map +0 -1
- package/dist/template/workspace.d.ts +0 -23
- package/dist/template/workspace.d.ts.map +0 -1
- package/dist/template/workspace.js +0 -152
- package/dist/template/workspace.js.map +0 -1
- package/dist/verify/runner.d.ts +0 -16
- package/dist/verify/runner.d.ts.map +0 -1
- package/dist/verify/runner.js +0 -112
- package/dist/verify/runner.js.map +0 -1
- package/docs/agent-audit.md +0 -24
|
@@ -1,374 +0,0 @@
|
|
|
1
|
-
import { designGuardrails } from "./design.js";
|
|
2
|
-
/** Standalone project tooling: no dependency on the generator at runtime. */
|
|
3
|
-
export const backendCheckScript = `import { spawnSync } from "node:child_process";
|
|
4
|
-
import { readdir } from "node:fs/promises";
|
|
5
|
-
import path from "node:path";
|
|
6
|
-
|
|
7
|
-
function php(args) {
|
|
8
|
-
const result = spawnSync("php", args, {
|
|
9
|
-
encoding: "utf8",
|
|
10
|
-
shell: false,
|
|
11
|
-
timeout: 10000,
|
|
12
|
-
});
|
|
13
|
-
if (result.error || result.status !== 0)
|
|
14
|
-
throw new Error(result.error?.message || result.stderr || result.stdout);
|
|
15
|
-
return result.stdout.trim();
|
|
16
|
-
}
|
|
17
|
-
async function lint(directory) {
|
|
18
|
-
for (const entry of await readdir(directory, { withFileTypes: true })) {
|
|
19
|
-
const file = path.join(directory, entry.name);
|
|
20
|
-
if (entry.isDirectory()) await lint(file);
|
|
21
|
-
else if (entry.isFile() && entry.name.endsWith(".php")) php(["-l", file]);
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
try {
|
|
25
|
-
const version = Number(php(["-r", "echo PHP_VERSION_ID;"]));
|
|
26
|
-
if (!Number.isInteger(version) || version < 80000)
|
|
27
|
-
throw new Error("PHP 8.0 or newer is required.");
|
|
28
|
-
await lint("api");
|
|
29
|
-
console.log("PHP PASS");
|
|
30
|
-
} catch (error) {
|
|
31
|
-
console.error(\`PHP FAIL\\n\${error.message}\`);
|
|
32
|
-
process.exitCode = 1;
|
|
33
|
-
}
|
|
34
|
-
`;
|
|
35
|
-
export const deployScript = `import { cp, lstat, mkdir, rename, rm } from "node:fs/promises";
|
|
36
|
-
import path from "node:path";
|
|
37
|
-
|
|
38
|
-
const target = path.resolve("deploy");
|
|
39
|
-
const staging = \`\${target}.\${process.pid}.tmp\`;
|
|
40
|
-
const backup = \`\${target}.\${process.pid}.backup\`;
|
|
41
|
-
let backedUp = false;
|
|
42
|
-
try {
|
|
43
|
-
await mkdir(staging);
|
|
44
|
-
await cp("build/client", staging, { recursive: true, errorOnExist: true });
|
|
45
|
-
await cp("api", path.join(staging, "api"), { recursive: true });
|
|
46
|
-
await cp(".htaccess", path.join(staging, ".htaccess"));
|
|
47
|
-
try {
|
|
48
|
-
await lstat(target);
|
|
49
|
-
await rename(target, backup);
|
|
50
|
-
backedUp = true;
|
|
51
|
-
} catch (error) {
|
|
52
|
-
if (error.code !== "ENOENT") throw error;
|
|
53
|
-
}
|
|
54
|
-
try {
|
|
55
|
-
await rename(staging, target);
|
|
56
|
-
} catch (error) {
|
|
57
|
-
if (backedUp) await rename(backup, target);
|
|
58
|
-
throw error;
|
|
59
|
-
}
|
|
60
|
-
if (backedUp) await rm(backup, { recursive: true });
|
|
61
|
-
console.log("DEPLOY READY: deploy/");
|
|
62
|
-
} finally {
|
|
63
|
-
await rm(staging, { recursive: true, force: true });
|
|
64
|
-
}
|
|
65
|
-
`;
|
|
66
|
-
export const qaScript = `import { spawn, spawnSync } from "node:child_process";
|
|
67
|
-
import { mkdir, readFile } from "node:fs/promises";
|
|
68
|
-
import net from "node:net";
|
|
69
|
-
import { chromium } from "playwright";
|
|
70
|
-
|
|
71
|
-
const flags = process.argv.slice(2);
|
|
72
|
-
if (
|
|
73
|
-
flags.some((flag) => !["--visual", "--interactive", "--force"].includes(flag))
|
|
74
|
-
)
|
|
75
|
-
throw new Error("Unknown QA option");
|
|
76
|
-
const config = JSON.parse(await readFile(".mozole/project.json", "utf8"));
|
|
77
|
-
const routes = config.routes;
|
|
78
|
-
const viewports = config.qa?.viewports;
|
|
79
|
-
const artifactName = (route) =>
|
|
80
|
-
route === "/"
|
|
81
|
-
? "index"
|
|
82
|
-
: route
|
|
83
|
-
.replace(/^\\/+/, "")
|
|
84
|
-
.replaceAll("/", "-")
|
|
85
|
-
.replace(/[^a-zA-Z0-9._-]+/g, "-")
|
|
86
|
-
.replace(/-+/g, "-")
|
|
87
|
-
.replace(/^-+|-+$/g, "") || "route";
|
|
88
|
-
if (
|
|
89
|
-
!Array.isArray(routes) ||
|
|
90
|
-
routes.length === 0 ||
|
|
91
|
-
routes.length > 100 ||
|
|
92
|
-
new Set(routes).size !== routes.length ||
|
|
93
|
-
new Set(routes.map(artifactName)).size !== routes.length ||
|
|
94
|
-
!routes.every(
|
|
95
|
-
(route) =>
|
|
96
|
-
typeof route === "string" &&
|
|
97
|
-
route.startsWith("/") &&
|
|
98
|
-
!route.startsWith("//") &&
|
|
99
|
-
route.length <= 2048,
|
|
100
|
-
) ||
|
|
101
|
-
!Array.isArray(viewports) ||
|
|
102
|
-
viewports.length === 0 ||
|
|
103
|
-
viewports.length > 20 ||
|
|
104
|
-
new Set(
|
|
105
|
-
viewports.map(({ width, height }) => \`\${String(width)}x\${String(height)}\`),
|
|
106
|
-
).size !== viewports.length ||
|
|
107
|
-
!viewports.every(
|
|
108
|
-
({ width, height }) =>
|
|
109
|
-
Number.isInteger(width) &&
|
|
110
|
-
width > 0 &&
|
|
111
|
-
width <= 7680 &&
|
|
112
|
-
Number.isInteger(height) &&
|
|
113
|
-
height > 0 &&
|
|
114
|
-
height <= 7680,
|
|
115
|
-
)
|
|
116
|
-
)
|
|
117
|
-
throw new Error("Invalid QA routes or viewports");
|
|
118
|
-
function safe(value) {
|
|
119
|
-
value = String(value);
|
|
120
|
-
let output = "";
|
|
121
|
-
for (let index = 0; index < value.length; index++) {
|
|
122
|
-
const code = value.charCodeAt(index);
|
|
123
|
-
if (code === 27) {
|
|
124
|
-
const kind = value[index + 1];
|
|
125
|
-
if (kind === "[") {
|
|
126
|
-
index += 2;
|
|
127
|
-
while (index < value.length) {
|
|
128
|
-
const byte = value.charCodeAt(index);
|
|
129
|
-
if (byte >= 64 && byte <= 126) break;
|
|
130
|
-
index++;
|
|
131
|
-
}
|
|
132
|
-
} else if (kind === "]") {
|
|
133
|
-
index += 2;
|
|
134
|
-
while (index < value.length) {
|
|
135
|
-
if (value.charCodeAt(index) === 7) break;
|
|
136
|
-
if (value.charCodeAt(index) === 27 && value[index + 1] === "\\\\") {
|
|
137
|
-
index++;
|
|
138
|
-
break;
|
|
139
|
-
}
|
|
140
|
-
index++;
|
|
141
|
-
}
|
|
142
|
-
} else if (kind !== undefined) index++;
|
|
143
|
-
continue;
|
|
144
|
-
}
|
|
145
|
-
if (
|
|
146
|
-
(code >= 0 && code <= 8) ||
|
|
147
|
-
code === 11 ||
|
|
148
|
-
code === 12 ||
|
|
149
|
-
(code >= 14 && code <= 31) ||
|
|
150
|
-
(code >= 127 && code <= 159)
|
|
151
|
-
)
|
|
152
|
-
continue;
|
|
153
|
-
output += value[index];
|
|
154
|
-
}
|
|
155
|
-
return output;
|
|
156
|
-
}
|
|
157
|
-
const socket = net.createServer();
|
|
158
|
-
await new Promise((resolve, reject) => {
|
|
159
|
-
socket.once("error", reject);
|
|
160
|
-
socket.listen(0, "127.0.0.1", resolve);
|
|
161
|
-
});
|
|
162
|
-
const port = socket.address().port;
|
|
163
|
-
await new Promise((resolve) => socket.close(resolve));
|
|
164
|
-
const configured = config.qa.server;
|
|
165
|
-
const npmCli = process.env.npm_execpath;
|
|
166
|
-
if (configured.command === "npm" && !npmCli) {
|
|
167
|
-
throw new Error(
|
|
168
|
-
"Run QA through npm run qa so npm can be resolved without a shell.",
|
|
169
|
-
);
|
|
170
|
-
}
|
|
171
|
-
const command =
|
|
172
|
-
configured.command === "npm" ? process.execPath : configured.command;
|
|
173
|
-
const args = [
|
|
174
|
-
...(configured.command === "npm" ? [npmCli] : []),
|
|
175
|
-
...configured.args,
|
|
176
|
-
"--port",
|
|
177
|
-
String(port),
|
|
178
|
-
"--strictPort",
|
|
179
|
-
];
|
|
180
|
-
const child = spawn(command, args, {
|
|
181
|
-
shell: false,
|
|
182
|
-
detached: process.platform !== "win32",
|
|
183
|
-
stdio: ["ignore", "pipe", "pipe"],
|
|
184
|
-
});
|
|
185
|
-
let serverLog = "";
|
|
186
|
-
for (const stream of [child.stdout, child.stderr])
|
|
187
|
-
stream.on("data", (data) => {
|
|
188
|
-
serverLog = (serverLog + data).slice(-4000);
|
|
189
|
-
});
|
|
190
|
-
let serverError;
|
|
191
|
-
child.on("error", (error) => {
|
|
192
|
-
serverError = error;
|
|
193
|
-
});
|
|
194
|
-
let browser;
|
|
195
|
-
let stopping = false;
|
|
196
|
-
async function cleanup() {
|
|
197
|
-
if (stopping) return;
|
|
198
|
-
stopping = true;
|
|
199
|
-
await browser?.close().catch(() => {});
|
|
200
|
-
if (child.pid) {
|
|
201
|
-
if (process.platform === "win32")
|
|
202
|
-
spawnSync("taskkill", ["/pid", String(child.pid), "/T", "/F"], {
|
|
203
|
-
shell: false,
|
|
204
|
-
stdio: "ignore",
|
|
205
|
-
});
|
|
206
|
-
else {
|
|
207
|
-
try {
|
|
208
|
-
process.kill(-child.pid, "SIGTERM");
|
|
209
|
-
} catch {}
|
|
210
|
-
}
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
|
-
const interrupted = () => {
|
|
214
|
-
void cleanup().finally(() => process.exit(130));
|
|
215
|
-
};
|
|
216
|
-
process.once("SIGINT", interrupted);
|
|
217
|
-
process.once("SIGTERM", interrupted);
|
|
218
|
-
const deadline = setTimeout(() => {
|
|
219
|
-
console.error("QA timed out");
|
|
220
|
-
void cleanup().finally(() => process.exit(1));
|
|
221
|
-
}, 120000);
|
|
222
|
-
const base = \`http://127.0.0.1:\${port}\`;
|
|
223
|
-
try {
|
|
224
|
-
let ready = false;
|
|
225
|
-
for (let attempt = 0; attempt < 300; attempt++) {
|
|
226
|
-
if (serverError || child.exitCode !== null)
|
|
227
|
-
throw new Error(serverError?.message || serverLog);
|
|
228
|
-
try {
|
|
229
|
-
ready = (
|
|
230
|
-
await fetch(base + config.qa.server.readinessPath, {
|
|
231
|
-
signal: AbortSignal.timeout(1000),
|
|
232
|
-
})
|
|
233
|
-
).ok;
|
|
234
|
-
} catch {}
|
|
235
|
-
if (ready) break;
|
|
236
|
-
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
237
|
-
}
|
|
238
|
-
if (!ready)
|
|
239
|
-
throw new Error(\`Development server did not become ready.\\n\${serverLog}\`);
|
|
240
|
-
browser = await chromium.launch();
|
|
241
|
-
const failures = [];
|
|
242
|
-
for (const viewport of config.qa.viewports) {
|
|
243
|
-
const page = await browser.newPage({ viewport });
|
|
244
|
-
page.on("pageerror", (error) => failures.push(error.message));
|
|
245
|
-
page.on("console", (message) => {
|
|
246
|
-
if (message.type() === "error") failures.push(message.text());
|
|
247
|
-
});
|
|
248
|
-
page.on("requestfailed", (request) => {
|
|
249
|
-
if (request.failure()?.errorText !== "net::ERR_ABORTED")
|
|
250
|
-
failures.push(request.url());
|
|
251
|
-
});
|
|
252
|
-
page.on("response", (response) => {
|
|
253
|
-
if (response.status() >= 400)
|
|
254
|
-
failures.push(\`\${response.status()} \${response.url()}\`);
|
|
255
|
-
});
|
|
256
|
-
for (const route of config.routes) {
|
|
257
|
-
const response = await page.goto(base + route, {
|
|
258
|
-
waitUntil: "networkidle",
|
|
259
|
-
});
|
|
260
|
-
if (!response?.ok()) failures.push(\`\${route}: HTTP failure\`);
|
|
261
|
-
const issues = await page.evaluate(() => {
|
|
262
|
-
const found = [];
|
|
263
|
-
if (!document.documentElement.lang) found.push("missing lang");
|
|
264
|
-
if (!document.title.trim()) found.push("missing title");
|
|
265
|
-
if (!document.querySelector("h1")) found.push("missing h1");
|
|
266
|
-
if (document.documentElement.scrollWidth > innerWidth + 1)
|
|
267
|
-
found.push("horizontal overflow");
|
|
268
|
-
for (const element of document.querySelectorAll(
|
|
269
|
-
"a, button, input:not([type=hidden]), select, textarea",
|
|
270
|
-
)) {
|
|
271
|
-
if (!element.getClientRects().length) continue;
|
|
272
|
-
const labelled = (element.getAttribute("aria-labelledby") || "")
|
|
273
|
-
.split(/\\s+/)
|
|
274
|
-
.some((id) => document.getElementById(id)?.textContent?.trim());
|
|
275
|
-
if (
|
|
276
|
-
!element.textContent?.trim() &&
|
|
277
|
-
!element.getAttribute("aria-label") &&
|
|
278
|
-
!labelled &&
|
|
279
|
-
!element.labels?.length &&
|
|
280
|
-
!element.getAttribute("title") &&
|
|
281
|
-
!element.getAttribute("alt") &&
|
|
282
|
-
!element.querySelector("img[alt]")
|
|
283
|
-
)
|
|
284
|
-
found.push("unnamed control");
|
|
285
|
-
}
|
|
286
|
-
return found;
|
|
287
|
-
});
|
|
288
|
-
failures.push(...issues.map((issue) => \`\${route}: \${issue}\`));
|
|
289
|
-
const links = await page
|
|
290
|
-
.locator("a[href]")
|
|
291
|
-
.evaluateAll((anchors) => anchors.map((anchor) => anchor.href));
|
|
292
|
-
for (const href of new Set(links)) {
|
|
293
|
-
if (
|
|
294
|
-
new URL(href).origin === base &&
|
|
295
|
-
!(await page.request.get(href)).ok()
|
|
296
|
-
)
|
|
297
|
-
failures.push(\`broken link: \${href}\`);
|
|
298
|
-
}
|
|
299
|
-
if (flags.includes("--interactive")) {
|
|
300
|
-
await page.keyboard.press("Tab");
|
|
301
|
-
if (
|
|
302
|
-
!(await page.evaluate(() => document.activeElement !== document.body))
|
|
303
|
-
)
|
|
304
|
-
failures.push(\`\${route}: keyboard focus missing\`);
|
|
305
|
-
}
|
|
306
|
-
if (flags.includes("--visual")) {
|
|
307
|
-
await mkdir(".mozole/qa", { recursive: true });
|
|
308
|
-
const name = artifactName(route);
|
|
309
|
-
await page.screenshot({
|
|
310
|
-
path:
|
|
311
|
-
".mozole/qa/" +
|
|
312
|
-
viewport.width +
|
|
313
|
-
"x" +
|
|
314
|
-
viewport.height +
|
|
315
|
-
"-" +
|
|
316
|
-
name +
|
|
317
|
-
".png",
|
|
318
|
-
fullPage: true,
|
|
319
|
-
});
|
|
320
|
-
}
|
|
321
|
-
}
|
|
322
|
-
await page.close();
|
|
323
|
-
}
|
|
324
|
-
if (failures.length) throw new Error([...new Set(failures)].join("\\n"));
|
|
325
|
-
console.log(
|
|
326
|
-
"QA PASS: " +
|
|
327
|
-
config.routes.length +
|
|
328
|
-
" routes, " +
|
|
329
|
-
config.qa.viewports.length +
|
|
330
|
-
" viewports",
|
|
331
|
-
);
|
|
332
|
-
} catch (error) {
|
|
333
|
-
console.error(\`QA FAIL\\n\${safe(error.message)}\`);
|
|
334
|
-
process.exitCode = 1;
|
|
335
|
-
} finally {
|
|
336
|
-
clearTimeout(deadline);
|
|
337
|
-
process.removeListener("SIGINT", interrupted);
|
|
338
|
-
process.removeListener("SIGTERM", interrupted);
|
|
339
|
-
await cleanup();
|
|
340
|
-
}
|
|
341
|
-
`;
|
|
342
|
-
export function basicAgentGuide(backend) {
|
|
343
|
-
return `# Project guide\n\n## Commands\n\n- \`npm run dev\` — frontend development server\n- \`npm run verify\` — lint, typecheck, tests, production build\n- \`npm run qa\` — browser checks without screenshots\n- \`npm run qa:interactive\` — keyboard checks\n- \`npm run qa:visual\` — explicitly requested screenshots\n${backend ? "- `npm run dev:api` — PHP API in a separate terminal (PHP 8.0+)\n- `npm run check:php` — PHP version and syntax checks\n- `npm run build:deploy` — assemble deploy/ for Apache or LiteSpeed\n" : ""}\n## Architecture\n\nReact Router and Vite source is in \`app/\`; routes are declared in \`app/routes.ts\`. Production HTML and assets are in \`build/client/\`.${backend ? " PHP endpoints are in `api/`; the frontend uses relative `/api/` URLs through Vite's proxy. See `docs/backend-php.md`." : ""}\n\n## Working rules\n\nPreserve user changes. Inspect relevant code before editing. Run verification and relevant browser checks before handoff. Routine QA never captures screenshots; use visual QA only when requested. Report failed checks and remaining limitations.\n\n${designGuardrails}`;
|
|
344
|
-
}
|
|
345
|
-
export const extraVerifierScript = `import { spawnSync } from "node:child_process";
|
|
346
|
-
import { readFile } from "node:fs/promises";
|
|
347
|
-
|
|
348
|
-
const config = JSON.parse(await readFile(".mozole/project.json", "utf8"));
|
|
349
|
-
for (const check of config.verifiers ?? []) {
|
|
350
|
-
if (
|
|
351
|
-
typeof check.command !== "string" ||
|
|
352
|
-
!Array.isArray(check.args) ||
|
|
353
|
-
!check.args.every((arg) => typeof arg === "string")
|
|
354
|
-
)
|
|
355
|
-
throw new Error("Invalid extra verifier");
|
|
356
|
-
const npm = check.command === "npm";
|
|
357
|
-
if (npm && !process.env.npm_execpath)
|
|
358
|
-
throw new Error("Run verification through npm run verify");
|
|
359
|
-
const result = spawnSync(
|
|
360
|
-
npm ? process.execPath : check.command,
|
|
361
|
-
npm ? [process.env.npm_execpath, ...check.args] : check.args,
|
|
362
|
-
{ shell: false, stdio: "inherit", timeout: 600000 },
|
|
363
|
-
);
|
|
364
|
-
if (result.error || result.status !== 0) {
|
|
365
|
-
console.error(
|
|
366
|
-
"Extra verifier failed:",
|
|
367
|
-
check.name,
|
|
368
|
-
result.error?.message ?? result.status,
|
|
369
|
-
);
|
|
370
|
-
process.exit(result.status || 1);
|
|
371
|
-
}
|
|
372
|
-
}
|
|
373
|
-
`;
|
|
374
|
-
//# sourceMappingURL=standalone.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"standalone.js","sourceRoot":"","sources":["../../src/scaffold/standalone.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAE/C,6EAA6E;AAC7E,MAAM,CAAC,MAAM,kBAAkB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA+BjC,CAAC;AAEF,MAAM,CAAC,MAAM,YAAY,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA8B3B,CAAC;AAEF,MAAM,CAAC,MAAM,QAAQ,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAmRvB,CAAC;AAEF,MAAM,UAAU,eAAe,CAAC,OAAgB;IAC9C,OAAO,0TAA0T,OAAO,CAAC,CAAC,CAAC,+LAA+L,CAAC,CAAC,CAAC,EAAE,mKAAmK,OAAO,CAAC,CAAC,CAAC,wHAAwH,CAAC,CAAC,CAAC,EAAE,kRAAkR,gBAAgB,EAAE,CAAC;AAChmC,CAAC;AAED,MAAM,CAAC,MAAM,mBAAmB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA4BlC,CAAC"}
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import type { MozoleConfig } from "../config/project.js";
|
|
2
|
-
export interface ProjectTemplateOptions {
|
|
3
|
-
scaffold?: boolean | undefined;
|
|
4
|
-
backend?: boolean | undefined;
|
|
5
|
-
sharedDependencies?: boolean | undefined;
|
|
6
|
-
}
|
|
7
|
-
export declare function projectConfig(name: string, options?: ProjectTemplateOptions): MozoleConfig;
|
|
8
|
-
export declare function projectTemplates(name: string, options?: ProjectTemplateOptions): Record<string, string>;
|
|
9
|
-
//# sourceMappingURL=templates.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"templates.d.ts","sourceRoot":"","sources":["../../src/scaffold/templates.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAczD,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAC/B,OAAO,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAC9B,kBAAkB,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;CAC1C;AAED,wBAAgB,aAAa,CAC3B,IAAI,EAAE,MAAM,EACZ,OAAO,GAAE,sBAA2B,GACnC,YAAY,CAmDd;AAID,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,MAAM,EACZ,OAAO,GAAE,sBAA2B,GACnC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAsTxB"}
|