demo-this-pr 0.1.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/LICENSE +21 -0
- package/README.md +289 -0
- package/assets/demo-this-pr-logo.svg +41 -0
- package/dist/auto.d.ts +17 -0
- package/dist/auto.js +457 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +201 -0
- package/dist/demoPlan.d.ts +10 -0
- package/dist/demoPlan.js +159 -0
- package/dist/git.d.ts +2 -0
- package/dist/git.js +87 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +6 -0
- package/dist/playwright.d.ts +11 -0
- package/dist/playwright.js +846 -0
- package/dist/prKit.d.ts +2 -0
- package/dist/prKit.js +99 -0
- package/dist/report.d.ts +3 -0
- package/dist/report.js +239 -0
- package/dist/runs.d.ts +1 -0
- package/dist/runs.js +30 -0
- package/dist/shell.d.ts +3 -0
- package/dist/shell.js +61 -0
- package/dist/types.d.ts +101 -0
- package/dist/types.js +1 -0
- package/dist/viewer.d.ts +1 -0
- package/dist/viewer.js +32 -0
- package/package.json +61 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Carlos Miret
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,289 @@
|
|
|
1
|
+
<p align="center">
|
|
2
|
+
<img src="./assets/demo-this-pr-logo.svg" alt="DEMO THIS PR animated wordmark" width="920">
|
|
3
|
+
</p>
|
|
4
|
+
|
|
5
|
+
# demo-this-pr
|
|
6
|
+
|
|
7
|
+
`demo-this-pr` records the current local change before you open a pull request. Run one command from a working tree, get an isolated Chromium demo, a local MP4 with cursor/highlight overlays, captured test output, and a review report that explains what changed.
|
|
8
|
+
|
|
9
|
+
It is not an AI detector. It is a PR-quality tool for avoiding vague descriptions, missing demos, and unverifiable testing claims.
|
|
10
|
+
|
|
11
|
+
## One Command
|
|
12
|
+
|
|
13
|
+
Run this from the repository that has local or unpushed changes:
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
demo-this-pr
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
Or point it at a repository from anywhere:
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
demo-this-pr --cwd /path/to/repository
|
|
23
|
+
# or
|
|
24
|
+
demo-this-pr /path/to/repository
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
The command will:
|
|
28
|
+
|
|
29
|
+
- detect branch changes, including uncommitted files;
|
|
30
|
+
- start the repository dev server when a `dev` script exists;
|
|
31
|
+
- otherwise use a reachable local app on a common localhost port;
|
|
32
|
+
- open isolated Playwright Chromium, never the user's normal Chrome profile;
|
|
33
|
+
- record a slow local MP4 with captions, cursor movement, and highlighted elements;
|
|
34
|
+
- run inferred safe test commands from `package.json`;
|
|
35
|
+
- open a local report so the user can press play immediately;
|
|
36
|
+
- write artifacts into a unique directory under `.demo-this-pr/runs/`.
|
|
37
|
+
|
|
38
|
+
Each execution gets its own run directory, for example:
|
|
39
|
+
|
|
40
|
+
```text
|
|
41
|
+
.demo-this-pr/runs/20260515-164322-381-my-feature/
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
The run label comes from the current branch, then `package.json` `name`, then the folder name. Non-meaningful Git labels such as `HEAD` or `unknown` are not used in generated directory names. Artifacts from previous runs are not overwritten unless you explicitly pass `--output`.
|
|
45
|
+
|
|
46
|
+
## Installation
|
|
47
|
+
|
|
48
|
+
During local development of this tool:
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
npm install
|
|
52
|
+
npm run build
|
|
53
|
+
npm link
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
After publishing to npm, the intended installation paths are:
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
npm install -g demo-this-pr
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
or per repository:
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
npm install --save-dev demo-this-pr
|
|
66
|
+
npx demo-this-pr
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
For CI or agent runners, prefer a pinned package version and a deterministic
|
|
70
|
+
artifact directory:
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
npx demo-this-pr@0.1.0 ci
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
The command exits non-zero when Git context or a reachable local app is missing.
|
|
77
|
+
CI systems can archive `.demo-this-pr/ci/` as a build artifact after the command
|
|
78
|
+
finishes.
|
|
79
|
+
|
|
80
|
+
## Publishing From A Private Repository
|
|
81
|
+
|
|
82
|
+
The source repository can remain private. The lowest-friction public distribution path is a public npm package named `demo-this-pr` that ships only the compiled CLI, assets, README, package metadata, and license.
|
|
83
|
+
|
|
84
|
+
Recommended package surface:
|
|
85
|
+
|
|
86
|
+
- npm package: `demo-this-pr`.
|
|
87
|
+
- CLI binary: `demo-this-pr`.
|
|
88
|
+
- Optional short alias: `demo-pr`.
|
|
89
|
+
- Public files: `dist/`, `assets/`, `README.md`, `package.json`, and `LICENSE`.
|
|
90
|
+
- Private files: source history, local `.demo-this-pr/` runs, generated videos, and internal planning notes.
|
|
91
|
+
|
|
92
|
+
When the repository is private, avoid public npm metadata that points to private GitHub issues or a private README URL. Add `repository`, `bugs`, and `homepage` later if there is a public docs site, public landing page, or public mirror.
|
|
93
|
+
|
|
94
|
+
Pre-publish checks:
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
npm run publish:check
|
|
98
|
+
npm publish
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
`npm run publish:check` builds the TypeScript output, runs tests, and verifies
|
|
102
|
+
the package contents with `npm pack --dry-run`.
|
|
103
|
+
|
|
104
|
+
## Requirements
|
|
105
|
+
|
|
106
|
+
Runtime requirements:
|
|
107
|
+
|
|
108
|
+
- Node.js `>=20`.
|
|
109
|
+
- Git CLI available in `PATH`.
|
|
110
|
+
- A Git working tree; uncommitted files are supported.
|
|
111
|
+
- Run the command from inside the repository that contains the changes, or pass `--cwd <repo>` / `[repo]`. The automatic flow exits if Git context is unavailable instead of generating a generic report.
|
|
112
|
+
- A local web application reachable by HTTP.
|
|
113
|
+
- Playwright Chromium installed for the machine running the tool.
|
|
114
|
+
|
|
115
|
+
Target project requirements:
|
|
116
|
+
|
|
117
|
+
- Best case: a `package.json` with a `dev` script that prints a localhost URL.
|
|
118
|
+
- Supported package managers for auto-start: npm, pnpm, Yarn, and Bun.
|
|
119
|
+
- Supported app URLs for fallback detection include common localhost ports: `3000`, `3001`, `5173`, `4173`, `4321`, `8080`, and `8000`.
|
|
120
|
+
- Optional test scripts: `test:ci`, `test`, `typecheck`, and `lint`.
|
|
121
|
+
|
|
122
|
+
If Chromium is missing, install it once:
|
|
123
|
+
|
|
124
|
+
```bash
|
|
125
|
+
npx playwright install chromium
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
## Technical Stack
|
|
129
|
+
|
|
130
|
+
`demo-this-pr` is a Node.js CLI implemented in TypeScript.
|
|
131
|
+
|
|
132
|
+
Core stack:
|
|
133
|
+
|
|
134
|
+
- TypeScript with ESM output.
|
|
135
|
+
- Node.js `child_process` for dev-server and test-command orchestration.
|
|
136
|
+
- Git CLI for branch, base, commit, and working-tree metadata.
|
|
137
|
+
- Commander for CLI parsing.
|
|
138
|
+
- Playwright for isolated Chromium automation, local video capture, screenshots, and report playback.
|
|
139
|
+
- `ffmpeg-static` for WebM-to-MP4 conversion.
|
|
140
|
+
- `picocolors` for terminal output.
|
|
141
|
+
- Vitest for unit tests.
|
|
142
|
+
|
|
143
|
+
Runtime architecture:
|
|
144
|
+
|
|
145
|
+
- `src/auto.ts` detects repository context, starts or discovers the local app, infers tests, and builds the default demo plan.
|
|
146
|
+
- `src/playwright.ts` records the Chromium demo, renders overlays, captures screenshots, and converts video to MP4.
|
|
147
|
+
- `src/prKit.ts` writes the review kit.
|
|
148
|
+
- `src/report.ts` renders Markdown and HTML reports.
|
|
149
|
+
- `src/viewer.ts` opens the generated HTML report in isolated Chromium and exits when the viewer closes.
|
|
150
|
+
|
|
151
|
+
No LLM or external API is required.
|
|
152
|
+
|
|
153
|
+
## Output
|
|
154
|
+
|
|
155
|
+
A normal run writes:
|
|
156
|
+
|
|
157
|
+
```text
|
|
158
|
+
.demo-this-pr/runs/<run-id>/
|
|
159
|
+
PR_REVIEW.md
|
|
160
|
+
PR_REVIEW.html
|
|
161
|
+
MCP_PLAYWRIGHT.md
|
|
162
|
+
mcp-playwright-demo.js
|
|
163
|
+
demo-plan.json
|
|
164
|
+
pr-demo.spec.ts
|
|
165
|
+
playwright.config.ts
|
|
166
|
+
assets/
|
|
167
|
+
demo-this-pr.mp4
|
|
168
|
+
demo-this-pr.webm
|
|
169
|
+
screenshots/
|
|
170
|
+
mcp-screenshots/
|
|
171
|
+
test-results/
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
The generated video is local review evidence. `.demo-this-pr/` is ignored by git and the MP4 is not uploaded automatically.
|
|
175
|
+
|
|
176
|
+
## Common Commands
|
|
177
|
+
|
|
178
|
+
Generate and open the report:
|
|
179
|
+
|
|
180
|
+
```bash
|
|
181
|
+
demo-this-pr
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
Generate without opening the report viewer:
|
|
185
|
+
|
|
186
|
+
```bash
|
|
187
|
+
demo-this-pr --no-open
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
Run without a visible browser window:
|
|
191
|
+
|
|
192
|
+
```bash
|
|
193
|
+
demo-this-pr --headless
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
Write to an explicit directory:
|
|
197
|
+
|
|
198
|
+
```bash
|
|
199
|
+
demo-this-pr --output .demo-this-pr/manual-checkout-demo
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
Generate in CI without a visible browser or report viewer:
|
|
203
|
+
|
|
204
|
+
```bash
|
|
205
|
+
demo-this-pr ci
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
Jenkins example:
|
|
209
|
+
|
|
210
|
+
```groovy
|
|
211
|
+
stage('PR demo') {
|
|
212
|
+
steps {
|
|
213
|
+
sh 'npm ci'
|
|
214
|
+
sh 'npx demo-this-pr@0.1.0 ci'
|
|
215
|
+
}
|
|
216
|
+
post {
|
|
217
|
+
always {
|
|
218
|
+
archiveArtifacts artifacts: '.demo-this-pr/ci/**', allowEmptyArchive: true
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
`demo-this-pr ci` starts the repository `dev` script when one exists. If the
|
|
225
|
+
application needs a non-standard start command, start it in the pipeline and run
|
|
226
|
+
the explicit `demo` command with `--url`.
|
|
227
|
+
|
|
228
|
+
Use an explicit flow:
|
|
229
|
+
|
|
230
|
+
```bash
|
|
231
|
+
demo-this-pr demo \
|
|
232
|
+
--url http://localhost:3000 \
|
|
233
|
+
--feature "Project creation flow" \
|
|
234
|
+
--why "Users can create projects without leaving the dashboard" \
|
|
235
|
+
--change "Project creation now happens inline" \
|
|
236
|
+
--tech "Next.js server actions and React form state" \
|
|
237
|
+
--step "goto:/dashboard" \
|
|
238
|
+
--step "click:text=New project" \
|
|
239
|
+
--step "fill:input[name=name]:Demo Project" \
|
|
240
|
+
--step "click:text=Create" \
|
|
241
|
+
--step "expect:Demo Project" \
|
|
242
|
+
--test "npm test"
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
## Demo Step DSL
|
|
246
|
+
|
|
247
|
+
```text
|
|
248
|
+
goto:/path
|
|
249
|
+
click:text=Button label
|
|
250
|
+
fill:input[name=email]:user@example.com
|
|
251
|
+
press:input[name=q]:Enter
|
|
252
|
+
expect:Expected text on screen
|
|
253
|
+
screenshot:after-action
|
|
254
|
+
wait:500
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
For richer demos, generate a JSON plan:
|
|
258
|
+
|
|
259
|
+
```bash
|
|
260
|
+
demo-this-pr init-demo --output demo-this-pr.demo.json
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
Then run:
|
|
264
|
+
|
|
265
|
+
```bash
|
|
266
|
+
demo-this-pr demo --demo-plan demo-this-pr.demo.json
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
## Playwright MCP
|
|
270
|
+
|
|
271
|
+
Every run also writes an MCP-first browser verification guide:
|
|
272
|
+
|
|
273
|
+
```text
|
|
274
|
+
MCP_PLAYWRIGHT.md
|
|
275
|
+
mcp-playwright-demo.js
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
Agents with Playwright MCP can load `mcp-playwright-demo.js` through `mcp__playwright__.browser_run_code_unsafe`, run the same browser flow, capture screenshots, and close the MCP tab afterwards.
|
|
279
|
+
|
|
280
|
+
## Development
|
|
281
|
+
|
|
282
|
+
```bash
|
|
283
|
+
npm install
|
|
284
|
+
npm run build
|
|
285
|
+
npm test
|
|
286
|
+
npm run check
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
The repository includes a root `AGENTS.md` with the local browser-testing policy and implementation standards for future agents.
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
<svg width="1200" height="330" viewBox="0 0 1200 330" fill="none" xmlns="http://www.w3.org/2000/svg" role="img" aria-labelledby="title desc">
|
|
2
|
+
<title id="title">DEMO THIS PR animated wordmark</title>
|
|
3
|
+
<desc id="desc">Animated terminal-style wordmark reading DEMO THIS PR.</desc>
|
|
4
|
+
<defs>
|
|
5
|
+
<linearGradient id="bg" x1="0" y1="0" x2="1200" y2="330" gradientUnits="userSpaceOnUse">
|
|
6
|
+
<stop offset="0" stop-color="#0B0F14"/>
|
|
7
|
+
<stop offset="0.58" stop-color="#111820"/>
|
|
8
|
+
<stop offset="1" stop-color="#171D24"/>
|
|
9
|
+
</linearGradient>
|
|
10
|
+
<linearGradient id="ink" x1="90" y1="0" x2="1090" y2="0" gradientUnits="userSpaceOnUse">
|
|
11
|
+
<stop offset="0" stop-color="#F8FAFC"/>
|
|
12
|
+
<stop offset="0.55" stop-color="#E7EEF7"/>
|
|
13
|
+
<stop offset="1" stop-color="#B9C7D7"/>
|
|
14
|
+
</linearGradient>
|
|
15
|
+
<filter id="shadow" x="-10%" y="-40%" width="120%" height="190%">
|
|
16
|
+
<feDropShadow dx="8" dy="8" stdDeviation="0" flood-color="#748094" flood-opacity="0.42"/>
|
|
17
|
+
<feDropShadow dx="13" dy="13" stdDeviation="0" flood-color="#334155" flood-opacity="0.5"/>
|
|
18
|
+
<feDropShadow dx="0" dy="22" stdDeviation="18" flood-color="#000000" flood-opacity="0.4"/>
|
|
19
|
+
</filter>
|
|
20
|
+
</defs>
|
|
21
|
+
|
|
22
|
+
<rect x="32" y="34" width="1136" height="262" rx="18" fill="url(#bg)"/>
|
|
23
|
+
<rect x="32" y="34" width="1136" height="262" rx="18" stroke="#2B3542" stroke-width="2"/>
|
|
24
|
+
|
|
25
|
+
<text x="78" y="82" fill="#91A4BA" font-family="ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, Liberation Mono, monospace" font-size="17" font-weight="800" letter-spacing="4">LOCAL PR DEMOS · PLAYWRIGHT MP4 · REVIEW EVIDENCE</text>
|
|
26
|
+
|
|
27
|
+
<g filter="url(#shadow)" font-family="ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, Liberation Mono, monospace" font-size="104" font-weight="950" letter-spacing="0" fill="url(#ink)">
|
|
28
|
+
<g><text x="78" y="202">D</text><animateTransform attributeName="transform" type="translate" values="0 0;0 -11;0 0" dur="2.8s" begin="0s" repeatCount="indefinite"/></g>
|
|
29
|
+
<g><text x="145" y="202">E</text><animateTransform attributeName="transform" type="translate" values="0 0;0 -9;0 0" dur="2.8s" begin="0.08s" repeatCount="indefinite"/></g>
|
|
30
|
+
<g><text x="212" y="202">M</text><animateTransform attributeName="transform" type="translate" values="0 0;0 -13;0 0" dur="2.8s" begin="0.16s" repeatCount="indefinite"/></g>
|
|
31
|
+
<g><text x="296" y="202">O</text><animateTransform attributeName="transform" type="translate" values="0 0;0 -10;0 0" dur="2.8s" begin="0.24s" repeatCount="indefinite"/></g>
|
|
32
|
+
<g><text x="410" y="202">T</text><animateTransform attributeName="transform" type="translate" values="0 0;0 -8;0 0" dur="2.8s" begin="0.32s" repeatCount="indefinite"/></g>
|
|
33
|
+
<g><text x="477" y="202">H</text><animateTransform attributeName="transform" type="translate" values="0 0;0 -12;0 0" dur="2.8s" begin="0.4s" repeatCount="indefinite"/></g>
|
|
34
|
+
<g><text x="544" y="202">I</text><animateTransform attributeName="transform" type="translate" values="0 0;0 -9;0 0" dur="2.8s" begin="0.48s" repeatCount="indefinite"/></g>
|
|
35
|
+
<g><text x="611" y="202">S</text><animateTransform attributeName="transform" type="translate" values="0 0;0 -13;0 0" dur="2.8s" begin="0.56s" repeatCount="indefinite"/></g>
|
|
36
|
+
<g><text x="728" y="202">P</text><animateTransform attributeName="transform" type="translate" values="0 0;0 -10;0 0" dur="2.8s" begin="0.64s" repeatCount="indefinite"/></g>
|
|
37
|
+
<g><text x="795" y="202">R</text><animateTransform attributeName="transform" type="translate" values="0 0;0 -12;0 0" dur="2.8s" begin="0.72s" repeatCount="indefinite"/></g>
|
|
38
|
+
</g>
|
|
39
|
+
|
|
40
|
+
<text x="78" y="264" fill="#91A4BA" font-family="ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, Liberation Mono, monospace" font-size="17" font-weight="800" letter-spacing="2">SHOW THE CHANGE BEFORE THE PULL REQUEST</text>
|
|
41
|
+
</svg>
|
package/dist/auto.d.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { GitFileChange, PrKitOptions } from "./types.js";
|
|
2
|
+
export interface AutoDemoResult {
|
|
3
|
+
options: PrKitOptions;
|
|
4
|
+
cleanup(): Promise<void>;
|
|
5
|
+
notes: string[];
|
|
6
|
+
}
|
|
7
|
+
export declare function resolveAutoDemo(cwd: string, overrides: {
|
|
8
|
+
headless: boolean;
|
|
9
|
+
output?: string;
|
|
10
|
+
open: boolean;
|
|
11
|
+
}): Promise<AutoDemoResult>;
|
|
12
|
+
export declare function titleForAutoRun(input: {
|
|
13
|
+
gitAvailable?: boolean;
|
|
14
|
+
branch: string;
|
|
15
|
+
commits: string[];
|
|
16
|
+
changedFiles: GitFileChange[];
|
|
17
|
+
}): string;
|