fastscript 2.0.0 → 3.0.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/CHANGELOG.md +6 -0
- package/README.md +41 -3
- package/node_modules/@fastscript/core-private/src/fs-error-codes.mjs +2 -2
- package/node_modules/@fastscript/core-private/src/fs-normalize.mjs +33 -3
- package/node_modules/@fastscript/core-private/src/fs-parser.mjs +197 -57
- package/node_modules/@fastscript/core-private/src/typecheck.mjs +5 -3
- package/package.json +26 -5
- package/src/benchmark-discipline.mjs +39 -0
- package/src/cli.mjs +37 -2
- package/src/conversion-manifest.mjs +101 -0
- package/src/diagnostics.mjs +100 -0
- package/src/fs-error-codes.mjs +2 -2
- package/src/fs-normalize.mjs +33 -3
- package/src/generated/docs-search-index.mjs +545 -174
- package/src/migrate-rollback.mjs +144 -0
- package/src/migrate.mjs +1275 -47
- package/src/migration-wizard.mjs +37 -11
- package/src/module-loader.mjs +13 -1
- package/src/permissions-cli.mjs +112 -0
- package/src/profile.mjs +95 -0
- package/src/regression-guard.mjs +245 -0
- package/src/runtime-permissions.mjs +299 -0
- package/src/trace.mjs +95 -0
- package/src/validate.mjs +8 -0
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
2
|
+
import { resolve } from "node:path";
|
|
3
|
+
|
|
4
|
+
function assertField(condition, message) {
|
|
5
|
+
if (!condition) throw new Error(message);
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export async function runBenchmarkDiscipline({ suitePath = resolve("benchmarks", "suite-latest.json") } = {}) {
|
|
9
|
+
assertField(existsSync(suitePath), `missing benchmark suite: ${suitePath}`);
|
|
10
|
+
const suite = JSON.parse(readFileSync(suitePath, "utf8"));
|
|
11
|
+
|
|
12
|
+
assertField(suite.protocol && typeof suite.protocol === "object", "suite protocol missing");
|
|
13
|
+
assertField(Number.isFinite(suite.protocol.runs) && suite.protocol.runs >= 3, "protocol.runs must be >= 3");
|
|
14
|
+
assertField(Number.isFinite(suite.protocol.sampleIntervalMs) && suite.protocol.sampleIntervalMs > 0, "protocol.sampleIntervalMs invalid");
|
|
15
|
+
|
|
16
|
+
assertField(suite.environment && typeof suite.environment === "object", "suite environment missing");
|
|
17
|
+
for (const key of ["node", "platform", "arch", "cpuModel", "cpuCount", "totalMemoryMb"]) {
|
|
18
|
+
assertField(Boolean(suite.environment[key] || suite.environment[key] === 0), `suite environment missing ${key}`);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
assertField(Array.isArray(suite.corpora) && suite.corpora.length > 0, "suite corpora missing");
|
|
22
|
+
|
|
23
|
+
for (const corpus of suite.corpora) {
|
|
24
|
+
if (corpus.skipped) continue;
|
|
25
|
+
assertField(Boolean(corpus.id), "corpus id missing");
|
|
26
|
+
assertField(Boolean(corpus.root), `corpus root missing for ${corpus.id}`);
|
|
27
|
+
assertField(Number.isFinite(corpus?.timingsMs?.buildCold?.ms), `corpus buildCold invalid for ${corpus.id}`);
|
|
28
|
+
assertField(Number.isFinite(corpus?.timingsMs?.buildWarm?.p95Trimmed), `corpus buildWarm p95Trimmed invalid for ${corpus.id}`);
|
|
29
|
+
assertField(Number.isFinite(corpus?.timingsMs?.typecheck?.p95Trimmed), `corpus typecheck p95Trimmed invalid for ${corpus.id}`);
|
|
30
|
+
assertField(Number.isFinite(corpus?.bundles?.js) && Number.isFinite(corpus?.bundles?.css), `corpus bundle sizes invalid for ${corpus.id}`);
|
|
31
|
+
|
|
32
|
+
const hard = corpus.hardLimitCheck || {};
|
|
33
|
+
for (const key of ["parsePerFileUnder100ms", "typecheckPer100FilesUnder500ms", "warmBuildUnder2000ms", "coldBuildUnder5000ms", "firstLoadJsUnder5kb"]) {
|
|
34
|
+
assertField(typeof hard[key] === "boolean" || hard[key] === null, `corpus hardLimitCheck.${key} invalid for ${corpus.id}`);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
console.log("benchmark discipline pass");
|
|
39
|
+
}
|
package/src/cli.mjs
CHANGED
|
@@ -16,6 +16,14 @@ import { runTypeCheck } from "./typecheck.mjs";
|
|
|
16
16
|
import { runFormat } from "./fs-formatter.mjs";
|
|
17
17
|
import { runLint } from "./fs-linter.mjs";
|
|
18
18
|
import { runMigrationWizard } from "./migration-wizard.mjs";
|
|
19
|
+
import { runProfile } from "./profile.mjs";
|
|
20
|
+
import { runTrace } from "./trace.mjs";
|
|
21
|
+
import { runDiagnostics } from "./diagnostics.mjs";
|
|
22
|
+
import { runMigrateRollback } from "./migrate-rollback.mjs";
|
|
23
|
+
import { runManifest } from "./conversion-manifest.mjs";
|
|
24
|
+
import { runPermissions } from "./permissions-cli.mjs";
|
|
25
|
+
import { runBenchmarkDiscipline } from "./benchmark-discipline.mjs";
|
|
26
|
+
import { runRegressionGuard } from "./regression-guard.mjs";
|
|
19
27
|
|
|
20
28
|
const [, , command, ...args] = process.argv;
|
|
21
29
|
|
|
@@ -42,7 +50,16 @@ async function main() {
|
|
|
42
50
|
await runCheck();
|
|
43
51
|
break;
|
|
44
52
|
case "migrate":
|
|
45
|
-
await runMigrate(args
|
|
53
|
+
await runMigrate(args.length ? args : ["app"]);
|
|
54
|
+
break;
|
|
55
|
+
case "convert":
|
|
56
|
+
await runMigrate(args.length ? args : ["app"]);
|
|
57
|
+
break;
|
|
58
|
+
case "migrate:rollback":
|
|
59
|
+
await runMigrateRollback(args);
|
|
60
|
+
break;
|
|
61
|
+
case "manifest":
|
|
62
|
+
await runManifest(args);
|
|
46
63
|
break;
|
|
47
64
|
case "wizard:migrate":
|
|
48
65
|
await runMigrationWizard(args);
|
|
@@ -50,6 +67,12 @@ async function main() {
|
|
|
50
67
|
case "bench":
|
|
51
68
|
await runBench();
|
|
52
69
|
break;
|
|
70
|
+
case "bench:discipline":
|
|
71
|
+
await runBenchmarkDiscipline();
|
|
72
|
+
break;
|
|
73
|
+
case "regression":
|
|
74
|
+
await runRegressionGuard(args);
|
|
75
|
+
break;
|
|
53
76
|
case "export":
|
|
54
77
|
await runExport(args);
|
|
55
78
|
break;
|
|
@@ -62,6 +85,18 @@ async function main() {
|
|
|
62
85
|
case "typecheck":
|
|
63
86
|
await runTypeCheck(args);
|
|
64
87
|
break;
|
|
88
|
+
case "profile":
|
|
89
|
+
await runProfile(args);
|
|
90
|
+
break;
|
|
91
|
+
case "trace":
|
|
92
|
+
await runTrace(args);
|
|
93
|
+
break;
|
|
94
|
+
case "diagnostics":
|
|
95
|
+
await runDiagnostics(args);
|
|
96
|
+
break;
|
|
97
|
+
case "permissions":
|
|
98
|
+
await runPermissions(args);
|
|
99
|
+
break;
|
|
65
100
|
case "format":
|
|
66
101
|
await runFormat(args);
|
|
67
102
|
break;
|
|
@@ -85,7 +120,7 @@ async function main() {
|
|
|
85
120
|
break;
|
|
86
121
|
default:
|
|
87
122
|
console.log("FastScript CLI");
|
|
88
|
-
console.log("Commands: create, dev, start, build, ssg, check, migrate, wizard:migrate, bench, export, compat, validate, typecheck, format, lint, db:migrate, db:seed, db:rollback, deploy, worker");
|
|
123
|
+
console.log("Commands: create, dev, start, build, ssg, check, migrate, convert, migrate:rollback, manifest, wizard:migrate, bench, bench:discipline, regression, export, compat, validate, typecheck, profile, trace, diagnostics, permissions, format, lint, db:migrate, db:seed, db:rollback, deploy, worker");
|
|
89
124
|
}
|
|
90
125
|
}
|
|
91
126
|
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { dirname, relative, resolve } from "node:path";
|
|
3
|
+
|
|
4
|
+
const DEFAULT_MANIFEST = resolve(".fastscript", "conversion", "latest", "conversion-manifest.json");
|
|
5
|
+
|
|
6
|
+
function normalize(path) {
|
|
7
|
+
return String(path || "").replace(/\\/g, "/");
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
function parseArgs(args = []) {
|
|
11
|
+
const options = {
|
|
12
|
+
manifest: DEFAULT_MANIFEST,
|
|
13
|
+
json: false,
|
|
14
|
+
out: "",
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
for (let i = 0; i < args.length; i += 1) {
|
|
18
|
+
const arg = args[i];
|
|
19
|
+
if (arg === "--manifest") {
|
|
20
|
+
options.manifest = resolve(args[i + 1] || options.manifest);
|
|
21
|
+
i += 1;
|
|
22
|
+
continue;
|
|
23
|
+
}
|
|
24
|
+
if (arg === "--json") {
|
|
25
|
+
options.json = true;
|
|
26
|
+
continue;
|
|
27
|
+
}
|
|
28
|
+
if (arg === "--out") {
|
|
29
|
+
options.out = resolve(args[i + 1] || "");
|
|
30
|
+
i += 1;
|
|
31
|
+
continue;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
return options;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export function loadConversionManifest(manifestPath) {
|
|
39
|
+
const path = resolve(manifestPath || DEFAULT_MANIFEST);
|
|
40
|
+
if (!existsSync(path)) throw new Error(`manifest missing: ${path}`);
|
|
41
|
+
return { path, manifest: JSON.parse(readFileSync(path, "utf8")) };
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export function summarizeConversionManifest(manifest) {
|
|
45
|
+
const converted = Array.isArray(manifest.convertedFiles) ? manifest.convertedFiles.length : 0;
|
|
46
|
+
const importRewrites = Array.isArray(manifest.importRewrites)
|
|
47
|
+
? manifest.importRewrites.reduce((sum, item) => sum + Number(item.count || 0), 0)
|
|
48
|
+
: 0;
|
|
49
|
+
const blocked = Array.isArray(manifest.blockedFiles) ? manifest.blockedFiles.length : 0;
|
|
50
|
+
const protectedCount = Array.isArray(manifest.protectedFiles) ? manifest.protectedFiles.length : 0;
|
|
51
|
+
const untouched = Array.isArray(manifest.untouchedFiles) ? manifest.untouchedFiles.length : 0;
|
|
52
|
+
|
|
53
|
+
return {
|
|
54
|
+
spec: manifest.spec || "unknown",
|
|
55
|
+
mode: manifest.mode || "unknown",
|
|
56
|
+
runId: manifest.runId || "unknown",
|
|
57
|
+
generatedAt: manifest.generatedAt || "unknown",
|
|
58
|
+
target: manifest.target || ".",
|
|
59
|
+
dryRun: Boolean(manifest.dryRun),
|
|
60
|
+
convertedFiles: converted,
|
|
61
|
+
importRewrites,
|
|
62
|
+
blockedFiles: blocked,
|
|
63
|
+
protectedFiles: protectedCount,
|
|
64
|
+
untouchedFiles: untouched,
|
|
65
|
+
diffRenameOperations: Number(manifest?.diffPreview?.renameOperationCount || 0),
|
|
66
|
+
diffRewriteOperations: Number(manifest?.diffPreview?.rewriteOperationCount || 0),
|
|
67
|
+
diffDeleteOperations: Number(manifest?.diffPreview?.deleteOperationCount || 0),
|
|
68
|
+
validationFailedChecks: manifest?.validation?.failedChecks || [],
|
|
69
|
+
fidelityStatus: manifest?.fidelity?.status || "unknown",
|
|
70
|
+
fidelityFailedChecks: manifest?.fidelity?.failedChecks || [],
|
|
71
|
+
fidelityFailedProbes: manifest?.fidelity?.failedProbes || [],
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export async function runManifest(args = []) {
|
|
76
|
+
const options = parseArgs(args);
|
|
77
|
+
const { path, manifest } = loadConversionManifest(options.manifest);
|
|
78
|
+
const summary = summarizeConversionManifest(manifest);
|
|
79
|
+
|
|
80
|
+
if (options.out) {
|
|
81
|
+
mkdirSync(dirname(options.out), { recursive: true });
|
|
82
|
+
writeFileSync(options.out, `${JSON.stringify(summary, null, 2)}\n`, "utf8");
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
if (options.json) {
|
|
86
|
+
console.log(JSON.stringify(summary, null, 2));
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
console.log(`manifest: ${normalize(relative(resolve("."), path))}`);
|
|
91
|
+
console.log(`run: ${summary.runId} (${summary.mode})`);
|
|
92
|
+
console.log(`target: ${summary.target}`);
|
|
93
|
+
console.log(`converted: ${summary.convertedFiles}`);
|
|
94
|
+
console.log(`import rewrites: ${summary.importRewrites}`);
|
|
95
|
+
console.log(`blocked: ${summary.blockedFiles}`);
|
|
96
|
+
console.log(`protected: ${summary.protectedFiles}`);
|
|
97
|
+
console.log(`untouched: ${summary.untouchedFiles}`);
|
|
98
|
+
console.log(`diff preview -> rename:${summary.diffRenameOperations} rewrite:${summary.diffRewriteOperations} delete:${summary.diffDeleteOperations}`);
|
|
99
|
+
console.log(`validation failed checks: ${summary.validationFailedChecks.length}`);
|
|
100
|
+
console.log(`fidelity: ${summary.fidelityStatus}`);
|
|
101
|
+
}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { mkdirSync, readdirSync, readFileSync, statSync, writeFileSync, existsSync } from "node:fs";
|
|
2
|
+
import { dirname, join, relative, resolve } from "node:path";
|
|
3
|
+
import { analyzeFastScript } from "./fs-diagnostics.mjs";
|
|
4
|
+
|
|
5
|
+
function walk(dir) {
|
|
6
|
+
const out = [];
|
|
7
|
+
if (!existsSync(dir)) return out;
|
|
8
|
+
for (const entry of readdirSync(dir, { withFileTypes: true })) {
|
|
9
|
+
const full = join(dir, entry.name);
|
|
10
|
+
if (entry.isDirectory()) {
|
|
11
|
+
if (["node_modules", ".git", "dist", ".fastscript"].includes(entry.name)) continue;
|
|
12
|
+
out.push(...walk(full));
|
|
13
|
+
} else if (entry.isFile()) {
|
|
14
|
+
out.push(full);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
return out;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function parseArgs(args = []) {
|
|
21
|
+
const options = {
|
|
22
|
+
path: resolve("app"),
|
|
23
|
+
mode: "report",
|
|
24
|
+
out: resolve(".fastscript", "diagnostics-report.json"),
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
for (let i = 0; i < args.length; i += 1) {
|
|
28
|
+
const arg = args[i];
|
|
29
|
+
if (arg === "--path") {
|
|
30
|
+
options.path = resolve(args[i + 1] || options.path);
|
|
31
|
+
i += 1;
|
|
32
|
+
continue;
|
|
33
|
+
}
|
|
34
|
+
if (arg === "--out") {
|
|
35
|
+
options.out = resolve(args[i + 1] || options.out);
|
|
36
|
+
i += 1;
|
|
37
|
+
continue;
|
|
38
|
+
}
|
|
39
|
+
if (arg === "--mode") {
|
|
40
|
+
const next = (args[i + 1] || "report").toLowerCase();
|
|
41
|
+
options.mode = next === "fail" ? "fail" : "report";
|
|
42
|
+
i += 1;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return options;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export async function runDiagnostics(args = []) {
|
|
50
|
+
const options = parseArgs(args);
|
|
51
|
+
const files = walk(options.path).filter((file) => file.endsWith(".fs"));
|
|
52
|
+
const diagnostics = [];
|
|
53
|
+
|
|
54
|
+
for (const file of files) {
|
|
55
|
+
const source = readFileSync(file, "utf8");
|
|
56
|
+
const issues = analyzeFastScript(source, { file, mode: "lenient" });
|
|
57
|
+
for (const issue of issues) {
|
|
58
|
+
diagnostics.push({
|
|
59
|
+
file: normalizePath(file),
|
|
60
|
+
code: issue.code,
|
|
61
|
+
severity: issue.severity,
|
|
62
|
+
message: issue.message,
|
|
63
|
+
line: issue.line,
|
|
64
|
+
column: issue.column,
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const summary = diagnostics.reduce(
|
|
70
|
+
(acc, item) => {
|
|
71
|
+
if (item.severity === "warning") acc.warnings += 1;
|
|
72
|
+
else acc.errors += 1;
|
|
73
|
+
acc.byCode[item.code] = (acc.byCode[item.code] || 0) + 1;
|
|
74
|
+
return acc;
|
|
75
|
+
},
|
|
76
|
+
{ errors: 0, warnings: 0, byCode: {} },
|
|
77
|
+
);
|
|
78
|
+
|
|
79
|
+
const report = {
|
|
80
|
+
generatedAt: new Date().toISOString(),
|
|
81
|
+
root: normalizePath(options.path),
|
|
82
|
+
filesScanned: files.length,
|
|
83
|
+
summary,
|
|
84
|
+
diagnostics,
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
mkdirSync(dirname(options.out), { recursive: true });
|
|
88
|
+
writeFileSync(options.out, `${JSON.stringify(report, null, 2)}\n`, "utf8");
|
|
89
|
+
|
|
90
|
+
if (options.mode === "fail" && summary.errors > 0) {
|
|
91
|
+
throw new Error(`diagnostics failed: ${summary.errors} blocking issue(s)`);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
console.log(`diagnostics complete: files=${files.length}, errors=${summary.errors}, warnings=${summary.warnings}`);
|
|
95
|
+
console.log(`diagnostics report: ${normalizePath(relative(resolve("."), options.out))}`);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
function normalizePath(path) {
|
|
99
|
+
return String(path || "").replace(/\\/g, "/");
|
|
100
|
+
}
|
package/src/fs-error-codes.mjs
CHANGED
|
@@ -16,8 +16,8 @@ export const FS_ERROR_CODES = Object.freeze({
|
|
|
16
16
|
},
|
|
17
17
|
FS1004: {
|
|
18
18
|
severity: "error",
|
|
19
|
-
message: "
|
|
20
|
-
hint: "
|
|
19
|
+
message: "Legacy compatibility frontend conflict.",
|
|
20
|
+
hint: "Ordinary TS type-only syntax in `.fs` should parse. If this appears, treat it as a FastScript compatibility bug.",
|
|
21
21
|
},
|
|
22
22
|
FS1005: {
|
|
23
23
|
severity: "error",
|
package/src/fs-normalize.mjs
CHANGED
|
@@ -60,28 +60,58 @@ export function stripTypeScriptHints(source) {
|
|
|
60
60
|
continue;
|
|
61
61
|
}
|
|
62
62
|
|
|
63
|
+
if (/^\s*declare\s+(global|module|namespace)\b/.test(next)) {
|
|
64
|
+
out.push(`// ${next.trim()} (removed by fastscript migrate)`);
|
|
65
|
+
if (next.includes("{")) {
|
|
66
|
+
skippingBlock = true;
|
|
67
|
+
const opens = (next.match(/{/g) || []).length;
|
|
68
|
+
const closes = (next.match(/}/g) || []).length;
|
|
69
|
+
blockDepth = Math.max(1, opens - closes);
|
|
70
|
+
}
|
|
71
|
+
continue;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
if (/^\s*declare\s+/.test(next)) {
|
|
75
|
+
out.push(`// ${next.trim()} (removed by fastscript migrate)`);
|
|
76
|
+
continue;
|
|
77
|
+
}
|
|
78
|
+
|
|
63
79
|
next = next.replace(/\bimport\s+type\b/g, "import");
|
|
64
80
|
next = next.replace(/\bexport\s+type\b/g, "export");
|
|
81
|
+
next = next.replace(/\btype\s+([A-Za-z_$][\w$]*)\s+as\s+/g, "$1 as ");
|
|
82
|
+
next = next.replace(/\b(?:public|private|protected|readonly|declare|override|abstract)\s+/g, "");
|
|
83
|
+
next = next.replace(/\s+implements\s+[A-Za-z_$][\w$<>\[\]\|&, ?.]+/g, "");
|
|
84
|
+
next = next.replace(/([A-Za-z_$][\w$]*)!([?:;=,\)])/g, "$1$2");
|
|
65
85
|
|
|
66
86
|
next = next.replace(
|
|
67
87
|
/^(\s*)(const|let|var)\s+([A-Za-z_$][\w$]*)\s*:\s*([^=;]+)([=;].*)$/,
|
|
68
88
|
"$1$2 $3 $5",
|
|
69
89
|
);
|
|
90
|
+
next = next.replace(
|
|
91
|
+
/^(\s*)(const|let|var)\s+([A-Za-z_$][\w$]*)\s*<[^>]+>\s*=\s*/,
|
|
92
|
+
"$1$2 $3 = ",
|
|
93
|
+
);
|
|
70
94
|
|
|
71
|
-
if (/\bfunction\b/.test(next) || /\)\s*=>/.test(next)) {
|
|
95
|
+
if (/\bfunction\b/.test(next) || /\bfn\b/.test(next) || /\)\s*=>/.test(next)) {
|
|
72
96
|
next = next.replace(/\(([^)]*)\)/, (_, params) => {
|
|
73
97
|
const cleaned = params.replace(
|
|
74
|
-
/([A-Za-z_$][\w$]*)
|
|
98
|
+
/([A-Za-z_$][\w$]*)(\?)?\s*:\s*([A-Za-z_$][\w$<>\[\]\|&, ?.:{}=]*)/g,
|
|
75
99
|
"$1",
|
|
76
100
|
);
|
|
77
101
|
return `(${cleaned})`;
|
|
78
102
|
});
|
|
79
|
-
next = next.replace(/\)\s*:\s*([A-Za-z_$][\w$<>\[\]\|&,
|
|
103
|
+
next = next.replace(/\)\s*:\s*([A-Za-z_$][\w$<>\[\]\|&, ?.:{}=]*)\s*\{/g, ") {");
|
|
104
|
+
next = next.replace(/\)\s*:\s*([A-Za-z_$][\w$<>\[\]\|&, ?.:{}=]*)\s*=>/g, ") =>");
|
|
80
105
|
next = next.replace(/\bfunction\s+([A-Za-z_$][\w$]*)\s*<[^>]+>\s*\(/g, "function $1(");
|
|
106
|
+
next = next.replace(/\bfn\s+([A-Za-z_$][\w$]*)\s*<[^>]+>\s*\(/g, "fn $1(");
|
|
107
|
+
next = next.replace(/=\s*async\s*<[^>]+>\s*\(/g, "= async (");
|
|
108
|
+
next = next.replace(/=\s*<[^>]+>\s*\(/g, "= (");
|
|
81
109
|
}
|
|
82
110
|
|
|
83
111
|
next = next.replace(/^\s*<([A-Za-z_$][\w$,\s]*)>\s*\(/, "(");
|
|
84
112
|
next = next.replace(/\)\s*=>\s*<[A-Za-z_$][\w$<>\[\]\|&, ?.]*>/g, ") =>");
|
|
113
|
+
next = next.replace(/\s+as\s+const\b/g, "");
|
|
114
|
+
next = next.replace(/\s+as\s+[A-Za-z_$][\w$<>\[\]\|&, ?.:{}=]*/g, "");
|
|
85
115
|
next = next.replace(/\sas\s+const\b/g, "");
|
|
86
116
|
next = next.replace(/\s+satisfies\s+[A-Za-z_$][\w$<>\[\]\|&, ?.]*/g, "");
|
|
87
117
|
out.push(next);
|