release: WRNexusJS 0.8.0
This commit is contained in:
@@ -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,
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user