UNPKG

better-auth

Version:

The most comprehensive authentication framework for TypeScript.

1 lines • 10.3 kB
{"version":3,"file":"schema.mjs","names":["parsedData: Record<string, any>","schema: Record<string, DBFieldAttribute>"],"sources":["../../src/db/schema.ts"],"sourcesContent":["import type { BetterAuthOptions } from \"@better-auth/core\";\nimport type {\n\tBetterAuthPluginDBSchema,\n\tDBFieldAttribute,\n} from \"@better-auth/core/db\";\nimport { getAuthTables } from \"@better-auth/core/db\";\nimport { APIError } from \"better-call\";\nimport type { Account, Session, User } from \"../types\";\n\n// Cache for parsed schemas to avoid reparsing on every request\nconst cache = new WeakMap<\n\tBetterAuthOptions,\n\tMap<string, Record<string, DBFieldAttribute>>\n>();\n\nfunction parseOutputData<T extends Record<string, any>>(\n\tdata: T,\n\tschema: {\n\t\tfields: Record<string, DBFieldAttribute>;\n\t},\n) {\n\tconst fields = schema.fields;\n\tconst parsedData: Record<string, any> = {};\n\tfor (const key in data) {\n\t\tconst field = fields[key];\n\t\tif (!field) {\n\t\t\tparsedData[key] = data[key];\n\t\t\tcontinue;\n\t\t}\n\t\tif (\n\t\t\tfield.returned === false &&\n\t\t\tkey !== \"id\" // id is always returned\n\t\t) {\n\t\t\tcontinue;\n\t\t}\n\t\tparsedData[key] = data[key];\n\t}\n\treturn parsedData as T;\n}\n\nfunction getFields(\n\toptions: BetterAuthOptions,\n\ttable: string,\n\tmode: \"input\" | \"output\",\n) {\n\tconst cacheKey = `${table}:${mode}`;\n\tif (!cache.has(options)) {\n\t\tcache.set(options, new Map());\n\t}\n\tconst tableCache = cache.get(options)!;\n\tif (tableCache.has(cacheKey)) {\n\t\treturn tableCache.get(cacheKey)!;\n\t}\n\tconst coreSchema =\n\t\tmode === \"output\" ? (getAuthTables(options)[table]?.fields ?? {}) : {};\n\tconst additionalFields =\n\t\ttable === \"user\" || table === \"session\" || table === \"account\"\n\t\t\t? options[table]?.additionalFields\n\t\t\t: undefined;\n\tlet schema: Record<string, DBFieldAttribute> = {\n\t\t...coreSchema,\n\t\t...(additionalFields ?? {}),\n\t};\n\tfor (const plugin of options.plugins || []) {\n\t\tif (plugin.schema && plugin.schema[table]) {\n\t\t\tschema = {\n\t\t\t\t...schema,\n\t\t\t\t...plugin.schema[table].fields,\n\t\t\t};\n\t\t}\n\t}\n\ttableCache.set(cacheKey, schema);\n\treturn schema;\n}\n\nexport function parseUserOutput<T extends User>(\n\toptions: BetterAuthOptions,\n\tuser: T,\n) {\n\tconst schema = getFields(options, \"user\", \"output\");\n\treturn parseOutputData(user, { fields: schema });\n}\n\nexport function parseSessionOutput<T extends Session>(\n\toptions: BetterAuthOptions,\n\tsession: T,\n) {\n\tconst schema = getFields(options, \"session\", \"output\");\n\treturn parseOutputData(session, { fields: schema });\n}\n\nexport function parseAccountOutput<T extends Account>(\n\toptions: BetterAuthOptions,\n\taccount: T,\n) {\n\tconst schema = getFields(options, \"account\", \"output\");\n\tconst parsed = parseOutputData(account, { fields: schema });\n\t// destructuring for type inference\n\t// runtime filtering is already done by `parseOutputData`\n\tconst {\n\t\taccessToken: _accessToken,\n\t\trefreshToken: _refreshToken,\n\t\tidToken: _idToken,\n\t\taccessTokenExpiresAt: _accessTokenExpiresAt,\n\t\trefreshTokenExpiresAt: _refreshTokenExpiresAt,\n\t\tpassword: _password,\n\t\t...rest\n\t} = parsed;\n\treturn rest;\n}\n\nexport function parseInputData<T extends Record<string, any>>(\n\tdata: T,\n\tschema: {\n\t\tfields: Record<string, DBFieldAttribute>;\n\t\taction?: (\"create\" | \"update\") | undefined;\n\t},\n) {\n\tconst action = schema.action || \"create\";\n\tconst fields = schema.fields;\n\tconst parsedData: Record<string, any> = Object.assign(\n\t\tObject.create(null),\n\t\tnull,\n\t);\n\tfor (const key in fields) {\n\t\tif (key in data) {\n\t\t\tif (fields[key]!.input === false) {\n\t\t\t\tif (fields[key]!.defaultValue !== undefined) {\n\t\t\t\t\tif (action !== \"update\") {\n\t\t\t\t\t\tparsedData[key] = fields[key]!.defaultValue;\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (data[key]) {\n\t\t\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\t\tmessage: `${key} is not allowed to be set`,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (fields[key]!.validator?.input && data[key] !== undefined) {\n\t\t\t\tconst result = fields[key]!.validator.input[\"~standard\"].validate(\n\t\t\t\t\tdata[key],\n\t\t\t\t);\n\t\t\t\tif (result instanceof Promise) {\n\t\t\t\t\tthrow new APIError(\"INTERNAL_SERVER_ERROR\", {\n\t\t\t\t\t\tmessage: \"Async validation is not supported for additional fields\",\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tif (\"issues\" in result && result.issues) {\n\t\t\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\t\tmessage: result.issues[0]?.message || \"Validation Error\",\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tparsedData[key] = result.value;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (fields[key]!.transform?.input && data[key] !== undefined) {\n\t\t\t\tparsedData[key] = fields[key]!.transform?.input(data[key]);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tparsedData[key] = data[key];\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (fields[key]!.defaultValue !== undefined && action === \"create\") {\n\t\t\tif (typeof fields[key]!.defaultValue === \"function\") {\n\t\t\t\tparsedData[key] = fields[key]!.defaultValue();\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tparsedData[key] = fields[key]!.defaultValue;\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (fields[key]!.required && action === \"create\") {\n\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\tmessage: `${key} is required`,\n\t\t\t});\n\t\t}\n\t}\n\treturn parsedData as Partial<T>;\n}\n\nexport function parseUserInput(\n\toptions: BetterAuthOptions,\n\tuser: Record<string, any> = {},\n\taction: \"create\" | \"update\",\n) {\n\tconst schema = getFields(options, \"user\", \"input\");\n\treturn parseInputData(user, { fields: schema, action });\n}\n\nexport function parseAdditionalUserInput(\n\toptions: BetterAuthOptions,\n\tuser?: Record<string, any> | undefined,\n) {\n\tconst schema = getFields(options, \"user\", \"input\");\n\treturn parseInputData(user || {}, { fields: schema });\n}\n\nexport function parseAccountInput(\n\toptions: BetterAuthOptions,\n\taccount: Partial<Account>,\n) {\n\tconst schema = getFields(options, \"account\", \"input\");\n\treturn parseInputData(account, { fields: schema });\n}\n\nexport function parseSessionInput(\n\toptions: BetterAuthOptions,\n\tsession: Partial<Session>,\n) {\n\tconst schema = getFields(options, \"session\", \"input\");\n\treturn parseInputData(session, { fields: schema });\n}\n\nexport function mergeSchema<S extends BetterAuthPluginDBSchema>(\n\tschema: S,\n\tnewSchema?:\n\t\t| {\n\t\t\t\t[K in keyof S]?:\n\t\t\t\t\t| {\n\t\t\t\t\t\t\tmodelName?: string | undefined;\n\t\t\t\t\t\t\tfields?:\n\t\t\t\t\t\t\t\t| {\n\t\t\t\t\t\t\t\t\t\t[P: string]: string;\n\t\t\t\t\t\t\t\t }\n\t\t\t\t\t\t\t\t| undefined;\n\t\t\t\t\t }\n\t\t\t\t\t| undefined;\n\t\t }\n\t\t| undefined,\n) {\n\tif (!newSchema) {\n\t\treturn schema;\n\t}\n\tfor (const table in newSchema) {\n\t\tconst newModelName = newSchema[table]?.modelName;\n\t\tif (newModelName) {\n\t\t\tschema[table]!.modelName = newModelName;\n\t\t}\n\t\tfor (const field in schema[table]!.fields) {\n\t\t\tconst newField = newSchema[table]?.fields?.[field];\n\t\t\tif (!newField) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tschema[table]!.fields[field]!.fieldName = newField;\n\t\t}\n\t}\n\treturn schema;\n}\n"],"mappings":"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"}