@linghun/pre-engine-darwin-x64 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.
@@ -0,0 +1,172 @@
1
+ "use strict";
2
+ const readline = require("readline");
3
+ const path = require("path");
4
+ const fs = require("fs");
5
+ const { spawnSync } = require("child_process");
6
+
7
+ function findSqlfluff() {
8
+ const whichCmd = process.platform === "win32" ? "where.exe" : "which";
9
+ const r = spawnSync(whichCmd, ["sqlfluff"], {
10
+ encoding: "utf8", stdio: ["ignore", "pipe", "ignore"], windowsHide: true,
11
+ });
12
+ if (r.status === 0) {
13
+ const line = r.stdout.split(/\r?\n/).map(l => l.trim()).filter(Boolean)[0];
14
+ return line || null;
15
+ }
16
+ return null;
17
+ }
18
+
19
+ function runSqlfluff(root, files) {
20
+ const sqlfluff = findSqlfluff();
21
+ if (!sqlfluff) return null;
22
+
23
+ const absPaths = files.map(f => path.isAbsolute(f) ? f : path.join(root, f));
24
+ const args = ["lint", "--format", "json", "--nocolor", ...absPaths];
25
+ let r;
26
+ try {
27
+ r = spawnSync(sqlfluff, args, {
28
+ cwd: root, encoding: "utf8", stdio: ["ignore", "pipe", "pipe"],
29
+ windowsHide: true, timeout: 30000,
30
+ });
31
+ } catch (e) { return { error: `sqlfluff exec: ${e.message}` }; }
32
+
33
+ if (r.error) {
34
+ return { error: r.error.code === "ETIMEDOUT" ? "sqlfluff timeout" : r.error.message };
35
+ }
36
+
37
+ const issues = [];
38
+ const output = r.stdout || "";
39
+ try {
40
+ const parsed = JSON.parse(output);
41
+ for (const fileEntry of parsed) {
42
+ const filePath = fileEntry.filepath || "";
43
+ const rel = path.relative(root, filePath).replace(/\\/g, "/");
44
+ for (const violation of (fileEntry.violations || [])) {
45
+ issues.push({
46
+ file: rel,
47
+ line: violation.start_line_no || violation.line_no || 1,
48
+ col: violation.start_line_pos || violation.line_pos || 1,
49
+ kind: "sql_error",
50
+ message: violation.description || violation.message || "SQL lint error",
51
+ code: violation.code || null,
52
+ source: "sql-deep-layer",
53
+ });
54
+ }
55
+ }
56
+ } catch {
57
+ const lines = output.split(/\r?\n/);
58
+ for (const l of lines) {
59
+ const m = l.match(/^(.+?):(\d+):(\d+):\s*(.+)/);
60
+ if (m) {
61
+ issues.push({
62
+ file: path.relative(root, m[1]).replace(/\\/g, "/"),
63
+ line: parseInt(m[2], 10), col: parseInt(m[3], 10),
64
+ kind: "sql_error", message: m[4], source: "sql-deep-layer",
65
+ });
66
+ }
67
+ }
68
+ }
69
+ return { issues };
70
+ }
71
+
72
+ function fallbackSyntaxCheck(root, files) {
73
+ const issues = [];
74
+ for (const f of files) {
75
+ const abs = path.isAbsolute(f) ? f : path.join(root, f);
76
+ let content;
77
+ try { content = fs.readFileSync(abs, "utf8"); } catch { continue; }
78
+ const rel = path.relative(root, abs).replace(/\\/g, "/");
79
+ const lines = content.split(/\r?\n/);
80
+ let parenDepth = 0;
81
+ let inSingleQuote = false;
82
+ let unclosedQuoteLine = 0;
83
+ for (let i = 0; i < lines.length; i++) {
84
+ const line = lines[i];
85
+ for (let j = 0; j < line.length; j++) {
86
+ const ch = line[j];
87
+ if (ch === "'" && (j === 0 || line[j - 1] !== "'")) {
88
+ if (!inSingleQuote) { inSingleQuote = true; unclosedQuoteLine = i + 1; }
89
+ else { inSingleQuote = false; }
90
+ }
91
+ if (!inSingleQuote) {
92
+ if (ch === "(") parenDepth++;
93
+ else if (ch === ")") parenDepth--;
94
+ }
95
+ }
96
+ if (inSingleQuote && i < lines.length - 1) {
97
+ if (!lines[i + 1].includes("'")) {
98
+ issues.push({ file: rel, line: unclosedQuoteLine, col: 1,
99
+ kind: "syntax_error", message: "Unclosed string literal",
100
+ source: "sql-deep-layer" });
101
+ inSingleQuote = false;
102
+ }
103
+ }
104
+ }
105
+ if (inSingleQuote) {
106
+ issues.push({ file: rel, line: unclosedQuoteLine, col: 1,
107
+ kind: "syntax_error", message: "Unclosed string literal at end of file",
108
+ source: "sql-deep-layer" });
109
+ }
110
+ if (parenDepth > 0) {
111
+ issues.push({ file: rel, line: 1, col: 1,
112
+ kind: "syntax_error", message: `Unmatched opening parenthesis (${parenDepth} unclosed)`,
113
+ source: "sql-deep-layer" });
114
+ } else if (parenDepth < 0) {
115
+ issues.push({ file: rel, line: 1, col: 1,
116
+ kind: "syntax_error", message: `Unmatched closing parenthesis (${-parenDepth} extra)`,
117
+ source: "sql-deep-layer" });
118
+ }
119
+ }
120
+ return issues;
121
+ }
122
+
123
+ async function handleRequest(req) {
124
+ const t0 = Date.now();
125
+ const root = req.root || process.cwd();
126
+ const files = req.files || [];
127
+ if (files.length === 0) {
128
+ return { issues: [], status: "clean", reason: "no_files", elapsed_ms: 0 };
129
+ }
130
+
131
+ const sqlfluffResult = runSqlfluff(root, files);
132
+ if (sqlfluffResult && !sqlfluffResult.error) {
133
+ return {
134
+ issues: sqlfluffResult.issues,
135
+ status: sqlfluffResult.issues.length > 0 ? "sql_error" : "clean",
136
+ reason: "sqlfluff",
137
+ elapsed_ms: Date.now() - t0,
138
+ };
139
+ }
140
+
141
+ const fallbackIssues = fallbackSyntaxCheck(root, files);
142
+ if (sqlfluffResult && sqlfluffResult.error) {
143
+ return {
144
+ issues: fallbackIssues,
145
+ status: fallbackIssues.length > 0 ? "syntax_error" : "clean",
146
+ reason: "fallback",
147
+ fallback: sqlfluffResult.error,
148
+ elapsed_ms: Date.now() - t0,
149
+ };
150
+ }
151
+
152
+ return {
153
+ issues: fallbackIssues,
154
+ status: fallbackIssues.length > 0 ? "syntax_error" : "clean",
155
+ reason: fallbackIssues.length > 0 ? "fallback" : "fallback_clean",
156
+ elapsed_ms: Date.now() - t0,
157
+ };
158
+ }
159
+
160
+ const rl = readline.createInterface({ input: process.stdin, terminal: false });
161
+ rl.on("line", (line) => {
162
+ const trimmed = line.trim();
163
+ if (!trimmed) return;
164
+ let req;
165
+ try { req = JSON.parse(trimmed); } catch { return; }
166
+ handleRequest(req).then((result) => {
167
+ process.stdout.write(JSON.stringify(result) + "\n");
168
+ }).catch((err) => {
169
+ process.stdout.write(JSON.stringify({ issues: [], status: "error", error: String(err), elapsed_ms: 0 }) + "\n");
170
+ });
171
+ });
172
+ rl.on("close", () => { process.exit(0); });
@@ -0,0 +1,113 @@
1
+ "use strict";
2
+ const readline = require("readline");
3
+ const path = require("path");
4
+ const { spawnSync } = require("child_process");
5
+
6
+ function findSwiftc() {
7
+ const whichCmd = process.platform === "win32" ? "where.exe" : "which";
8
+ for (const cmd of ["swiftc", "xcrun"]) {
9
+ const r = spawnSync(whichCmd, [cmd], {
10
+ encoding: "utf8", stdio: ["ignore", "pipe", "ignore"], windowsHide: true,
11
+ });
12
+ if (r.status === 0) {
13
+ const line = r.stdout.split(/\r?\n/).map(l => l.trim()).filter(Boolean)[0];
14
+ if (line) return cmd === "xcrun" ? { mode: "xcrun", bin: line } : { mode: "swiftc", bin: line };
15
+ }
16
+ }
17
+ return null;
18
+ }
19
+
20
+ function runSwiftcCheck(root, files) {
21
+ const tool = findSwiftc();
22
+ if (!tool) return null;
23
+
24
+ const issues = [];
25
+ for (const f of files) {
26
+ const abs = path.isAbsolute(f) ? f : path.join(root, f);
27
+ let args;
28
+ if (tool.mode === "xcrun") {
29
+ args = [tool.bin, ["swiftc", "-parse", abs]];
30
+ } else {
31
+ args = [tool.bin, ["-parse", abs]];
32
+ }
33
+ let r;
34
+ try {
35
+ r = spawnSync(args[0], args[1], {
36
+ cwd: root, encoding: "utf8", stdio: ["ignore", "pipe", "pipe"],
37
+ windowsHide: true, timeout: 60000,
38
+ });
39
+ } catch (e) { continue; }
40
+
41
+ if (r.error) continue;
42
+
43
+ if (r.status !== 0) {
44
+ const output = (r.stderr || "") + (r.stdout || "");
45
+ const rel = path.relative(root, abs).replace(/\\/g, "/");
46
+ const lines = output.split(/\r?\n/);
47
+ let found = false;
48
+ for (const line of lines) {
49
+ const m = line.match(/^.+?:(\d+):(\d+):\s*(error|warning|note):\s*(.+)$/);
50
+ if (m && m[3] !== "note") {
51
+ issues.push({
52
+ file: rel,
53
+ line: parseInt(m[1], 10),
54
+ col: parseInt(m[2], 10),
55
+ kind: m[3] === "warning" ? "warning" : "error",
56
+ message: m[4].trim(),
57
+ source: "swift-deep-layer",
58
+ });
59
+ found = true;
60
+ }
61
+ }
62
+ if (!found) {
63
+ const firstLine = lines.find(l => l.trim()) || "compilation error";
64
+ issues.push({
65
+ file: rel, line: 1, col: 1,
66
+ kind: "error", message: firstLine.trim(),
67
+ source: "swift-deep-layer",
68
+ });
69
+ }
70
+ }
71
+ }
72
+ return { issues };
73
+ }
74
+
75
+ async function handleRequest(req) {
76
+ const t0 = Date.now();
77
+ const root = req.root || process.cwd();
78
+ const files = req.files || [];
79
+ if (files.length === 0) {
80
+ return { issues: [], status: "clean", reason: "no_files", elapsed_ms: 0 };
81
+ }
82
+
83
+ const lintResult = runSwiftcCheck(root, files);
84
+ if (lintResult) {
85
+ return {
86
+ issues: lintResult.issues,
87
+ status: lintResult.issues.length > 0 ? "swift_error" : "clean",
88
+ reason: "swiftc",
89
+ elapsed_ms: Date.now() - t0,
90
+ };
91
+ }
92
+
93
+ return {
94
+ issues: [],
95
+ status: "unavailable",
96
+ reason: "swift_not_found",
97
+ elapsed_ms: Date.now() - t0,
98
+ };
99
+ }
100
+
101
+ const rl = readline.createInterface({ input: process.stdin, terminal: false });
102
+ rl.on("line", (line) => {
103
+ const trimmed = line.trim();
104
+ if (!trimmed) return;
105
+ let req;
106
+ try { req = JSON.parse(trimmed); } catch { return; }
107
+ handleRequest(req).then((result) => {
108
+ process.stdout.write(JSON.stringify(result) + "\n");
109
+ }).catch((err) => {
110
+ process.stdout.write(JSON.stringify({ issues: [], status: "error", error: String(err), elapsed_ms: 0 }) + "\n");
111
+ });
112
+ });
113
+ rl.on("close", () => { process.exit(0); });
@@ -0,0 +1,142 @@
1
+ "use strict";
2
+ const readline = require("readline");
3
+ const path = require("path");
4
+ const fs = require("fs");
5
+
6
+ let ts = null;
7
+ let cachedHost = null;
8
+ let cachedOpts = null;
9
+ let cachedFileNames = null;
10
+ let cachedRoot = null;
11
+ let cachedTsconfigPath = null;
12
+ let currentProgram = null;
13
+ let fileStatCache = new Map();
14
+ let knownProjectFiles = new Set();
15
+
16
+ function updateStatCache(absPath) {
17
+ try {
18
+ const st = fs.statSync(absPath);
19
+ const cached = fileStatCache.get(absPath);
20
+ const changed = !cached || cached.mtimeMs !== st.mtimeMs || cached.size !== st.size;
21
+ fileStatCache.set(absPath, { mtimeMs: st.mtimeMs, size: st.size });
22
+ return changed;
23
+ } catch {
24
+ fileStatCache.delete(absPath);
25
+ return true;
26
+ }
27
+ }
28
+
29
+ function tryResolveTs(root) {
30
+ for (const c of [path.join(root, "node_modules", "typescript"), "typescript"]) {
31
+ try { return require(c); } catch {}
32
+ }
33
+ return null;
34
+ }
35
+
36
+ function ensureSetup(root, tsconfigPath) {
37
+ if (!ts) {
38
+ ts = tryResolveTs(root);
39
+ if (!ts) return "typescript not available";
40
+ }
41
+ if (cachedRoot === root && cachedTsconfigPath === tsconfigPath) return null;
42
+
43
+ let opts = { noEmit: true, strict: false, skipLibCheck: true };
44
+ let fileNames = [];
45
+
46
+ if (tsconfigPath) {
47
+ const cfgFile = ts.readConfigFile(tsconfigPath, ts.sys.readFile);
48
+ if (!cfgFile.error) {
49
+ const parsed = ts.parseJsonConfigFileContent(cfgFile.config, ts.sys, path.dirname(tsconfigPath));
50
+ opts = { ...parsed.options, noEmit: true };
51
+ fileNames = parsed.fileNames;
52
+ }
53
+ }
54
+
55
+ cachedOpts = opts;
56
+ cachedFileNames = fileNames;
57
+ cachedHost = ts.createCompilerHost(opts);
58
+ cachedRoot = root;
59
+ cachedTsconfigPath = tsconfigPath;
60
+ currentProgram = null;
61
+ fileStatCache.clear();
62
+ knownProjectFiles.clear();
63
+ return null;
64
+ }
65
+
66
+ function runCheck(root, files, tsconfigPath) {
67
+ const err = ensureSetup(root, tsconfigPath);
68
+ if (err) return { error: err };
69
+
70
+ const absFiles = files.map(f => path.isAbsolute(f) ? f : path.join(root, f));
71
+ for (const f of absFiles) knownProjectFiles.add(f);
72
+ const allFiles = [...new Set([...cachedFileNames, ...knownProjectFiles])];
73
+
74
+ let anyStatChanged = false;
75
+ for (const f of absFiles) {
76
+ if (updateStatCache(f)) anyStatChanged = true;
77
+ }
78
+ let needRebuild = !currentProgram || anyStatChanged;
79
+ if (!needRebuild) {
80
+ for (const f of absFiles) {
81
+ if (!currentProgram.getSourceFile(path.normalize(f))) {
82
+ needRebuild = true;
83
+ break;
84
+ }
85
+ }
86
+ }
87
+
88
+ if (needRebuild) {
89
+ currentProgram = ts.createProgram(allFiles, cachedOpts, cachedHost, currentProgram);
90
+ const normalRoot = path.normalize(root) + path.sep;
91
+ for (const sf of currentProgram.getSourceFiles()) {
92
+ const sfPath = path.normalize(sf.fileName);
93
+ if (sfPath.startsWith(normalRoot) && !fileStatCache.has(sfPath)) {
94
+ updateStatCache(sfPath);
95
+ }
96
+ }
97
+ }
98
+
99
+ const issues = [];
100
+ for (const f of absFiles) {
101
+ const sf = currentProgram.getSourceFile(path.normalize(f));
102
+ if (!sf) continue;
103
+ const diags = [
104
+ ...currentProgram.getSemanticDiagnostics(sf),
105
+ ...currentProgram.getSyntacticDiagnostics(sf),
106
+ ];
107
+ for (const d of diags) {
108
+ if (d.category !== 1) continue;
109
+ const rel = path.relative(root, sf.fileName).replace(/\\/g, "/");
110
+ let line = 1;
111
+ if (d.file && d.start != null) {
112
+ const lc = d.file.getLineAndCharacterOfPosition(d.start);
113
+ line = lc.line + 1;
114
+ }
115
+ issues.push({
116
+ file: rel,
117
+ line,
118
+ kind: "type_error",
119
+ detail: ts.flattenDiagnosticMessageText(d.messageText, " "),
120
+ source: "typescript-deep-layer",
121
+ });
122
+ }
123
+ }
124
+ return { issues };
125
+ }
126
+
127
+ const rl = readline.createInterface({ input: process.stdin, terminal: false });
128
+ rl.on("line", line => {
129
+ line = line.trim();
130
+ if (!line) return;
131
+ let req;
132
+ try { req = JSON.parse(line); } catch { return; }
133
+ const t0 = Date.now();
134
+ let resp;
135
+ try {
136
+ const result = runCheck(req.root, req.files || [], req.tsconfig || null);
137
+ resp = { ...result, elapsed_ms: Date.now() - t0 };
138
+ } catch (e) {
139
+ resp = { error: String(e), elapsed_ms: Date.now() - t0 };
140
+ }
141
+ process.stdout.write(JSON.stringify(resp) + "\n");
142
+ });
package/package.json ADDED
@@ -0,0 +1,17 @@
1
+ {
2
+ "name": "@linghun/pre-engine-darwin-x64",
3
+ "version": "0.1.0",
4
+ "license": "Apache-2.0",
5
+ "os": [
6
+ "darwin"
7
+ ],
8
+ "cpu": [
9
+ "x64"
10
+ ],
11
+ "files": [
12
+ "bundled"
13
+ ],
14
+ "publishConfig": {
15
+ "access": "public"
16
+ }
17
+ }