From 77f1417a2983c2ba4348cddf23d7f0bd6709ae5f Mon Sep 17 00:00:00 2001 From: DevBot Date: Thu, 16 Jul 2026 22:39:35 +0800 Subject: [PATCH 1/3] chore(dogfood): refresh mastodon lockfile --- examples/deno-desktop-mastodon/deno.lock | 32 ++++++------------------ 1 file changed, 8 insertions(+), 24 deletions(-) diff --git a/examples/deno-desktop-mastodon/deno.lock b/examples/deno-desktop-mastodon/deno.lock index a154d6880..962e522e7 100644 --- a/examples/deno-desktop-mastodon/deno.lock +++ b/examples/deno-desktop-mastodon/deno.lock @@ -320,33 +320,25 @@ "npm:vite@8.0.10" ], "links": { - "jsr:@openelement/adapter-vite@0.41.0-alpha.8": { + "jsr:@openelement/adapter-vite@0.41.0-alpha.15": { "dependencies": [ "npm:@hono/vite-dev-server@~0.25.3", "npm:@mdx-js/rollup@^3.1.1", "npm:@types/sanitize-html@2", + "npm:gray-matter@^4.0.3", + "npm:hono@^4.12.0", + "npm:marked@15", "npm:sanitize-html@^2.17.4", "npm:vite@8.0.10" ] }, - "jsr:@openelement/app@0.41.0-alpha.8": { + "jsr:@openelement/app@0.41.0-alpha.15": { "dependencies": [ "npm:preact-render-to-string@^6.5.0" ] }, - "jsr:@openelement/content@0.41.0-alpha.8": { - "dependencies": [ - "npm:@mdx-js/mdx@^3.1.1", - "npm:@types/sanitize-html@2", - "npm:gray-matter@^4.0.3", - "npm:marked@15", - "npm:sanitize-html@^2.17.4", - "npm:vite@8.0.10" - ] - }, - "jsr:@openelement/core@0.41.0-alpha.8": {}, - "jsr:@openelement/create@0.41.0-alpha.8": {}, - "jsr:@openelement/element@0.41.0-alpha.8": {}, + "jsr:@openelement/create@0.41.0-alpha.15": {}, + "jsr:@openelement/element@0.41.0-alpha.15": {}, "jsr:@openelement/example-desktop-reader@0.41.0-alpha.6": { "dependencies": [ "jsr:@std/assert@1", @@ -358,15 +350,7 @@ "npm:vite@8.0.10" ] }, - "jsr:@openelement/protocol@0.41.0-alpha.8": {}, - "jsr:@openelement/router@0.41.0-alpha.8": {}, - "jsr:@openelement/signal@0.41.0-alpha.8": { - "dependencies": [ - "npm:@preact/signals-core@^1.12.1" - ] - }, - "jsr:@openelement/ssg@0.41.0-alpha.8": {}, - "jsr:@openelement/ui@0.41.0-alpha.8": {} + "jsr:@openelement/ui@0.41.0-alpha.15": {} } } } From 79b44ad25c4725f0f08f5cbd684a986eed5f893f Mon Sep 17 00:00:00 2001 From: DevBot Date: Thu, 16 Jul 2026 22:39:36 +0800 Subject: [PATCH 2/3] refactor(adapter-vite): narrow public build interface --- CHANGELOG.md | 9 ++ docs/release/v0.41.0-interface-snapshot.json | 95 +------------------ packages/adapter-vite/README.md | 15 ++- .../adapter-vite/__tests__/app-vite.test.ts | 2 +- .../__tests__/index-plugin.test.ts | 12 +++ packages/adapter-vite/deno.json | 13 +-- .../src/generated-export-files.ts | 11 --- packages/adapter-vite/src/i18n-plugin.ts | 2 +- .../src/internal/ssg/entry-render-ssg.ts | 1 - .../src/internal/ssg/entry-renderer.ts | 2 +- packages/app/README.md | 6 +- packages/app/src/i18n-runtime.ts | 2 +- packages/app/src/i18n.ts | 2 +- 13 files changed, 39 insertions(+), 133 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e0450f4ab..eb2b9b8e6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,15 @@ Current truth lives in: Historical changelog details remain available through git history and release evidence. +## Unreleased + +- Narrows `@openelement/adapter-vite` to its documented root, + `nitro-mount`, and `cli/build` interfaces. Import `openElement`, build + helpers, MDX helpers, and sitemap generation from the package root; internal + plugin factories and individual build phases are no longer published. +- Refreshes the Mastodon dogfood lockfile to the current five-package + `0.41.0-alpha.15` dependency graph so clean verification is reproducible. + ## 0.41.0-alpha.13 (unreleased) - Removes the alpha-only `defineLayout` alias; use `defineElement` with the same diff --git a/docs/release/v0.41.0-interface-snapshot.json b/docs/release/v0.41.0-interface-snapshot.json index e03cae14f..d1fad4607 100644 --- a/docs/release/v0.41.0-interface-snapshot.json +++ b/docs/release/v0.41.0-interface-snapshot.json @@ -98,7 +98,7 @@ ] }, "./i18n": { - "sha256": "56dd01445bd8ada8b9ca5489eb8d0cb83a911f105c1226cd093ded19fdf8b505", + "sha256": "3ad65c2d8218586e85d556dd013c6e08ab17d741a1b544886c52f34ae63dfb7c", "publicDeclarations": [ "export type { OpenElementI18nOptions } from './i18n-runtime.ts';", "export type { LocalePath } from './internal/router/i18n.ts';" @@ -136,19 +136,8 @@ "name": "@openelement/adapter-vite", "exports": { ".": "./src/index.ts", - "./app-vite": "./src/app-vite.ts", - "./build-context": "./src/build-context.ts", "./cli/build": "./src/cli/build.ts", - "./cli/build-client": "./src/cli/build-client.ts", - "./cli/build-ssg": "./src/cli/build-ssg.ts", - "./generated-data-resolver": "./src/generated-data-resolver.ts", - "./head-injection": "./src/head-injection.ts", - "./i18n-plugin": "./src/i18n-plugin.ts", - "./nitro-mount": "./src/nitro-mount.ts", - "./plugin": "./src/plugin.ts", - "./plugin-mdx": "./src/plugin-mdx.ts", - "./route-manifest": "./src/route-manifest.ts", - "./sitemap": "./src/sitemap.ts" + "./nitro-mount": "./src/nitro-mount.ts" }, "declarations": { ".": { @@ -164,62 +153,10 @@ "export type { OpenMdxPluginOptions } from './plugin-mdx.ts';" ] }, - "./app-vite": { - "sha256": "57646b30b6aef837c2929b4e0ac5cf19247cac2261ab2049fad306309f2ae64b", - "publicDeclarations": [ - "export interface OpenElementOptions extends FrameworkOptions {", - "export function openElement(options: OpenElementOptions = {}): Plugin[] {" - ] - }, - "./build-context": { - "sha256": "3a58c9c14a9ad04bce324e2877c81e826a5339c2497eab8b014c2cbeda921c5b", - "publicDeclarations": [ - "export type Phase = 1 | 2 | 3;", - "export class Phase1Meta {", - "export class Phase2Meta {", - "export class Phase3Meta {", - "export class OpenElementBuildContext {" - ] - }, "./cli/build": { "sha256": "19b817d8d114f0b107b7708675754de3fdc12c76c85c4dd3333814b6643894bd", "publicDeclarations": [] }, - "./cli/build-client": { - "sha256": "14e89ab366b2a2230c872baffb3519042fd1ac39cac15326906da537098a36ae", - "publicDeclarations": [] - }, - "./cli/build-ssg": { - "sha256": "55fed1e0cf8265222329dd036c709fc967054e1f1f3dd3e4f9b3856382a3ad42", - "publicDeclarations": [] - }, - "./generated-data-resolver": { - "sha256": "d18395cfa3eca7cd72f2e5481b24a0e76d49284d717a9c08274c085adf80788c", - "publicDeclarations": [ - "export const GENERATED_NAV_ID = '@openelement/generated/nav';", - "export const GENERATED_BLOG_DATA_ID = '@openelement/generated/blog-data';", - "export const GENERATED_I18N_ID = '@openelement/generated/i18n';", - "export type GeneratedDataResolverOptions = {", - "export function generatedDataPath(", - "export function createGeneratedDataResolverPlugin(" - ] - }, - "./head-injection": { - "sha256": "28dab8f1b72b612847e1a158869ad8afc8fe89a242684ffffb44997c022a66e0", - "publicDeclarations": [ - "export function assertNoScriptTags(html: string, context: string): void {", - "export function validateSafeUrl(url: string, context: string): string {", - "export interface HeadExtrasResult {", - "export function buildHeadExtras(options: FrameworkOptions): HeadExtrasResult {" - ] - }, - "./i18n-plugin": { - "sha256": "b24544efcdc71ff563a6a5ad4745bbfa3c3152a4694d42bdae2ec929a5f47cb3", - "publicDeclarations": [ - "export function writeI18nDataModule(locales: string[], defaultLocale: string): string {", - "export function openI18n(" - ] - }, "./nitro-mount": { "sha256": "13667f6d4b8db527d5f5cf4f7f21e8764aa92732d48a7d2601760d81e5321a39", "publicDeclarations": [ @@ -228,34 +165,6 @@ "export interface OpenElementNitroMountOptions<", "export function createOpenElementNitroHandler<" ] - }, - "./plugin": { - "sha256": "86180df73bccca4e4527599ff948e98f0cf49b3764bde8d844f4fb409e58c0d2", - "publicDeclarations": [ - "export function optionalPackageStubsPlugin(): Plugin {", - "export function createOpenPlugin(" - ] - }, - "./plugin-mdx": { - "sha256": "5acc04ce17016f446a66384f859e24ef914743a71fa02c0cb10cdfa3adcc84eb", - "publicDeclarations": [ - "export interface OpenMdxPluginOptions {", - "export function mdxPlugin(options: OpenMdxPluginOptions = {}): Plugin {" - ] - }, - "./route-manifest": { - "sha256": "383a1fdf94c5df10b62fbbdcc3e9d021dfbab222e7c232c3358718d8a866a8f8", - "publicDeclarations": [ - "export interface GenerateRouteManifestOptions {", - "export const routeManifest = {} as const;", - "export const routeManifest = {" - ] - }, - "./sitemap": { - "sha256": "2c24151329624e9adde127f4762580ff3ac75fff4a66818fc83d7100d91a9135", - "publicDeclarations": [ - "export type { SitemapOptions } from './internal/content/types.ts';" - ] } } }, diff --git a/packages/adapter-vite/README.md b/packages/adapter-vite/README.md index 05ca0ef93..e2497b21f 100644 --- a/packages/adapter-vite/README.md +++ b/packages/adapter-vite/README.md @@ -2,9 +2,8 @@ openElement build orchestration for Vite. -> v0.39 surface: advanced Framework infrastructure. First-run apps should use -> `@openelement/adapter-vite/app-vite` or generated `@openelement/create` tasks instead of -> importing this package directly. +The package root is the supported Vite interface. Generated +`@openelement/create` projects use the same interface. This package scans routes and islands, generates virtual entries, builds client island chunks, runs SSG, and writes post-processed HTML. It is build-time @@ -19,12 +18,12 @@ npm install @openelement/adapter-vite ## Usage ```ts -import { createOpenPlugin } from '@openelement/adapter-vite/plugin'; +import { openElement } from '@openelement/adapter-vite'; import { defineConfig } from 'vite'; export default defineConfig({ plugins: [ - createOpenPlugin({ + openElement({ routesDir: 'app/routes', islandsDir: 'app/islands', componentsDir: 'app/components', @@ -34,9 +33,9 @@ export default defineConfig({ }); ``` -Most applications should use `openElement()` from `@openelement/adapter-vite/app-vite` -instead; it combines the core adapter, content pipeline, and i18n with one -shared build context. +`openElement()` combines the core adapter, content pipeline, and i18n behind one +shared build context. Internal plugin factories and build phases are not +published as package subpaths. ## Nitro Deploy Adapter diff --git a/packages/adapter-vite/__tests__/app-vite.test.ts b/packages/adapter-vite/__tests__/app-vite.test.ts index bdf90f955..85a586c48 100644 --- a/packages/adapter-vite/__tests__/app-vite.test.ts +++ b/packages/adapter-vite/__tests__/app-vite.test.ts @@ -1,5 +1,5 @@ /** - * @openelement/adapter-vite/app-vite - Unified entry tests + * @openelement/adapter-vite unified entry tests. * * Tests that openElement() correctly combines openPipeline() + openContent() + openI18n() * with a shared OpenElementBuildContext. This is the primary user-facing API. diff --git a/packages/adapter-vite/__tests__/index-plugin.test.ts b/packages/adapter-vite/__tests__/index-plugin.test.ts index 3c6916553..e4fb5c6b8 100644 --- a/packages/adapter-vite/__tests__/index-plugin.test.ts +++ b/packages/adapter-vite/__tests__/index-plugin.test.ts @@ -17,6 +17,18 @@ import { createOpenPlugin } from '../src/plugin.ts'; import { openPipeline } from '../src/index.ts'; +Deno.test('package exposes only the supported deep build interface', async () => { + const manifest = JSON.parse( + await Deno.readTextFile(new URL('../deno.json', import.meta.url)), + ) as { exports: Record }; + + assertEquals(Object.keys(manifest.exports).sort(), [ + '.', + './cli/build', + './nitro-mount', + ]); +}); + type CallablePluginHook = (...args: unknown[]) => unknown; function callPluginHook(hook: unknown, ...args: unknown[]): unknown { diff --git a/packages/adapter-vite/deno.json b/packages/adapter-vite/deno.json index 395046b14..ec16439ba 100644 --- a/packages/adapter-vite/deno.json +++ b/packages/adapter-vite/deno.json @@ -3,19 +3,8 @@ "version": "0.41.0-alpha.15", "exports": { ".": "./src/index.ts", - "./app-vite": "./src/app-vite.ts", - "./build-context": "./src/build-context.ts", - "./head-injection": "./src/head-injection.ts", - "./i18n-plugin": "./src/i18n-plugin.ts", "./nitro-mount": "./src/nitro-mount.ts", - "./plugin": "./src/plugin.ts", - "./generated-data-resolver": "./src/generated-data-resolver.ts", - "./plugin-mdx": "./src/plugin-mdx.ts", - "./route-manifest": "./src/route-manifest.ts", - "./sitemap": "./src/sitemap.ts", - "./cli/build": "./src/cli/build.ts", - "./cli/build-client": "./src/cli/build-client.ts", - "./cli/build-ssg": "./src/cli/build-ssg.ts" + "./cli/build": "./src/cli/build.ts" }, "imports": { "@mdx-js/rollup": "npm:@mdx-js/rollup@^3.1.1", diff --git a/packages/adapter-vite/src/generated-export-files.ts b/packages/adapter-vite/src/generated-export-files.ts index c18c3cf1f..9ffaf53f0 100644 --- a/packages/adapter-vite/src/generated-export-files.ts +++ b/packages/adapter-vite/src/generated-export-files.ts @@ -4,19 +4,8 @@ export const OPENELEMENT_EXPORT_FILES: Record> = { 'adapter-vite': { '.': 'src/index.ts', - 'app-vite': 'src/app-vite.ts', - 'build-context': 'src/build-context.ts', 'cli/build': 'src/cli/build.ts', - 'cli/build-client': 'src/cli/build-client.ts', - 'cli/build-ssg': 'src/cli/build-ssg.ts', - 'generated-data-resolver': 'src/generated-data-resolver.ts', - 'head-injection': 'src/head-injection.ts', - 'i18n-plugin': 'src/i18n-plugin.ts', 'nitro-mount': 'src/nitro-mount.ts', - 'plugin': 'src/plugin.ts', - 'plugin-mdx': 'src/plugin-mdx.ts', - 'route-manifest': 'src/route-manifest.ts', - 'sitemap': 'src/sitemap.ts', }, 'app': { '.': 'src/index.ts', diff --git a/packages/adapter-vite/src/i18n-plugin.ts b/packages/adapter-vite/src/i18n-plugin.ts index e34fb10a6..0354cf2b0 100644 --- a/packages/adapter-vite/src/i18n-plugin.ts +++ b/packages/adapter-vite/src/i18n-plugin.ts @@ -1,6 +1,6 @@ // deno-api-free:ignore /** - * @openelement/adapter-vite/i18n-plugin - Node-only Vite plugin for i18n + * Internal Node-only Vite plugin for i18n. * * Build-time Vite plugin, allowed to use node:*. * diff --git a/packages/adapter-vite/src/internal/ssg/entry-render-ssg.ts b/packages/adapter-vite/src/internal/ssg/entry-render-ssg.ts index df485134d..a6aa1f986 100644 --- a/packages/adapter-vite/src/internal/ssg/entry-render-ssg.ts +++ b/packages/adapter-vite/src/internal/ssg/entry-render-ssg.ts @@ -37,7 +37,6 @@ export function renderSsgSection(desc: EntryDescriptor): string { lines.push( 'export { posts, getPostBySlug, getBlogOptions } from "@openelement/generated/blog-data"', ); - lines.push('export { generateSitemap } from "@openelement/adapter-vite/sitemap"'); lines.push( 'export { locales, getDefaultLocale, getI18nOptions } from "@openelement/generated/i18n"', ); diff --git a/packages/adapter-vite/src/internal/ssg/entry-renderer.ts b/packages/adapter-vite/src/internal/ssg/entry-renderer.ts index c03b41726..20f27f7e5 100644 --- a/packages/adapter-vite/src/internal/ssg/entry-renderer.ts +++ b/packages/adapter-vite/src/internal/ssg/entry-renderer.ts @@ -15,7 +15,7 @@ * * H-16 KNOWN ISSUE: Circular dependency between adapter-vite <-> content * adapter-vite generates code that imports its public sitemap utility - * content package imports @openelement/adapter-vite/build-context + * adapter internals share the private OpenElementBuildContext implementation * Shared contracts now live in @openelement/element and adapter internals. * so consumer import maps can be checked. * diff --git a/packages/app/README.md b/packages/app/README.md index c5a527bce..239f6c10a 100644 --- a/packages/app/README.md +++ b/packages/app/README.md @@ -19,10 +19,10 @@ export default definePage({ }); ``` -Use the Vite facade from `@openelement/adapter-vite/app-vite` in `vite.config.ts`: +Use the Vite facade from `@openelement/adapter-vite` in `vite.config.ts`: ```ts -import { openElement } from '@openelement/adapter-vite/app-vite'; +import { openElement } from '@openelement/adapter-vite'; import { defineConfig } from 'vite'; export default defineConfig({ @@ -58,7 +58,7 @@ parameters, and wildcards remain supported. authors should start from this package. Build configuration is owned by `@openelement/adapter-vite`; generated projects -and docs import its `app-vite` facade rather than an app-package Vite subpath. +and docs import its package root rather than an implementation subpath. ## Install diff --git a/packages/app/src/i18n-runtime.ts b/packages/app/src/i18n-runtime.ts index ba633aa30..4234d471d 100644 --- a/packages/app/src/i18n-runtime.ts +++ b/packages/app/src/i18n-runtime.ts @@ -1,7 +1,7 @@ /** * @openelement/app/i18n-runtime - Runtime-safe i18n helpers (no node:* modules) * - * Separated from @openelement/adapter-vite/i18n-plugin to prevent node built-ins from + * Separated from the adapter-vite internal i18n plugin to prevent node built-ins from * being pulled into client island bundles via @openelement/app main re-exports. * * Route-level helpers: diff --git a/packages/app/src/i18n.ts b/packages/app/src/i18n.ts index e9315e031..2789d99e5 100644 --- a/packages/app/src/i18n.ts +++ b/packages/app/src/i18n.ts @@ -2,7 +2,7 @@ * @openelement/app/i18n - Runtime-safe i18n helpers (no node:* modules) * * Thin re-export barrel from i18n-runtime.ts. - * The node-only Vite plugin is in @openelement/adapter-vite/i18n-plugin and + * The node-only Vite plugin is internal to @openelement/adapter-vite and * must NOT be re-exported here, * to prevent node:process/node:path/node:fs from being pulled into client * island bundles via @openelement/app main re-exports. From 32cae7722f04c958c2a7b0c7bf2297d8f4d6f69d Mon Sep 17 00:00:00 2001 From: DevBot Date: Thu, 16 Jul 2026 22:39:36 +0800 Subject: [PATCH 3/3] fix(tools): compare generated exports by content --- tools/generate-openelement-export-files.ts | 38 ++++++++++++---------- 1 file changed, 20 insertions(+), 18 deletions(-) diff --git a/tools/generate-openelement-export-files.ts b/tools/generate-openelement-export-files.ts index 12545613a..1095e40d5 100644 --- a/tools/generate-openelement-export-files.ts +++ b/tools/generate-openelement-export-files.ts @@ -90,35 +90,37 @@ async function runFormatter(target: string): Promise { } } -async function gitDiffIsEmpty(target: string): Promise { - const cmd = new Deno.Command('git', { args: ['diff', '--quiet', '--', target] }); - const status = await cmd.output(); - return status.code === 0; -} - async function main(args: string[]): Promise { const checkOnly = args.includes('--check'); const map = await buildExportFiles(); const source = render(map); - await Deno.writeTextFile(TARGET, source); - await runFormatter(TARGET); - if (checkOnly) { - const clean = await gitDiffIsEmpty(TARGET); - if (!clean) { - const diff = new Deno.Command('git', { - args: ['--no-pager', 'diff', '--', TARGET], - }); - const out = await diff.output(); - console.error('export-files sync check failed: generated file is stale.'); - console.error(new TextDecoder().decode(out.stdout)); - Deno.exit(1); + const temporary = await Deno.makeTempFile({ + dir: `${REPO_ROOT}packages/adapter-vite/src`, + prefix: '.generated-export-files-', + suffix: '.ts', + }); + try { + await Deno.writeTextFile(temporary, source); + await runFormatter(temporary); + const [actual, expected] = await Promise.all([ + Deno.readTextFile(TARGET), + Deno.readTextFile(temporary), + ]); + if (actual !== expected) { + console.error('export-files sync check failed: generated file is stale.'); + Deno.exit(1); + } + } finally { + await Deno.remove(temporary).catch(() => undefined); } console.log('export-files sync check passed (generated file matches deno.json exports).'); return; } + await Deno.writeTextFile(TARGET, source); + await runFormatter(TARGET); console.log(`Wrote ${TARGET}`); }