Skip to content

refactor(sdk)!: move TailorDB erdSite config into the ERD plugin's own configuration#1811

Open
toiroakr wants to merge 9 commits into
v2from
fix/erd-plugin
Open

refactor(sdk)!: move TailorDB erdSite config into the ERD plugin's own configuration#1811
toiroakr wants to merge 9 commits into
v2from
fix/erd-plugin

Conversation

@toiroakr

@toiroakr toiroakr commented Jul 19, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Remove the plugin-only erdSite field from the core TailorDB service config schema. Core (tailor deploy / generate) never read it; the external ERD CLI plugin was its sole consumer, so the setting moves to the standard plugin configuration surface.
  • Add tailordbErdPlugin({ sites }) to @tailor-platform/sdk-plugin-tailordb-erd (imported from the package root; the CLI bin moved to its own entry) as a definePlugins()-compatible configuration carrier. The tailor tailordb erd commands resolve deploy targets from it.
  • Cross-validate the configuration when the config is loaded: each sites key must be an owned namespace in config.db, and each value must match a static website defined in staticWebsites. Mismatches are fatal for erd deploy and warnings for erd export / serve, so typos surface early instead of at deploy time. The old .describe() text that mislabeled the value as a "URL" is gone with the field.
  • Extend loadTailorDBNamespaces() to also return the config module's registered plugins and pass them to namespace selector callbacks, so external CLI plugins can read their own definePlugins() configuration.
  • Add the v2/erd-site-to-plugin codemod (registered with prereleaseUntil: V2_NEXT_PENDING) that removes db.<namespace>.erdSite entries and appends tailordbErdPlugin({ sites: { <namespace>: <value> } }) to an existing definePlugins() call (or creates the plugins export), including the imports. Non-literal configs are flagged for LLM-assisted review.
  • Build the ERD plugin package in the shared install-deps CI action, since loading the example config now requires its dist output.
  • Update example/tailor.config.ts, the plugin README, and the generated migration docs; add changesets (sdk: major, sdk-plugin-tailordb-erd: minor, sdk-codemod: patch).

Breaking Changes

db.<namespace>.erdSite is no longer accepted in tailor.config.ts (strict schema parse error). Configure the ERD deploy target on the plugin instead:

import { tailordbErdPlugin } from "@tailor-platform/sdk-plugin-tailordb-erd";

export const plugins = definePlugins(
  // TailorDB namespace name → static website name
  tailordbErdPlugin({ sites: { tailordb: "my-erd-site" } }),
);

The v2/erd-site-to-plugin codemod migrates existing configs automatically.

…sites })

Remove the plugin-only erdSite field from the core TailorDB service schema.
The ERD deploy target is now configured on the ERD plugin itself via
tailordbErdPlugin({ sites }) from @tailor-platform/sdk-plugin-tailordb-erd/plugin,
registered through definePlugins(). The ERD commands validate each namespace
against config.db and each site name against staticWebsites at config load.

loadTailorDBNamespaces() now returns the config module's registered plugins and
passes them to namespace selector callbacks so external CLI plugins can read
their own definePlugins() configuration.

Adds the v2/erd-site-to-plugin codemod (prereleaseUntil: V2_NEXT_PENDING) that
rewrites db.<namespace>.erdSite entries into a definePlugins() entry.
@changeset-bot

changeset-bot Bot commented Jul 19, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 3321c78

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 4 packages
Name Type
@tailor-platform/sdk Major
@tailor-platform/sdk-plugin-tailordb-erd Major
@tailor-platform/sdk-codemod Patch
@tailor-platform/create-sdk Major

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@pkg-pr-new

pkg-pr-new Bot commented Jul 19, 2026

Copy link
Copy Markdown

Open in StackBlitz

pnpm add https://pkg.pr.new/@tailor-platform/create-sdk@3321c78
pnpm add https://pkg.pr.new/@tailor-platform/eslint-plugin-sdk@3321c78
pnpm add https://pkg.pr.new/@tailor-platform/sdk@3321c78
pnpm add https://pkg.pr.new/@tailor-platform/sdk-plugin-tailordb-erd@3321c78

commit: 3321c78

@github-actions

github-actions Bot commented Jul 19, 2026

Copy link
Copy Markdown

🗺️ ERD preview

