summaryrefslogtreecommitdiffhomepage
path: root/packages/surface-registry
diff options
context:
space:
mode:
authorAdam Malczewski <[email protected]>2026-06-27 01:09:39 +0900
committerAdam Malczewski <[email protected]>2026-06-27 01:09:39 +0900
commit61e45e60d699ed1ca46f94a8f181c92a940317c6 (patch)
tree2892d9773c5a8e367e1e58cdb1e88d9c6ad3fe6d /packages/surface-registry
parent63c7e64532e85e0bbdd6d9ac6825d8f86be98e7a (diff)
parent727c98c9dae516a2070eb950410314380a20c974 (diff)
downloaddispatch-61e45e60d699ed1ca46f94a8f181c92a940317c6.tar.gz
dispatch-61e45e60d699ed1ca46f94a8f181c92a940317c6.zip
Merge branch 'feature/indent-change' into dev
Diffstat (limited to 'packages/surface-registry')
-rw-r--r--packages/surface-registry/package.json20
-rw-r--r--packages/surface-registry/src/extension.ts28
-rw-r--r--packages/surface-registry/src/registry.test.ts224
-rw-r--r--packages/surface-registry/src/registry.ts100
-rw-r--r--packages/surface-registry/tsconfig.json8
5 files changed, 190 insertions, 190 deletions
diff --git a/packages/surface-registry/package.json b/packages/surface-registry/package.json
index 16b0c4c..9ae2a04 100644
--- a/packages/surface-registry/package.json
+++ b/packages/surface-registry/package.json
@@ -1,12 +1,12 @@
{
- "name": "@dispatch/surface-registry",
- "version": "0.0.0",
- "type": "module",
- "private": true,
- "main": "dist/index.js",
- "types": "dist/index.d.ts",
- "dependencies": {
- "@dispatch/kernel": "workspace:*",
- "@dispatch/ui-contract": "workspace:*"
- }
+ "name": "@dispatch/surface-registry",
+ "version": "0.0.0",
+ "type": "module",
+ "private": true,
+ "main": "dist/index.js",
+ "types": "dist/index.d.ts",
+ "dependencies": {
+ "@dispatch/kernel": "workspace:*",
+ "@dispatch/ui-contract": "workspace:*"
+ }
}
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);
+ },
+ };
}
diff --git a/packages/surface-registry/tsconfig.json b/packages/surface-registry/tsconfig.json
index e430ba9..789e54f 100644
--- a/packages/surface-registry/tsconfig.json
+++ b/packages/surface-registry/tsconfig.json
@@ -1,6 +1,6 @@
{
- "extends": "../../tsconfig.base.json",
- "compilerOptions": { "rootDir": "src", "outDir": "dist", "composite": true },
- "include": ["src/**/*.ts"],
- "references": [{ "path": "../kernel" }, { "path": "../ui-contract" }]
+ "extends": "../../tsconfig.base.json",
+ "compilerOptions": { "rootDir": "src", "outDir": "dist", "composite": true },
+ "include": ["src/**/*.ts"],
+ "references": [{ "path": "../kernel" }, { "path": "../ui-contract" }]
}