MCPcopy Create free account
hub / github.com/UsefulSoftwareCo/executor / createClient

Function createClient

packages/core/sdk/src/oauth-service.ts:801–881  ·  view source on GitHub ↗
(
    input: CreateOAuthClientInput,
  )

Source from the content-addressed store, hash-verified

799 // createClient — write the oauth_client row.
800 // -----------------------------------------------------------------------
801 const createClient = (
802 input: CreateOAuthClientInput,
803 ): Effect.Effect<OAuthClientSlug, StorageFailure> =>
804 Effect.gen(function* () {
805 // The `first-party:` namespace is reserved for config-declared apps — a
806 // stored row under it would be shadowed by (or worse, impersonate) the
807 // host's own app.
808 if (isFirstPartyOAuthClientSlug(String(input.slug))) {
809 return yield* new StorageError({
810 message: `OAuth client slug "${String(input.slug)}" uses the reserved first-party namespace.`,
811 cause: undefined,
812 });
813 }
814 yield* validateClientEndpoints(input, deps.endpointUrlPolicy);
815 const keys = yield* Effect.try({
816 try: () => deps.ownedKeys(input.owner),
817 catch: (cause) =>
818 new StorageError({
819 message: "Cannot write oauth_client for owner without a subject",
820 cause,
821 }),
822 });
823 const now = new Date();
824
825 // Store the secret out-of-band in the default writable provider; the row
826 // keeps only its item id. A public/PKCE client (empty secret) stores null
827 // — there is no plaintext column to fall back to (the schema dropped it).
828 let clientSecretItemIdValue: string | null = null;
829 if (input.clientSecret.length > 0) {
830 const provider = deps.defaultWritableProvider();
831 if (!provider || !provider.set) {
832 return yield* new StorageError({
833 message:
834 "No default writable credential provider is registered to store the OAuth client secret.",
835 cause: undefined,
836 });
837 }
838 clientSecretItemIdValue = clientSecretItemId(input.owner, input.slug);
839 yield* provider.set(ProviderItemId.make(clientSecretItemIdValue), input.clientSecret);
840 }
841
842 yield* deps.fuma
843 .use("oauth_client.deleteExisting", (db) =>
844 looseDb(db).deleteMany("oauth_client", {
845 where: (b: any) =>
846 b.and(b("owner", "=", input.owner), b("slug", "=", String(input.slug))),
847 }),
848 )
849 .pipe(Effect.catch(() => Effect.void));
850 yield* deps.fuma.use("oauth_client.create", (db) =>
851 looseDb(db).create("oauth_client", {
852 tenant: keys.tenant,
853 owner: keys.owner,
854 subject: keys.subject,
855 slug: String(input.slug),
856 authorization_url: input.authorizationUrl,
857 token_url: input.tokenUrl,
858 grant: input.grant,

Callers 13

registerClientsFunction · 0.70
createSqliteTestFumaDbFunction · 0.70
registerClientsFunction · 0.70
registerDynamicClientFunction · 0.70
createFunction · 0.50
openOwnershipLockClientFunction · 0.50
openLocalLibsqlFunction · 0.50

Calls 6

canonicalIssuerUrlFunction · 0.90
validateClientEndpointsFunction · 0.85
clientSecretItemIdFunction · 0.85
looseDbFunction · 0.85
setMethod · 0.65

Tested by 2

registerClientsFunction · 0.56
registerClientsFunction · 0.56