release: WRNexusJS 0.8.0
Quality / quality (ubuntu-latest) (push) Failing after 21s
Quality / quality (windows-latest) (push) Canceled after 0s

This commit is contained in:
2026-08-02 23:18:51 +05:30
parent 87507edf59
commit 586a6db8ff
625 changed files with 243608 additions and 11210 deletions
+5
View File
@@ -0,0 +1,5 @@
# @wrnexus/typecheck
Static type checking for `.wrn` declarations, props, state, outputs, functions, stores, and generated virtual TypeScript files.
The package is compiler tooling rather than a browser UI package, so its public kit consists of programmatic typecheck helpers and diagnostics.
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/typecheck",
"version": "0.7.0",
"version": "0.8.0",
"type": "module",
"main": "src/index.ts",
"exports": {
+43 -4
View File
@@ -1,4 +1,4 @@
import { existsSync, readFileSync } from "node:fs";
import { existsSync, readFileSync, readdirSync } from "node:fs";
import { dirname, join, normalize, resolve } from "node:path";
import ts from "typescript";
import {
@@ -51,6 +51,39 @@ function resolveImportedWrn(source: string, filePath: string, appRoot: string):
return null;
}
function workspacePackagePaths(appRoot: string): Record<string, string[]> {
let current = resolve(appRoot);
while (true) {
const manifestPath = join(current, "package.json");
if (existsSync(manifestPath)) {
try {
const manifest = JSON.parse(readFileSync(manifestPath, "utf8"));
if (Array.isArray(manifest.workspaces) && existsSync(join(current, "packages"))) {
const paths: Record<string, string[]> = {};
for (const entry of readdirSync(join(current, "packages"), { withFileTypes: true })) {
if (!entry.isDirectory()) continue;
const packageRoot = join(current, "packages", entry.name);
const packageManifestPath = join(packageRoot, "package.json");
if (!existsSync(packageManifestPath)) continue;
const packageManifest = JSON.parse(readFileSync(packageManifestPath, "utf8"));
if (typeof packageManifest.name !== "string") continue;
const main =
typeof packageManifest.main === "string" ? packageManifest.main : "src/index.ts";
paths[packageManifest.name] = [join(packageRoot, main)];
paths[`${packageManifest.name}/*`] = [join(packageRoot, "src", "*.ts")];
}
return paths;
}
} catch {
/* continue toward a parent workspace */
}
}
const parent = dirname(current);
if (parent === current) return {};
current = parent;
}
}
function importedWrnDeclarations(ast: PageAst, filePath: string, appRoot: string): string {
const declarations: string[] = [];
for (const entry of ast.structuredImports) {
@@ -106,7 +139,7 @@ function functionDeclaration(fn: RuntimeFunctionDecl): string {
const params = fn.parameters
.map(
(param) =>
`${param.name}${param.optional ? "?" : ""}${param.valueType ? `: ${param.valueType}` : ": unknown"}${param.default ? ` = ${param.default}` : ""}`,
`${param.name}${param.optional ? "?" : ""}${param.valueType ? `: ${param.valueType}` : param.name === "event" ? ": CustomEvent<any> & { target: HTMLElement }" : ": unknown"}${param.default ? ` = ${param.default}` : ""}`,
)
.join(", ");
return `export ${fn.async ? "async " : ""}function ${fn.name}(${params})${fn.returnType ? `: ${fn.returnType}` : ""} {${fn.body}}`;
@@ -186,6 +219,12 @@ export function virtualTypeScriptModule(
)
.join("; ");
append(`declare const output: { ${outputType} };`);
for (const output of ast.outputs)
append(
`declare const ${output.name}: (${output.payload ? `${output.payload.name}${output.payload.optional ? "?" : ""}: ${output.payload.valueType}` : ""}) => void;`,
);
for (const match of source.matchAll(/@event\s+([A-Za-z_$][\w$]*)\s*=\s*function/g))
append(`declare const ${match[1]}: ((...args: unknown[]) => void) | undefined;`);
append(`declare const server: { ${serverType} };`);
append(`declare const props: Readonly<${ast.name}Props>;`);
append("declare const refs: Record<string, Element | null>;");
@@ -601,8 +640,8 @@ export function checkWrnSource(
allowArbitraryExtensions: true,
noEmit: true,
baseUrl: appRoot,
paths: { "@/*": ["app/*"] },
lib: ["lib.esnext.d.ts", "lib.dom.d.ts"],
paths: { "@/*": ["app/*"], ...workspacePackagePaths(appRoot) },
lib: ["lib.esnext.d.ts", "lib.dom.d.ts", "lib.dom.iterable.d.ts"],
};
const rootNames = [virtual.fileName, ...appTypes.files.keys()];
const program = ts.createProgram(
@@ -45,7 +45,7 @@ page Home {
expect(diagnostics.some((item) => item.code === "WRN-COMPONENT-UNKNOWN-PROP")).toBe(true);
expect(diagnostics.some((item) => item.code === "WRN-COMPONENT-PROP-LITERAL")).toBe(true);
expect(diagnostics.some((item) => item.code === "WRN-OUTPUT-UNKNOWN-HANDLER")).toBe(true);
});
}, 15_000);
test("types imported store actions", () => {
const root = fixture();
@@ -59,4 +59,4 @@ page Home {
{ appRoot: root, filePath },
);
expect(diagnostics.some((item) => item.code === "WRN-TYPE-2345")).toBe(true);
});
}, 15_000);