Self-contained ERD viewer HTML built for this run. Each viewer can switch between the current schema and a diff against base branch v2.

example/tailor.config.ts now imports @tailor-platform/sdk-plugin-tailordb-erd/plugin,
which resolves to the package's dist output. Jobs that load the example config
(generate, deploy, migration, runtime performance) previously only built
@tailor-platform/sdk and failed with ERR_MODULE_NOT_FOUND.
@github-actions

This comment has been minimized.

This comment was marked as resolved.

Wrap the erd-site-to-plugin codemod name in backticks so the <namespace>
placeholder is not swallowed as an HTML tag in the rendered migration doc
heading, and mention definePlugins() in the explicit-namespace error message
so it matches the all-namespaces variant.
@github-actions

This comment has been minimized.

This comment was marked as off-topic.

Move the CLI bin entry to dist/cli.js and make dist/index.js the plugin
module, so the config plugin is imported as
@tailor-platform/sdk-plugin-tailordb-erd instead of a /plugin subpath.
The package root was previously not importable (bin-only, no exports),
so the root export is new surface rather than a change.
@github-actions

This comment has been minimized.

This comment was marked as resolved.

@toiroakr
toiroakr marked this pull request as ready for review July 19, 2026 13:57
@toiroakr
toiroakr requested review from a team as code owners July 19, 2026 13:57
import type { Edit, SgNode } from "@ast-grep/napi";

const PLUGIN_IMPORT =
'import { tailordbErdPlugin } from "@tailor-platform/sdk-plugin-tailordb-erd";';

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

How is the required package dependency surfaced for v1 projects, given that a clean transform adds this import, leaves no residual prompt, and makes config loading fail with ERR_MODULE_NOT_FOUND when the plugin is absent?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Addressed in 5782d6f: migrated configs are now flagged for LLM review (suspiciousPatterns includes tailordbErdPlugin), and the codemod description/prompt state upfront that the package must be installed as a dev dependency — otherwise config loading fails with ERR_MODULE_NOT_FOUND.

const valueNode = erdPair?.field("value");
if (!erdPair || !valueNode) continue;

siteEntries.push(`${nsKey.text()}: ${valueNode.text()}`);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

When defineConfig() is called inside a factory, this moves an erdSite expression that references a parameter or local into the module-level plugins export, leaving that binding out of scope and making the migrated config unloadable.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fixed in 5782d6f: defineConfig() calls inside functions are now skipped entirely, so an erdSite value referencing a parameter or local is never hoisted. Factory configs go to LLM review with guidance to keep referenced bindings in scope (factory-config fixture added).

const closeIndent = multiline[2] ?? "";
const head = callText.slice(0, callText.length - multiline[0].length);
const hasArgs = !/\(\s*$/.test(head);
return `${head}${hasArgs ? "," : ""}\n${closeIndent} ${arg},\n${closeIndent})`;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

If the last multiline definePlugins() argument has no trailing comma and is followed by a // comment, the inserted comma lands inside that comment, so the codemod emits invalid TypeScript.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fixed in 5782d6f: argument insertion now derives offsets from the argument-list AST nodes (last argument / existing comma token) instead of string surgery, so a trailing line comment can no longer swallow the separating comma (comment-arg fixture added).

let result = tree.commitEdits(edits);

const importLines = [PLUGIN_IMPORT];
if (!pluginsCall && !/import\s*\{[^}]*\bdefinePlugins\b/.test(result)) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

With definePlugins as makePlugins, this check treats the original name as locally bound and then emits a new definePlugins(...) call that has no binding.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fixed in 5782d6f: the local binding of definePlugins is now resolved from the sdk import specifier (honoring aliases), so the aliased call is extended instead of emitting an unbound definePlugins reference (aliased-define-plugins fixture added).

Comment thread packages/sdk-codemod/src/registry.ts Outdated
legacyPatterns: ["erdSite:"],
// Property-key shapes only, so an unrelated `erdSite` variable (e.g. a
// defineStaticWebSite binding) is not re-flagged after a clean transform.
suspiciousPatterns: ["erdSite:", /\berdSite\s*[,}]/],

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Quoted keys such as "erdSite" in a dynamic db object are masked before these residual patterns run, so the codemod leaves the removed field in place while reporting no warning or LLM review.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fixed in 5782d6f: added sourceStringLegacyPatterns / sourceStringSuspiciousPatterns for erdSite, so quoted keys that survive masking only as string fragments are still reported both as a residual warning and for LLM review.

