api-ref: infer builder ids and plugin ownership

Preserve literal API ref ids in the builder form while keeping the deprecated constructor compatible, and rely on explicit ownership metadata instead of the old core id fallback.

Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
Made-with: Cursor
This commit is contained in:
Patrik Oldsberg
2026-03-16 20:52:41 +01:00
parent 7a960a0d75
commit 76b89c7437
9 changed files with 181 additions and 71 deletions
@@ -417,6 +417,51 @@ describe('createSpecializedApp', () => {
expect(app.apis.get(testApiRef)).toEqual({ value: 'owner' });
});
it('should not infer app ownership from core-prefixed API ids', () => {
const testApiRef = createApiRef<{ value: string }>({ id: 'core.shared' });
const app = createSpecializedApp({
features: [
makeAppPlugin(),
createFrontendPlugin({
pluginId: 'other-before',
extensions: [
ApiBlueprint.make({
params: defineParams =>
defineParams({
api: testApiRef,
deps: {},
factory: () => ({ value: 'other' }),
}),
}),
],
}),
createFrontendModule({
pluginId: 'app',
extensions: [
ApiBlueprint.make({
params: defineParams =>
defineParams({
api: testApiRef,
deps: {},
factory: () => ({ value: 'app' }),
}),
}),
],
}),
],
});
expect(app.errors).toEqual([
expect.objectContaining({
code: 'API_FACTORY_CONFLICT',
message: expect.stringContaining("API 'core.shared'"),
}),
]);
expect(app.apis.get(testApiRef)).toEqual({ value: 'other' });
});
it('should allow API overrides within the same plugin', () => {
const testApiRef = createApiRef<{ value: string }>({ id: 'test.api' });
@@ -407,8 +407,8 @@ function createApiFactories(options: {
// This allows modules to override factories provided by the plugin, but
// it rejects API overrides from other plugins. In the event of a
// conflict, the owning plugin is attempted to be inferred from the API
// reference ID.
// conflict, the owning plugin is inferred from the explicit pluginId or
// legacy plugin-prefixed API reference ID.
if (existingFactory && existingFactory.pluginId !== pluginId) {
const shouldReplace =
ownerId === pluginId && existingFactory.pluginId !== ownerId;
@@ -465,9 +465,6 @@ function getApiOwnerId(apiRef: { id: string; pluginId?: string }): string {
if (!prefix) {
return apiRefId;
}
if (prefix === 'core') {
return 'app';
}
if (prefix === 'plugin' && rest[0]) {
return rest[0];
}