open-ready 0.1.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.
Files changed (2) hide show
  1. package/open-when-ready.mjs +104 -0
  2. package/package.json +37 -0
@@ -0,0 +1,104 @@
1
+ #!/usr/bin/env node
2
+ import fsPromises from "fs/promises";
3
+ import fs from "fs";
4
+ import path from "path";
5
+ import { spawn } from "child_process";
6
+ import open from "open";
7
+ import minimist from "minimist";
8
+
9
+ const argv = minimist(process.argv.slice(2));
10
+ const cmdArgs = argv._;
11
+ const aiBase = argv["ai-base"] || "https://perplexity.ai?q=";
12
+ const noAi = argv.noAi || argv.noai || argv.ai === false;
13
+ const maxErrorContextChars = 1000;
14
+
15
+ const nextDir = path.join(".", ".next");
16
+ const logPath = fs.existsSync(nextDir)
17
+ ? path.join(".next", "port.log")
18
+ : "open-when-ready.log";
19
+
20
+ console.log(`📁 Log: ${logPath}`);
21
+
22
+ function getErrorContext(log) {
23
+ console.log("🔍 Log preview:", log.slice(0, 200));
24
+ const lines = log.split(/\n/);
25
+ const errorRegex = /⨯|[Ss]yntax[Ee]rror|error/i;
26
+ console.log("Regex:", errorRegex);
27
+ for (let i = 0; i < lines.length; i++) {
28
+ if (errorRegex.test(lines[i])) {
29
+ console.log("✅ MATCHED on line", i, ":", lines[i].slice(0, 100));
30
+ const context = lines
31
+ .slice(Math.max(0, i - 5), i + 16)
32
+ .slice(0, 25)
33
+ .join(" ")
34
+ .replace(/[^\w\s:./\-]/g, "")
35
+ .trim()
36
+ .replace(/\s{2,}/g, " ")
37
+ .slice(0, maxErrorContextChars)
38
+ .replace(/ /g, "%20");
39
+ console.log("Context:", context.slice(0, 100));
40
+ return context;
41
+ }
42
+ }
43
+ return "";
44
+ }
45
+
46
+ async function run() {
47
+ try {
48
+ await fsPromises.rm(logPath, { force: true });
49
+ } catch {}
50
+ console.log("🚀 Starting", cmdArgs.join(" "));
51
+
52
+ const proc = spawn(cmdArgs.join(" "), [], {
53
+ stdio: ["ignore", "pipe", "pipe", "ipc"],
54
+ shell: true,
55
+ });
56
+
57
+ const logStream = fs.createWriteStream(logPath);
58
+ proc.stdout?.pipe(process.stdout);
59
+ proc.stdout?.pipe(logStream);
60
+ proc.stderr?.pipe(process.stderr);
61
+ proc.stderr?.pipe(logStream);
62
+
63
+ let opened = false;
64
+ let pollCount = 0;
65
+
66
+ // Aggressive 500ms poll + debug
67
+ const poll = setInterval(async () => {
68
+ pollCount++;
69
+ console.log(`⏱️ Poll #${pollCount}`);
70
+ if (opened) return;
71
+ try {
72
+ await sleep(100); // Brief settle
73
+ const stats = fs.statSync(logPath);
74
+ console.log("📊 Log size:", stats.size);
75
+ if (stats.size > 100) {
76
+ const log = await fsPromises.readFile(logPath, "utf8");
77
+ const errorRegex = /⨯|[Ss]yntax[Ee]rror|error/i;
78
+ if (errorRegex.test(log) && !noAi) {
79
+ console.log("🎯 ERROR TRIGGERED!");
80
+ const err = getErrorContext(log);
81
+ console.log("🔗 Opening:", `${aiBase}next.js+${err.slice(0, 50)}...`);
82
+ await open(`${aiBase}next.js+${err}`);
83
+ opened = true;
84
+ clearInterval(poll);
85
+ proc.kill();
86
+ return;
87
+ }
88
+ }
89
+ } catch (e) {
90
+ console.log("Poll error:", e.message);
91
+ }
92
+ }, 500);
93
+
94
+ setTimeout(() => {
95
+ clearInterval(poll);
96
+ proc.kill();
97
+ }, 30000);
98
+ }
99
+
100
+ function sleep(ms) {
101
+ return new Promise((r) => setTimeout(r, ms));
102
+ }
103
+
104
+ run().catch(console.error);
package/package.json ADDED
@@ -0,0 +1,37 @@
1
+ {
2
+ "name": "open-ready",
3
+ "version": "0.1.1",
4
+ "description": "Smart dev server launcher: error→AI search, success→auto-open browser. Any CLI tool.",
5
+ "type": "module",
6
+ "bin": {
7
+ "open-ready": "./open-when-ready.mjs"
8
+ },
9
+ "scripts": {
10
+ "ship": "bun x standard-version --release-as patch;rm CHANGELOG.md; npm publish",
11
+ "owr": "./open-when-ready.mjs bun run build"
12
+ },
13
+ "keywords": [
14
+ "devtools",
15
+ "nextjs",
16
+ "vite",
17
+ "cli",
18
+ "automation"
19
+ ],
20
+ "license": "MIT",
21
+ "dependencies": {
22
+ "minimist": "^1.2.8",
23
+ "open": "^10.1.0",
24
+ "wait-on": "^8.0.1"
25
+ },
26
+ "engines": {
27
+ "node": ">=18.0.0"
28
+ },
29
+ "repository": {
30
+ "type": "github",
31
+ "url": "https://github.com/yourusername/open-when-ready"
32
+ },
33
+ "bugs": {
34
+ "url": "https://github.com/yourusername/open-when-ready/issues"
35
+ },
36
+ "homepage": "https://github.com/yourusername/open-when-ready#readme"
37
+ }