@dqn dqn assigned toiroakr and unassigned dqn Jul 20, 2026
…e cases

- Skip defineConfig() calls inside functions: hoisting an erdSite value that
  references a parameter or local into a module-level definePlugins() export
  would leave the binding out of scope. Factory configs go to LLM review.
- Append arguments via AST offsets so a trailing line comment after the last
  definePlugins() argument cannot swallow the separating comma.
- Resolve the local binding of definePlugins from the sdk import so an
  aliased import (definePlugins as makePlugins) extends the aliased call
  instead of emitting an unbound definePlugins reference.
- Detect quoted "erdSite" keys via sourceString legacy/suspicious patterns;
  masking previously hid them from residual matching entirely.
- Flag migrated configs (tailordbErdPlugin) for LLM review and state in the
  description/prompt that the plugin package must be installed as a dev
  dependency, since a clean transform otherwise surfaced the new dependency
  only as ERR_MODULE_NOT_FOUND at config load.
@github-actions

This comment has been minimized.

This comment was marked as resolved.

… property

removePairEdit previously removed only the separating comma, leaving a
comment that documented the removed property orphaned on its own line.
@github-actions

This comment has been minimized.

This comment was marked as resolved.

…rgument

appendArgEdit inserted the new definePlugins argument before a comment on
the last argument's line, moving the comment onto the inserted line. The
separating comma still goes right after the last argument; the new argument
now goes after the same-line comment.
@github-actions

This comment has been minimized.

This comment was marked as resolved.

With requireErdSite, an invalid tailordbErdPlugin({ sites }) entry for an
unrelated namespace no longer blocks deploying an explicitly targeted valid
one; such issues degrade to warnings. resolveErdSites now returns structured
{ namespace, message } issues so callers can scope what is fatal. Also
reword the LoadedTailorDBNamespaces.plugins docstring: loadConfig collects
plugins from any matching array export, not only definePlugins().
@github-actions

This comment has been minimized.

This comment was marked as resolved.

…e changeset example

removePairEdit now consumes a same-line // comment when removing an erdSite
property that has no trailing comma (the leading-comma path), so the comment
no longer dangles on the previous property. The changeset example now imports
definePlugins so the snippet compiles as written.
@github-actions

Copy link
Copy Markdown

Code Metrics Report (packages/sdk)

main (6933803) #1811 (032344d) +/-
Coverage 74.6% 77.0% +2.4%
Code to Test Ratio 1:0.4 1:0.4 +0.0
Details
  |                    | main (6933803) | #1811 (032344d) |  +/-  |
  |--------------------|----------------|-----------------|-------|
+ | Coverage           |          74.6% |           77.0% | +2.4% |
  |   Files            |            458 |             443 |   -15 |
  |   Lines            |          17049 |           16478 |  -571 |
- |   Covered          |          12719 |           12703 |   -16 |
+ | Code to Test Ratio |          1:0.4 |           1:0.4 |  +0.0 |
  |   Code             |         114318 |          115443 | +1125 |
+ |   Test             |          53379 |           54874 | +1495 |

Code coverage of files in pull request scope (77.7% → 84.9%)

