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
+88 -3
View File
@@ -1,4 +1,4 @@
import type { PageAst, WrnDiagnostic } from "@wrnexus/syntax";
import type { PageAst, ViewNode, WrnDiagnostic } from "@wrnexus/syntax";
import { normalizeClientRuntime, normalizePackageAsset, validateStyleIds } from "./manifest.ts";
import type {
ClientRuntimeDefinition,
@@ -11,7 +11,13 @@ import type {
PluginContext,
PluginInput,
PluginOrder,
PluginPermission,
PluginRunner,
PluginDirective,
PluginCliCommand,
PluginVirtualModule,
PluginDeploymentAdapter,
PluginConfigSchema,
TransformContext,
WrnexusPlugin,
} from "./types.ts";
@@ -19,6 +25,8 @@ import type {
export * from "./types.ts";
export * from "./manifest.ts";
export { discoverPlugins, type DiscoverPluginOptions } from "./discovery.ts";
export { testPluginCompatibility } from "./compatibility.ts";
export type { PluginCompatibilityResult, PluginCompatibilityTarget } from "./compatibility.ts";
export { definePlugin, flattenPlugins } from "./base.ts";
import { flattenPlugins } from "./base.ts";
@@ -112,9 +120,40 @@ function assertUnique<T>(kind: string, entries: readonly T[], key: (entry: T) =>
}
}
async function transformDirectives(
nodes: ViewNode[],
directives: readonly PluginDirective[],
context: TransformContext,
): Promise<void> {
const registry = new Map(directives.map((directive) => [directive.name, directive]));
for (const node of nodes) {
if (node.type === "element") {
for (const attribute of node.attrs) {
if (!attribute.name.startsWith("use:")) continue;
const name = attribute.name.slice(4);
const directive = registry.get(name);
if (!directive) continue;
const transformed = await directive.transform?.(attribute.value, context);
if (transformed) {
attribute.name = transformed.name;
attribute.value = transformed.value;
} else attribute.name = `data-wrn-directive-${name}`;
}
await transformDirectives(node.children, directives, context);
} else if (node.type === "each") {
await transformDirectives(node.body, directives, context);
await transformDirectives(node.empty, directives, context);
} else if (node.type === "if") {
for (const branch of node.branches)
await transformDirectives(branch.body, directives, context);
}
}
}
export function createPluginRunner(input: PluginInput, context: PluginContext): PluginRunner {
const plugins = resolvePlugins(input);
let contributionCache: PluginContributions | null = null;
let setupComplete = false;
const transformContext = (file: string): TransformContext => ({ ...context, file });
const contributions = async (): Promise<PluginContributions> => {
@@ -126,6 +165,13 @@ export function createPluginRunner(input: PluginInput, context: PluginContext):
const routes: PackageRouteDefinition[] = [];
const middleware: string[] = [];
const migrations: PackageMigrationDefinition[] = [];
const directives: PluginDirective[] = [];
const cliCommands: PluginCliCommand[] = [];
const virtualModules: PluginVirtualModule[] = [];
const deploymentAdapters: PluginDeploymentAdapter[] = [];
const configSchemas: PluginConfigSchema[] = [];
const documentation: string[] = [];
const typeDefinitions: string[] = [];
for (const plugin of plugins) {
componentDirs.push(...(await resolveContribution(plugin.componentDirs, context)));
@@ -135,6 +181,13 @@ export function createPluginRunner(input: PluginInput, context: PluginContext):
routes.push(...(await resolveContribution(plugin.routeEntries, context)));
middleware.push(...(await resolveContribution(plugin.middleware, context)));
migrations.push(...(await resolveContribution(plugin.migrations, context)));
directives.push(...(await resolveContribution(plugin.directives, context)));
cliCommands.push(...(await resolveContribution(plugin.cliCommands, context)));
virtualModules.push(...(await resolveContribution(plugin.virtualModules, context)));
deploymentAdapters.push(...(await resolveContribution(plugin.deploymentAdapters, context)));
configSchemas.push(...(await resolveContribution(plugin.configSchemas, context)));
documentation.push(...(await resolveContribution(plugin.documentation, context)));
typeDefinitions.push(...(await resolveContribution(plugin.typeDefinitions, context)));
}
const normalizedRuntimes = clientRuntimes.map(normalizeClientRuntime);
@@ -164,6 +217,11 @@ export function createPluginRunner(input: PluginInput, context: PluginContext):
}
}
assertUnique("MIGRATION", migrations, (entry) => `${entry.database ?? "default"}:${entry.id}`);
assertUnique("DIRECTIVE", directives, (entry) => entry.name);
assertUnique("CLI-COMMAND", cliCommands, (entry) => entry.name);
assertUnique("VIRTUAL-MODULE", virtualModules, (entry) => entry.id);
assertUnique("DEPLOYMENT-ADAPTER", deploymentAdapters, (entry) => entry.name);
assertUnique("CONFIG-SCHEMA", configSchemas, (entry) => entry.namespace);
contributionCache = {
componentDirs: [...new Set(componentDirs)],
@@ -173,6 +231,13 @@ export function createPluginRunner(input: PluginInput, context: PluginContext):
routes,
middleware: [...new Set(middleware)],
migrations,
directives,
cliCommands,
virtualModules,
deploymentAdapters,
configSchemas,
documentation: [...new Set(documentation)],
typeDefinitions: [...new Set(typeDefinitions)],
};
context.metadata.set("@wrnexus/plugin:contributions", contributionCache);
return contributionCache;
@@ -181,18 +246,29 @@ export function createPluginRunner(input: PluginInput, context: PluginContext):
return {
plugins,
async configure(config) {
if (!setupComplete) {
for (const plugin of plugins) await plugin.setup?.(context);
setupComplete = true;
}
for (const plugin of plugins) await plugin.configure?.(config, context);
contributionCache = null;
},
async configResolved(config) {
for (const plugin of plugins) await plugin.configResolved?.(config, context);
contributionCache = null;
await contributions();
const resolved = await contributions();
for (const schema of resolved.configSchemas)
await schema.validate(config[schema.namespace], context);
},
async transformAst(ast, file) {
let current = ast;
for (const plugin of plugins)
current = (await plugin.transformAst?.(current, transformContext(file))) ?? current;
await transformDirectives(
current.view,
(await contributions()).directives,
transformContext(file),
);
return current;
},
async transformCode(code, file) {
@@ -219,11 +295,19 @@ export function createPluginRunner(input: PluginInput, context: PluginContext):
for (const plugin of plugins) current = (await plugin.routes?.(current, context)) ?? current;
return current;
},
async render(html) {
let current = html;
for (const plugin of plugins) current = (await plugin.render?.(current, context)) ?? current;
return current;
},
async hook(name, value) {
for (const plugin of plugins) {
if (name === "buildStart") await plugin.buildStart?.(context);
else if (name === "buildEnd") await plugin.buildEnd?.(value, context);
else await plugin.configureServer?.(value, context);
else if (name === "configureServer") await plugin.configureServer?.(value, context);
else if (name === "deploy") await plugin.deploy?.(value, context);
else if (name === "shutdown") await plugin.shutdown?.(context);
else await plugin.hmrUpdate?.((value as readonly string[]) ?? [], context);
}
},
};
@@ -237,6 +321,7 @@ export type {
PluginContext,
TransformContext,
WrnexusPlugin,
PluginPermission,
PluginInput,
PluginRunner,
};