Unified · Split
| @@ -1,93 +0,0 @@ | |||
| 1 | import { | ||
| 2 | type SourceCredentialBinding, | ||
| 3 | SourceCredentialBindingSchema, | ||
| 4 | } from "#schema"; | ||
| 5 | import * as Option from "effect/Option"; | ||
| 6 | import { Schema } from "effect"; | ||
| 7 | import { and, asc, eq } from "drizzle-orm"; | ||
| 8 | |||
| 9 | import type { DrizzleClient } from "../client"; | ||
| 10 | import type { DrizzleTables } from "../schema"; | ||
| 11 | import { firstOption, withoutCreatedAt } from "./shared"; | ||
| 12 | |||
| 13 | const decodeSourceCredentialBinding = Schema.decodeUnknownSync( | ||
| 14 | SourceCredentialBindingSchema, | ||
| 15 | ); | ||
| 16 | |||
| 17 | export const createSourceCredentialBindingsRepo = ( | ||
| 18 | client: DrizzleClient, | ||
| 19 | tables: DrizzleTables, | ||
| 20 | ) => ({ | ||
| 21 | listByWorkspaceId: (workspaceId: SourceCredentialBinding["workspaceId"]) => | ||
| 22 | client.use("rows.source_credential_bindings.list_by_workspace", async (db) => { | ||
| 23 | const rows = await db | ||
| 24 | .select() | ||
| 25 | .from(tables.sourceCredentialBindingsTable) | ||
| 26 | .where(eq(tables.sourceCredentialBindingsTable.workspaceId, workspaceId)) | ||
| 27 | .orderBy( | ||
| 28 | asc(tables.sourceCredentialBindingsTable.updatedAt), | ||
| 29 | asc(tables.sourceCredentialBindingsTable.sourceId), | ||
| 30 | ); | ||
| 31 | |||
| 32 | return rows.map((row) => decodeSourceCredentialBinding(row)); | ||
| 33 | }), | ||
| 34 | |||
| 35 | getByWorkspaceAndSourceId: ( | ||
| 36 | workspaceId: SourceCredentialBinding["workspaceId"], | ||
| 37 | sourceId: SourceCredentialBinding["sourceId"], | ||
| 38 | ) => | ||
| 39 | client.use( | ||
| 40 | "rows.source_credential_bindings.get_by_workspace_and_source_id", | ||
| 41 | async (db) => { | ||
| 42 | const rows = await db | ||
| 43 | .select() | ||
| 44 | .from(tables.sourceCredentialBindingsTable) | ||
| 45 | .where( | ||
| 46 | and( | ||
| 47 | eq(tables.sourceCredentialBindingsTable.workspaceId, workspaceId), | ||
| 48 | eq(tables.sourceCredentialBindingsTable.sourceId, sourceId), | ||
| 49 | ), | ||
| 50 | ) | ||
| 51 | .limit(1); | ||
| 52 | |||
| 53 | const row = firstOption(rows); | ||
| 54 | return Option.isSome(row) | ||
| 55 | ? Option.some(decodeSourceCredentialBinding(row.value)) | ||
| 56 | : Option.none<SourceCredentialBinding>(); | ||
| 57 | }, | ||
| 58 | ), | ||
| 59 | |||
| 60 | upsert: (binding: SourceCredentialBinding) => | ||
| 61 | client.use("rows.source_credential_bindings.upsert", async (db) => { | ||
| 62 | await db | ||
| 63 | .insert(tables.sourceCredentialBindingsTable) | ||
| 64 | .values(binding) | ||
| 65 | .onConflictDoUpdate({ | ||
| 66 | target: [ | ||
| 67 | tables.sourceCredentialBindingsTable.workspaceId, | ||
| 68 | tables.sourceCredentialBindingsTable.sourceId, | ||
| 69 | ], | ||
| 70 | set: { | ||
| 71 | ...withoutCreatedAt(binding), | ||
| 72 | }, | ||
| 73 | }); | ||
| 74 | }), | ||
| 75 | |||
| 76 | removeByWorkspaceAndSourceId: ( | ||
| 77 | workspaceId: SourceCredentialBinding["workspaceId"], | ||
| 78 | sourceId: SourceCredentialBinding["sourceId"], | ||
| 79 | ) => | ||
| 80 | client.use("rows.source_credential_bindings.remove", async (db) => { | ||
| 81 | const deleted = await db | ||
| 82 | .delete(tables.sourceCredentialBindingsTable) | ||
| 83 | .where( | ||
| 84 | and( | ||
| 85 | eq(tables.sourceCredentialBindingsTable.workspaceId, workspaceId), | ||
| 86 | eq(tables.sourceCredentialBindingsTable.sourceId, sourceId), | ||
| 87 | ), | ||
| 88 | ) | ||
| 89 | .returning(); | ||
| 90 | |||
| 91 | return deleted.length > 0; | ||
| 92 | }), | ||
| 93 | }); | ||
| @@ -12,6 +12,8 @@ import { · 11 unmodified lines | |||
| 12 | ExecutionInteractionIdSchema, | 12 | ExecutionInteractionIdSchema, |
| 13 | SecretMaterialIdSchema, | 13 | SecretMaterialIdSchema, |
| 14 | SourceIdSchema, | 14 | SourceIdSchema, |
| 15 | SourceRecipeIdSchema, | ||
| 16 | SourceRecipeRevisionIdSchema, | ||
| 15 | } from "#schema"; | 17 | } from "#schema"; |
| 16 | import type { ToolPath } from "@executor/codemode-core"; | 18 | import type { ToolPath } from "@executor/codemode-core"; |
| 17 | 19 | ||
| @@ -278,12 +280,15 @@ describe("control-plane-runtime", () => { · 260 unmodified lines | |||
| 278 | yield* runtime.persistence.rows.sources.insert({ | 280 | yield* runtime.persistence.rows.sources.insert({ |
| 279 | id: sourceId, | 281 | id: sourceId, |
| 280 | workspaceId: installation.workspaceId, | 282 | workspaceId: installation.workspaceId, |
| 283 | recipeId: SourceRecipeIdSchema.make(`src_recipe_${sourceId}`), | ||
| 284 | recipeRevisionId: SourceRecipeRevisionIdSchema.make(`src_recipe_rev_${sourceId}`), | ||
| 281 | name: "GitHub", | 285 | name: "GitHub", |
| 282 | kind: "openapi", | 286 | kind: "openapi", |
| 283 | endpoint: "https://api.github.com", | 287 | endpoint: "https://api.github.com", |
| 284 | status: "auth_required", | 288 | status: "auth_required", |
| 285 | enabled: true, | 289 | enabled: true, |
| 286 | namespace: "github", | 290 | namespace: "github", |
| 291 | bindingConfigJson: null, | ||
| 287 | transport: null, | 292 | transport: null, |
| 288 | queryParamsJson: null, | 293 | queryParamsJson: null, |
| 289 | headersJson: null, | 294 | headersJson: null, |
| @@ -435,12 +440,15 @@ describe("control-plane-runtime", () => { · 145 unmodified lines | |||
| 435 | yield* runtime.persistence.rows.sources.insert({ | 440 | yield* runtime.persistence.rows.sources.insert({ |
| 436 | id: sourceId, | 441 | id: sourceId, |
| 437 | workspaceId: installation.workspaceId, | 442 | workspaceId: installation.workspaceId, |
| 443 | recipeId: SourceRecipeIdSchema.make(`src_recipe_${sourceId}`), | ||
| 444 | recipeRevisionId: SourceRecipeRevisionIdSchema.make(`src_recipe_rev_${sourceId}`), | ||
| 438 | name: "GitHub", | 445 | name: "GitHub", |
| 439 | kind: "openapi", | 446 | kind: "openapi", |
| 440 | endpoint: "https://api.github.com", | 447 | endpoint: "https://api.github.com", |
| 441 | status: "auth_required", | 448 | status: "auth_required", |
| 442 | enabled: true, | 449 | enabled: true, |
| 443 | namespace: "github", | 450 | namespace: "github", |
| 451 | bindingConfigJson: null, | ||
| 444 | transport: null, | 452 | transport: null, |
| 445 | queryParamsJson: null, | 453 | queryParamsJson: null, |
| 446 | headersJson: null, | 454 | headersJson: null, |
| @@ -32,6 +32,8 @@ import { · 31 unmodified lines | |||
| 32 | ExecutionIdSchema, | 32 | ExecutionIdSchema, |
| 33 | SecretMaterialIdSchema, | 33 | SecretMaterialIdSchema, |
| 34 | SourceIdSchema, | 34 | SourceIdSchema, |
| 35 | SourceRecipeIdSchema, | ||
| 36 | SourceRecipeRevisionIdSchema, | ||
| 35 | WorkspaceIdSchema, | 37 | WorkspaceIdSchema, |
| 36 | } from "#schema"; | 38 | } from "#schema"; |
| 37 | import * as Context from "effect/Context"; | 39 | import * as Context from "effect/Context"; |
| @@ -271,7 +273,8 @@ const testGraphqlSchema = new GraphQLSchema({ · 233 unmodified lines | |||
| 271 | const closeScope = (scope: Scope.CloseableScope) => | 273 | const closeScope = (scope: Scope.CloseableScope) => |
| 272 | Scope.close(scope, Exit.void).pipe(Effect.orDie); | 274 | Scope.close(scope, Exit.void).pipe(Effect.orDie); |
| 273 | 275 | ||
| 274 | const makePersistence = Effect.acquireRelease( | 276 | const makePersistence: Effect.Effect<SqlControlPlanePersistence, unknown, Scope.Scope> = |
| 277 | Effect.acquireRelease( | ||
| 275 | createSqlControlPlanePersistence({ | 278 | createSqlControlPlanePersistence({ |
| 276 | localDataDir: ":memory:", | 279 | localDataDir: ":memory:", |
| 277 | }), | 280 | }), |
| @@ -280,7 +283,7 @@ const makePersistence = Effect.acquireRelease( · 2 unmodified lines | |||
| 280 | try: () => persistence.close(), | 283 | try: () => persistence.close(), |
| 281 | catch: (cause) => (cause instanceof Error ? cause : new Error(String(cause))), | 284 | catch: (cause) => (cause instanceof Error ? cause : new Error(String(cause))), |
| 282 | }).pipe(Effect.orDie), | 285 | }).pipe(Effect.orDie), |
| 283 | ); | 286 | ); |
| 284 | 287 | ||
| 285 | const makeCountedMcpServer = Effect.acquireRelease( | 288 | const makeCountedMcpServer = Effect.acquireRelease( |
| 286 | Effect.promise<CountedMcpServer>( | 289 | Effect.promise<CountedMcpServer>( |
| @@ -644,12 +647,15 @@ const persistConnectedEchoTool = (input: { · 357 unmodified lines | |||
| 644 | yield* input.persistence.rows.sources.insert({ | 647 | yield* input.persistence.rows.sources.insert({ |
| 645 | id: input.sourceId, | 648 | id: input.sourceId, |
| 646 | workspaceId: input.workspaceId, | 649 | workspaceId: input.workspaceId, |
| 650 | recipeId: SourceRecipeIdSchema.make(`src_recipe_${input.sourceId}`), | ||
| 651 | recipeRevisionId: SourceRecipeRevisionIdSchema.make(`src_recipe_rev_${input.sourceId}`), | ||
| 647 | name: "Counted MCP", | 652 | name: "Counted MCP", |
| 648 | kind: "mcp", | 653 | kind: "mcp", |
| 649 | endpoint: input.endpoint, | 654 | endpoint: input.endpoint, |
| 650 | status: "connected", | 655 | status: "connected", |
| 651 | enabled: true, | 656 | enabled: true, |
| 652 | namespace: "counted", | 657 | namespace: "counted", |
| 658 | bindingConfigJson: null, | ||
| 653 | transport: "auto", | 659 | transport: "auto", |
| 654 | queryParamsJson: null, | 660 | queryParamsJson: null, |
| 655 | headersJson: null, | 661 | headersJson: null, |
| @@ -816,12 +822,15 @@ const persistConnectedGithubOpenApiSource = (input: { · 160 unmodified lines | |||
| 816 | yield* input.persistence.rows.sources.insert({ | 822 | yield* input.persistence.rows.sources.insert({ |
| 817 | id: input.sourceId, | 823 | id: input.sourceId, |
| 818 | workspaceId: input.workspaceId, | 824 | workspaceId: input.workspaceId, |
| 825 | recipeId: SourceRecipeIdSchema.make(`src_recipe_${input.sourceId}`), | ||
| 826 | recipeRevisionId: SourceRecipeRevisionIdSchema.make(`src_recipe_rev_${input.sourceId}`), | ||
| 819 | name: "GitHub", | 827 | name: "GitHub", |
| 820 | kind: "openapi", | 828 | kind: "openapi", |
| 821 | endpoint: input.endpoint ?? "https://api.github.com", | 829 | endpoint: input.endpoint ?? "https://api.github.com", |
| 822 | status: "connected", | 830 | status: "connected", |
| 823 | enabled: true, | 831 | enabled: true, |
| 824 | namespace: "github", | 832 | namespace: "github", |
| 833 | bindingConfigJson: null, | ||
| 825 | transport: null, | 834 | transport: null, |
| 826 | queryParamsJson: null, | 835 | queryParamsJson: null, |
| 827 | headersJson: null, | 836 | headersJson: null, |
| @@ -839,6 +848,8 @@ const persistConnectedGithubOpenApiSource = (input: { · 11 unmodified lines | |||
| 839 | yield* input.persistence.rows.credentials.upsert({ | 848 | yield* input.persistence.rows.credentials.upsert({ |
| 840 | id: credentialId, | 849 | id: credentialId, |
| 841 | workspaceId: input.workspaceId, | 850 | workspaceId: input.workspaceId, |
| 851 | sourceId: input.sourceId, | ||
| 852 | actorAccountId: null, | ||
| 842 | authKind: "bearer", | 853 | authKind: "bearer", |
| 843 | authHeaderName: "Authorization", | 854 | authHeaderName: "Authorization", |
| 844 | authPrefix: "Bearer ", | 855 | authPrefix: "Bearer ", |
| @@ -849,14 +860,6 @@ const persistConnectedGithubOpenApiSource = (input: { · 4 unmodified lines | |||
| 849 | createdAt: now, | 860 | createdAt: now, |
| 850 | updatedAt: now, | 861 | updatedAt: now, |
| 851 | }); | 862 | }); |
| 852 | yield* input.persistence.rows.sourceCredentialBindings.upsert({ | ||
| 853 | id: `src_cred_bind_${randomUUID()}`, | ||
| 854 | workspaceId: input.workspaceId, | ||
| 855 | sourceId: input.sourceId, | ||
| 856 | credentialId, | ||
| 857 | createdAt: now, | ||
| 858 | updatedAt: now, | ||
| 859 | }); | ||
| 860 | }; | 863 | }; |
| 861 | 864 | ||
| 862 | }); | 865 | }); |