better-auth
Version:
The most comprehensive authentication framework for TypeScript.
1 lines • 22.3 kB
Source Map (JSON)
{"version":3,"file":"create-api-key.mjs","names":["start: string | null","data: Omit<ApiKey, \"id\">","apiKey: ApiKey","generateId"],"sources":["../../../../src/plugins/api-key/routes/create-api-key.ts"],"sourcesContent":["import type { AuthContext, Awaitable } 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 { generateId } from \"../../../utils\";\nimport { getDate } from \"../../../utils/date\";\nimport { API_KEY_TABLE_NAME, ERROR_CODES } from \"..\";\nimport { defaultKeyHasher } from \"../\";\nimport { setApiKey } from \"../adapter\";\nimport type { apiKeySchema } from \"../schema\";\nimport type { ApiKey } from \"../types\";\nimport type { PredefinedApiKeyOptions } from \".\";\n\nconst createApiKeyBodySchema = z.object({\n\tname: z.string().meta({ description: \"Name of the Api Key\" }).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\t\t.default(null),\n\n\tuserId: z.coerce\n\t\t.string()\n\t\t.meta({\n\t\t\tdescription:\n\t\t\t\t'User Id of the user that the Api Key belongs to. server-only. Eg: \"user-id\"',\n\t\t})\n\t\t.optional(),\n\tprefix: z\n\t\t.string()\n\t\t.meta({ description: \"Prefix of the Api Key\" })\n\t\t.regex(/^[a-zA-Z0-9_-]+$/, {\n\t\t\tmessage:\n\t\t\t\t\"Invalid prefix format, must be alphanumeric and contain only underscores and hyphens.\",\n\t\t})\n\t\t.optional(),\n\tremaining: z\n\t\t.number()\n\t\t.meta({\n\t\t\tdescription: \"Remaining number of requests. Server side only\",\n\t\t})\n\t\t.min(0)\n\t\t.optional()\n\t\t.nullable()\n\t\t.default(null),\n\tmetadata: z.any().optional(),\n\trefillAmount: z\n\t\t.number()\n\t\t.meta({\n\t\t\tdescription:\n\t\t\t\t\"Amount to refill the remaining count of the Api Key. server-only. Eg: 100\",\n\t\t})\n\t\t.min(1)\n\t\t.optional(),\n\trefillInterval: z\n\t\t.number()\n\t\t.meta({\n\t\t\tdescription:\n\t\t\t\t\"Interval to refill the Api Key in milliseconds. server-only. Eg: 1000\",\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. 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: 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\trateLimitEnabled: z\n\t\t.boolean()\n\t\t.meta({\n\t\t\tdescription:\n\t\t\t\t\"Whether the key has rate limiting enabled. server-only. Eg: true\",\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: \"Permissions of the Api Key.\",\n\t\t})\n\t\t.optional(),\n});\n\nexport function createApiKey({\n\tkeyGenerator,\n\topts,\n\tschema,\n\tdeleteAllExpiredApiKeys,\n}: {\n\tkeyGenerator: (options: {\n\t\tlength: number;\n\t\tprefix: string | undefined;\n\t}) => Awaitable<string>;\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/create\",\n\t\t{\n\t\t\tmethod: \"POST\",\n\t\t\tbody: createApiKeyBodySchema,\n\t\t\tmetadata: {\n\t\t\t\topenapi: {\n\t\t\t\t\tdescription: \"Create a new API key for a user\",\n\t\t\t\t\tresponses: {\n\t\t\t\t\t\t\"200\": {\n\t\t\t\t\t\t\tdescription: \"API key created 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: \"Unique identifier of 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\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: \"Creation timestamp\",\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: \"Last update timestamp\",\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: \"Name of 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: \"Prefix of 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\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\"Starting characters of the key (if configured)\",\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\tkey: {\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:\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"The full API key (only returned on creation)\",\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: \"Whether the key is enabled\",\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: \"Expiration timestamp\",\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: \"ID of the user owning 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\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: \"Last refill timestamp\",\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: \"Last request timestamp\",\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: \"Metadata associated with 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\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: \"Maximum requests in 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\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: \"Rate limit time window 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\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: \"Remaining requests\",\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: \"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\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: \"Refill interval 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\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: \"Whether rate limiting is enabled\",\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: \"Current request count in window\",\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: \"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: {\n\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"array\",\n\t\t\t\t\t\t\t\t\t\t\t\t\titems: { type: \"string\" },\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\tdescription: \"Permissions associated with 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},\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\"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\t\"key\",\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\"userId\",\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],\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\tname,\n\t\t\t\texpiresIn,\n\t\t\t\tprefix,\n\t\t\t\tremaining,\n\t\t\t\tmetadata,\n\t\t\t\trefillAmount,\n\t\t\t\trefillInterval,\n\t\t\t\tpermissions,\n\t\t\t\trateLimitMax,\n\t\t\t\trateLimitTimeWindow,\n\t\t\t\trateLimitEnabled,\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\tpermissions !== undefined ||\n\t\t\t\t\tremaining !== null\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\t// if metadata is defined, than check that it's an object.\n\t\t\tif (metadata) {\n\t\t\t\tif (opts.enableMetadata === false) {\n\t\t\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\t\tmessage: ERROR_CODES.METADATA_DISABLED,\n\t\t\t\t\t});\n\t\t\t\t}\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}\n\n\t\t\t// make sure that if they pass a refill amount, they also pass a refill interval\n\t\t\tif (refillAmount && !refillInterval) {\n\t\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\tmessage: ERROR_CODES.REFILL_AMOUNT_AND_INTERVAL_REQUIRED,\n\t\t\t\t});\n\t\t\t}\n\t\t\t// make sure that if they pass a refill interval, they also pass a refill amount\n\t\t\tif (refillInterval && !refillAmount) {\n\t\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\tmessage: ERROR_CODES.REFILL_INTERVAL_AND_AMOUNT_REQUIRED,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tif (expiresIn) {\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\n\t\t\t\tconst expiresIn_in_days = expiresIn / (60 * 60 * 24);\n\n\t\t\t\tif (opts.keyExpiration.minExpiresIn > expiresIn_in_days) {\n\t\t\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\t\tmessage: ERROR_CODES.EXPIRES_IN_IS_TOO_SMALL,\n\t\t\t\t\t});\n\t\t\t\t} else if (opts.keyExpiration.maxExpiresIn < expiresIn_in_days) {\n\t\t\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\t\tmessage: ERROR_CODES.EXPIRES_IN_IS_TOO_LARGE,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (prefix) {\n\t\t\t\tif (prefix.length < opts.minimumPrefixLength) {\n\t\t\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\t\tmessage: ERROR_CODES.INVALID_PREFIX_LENGTH,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tif (prefix.length > opts.maximumPrefixLength) {\n\t\t\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\t\tmessage: ERROR_CODES.INVALID_PREFIX_LENGTH,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (name) {\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}\n\t\t\t\tif (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} else if (opts.requireName) {\n\t\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\tmessage: ERROR_CODES.NAME_REQUIRED,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tdeleteAllExpiredApiKeys(ctx.context);\n\n\t\t\tconst key = await keyGenerator({\n\t\t\t\tlength: opts.defaultKeyLength,\n\t\t\t\tprefix: prefix || opts.defaultPrefix,\n\t\t\t});\n\n\t\t\tconst hashed = opts.disableKeyHashing ? key : await defaultKeyHasher(key);\n\n\t\t\tlet start: string | null = null;\n\n\t\t\tif (opts.startingCharactersConfig.shouldStore) {\n\t\t\t\tstart = key.substring(\n\t\t\t\t\t0,\n\t\t\t\t\topts.startingCharactersConfig.charactersLength,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconst defaultPermissions = opts.permissions?.defaultPermissions\n\t\t\t\t? typeof opts.permissions.defaultPermissions === \"function\"\n\t\t\t\t\t? await opts.permissions.defaultPermissions(user.id, ctx)\n\t\t\t\t\t: opts.permissions.defaultPermissions\n\t\t\t\t: undefined;\n\t\t\tconst permissionsToApply = permissions\n\t\t\t\t? JSON.stringify(permissions)\n\t\t\t\t: defaultPermissions\n\t\t\t\t\t? JSON.stringify(defaultPermissions)\n\t\t\t\t\t: undefined;\n\n\t\t\tlet data: Omit<ApiKey, \"id\"> = {\n\t\t\t\tcreatedAt: new Date(),\n\t\t\t\tupdatedAt: new Date(),\n\t\t\t\tname: name ?? null,\n\t\t\t\tprefix: prefix ?? opts.defaultPrefix ?? null,\n\t\t\t\tstart: start,\n\t\t\t\tkey: hashed,\n\t\t\t\tenabled: true,\n\t\t\t\texpiresAt: expiresIn\n\t\t\t\t\t? getDate(expiresIn, \"sec\")\n\t\t\t\t\t: opts.keyExpiration.defaultExpiresIn\n\t\t\t\t\t\t? getDate(opts.keyExpiration.defaultExpiresIn, \"sec\")\n\t\t\t\t\t\t: null,\n\t\t\t\tuserId: user.id,\n\t\t\t\tlastRefillAt: null,\n\t\t\t\tlastRequest: null,\n\t\t\t\tmetadata: null,\n\t\t\t\trateLimitMax: rateLimitMax ?? opts.rateLimit.maxRequests ?? null,\n\t\t\t\trateLimitTimeWindow:\n\t\t\t\t\trateLimitTimeWindow ?? opts.rateLimit.timeWindow ?? null,\n\t\t\t\tremaining:\n\t\t\t\t\tremaining === null ? remaining : (remaining ?? refillAmount ?? null),\n\t\t\t\trefillAmount: refillAmount ?? null,\n\t\t\t\trefillInterval: refillInterval ?? null,\n\t\t\t\trateLimitEnabled:\n\t\t\t\t\trateLimitEnabled === undefined\n\t\t\t\t\t\t? (opts.rateLimit.enabled ?? true)\n\t\t\t\t\t\t: rateLimitEnabled,\n\t\t\t\trequestCount: 0,\n\t\t\t\t//@ts-expect-error - we intentionally save the permissions as string on DB.\n\t\t\t\tpermissions: permissionsToApply,\n\t\t\t};\n\n\t\t\tif (metadata) {\n\t\t\t\t//@ts-expect-error - we intentionally save the metadata as string on DB.\n\t\t\t\tdata.metadata = schema.apikey.fields.metadata.transform.input(metadata);\n\t\t\t}\n\n\t\t\tlet apiKey: ApiKey;\n\n\t\t\tif (opts.storage === \"secondary-storage\" && opts.fallbackToDatabase) {\n\t\t\t\tapiKey = await ctx.context.adapter.create<Omit<ApiKey, \"id\">, ApiKey>({\n\t\t\t\t\tmodel: API_KEY_TABLE_NAME,\n\t\t\t\t\tdata: data,\n\t\t\t\t});\n\t\t\t\tawait setApiKey(ctx, apiKey, opts);\n\t\t\t} else if (opts.storage === \"secondary-storage\") {\n\t\t\t\tconst id =\n\t\t\t\t\tctx.context.generateId({\n\t\t\t\t\t\tmodel: API_KEY_TABLE_NAME,\n\t\t\t\t\t}) ?? generateId();\n\t\t\t\tapiKey = {\n\t\t\t\t\t...data,\n\t\t\t\t\tid,\n\t\t\t\t} as ApiKey;\n\t\t\t\tawait setApiKey(ctx, apiKey, opts);\n\t\t\t} else {\n\t\t\t\tapiKey = await ctx.context.adapter.create<Omit<ApiKey, \"id\">, ApiKey>({\n\t\t\t\t\tmodel: API_KEY_TABLE_NAME,\n\t\t\t\t\tdata: data,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\treturn ctx.json({\n\t\t\t\t...(apiKey as ApiKey),\n\t\t\t\tkey: key,\n\t\t\t\tmetadata: metadata ?? null,\n\t\t\t\tpermissions: apiKey.permissions\n\t\t\t\t\t? safeJSONParse(apiKey.permissions)\n\t\t\t\t\t: null,\n\t\t\t});\n\t\t},\n\t);\n}\n"],"mappings":";;;;;;;;;;;AAcA,MAAM,yBAAyB,EAAE,OAAO;CACvC,MAAM,EAAE,QAAQ,CAAC,KAAK,EAAE,aAAa,uBAAuB,CAAC,CAAC,UAAU;CACxE,WAAW,EACT,QAAQ,CACR,KAAK,EACL,aAAa,6CACb,CAAC,CACD,IAAI,EAAE,CACN,UAAU,CACV,UAAU,CACV,QAAQ,KAAK;CAEf,QAAQ,EAAE,OACR,QAAQ,CACR,KAAK,EACL,aACC,iFACD,CAAC,CACD,UAAU;CACZ,QAAQ,EACN,QAAQ,CACR,KAAK,EAAE,aAAa,yBAAyB,CAAC,CAC9C,MAAM,oBAAoB,EAC1B,SACC,yFACD,CAAC,CACD,UAAU;CACZ,WAAW,EACT,QAAQ,CACR,KAAK,EACL,aAAa,kDACb,CAAC,CACD,IAAI,EAAE,CACN,UAAU,CACV,UAAU,CACV,QAAQ,KAAK;CACf,UAAU,EAAE,KAAK,CAAC,UAAU;CAC5B,cAAc,EACZ,QAAQ,CACR,KAAK,EACL,aACC,6EACD,CAAC,CACD,IAAI,EAAE,CACN,UAAU;CACZ,gBAAgB,EACd,QAAQ,CACR,KAAK,EACL,aACC,yEACD,CAAC,CACD,UAAU;CACZ,qBAAqB,EACnB,QAAQ,CACR,KAAK,EACL,aACC,uOACD,CAAC,CACD,UAAU;CACZ,cAAc,EACZ,QAAQ,CACR,KAAK,EACL,aACC,8NACD,CAAC,CACD,UAAU;CACZ,kBAAkB,EAChB,SAAS,CACT,KAAK,EACL,aACC,oEACD,CAAC,CACD,UAAU;CACZ,aAAa,EACX,OAAO,EAAE,QAAQ,EAAE,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC,CACvC,KAAK,EACL,aAAa,+BACb,CAAC,CACD,UAAU;CACZ,CAAC;AAEF,SAAgB,aAAa,EAC5B,cACA,MACA,QACA,2BAYE;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,WAAW;OACV,MAAM;OACN,QAAQ;OACR,aAAa;OACb;MACD,WAAW;OACV,MAAM;OACN,QAAQ;OACR,aAAa;OACb;MACD,MAAM;OACL,MAAM;OACN,UAAU;OACV,aAAa;OACb;MACD,QAAQ;OACP,MAAM;OACN,UAAU;OACV,aAAa;OACb;MACD,OAAO;OACN,MAAM;OACN,UAAU;OACV,aACC;OACD;MACD,KAAK;OACJ,MAAM;OACN,aACC;OACD;MACD,SAAS;OACR,MAAM;OACN,aAAa;OACb;MACD,WAAW;OACV,MAAM;OACN,QAAQ;OACR,UAAU;OACV,aAAa;OACb;MACD,QAAQ;OACP,MAAM;OACN,aAAa;OACb;MACD,cAAc;OACb,MAAM;OACN,QAAQ;OACR,UAAU;OACV,aAAa;OACb;MACD,aAAa;OACZ,MAAM;OACN,QAAQ;OACR,UAAU;OACV,aAAa;OACb;MACD,UAAU;OACT,MAAM;OACN,UAAU;OACV,sBAAsB;OACtB,aAAa;OACb;MACD,cAAc;OACb,MAAM;OACN,UAAU;OACV,aAAa;OACb;MACD,qBAAqB;OACpB,MAAM;OACN,UAAU;OACV,aAAa;OACb;MACD,WAAW;OACV,MAAM;OACN,UAAU;OACV,aAAa;OACb;MACD,cAAc;OACb,MAAM;OACN,UAAU;OACV,aAAa;OACb;MACD,gBAAgB;OACf,MAAM;OACN,UAAU;OACV,aAAa;OACb;MACD,kBAAkB;OACjB,MAAM;OACN,aAAa;OACb;MACD,cAAc;OACb,MAAM;OACN,aAAa;OACb;MACD,aAAa;OACZ,MAAM;OACN,UAAU;OACV,sBAAsB;QACrB,MAAM;QACN,OAAO,EAAE,MAAM,UAAU;QACzB;OACD,aAAa;OACb;MACD;KACD,UAAU;MACT;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;KACD,EACD,EACD;IACD,EACD;GACD,EACD;EACD,EACD,OAAO,QAAQ;EACd,MAAM,EACL,MACA,WACA,QACA,WACA,UACA,cACA,gBACA,aACA,cACA,qBACA,qBACG,IAAI;EAER,MAAM,UAAU,MAAM,kBAAkB,IAAI;EAC5C,MAAM,eAAe,IAAI,WAAW,IAAI;EACxC,MA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"}