fastscript 3.0.0 → 3.0.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.
- package/CHANGELOG.md +6 -0
- package/README.md +667 -636
- package/node_modules/@fastscript/core-private/src/fs-normalize.mjs +125 -121
- package/node_modules/@fastscript/core-private/src/typecheck.mjs +1466 -1464
- package/package.json +18 -3
- package/src/compatibility-governance.mjs +257 -0
- package/src/fs-normalize.mjs +6 -4
- package/src/generated/compatibility-registry-report.mjs +815 -0
- package/src/generated/docs-search-index.mjs +710 -219
- package/src/validate.mjs +2 -0
package/package.json
CHANGED
|
@@ -1,7 +1,20 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "fastscript",
|
|
3
|
-
"version": "3.0.
|
|
4
|
-
"description": "FastScript v3 universal JS/TS runtime with first-class .fs source.",
|
|
3
|
+
"version": "3.0.1",
|
|
4
|
+
"description": "FastScript v3 universal JS/TS runtime with governed compatibility proof and first-class .fs source.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"fastscript",
|
|
7
|
+
"javascript",
|
|
8
|
+
"typescript",
|
|
9
|
+
"tsx",
|
|
10
|
+
"jsx",
|
|
11
|
+
"full-stack",
|
|
12
|
+
"runtime",
|
|
13
|
+
"framework",
|
|
14
|
+
"compatibility",
|
|
15
|
+
"interop",
|
|
16
|
+
"npm"
|
|
17
|
+
],
|
|
5
18
|
"license": "SEE LICENSE IN LICENSE",
|
|
6
19
|
"type": "module",
|
|
7
20
|
"publishConfig": {
|
|
@@ -79,6 +92,7 @@
|
|
|
79
92
|
"test:benchmark-discipline": "node ./scripts/test-benchmark-discipline.mjs",
|
|
80
93
|
"test:regression-guard": "node ./scripts/test-regression-guard.mjs",
|
|
81
94
|
"test:ecosystem-compatibility-contract": "node ./scripts/test-ecosystem-compatibility-contract.mjs",
|
|
95
|
+
"test:compatibility-matrix": "node ./scripts/test-compatibility-matrix.mjs",
|
|
82
96
|
"test:release-discipline": "node ./scripts/test-release-discipline.mjs",
|
|
83
97
|
"test:validation": "node ./scripts/test-validation.mjs",
|
|
84
98
|
"test:webhook-storage": "node ./scripts/test-webhook-storage.mjs",
|
|
@@ -119,6 +133,7 @@
|
|
|
119
133
|
"sbom:generate": "node ./scripts/generate-sbom.mjs",
|
|
120
134
|
"proof:publish": "node ./scripts/publish-proof-pack.mjs",
|
|
121
135
|
"docs:index": "node ./scripts/build-docs-index.mjs",
|
|
136
|
+
"compatibility:generate": "node ./scripts/generate-compatibility-matrix.mjs",
|
|
122
137
|
"docs:api-ref": "node ./scripts/generate-api-reference.mjs",
|
|
123
138
|
"plugins:marketplace-sync": "node ./scripts/plugin-marketplace-sync.mjs",
|
|
124
139
|
"security:rotate-secrets": "node ./scripts/secret-rotation.mjs",
|
|
@@ -129,7 +144,7 @@
|
|
|
129
144
|
"kpi:track": "node ./scripts/kpi-track.mjs",
|
|
130
145
|
"deploy:zero-downtime": "node ./scripts/zero-downtime-deploy.mjs",
|
|
131
146
|
"merge:gate": "node ./scripts/release-merge-gate.mjs",
|
|
132
|
-
"test:core": "npm run test:middleware && npm run test:auth && npm run test:db && npm run test:db-cli && npm run test:validation && npm run test:webhook-storage && npm run test:jobs && npm run test:plugins && npm run test:fs-diag && npm run test:metrics && npm run test:roundtrip && npm run test:compatibility-first-runtime && npm run test:authored-ts-in-fs && npm run test:js-ts-syntax-proof && npm run test:fs-parity-corpus && npm run test:conversion-rollback-manifest && npm run test:toolchain-observability && npm run test:runtime-permissions && npm run test:benchmark-discipline && npm run test:regression-guard && npm run test:ecosystem-compatibility-contract && npm run test:release-discipline && npm run test:sourcemap-fidelity && npm run test:cache-parity && npm run test:typecheck && npm run test:typecheck-depth && npm run test:format-lint && npm run test:style-rules && npm run test:style-primitives && npm run test:routes && npm run test:runtime-contract && npm run test:determinism && npm run test:parser-fuzz && npm run test:security-baseline && npm run test:deploy-adapters && npm run test:interop-matrix && npm run test:vscode-language && npm run test:runtime-context-rules && npm run test:runtime-scope-diagnostics && npm run test:v2:ambient-runtime && npm run test:v2:stdlib-methods && npm run test:v2:stdlib-matrix && npm run test:v2:dom-globals && npm run test:v2:dom-patterns && npm run test:v2:inference-corpus && npm run test:v2:inference-patterns && npm run test:v2:zero-js-app && npm run test:v2:zero-js-corpora && npm run test:conformance",
|
|
147
|
+
"test:core": "npm run test:middleware && npm run test:auth && npm run test:db && npm run test:db-cli && npm run test:validation && npm run test:webhook-storage && npm run test:jobs && npm run test:plugins && npm run test:fs-diag && npm run test:metrics && npm run test:roundtrip && npm run test:compatibility-first-runtime && npm run test:authored-ts-in-fs && npm run test:js-ts-syntax-proof && npm run test:fs-parity-corpus && npm run test:conversion-rollback-manifest && npm run test:toolchain-observability && npm run test:runtime-permissions && npm run test:benchmark-discipline && npm run test:regression-guard && npm run test:ecosystem-compatibility-contract && npm run test:compatibility-matrix && npm run test:release-discipline && npm run test:sourcemap-fidelity && npm run test:cache-parity && npm run test:typecheck && npm run test:typecheck-depth && npm run test:format-lint && npm run test:style-rules && npm run test:style-primitives && npm run test:routes && npm run test:runtime-contract && npm run test:determinism && npm run test:parser-fuzz && npm run test:security-baseline && npm run test:deploy-adapters && npm run test:interop-matrix && npm run test:vscode-language && npm run test:runtime-context-rules && npm run test:runtime-scope-diagnostics && npm run test:v2:ambient-runtime && npm run test:v2:stdlib-methods && npm run test:v2:stdlib-matrix && npm run test:v2:dom-globals && npm run test:v2:dom-patterns && npm run test:v2:inference-corpus && npm run test:v2:inference-patterns && npm run test:v2:zero-js-app && npm run test:v2:zero-js-corpora && npm run test:conformance",
|
|
133
148
|
"qa:gate": "npm run repo:lock && npm run format:check && npm run lint:fs && npm run typecheck && npm run validate && npm run test:core && npm run smoke:dev && npm run smoke:start",
|
|
134
149
|
"qa:all": "npm run repo:lock && npm run format:check && npm run lint:fs && npm run typecheck && npm run docs:index && npm run docs:api-ref && npm run validate && npm run test:core && npm run smoke:dev && npm run smoke:start && npm run bench:report && npm run benchmark:suite && npm run interop:report && npm run sbom:generate && npm run proof:publish && npm run backup:create && npm run backup:verify",
|
|
135
150
|
"release:patch": "node ./scripts/release.mjs patch",
|
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { resolve } from "node:path";
|
|
3
|
+
|
|
4
|
+
const REGISTRY_PATH = resolve("spec", "compatibility-registry.json");
|
|
5
|
+
const SUPPORT_MATRIX_PATH = resolve("docs", "SUPPORT_MATRIX.md");
|
|
6
|
+
const REPORT_PATH = resolve(".fastscript", "proofs", "compatibility-registry-report.json");
|
|
7
|
+
const GENERATED_DIR = resolve("src", "generated");
|
|
8
|
+
const GENERATED_MODULE_PATH = resolve(GENERATED_DIR, "compatibility-registry-report.mjs");
|
|
9
|
+
const VALID_STATUSES = new Set(["proven", "supported", "partial", "planned", "blocked"]);
|
|
10
|
+
const CATEGORY_ORDER = [
|
|
11
|
+
"ecmascript",
|
|
12
|
+
"typescript",
|
|
13
|
+
"jsx-tsx",
|
|
14
|
+
"fastscript-sugar",
|
|
15
|
+
"modules-interop",
|
|
16
|
+
"runtime-targets",
|
|
17
|
+
"framework-patterns",
|
|
18
|
+
"tooling",
|
|
19
|
+
"deployment-adapters",
|
|
20
|
+
];
|
|
21
|
+
const CATEGORY_LABELS = {
|
|
22
|
+
"ecmascript": "ECMAScript Syntax",
|
|
23
|
+
"typescript": "TypeScript Syntax Erasure",
|
|
24
|
+
"jsx-tsx": "JSX / TSX",
|
|
25
|
+
"fastscript-sugar": "FastScript Sugar",
|
|
26
|
+
"modules-interop": "Modules And Interop",
|
|
27
|
+
"runtime-targets": "Runtime Targets",
|
|
28
|
+
"framework-patterns": "Framework Patterns",
|
|
29
|
+
"tooling": "Tooling",
|
|
30
|
+
"deployment-adapters": "Deployment Adapters",
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
function readJson(path, fallback = null) {
|
|
34
|
+
if (!existsSync(path)) return fallback;
|
|
35
|
+
return JSON.parse(readFileSync(path, "utf8"));
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function stableLineFromVersion(version) {
|
|
39
|
+
const [major = "0", minor = "0"] = String(version || "0.0.0").split(".");
|
|
40
|
+
return `${major}.${minor}.x`;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function formatProofId(id) {
|
|
44
|
+
return `\`${String(id || "").replace(/^artifact:/, "").replace(/^script:/, "script:")}\``;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export function loadCompatibilityRegistry(path = REGISTRY_PATH) {
|
|
48
|
+
const registry = readJson(path, {});
|
|
49
|
+
return {
|
|
50
|
+
governanceTrack: String(registry.governanceTrack || "4.0"),
|
|
51
|
+
contract: String(registry.contract || ""),
|
|
52
|
+
entries: Array.isArray(registry.entries) ? registry.entries : [],
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export function loadCompatibilityArtifacts() {
|
|
57
|
+
return {
|
|
58
|
+
jsTsProof: readJson(resolve(".fastscript", "proofs", "js-ts-syntax-proof.json"), { status: "missing", cases: [] }),
|
|
59
|
+
fsParityProof: readJson(resolve(".fastscript", "proofs", "fs-parity-matrix.json"), { status: "missing", results: [] }),
|
|
60
|
+
interop: readJson(resolve("benchmarks", "interop-latest.json"), { summary: { total: 0, pass: 0, fail: 0 }, cases: [] }),
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export function collectProofMap(pkg, artifacts = loadCompatibilityArtifacts()) {
|
|
65
|
+
const map = new Map();
|
|
66
|
+
const artifactIds = [];
|
|
67
|
+
for (const scriptName of Object.keys(pkg.scripts || {})) {
|
|
68
|
+
map.set(`script:${scriptName}`, { id: `script:${scriptName}`, status: "configured", kind: "script" });
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
for (const testCase of artifacts.jsTsProof.cases || []) {
|
|
72
|
+
const id = `artifact:js-ts-syntax-proof:${testCase.id}`;
|
|
73
|
+
map.set(id, { id, status: testCase.status, kind: "artifact", artifact: "js-ts-syntax-proof", label: testCase.id });
|
|
74
|
+
if (testCase.status === "pass") artifactIds.push(id);
|
|
75
|
+
}
|
|
76
|
+
for (const result of artifacts.fsParityProof.results || []) {
|
|
77
|
+
const id = `artifact:fs-parity:${result.id}`;
|
|
78
|
+
map.set(id, { id, status: result.status, kind: "artifact", artifact: "fs-parity", label: result.id });
|
|
79
|
+
if (result.status === "pass") artifactIds.push(id);
|
|
80
|
+
}
|
|
81
|
+
for (const item of artifacts.interop.cases || []) {
|
|
82
|
+
const id = `artifact:interop:${item.id}`;
|
|
83
|
+
map.set(id, { id, status: item.status, kind: "artifact", artifact: "interop", label: item.id });
|
|
84
|
+
if (item.status === "pass") artifactIds.push(id);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
return { map, artifactIds };
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
function summarizeByStatus(entries) {
|
|
91
|
+
const out = {};
|
|
92
|
+
for (const entry of entries) out[entry.status] = (out[entry.status] || 0) + 1;
|
|
93
|
+
return out;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function summarizeByCategory(entries) {
|
|
97
|
+
const out = {};
|
|
98
|
+
for (const entry of entries) out[entry.category] = (out[entry.category] || 0) + 1;
|
|
99
|
+
return out;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
function normalizeReportForCompare(report) {
|
|
103
|
+
const clone = JSON.parse(JSON.stringify(report || {}));
|
|
104
|
+
delete clone.generatedAt;
|
|
105
|
+
return clone;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
function normalizeSupportMatrixForCompare(markdown) {
|
|
109
|
+
return String(markdown || "").replace(/^- Generated: .*\r?\n/m, "- Generated: <normalized>\n");
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
export function buildCompatibilityReport({ registry, pkg, artifacts }) {
|
|
113
|
+
const { map: proofMap } = collectProofMap(pkg, artifacts);
|
|
114
|
+
const resolvedEntries = registry.entries.map((entry) => ({
|
|
115
|
+
...entry,
|
|
116
|
+
proofDetails: (entry.proofIds || []).map((proofId) => proofMap.get(proofId) || { id: proofId, status: "missing", kind: "unknown" }),
|
|
117
|
+
}));
|
|
118
|
+
return {
|
|
119
|
+
generatedAt: new Date().toISOString(),
|
|
120
|
+
governanceTrack: registry.governanceTrack,
|
|
121
|
+
stableLine: stableLineFromVersion(pkg.version),
|
|
122
|
+
packageVersion: pkg.version,
|
|
123
|
+
contract: registry.contract,
|
|
124
|
+
summary: {
|
|
125
|
+
entries: resolvedEntries.length,
|
|
126
|
+
byStatus: summarizeByStatus(resolvedEntries),
|
|
127
|
+
byCategory: summarizeByCategory(resolvedEntries),
|
|
128
|
+
provenEntries: resolvedEntries.filter((entry) => entry.status === "proven").length,
|
|
129
|
+
},
|
|
130
|
+
artifacts: {
|
|
131
|
+
jsTsSyntaxCases: (artifacts.jsTsProof.cases || []).length,
|
|
132
|
+
fsParityCases: (artifacts.fsParityProof.results || []).length,
|
|
133
|
+
interopCases: (artifacts.interop.cases || []).length,
|
|
134
|
+
},
|
|
135
|
+
entries: resolvedEntries,
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
export function generateSupportMatrixMarkdown(report) {
|
|
140
|
+
const lines = [
|
|
141
|
+
"# FastScript Compatibility Matrix",
|
|
142
|
+
"",
|
|
143
|
+
`- Generated: ${report.generatedAt}`,
|
|
144
|
+
`- Current stable line: \`${report.stableLine}\``,
|
|
145
|
+
`- Governance track: FastScript \`${report.governanceTrack}\` compatibility system`,
|
|
146
|
+
`- Product contract: ${report.contract}`,
|
|
147
|
+
`- Proven means: linked automated coverage and CI-enforced release discipline`,
|
|
148
|
+
"",
|
|
149
|
+
"## Status Legend",
|
|
150
|
+
"- `proven`: linked automated coverage exists and release gates fail on regression",
|
|
151
|
+
"- `supported`: intended support surface with some proof or operational confidence, but not yet fully governed as `proven`",
|
|
152
|
+
"- `partial`: some known working coverage exists, but not enough to claim full contract safety",
|
|
153
|
+
"- `planned`: visible compatibility lane targeted for future proof coverage",
|
|
154
|
+
"- `blocked`: explicitly unsupported or blocked pending design/runtime work",
|
|
155
|
+
"",
|
|
156
|
+
"## Summary",
|
|
157
|
+
`- Registry entries: ${report.summary.entries}`,
|
|
158
|
+
`- Proven entries: ${report.summary.provenEntries}`,
|
|
159
|
+
`- JS/TS syntax proof cases: ${report.artifacts.jsTsSyntaxCases}`,
|
|
160
|
+
`- .fs parity cases: ${report.artifacts.fsParityCases}`,
|
|
161
|
+
`- Interop cases: ${report.artifacts.interopCases}`,
|
|
162
|
+
"",
|
|
163
|
+
];
|
|
164
|
+
|
|
165
|
+
for (const category of CATEGORY_ORDER) {
|
|
166
|
+
const items = report.entries.filter((entry) => entry.category === category);
|
|
167
|
+
if (!items.length) continue;
|
|
168
|
+
lines.push(`## ${CATEGORY_LABELS[category] || category}`);
|
|
169
|
+
lines.push("| Feature | Status | Proof | Notes |");
|
|
170
|
+
lines.push("|---|---|---|---|");
|
|
171
|
+
for (const entry of items) {
|
|
172
|
+
const proof = entry.proofIds && entry.proofIds.length
|
|
173
|
+
? entry.proofIds.map((proofId) => formatProofId(proofId)).join(", ")
|
|
174
|
+
: "-";
|
|
175
|
+
const note = entry.docsNote || entry.contractNote || "";
|
|
176
|
+
lines.push(`| ${entry.feature} | ${entry.status} | ${proof} | ${note.replace(/\|/g, "\\|")} |`);
|
|
177
|
+
}
|
|
178
|
+
lines.push("");
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
lines.push("## Compatibility Request Lane");
|
|
182
|
+
lines.push("If valid JS/TS, a framework pattern, or a real migration case fails in `.fs`, treat it as a FastScript compatibility bug and report it through the compatibility intake workflow.");
|
|
183
|
+
lines.push("");
|
|
184
|
+
return `${lines.join("\n").trim()}\n`;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
export function validateCompatibilityGovernance({ registry, pkg, artifacts, supportMatrix = null, reportJson = null }) {
|
|
188
|
+
const errors = [];
|
|
189
|
+
const { map: proofMap, artifactIds } = collectProofMap(pkg, artifacts);
|
|
190
|
+
const referencedArtifactIds = new Set();
|
|
191
|
+
|
|
192
|
+
for (const entry of registry.entries) {
|
|
193
|
+
if (!entry.id || !entry.category || !entry.feature) errors.push(`registry entry missing id/category/feature: ${JSON.stringify(entry)}`);
|
|
194
|
+
if (!VALID_STATUSES.has(entry.status)) errors.push(`registry entry has invalid status: ${entry.id} -> ${entry.status}`);
|
|
195
|
+
if (!Array.isArray(entry.proofIds)) errors.push(`registry entry proofIds must be an array: ${entry.id}`);
|
|
196
|
+
for (const proofId of entry.proofIds || []) {
|
|
197
|
+
const resolved = proofMap.get(proofId);
|
|
198
|
+
if (!resolved) {
|
|
199
|
+
errors.push(`registry proof id does not resolve: ${entry.id} -> ${proofId}`);
|
|
200
|
+
continue;
|
|
201
|
+
}
|
|
202
|
+
if (proofId.startsWith("artifact:")) referencedArtifactIds.add(proofId);
|
|
203
|
+
if (entry.status === "proven" && resolved.status !== "pass" && resolved.status !== "configured") {
|
|
204
|
+
errors.push(`proven registry entry links to non-passing proof: ${entry.id} -> ${proofId} (${resolved.status})`);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
if (entry.status === "proven" && (!entry.proofIds || entry.proofIds.length === 0)) {
|
|
208
|
+
errors.push(`proven registry entry must link proof ids: ${entry.id}`);
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
for (const artifactId of artifactIds) {
|
|
213
|
+
if (!referencedArtifactIds.has(artifactId)) {
|
|
214
|
+
errors.push(`passing proof artifact is unregistered in compatibility registry: ${artifactId}`);
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
const expectedReport = buildCompatibilityReport({ registry, pkg, artifacts });
|
|
219
|
+
const expectedSupportMatrix = generateSupportMatrixMarkdown(expectedReport);
|
|
220
|
+
const actualSupportMatrix = supportMatrix ?? (existsSync(SUPPORT_MATRIX_PATH) ? readFileSync(SUPPORT_MATRIX_PATH, "utf8") : "");
|
|
221
|
+
if (normalizeSupportMatrixForCompare(actualSupportMatrix) !== normalizeSupportMatrixForCompare(expectedSupportMatrix)) {
|
|
222
|
+
errors.push("docs/SUPPORT_MATRIX.md is stale relative to the compatibility registry");
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
const actualReportJson = reportJson ?? readJson(REPORT_PATH, null);
|
|
226
|
+
if (JSON.stringify(normalizeReportForCompare(actualReportJson || {})) !== JSON.stringify(normalizeReportForCompare(expectedReport))) {
|
|
227
|
+
errors.push(".fastscript/proofs/compatibility-registry-report.json is stale relative to the compatibility registry");
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
return { errors, expectedReport, expectedSupportMatrix };
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
export function writeCompatibilityArtifacts({ registry, pkg, artifacts }) {
|
|
234
|
+
const report = buildCompatibilityReport({ registry, pkg, artifacts });
|
|
235
|
+
const supportMatrix = generateSupportMatrixMarkdown(report);
|
|
236
|
+
mkdirSync(resolve("docs"), { recursive: true });
|
|
237
|
+
mkdirSync(resolve(".fastscript", "proofs"), { recursive: true });
|
|
238
|
+
mkdirSync(GENERATED_DIR, { recursive: true });
|
|
239
|
+
writeFileSync(SUPPORT_MATRIX_PATH, supportMatrix, "utf8");
|
|
240
|
+
writeFileSync(REPORT_PATH, `${JSON.stringify(report, null, 2)}\n`, "utf8");
|
|
241
|
+
writeFileSync(GENERATED_MODULE_PATH, `export const COMPATIBILITY_REPORT = ${JSON.stringify(report, null, 2)};\nexport default COMPATIBILITY_REPORT;\n`, "utf8");
|
|
242
|
+
return { report, supportMatrix };
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
export async function runCompatibilityGovernanceCheck() {
|
|
246
|
+
const registry = loadCompatibilityRegistry();
|
|
247
|
+
const pkg = readJson(resolve("package.json"), {});
|
|
248
|
+
const artifacts = loadCompatibilityArtifacts();
|
|
249
|
+
const { errors } = validateCompatibilityGovernance({ registry, pkg, artifacts });
|
|
250
|
+
if (errors.length) {
|
|
251
|
+
const error = new Error(`compatibility governance failed:\n- ${errors.join("\n- ")}`);
|
|
252
|
+
error.status = 1;
|
|
253
|
+
throw error;
|
|
254
|
+
}
|
|
255
|
+
console.log("compatibility governance pass");
|
|
256
|
+
}
|
|
257
|
+
|
package/src/fs-normalize.mjs
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { compileFastScript } from "./fs-parser.mjs";
|
|
2
2
|
|
|
3
3
|
export function normalizeFastScript(source, options = {}) {
|
|
4
|
-
const
|
|
4
|
+
const prepared = stripTypeScriptHints(String(source ?? ""));
|
|
5
|
+
const { code } = compileFastScript(prepared, {
|
|
5
6
|
file: options.file || "",
|
|
6
7
|
mode: options.mode || "lenient",
|
|
7
8
|
recover: options.recover !== false,
|
|
@@ -11,7 +12,8 @@ export function normalizeFastScript(source, options = {}) {
|
|
|
11
12
|
}
|
|
12
13
|
|
|
13
14
|
export function normalizeFastScriptWithMetadata(source, options = {}) {
|
|
14
|
-
|
|
15
|
+
const prepared = stripTypeScriptHints(String(source ?? ""));
|
|
16
|
+
return compileFastScript(prepared, {
|
|
15
17
|
file: options.file || "",
|
|
16
18
|
mode: options.mode || "lenient",
|
|
17
19
|
recover: options.recover !== false,
|
|
@@ -40,7 +42,7 @@ export function stripTypeScriptHints(source) {
|
|
|
40
42
|
continue;
|
|
41
43
|
}
|
|
42
44
|
|
|
43
|
-
if (/^\s*interface\s+[A-Za-z_$][\w$]
|
|
45
|
+
if (/^\s*interface\s+[A-Za-z_$][\w$]*(?:\s*<[^>]+>)?\s*[{]/.test(next) || /^\s*enum\s+[A-Za-z_$][\w$]*\s*[{]/.test(next)) {
|
|
44
46
|
out.push(`// ${next.trim()} (removed by fastscript migrate)`);
|
|
45
47
|
skippingBlock = true;
|
|
46
48
|
const opens = (next.match(/{/g) || []).length;
|
|
@@ -49,7 +51,7 @@ export function stripTypeScriptHints(source) {
|
|
|
49
51
|
continue;
|
|
50
52
|
}
|
|
51
53
|
|
|
52
|
-
if (/^\s*type\s+[A-Za-z_$][\w$]
|
|
54
|
+
if (/^\s*type\s+[A-Za-z_$][\w$]*(?:\s*<[^>]+>)?\s*=/.test(next)) {
|
|
53
55
|
out.push(`// ${next.trim()} (removed by fastscript migrate)`);
|
|
54
56
|
if (!next.includes(";") && next.includes("{")) {
|
|
55
57
|
skippingBlock = true;
|