better-auth
Version:
The most comprehensive authentication framework for TypeScript.
1 lines • 21.2 kB
Source Map (JSON)
{"version":3,"file":"update-api-key.mjs","names":["apiKey: ApiKey | null","newValues: Partial<ApiKey>","newApiKey: ApiKey","updated: ApiKey","error: any"],"sources":["../../../../src/plugins/api-key/routes/update-api-key.ts"],"sourcesContent":["import type { AuthContext } from \"@better-auth/core\";\nimport { createAuthEndpoint } from \"@better-auth/core/api\";\nimport { safeJSONParse } from \"@better-auth/core/utils\";\nimport * as z from \"zod\";\nimport { APIError, getSessionFromCtx } from \"../../../api\";\nimport { getDate } from \"../../../utils/date\";\nimport { API_KEY_TABLE_NAME, ERROR_CODES } from \"..\";\nimport { getApiKeyById, setApiKey } from \"../adapter\";\nimport type { apiKeySchema } from \"../schema\";\nimport type { ApiKey } from \"../types\";\nimport type { PredefinedApiKeyOptions } from \".\";\n\nconst updateApiKeyBodySchema = z.object({\n\tkeyId: z.string().meta({\n\t\tdescription: \"The id of the Api Key\",\n\t}),\n\tuserId: z.coerce\n\t\t.string()\n\t\t.meta({\n\t\t\tdescription:\n\t\t\t\t'The id of the user which the api key belongs to. server-only. Eg: \"some-user-id\"',\n\t\t})\n\t\t.optional(),\n\tname: z\n\t\t.string()\n\t\t.meta({\n\t\t\tdescription: \"The name of the key\",\n\t\t})\n\t\t.optional(),\n\tenabled: z\n\t\t.boolean()\n\t\t.meta({\n\t\t\tdescription: \"Whether the Api Key is enabled or not\",\n\t\t})\n\t\t.optional(),\n\tremaining: z\n\t\t.number()\n\t\t.meta({\n\t\t\tdescription: \"The number of remaining requests\",\n\t\t})\n\t\t.min(1)\n\t\t.optional(),\n\trefillAmount: z\n\t\t.number()\n\t\t.meta({\n\t\t\tdescription: \"The refill amount\",\n\t\t})\n\t\t.optional(),\n\trefillInterval: z\n\t\t.number()\n\t\t.meta({\n\t\t\tdescription: \"The refill interval\",\n\t\t})\n\t\t.optional(),\n\tmetadata: z.any().optional(),\n\texpiresIn: z\n\t\t.number()\n\t\t.meta({\n\t\t\tdescription: \"Expiration time of the Api Key in seconds\",\n\t\t})\n\t\t.min(1)\n\t\t.optional()\n\t\t.nullable(),\n\trateLimitEnabled: z\n\t\t.boolean()\n\t\t.meta({\n\t\t\tdescription: \"Whether the key has rate limiting enabled.\",\n\t\t})\n\t\t.optional(),\n\trateLimitTimeWindow: z\n\t\t.number()\n\t\t.meta({\n\t\t\tdescription:\n\t\t\t\t\"The duration in milliseconds where each request is counted. server-only. Eg: 1000\",\n\t\t})\n\t\t.optional(),\n\trateLimitMax: z\n\t\t.number()\n\t\t.meta({\n\t\t\tdescription:\n\t\t\t\t\"Maximum amount of requests allowed within a window. Once the `maxRequests` is reached, the request will be rejected until the `timeWindow` has passed, at which point the `timeWindow` will be reset. server-only. Eg: 100\",\n\t\t})\n\t\t.optional(),\n\tpermissions: z\n\t\t.record(z.string(), z.array(z.string()))\n\t\t.meta({\n\t\t\tdescription: \"Update the permissions on the API Key. server-only.\",\n\t\t})\n\t\t.optional()\n\t\t.nullable(),\n});\n\nexport function updateApiKey({\n\topts,\n\tschema,\n\tdeleteAllExpiredApiKeys,\n}: {\n\topts: PredefinedApiKeyOptions;\n\tschema: ReturnType<typeof apiKeySchema>;\n\tdeleteAllExpiredApiKeys(\n\t\tctx: AuthContext,\n\t\tbyPassLastCheckTime?: boolean | undefined,\n\t): void;\n}) {\n\treturn createAuthEndpoint(\n\t\t\"/api-key/update\",\n\t\t{\n\t\t\tmethod: \"POST\",\n\t\t\tbody: updateApiKeyBodySchema,\n\t\t\tmetadata: {\n\t\t\t\topenapi: {\n\t\t\t\t\tdescription: \"Update an existing API key by ID\",\n\t\t\t\t\tresponses: {\n\t\t\t\t\t\t\"200\": {\n\t\t\t\t\t\t\tdescription: \"API key updated successfully\",\n\t\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\t\t\"application/json\": {\n\t\t\t\t\t\t\t\t\tschema: {\n\t\t\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\t\t\t\t\tid: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\tdescription: \"ID\",\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\tname: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\tnullable: true,\n\t\t\t\t\t\t\t\t\t\t\t\tdescription: \"The name of the key\",\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\tstart: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\tnullable: true,\n\t\t\t\t\t\t\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"Shows the first few characters of the API key, including the prefix. This allows you to show those few characters in the UI to make it easier for users to identify the API key.\",\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\tprefix: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\tnullable: true,\n\t\t\t\t\t\t\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"The API Key prefix. Stored as plain text.\",\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\tuserId: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\tdescription: \"The owner of the user id\",\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\trefillInterval: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"number\",\n\t\t\t\t\t\t\t\t\t\t\t\tnullable: true,\n\t\t\t\t\t\t\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"The interval in milliseconds between refills of the `remaining` count. Example: 3600000 // refill every hour (3600000ms = 1h)\",\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\trefillAmount: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"number\",\n\t\t\t\t\t\t\t\t\t\t\t\tnullable: true,\n\t\t\t\t\t\t\t\t\t\t\t\tdescription: \"The amount to refill\",\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\tlastRefillAt: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\tformat: \"date-time\",\n\t\t\t\t\t\t\t\t\t\t\t\tnullable: true,\n\t\t\t\t\t\t\t\t\t\t\t\tdescription: \"The last refill date\",\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\tenabled: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"boolean\",\n\t\t\t\t\t\t\t\t\t\t\t\tdescription: \"Sets if key is enabled or disabled\",\n\t\t\t\t\t\t\t\t\t\t\t\tdefault: true,\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\trateLimitEnabled: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"boolean\",\n\t\t\t\t\t\t\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"Whether the key has rate limiting enabled\",\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\trateLimitTimeWindow: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"number\",\n\t\t\t\t\t\t\t\t\t\t\t\tnullable: true,\n\t\t\t\t\t\t\t\t\t\t\t\tdescription: \"The duration in milliseconds\",\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\trateLimitMax: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"number\",\n\t\t\t\t\t\t\t\t\t\t\t\tnullable: true,\n\t\t\t\t\t\t\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"Maximum amount of requests allowed within a window\",\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\trequestCount: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"number\",\n\t\t\t\t\t\t\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"The number of requests made within the rate limit time window\",\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\tremaining: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"number\",\n\t\t\t\t\t\t\t\t\t\t\t\tnullable: true,\n\t\t\t\t\t\t\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"Remaining requests (every time api key is used this should updated and should be updated on refill as well)\",\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\tlastRequest: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\tformat: \"date-time\",\n\t\t\t\t\t\t\t\t\t\t\t\tnullable: true,\n\t\t\t\t\t\t\t\t\t\t\t\tdescription: \"When last request occurred\",\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\texpiresAt: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\tformat: \"date-time\",\n\t\t\t\t\t\t\t\t\t\t\t\tnullable: true,\n\t\t\t\t\t\t\t\t\t\t\t\tdescription: \"Expiry date of a key\",\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\tcreatedAt: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\tformat: \"date-time\",\n\t\t\t\t\t\t\t\t\t\t\t\tdescription: \"created at\",\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\tupdatedAt: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\tformat: \"date-time\",\n\t\t\t\t\t\t\t\t\t\t\t\tdescription: \"updated at\",\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\tmetadata: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\t\t\t\t\tnullable: true,\n\t\t\t\t\t\t\t\t\t\t\t\tadditionalProperties: true,\n\t\t\t\t\t\t\t\t\t\t\t\tdescription: \"Extra metadata about the apiKey\",\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\tpermissions: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\tnullable: true,\n\t\t\t\t\t\t\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"Permissions for the api key (stored as JSON string)\",\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\trequired: [\n\t\t\t\t\t\t\t\t\t\t\t\"id\",\n\t\t\t\t\t\t\t\t\t\t\t\"userId\",\n\t\t\t\t\t\t\t\t\t\t\t\"enabled\",\n\t\t\t\t\t\t\t\t\t\t\t\"rateLimitEnabled\",\n\t\t\t\t\t\t\t\t\t\t\t\"requestCount\",\n\t\t\t\t\t\t\t\t\t\t\t\"createdAt\",\n\t\t\t\t\t\t\t\t\t\t\t\"updatedAt\",\n\t\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\tasync (ctx) => {\n\t\t\tconst {\n\t\t\t\tkeyId,\n\t\t\t\texpiresIn,\n\t\t\t\tenabled,\n\t\t\t\tmetadata,\n\t\t\t\trefillAmount,\n\t\t\t\trefillInterval,\n\t\t\t\tremaining,\n\t\t\t\tname,\n\t\t\t\tpermissions,\n\t\t\t\trateLimitEnabled,\n\t\t\t\trateLimitTimeWindow,\n\t\t\t\trateLimitMax,\n\t\t\t} = ctx.body;\n\n\t\t\tconst session = await getSessionFromCtx(ctx);\n\t\t\tconst authRequired = ctx.request || ctx.headers;\n\t\t\tconst user =\n\t\t\t\tauthRequired && !session\n\t\t\t\t\t? null\n\t\t\t\t\t: session?.user || { id: ctx.body.userId };\n\n\t\t\tif (!user?.id) {\n\t\t\t\tthrow new APIError(\"UNAUTHORIZED\", {\n\t\t\t\t\tmessage: ERROR_CODES.UNAUTHORIZED_SESSION,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tif (session && ctx.body.userId && session?.user.id !== ctx.body.userId) {\n\t\t\t\tthrow new APIError(\"UNAUTHORIZED\", {\n\t\t\t\t\tmessage: ERROR_CODES.UNAUTHORIZED_SESSION,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tif (authRequired) {\n\t\t\t\t// if this endpoint was being called from the client,\n\t\t\t\t// we must make sure they can't use server-only properties.\n\t\t\t\tif (\n\t\t\t\t\trefillAmount !== undefined ||\n\t\t\t\t\trefillInterval !== undefined ||\n\t\t\t\t\trateLimitMax !== undefined ||\n\t\t\t\t\trateLimitTimeWindow !== undefined ||\n\t\t\t\t\trateLimitEnabled !== undefined ||\n\t\t\t\t\tremaining !== undefined ||\n\t\t\t\t\tpermissions !== undefined\n\t\t\t\t) {\n\t\t\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\t\tmessage: ERROR_CODES.SERVER_ONLY_PROPERTY,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tlet apiKey: ApiKey | null = null;\n\n\t\t\tapiKey = await getApiKeyById(ctx, keyId, opts);\n\n\t\t\t// Verify ownership\n\t\t\tif (apiKey && apiKey.userId !== user.id) {\n\t\t\t\tapiKey = null;\n\t\t\t}\n\n\t\t\tif (!apiKey) {\n\t\t\t\tthrow new APIError(\"NOT_FOUND\", {\n\t\t\t\t\tmessage: ERROR_CODES.KEY_NOT_FOUND,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tlet newValues: Partial<ApiKey> = {};\n\n\t\t\tif (name !== undefined) {\n\t\t\t\tif (name.length < opts.minimumNameLength) {\n\t\t\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\t\tmessage: ERROR_CODES.INVALID_NAME_LENGTH,\n\t\t\t\t\t});\n\t\t\t\t} else if (name.length > opts.maximumNameLength) {\n\t\t\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\t\tmessage: ERROR_CODES.INVALID_NAME_LENGTH,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tnewValues.name = name;\n\t\t\t}\n\n\t\t\tif (enabled !== undefined) {\n\t\t\t\tnewValues.enabled = enabled;\n\t\t\t}\n\t\t\tif (expiresIn !== undefined) {\n\t\t\t\tif (opts.keyExpiration.disableCustomExpiresTime === true) {\n\t\t\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\t\tmessage: ERROR_CODES.KEY_DISABLED_EXPIRATION,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tif (expiresIn !== null) {\n\t\t\t\t\t// if expires is not null, check if it's under the valid range\n\t\t\t\t\t// if it IS null, this means the user wants to disable expiration time on the key\n\t\t\t\t\tconst expiresIn_in_days = expiresIn / (60 * 60 * 24);\n\n\t\t\t\t\tif (expiresIn_in_days < opts.keyExpiration.minExpiresIn) {\n\t\t\t\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\t\t\tmessage: ERROR_CODES.EXPIRES_IN_IS_TOO_SMALL,\n\t\t\t\t\t\t});\n\t\t\t\t\t} else if (expiresIn_in_days > opts.keyExpiration.maxExpiresIn) {\n\t\t\t\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\t\t\tmessage: ERROR_CODES.EXPIRES_IN_IS_TOO_LARGE,\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tnewValues.expiresAt = expiresIn ? getDate(expiresIn, \"sec\") : null;\n\t\t\t}\n\n\t\t\tif (metadata !== undefined && opts.enableMetadata === true) {\n\t\t\t\tif (typeof metadata !== \"object\") {\n\t\t\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\t\tmessage: ERROR_CODES.INVALID_METADATA_TYPE,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\t//@ts-expect-error - we need this to be a string to save into DB.\n\t\t\t\tnewValues.metadata =\n\t\t\t\t\tschema.apikey.fields.metadata.transform.input(metadata);\n\t\t\t}\n\t\t\tif (remaining !== undefined) {\n\t\t\t\tnewValues.remaining = remaining;\n\t\t\t}\n\t\t\tif (refillAmount !== undefined || refillInterval !== undefined) {\n\t\t\t\tif (refillAmount !== undefined && refillInterval === undefined) {\n\t\t\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\t\tmessage: ERROR_CODES.REFILL_AMOUNT_AND_INTERVAL_REQUIRED,\n\t\t\t\t\t});\n\t\t\t\t} else if (refillInterval !== undefined && refillAmount === undefined) {\n\t\t\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\t\tmessage: ERROR_CODES.REFILL_INTERVAL_AND_AMOUNT_REQUIRED,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tnewValues.refillAmount = refillAmount;\n\t\t\t\tnewValues.refillInterval = refillInterval;\n\t\t\t}\n\n\t\t\tif (rateLimitEnabled !== undefined) {\n\t\t\t\tnewValues.rateLimitEnabled = rateLimitEnabled;\n\t\t\t}\n\t\t\tif (rateLimitTimeWindow !== undefined) {\n\t\t\t\tnewValues.rateLimitTimeWindow = rateLimitTimeWindow;\n\t\t\t}\n\t\t\tif (rateLimitMax !== undefined) {\n\t\t\t\tnewValues.rateLimitMax = rateLimitMax;\n\t\t\t}\n\n\t\t\tif (permissions !== undefined) {\n\t\t\t\t//@ts-expect-error - we need this to be a string to save into DB.\n\t\t\t\tnewValues.permissions = JSON.stringify(permissions);\n\t\t\t}\n\n\t\t\tif (Object.keys(newValues).length === 0) {\n\t\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\tmessage: ERROR_CODES.NO_VALUES_TO_UPDATE,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tlet newApiKey: ApiKey = apiKey;\n\t\t\ttry {\n\t\t\t\tif (opts.storage === \"secondary-storage\" && opts.fallbackToDatabase) {\n\t\t\t\t\tconst dbUpdated = await ctx.context.adapter.update<ApiKey>({\n\t\t\t\t\t\tmodel: API_KEY_TABLE_NAME,\n\t\t\t\t\t\twhere: [\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tfield: \"id\",\n\t\t\t\t\t\t\t\tvalue: apiKey.id,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t],\n\t\t\t\t\t\tupdate: newValues,\n\t\t\t\t\t});\n\t\t\t\t\tif (dbUpdated) {\n\t\t\t\t\t\tawait setApiKey(ctx, dbUpdated, opts);\n\t\t\t\t\t\tnewApiKey = dbUpdated;\n\t\t\t\t\t}\n\t\t\t\t} else if (opts.storage === \"database\") {\n\t\t\t\t\tconst result = await ctx.context.adapter.update<ApiKey>({\n\t\t\t\t\t\tmodel: API_KEY_TABLE_NAME,\n\t\t\t\t\t\twhere: [\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tfield: \"id\",\n\t\t\t\t\t\t\t\tvalue: apiKey.id,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t],\n\t\t\t\t\t\tupdate: newValues,\n\t\t\t\t\t});\n\t\t\t\t\tif (result) newApiKey = result;\n\t\t\t\t} else {\n\t\t\t\t\tconst updated: ApiKey = {\n\t\t\t\t\t\t...apiKey,\n\t\t\t\t\t\t...newValues,\n\t\t\t\t\t\tupdatedAt: new Date(),\n\t\t\t\t\t};\n\t\t\t\t\tawait setApiKey(ctx, updated, opts);\n\t\t\t\t\tnewApiKey = updated;\n\t\t\t\t}\n\t\t\t} catch (error: any) {\n\t\t\t\tthrow new APIError(\"INTERNAL_SERVER_ERROR\", {\n\t\t\t\t\tmessage: error?.message,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tdeleteAllExpiredApiKeys(ctx.context);\n\n\t\t\t// transform metadata from string back to object\n\t\t\tnewApiKey.metadata = schema.apikey.fields.metadata.transform.output(\n\t\t\t\tnewApiKey.metadata as never as string,\n\t\t\t);\n\n\t\t\tconst { key: _key, ...returningApiKey } = newApiKey;\n\n\t\t\treturn ctx.json({\n\t\t\t\t...returningApiKey,\n\t\t\t\tpermissions: returningApiKey.permissions\n\t\t\t\t\t? safeJSONParse<{\n\t\t\t\t\t\t\t[key: string]: string[];\n\t\t\t\t\t\t}>(returningApiKey.permissions)\n\t\t\t\t\t: null,\n\t\t\t});\n\t\t},\n\t);\n}\n"],"mappings":";;;;;;;;;;AAYA,MAAM,yBAAyB,EAAE,OAAO;CACvC,OAAO,EAAE,QAAQ,CAAC,KAAK,EACtB,aAAa,yBACb,CAAC;CACF,QAAQ,EAAE,OACR,QAAQ,CACR,KAAK,EACL,aACC,sFACD,CAAC,CACD,UAAU;CACZ,MAAM,EACJ,QAAQ,CACR,KAAK,EACL,aAAa,uBACb,CAAC,CACD,UAAU;CACZ,SAAS,EACP,SAAS,CACT,KAAK,EACL,aAAa,yCACb,CAAC,CACD,UAAU;CACZ,WAAW,EACT,QAAQ,CACR,KAAK,EACL,aAAa,oCACb,CAAC,CACD,IAAI,EAAE,CACN,UAAU;CACZ,cAAc,EACZ,QAAQ,CACR,KAAK,EACL,aAAa,qBACb,CAAC,CACD,UAAU;CACZ,gBAAgB,EACd,QAAQ,CACR,KAAK,EACL,aAAa,uBACb,CAAC,CACD,UAAU;CACZ,UAAU,EAAE,KAAK,CAAC,UAAU;CAC5B,WAAW,EACT,QAAQ,CACR,KAAK,EACL,aAAa,6CACb,CAAC,CACD,IAAI,EAAE,CACN,UAAU,CACV,UAAU;CACZ,kBAAkB,EAChB,SAAS,CACT,KAAK,EACL,aAAa,8CACb,CAAC,CACD,UAAU;CACZ,qBAAqB,EACnB,QAAQ,CACR,KAAK,EACL,aACC,qFACD,CAAC,CACD,UAAU;CACZ,cAAc,EACZ,QAAQ,CACR,KAAK,EACL,aACC,8NACD,CAAC,CACD,UAAU;CACZ,aAAa,EACX,OAAO,EAAE,QAAQ,EAAE,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC,CACvC,KAAK,EACL,aAAa,uDACb,CAAC,CACD,UAAU,CACV,UAAU;CACZ,CAAC;AAEF,SAAgB,aAAa,EAC5B,MACA,QACA,2BAQE;AACF,QAAO,mBACN,mBACA;EACC,QAAQ;EACR,MAAM;EACN,UAAU,EACT,SAAS;GACR,aAAa;GACb,WAAW,EACV,OAAO;IACN,aAAa;IACb,SAAS,EACR,oBAAoB,EACnB,QAAQ;KACP,MAAM;KACN,YAAY;MACX,IAAI;OACH,MAAM;OACN,aAAa;OACb;MACD,MAAM;OACL,MAAM;OACN,UAAU;OACV,aAAa;OACb;MACD,OAAO;OACN,MAAM;OACN,UAAU;OACV,aACC;OACD;MACD,QAAQ;OACP,MAAM;OACN,UAAU;OACV,aACC;OACD;MACD,QAAQ;OACP,MAAM;OACN,aAAa;OACb;MACD,gBAAgB;OACf,MAAM;OACN,UAAU;OACV,aACC;OACD;MACD,cAAc;OACb,MAAM;OACN,UAAU;OACV,aAAa;OACb;MACD,cAAc;OACb,MAAM;OACN,QAAQ;OACR,UAAU;OACV,aAAa;OACb;MACD,SAAS;OACR,MAAM;OACN,aAAa;OACb,SAAS;OACT;MACD,kBAAkB;OACjB,MAAM;OACN,aACC;OACD;MACD,qBAAqB;OACpB,MAAM;OACN,UAAU;OACV,aAAa;OACb;MACD,cAAc;OACb,MAAM;OACN,UAAU;OACV,aACC;OACD;MACD,cAAc;OACb,MAAM;OACN,aACC;OACD;MACD,WAAW;OACV,MAAM;OACN,UAAU;OACV,aACC;OACD;MACD,aAAa;OACZ,MAAM;OACN,QAAQ;OACR,UAAU;OACV,aAAa;OACb;MACD,WAAW;OACV,MAAM;OACN,QAAQ;OACR,UAAU;OACV,aAAa;OACb;MACD,WAAW;OACV,MAAM;OACN,QAAQ;OACR,aAAa;OACb;MACD,WAAW;OACV,MAAM;OACN,QAAQ;OACR,aAAa;OACb;MACD,UAAU;OACT,MAAM;OACN,UAAU;OACV,sBAAsB;OACtB,aAAa;OACb;MACD,aAAa;OACZ,MAAM;OACN,UAAU;OACV,aACC;OACD;MACD;KACD,UAAU;MACT;MACA;MACA;MACA;MACA;MACA;MACA;MACA;KACD,EACD,EACD;IACD,EACD;GACD,EACD;EACD,EACD,OAAO,QAAQ;EACd,MAAM,EACL,OACA,WACA,SACA,UACA,cACA,gBACA,WACA,MACA,aACA,kBACA,qBACA,iBACG,IAAI;EAER,MAAM,UAAU,MAAM,kBAAkB,IAAI;EAC5C,MAAM,eAAe,IAAI,WAAW,IAAI;EACxC,MAAM,OACL,gBAAgB,CAAC,UACd,OACA,SAAS,QAAQ,EAAE,IAAI,IAAI,KAAK,QAAQ;AAE5C,MAAI,CAAC,MAAM,GACV,OAAM,IAAI,SAAS,gBAAgB,EAClC,S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"}