diff options
| author | Adam Malczewski <[email protected]> | 2026-06-26 22:03:19 +0900 |
|---|---|---|
| committer | Adam Malczewski <[email protected]> | 2026-06-26 22:23:39 +0900 |
| commit | 727c98c9dae516a2070eb950410314380a20c974 (patch) | |
| tree | 52aa1022c54f11770be7e4e2a324f0a8b8b8deec /packages/surface-registry/src | |
| parent | e59dc11f63b1df51142259bb2c406af8c9c8c2bb (diff) | |
| download | dispatch-727c98c9dae516a2070eb950410314380a20c974.tar.gz dispatch-727c98c9dae516a2070eb950410314380a20c974.zip | |
style: switch from tabs to 2-space indentation
Diffstat (limited to 'packages/surface-registry/src')
| -rw-r--r-- | packages/surface-registry/src/extension.ts | 28 | ||||
| -rw-r--r-- | packages/surface-registry/src/registry.test.ts | 224 | ||||
| -rw-r--r-- | packages/surface-registry/src/registry.ts | 100 |
3 files changed, 176 insertions, 176 deletions
diff --git a/packages/surface-registry/src/extension.ts b/packages/surface-registry/src/extension.ts index 6d0ce22..2e0c038 100644 --- a/packages/surface-registry/src/extension.ts +++ b/packages/surface-registry/src/extension.ts @@ -3,21 +3,21 @@ import { createSurfaceRegistry } from "./registry.js"; import { surfaceRegistryHandle } from "./service.js"; export const manifest: Manifest = { - id: "surface-registry", - name: "Surface Registry", - version: "0.0.0", - apiVersion: "^0.1.0", - trust: "bundled", - activation: "eager", - contributes: { services: ["surface-registry/registry"] }, + id: "surface-registry", + name: "Surface Registry", + version: "0.0.0", + apiVersion: "^0.1.0", + trust: "bundled", + activation: "eager", + contributes: { services: ["surface-registry/registry"] }, }; export function createSurfaceRegistryExtension(): Extension { - return { - manifest, - activate(host) { - const registry = createSurfaceRegistry(); - host.provideService(surfaceRegistryHandle, registry); - }, - }; + return { + manifest, + activate(host) { + const registry = createSurfaceRegistry(); + host.provideService(surfaceRegistryHandle, registry); + }, + }; } diff --git a/packages/surface-registry/src/registry.test.ts b/packages/surface-registry/src/registry.test.ts index c47c979..151e449 100644 --- a/packages/surface-registry/src/registry.test.ts +++ b/packages/surface-registry/src/registry.test.ts @@ -4,119 +4,119 @@ import type { SurfaceProvider } from "./registry.js"; import { createSurfaceRegistry } from "./registry.js"; function fakeProvider(id: string, title?: string): SurfaceProvider { - const catalogEntry: SurfaceCatalogEntry = { - id, - region: "default", - title: title ?? `Surface ${id}`, - }; - return { - catalogEntry, - getSpec(): SurfaceSpec { - return { - id, - region: "default", - title: catalogEntry.title, - fields: [], - }; - }, - invoke() {}, - }; + const catalogEntry: SurfaceCatalogEntry = { + id, + region: "default", + title: title ?? `Surface ${id}`, + }; + return { + catalogEntry, + getSpec(): SurfaceSpec { + return { + id, + region: "default", + title: catalogEntry.title, + fields: [], + }; + }, + invoke() {}, + }; } describe("createSurfaceRegistry", () => { - describe("register + getCatalog", () => { - it("returns the entry after registration", () => { - const registry = createSurfaceRegistry(); - registry.register(fakeProvider("a", "Surface A")); - - const catalog = registry.getCatalog(); - expect(catalog).toHaveLength(1); - expect(catalog[0]).toEqual({ - id: "a", - region: "default", - title: "Surface A", - }); - }); - - it("returns entries for multiple providers", () => { - const registry = createSurfaceRegistry(); - registry.register(fakeProvider("a")); - registry.register(fakeProvider("b")); - - const catalog = registry.getCatalog(); - expect(catalog).toHaveLength(2); - expect(catalog.map((e) => e.id)).toEqual(["a", "b"]); - }); - }); - - describe("getSurface", () => { - it("returns the provider for a known id", () => { - const registry = createSurfaceRegistry(); - const provider = fakeProvider("x"); - registry.register(provider); - - expect(registry.getSurface("x")).toBe(provider); - }); - - it("returns undefined for an unknown id", () => { - const registry = createSurfaceRegistry(); - expect(registry.getSurface("nonexistent")).toBeUndefined(); - }); - }); - - describe("disposer", () => { - it("removes the provider from catalog and lookup", () => { - const registry = createSurfaceRegistry(); - const dispose = registry.register(fakeProvider("a")); - - expect(registry.getCatalog()).toHaveLength(1); - expect(registry.getSurface("a")).toBeDefined(); - - dispose(); - - expect(registry.getCatalog()).toHaveLength(0); - expect(registry.getSurface("a")).toBeUndefined(); - }); - - it("is idempotent — calling dispose twice is safe", () => { - const registry = createSurfaceRegistry(); - const dispose = registry.register(fakeProvider("a")); - - dispose(); - dispose(); - - expect(registry.getCatalog()).toHaveLength(0); - }); - - it("does not remove a replacement provider with the same id", () => { - const registry = createSurfaceRegistry(); - const first = fakeProvider("a", "First"); - const second = fakeProvider("a", "Second"); - - const disposeFirst = registry.register(first); - registry.register(second); - - disposeFirst(); - - // The second provider should still be registered - expect(registry.getSurface("a")).toBe(second); - expect(registry.getCatalog()).toHaveLength(1); - expect(registry.getCatalog()[0]?.title).toBe("Second"); - }); - }); - - describe("duplicate-id behavior (last-wins)", () => { - it("replaces an existing provider when registering the same id", () => { - const registry = createSurfaceRegistry(); - const first = fakeProvider("a", "First"); - const second = fakeProvider("a", "Second"); - - registry.register(first); - registry.register(second); - - expect(registry.getSurface("a")).toBe(second); - expect(registry.getCatalog()).toHaveLength(1); - expect(registry.getCatalog()[0]?.title).toBe("Second"); - }); - }); + describe("register + getCatalog", () => { + it("returns the entry after registration", () => { + const registry = createSurfaceRegistry(); + registry.register(fakeProvider("a", "Surface A")); + + const catalog = registry.getCatalog(); + expect(catalog).toHaveLength(1); + expect(catalog[0]).toEqual({ + id: "a", + region: "default", + title: "Surface A", + }); + }); + + it("returns entries for multiple providers", () => { + const registry = createSurfaceRegistry(); + registry.register(fakeProvider("a")); + registry.register(fakeProvider("b")); + + const catalog = registry.getCatalog(); + expect(catalog).toHaveLength(2); + expect(catalog.map((e) => e.id)).toEqual(["a", "b"]); + }); + }); + + describe("getSurface", () => { + it("returns the provider for a known id", () => { + const registry = createSurfaceRegistry(); + const provider = fakeProvider("x"); + registry.register(provider); + + expect(registry.getSurface("x")).toBe(provider); + }); + + it("returns undefined for an unknown id", () => { + const registry = createSurfaceRegistry(); + expect(registry.getSurface("nonexistent")).toBeUndefined(); + }); + }); + + describe("disposer", () => { + it("removes the provider from catalog and lookup", () => { + const registry = createSurfaceRegistry(); + const dispose = registry.register(fakeProvider("a")); + + expect(registry.getCatalog()).toHaveLength(1); + expect(registry.getSurface("a")).toBeDefined(); + + dispose(); + + expect(registry.getCatalog()).toHaveLength(0); + expect(registry.getSurface("a")).toBeUndefined(); + }); + + it("is idempotent — calling dispose twice is safe", () => { + const registry = createSurfaceRegistry(); + const dispose = registry.register(fakeProvider("a")); + + dispose(); + dispose(); + + expect(registry.getCatalog()).toHaveLength(0); + }); + + it("does not remove a replacement provider with the same id", () => { + const registry = createSurfaceRegistry(); + const first = fakeProvider("a", "First"); + const second = fakeProvider("a", "Second"); + + const disposeFirst = registry.register(first); + registry.register(second); + + disposeFirst(); + + // The second provider should still be registered + expect(registry.getSurface("a")).toBe(second); + expect(registry.getCatalog()).toHaveLength(1); + expect(registry.getCatalog()[0]?.title).toBe("Second"); + }); + }); + + describe("duplicate-id behavior (last-wins)", () => { + it("replaces an existing provider when registering the same id", () => { + const registry = createSurfaceRegistry(); + const first = fakeProvider("a", "First"); + const second = fakeProvider("a", "Second"); + + registry.register(first); + registry.register(second); + + expect(registry.getSurface("a")).toBe(second); + expect(registry.getCatalog()).toHaveLength(1); + expect(registry.getCatalog()[0]?.title).toBe("Second"); + }); + }); }); diff --git a/packages/surface-registry/src/registry.ts b/packages/surface-registry/src/registry.ts index 5780910..840ef5a 100644 --- a/packages/surface-registry/src/registry.ts +++ b/packages/surface-registry/src/registry.ts @@ -6,7 +6,7 @@ import type { SurfaceCatalog, SurfaceCatalogEntry, SurfaceSpec } from "@dispatch * the default/global behaviour. */ export interface SurfaceContext { - readonly conversationId?: string; + readonly conversationId?: string; } /** @@ -14,20 +14,20 @@ export interface SurfaceContext { * Each provider owns one surface identified by its catalog entry id. */ export interface SurfaceProvider { - /** Discovery metadata for the surface catalog. */ - readonly catalogEntry: SurfaceCatalogEntry; + /** Discovery metadata for the surface catalog. */ + readonly catalogEntry: SurfaceCatalogEntry; - /** Build the current surface spec (may be async for dynamic surfaces). */ - getSpec(context?: SurfaceContext): SurfaceSpec | Promise<SurfaceSpec>; + /** Build the current surface spec (may be async for dynamic surfaces). */ + getSpec(context?: SurfaceContext): SurfaceSpec | Promise<SurfaceSpec>; - /** Run a backend action by id with an optional payload. */ - invoke(actionId: string, payload?: unknown, context?: SurfaceContext): void | Promise<void>; + /** Run a backend action by id with an optional payload. */ + invoke(actionId: string, payload?: unknown, context?: SurfaceContext): void | Promise<void>; - /** - * Optional: subscribe to spec changes. Returns an unsubscribe disposer. - * When the spec changes, the caller should re-fetch via getSpec() and push. - */ - subscribe?(onChange: () => void): () => void; + /** + * Optional: subscribe to spec changes. Returns an unsubscribe disposer. + * When the spec changes, the caller should re-fetch via getSpec() and push. + */ + subscribe?(onChange: () => void): () => void; } /** @@ -35,18 +35,18 @@ export interface SurfaceProvider { * `host.getService(surfaceRegistryHandle)`. */ export interface SurfaceRegistry { - /** - * Register a surface provider. Returns an unregister disposer. - * If a provider with the same id is already registered, the new one - * replaces it (last-wins semantics). - */ - register(provider: SurfaceProvider): () => void; + /** + * Register a surface provider. Returns an unregister disposer. + * If a provider with the same id is already registered, the new one + * replaces it (last-wins semantics). + */ + register(provider: SurfaceProvider): () => void; - /** Return discovery metadata for all currently registered providers. */ - getCatalog(): SurfaceCatalog; + /** Return discovery metadata for all currently registered providers. */ + getCatalog(): SurfaceCatalog; - /** Look up a provider by its surface id. */ - getSurface(id: string): SurfaceProvider | undefined; + /** Look up a provider by its surface id. */ + getSurface(id: string): SurfaceProvider | undefined; } /** @@ -54,36 +54,36 @@ export interface SurfaceRegistry { * the decision logic is a plain Map behind the SurfaceRegistry interface. */ export function createSurfaceRegistry(): SurfaceRegistry { - const providers = new Map<string, SurfaceProvider>(); + const providers = new Map<string, SurfaceProvider>(); - return { - register(provider: SurfaceProvider): () => void { - const id = provider.catalogEntry.id; - providers.set(id, provider); + return { + register(provider: SurfaceProvider): () => void { + const id = provider.catalogEntry.id; + providers.set(id, provider); - let disposed = false; - return () => { - if (!disposed) { - disposed = true; - // Only delete if the current entry is still this provider - // (another register with the same id may have replaced it). - if (providers.get(id) === provider) { - providers.delete(id); - } - } - }; - }, + let disposed = false; + return () => { + if (!disposed) { + disposed = true; + // Only delete if the current entry is still this provider + // (another register with the same id may have replaced it). + if (providers.get(id) === provider) { + providers.delete(id); + } + } + }; + }, - getCatalog(): SurfaceCatalog { - const entries: SurfaceCatalogEntry[] = []; - for (const provider of providers.values()) { - entries.push(provider.catalogEntry); - } - return entries; - }, + getCatalog(): SurfaceCatalog { + const entries: SurfaceCatalogEntry[] = []; + for (const provider of providers.values()) { + entries.push(provider.catalogEntry); + } + return entries; + }, - getSurface(id: string): SurfaceProvider | undefined { - return providers.get(id); - }, - }; + getSurface(id: string): SurfaceProvider | undefined { + return providers.get(id); + }, + }; } |
