import { describe, expect, it } from "@effect/vitest";import * as Effect from "effect/Effect"; import { CredentialIdSchema, decodeBuiltInAuthArtifactConfig, SourceIdSchema, WorkspaceIdSchema, type Source,} from "#schema"; import { createSourceFromPayload, projectSourceFromStorage, splitSourceForStorage, stableSourceCatalogId, stableSourceCatalogRevisionId, updateSourceFromPayload,} from "./source-definitions";import { namespaceFromSourceName } from "./source-names"; const openApiBinding = ( specUrl = "https://api.github.com/openapi.json", defaultHeaders: Record<string, string> | null = null,) => ({ specUrl, defaultHeaders,}); const graphqlBinding = (defaultHeaders: Record<string, string> | null = null) => ({ defaultHeaders,}); const mcpBinding = (input: { transport?: "auto" | "streamable-http" | "sse" | null; queryParams?: Record<string, string> | null; headers?: Record<string, string> | null;} = {}) => ({ transport: input.transport ?? null, queryParams: input.queryParams ?? null, headers: input.headers ?? null,}); const makeSource = (overrides: Partial<Source> = {}): Source => ({ id: SourceIdSchema.make("src_source_definitions"), workspaceId: WorkspaceIdSchema.make("ws_source_definitions"), name: "GitHub", kind: "openapi", endpoint: "https://api.github.com", status: "connected", enabled: true, namespace: "github", bindingVersion: 1, binding: openApiBinding(), importAuthPolicy: "reuse_runtime", importAuth: { kind: "none" }, auth: { kind: "none" }, sourceHash: null, lastError: null, createdAt: 1000, updatedAt: 1000, ...overrides,}); describe("source-definitions", () => { describe("stable catalog ids", () => { it("is deterministic across calls and ignores source name/workspace", () => { const source = makeSource(); const renamed = makeSource({ name: "Renamed GitHub", }); const differentWorkspace = makeSource({ workspaceId: WorkspaceIdSchema.make("ws_source_definitions_other"), }); expect(stableSourceCatalogId(source)).toBe(stableSourceCatalogId(source)); expect(stableSourceCatalogRevisionId(source)).toBe(stableSourceCatalogRevisionId(source)); expect(stableSourceCatalogId(renamed)).toBe(stableSourceCatalogId(source)); expect(stableSourceCatalogRevisionId(renamed)).toBe(stableSourceCatalogRevisionId(source)); expect(stableSourceCatalogId(differentWorkspace)).toBe(stableSourceCatalogId(source)); expect(stableSourceCatalogRevisionId(differentWorkspace)).toBe( stableSourceCatalogRevisionId(source), ); }); it("changes catalog and revision ids when the source config changes", () => { const source = makeSource(); const changedEndpoint = makeSource({ endpoint: "https://example.com", binding: openApiBinding("https://example.com/openapi.json"), }); expect(stableSourceCatalogId(changedEndpoint)).not.toBe(stableSourceCatalogId(source)); expect(stableSourceCatalogRevisionId(changedEndpoint)).not.toBe( stableSourceCatalogRevisionId(source), ); }); }); describe("payload normalization and validation", () => { it("defaults created sources to draft/enabled and trims fields", async () => { const source = await Effect.runPromise(createSourceFromPayload({ workspaceId: WorkspaceIdSchema.make("ws_create_defaults"), sourceId: SourceIdSchema.make("src_create_defaults"), payload: { name: " GitHub ", kind: "openapi", endpoint: " https://api.github.com ", binding: openApiBinding(" https://api.github.com/openapi.json "), }, now: 1234, })); expect(source.name).toBe("GitHub"); expect(source.endpoint).toBe("https://api.github.com"); expect(source.binding).toEqual(openApiBinding("https://api.github.com/openapi.json")); expect(source.status).toBe("draft"); expect(source.enabled).toBe(true); expect(source.auth).toEqual({ kind: "none" }); }); it("preserves existing values on partial update and keeps auth when undefined", async () => { const source = makeSource({ kind: "graphql", endpoint: "https://example.com/graphql", binding: graphqlBinding({ accept: "application/json" }), auth: { kind: "bearer", headerName: "Authorization", prefix: "Bearer ", token: { providerId: "local", handle: "sec_token", }, }, }); const updated = await Effect.runPromise(updateSourceFromPayload({ source, payload: { status: "error", lastError: "bad gateway", }, now: 2000, })); expect(updated.name).toBe(source.name); expect(updated.endpoint).toBe(source.endpoint); expect(updated.binding).toEqual(source.binding); expect(updated.auth).toEqual(source.auth); expect(updated.status).toBe("error"); expect(updated.lastError).toBe("bad gateway"); expect(updated.updatedAt).toBe(2000); }); it("normalizes oauth2 auth defaults and allows null refresh tokens", async () => { const source = await Effect.runPromise(createSourceFromPayload({ workspaceId: WorkspaceIdSchema.make("ws_create_oauth_defaults"), sourceId: SourceIdSchema.make("src_create_oauth_defaults"), payload: { name: "GraphQL Demo", kind: "graphql", endpoint: "https://example.com/graphql", auth: { kind: "oauth2", headerName: " ", prefix: undefined, accessToken: { providerId: " local ", handle: " sec_access ", }, refreshToken: null, } as never, }, now: 1234, })); expect(source.auth).toEqual({ kind: "oauth2", headerName: "Authorization", prefix: "Bearer ", accessToken: { providerId: "local", handle: "sec_access", }, refreshToken: null, }); }); it("rejects invalid bearer and oauth2 secret refs", async () => { await expect(Effect.runPromise(createSourceFromPayload({ workspaceId: WorkspaceIdSchema.make("ws_invalid_bearer"), sourceId: SourceIdSchema.make("src_invalid_bearer"), payload: { name: "Bad Bearer", kind: "openapi", endpoint: "https://example.com", binding: openApiBinding("https://example.com/openapi.json"), auth: { kind: "bearer", headerName: "Authorization", prefix: "Bearer ", token: { providerId: " ", handle: "sec_token", }, }, }, now: 1234, }))).rejects.toThrow("Bearer auth requires a token secret ref"); await expect(Effect.runPromise(createSourceFromPayload({ workspaceId: WorkspaceIdSchema.make("ws_invalid_refresh"), sourceId: SourceIdSchema.make("src_invalid_refresh"), payload: { name: "Bad OAuth", kind: "graphql", endpoint: "https://example.com/graphql", binding: graphqlBinding(), auth: { kind: "oauth2", headerName: "Authorization", prefix: "Bearer ", accessToken: { providerId: "local", handle: "sec_access", }, refreshToken: { providerId: "local", handle: " ", }, } as never, }, now: 1234, }))).rejects.toThrow("OAuth2 refresh token ref must include providerId and handle"); }); it("rejects invalid source kind combinations", async () => { await expect(Effect.runPromise(createSourceFromPayload({ workspaceId: WorkspaceIdSchema.make("ws_invalid_mcp"), sourceId: SourceIdSchema.make("src_invalid_mcp"), payload: { name: "MCP", kind: "mcp", endpoint: "https://example.com/mcp", binding: { specUrl: "https://example.com/openapi.json", }, } as never, now: 1234, }))).rejects.toThrow("MCP sources cannot define specUrl"); await expect(Effect.runPromise(createSourceFromPayload({ workspaceId: WorkspaceIdSchema.make("ws_invalid_openapi_spec"), sourceId: SourceIdSchema.make("src_invalid_openapi_spec"), payload: { name: "OpenAPI", kind: "openapi", endpoint: "https://example.com", binding: openApiBinding(" "), } as never, now: 1234, }))).rejects.toThrow("OpenAPI sources require specUrl"); await expect(Effect.runPromise(createSourceFromPayload({ workspaceId: WorkspaceIdSchema.make("ws_invalid_openapi_transport"), sourceId: SourceIdSchema.make("src_invalid_openapi_transport"), payload: { name: "OpenAPI", kind: "openapi", endpoint: "https://example.com", binding: { specUrl: "https://example.com/openapi.json", transport: "sse", }, } as never, now: 1234, }))).rejects.toThrow("OpenAPI sources cannot define MCP transport settings"); await expect(Effect.runPromise(createSourceFromPayload({ workspaceId: WorkspaceIdSchema.make("ws_invalid_graphql"), sourceId: SourceIdSchema.make("src_invalid_graphql"), payload: { name: "GraphQL", kind: "graphql", endpoint: "https://example.com/graphql", binding: { specUrl: "https://example.com/openapi.json", }, } as never, now: 1234, }))).rejects.toThrow("GraphQL sources cannot define specUrl"); await expect(Effect.runPromise(createSourceFromPayload({ workspaceId: WorkspaceIdSchema.make("ws_invalid_internal"), sourceId: SourceIdSchema.make("src_invalid_internal"), payload: { name: "Internal", kind: "internal", endpoint: "internal://executor", binding: { defaultHeaders: { accept: "application/json", }, }, } as never, now: 1234, }))).rejects.toThrow("internal sources cannot define HTTP source settings"); }); it("normalizes new auth during updates", async () => { const updated = await Effect.runPromise(updateSourceFromPayload({ source: makeSource({ auth: { kind: "none" }, }), payload: { auth: { kind: "bearer", headerName: " ", prefix: "Token ", token: { providerId: " local ", handle: " sec_token ", }, } as never, }, now: 2000, })); expect(updated.auth).toEqual({ kind: "bearer", headerName: "Authorization", prefix: "Token ", token: { providerId: "local", handle: "sec_token", }, }); }); }); describe("storage roundtrip", () => { it("roundtrips bearer auth and serialized maps", async () => { const source = makeSource({ kind: "mcp", binding: mcpBinding({ transport: "auto", queryParams: { page: "1" }, headers: { "x-api-key": "secret" }, }), auth: { kind: "bearer", headerName: "Authorization", prefix: "Bearer ", token: { providerId: "local", handle: "sec_bearer", }, }, }); const catalogId = stableSourceCatalogId(source); const catalogRevisionId = stableSourceCatalogRevisionId(source); const existingCredentialId = CredentialIdSchema.make("cred_existing"); const { sourceRecord, runtimeAuthArtifact } = splitSourceForStorage({ source, catalogId, catalogRevisionId, existingRuntimeAuthArtifactId: existingCredentialId, }); expect(runtimeAuthArtifact?.id).toBe(existingCredentialId); const decoded = runtimeAuthArtifact ? decodeBuiltInAuthArtifactConfig(runtimeAuthArtifact) : null; expect(decoded?.artifactKind).toBe("static_bearer"); expect(JSON.parse(sourceRecord.bindingConfigJson ?? "{}")).toEqual({ adapterKey: "mcp", version: 1, payload: source.binding, }); const projected = await Effect.runPromise(projectSourceFromStorage({ sourceRecord, runtimeAuthArtifact: runtimeAuthArtifact ?? null, importAuthArtifact: null, })); expect(projected).toEqual(source); }); it("roundtrips oauth2 auth with and without refresh tokens", async () => { const withRefresh = makeSource({ kind: "graphql", endpoint: "https://example.com/graphql", binding: graphqlBinding({ accept: "application/json" }), auth: { kind: "oauth2", headerName: "Authorization", prefix: "Bearer ", accessToken: { providerId: "local", handle: "sec_access", }, refreshToken: { providerId: "local", handle: "sec_refresh", }, }, }); const withoutRefresh = makeSource({ id: SourceIdSchema.make("src_source_definitions_no_refresh"), kind: "graphql", endpoint: "https://example.com/graphql", binding: graphqlBinding({ accept: "application/json" }), auth: { kind: "oauth2", headerName: "Authorization", prefix: "Bearer ", accessToken: { providerId: "local", handle: "sec_access", }, refreshToken: null, }, }); for (const source of [withRefresh, withoutRefresh]) { const { sourceRecord, runtimeAuthArtifact } = splitSourceForStorage({ source, catalogId: stableSourceCatalogId(source), catalogRevisionId: stableSourceCatalogRevisionId(source), }); const projected = await Effect.runPromise(projectSourceFromStorage({ sourceRecord, runtimeAuthArtifact: runtimeAuthArtifact ?? null, importAuthArtifact: null, })); expect(projected).toEqual(source); } }); it("stores no credential for auth.kind none and projects back correctly", async () => { const source = makeSource({ auth: { kind: "none" }, }); const { sourceRecord, runtimeAuthArtifact } = splitSourceForStorage({ source, catalogId: stableSourceCatalogId(source), catalogRevisionId: stableSourceCatalogRevisionId(source), }); expect(runtimeAuthArtifact).toBeNull(); const projected = await Effect.runPromise(projectSourceFromStorage({ sourceRecord, runtimeAuthArtifact: null, importAuthArtifact: null, })); expect(projected.auth).toEqual({ kind: "none" }); expect(projected).toEqual(source); }); }); describe("namespaceFromSourceName", () => { it("normalizes names into namespace-safe dotted segments", () => { expect(namespaceFromSourceName("My API v2!")).toBe("my.api.v2"); expect(namespaceFromSourceName(" ")).toBe("source"); expect(namespaceFromSourceName("!!!")).toBe("source"); }); });});
import { describe, expect, it } from "@effect/vitest";
import * as Effect from "effect/Effect";
import {
CredentialIdSchema,
decodeBuiltInAuthArtifactConfig,
SourceIdSchema,
WorkspaceIdSchema,
type Source,
} from "#schema";
import {
createSourceFromPayload,
projectSourceFromStorage,
splitSourceForStorage,
stableSourceCatalogId,
stableSourceCatalogRevisionId,
updateSourceFromPayload,
} from "./source-definitions";
import { namespaceFromSourceName } from "./source-names";
const openApiBinding = (
specUrl = "https://api.github.com/openapi.json",
defaultHeaders: Record<string, string> | null = null,
) => ({
specUrl,
defaultHeaders,
});
const graphqlBinding = (defaultHeaders: Record<string, string> | null = null) => ({
defaultHeaders,
});
const mcpBinding = (input: {
transport?: "auto" | "streamable-http" | "sse" | null;
queryParams?: Record<string, string> | null;
headers?: Record<string, string> | null;
} = {}) => ({
transport: input.transport ?? null,
queryParams: input.queryParams ?? null,
headers: input.headers ?? null,
});
const makeSource = (overrides: Partial<Source> = {}): Source => ({
id: SourceIdSchema.make("src_source_definitions"),
workspaceId: WorkspaceIdSchema.make("ws_source_definitions"),
name: "GitHub",
kind: "openapi",
endpoint: "https://api.github.com",
status: "connected",
enabled: true,
namespace: "github",
bindingVersion: 1,
binding: openApiBinding(),
importAuthPolicy: "reuse_runtime",
importAuth: { kind: "none" },
auth: { kind: "none" },
sourceHash: null,
lastError: null,
createdAt: 1000,
updatedAt: 1000,
...overrides,
});
describe("source-definitions", () => {
describe("stable catalog ids", () => {
it("is deterministic across calls and ignores source name/workspace", () => {
const source = makeSource();
const renamed = makeSource({
name: "Renamed GitHub",
});
const differentWorkspace = makeSource({
workspaceId: WorkspaceIdSchema.make("ws_source_definitions_other"),
});
expect(stableSourceCatalogId(source)).toBe(stableSourceCatalogId(source));
expect(stableSourceCatalogRevisionId(source)).toBe(stableSourceCatalogRevisionId(source));
expect(stableSourceCatalogId(renamed)).toBe(stableSourceCatalogId(source));
expect(stableSourceCatalogRevisionId(renamed)).toBe(stableSourceCatalogRevisionId(source));
expect(stableSourceCatalogId(differentWorkspace)).toBe(stableSourceCatalogId(source));
expect(stableSourceCatalogRevisionId(differentWorkspace)).toBe(
stableSourceCatalogRevisionId(source),
);
});
it("changes catalog and revision ids when the source config changes", () => {
const source = makeSource();
const changedEndpoint = makeSource({
endpoint: "https://example.com",
binding: openApiBinding("https://example.com/openapi.json"),
});
expect(stableSourceCatalogId(changedEndpoint)).not.toBe(stableSourceCatalogId(source));
expect(stableSourceCatalogRevisionId(changedEndpoint)).not.toBe(
stableSourceCatalogRevisionId(source),
);
});
});
describe("payload normalization and validation", () => {
it("defaults created sources to draft/enabled and trims fields", async () => {
const source = await Effect.runPromise(createSourceFromPayload({
workspaceId: WorkspaceIdSchema.make("ws_create_defaults"),
sourceId: SourceIdSchema.make("src_create_defaults"),
payload: {
name: " GitHub ",
kind: "openapi",
endpoint: " https://api.github.com ",
binding: openApiBinding(" https://api.github.com/openapi.json "),
},
now: 1234,
}));
expect(source.name).toBe("GitHub");
expect(source.endpoint).toBe("https://api.github.com");
expect(source.binding).toEqual(openApiBinding("https://api.github.com/openapi.json"));
expect(source.status).toBe("draft");
expect(source.enabled).toBe(true);
expect(source.auth).toEqual({ kind: "none" });
});
it("preserves existing values on partial update and keeps auth when undefined", async () => {
const source = makeSource({
kind: "graphql",
endpoint: "https://example.com/graphql",
binding: graphqlBinding({ accept: "application/json" }),
auth: {
kind: "bearer",
headerName: "Authorization",
prefix: "Bearer ",
token: {
providerId: "local",
handle: "sec_token",
},
},
});
const updated = await Effect.runPromise(updateSourceFromPayload({
source,
payload: {
status: "error",
lastError: "bad gateway",
},
now: 2000,
}));
expect(updated.name).toBe(source.name);
expect(updated.endpoint).toBe(source.endpoint);
expect(updated.binding).toEqual(source.binding);
expect(updated.auth).toEqual(source.auth);
expect(updated.status).toBe("error");
expect(updated.lastError).toBe("bad gateway");
expect(updated.updatedAt).toBe(2000);
});
it("normalizes oauth2 auth defaults and allows null refresh tokens", async () => {
const source = await Effect.runPromise(createSourceFromPayload({
workspaceId: WorkspaceIdSchema.make("ws_create_oauth_defaults"),
sourceId: SourceIdSchema.make("src_create_oauth_defaults"),
payload: {
name: "GraphQL Demo",
kind: "graphql",
endpoint: "https://example.com/graphql",
auth: {
kind: "oauth2",
headerName: " ",
prefix: undefined,
accessToken: {
providerId: " local ",
handle: " sec_access ",
},
refreshToken: null,
} as never,
},
now: 1234,
}));
expect(source.auth).toEqual({
kind: "oauth2",
headerName: "Authorization",
prefix: "Bearer ",
accessToken: {
providerId: "local",
handle: "sec_access",
},
refreshToken: null,
});
});
it("rejects invalid bearer and oauth2 secret refs", async () => {
await expect(Effect.runPromise(createSourceFromPayload({
workspaceId: WorkspaceIdSchema.make("ws_invalid_bearer"),
sourceId: SourceIdSchema.make("src_invalid_bearer"),
payload: {
name: "Bad Bearer",
kind: "openapi",
endpoint: "https://example.com",
binding: openApiBinding("https://example.com/openapi.json"),
auth: {
kind: "bearer",
headerName: "Authorization",
prefix: "Bearer ",
token: {
providerId: " ",
handle: "sec_token",
},
},
},
now: 1234,
}))).rejects.toThrow("Bearer auth requires a token secret ref");
await expect(Effect.runPromise(createSourceFromPayload({
workspaceId: WorkspaceIdSchema.make("ws_invalid_refresh"),
sourceId: SourceIdSchema.make("src_invalid_refresh"),
payload: {
name: "Bad OAuth",
kind: "graphql",
endpoint: "https://example.com/graphql",
binding: graphqlBinding(),
auth: {
kind: "oauth2",
headerName: "Authorization",
prefix: "Bearer ",
accessToken: {
providerId: "local",
handle: "sec_access",
},
refreshToken: {
providerId: "local",
handle: " ",
},
} as never,
},
now: 1234,
}))).rejects.toThrow("OAuth2 refresh token ref must include providerId and handle");
});
it("rejects invalid source kind combinations", async () => {
await expect(Effect.runPromise(createSourceFromPayload({
workspaceId: WorkspaceIdSchema.make("ws_invalid_mcp"),
sourceId: SourceIdSchema.make("src_invalid_mcp"),
payload: {
name: "MCP",
kind: "mcp",
endpoint: "https://example.com/mcp",
binding: {
specUrl: "https://example.com/openapi.json",
},
} as never,
now: 1234,
}))).rejects.toThrow("MCP sources cannot define specUrl");
await expect(Effect.runPromise(createSourceFromPayload({
workspaceId: WorkspaceIdSchema.make("ws_invalid_openapi_spec"),
sourceId: SourceIdSchema.make("src_invalid_openapi_spec"),
payload: {
name: "OpenAPI",
kind: "openapi",
endpoint: "https://example.com",
binding: openApiBinding(" "),
} as never,
now: 1234,
}))).rejects.toThrow("OpenAPI sources require specUrl");
await expect(Effect.runPromise(createSourceFromPayload({
workspaceId: WorkspaceIdSchema.make("ws_invalid_openapi_transport"),
sourceId: SourceIdSchema.make("src_invalid_openapi_transport"),
payload: {
name: "OpenAPI",
kind: "openapi",
endpoint: "https://example.com",
binding: {
specUrl: "https://example.com/openapi.json",
transport: "sse",
},
} as never,
now: 1234,
}))).rejects.toThrow("OpenAPI sources cannot define MCP transport settings");
await expect(Effect.runPromise(createSourceFromPayload({
workspaceId: WorkspaceIdSchema.make("ws_invalid_graphql"),
sourceId: SourceIdSchema.make("src_invalid_graphql"),
payload: {
name: "GraphQL",
kind: "graphql",
endpoint: "https://example.com/graphql",
binding: {
specUrl: "https://example.com/openapi.json",
},
} as never,
now: 1234,
}))).rejects.toThrow("GraphQL sources cannot define specUrl");
await expect(Effect.runPromise(createSourceFromPayload({
workspaceId: WorkspaceIdSchema.make("ws_invalid_internal"),
sourceId: SourceIdSchema.make("src_invalid_internal"),
payload: {
name: "Internal",
kind: "internal",
endpoint: "internal://executor",
binding: {
defaultHeaders: {
accept: "application/json",
},
},
} as never,
now: 1234,
}))).rejects.toThrow("internal sources cannot define HTTP source settings");
});
it("normalizes new auth during updates", async () => {
const updated = await Effect.runPromise(updateSourceFromPayload({
source: makeSource({
auth: { kind: "none" },
}),
payload: {
auth: {
kind: "bearer",
headerName: " ",
prefix: "Token ",
token: {
providerId: " local ",
handle: " sec_token ",
},
} as never,
},
now: 2000,
}));
expect(updated.auth).toEqual({
kind: "bearer",
headerName: "Authorization",
prefix: "Token ",
token: {
providerId: "local",
handle: "sec_token",
},
});
});
});
describe("storage roundtrip", () => {
it("roundtrips bearer auth and serialized maps", async () => {
const source = makeSource({
kind: "mcp",
binding: mcpBinding({
transport: "auto",
queryParams: { page: "1" },
headers: { "x-api-key": "secret" },
}),
auth: {
kind: "bearer",
headerName: "Authorization",
prefix: "Bearer ",
token: {
providerId: "local",
handle: "sec_bearer",
},
},
});
const catalogId = stableSourceCatalogId(source);
const catalogRevisionId = stableSourceCatalogRevisionId(source);
const existingCredentialId = CredentialIdSchema.make("cred_existing");
const { sourceRecord, runtimeAuthArtifact } = splitSourceForStorage({
source,
catalogId,
catalogRevisionId,
existingRuntimeAuthArtifactId: existingCredentialId,
});
expect(runtimeAuthArtifact?.id).toBe(existingCredentialId);
const decoded = runtimeAuthArtifact ? decodeBuiltInAuthArtifactConfig(runtimeAuthArtifact) : null;
expect(decoded?.artifactKind).toBe("static_bearer");
expect(JSON.parse(sourceRecord.bindingConfigJson ?? "{}")).toEqual({
adapterKey: "mcp",
version: 1,
payload: source.binding,
});
const projected = await Effect.runPromise(projectSourceFromStorage({
sourceRecord,
runtimeAuthArtifact: runtimeAuthArtifact ?? null,
importAuthArtifact: null,
}));
expect(projected).toEqual(source);
});
it("roundtrips oauth2 auth with and without refresh tokens", async () => {
const withRefresh = makeSource({
kind: "graphql",
endpoint: "https://example.com/graphql",
binding: graphqlBinding({ accept: "application/json" }),
auth: {
kind: "oauth2",
headerName: "Authorization",
prefix: "Bearer ",
accessToken: {
providerId: "local",
handle: "sec_access",
},
refreshToken: {
providerId: "local",
handle: "sec_refresh",
},
},
});
const withoutRefresh = makeSource({
id: SourceIdSchema.make("src_source_definitions_no_refresh"),
kind: "graphql",
endpoint: "https://example.com/graphql",
binding: graphqlBinding({ accept: "application/json" }),
auth: {
kind: "oauth2",
headerName: "Authorization",
prefix: "Bearer ",
accessToken: {
providerId: "local",
handle: "sec_access",
},
refreshToken: null,
},
});
for (const source of [withRefresh, withoutRefresh]) {
const { sourceRecord, runtimeAuthArtifact } = splitSourceForStorage({
source,
catalogId: stableSourceCatalogId(source),
catalogRevisionId: stableSourceCatalogRevisionId(source),
});
const projected = await Effect.runPromise(projectSourceFromStorage({
sourceRecord,
runtimeAuthArtifact: runtimeAuthArtifact ?? null,
importAuthArtifact: null,
}));
expect(projected).toEqual(source);
}
});
it("stores no credential for auth.kind none and projects back correctly", async () => {
const source = makeSource({
auth: { kind: "none" },
});
const { sourceRecord, runtimeAuthArtifact } = splitSourceForStorage({
source,
catalogId: stableSourceCatalogId(source),
catalogRevisionId: stableSourceCatalogRevisionId(source),
});
expect(runtimeAuthArtifact).toBeNull();
const projected = await Effect.runPromise(projectSourceFromStorage({
sourceRecord,
runtimeAuthArtifact: null,
importAuthArtifact: null,
}));
expect(projected.auth).toEqual({ kind: "none" });
expect(projected).toEqual(source);
});
});
describe("namespaceFromSourceName", () => {
it("normalizes names into namespace-safe dotted segments", () => {
expect(namespaceFromSourceName("My API v2!")).toBe("my.api.v2");
expect(namespaceFromSourceName(" ")).toBe("source");
expect(namespaceFromSourceName("!!!")).toBe("source");
});
});
});