Skip to content

Commit fd01603

Browse files
Merge pull request #104 from CodeWithDennis/laravel-boost-v2
Laravel boost V2 & more
2 parents 7f7ae75 + a0f588e commit fd01603

13 files changed

Lines changed: 1696 additions & 26 deletions

File tree

.cursor/hooks.json

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"version": 1,
3+
"hooks": {
4+
"stop": [
5+
{
6+
"command": "npx tsx .cursor/hooks/run-phpstan-on-stop.ts"
7+
}
8+
]
9+
}
10+
}
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
/// <reference types="node" />
2+
import { spawnSync } from "node:child_process";
3+
4+
type StopHookInput = {
5+
status?: "completed" | "aborted" | "error";
6+
};
7+
8+
const COMMAND = {
9+
tool: "phpstan",
10+
cmd: "./vendor/bin/phpstan analyse --memory-limit=512M",
11+
};
12+
13+
async function parseInput(): Promise<StopHookInput> {
14+
const chunks: Buffer[] = [];
15+
for await (const chunk of process.stdin) {
16+
chunks.push(typeof chunk === "string" ? Buffer.from(chunk) : chunk);
17+
}
18+
const text = Buffer.concat(chunks).toString("utf8");
19+
try {
20+
return JSON.parse(text) as StopHookInput;
21+
} catch {
22+
return {};
23+
}
24+
}
25+
26+
function hasGitChanges(): boolean {
27+
const result = spawnSync("git", [
28+
"status",
29+
"--porcelain",
30+
"--untracked-files",
31+
]);
32+
return result.stdout.toString().trim().length > 0;
33+
}
34+
35+
function runCommand(
36+
_name: string,
37+
cmd: string,
38+
): { ok: boolean; output: string } {
39+
const result = spawnSync(cmd, {
40+
stdio: ["inherit", "pipe", "pipe"],
41+
shell: true,
42+
});
43+
const out = result.stdout?.toString() ?? "";
44+
const err = result.stderr?.toString() ?? "";
45+
const output = [out, err].filter(Boolean).join("\n").trim();
46+
if (output) process.stderr.write(output);
47+
return { ok: result.status === 0, output };
48+
}
49+
50+
async function main(): Promise<void> {
51+
const input = await parseInput();
52+
53+
if (input.status !== "completed") {
54+
process.stdout.write(JSON.stringify({}) + "\n");
55+
return;
56+
}
57+
58+
if (!hasGitChanges()) {
59+
process.stdout.write(JSON.stringify({}) + "\n");
60+
return;
61+
}
62+
63+
const MAX_ERROR_CHARS = 1000;
64+
65+
const { ok, output } = runCommand(COMMAND.tool, COMMAND.cmd);
66+
const failures = ok ? [] : [{ tool: COMMAND.tool, output }];
67+
68+
const truncatedOutput =
69+
output && output.length > MAX_ERROR_CHARS
70+
? output.slice(0, MAX_ERROR_CHARS) + "\n… (truncated)"
71+
: output || "(no output)";
72+
73+
const result =
74+
failures.length > 0
75+
? {
76+
followup_message: [
77+
`Please fix the errors reported by ${COMMAND.tool}.`,
78+
"Don't do any other investigation.",
79+
"",
80+
`<${COMMAND.tool}-errors>\n${truncatedOutput}\n</${COMMAND.tool}-errors>`,
81+
].join("\n"),
82+
}
83+
: {};
84+
process.stdout.write(JSON.stringify(result) + "\n");
85+
}
86+
87+
main().catch((err) => {
88+
console.error("[run-phpstan-on-stop]", err);
89+
process.stdout.write(JSON.stringify({}) + "\n");
90+
});

.cursor/mcp.json

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"mcpServers": {
3+
"laravel-boost": {
4+
"command": "php",
5+
"args": [
6+
"artisan",
7+
"boost:mcp"
8+
]
9+
}
10+
}
11+
}

.cursor/rules/code-formatters.mdc

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
---
2+
alwaysApply: true
3+
---
4+
5+
# Code formatters & refactors (auto-updating tools)
6+
7+
These tools modify code automatically. Run them before finalizing changes so the codebase stays consistent.
8+
9+
## Rector
10+
11+
- Run `vendor/bin/rector --ansi` before finalizing changes so refactoring rules are applied.
12+
- Rector updates code on its own; run it to keep the codebase aligned with configured rules.
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
---
2+
description: Use Conventional Commits format for all commit messages
3+
alwaysApply: true
4+
---
5+
6+
# Conventional Commits
7+
8+
## Format
9+
10+
```
11+
<type>[optional scope]: <description>
12+
13+
[optional body]
14+
15+
[optional footer(s)]
16+
```
17+
18+
## Types
19+
20+
| Type | Use when |
21+
|------|----------|
22+
| `feat` | Adding a new feature (MINOR in SemVer) |
23+
| `fix` | Patching a bug (PATCH in SemVer) |
24+
| `docs` | Documentation only |
25+
| `style` | Formatting, whitespace, no code change |
26+
| `refactor` | Code change that neither fixes a bug nor adds a feature |
27+
| `perf` | Performance improvement |
28+
| `test` | Adding or updating tests |
29+
| `build` | Build system or dependencies |
30+
| `ci` | CI configuration |
31+
| `chore` | Other changes (maintenance, tooling) |
32+
33+
## Scope
34+
35+
Optional. Use a noun describing the affected area in parentheses: `feat(auth):`, `fix(api):`.
36+
37+
## Examples
38+
39+
```
40+
feat: add user registration endpoint
41+
```
42+
43+
```
44+
fix(login): prevent redirect loop on session expiry
45+
```
46+
47+
```
48+
chore(hooks): rename run-quality-checks to run-phpstan-on-stop
49+
```
50+
51+
```
52+
docs: correct spelling of CHANGELOG
53+
```
54+
55+
```
56+
feat(api)!: drop support for deprecated endpoints
57+
58+
BREAKING CHANGE: /v1/users has been removed. Use /v2/users instead.
59+
```
60+
61+
## Rules
62+
63+
- Description is required and MUST immediately follow the type/scope.
64+
- Use imperative mood: "add feature" not "added feature".
65+
- No period at the end of the description.
66+
- Use `!` after type/scope or `BREAKING CHANGE:` in footer for breaking changes.

0 commit comments

Comments
 (0)