@tsrx/oxc 0.0.0-trusted-publishing-bootstrap → 0.8.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 +141 -0
- package/THIRD_PARTY_NOTICES.md +49 -0
- package/bin/oxc-tsrx +2 -0
- package/bin/oxc-tsrx-fmt +2 -0
- package/bin/oxc-tsrx-lint +2 -0
- package/bin/oxc-tsrx-lsp +2 -0
- package/bin/oxfmt +2 -0
- package/bin/oxlint +2 -0
- package/dist/bin/oxc-tsrx-fmt.js +13 -0
- package/dist/bin/oxc-tsrx-lint.js +13 -0
- package/dist/bin/oxc-tsrx-lsp.js +13 -0
- package/dist/bin/oxc-tsrx.js +115 -0
- package/dist/bin/oxfmt.js +24 -0
- package/dist/bin/oxlint.js +33 -0
- package/dist/canonical-command.d.ts +50 -0
- package/dist/canonical-command.js +196 -0
- package/dist/compat.d.ts +149 -0
- package/dist/compat.js +1615 -0
- package/dist/editor-resolution.js +508 -0
- package/dist/format-cli.js +276 -0
- package/dist/format-invocation.js +97 -0
- package/dist/format.d.ts +1 -0
- package/dist/format.js +56 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +16 -0
- package/dist/lint-cli.js +487 -0
- package/dist/lint-invocation.js +192 -0
- package/dist/lint-js-plugins.js +819 -0
- package/dist/lint-plugins-dev.d.ts +1 -0
- package/dist/lint-plugins-dev.js +2 -0
- package/dist/lint-prestart.js +16 -0
- package/dist/lint.d.ts +1 -0
- package/dist/lint.js +2 -0
- package/dist/native-targets.js +76 -0
- package/dist/oxlint-lsp-multiplexer.js +622 -0
- package/dist/package-binary.js +29 -0
- package/dist/parser.d.ts +216 -0
- package/dist/parser.js +557 -0
- package/dist/process.js +88 -0
- package/dist/provider-resolve.d.ts +160 -0
- package/dist/provider-resolve.js +471 -0
- package/dist/providers-report.js +49 -0
- package/dist/runtime.js +323 -0
- package/dist/spawn-command.d.ts +20 -0
- package/dist/spawn-command.js +87 -0
- package/dist/tsrx-core-compat/facade.js +1184 -0
- package/dist/tsrx-core-compat/index.d.ts +6 -0
- package/dist/tsrx-core-compat/index.js +9 -0
- package/dist/tsrx-core-compat/style.js +525 -0
- package/dist/tsrx-core-compat/types/estree.d.ts +20 -0
- package/dist/tsrx-core-compat/types/index.d.ts +50 -0
- package/dist/tsrx-transfer.js +352 -0
- package/package.json +144 -5
|
@@ -0,0 +1,276 @@
|
|
|
1
|
+
import { resolvePackageBinary } from "./package-binary.js";
|
|
2
|
+
import { runCaptured, runPassthrough } from "./process.js";
|
|
3
|
+
import { argumentValue, canonicalToolEnvironment, discoverTsrxFiles, isViteConfigPath, prepareVitePlusConfig, removeExplicitTsrx, replaceConfigArgument, resolveNativeCommand } from "./runtime.js";
|
|
4
|
+
import { VALUE_OPTIONS, parseOxfmtInvocation, parseOxfmtOption } from "./format-invocation.js";
|
|
5
|
+
import { isAbsolute, relative } from "node:path";
|
|
6
|
+
import { readFileSync } from "node:fs";
|
|
7
|
+
//#region src/format-cli.ts
|
|
8
|
+
function unknownOptionMessage(name) {
|
|
9
|
+
return `Error: \`${name}\` is not expected in this context`;
|
|
10
|
+
}
|
|
11
|
+
function unknownCanonicalOption(args) {
|
|
12
|
+
let positionalOnly = false;
|
|
13
|
+
for (let index = 0; index < args.length; index += 1) {
|
|
14
|
+
const argument = args[index];
|
|
15
|
+
if (positionalOnly) continue;
|
|
16
|
+
if (argument === "--") {
|
|
17
|
+
positionalOnly = true;
|
|
18
|
+
continue;
|
|
19
|
+
}
|
|
20
|
+
if (!argument.startsWith("-") || argument === "-") continue;
|
|
21
|
+
const { name, value } = parseOxfmtOption(argument);
|
|
22
|
+
if (VALUE_OPTIONS.has(name)) {
|
|
23
|
+
if (value === null) index += 1;
|
|
24
|
+
continue;
|
|
25
|
+
}
|
|
26
|
+
if (!parseOxfmtInvocation([name]).known) return name;
|
|
27
|
+
}
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
30
|
+
function attributeNativeErrors(stderr) {
|
|
31
|
+
return stderr.replace(/^oxc-tsrx-fmt: /gmu, "oxfmt (oxc-tsrx): ");
|
|
32
|
+
}
|
|
33
|
+
function hasTsrxPositional(positionals) {
|
|
34
|
+
return positionals.some((argument) => argument.split("?")[0].endsWith(".tsrx"));
|
|
35
|
+
}
|
|
36
|
+
const NATIVE_VALUE_OPTIONS = /* @__PURE__ */ new Map([
|
|
37
|
+
["-c", "--config"],
|
|
38
|
+
["--config", "--config"],
|
|
39
|
+
["--threads", "--threads"]
|
|
40
|
+
]);
|
|
41
|
+
const WRAPPER_OPTIONS = /* @__PURE__ */ new Set(["--no-error-on-unmatched-pattern"]);
|
|
42
|
+
function nativeArguments(args, files, resolvedConfig) {
|
|
43
|
+
const output = [];
|
|
44
|
+
let positionalOnly = false;
|
|
45
|
+
for (let index = 0; index < args.length; index += 1) {
|
|
46
|
+
const argument = args[index];
|
|
47
|
+
if (positionalOnly) continue;
|
|
48
|
+
if (argument === "--") {
|
|
49
|
+
positionalOnly = true;
|
|
50
|
+
continue;
|
|
51
|
+
}
|
|
52
|
+
if (!argument.startsWith("-") || argument === "-") continue;
|
|
53
|
+
const { name, value: inlineValue } = parseOxfmtOption(argument);
|
|
54
|
+
if (NATIVE_VALUE_OPTIONS.has(name)) {
|
|
55
|
+
const value = inlineValue ?? args[++index];
|
|
56
|
+
if (!value) throw new Error(`${name} requires a value`);
|
|
57
|
+
if (resolvedConfig && (name === "-c" || name === "--config")) continue;
|
|
58
|
+
output.push(NATIVE_VALUE_OPTIONS.get(name), value);
|
|
59
|
+
continue;
|
|
60
|
+
}
|
|
61
|
+
if (name === "--write" || name === "--check" || name === "--list-different") {
|
|
62
|
+
output.push(name);
|
|
63
|
+
continue;
|
|
64
|
+
}
|
|
65
|
+
if (WRAPPER_OPTIONS.has(name)) continue;
|
|
66
|
+
throw new Error(`${name} is not yet supported for .tsrx by the drop-in Oxfmt command; canonical Oxfmt still handles ordinary files`);
|
|
67
|
+
}
|
|
68
|
+
if (resolvedConfig) output.push("--config", resolvedConfig.path, "--config-base", resolvedConfig.base);
|
|
69
|
+
return [...output, ...files];
|
|
70
|
+
}
|
|
71
|
+
function withCwdRelativePaths(files, cwd) {
|
|
72
|
+
return files.map((file) => {
|
|
73
|
+
if (!isAbsolute(file)) return file;
|
|
74
|
+
const relativePath = relative(cwd, file);
|
|
75
|
+
if (relativePath === "" || relativePath.startsWith("..") || isAbsolute(relativePath)) return file;
|
|
76
|
+
return relativePath;
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
function fileMode(args) {
|
|
80
|
+
let mode = "write";
|
|
81
|
+
let positionalOnly = false;
|
|
82
|
+
for (let index = 0; index < args.length; index += 1) {
|
|
83
|
+
const argument = args[index];
|
|
84
|
+
if (positionalOnly) continue;
|
|
85
|
+
if (argument === "--") {
|
|
86
|
+
positionalOnly = true;
|
|
87
|
+
continue;
|
|
88
|
+
}
|
|
89
|
+
if (!argument.startsWith("-") || argument === "-") continue;
|
|
90
|
+
const { name, value: inlineValue } = parseOxfmtOption(argument);
|
|
91
|
+
if (VALUE_OPTIONS.has(name)) {
|
|
92
|
+
if (inlineValue === null) index += 1;
|
|
93
|
+
continue;
|
|
94
|
+
}
|
|
95
|
+
if (name === "--check") mode = "check";
|
|
96
|
+
else if (name === "--list-different") mode = "list-different";
|
|
97
|
+
else if (name === "--write") mode = "write";
|
|
98
|
+
}
|
|
99
|
+
return mode;
|
|
100
|
+
}
|
|
101
|
+
function reportedFileCount(line) {
|
|
102
|
+
const match = /\bon (\d+) files\b/u.exec(line ?? "");
|
|
103
|
+
return match ? Number(match[1]) : null;
|
|
104
|
+
}
|
|
105
|
+
function withReportedFileCount(line, count) {
|
|
106
|
+
return line.replace(/\bon \d+ files\b/u, `on ${count} files`);
|
|
107
|
+
}
|
|
108
|
+
function withVerdictCount(verdict, count) {
|
|
109
|
+
return verdict.replace(/\b\d+ files\b/u, `${count} files`);
|
|
110
|
+
}
|
|
111
|
+
function parseCheckReport(stdout) {
|
|
112
|
+
const separator = stdout.indexOf("\n\n");
|
|
113
|
+
if (separator <= 0 || stdout.slice(0, separator).includes("\n")) return null;
|
|
114
|
+
const preamble = stdout.slice(0, separator + 2);
|
|
115
|
+
const body = stdout.slice(separator + 2);
|
|
116
|
+
if (!body.endsWith("\n")) return {
|
|
117
|
+
preamble,
|
|
118
|
+
files: body === "" ? [] : body.split("\n"),
|
|
119
|
+
verdict: null,
|
|
120
|
+
summary: null,
|
|
121
|
+
count: null
|
|
122
|
+
};
|
|
123
|
+
const lines = body.slice(0, -1).split("\n");
|
|
124
|
+
const summary = lines.pop() ?? null;
|
|
125
|
+
const verdict = lines.pop() ?? null;
|
|
126
|
+
if (lines.at(-1) === "") lines.pop();
|
|
127
|
+
return {
|
|
128
|
+
preamble,
|
|
129
|
+
files: lines,
|
|
130
|
+
verdict,
|
|
131
|
+
summary,
|
|
132
|
+
count: reportedFileCount(summary)
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
function parseWriteReport(stdout) {
|
|
136
|
+
if (!stdout.endsWith("\n")) return null;
|
|
137
|
+
const line = stdout.slice(0, -1);
|
|
138
|
+
const count = reportedFileCount(line);
|
|
139
|
+
if (line.includes("\n") || count === null) return null;
|
|
140
|
+
return {
|
|
141
|
+
line,
|
|
142
|
+
count
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
function mergeCheckStdout(upstream, native, failed) {
|
|
146
|
+
const reports = [parseCheckReport(upstream.stdout), parseCheckReport(native.stdout)].filter(Boolean);
|
|
147
|
+
if (reports.length === 0) return upstream.stdout + native.stdout;
|
|
148
|
+
const preamble = reports[0].preamble;
|
|
149
|
+
const files = reports.flatMap((report) => report.files);
|
|
150
|
+
if (failed) return preamble + files.join("\n");
|
|
151
|
+
const verdict = files.length > 0 ? reports.find((report) => report.files.length > 0)?.verdict : reports.find((report) => report.files.length === 0)?.verdict;
|
|
152
|
+
const summary = reports.find((report) => report.summary !== null)?.summary;
|
|
153
|
+
if (!verdict || !summary) return upstream.stdout + native.stdout;
|
|
154
|
+
const count = reports.reduce((total, report) => total + (report.count ?? 0), 0);
|
|
155
|
+
return `${preamble}${files.join("\n")}${files.length > 0 ? "\n\n" : ""}${withVerdictCount(verdict, files.length)}\n${withReportedFileCount(summary, count)}\n`;
|
|
156
|
+
}
|
|
157
|
+
function mergeWriteStdout(upstream, native, failed) {
|
|
158
|
+
const reports = [upstream.stdout, native.stdout].map(parseWriteReport).filter(Boolean);
|
|
159
|
+
if (reports.length === 0) return upstream.stdout + native.stdout;
|
|
160
|
+
if (failed) return "";
|
|
161
|
+
const count = reports.reduce((total, report) => total + report.count, 0);
|
|
162
|
+
return `${withReportedFileCount(reports[0].line, count)}\n`;
|
|
163
|
+
}
|
|
164
|
+
function mergeListDifferentStdout(upstream, native) {
|
|
165
|
+
return [upstream.stdout, native.stdout].filter((part) => part.length > 0).join("\n");
|
|
166
|
+
}
|
|
167
|
+
function mergeFormatStdout(mode, upstream, native) {
|
|
168
|
+
const failed = upstream.status >= 2 || native.status >= 2;
|
|
169
|
+
if (mode === "list-different") return mergeListDifferentStdout(upstream, native);
|
|
170
|
+
if (mode === "check") return mergeCheckStdout(upstream, native, failed);
|
|
171
|
+
return mergeWriteStdout(upstream, native, failed);
|
|
172
|
+
}
|
|
173
|
+
function lastNonEmptyLine(text) {
|
|
174
|
+
return text.split("\n").filter((line) => line !== "").at(-1) ?? "";
|
|
175
|
+
}
|
|
176
|
+
function withoutLine(text, line) {
|
|
177
|
+
const marker = `${line}\n`;
|
|
178
|
+
const index = text.lastIndexOf(marker);
|
|
179
|
+
return index === -1 ? text : text.slice(0, index) + text.slice(index + marker.length);
|
|
180
|
+
}
|
|
181
|
+
function mergeFormatStderr(upstream, native, stdout) {
|
|
182
|
+
let leading = upstream.stderr;
|
|
183
|
+
const summary = lastNonEmptyLine(native.stderr);
|
|
184
|
+
if (summary !== "" && lastNonEmptyLine(leading) === summary) leading = withoutLine(leading, summary);
|
|
185
|
+
const merged = leading + native.stderr;
|
|
186
|
+
if (merged === "" || merged.startsWith("\n") || stdout === "" || stdout.endsWith("\n")) return merged;
|
|
187
|
+
return `\n${merged}`;
|
|
188
|
+
}
|
|
189
|
+
async function delegate(args, cwd, input) {
|
|
190
|
+
const upstreamArgs = [resolvePackageBinary("oxfmt-current", "oxfmt", import.meta.url), ...args];
|
|
191
|
+
if (args.some((argument) => argument.split("=")[0] === "--lsp")) return (await runPassthrough(process.execPath, upstreamArgs, { cwd })).status;
|
|
192
|
+
const result = await runCaptured(process.execPath, upstreamArgs, {
|
|
193
|
+
cwd,
|
|
194
|
+
input
|
|
195
|
+
});
|
|
196
|
+
process.stdout.write(result.stdout);
|
|
197
|
+
process.stderr.write(result.stderr);
|
|
198
|
+
return result.status;
|
|
199
|
+
}
|
|
200
|
+
async function runCli(args, options = {}) {
|
|
201
|
+
const cwd = options.cwd ?? process.cwd();
|
|
202
|
+
const invocation = parseOxfmtInvocation(args);
|
|
203
|
+
if (invocation.delegateOnly) return delegate(args, cwd, options.input);
|
|
204
|
+
const requestedStdin = invocation.stdinFilepath;
|
|
205
|
+
if (requestedStdin !== null) {
|
|
206
|
+
const input = options.input ?? readFileSync(0);
|
|
207
|
+
if (!requestedStdin.split("?")[0].endsWith(".tsrx")) return delegate(args, cwd, input);
|
|
208
|
+
const unknownStdinOption = unknownCanonicalOption(args);
|
|
209
|
+
if (unknownStdinOption !== null) {
|
|
210
|
+
process.stderr.write(`${unknownOptionMessage(unknownStdinOption)}\n`);
|
|
211
|
+
return 1;
|
|
212
|
+
}
|
|
213
|
+
const explicitConfig = argumentValue(args, /* @__PURE__ */ new Set(["-c", "--config"]));
|
|
214
|
+
const viteConfig = explicitConfig === null || isViteConfigPath(explicitConfig) ? await prepareVitePlusConfig("fmt", cwd, isViteConfigPath(explicitConfig) ? explicitConfig : null) : null;
|
|
215
|
+
try {
|
|
216
|
+
let nativeArgs = args.filter((argument) => argument !== "--no-error-on-unmatched-pattern");
|
|
217
|
+
if (viteConfig) {
|
|
218
|
+
nativeArgs = replaceConfigArgument(nativeArgs, viteConfig.path);
|
|
219
|
+
nativeArgs.push("--config-base", viteConfig.base);
|
|
220
|
+
}
|
|
221
|
+
const nativeCommand = resolveNativeCommand("format", nativeArgs);
|
|
222
|
+
const result = await runCaptured(nativeCommand.executable, nativeCommand.args, {
|
|
223
|
+
cwd,
|
|
224
|
+
input
|
|
225
|
+
});
|
|
226
|
+
process.stdout.write(result.stdout);
|
|
227
|
+
process.stderr.write(attributeNativeErrors(result.stderr));
|
|
228
|
+
return result.status;
|
|
229
|
+
} finally {
|
|
230
|
+
await viteConfig?.cleanup();
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
const positions = invocation.positionals;
|
|
234
|
+
const files = await discoverTsrxFiles(positions, cwd);
|
|
235
|
+
if (files.length > 0 || hasTsrxPositional(positions)) {
|
|
236
|
+
const unknown = unknownCanonicalOption(args);
|
|
237
|
+
if (unknown !== null) {
|
|
238
|
+
process.stderr.write(`${unknownOptionMessage(unknown)}\n`);
|
|
239
|
+
return 1;
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
const explicitConfig = argumentValue(args, /* @__PURE__ */ new Set(["-c", "--config"]));
|
|
243
|
+
const bridgeViteConfig = explicitConfig === null || isViteConfigPath(explicitConfig);
|
|
244
|
+
const viteConfig = files.length > 0 && bridgeViteConfig ? await prepareVitePlusConfig("fmt", cwd, isViteConfigPath(explicitConfig) ? explicitConfig : null) : null;
|
|
245
|
+
try {
|
|
246
|
+
const stripped = removeExplicitTsrx(args, VALUE_OPTIONS);
|
|
247
|
+
const shouldRunUpstream = !stripped.hadPositionals || stripped.remainingPositionals > 0;
|
|
248
|
+
const upstream = resolvePackageBinary("oxfmt-current", "oxfmt", import.meta.url);
|
|
249
|
+
const useMaterializedUpstreamConfig = Boolean(viteConfig && !viteConfig.requiresAuthoredBase);
|
|
250
|
+
const upstreamArgs = useMaterializedUpstreamConfig ? replaceConfigArgument(stripped.args, viteConfig.path) : stripped.args;
|
|
251
|
+
const nativeArgs = files.length > 0 ? nativeArguments(args, withCwdRelativePaths(files, cwd), viteConfig) : null;
|
|
252
|
+
const nativeCommand = nativeArgs ? resolveNativeCommand("format", nativeArgs) : null;
|
|
253
|
+
const [upstreamResult, nativeResult] = await Promise.all([shouldRunUpstream ? runCaptured(process.execPath, [upstream, ...upstreamArgs], {
|
|
254
|
+
cwd,
|
|
255
|
+
env: canonicalToolEnvironment(useMaterializedUpstreamConfig)
|
|
256
|
+
}) : Promise.resolve({
|
|
257
|
+
status: 0,
|
|
258
|
+
stdout: "",
|
|
259
|
+
stderr: "",
|
|
260
|
+
signal: null
|
|
261
|
+
}), nativeCommand ? runCaptured(nativeCommand.executable, nativeCommand.args, { cwd }) : Promise.resolve({
|
|
262
|
+
status: 0,
|
|
263
|
+
stdout: "",
|
|
264
|
+
stderr: "",
|
|
265
|
+
signal: null
|
|
266
|
+
})]);
|
|
267
|
+
const stdout = mergeFormatStdout(fileMode(args), upstreamResult, nativeResult);
|
|
268
|
+
process.stdout.write(stdout);
|
|
269
|
+
process.stderr.write(attributeNativeErrors(mergeFormatStderr(upstreamResult, nativeResult, stdout)));
|
|
270
|
+
return Math.max(upstreamResult.status, nativeResult.status);
|
|
271
|
+
} finally {
|
|
272
|
+
await viteConfig?.cleanup();
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
//#endregion
|
|
276
|
+
export { runCli };
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { importDeclaredPackageBinary } from "./package-binary.js";
|
|
2
|
+
import { statSync } from "node:fs";
|
|
3
|
+
import { resolve } from "pathe";
|
|
4
|
+
//#region src/format-invocation.ts
|
|
5
|
+
const VALUE_OPTIONS = /* @__PURE__ */ new Set([
|
|
6
|
+
"-c",
|
|
7
|
+
"--config",
|
|
8
|
+
"--migrate",
|
|
9
|
+
"--stdin-filepath",
|
|
10
|
+
"--ignore-path",
|
|
11
|
+
"--threads"
|
|
12
|
+
]);
|
|
13
|
+
const DELEGATE_ONLY = /* @__PURE__ */ new Set([
|
|
14
|
+
"--help",
|
|
15
|
+
"-h",
|
|
16
|
+
"--version",
|
|
17
|
+
"-V",
|
|
18
|
+
"--init",
|
|
19
|
+
"--migrate",
|
|
20
|
+
"--lsp"
|
|
21
|
+
]);
|
|
22
|
+
const FLAG_OPTIONS = /* @__PURE__ */ new Set([
|
|
23
|
+
"--write",
|
|
24
|
+
"--check",
|
|
25
|
+
"--list-different",
|
|
26
|
+
"--disable-nested-config",
|
|
27
|
+
"--with-node-modules",
|
|
28
|
+
"--no-error-on-unmatched-pattern"
|
|
29
|
+
]);
|
|
30
|
+
function parseOxfmtOption(argument) {
|
|
31
|
+
const equals = argument.indexOf("=");
|
|
32
|
+
if (equals !== -1) return {
|
|
33
|
+
name: argument.slice(0, equals),
|
|
34
|
+
value: argument.slice(equals + 1)
|
|
35
|
+
};
|
|
36
|
+
if (argument.startsWith("-c") && argument.length > 2) return {
|
|
37
|
+
name: "-c",
|
|
38
|
+
value: argument.slice(2)
|
|
39
|
+
};
|
|
40
|
+
return {
|
|
41
|
+
name: argument,
|
|
42
|
+
value: null
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
function parseOxfmtInvocation(args) {
|
|
46
|
+
const positionals = [];
|
|
47
|
+
let positionalOnly = false;
|
|
48
|
+
let delegateOnly = false;
|
|
49
|
+
let known = true;
|
|
50
|
+
let stdinFilepath = null;
|
|
51
|
+
for (let index = 0; index < args.length; index += 1) {
|
|
52
|
+
const argument = args[index];
|
|
53
|
+
if (positionalOnly) {
|
|
54
|
+
positionals.push(argument);
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
if (argument === "--") {
|
|
58
|
+
positionalOnly = true;
|
|
59
|
+
continue;
|
|
60
|
+
}
|
|
61
|
+
if (!argument.startsWith("-") || argument === "-") {
|
|
62
|
+
positionals.push(argument);
|
|
63
|
+
continue;
|
|
64
|
+
}
|
|
65
|
+
const { name, value: inlineValue } = parseOxfmtOption(argument);
|
|
66
|
+
if (DELEGATE_ONLY.has(name)) delegateOnly = true;
|
|
67
|
+
if (VALUE_OPTIONS.has(name)) {
|
|
68
|
+
const value = inlineValue ?? args[++index] ?? null;
|
|
69
|
+
if (name === "--stdin-filepath") stdinFilepath = value;
|
|
70
|
+
continue;
|
|
71
|
+
}
|
|
72
|
+
if (!DELEGATE_ONLY.has(name) && !FLAG_OPTIONS.has(name)) known = false;
|
|
73
|
+
}
|
|
74
|
+
return {
|
|
75
|
+
positionals,
|
|
76
|
+
delegateOnly,
|
|
77
|
+
known,
|
|
78
|
+
stdinFilepath
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
function canRunCanonicalOxfmt(args, cwd = process.cwd()) {
|
|
82
|
+
const invocation = parseOxfmtInvocation(args);
|
|
83
|
+
if (invocation.delegateOnly) return true;
|
|
84
|
+
if (!invocation.known) return false;
|
|
85
|
+
if (invocation.stdinFilepath !== null) return invocation.stdinFilepath.length > 0 && !invocation.stdinFilepath.split("?")[0].endsWith(".tsrx");
|
|
86
|
+
if (invocation.positionals.length === 0) return false;
|
|
87
|
+
return invocation.positionals.every((argument) => {
|
|
88
|
+
if (argument.split("?")[0].endsWith(".tsrx")) return false;
|
|
89
|
+
try {
|
|
90
|
+
return statSync(resolve(cwd, argument)).isFile();
|
|
91
|
+
} catch {
|
|
92
|
+
return false;
|
|
93
|
+
}
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
//#endregion
|
|
97
|
+
export { DELEGATE_ONLY, VALUE_OPTIONS, canRunCanonicalOxfmt, importDeclaredPackageBinary, parseOxfmtInvocation, parseOxfmtOption };
|
package/dist/format.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from 'oxfmt-current';
|
package/dist/format.js
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { runCaptured } from "./process.js";
|
|
2
|
+
import { resolveNativeCommand } from "./runtime.js";
|
|
3
|
+
import { mkdtemp, rm, writeFile } from "node:fs/promises";
|
|
4
|
+
import { tmpdir } from "node:os";
|
|
5
|
+
import { join } from "pathe";
|
|
6
|
+
import { defineConfig, format as format$1, jsTextToDoc as jsTextToDoc$1 } from "oxfmt-current";
|
|
7
|
+
//#region src/format.ts
|
|
8
|
+
function isTsrx(fileName) {
|
|
9
|
+
return fileName.split("?")[0].endsWith(".tsrx");
|
|
10
|
+
}
|
|
11
|
+
function serializeOptions(options) {
|
|
12
|
+
if (!options || Object.keys(options).length === 0) return null;
|
|
13
|
+
let json;
|
|
14
|
+
try {
|
|
15
|
+
json = JSON.stringify(options);
|
|
16
|
+
} catch (error) {
|
|
17
|
+
throw new TypeError(`TSRX formatter options must be JSON-serializable: ${error}`);
|
|
18
|
+
}
|
|
19
|
+
if (json === void 0) throw new TypeError("TSRX formatter options must be JSON-serializable");
|
|
20
|
+
return json;
|
|
21
|
+
}
|
|
22
|
+
async function format(fileName, sourceText, options) {
|
|
23
|
+
if (typeof fileName !== "string") throw new TypeError("`fileName` must be a string");
|
|
24
|
+
if (typeof sourceText !== "string") throw new TypeError("`sourceText` must be a string");
|
|
25
|
+
if (!isTsrx(fileName)) return format$1(fileName, sourceText, options);
|
|
26
|
+
const serialized = serializeOptions(options);
|
|
27
|
+
let directory = null;
|
|
28
|
+
const args = [`--stdin-filepath=${fileName}`];
|
|
29
|
+
try {
|
|
30
|
+
if (serialized !== null) {
|
|
31
|
+
directory = await mkdtemp(join(tmpdir(), "oxc-tsrx-format-api-"));
|
|
32
|
+
const config = join(directory, ".oxfmtrc.json");
|
|
33
|
+
await writeFile(config, serialized);
|
|
34
|
+
args.unshift(`--config=${config}`);
|
|
35
|
+
}
|
|
36
|
+
const native = resolveNativeCommand("format", args);
|
|
37
|
+
const result = await runCaptured(native.executable, native.args, { input: sourceText });
|
|
38
|
+
if (result.status !== 0) throw new Error(result.stderr.trim() || `native TSRX formatter exited ${result.status}`);
|
|
39
|
+
return {
|
|
40
|
+
code: result.stdout,
|
|
41
|
+
errors: []
|
|
42
|
+
};
|
|
43
|
+
} finally {
|
|
44
|
+
if (directory !== null) await rm(directory, {
|
|
45
|
+
recursive: true,
|
|
46
|
+
force: true
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
async function jsTextToDoc(sourceExt, sourceText, optionsJson, parentContext) {
|
|
51
|
+
if (sourceExt !== "tsrx" && sourceExt !== ".tsrx") return jsTextToDoc$1(sourceExt, sourceText, optionsJson, parentContext);
|
|
52
|
+
const options = optionsJson ? JSON.parse(optionsJson) : void 0;
|
|
53
|
+
return format(`snippet.${sourceExt.replace(/^\./, "")}`, sourceText, options);
|
|
54
|
+
}
|
|
55
|
+
//#endregion
|
|
56
|
+
export { defineConfig, format, jsTextToDoc };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export interface OxcTsrxToolchain {
|
|
2
|
+
readonly name: "@tsrx/oxc";
|
|
3
|
+
readonly language: "tsrx";
|
|
4
|
+
readonly extensions: readonly [".tsrx"];
|
|
5
|
+
readonly capabilities: readonly ["parser", "lint", "format", "languageServer"];
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export declare const toolchain: Readonly<OxcTsrxToolchain>;
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
//#region src/index.ts
|
|
2
|
+
const extensions = Object.freeze([".tsrx"]);
|
|
3
|
+
const capabilities = Object.freeze([
|
|
4
|
+
"parser",
|
|
5
|
+
"lint",
|
|
6
|
+
"format",
|
|
7
|
+
"languageServer"
|
|
8
|
+
]);
|
|
9
|
+
const toolchain = Object.freeze({
|
|
10
|
+
name: "@tsrx/oxc",
|
|
11
|
+
language: "tsrx",
|
|
12
|
+
extensions,
|
|
13
|
+
capabilities
|
|
14
|
+
});
|
|
15
|
+
//#endregion
|
|
16
|
+
export { toolchain };
|