Showing the changes to packages/client-runtime/src (4 of 121 files). Show all
Unified · Split
| @@ -0,0 +1,2 @@ | |||
| 1 | export * from "./knownEnvironment"; | ||
| 2 | export * from "./scoped"; | ||
| @@ -0,0 +1,63 @@ | |||
| 1 | import { EnvironmentId, ProjectId, ThreadId } from "@t3tools/contracts"; | ||
| 2 | import { describe, expect, it } from "vitest"; | ||
| 3 | |||
| 4 | import { createKnownEnvironmentFromWsUrl } from "./knownEnvironment"; | ||
| 5 | import { | ||
| 6 | parseScopedProjectKey, | ||
| 7 | parseScopedThreadKey, | ||
| 8 | scopedProjectKey, | ||
| 9 | scopedRefKey, | ||
| 10 | scopedThreadKey, | ||
| 11 | scopeProjectRef, | ||
| 12 | scopeThreadRef, | ||
| 13 | } from "./scoped"; | ||
| 14 | |||
| 15 | describe("known environment bootstrap helpers", () => { | ||
| 16 | it("creates known environments from explicit ws urls", () => { | ||
| 17 | expect( | ||
| 18 | createKnownEnvironmentFromWsUrl({ | ||
| 19 | label: "Remote environment", | ||
| 20 | wsUrl: "wss://remote.example.com/ws", | ||
| 21 | }), | ||
| 22 | ).toEqual({ | ||
| 23 | id: "ws:Remote environment", | ||
| 24 | label: "Remote environment", | ||
| 25 | source: "manual", | ||
| 26 | target: { | ||
| 27 | type: "ws", | ||
| 28 | wsUrl: "wss://remote.example.com/ws", | ||
| 29 | }, | ||
| 30 | }); | ||
| 31 | }); | ||
| 32 | }); | ||
| 33 | |||
| 34 | describe("scoped refs", () => { | ||
| 35 | const environmentId = EnvironmentId.makeUnsafe("environment-test"); | ||
| 36 | const projectRef = scopeProjectRef(environmentId, ProjectId.makeUnsafe("project-1")); | ||
| 37 | const threadRef = scopeThreadRef(environmentId, ThreadId.makeUnsafe("thread-1")); | ||
| 38 | |||
| 39 | it("builds stable scoped project and thread keys", () => { | ||
| 40 | expect(scopedRefKey(projectRef)).toBe("environment-test:project-1"); | ||
| 41 | expect(scopedRefKey(threadRef)).toBe("environment-test:thread-1"); | ||
| 42 | expect(scopedProjectKey(projectRef)).toBe("environment-test:project-1"); | ||
| 43 | expect(scopedThreadKey(threadRef)).toBe("environment-test:thread-1"); | ||
| 44 | }); | ||
| 45 | |||
| 46 | it("returns typed scoped refs", () => { | ||
| 47 | expect(projectRef).toEqual({ | ||
| 48 | environmentId, | ||
| 49 | projectId: ProjectId.makeUnsafe("project-1"), | ||
| 50 | }); | ||
| 51 | expect(threadRef).toEqual({ | ||
| 52 | environmentId, | ||
| 53 | threadId: ThreadId.makeUnsafe("thread-1"), | ||
| 54 | }); | ||
| 55 | }); | ||
| 56 | |||
| 57 | it("parses scoped project and thread keys back into refs", () => { | ||
| 58 | expect(parseScopedProjectKey("environment-test:project-1")).toEqual(projectRef); | ||
| 59 | expect(parseScopedThreadKey("environment-test:thread-1")).toEqual(threadRef); | ||
| 60 | expect(parseScopedProjectKey("bad-key")).toBeNull(); | ||
| 61 | expect(parseScopedThreadKey("bad-key")).toBeNull(); | ||
| 62 | }); | ||
| 63 | }); | ||
| @@ -0,0 +1,39 @@ | |||
| 1 | import type { EnvironmentId } from "@t3tools/contracts"; | ||
| 2 | |||
| 3 | export interface KnownEnvironmentConnectionTarget { | ||
| 4 | readonly type: "ws"; | ||
| 5 | readonly wsUrl: string; | ||
| 6 | } | ||
| 7 | |||
| 8 | export type KnownEnvironmentSource = "configured" | "desktop-managed" | "manual" | "window-origin"; | ||
| 9 | |||
| 10 | export interface KnownEnvironment { | ||
| 11 | readonly id: string; | ||
| 12 | readonly label: string; | ||
| 13 | readonly source: KnownEnvironmentSource; | ||
| 14 | readonly environmentId?: EnvironmentId; | ||
| 15 | readonly target: KnownEnvironmentConnectionTarget; | ||
| 16 | } | ||
| 17 | |||
| 18 | export function createKnownEnvironmentFromWsUrl(input: { | ||
| 19 | readonly id?: string; | ||
| 20 | readonly label: string; | ||
| 21 | readonly source?: KnownEnvironmentSource; | ||
| 22 | readonly wsUrl: string; | ||
| 23 | }): KnownEnvironment { | ||
| 24 | return { | ||
| 25 | id: input.id ?? `ws:${input.label}`, | ||
| 26 | label: input.label, | ||
| 27 | source: input.source ?? "manual", | ||
| 28 | target: { | ||
| 29 | type: "ws", | ||
| 30 | wsUrl: input.wsUrl, | ||
| 31 | }, | ||
| 32 | }; | ||
| 33 | } | ||
| 34 | |||
| 35 | export function getKnownEnvironmentBaseUrl( | ||
| 36 | environment: KnownEnvironment | null | undefined, | ||
| 37 | ): string | null { | ||
| 38 | return environment?.target.wsUrl ?? null; | ||
| 39 | } | ||
| @@ -0,0 +1,64 @@ | |||
| 1 | import type { | ||
| 2 | EnvironmentId, | ||
| 3 | ProjectId, | ||
| 4 | ScopedProjectRef, | ||
| 5 | ScopedThreadRef, | ||
| 6 | ThreadId, | ||
| 7 | } from "@t3tools/contracts"; | ||
| 8 | |||
| 9 | export function scopeProjectRef( | ||
| 10 | environmentId: EnvironmentId, | ||
| 11 | projectId: ProjectId, | ||
| 12 | ): ScopedProjectRef { | ||
| 13 | return { environmentId, projectId }; | ||
| 14 | } | ||
| 15 | |||
| 16 | export function scopeThreadRef(environmentId: EnvironmentId, threadId: ThreadId): ScopedThreadRef { | ||
| 17 | return { environmentId, threadId }; | ||
| 18 | } | ||
| 19 | |||
| 20 | export function scopedRefKey(ref: ScopedProjectRef | ScopedThreadRef): string { | ||
| 21 | const localId = "projectId" in ref ? ref.projectId : ref.threadId; | ||
| 22 | return `${ref.environmentId}:${localId}`; | ||
| 23 | } | ||
| 24 | |||
| 25 | export function scopedProjectKey(ref: ScopedProjectRef): string { | ||
| 26 | return scopedRefKey(ref); | ||
| 27 | } | ||
| 28 | |||
| 29 | export function scopedThreadKey(ref: ScopedThreadRef): string { | ||
| 30 | return scopedRefKey(ref); | ||
| 31 | } | ||
| 32 | |||
| 33 | function parseScopedKey(key: string): { environmentId: EnvironmentId; localId: string } | null { | ||
| 34 | const separatorIndex = key.indexOf(":"); | ||
| 35 | if (separatorIndex <= 0 || separatorIndex >= key.length - 1) { | ||
| 36 | return null; | ||
| 37 | } | ||
| 38 | return { | ||
| 39 | environmentId: key.slice(0, separatorIndex) as EnvironmentId, | ||
| 40 | localId: key.slice(separatorIndex + 1), | ||
| 41 | }; | ||
| 42 | } | ||
| 43 | |||
| 44 | export function parseScopedProjectKey(key: string): ScopedProjectRef | null { | ||
| 45 | const parsed = parseScopedKey(key); | ||
| 46 | if (!parsed) { | ||
| 47 | return null; | ||
| 48 | } | ||
| 49 | return { | ||
| 50 | environmentId: parsed.environmentId, | ||
| 51 | projectId: parsed.localId as ProjectId, | ||
| 52 | }; | ||
| 53 | } | ||
| 54 | |||
| 55 | export function parseScopedThreadKey(key: string): ScopedThreadRef | null { | ||
| 56 | const parsed = parseScopedKey(key); | ||
| 57 | if (!parsed) { | ||
| 58 | return null; | ||
| 59 | } | ||
| 60 | return { | ||
| 61 | environmentId: parsed.environmentId, | ||
| 62 | threadId: parsed.localId as ThreadId, | ||
| 63 | }; | ||
| 64 | } | ||