feat(compat): add /server/zod-schemas subpath re-exporting *Schema constants#1906
feat(compat): add /server/zod-schemas subpath re-exporting *Schema constants#1906felixweinberger wants to merge 2 commits intomainfrom
Conversation
🦋 Changeset detectedLatest commit: e8a7dcf The changes in this PR will be included in the next version bump. This PR includes changesets to release 5 packages
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 |
@modelcontextprotocol/client
@modelcontextprotocol/server
@modelcontextprotocol/express
@modelcontextprotocol/fastify
@modelcontextprotocol/hono
@modelcontextprotocol/node
commit: |
8c9a388 to
ab8b2ed
Compare
ab8b2ed to
54f3063
Compare
|
@claude review |
There was a problem hiding this comment.
Beyond the inline nits: docs/migration-SKILL.md:101 still states Zod schemas "are no longer part of the public API" and points users at type guards instead — that prose now contradicts this subpath and should mention /zod-schemas as the v1-compat option. Also worth confirming whether @modelcontextprotocol/client should get the same subpath, since v1's types.js served both sides.
Extended reasoning...
Overview
Adds a new public subpath @modelcontextprotocol/server/zod-schemas that re-exports ~150 Zod schema constants (plus OAuth/auth schemas from core) as a v1→v2 compat shim. Touches core/package.json (new ./schemas export on the private core package), server/package.json exports map, a new zodSchemas.ts entry, tsdown/tsconfig/typedoc plumbing, a compat test, and a changeset.
Security risks
None — pure re-exports of existing internal constants; no new logic, auth, or I/O paths.
Level of scrutiny
Moderate-to-high. Per REVIEW.md, "every new export is intentional" and "burden of proof is on addition" — this is a deliberate public-API-surface expansion (an entire subpath), even if framed as deprecated. A maintainer should sign off on the surface shape, especially given the export * pulls in three non-v1 helper functions (getResultSchema/getRequestSchema/getNotificationSchema) and the changeset only promises *Schema constants.
Other factors
docs/migration-SKILL.md:101anddocs/migration.md(around L447–503) currently tell users Zod schemas are gone and to use type guards /specTypeSchema; that guidance now needs a pointer to this compat subpath (REVIEW.md "flag prose that now contradicts the implementation").- v1's
@modelcontextprotocol/sdk/types.jswas consumed by client-side code too (e.g., validatingCallToolResult), but only the server package gets the subpath here — may be intentional, but worth an explicit call. - Core package is
private: trueand bundled vianoExternal, so the new./schemascore export doesn't leak externally — that part is fine. - Test coverage is minimal (instanceof + one parse) but adequate for a re-export shim.
a860d7e to
f7e391b
Compare
|
Re the review-body points: @claude review |
|
Claude finished @felixweinberger's task in 2m 37s —— View job Review
The previous nits were all addressed appropriately. One documentation gap remains; a couple of minor points below. 🔴
|
Re-exports the internal *Schema Zod constants (CallToolRequestSchema, JSONRPCMessageSchema, etc.) from a deprecated /zod-schemas subpath so v1 code that imported schemas from @modelcontextprotocol/sdk/types.js has a single drop-in target. - packages/server/src/zodSchemas.ts: re-export barrel (deprecated module) - packages/server/package.json: ./zod-schemas exports entry - packages/server/tsdown.config.ts: build entry + dts path mapping - packages/server/tsconfig.json: path mappings for core/schemas and the self-reference subpath - packages/core/package.json: internal ./schemas subpath (core is private, consumed only by sibling packages) - compat test asserting the import resolves and schemas parse The schemas remain an internal implementation detail; their Zod major version is not covered by semver. Subpath will be removed in v3.
f7e391b to
e77d678
Compare
|
Claude finished @felixweinberger's task in 1m 15s —— View job Review
All three issues from the previous review are resolved. The implementation is clean. ✅
|
… specTypeSchemas/isSpecType
|
We should be able to achieve this effect by:
This should remove the necessity to keep exporting zod schemas? |
| export { | ||
| /** @deprecated Use {@linkcode JSONRPCErrorResponseSchema}. */ | ||
| JSONRPCErrorResponseSchema as JSONRPCErrorSchema, | ||
| /** @deprecated Use {@linkcode ResourceTemplateReferenceSchema}. */ | ||
| ResourceTemplateReferenceSchema as ResourceReferenceSchema | ||
| } from '@modelcontextprotocol/core/schemas'; |
There was a problem hiding this comment.
🔴 The export * carries v2's JSONRPCResponseSchema (a union of result and error responses) under the same name v1 used for the result-only schema, so v1 code doing JSONRPCResponseSchema.parse(msg) at a transport boundary will now silently accept {jsonrpc, id, error} payloads as valid. This is the schema-constant twin of the isJSONRPCResponse flip already called out at migration.md:505 — add JSONRPCResultResponseSchema as JSONRPCResponseSchema to this alias block (the explicit named export shadows the wildcard) and add the JSONRPCResponseSchema → JSONRPCResultResponseSchema row to the removed-aliases tables in both migration docs.
Extended reasoning...
What changed semantically
In v1 (@modelcontextprotocol/sdk@1.20.2, src/types.ts:99-105), JSONRPCResponseSchema was z.object({jsonrpc, id, result}).strict() with the docstring "A successful (non-error) response to a request." — it required result, and .strict() rejected an error key. v1 had no JSONRPCResultResponseSchema; JSONRPCResponseSchema was the canonical success-response schema.
In v2 (packages/core/src/types/schemas.ts:187), the v1 schema was renamed to JSONRPCResultResponseSchema (line 148, same docstring), and a new JSONRPCResponseSchema was introduced as z.union([JSONRPCResultResponseSchema, JSONRPCErrorResponseSchema]) — it now matches both result and error responses. The migration guide already documents exactly this flip for the type guard at migration.md:505 (isJSONRPCResponse → isJSONRPCResultResponse), and guards.ts:71 shows isJSONRPCResponse is implemented as JSONRPCResponseSchema.safeParse(...) — so the schema flipped the same way the guard did.
How the shim leaks the wider schema
zodSchemas.ts:13 does export * from '@modelcontextprotocol/core/schemas', which carries v2's union JSONRPCResponseSchema under the unchanged v1 name. The alias block at lines 32-37 already shadows the wildcard for two sibling renames (JSONRPCErrorResponseSchema as JSONRPCErrorSchema, ResourceTemplateReferenceSchema as ResourceReferenceSchema) but does not add JSONRPCResultResponseSchema as JSONRPCResponseSchema. Per ESM semantics an explicit named export would shadow the same name from export *, so the omission means consumers get the v2 union.
Why nothing catches it
The compat test (zod-schemas.compat.test.ts) only checks instanceof z.ZodType and a CallToolRequestSchema.parse; it never exercises the JSON-RPC envelope schemas. The migration guide's removed-aliases tables (migration.md:492-501, migration-SKILL.md:84-99) list isJSONRPCResponse → isJSONRPCResultResponse but omit the parallel JSONRPCResponseSchema → JSONRPCResultResponseSchema row, so a migrating user has no warning. Because the v2 schema is a strict superset of the v1 schema, nothing fails at compile time and the happy path (result responses) parses identically — the divergence only surfaces when an error response arrives.
Step-by-step proof
- v1 consumer has a custom transport doing
const ok = JSONRPCResponseSchema.safeParse(raw); if (ok.success) handleResult(ok.data.result); else handleError(raw);— under v1,ok.success⇒raw.resultexists (.strict()+ requiredresult). - They follow this PR's migration guidance and point the import at
@modelcontextprotocol/server/zod-schemas(or, once feat(sdk): @modelcontextprotocol/sdk meta-package with v1 deep-import subpaths #1913 lands, leave it atsdk/types.js). export *at line 13 bindsJSONRPCResponseSchemato v2'sz.union([JSONRPCResultResponseSchema, JSONRPCErrorResponseSchema]).- Server returns
{"jsonrpc":"2.0","id":1,"error":{"code":-32603,"message":"Internal error"}}. - v1 schema:
.parse()throws /.safeParse().success === false(noresult, extraerrorkey under.strict()). - v2 schema via this shim:
.safeParse().success === true(matches theJSONRPCErrorResponseSchemaarm of the union). handleResult(ok.data.result)runs withundefined; the error is swallowed.
Impact
This is the PR's stated target use case ("runtime validation at HTTP boundaries… custom transports"), and the changeset promises "v1 imports work unchanged." Same-name/silently-wider-acceptance is the worst failure mode for that promise: unlike a missing export, nothing fails — error responses pass validation as success and downstream code reads .result on an error payload. The repo already considered this footgun serious enough to give isJSONRPCResponse its own callout box in the migration guide; the schema constant deserves the same treatment.
Fix
Add to the alias block at lines 32-37:
export {
/** @deprecated Use {@linkcode JSONRPCErrorResponseSchema}. */
JSONRPCErrorResponseSchema as JSONRPCErrorSchema,
/** @deprecated Use {@linkcode ResourceTemplateReferenceSchema}. */
ResourceTemplateReferenceSchema as ResourceReferenceSchema,
/** @deprecated Use {@linkcode JSONRPCResultResponseSchema}. v2's `JSONRPCResponseSchema` now matches both result and error responses. */
JSONRPCResultResponseSchema as JSONRPCResponseSchema
} from '@modelcontextprotocol/core/schemas';And add JSONRPCResponseSchema → JSONRPCResultResponseSchema (and JSONRPCResponse → JSONRPCResultResponse for the type) to the removed-aliases tables in docs/migration.md and docs/migration-SKILL.md, alongside the existing isJSONRPCResponse row.
There was a problem hiding this comment.
Checked this against v1.25.2, v1.26.0, and v1.29.0 — JSONRPCResponseSchema is already z.union([JSONRPCResultResponseSchema, JSONRPCErrorResponseSchema]) at all three (src/types.ts:257-258). The result-only form cited above is from v1.20.2; the schema flipped mid-v1, not at v1→v2. So the shim's export * carrying the union matches latest v1 exactly, and aliasing JSONRPCResultResponseSchema as JSONRPCResponseSchema here would actually diverge from v1.29.0.
The guard isJSONRPCResponse did change semantics v1→v2 (v1.29.0:186 has export const isJSONRPCResponse = isJSONRPCResultResponse as a deprecated result-only alias), which migration.md:503 already documents — but /zod-schemas doesn't re-export guards.
The two 🟡 below (migration.md:896 stale "All Zod schemas" line, and the OAuth-block @deprecated pointing at spec-type-only specTypeSchemas) do look real and worth a quick fixup; my approve stands with those as non-blocking nits.
| | `AuthInfo` (from `server/auth/types.js`) | `AuthInfo` (now re-exported by `@modelcontextprotocol/client` and `@modelcontextprotocol/server`) | | ||
|
|
||
| All other types and schemas exported from `@modelcontextprotocol/sdk/types.js` retain their original names — import them from `@modelcontextprotocol/client` or `@modelcontextprotocol/server`. | ||
| All other **type** symbols from `@modelcontextprotocol/sdk/types.js` retain their original names — import them from `@modelcontextprotocol/client` or `@modelcontextprotocol/server`. **Zod schemas** (e.g., `CallToolRequestSchema`) are not re-exported from the package roots; for runtime validation prefer the `isSpecType` / `specTypeSchemas` Records, or for v1 source compatibility import them from `@modelcontextprotocol/server/zod-schemas`. |
There was a problem hiding this comment.
🟡 This PR rewrote line 503 (and migration-SKILL.md:101) to clarify that Zod schema constants are not at the package roots and live at @modelcontextprotocol/server/zod-schemas — but the same two files still say the opposite further down: migration.md:896 ("All Zod schemas and type definitions from types.ts" under Unchanged APIs — only the import paths changed) and migration-SKILL.md:206-207 ("Unchanged APIs … all Zod schemas"). A reader following those sections will map sdk/types.js → package root per the §3 table and hit TS2305. Suggest dropping "Zod schemas and" from migration.md:896 (or pointing at the /zod-schemas subpath), and dropping "all Zod schemas," from migration-SKILL.md:207.
Extended reasoning...
What's stale
This PR's purpose is to document where Zod schema constants live in v2. It rewrote two lines to that end:
- docs/migration.md:503 — now reads: "Zod schemas (e.g.,
CallToolRequestSchema) are not re-exported from the package roots; … import them from@modelcontextprotocol/server/zod-schemas." - docs/migration-SKILL.md:101 — now reads: "Zod schemas … are not exported from the package root; … available from the
@modelcontextprotocol/server/zod-schemassubpath."
But each file has a second occurrence of the same claim that the PR didn't touch:
- docs/migration.md:896 — under
## Unchanged APIswhose lead-in is "The following APIs are unchanged between v1 and v2 (only the import paths changed)", the bullet still reads: "All Zod schemas and type definitions fromtypes.ts(except the aliases listed above)". - docs/migration-SKILL.md:206-207 — "Unchanged APIs (only import paths changed): …
StdioServerTransport, all Zod schemas, all callback return types."
Both leftover passages list Zod schemas alongside Client, McpServer, StdioServerTransport, etc. — every other item in those lists moved to a package root. The §3 import-mapping table for @modelcontextprotocol/sdk/types.js also points at the package root. So a reader applying "Zod schemas → unchanged, only import path changed → use the §3 mapping" lands on @modelcontextprotocol/server, which is exactly the misconception line 503 was rewritten to dispel.
Why nothing catches it
Both files are prose markdown; no link-checker or symbol-checker validates API names mentioned in them. CI is green. The author updated one occurrence in each file (responding to earlier bot review of line 503) but missed the second occurrence further down — a classic §Completeness leftover ("grep for surviving instances of the old form").
Step-by-step proof (migration.md)
- A v1 consumer reads
docs/migration.mdtop-to-bottom and reaches## Unchanged APIs(line 889). - The lead-in says "only the import paths changed"; line 896 lists "All Zod schemas and type definitions from
types.ts" alongsideClient, transports, andStdioServerTransport. - Every sibling bullet in that list resolves via the §Package-split mapping (
sdk/types.js→@modelcontextprotocol/clientor@modelcontextprotocol/server). - Consumer writes
import { CallToolRequestSchema } from '@modelcontextprotocol/server'. packages/server/src/index.tsdoes not re-exportCallToolRequestSchema(onlyzodSchemas.tsdoes, behind the./zod-schemassubpath added in this PR) → TS2305 "Module has no exported member 'CallToolRequestSchema'".- This is precisely the failure mode the 2026-04-16 bot review flagged on line 503 ("A consumer reading migration.md will try
import { CallToolRequestSchema } from '@modelcontextprotocol/server'and get a type error") and that the PR fixed at 503 — line 896 is the surviving instance.
The same walk-through applies to migration-SKILL.md, which is designed to be loaded into an LLM for mechanical migration; an automated rewrite that pattern-matches "all Zod schemas → only import path changed → apply §3 table" will produce the broken import.
Addressing the refutation (migration-SKILL.md only)
One verifier argued that for migration-SKILL.md specifically, the PR resolved rather than created a contradiction: pre-PR line 101 said schemas were "no longer part of the public API", which flatly contradicted line 207's "all Zod schemas [unchanged]"; post-PR line 101 says they're at /zod-schemas, so line 207's "(only import paths changed)" is now literally true.
That's fair as far as it goes — line 207 is no longer a hard contradiction in the SKILL file. But it remains misleading in context: every other item in that comma-separated list (Client, McpServer, transports, StdioServerTransport, callback return types) maps to a package root via §3, and line 207 names no path, so the only mapping a mechanical reader can apply is the §3 sdk/types.js → package-root one. Line 101 corrects this if read, but an LLM scanning §5's summary list may not back-reference. Importantly, the refuter explicitly agreed that the migration.md:896 case is a genuine leftover ("both lines were previously consistent (and wrong), and the PR's edit to 503 left 896 stale"). Since the PR should fix migration.md:896 anyway, tidying the parallel migration-SKILL.md:207 in the same sweep is essentially free and keeps the two docs aligned.
Impact
Documentation consistency only — no runtime or build impact. Worst case is a confused migrating user (or LLM-driven migration) trying the package root, getting TS2305, and having to re-read §5. Hence nit.
Fix
- migration.md:896 →
- All type definitions fromtypes.ts(except the aliases listed above); Zod schema constants moved to@modelcontextprotocol/server/zod-schemas`` — or simply drop "Zod schemas and". - migration-SKILL.md:207 → drop "all Zod schemas," (line 101 already covers them), or replace with "all Zod schemas (via the
/zod-schemassubpath)".
| /** @deprecated Use `specTypeSchemas` / `isSpecType` for runtime validation. */ | ||
| export { | ||
| IdJagTokenExchangeResponseSchema, | ||
| OAuthClientInformationFullSchema, | ||
| OAuthClientInformationSchema, | ||
| OAuthClientMetadataSchema, | ||
| OAuthClientRegistrationErrorSchema, | ||
| OAuthErrorResponseSchema, | ||
| OAuthMetadataSchema, | ||
| OAuthProtectedResourceMetadataSchema, | ||
| OAuthTokenRevocationRequestSchema, | ||
| OAuthTokensSchema, | ||
| OpenIdProviderDiscoveryMetadataSchema, | ||
| OpenIdProviderMetadataSchema, | ||
| OptionalSafeUrlSchema, | ||
| SafeUrlSchema | ||
| } from '@modelcontextprotocol/core'; |
There was a problem hiding this comment.
🟡 The @deprecated message on the OAuth/OIDC export block (line 15) was copy-pasted from the protocol-schema block above and points users at specTypeSchemas / isSpecType — but those are keyed on MCP spec types from core/src/types/schemas.ts, while OAuthTokensSchema, OAuthMetadataSchema, SafeUrlSchema, etc. live in core/src/shared/auth.ts and won't appear there. Since the PR description explicitly targets "token endpoints, OIDC discovery" consumers, this hint sends them to a dead end; consider dropping the replacement pointer on this block (just @deprecated v1-compat shim) or pointing at whatever the v2-native source for auth schemas is intended to be.
Extended reasoning...
What's wrong
packages/server/src/zodSchemas.ts:15 carries the same @deprecated text as line 12:
/** @deprecated Use `specTypeSchemas` / `isSpecType` for runtime validation. */
export {
IdJagTokenExchangeResponseSchema,
OAuthClientInformationFullSchema,
...
OAuthTokensSchema,
OpenIdProviderDiscoveryMetadataSchema,
...
SafeUrlSchema
} from '@modelcontextprotocol/core';On line 12 the pointer is correct — the wildcard re-export pulls from @modelcontextprotocol/core/schemas (i.e. core/src/types/schemas.ts), which is exactly the surface that specTypeSchemas / isSpecType (#1887) index by spec-type name. On line 15 it isn't: the OAuth/OIDC schemas come from packages/core/src/shared/auth.ts, which is a separate module that has nothing to do with MCP spec types.
Why specTypeSchemas / isSpecType can't cover these
specTypeSchemas/isSpecType(per feat(core): add isSpecType / specTypeSchemas Records for runtime validation of spec types #1887 and the PR description's own example,specTypeSchema('CallToolRequest')) are keyed on MCP protocol type names — the contents ofcore/src/types/schemas.ts.- Grep confirms
schemas.tscontains zeroOAuth*orOpenId*references — the OAuth/OIDC Zod schemas are defined exclusively incore/src/shared/auth.ts. - The core public barrel makes the separation explicit:
packages/core/src/exports/public/index.ts:18is annotated "Auth TypeScript types (NOT Zod schemas like OAuthMetadataSchema)" — the auth Zod schemas are deliberately kept off the spec-type surface.
So there will be no specTypeSchemas.OAuthTokens / isSpecType.OAuthMetadata entry for a consumer to migrate to.
Step-by-step proof
- A v1 consumer validates a token-endpoint response:
OAuthTokensSchema.parse(await res.json()). - They migrate to v2, import
OAuthTokensSchemafrom@modelcontextprotocol/server/zod-schemas, and their IDE shows the deprecation hover from line 15: "UsespecTypeSchemas/isSpecTypefor runtime validation." - They look up
specTypeSchemas(from feat(core): add isSpecType / specTypeSchemas Records for runtime validation of spec types #1887) and find it is aRecord<SpecTypeName, ZodType>keyed on names likeCallToolRequest,JSONRPCMessage,Tool— the contents ofschemas.ts. - There is no
OAuthTokens,OAuthMetadata,OpenIdProviderMetadata, orSafeUrlkey, because those schemas are defined inshared/auth.ts, nottypes/schemas.ts. - The deprecation pointer is a dead end — there is no v2-native replacement at the location named.
Why this audience matters
The PR description's own motivation calls out "Consumers using them for runtime validation at HTTP boundaries (token endpoints, OIDC discovery, custom transports)" — i.e., OAuth-schema users are an explicitly targeted audience of this subpath. They are precisely the group that will hover OAuthTokensSchema and follow this hint.
Why nothing catches it
Line 15's text was copy-pasted from line 12 when e8a7dcf updated the wording from specTypeSchema() to specTypeSchemas / isSpecType. zodSchemas.ts is excluded from typedoc (typedoc.json:5), and TypeScript doesn't validate @deprecated prose, so no tooling flags the inapplicable pointer. This falls under the repo's recurring "Documentation & Changesets" catch — prose that promises behavior the code doesn't ship misleads consumers.
Impact & fix
Documentation/DX only, no runtime impact — hence nit. But the whole point of this PR is to give v1 consumers correct migration guidance, so a dead-end pointer on one of its two explicitly-named use cases is worth fixing. Either:
/** @deprecated v1-compat shim; OAuth/OIDC Zod schemas have no v2-native replacement yet. */or simply drop the replacement clause on this block:
/** @deprecated v1-compat shim. */(or, if there is an intended v2-native home for auth schemas, point there instead).
bhosmer-ant
left a comment
There was a problem hiding this comment.
Reviewed at e8a7dcf9. LGTM — completeness verified exhaustively.
comm -23 of v1.29.0's exported *Schema constants against this subpath = empty set after the two aliases (JSONRPCErrorSchema, ResourceReferenceSchema). All 13 v1 auth schemas present. Built dist/zodSchemas.mjs shares the same chunk as index.mjs (no duplicated Zod construction). Tests/typecheck pass.
Merge-order note (zodSchemas.ts:4-15, docs/migration.md:503): the @deprecated guidance and migration-doc text point at specTypeSchemas / isSpecType, which come from #1887 (open). If this lands first, IDE tooltips and docs reference a non-existent API until #1887 is in. Suggest landing #1887 first, or softening to "prefer the type-guard helpers (isCallToolResult, etc.)" in the interim.
Question: subpath is server-only; there's no @modelcontextprotocol/client/zod-schemas. The PR description's own motivating examples (token endpoints, OIDC discovery, custom transports) are client-side use cases. Intentional given the #1913 meta-package covers sdk/types.js, or worth a client mirror?
Nit (docs/migration-SKILL.md:101): the update is prose-after-the-table. For the LLM-mechanical-migration use case, a mapping-table row (e.g. | *Schema constants from sdk/types.js | @modelcontextprotocol/server/zod-schemas (deprecated) |) would be more directly actionable.
Process: deep-analysis subagent + dynamic verification (built package, completeness diff vs v1.29.0, runtime import check). Bughunter unavailable this run (env auth issue).
| * @packageDocumentation | ||
| */ | ||
|
|
||
| /** @deprecated Use `specTypeSchemas` / `isSpecType` for runtime validation. */ |
There was a problem hiding this comment.
One more from a deeper pass (nit, non-blocking): the /** @deprecated */ on lines 12 and 14 doesn't propagate through export * / block-level export {…} to the individual symbols — TS only honors @deprecated on per-specifier JSDoc or the original declaration. So CallToolRequestSchema etc. won't show IDE strikethrough; only the two aliases at 33-37 do. The @packageDocumentation tag covers the TypeDoc page but not call sites. If per-symbol deprecation matters, each name needs its own /** @deprecated */ specifier (~156 of them); if the module-level signal is enough, fine to leave as-is.
Separately — bughunter independently flagged the JSONRPCResponseSchema claim above; same refutation applies (union since v1.25.2).
Part of the v2 backwards-compatibility series — see reviewer guide.
v2 stopped exporting Zod schema constants (only TS types). Consumers using them for runtime validation at HTTP boundaries (token endpoints, OIDC discovery, custom transports) lose validators. This re-exports them under a
@deprecatedsubpath.Motivation and Context
v2 stopped exporting Zod schema constants (only TS types). Consumers using them for runtime validation at HTTP boundaries (token endpoints, OIDC discovery, custom transports) lose validators. This re-exports them under a
@deprecatedsubpath.v1 vs v2 pattern & evidence
v1 pattern:
`import { OAuthTokensSchema, CallToolRequestSchema } from '@modelcontextprotocol/sdk/types.js'`v2-native:
Evidence: Hits any consumer doing runtime validation of HTTP responses or implementing a custom transport.
How Has This Been Tested?
v2-bc-integrationvalidation branchpnpm typecheck:all && pnpm lint:all && pnpm test:allgreenBreaking Changes
None — additive
@deprecatedshim. Removed in v3.Types of changes
Checklist
Additional context
Stacks on: none