Details
Files Coverage +/- Status
packages/sdk-codemod/src/registry.ts 0.0% -60.0% modified
packages/sdk-plugin-tailordb-erd/src/export.ts 0.0% -4.4% modified
packages/sdk-plugin-tailordb-erd/src/local-schema.ts 0.0% -25.0% modified
packages/sdk/example/tailordb/user.ts 0.0% -100.0% affected
packages/sdk/llm-challenge/src/types.ts 0.0% -100.0% affected
packages/sdk/packages/sdk-plugin-tailordb-erd/src/diff-command.ts 0.0% -71.0% affected
packages/sdk/packages/sdk-plugin-tailordb-erd/src/diff.ts 0.0% -89.5% affected
packages/sdk/packages/sdk-plugin-tailordb-erd/src/serve.ts 0.0% -18.8% affected
packages/sdk/packages/sdk-plugin-tailordb-erd/src/viewer.ts 0.0% -82.8% affected
packages/sdk/src/cli/commands/auth/index.ts 100.0% +100.0% affected
packages/sdk/src/cli/commands/auth/token.ts 33.3% +33.3% affected
packages/sdk/src/cli/commands/deploy/test_fixtures/prepare.ts 90.9% -2.5% affected
packages/sdk/src/cli/commands/deploy/test_fixtures/tailor.config.generators-compat.ts 0.0% -100.0% affected
packages/sdk/src/cli/commands/deploy/test_fixtures/tailor.config.plugins-compat.ts 0.0% -100.0% affected
packages/sdk/src/cli/commands/deploy/auth-connection.ts 94.3% -1.3% affected
packages/sdk/src/cli/commands/deploy/auth-invoker.ts 0.0% -100.0% affected
packages/sdk/src/cli/commands/deploy/deploy.ts 89.9% +84.6% affected
packages/sdk/src/cli/commands/deploy/executor.ts 83.8% +2.0% affected
packages/sdk/src/cli/commands/deploy/function-registry.ts 90.8% -0.2% affected
packages/sdk/src/cli/commands/deploy/invoker.ts 100.0% +100.0% affected
packages/sdk/src/cli/commands/deploy/secret-manager.ts 96.9% -0.3% affected
packages/sdk/src/cli/commands/deploy/secrets-state.ts 91.6% +10.8% affected
packages/sdk/src/cli/commands/deploy/tailordb/index.ts 87.8% -0.3% affected
packages/sdk/src/cli/commands/function/logs.ts 39.7% -4.6% affected
packages/sdk/src/cli/commands/function/test-run.ts 56.8% -3.4% affected
packages/sdk/src/cli/commands/generate/service.ts 69.3% +1.3% affected
packages/sdk/src/cli/commands/login.ts 82.9% -0.9% affected
packages/sdk/src/cli/commands/plugin/index.ts 50.0% +50.0% affected
packages/sdk/src/cli/commands/plugin/list.ts 6.6% +6.6% affected
packages/sdk/src/cli/commands/profile/create.ts 77.2% +72.7% affected
packages/sdk/src/cli/commands/profile/update.ts 92.3% +0.2% affected
packages/sdk/src/cli/commands/skills/install.ts 0.0% -57.2% affected
packages/sdk/src/cli/commands/tailordb/migrate/db-types-generator.ts 95.8% -1.4% affected
packages/sdk/src/cli/commands/tailordb/migrate/diff-calculator.ts 72.9% -0.8% affected
packages/sdk/src/cli/commands/tailordb/migrate/snapshot-manifest.ts 61.7% -0.3% affected
packages/sdk/src/cli/commands/tailordb/migrate/snapshot.ts 80.2% -1.1% affected
packages/sdk/src/cli/commands/user/switch.ts 88.2% +0.7% affected
packages/sdk/src/cli/commands/workflow/start.ts 83.6% +12.5% affected
packages/sdk/src/cli/commands/workspace/create.ts 89.0% +0.2% affected
packages/sdk/src/cli/crashreport/report.ts 88.0% +2.2% affected
packages/sdk/src/cli/index.ts 50.0% -50.0% affected
packages/sdk/src/cli/query/type-field-order.ts 86.6% +86.6% affected
packages/sdk/src/cli/services/application.ts 84.3% +3.3% affected
packages/sdk/src/cli/services/executor/loader.ts 84.6% +1.2% affected
packages/sdk/src/cli/services/stale-cleanup.ts 0.0% -91.0% affected
packages/sdk/src/cli/services/tailordb/hooks-validate-bundler.ts 85.7% -1.0% affected
packages/sdk/src/cli/services/workflow/service.ts 83.7% +3.7% affected
packages/sdk/src/cli/services/workflow/start-transformer.ts 87.5% +87.5% affected
packages/sdk/src/cli/services/workflow/trigger-transformer.ts 0.0% -88.9% affected
packages/sdk/src/cli/shared/auth-namespace.ts 100.0% +100.0% affected
packages/sdk/src/cli/shared/builtin-commands.ts 100.0% +100.0% affected
packages/sdk/src/cli/shared/config-loader.ts 77.4% -6.9% affected
packages/sdk/src/cli/shared/context.ts 94.5% +15.1% affected
packages/sdk/src/cli/shared/plugin.ts 85.8% +85.8% affected
packages/sdk/src/cli/shared/register-ts-hook.ts 100.0% +100.0% affected
packages/sdk/src/cli/shared/register-tsconfig-paths-hook.ts 0.0% -100.0% affected
packages/sdk/src/cli/shared/register-typescript-runtime.ts 0.0% -100.0% affected
packages/sdk/src/cli/shared/skills-installer.ts 0.0% -93.4% affected
packages/sdk/src/cli/shared/start-context.ts 82.6% +82.6% affected
packages/sdk/src/cli/shared/test-helpers/concurrency-probe.ts 0.0% -100.0% affected
packages/sdk/src/cli/shared/trigger-context.ts 0.0% -82.7% affected
packages/sdk/src/cli/ts-hook.mjs 92.3% +92.3% affected
packages/sdk/src/cli/tsconfig-paths-hook.mjs 0.0% -96.0% affected
packages/sdk/src/configure/services/auth/index.ts 100.0% +25.0% affected
packages/sdk/src/configure/services/staticwebsite/index.ts 100.0% +100.0% affected
packages/sdk/src/configure/services/tailordb/schema.ts 96.6% +7.6% affected
packages/sdk/src/configure/services/workflow/job.ts 90.0% +4.2% affected
packages/sdk/src/configure/services/workflow/registry.ts 100.0% +9.0% affected
packages/sdk/src/configure/services/workflow/test-env-key.ts 100.0% +6.6% affected
packages/sdk/src/configure/services/workflow/workflow.ts 66.6% -13.4% affected
packages/sdk/src/parser/service/auth/schema.ts 92.6% +4.8% affected
packages/sdk/src/parser/service/executor/schema.ts 92.3% +1.3% affected
packages/sdk/src/parser/service/tailordb/builder-helpers.ts 100.0% +100.0% affected
packages/sdk/src/parser/service/tailordb/field.ts 83.8% -16.2% affected
packages/sdk/src/parser/service/tailordb/relation.ts 92.0% -0.6% affected
packages/sdk/src/parser/service/tailordb/schema.ts 85.2% 0.0% modified
packages/sdk/src/parser/service/tailordb/type-script.ts 100.0% +100.0% affected
packages/sdk/src/plugin/builtin/kysely-type/type-processor.ts 91.9% +0.1% affected
packages/sdk/src/plugin/builtin/seed/index.ts 0.0% -1.6% affected
packages/sdk/src/utils/test/index.ts 95.0% -5.0% affected
packages/sdk/src/vitest/mocks/file.ts 92.5% +7.4% affected
packages/sdk/src/vitest/mocks/workflow.ts 91.2% -0.3% affected
packages/sdk/src/vitest/workflow-local.ts 77.1% +77.1% affected
packages/sdk/src/vitest/workflow-runtime.ts 70.0% +12.8% affected

