@coursebuilder/core
Version:
Core package for Course Builder
1 lines • 14 kB
Source Map (JSON)
{"version":3,"sources":["../../src/lib/init.ts","../../src/errors.ts","../../src/lib/utils/cookie.ts","../../src/lib/utils/logger.ts","../../src/lib/utils/merge.ts","../../src/lib/utils/providers.ts"],"sourcesContent":["import { AdapterError } from '../errors'\nimport { CourseBuilderConfig } from '../index'\nimport { CallbacksOptions, InternalOptions, RequestInternal } from '../types'\nimport * as cookie from './utils/cookie.js'\nimport { logger, LoggerInstance } from './utils/logger'\nimport { merge } from './utils/merge'\nimport parseProviders from './utils/providers'\n\ninterface InitParams {\n\turl: URL\n\tcourseBuilderOptions: CourseBuilderConfig\n\tproviderId?: string\n\taction: InternalOptions['action']\n\tisPost: boolean\n\tcookies: RequestInternal['cookies']\n}\n\nexport async function init({\n\turl,\n\tcourseBuilderOptions,\n\tproviderId,\n\taction,\n\tisPost,\n\tcookies: reqCookies,\n}: InitParams): Promise<{\n\toptions: InternalOptions\n\tcookies: cookie.Cookie[]\n}> {\n\tconst { providers, provider } = parseProviders({\n\t\tproviders: courseBuilderOptions.providers,\n\t\turl,\n\t\tproviderId,\n\t\toptions: courseBuilderOptions,\n\t})\n\n\tconst maxAge = 30 * 24 * 60 * 60\n\n\tconst options: InternalOptions = {\n\t\tdebug: false,\n\t\tpages: {},\n\t\t...courseBuilderOptions,\n\t\turl,\n\t\taction,\n\t\t// @ts-expect-errors\n\t\tprovider,\n\t\tcookies: merge(\n\t\t\t{},\n\t\t\tcookie.defaultCookies(\n\t\t\t\tcourseBuilderOptions.useSecureCookies ?? url.protocol === 'https:',\n\t\t\t),\n\t\t\tcourseBuilderOptions.cookies || {},\n\t\t\treqCookies,\n\t\t),\n\t\tproviders,\n\t\tadapter: adapterErrorHandler(courseBuilderOptions.adapter, logger),\n\t\tcallbacks: { ...defaultCallbacks, ...courseBuilderOptions.callbacks },\n\t\tlogger,\n\t\tgetCurrentUser: courseBuilderOptions.getCurrentUser,\n\t}\n\n\tconst cookies: cookie.Cookie[] = []\n\n\treturn { options, cookies }\n}\n\ntype Method = (...args: any[]) => Promise<any>\n\nexport const defaultCallbacks: CallbacksOptions = {\n\tsession(payload) {\n\t\treturn payload\n\t},\n}\n\nfunction adapterErrorHandler(\n\tadapter: CourseBuilderConfig['adapter'],\n\tlogger: LoggerInstance,\n) {\n\tif (!adapter) return\n\n\treturn Object.keys(adapter).reduce<any>((acc, name) => {\n\t\tacc[name] = async (...args: any[]) => {\n\t\t\ttry {\n\t\t\t\tlogger.debug(`adapter_${name}`, { args })\n\t\t\t\tconst method: Method = adapter[name as keyof Method]\n\t\t\t\treturn await method(...args)\n\t\t\t} catch (e) {\n\t\t\t\tconst error = new AdapterError(e as Error)\n\t\t\t\tlogger.error(error)\n\t\t\t\tthrow error\n\t\t\t}\n\t\t}\n\t\treturn acc\n\t}, {})\n}\n","type ErrorOptions = Error | Record<string, unknown>\n\ntype ErrorType =\n\t| 'AdapterError'\n\t| 'UnknownAction'\n\t| 'UnsupportedStrategy'\n\t| 'MissingAdapter'\n\t| 'MissingAdapterMethods'\n\nexport class CourseBuilderError extends Error {\n\t/** The error type. Used to identify the error in the logs. */\n\ttype: ErrorType\n\t/**\n\t * Determines on which page an error should be handled. Typically `signIn` errors can be handled in-page.\n\t * Default is `\"error\"`.\n\t * @internal\n\t */\n\tkind?: 'error'\n\tcause?: Record<string, unknown> & { err?: Error }\n\tconstructor(\n\t\tmessage?: string | Error | ErrorOptions,\n\t\terrorOptions?: ErrorOptions,\n\t) {\n\t\tif (message instanceof Error) {\n\t\t\tsuper(undefined, {\n\t\t\t\tcause: { err: message, ...(message.cause as any), ...errorOptions },\n\t\t\t})\n\t\t} else if (typeof message === 'string') {\n\t\t\tif (errorOptions instanceof Error) {\n\t\t\t\terrorOptions = { err: errorOptions, ...(errorOptions.cause as any) }\n\t\t\t}\n\t\t\tsuper(message, errorOptions)\n\t\t} else {\n\t\t\tsuper(undefined, message)\n\t\t}\n\t\tthis.name = this.constructor.name\n\t\t// @ts-expect-error https://github.com/microsoft/TypeScript/issues/3841\n\t\tthis.type = this.constructor.type ?? 'CourseBuilderError'\n\t\t// @ts-expect-error https://github.com/microsoft/TypeScript/issues/3841\n\t\tthis.kind = this.constructor.kind ?? 'error'\n\n\t\tError.captureStackTrace?.(this, this.constructor)\n\t\tconst url = `https://errors.authjs.dev#${this.type.toLowerCase()}`\n\t\tthis.message += `${this.message ? '. ' : ''}Read more at ${url}`\n\t}\n}\n\nexport class AdapterError extends CourseBuilderError {\n\tstatic type = 'AdapterError'\n}\n\nexport class UnsupportedStrategy extends CourseBuilderError {\n\tstatic type = 'UnsupportedStrategy'\n}\n\nexport class MissingAdapter extends CourseBuilderError {\n\tstatic type = 'MissingAdapter'\n}\n\nexport class MissingAdapterMethods extends CourseBuilderError {\n\tstatic type = 'MissingAdapterMethods'\n}\n","import { CookieOption, CookiesOptions } from '../../types'\n\nexport interface Cookie extends CookieOption {\n\tvalue: string\n}\n\nexport function defaultCookies(useSecureCookies: boolean) {\n\tconst cookiePrefix = useSecureCookies ? '__Secure-' : ''\n\treturn {\n\t\t// default cookie options\n\t} as const satisfies CookiesOptions\n}\n","import { CourseBuilderError } from '../../errors.js'\n\nexport type WarningCode =\n\t| 'debug-enabled'\n\t| 'env-url-basepath-redundant'\n\t| 'env-url-basepath-mismatch'\n\nexport interface LoggerInstance extends Record<string, Function> {\n\twarn: (code: WarningCode) => void\n\terror: (error: Error) => void\n\tdebug: (message: string, metadata?: unknown) => void\n}\n\nconst red = '\\x1b[31m'\nconst yellow = '\\x1b[33m'\nconst grey = '\\x1b[38;5;246m'\nconst reset = '\\x1b[0m'\n\nexport const logger: LoggerInstance = {\n\terror(error) {\n\t\tconst name = error instanceof CourseBuilderError ? error.type : error.name\n\t\tconsole.error(\n\t\t\t`${red}[coursebuilder][error]${reset} ${name}: ${error.message}`,\n\t\t)\n\t\tif (\n\t\t\terror.cause &&\n\t\t\ttypeof error.cause === 'object' &&\n\t\t\t'err' in error.cause &&\n\t\t\terror.cause.err instanceof Error\n\t\t) {\n\t\t\tconst { err, ...data } = error.cause\n\t\t\tconsole.error(`${red}[coursebuilder][cause]${reset}:`, err.stack)\n\t\t\tif (data)\n\t\t\t\tconsole.error(\n\t\t\t\t\t`${red}[coursebuilder][details]${reset}:`,\n\t\t\t\t\tJSON.stringify(data, null, 2),\n\t\t\t\t)\n\t\t} else if (error.stack) {\n\t\t\tconsole.error(error.stack.replace(/.*/, '').substring(1))\n\t\t}\n\t},\n\twarn(code) {\n\t\tconst url = `https://warnings.coursebuilder.dev#${code}`\n\t\tconsole.warn(\n\t\t\t`${yellow}[coursebuilder][warn][${code}]${reset}`,\n\t\t\t`Read more: ${url}`,\n\t\t)\n\t},\n\tdebug(message, metadata) {\n\t\tconsole.log(\n\t\t\t`${grey}[coursebuilder][debug]:${reset} ${message}`,\n\t\t\tJSON.stringify(metadata, null, 2),\n\t\t)\n\t},\n}\n\n/**\n * Override the built-in logger with user's implementation.\n * Any `undefined` level will use the default logger.\n */\nexport function setLogger(\n\tnewLogger: Partial<LoggerInstance> = {},\n\tdebug?: boolean,\n) {\n\t// Turn off debug logging if `debug` isn't set to `true`\n\tif (!debug) logger.debug = () => {}\n\n\tif (newLogger.error) logger.error = newLogger.error\n\tif (newLogger.warn) logger.warn = newLogger.warn\n\tif (newLogger.debug) logger.debug = newLogger.debug\n}\n","// Source: https://stackoverflow.com/a/34749873/5364135\n\n/** Simple object check */\nfunction isObject(item: any): boolean {\n\treturn item && typeof item === 'object' && !Array.isArray(item)\n}\n\n/** Deep merge two objects */\nexport function merge(target: any, ...sources: any[]): any {\n\tif (!sources.length) return target\n\tconst source = sources.shift()\n\n\tif (isObject(target) && isObject(source)) {\n\t\tfor (const key in source) {\n\t\t\tif (isObject(source[key])) {\n\t\t\t\tif (!target[key]) Object.assign(target, { [key]: {} })\n\t\t\t\tmerge(target[key], source[key])\n\t\t\t} else {\n\t\t\t\tObject.assign(target, { [key]: source[key] })\n\t\t\t}\n\t\t}\n\t}\n\n\treturn merge(target, ...sources)\n}\n","import { CourseBuilderConfig } from '../../index'\nimport { Provider } from '../../providers'\nimport { InternalProvider } from '../../types'\nimport { merge } from './merge'\n\nexport default function parseProviders(params: {\n\tproviders: Provider[]\n\turl: URL\n\tproviderId?: string\n\toptions: CourseBuilderConfig\n}): {\n\tproviders: InternalProvider[]\n\tprovider?: InternalProvider\n} {\n\tconst { providerId, options } = params\n\n\tconst providers = params.providers.map((p) => {\n\t\tconst provider = typeof p === 'function' ? p() : p\n\t\tconst { options: userOptions, ...defaults } = provider\n\n\t\tif (!userOptions) {\n\t\t\tthrow new Error(`Provider ${provider.id} is missing options`)\n\t\t}\n\n\t\tconst { paymentsAdapter, ...userOptionsWithPaymentsAdapter } = userOptions\n\n\t\treturn {\n\t\t\t...merge(defaults, userOptionsWithPaymentsAdapter),\n\t\t\t...(paymentsAdapter ? { options: paymentsAdapter } : {}),\n\t\t}\n\t})\n\n\treturn {\n\t\tproviders,\n\t\tprovider: providers.find(({ id }) => id === providerId),\n\t}\n}\n"],"mappings":"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","names":["CourseBuilderError","Error","constructor","message","errorOptions","type","kind","cause","undefined","err","name","captureStackTrace","url","toLowerCase","AdapterError","defaultCookies","useSecureCookies","cookiePrefix","red","yellow","grey","reset","logger","error","name","CourseBuilderError","type","console","message","cause","err","Error","data","stack","JSON","stringify","replace","substring","warn","code","url","debug","metadata","log","isObject","item","Array","isArray","merge","target","sources","length","source","shift","key","Object","assign","params","providerId","options","providers","map","p","provider","userOptions","defaults","Error","id","paymentsAdapter","userOptionsWithPaymentsAdapter","merge","find","parseProviders","init","url","courseBuilderOptions","providerId","action","isPost","cookies","reqCookies","providers","provider","parseProviders","options","maxAge","debug","pages","merge","defaultCookies","useSecureCookies","protocol","adapter","adapterErrorHandler","logger","callbacks","defaultCallbacks","getCurrentUser","session","payload","Object","keys","reduce","acc","name","args","method","e","error","AdapterError"]}