Skip to content

feat(plugin): Add API support and enhance plugin registration process - #809

Merged
aXenDeveloper merged 10 commits into
refactor/tanstack_formfrom
perf/plugin_install_and_config
Sep 14, 2026
Merged

aXenDeveloper merged 10 commits into
refactor/tanstack_formfrom
perf/plugin_install_and_config

Conversation

@aXenDeveloper

Copy link
Copy Markdown
Owner

Improving Documentation

Description

What?

Why?

@vercel

vercel Bot commented Sep 13, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
vitnode-prod Ready Ready Preview Sep 14, 2026 1:14pm UTC

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 8933ac9849

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +118 to +121
const key = /\bplugins\s*:\s*\[/g;
key.lastIndex = from;

const match = key.exec(source);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Constrain the plugin-array search to the config object

When a config contains a commented-out plugins: [] or a nested property with that name before the real top-level array, this regex selects the first textual occurrence after buildConfig(. The generator then edits the comment or nested array and leaves vitNodeConfig.plugins unchanged, so it reports successful registration even though the plugin is not enabled; the search needs to ignore comments and identify the top-level property of the builder argument.

Useful? React with 👍 / 👎.

Comment on lines +226 to +228
const comma = entries.endsWith(",") ? "" : ",";

return `${head}${entries}${comma}\n${indent}${call},${trailing}${tail}`;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Insert the comma before a trailing line comment

When the existing multiline array ends with a valid untrailed entry such as blogPlugin() // keep this, entries.endsWith(",") is false and the generated comma is appended after the comment marker. That comma is ignored, leaving the new factory call adjacent to the previous element without a separator and making the generated config syntactically invalid.

Useful? React with 👍 / 👎.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 8890e8dc51

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +60 to +62
const unusable = registrations.filter(
({ status }) => status === "no-plugins-array",
);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Report configs whose builder call is not recognized

When a discovered config formats or aliases its builder so that registerPluginInSource returns no-config-call—for example, buildConfig /* comment */ ({ ... })—this filter excludes it from unusable. If another config is registered successfully, the fallback warning is also suppressed, so the CLI finishes without telling the user that this app was left unregistered. Treat no-config-call as an unusable config and print a per-file manual-registration warning.

Useful? React with 👍 / 👎.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: bd37f688f0

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +35 to +36
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export type AnyFormFieldApi = FormFieldApi<any>;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Remove the any escape hatch from form fields

Because AnyFormFieldApi is passed through both FormField and ItemAutoFormComponentProps, defining it as FormFieldApi<any> collapses field.value and the accepted onChange values to any across every AutoForm control. This allows a custom control expecting one value shape to be connected to an incompatible field without a diagnostic, defeating the type-safe generic introduced here; keep the erased boundary type-safe instead of suppressing the lint rule.

AGENTS.md reference: AGENTS.md:L11-L13

Useful? React with 👍 / 👎.

Comment on lines +241 to +242
const called = new RegExp(`\\b${factory}\\s*\\(`);
const hasEntry = called.test(source.slice(range.open + 1, range.close));

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Ignore commented calls when checking registration

When the target array contains a disabled entry such as // siteNotesPlugin(), this regex treats the comment as a real call. registerPluginInSource then adds only the import—or returns already-registered if the import remains—without inserting an active array element, so the CLI reports registration while the plugin stays disabled. The entry check needs to skip comments and identify an actual top-level call in the array.

Useful? React with 👍 / 👎.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: e175bb2428

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +184 to +185
spinner.text = "Registering the plugin with the apps that can serve it...";
const registrations = await addPluginToConfig({

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Update existing workspaces before registering plugins

When the latest CLI adds a plugin to a workspace generated before this commit, this call writes imports whose package exports resolve only through the new plugin's dist, but only the new app template receives the build:plugins task and root sequencing. The plugin is not built here, so an older root dev runs db:prepare, loads the newly edited API config, and fails to resolve the plugin before its watcher can start; production builds have the same missing-output problem. Patch or validate the existing workspace pipeline as part of plugin creation, or build the plugin before activating these imports.

Useful? React with 👍 / 👎.

Comment on lines +314 to +317
if (!body.includes("\n")) {
const separator = body.trimEnd().endsWith(",") ? " " : ", ";

return `${head}${body}${separator}${call}${tail}`;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Treat inline comment-only arrays as empty

When a valid placeholder is written as plugins: [/* add plugins here */], this branch treats the comment as an existing entry and emits plugins: [/* add plugins here */, newPlugin()]. That leading comma creates an elided undefined array element, violating the typed plugin array and potentially reaching consumers that dereference each plugin; detect whether the body contains actual code before choosing this separator.

Useful? React with 👍 / 👎.

Comment on lines +459 to +460
} catch {
continue;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Report config I/O failures instead of swallowing them

If one discovered config cannot be read or written—for example, a read-only API config while the web config remains writable—this catch omits it from registrations. Because another file can still have status registered, reportConfigRegistrations then suppresses the fallback warning and reports only success, leaving one half of the plugin silently disabled. Preserve a per-file failure status or propagate the error so the CLI can request manual registration.

Useful? React with 👍 / 👎.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 348545b997

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

<Field
className="@md/field-group:items-end"
key={index}
key={rowKey}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve nested controls when a row moves

When an earlier row is removed while a later control holds state that is not yet represented in the form store—such as AutoFormNumber's transient invalid text or an upload queue—the stable outer key does not preserve that control. The nested FormField is still keyed by fullFieldName, which changes from (for example) amounts[2].value to amounts[1].value, so React unmounts it and discards its local state. The added test misses this because it enters valid numbers that can be restored from the form store; the nested field also needs an identity that remains stable when its row moves.

Useful? React with 👍 / 👎.

Comment on lines +386 to +389
const packageMessages = resolvePackageMessagesModules(
plugins,
relative(appRoot, paths.config),
);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Watch plugin configs for locale manifest changes

When vitnode dev is already running and a plugin adds or removes a localeFiles entry, its watcher rebuilds the plugin's dist/src/config.js, but this generation pass only watches the app config plus route, admin-nav, and content module files. Because the resolved plugin config module that supplied plugins is never added to the watched set, that rebuild does not request regeneration and package-messages.gen.ts remains stale until the app config is touched or the dev server is restarted. Resolve and watch each configured plugin's config module alongside the other projection inputs.

Useful? React with 👍 / 👎.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 5b821559c6

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +13 to +15
pl: {
'@vitnode/blog': async () => await import('./@vitnode/blog/pl.json'),
'@vitnode/core': async () => await import('./@vitnode/core/pl.json'),

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Register the moved Polish messages in the standalone API

In the split deployment, apps/api/src/i18n.ts still enables pl while leaving messages empty, and this commit removes the Polish loader from core's API locale barrel. The replacement loader added here is imported only by apps/web/src/vitnode.api.config.ts, so requests and emails served by the standalone apps/api process now fall back to English for Polish users; register these moved messages in that API config as well.

Useful? React with 👍 / 👎.

Comment on lines +224 to +227
export const pluginApiClientTemplate = (): string =>
`import type { ApiClient } from "@vitnode/core/tanstack/fetcher";

import { createApiClient } from "@vitnode/core/tanstack/fetcher";

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Generate direct universal fetcher calls

Replace this scaffolded ApiClient wrapper with a lightweight clientModule<typeof helloModule>(CONFIG_PLUGIN.pluginId) reference and call the universal fetcher inline in the loader. As written, every generated plugin starts with the legacy stored-client abstraction and an explicitly annotated API value, contrary to the repository's required transport pattern and inference boundary.

AGENTS.md reference: AGENTS.md:L35-L40

Useful? React with 👍 / 👎.

…tion check

feat(router): ✨ add support for blank routes in the router configuration

feat(helpers): ✨ introduce `runPackageScript` to manage package scripts execution

feat(plugin): ✨ implement plugin build and restart logic for development servers

test(restart-dev-servers): 🧪 add comprehensive tests for dev server restart functionality

feat(breadcrumb): ✨ introduce deferred breadcrumbs for dynamic route handling

feat(plugin-routes): ✨ enhance plugin route handling with blank area support

feat(example-plugin): ✨ add example plugin routes and embed page for demonstration
@aXenDeveloper
aXenDeveloper merged commit f5d0b24 into canary Sep 14, 2026
3 of 4 checks passed
@aXenDeveloper
aXenDeveloper deleted the perf/plugin_install_and_config branch September 14, 2026 13:13

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 9a1b672459

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

import { pageHead } from '@vitnode/core/tanstack/metadata'
import { Suspense } from 'react'

import { DocsError, DocsNotFound } from '@/docs/error-views'

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Keep error screens out of the route topology

Move the newly added error and not-found presentation behind the TanStack adapter rather than importing app views into this route. The repository requires route files to contain topology only and keeps screens in @vitnode/core/tanstack/*; directly wiring DocsError and DocsNotFound here extends the existing coupling and makes future error-screen changes require editing the route definition itself.

AGENTS.md reference: AGENTS.md:L27-L27

Useful? React with 👍 / 👎.

"icon": "Plug",
"defaultOpen": true,
"pages": ["create", "routes", "api", "admin", "breadcrumbs", "..."]
"pages": ["create", "routes", "breadcrumbs", "api", "admin", "..."]

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Point the plugin sidebar at the moved routing pages

After this commit deletes dev/plugins/routes.mdx and dev/plugins/breadcrumbs.mdx, these two sidebar entries still resolve to /docs/dev/plugins/routes and /docs/dev/plugins/breadcrumbs, so selecting either one reaches the not-found screen. Their replacements now live at dev/routing/routes.mdx and dev/routing/breadcrumbs.mdx; update the navigation and remaining inbound links, or retain redirects for the old URLs.

Useful? React with 👍 / 👎.

"pages": [
"routes",
"navigation",
"metadata",

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Remove or restore the missing metadata page

When the Routing sidebar is rendered, this entry advertises dev/routing/metadata.mdx, but that file is deleted in the same commit and no replacement exists at that slug. Clicking Metadata therefore leads to a 404; either restore the page, point this entry to the section that absorbed its content, or add a redirect.

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

💡 Feature A new feature

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant