| name | general-deprecate-api |
| description | Deprecate a public API (class, method, property, type, constant, or context token) following the 2-major-version rule. Use when removing or replacing any publicly exported symbol that external consumers may depend on — includes exports from package index.ts files, global components, extension type aliases, and manifest schemas. |
| allowed-tools | Read, Write, Edit, Grep, Glob |
Deprecate API
Deprecate a public API following Umbraco's breaking changes policy.
What you need from the user
- What to deprecate — The class, method, property, type, or constant
- The replacement — What consumers should use instead
- Current major version — Read from
version.json at the repository root
The 2-Major-Version Rule
Deprecated in vN -> earliest removal in vN+2.
Example: deprecated in v17 -> scheduled for removal in v19.
Read version.json to determine the current major version and calculate the removal version.
Both mechanisms are required
Every deprecation must use both:
- JSDoc
@deprecated tag — for IDE warnings and documentation
UmbDeprecation runtime warning — for console output at runtime
Step 1: Add the replacement API
Introduce the new API alongside the old one. The old API should delegate to the new implementation internally.
requestSummary() {
}
Step 2: Add JSDoc @deprecated tag
Include: what was deprecated, when, the replacement, and when it will be removed.
getSummary() {
return this.requestSummary();
}
For types and interfaces:
export interface UmbOldInterface {
}
Step 3: Add UmbDeprecation runtime warning
import { UmbDeprecation } from '@umbraco-cms/backoffice/utils';
getSummary() {
new UmbDeprecation({
deprecated: 'UmbMyContext.getSummary()',
removeInVersion: '19.0.0',
solution: 'Use requestSummary() instead.',
}).warn();
return this.requestSummary();
}
Placement by symbol type
| Symbol | Where to place UmbDeprecation |
|---|
| Method | Inside the method body |
| Class | In the constructor |
| Property getter | Inside the getter |
| Constant | At module level (executes on import) |
For deprecated classes
export class UmbOldRepository extends UmbControllerBase {
constructor(host: UmbControllerHost) {
super(host);
new UmbDeprecation({
deprecated: 'UmbOldRepository is deprecated.',
removeInVersion: '19.0.0',
solution: 'Use UmbNewRepository instead.',
}).warn();
}
}
Step 4: Delegate old to new
The deprecated API must keep working. Delegate to the replacement internally:
getContentTypeId(): string | undefined {
new UmbDeprecation({
deprecated: 'UmbMemberWorkspaceContext.getContentTypeId()',
removeInVersion: '19.0.0',
solution: 'Use getContentTypeUnique() instead.',
}).warn();
return this.getContentTypeUnique();
}
Step 5: Update internal callers
All internal code must use the new API. No code within the repository should call the deprecated member.
What counts as a breaking change
Any of the following to a publicly exported symbol:
- Removing/renaming an exported class, function, type, constant, or context token
- Removing/renaming a public method or property
- Changing a public method signature (required params, return type)
- Removing/renaming a subpath export from
package.json
- Changing an extension type alias or manifest schema
- Removing/renaming a global component's tag name
Not breaking: Internal code (unexported classes, private methods) can be changed freely without deprecation.
Checklist