SDK Configure Bundle Size

main (6933803) #1811 (032344d) +/-
configure-index-size 32.17KB 31.26KB -0.91KB
dependency-chunks-size 29.88KB 24.97KB -4.91KB
total-bundle-size 62.05KB 56.22KB -5.83KB

Runtime Performance

main (6933803) #1811 (032344d) +/-
Generate Median 3,107ms 2,554ms -553ms
Generate Max 3,181ms 2,571ms -610ms
Apply Build Median 3,160ms 2,603ms -557ms
Apply Build Max 3,185ms 2,620ms -565ms

Type Performance (instantiations)

main (6933803) #1811 (032344d) +/-
tailordb-basic 43,881 40,190 -3,691
tailordb-optional 4,451 4,535 84
tailordb-relation 6,220 3,854 -2,366
tailordb-validate 753 666 -87
tailordb-hooks 5,279 5,499 220
tailordb-object 12,547 16,345 3,798
tailordb-enum 1,486 1,538 52
resolver-basic 9,252 12,107 2,855
resolver-nested 26,119 35,406 9,287
resolver-array 18,059 24,043 5,984
executor-schedule 4,310 4,481 171
executor-webhook 949 1,120 171
executor-record 6,762 4,532 -2,230
executor-resolver 4,090 5,777 1,687
executor-operation-function 937 1,108 171
executor-operation-gql 945 1,116 171
executor-operation-webhook 956 1,127 171
executor-operation-workflow 1,798 1,921 123

Reported by octocov

@toiroakr toiroakr assigned dqn and unassigned toiroakr Jul 21, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants