UNPKG

@r1tsu/payload

Version:

285 lines (284 loc) 10 kB
import crypto from 'crypto'; import { decrypt, encrypt } from './auth/crypto.js'; import { APIKeyAuthentication } from './auth/strategies/apiKey.js'; import { JWTAuthentication } from './auth/strategies/jwt.js'; import localOperations from './collections/operations/local/index.js'; import { validateSchema } from './config/validate.js'; import { consoleEmailAdapter } from './email/consoleEmailAdapter.js'; import { fieldAffectsData } from './exports/types.js'; import localGlobalOperations from './globals/operations/local/index.js'; import flattenFields from './utilities/flattenTopLevelFields.js'; import Logger from './utilities/logger.js'; import { serverInit as serverInitTelemetry } from './utilities/telemetry/events/serverInit.js'; /** * @description Payload */ export class BasePayload { /** * @description Authorization and Authentication using headers and cookies to run auth user strategies * @returns cookies: Map<string, string> * @returns permissions: Permissions * @returns user: User */ auth = async (options)=>{ const { auth } = localOperations.auth; return auth(this, options); }; authStrategies; collections = {}; config; /** * @description Performs count operation * @param options * @returns count of documents satisfying query */ count = async (options)=>{ const { count } = localOperations; return count(this, options); }; /** * @description Performs create operation * @param options * @returns created document */ create = async (options)=>{ const { create } = localOperations; return create(this, options); }; db; decrypt = decrypt; duplicate = async (options)=>{ const { duplicate } = localOperations; return duplicate(this, options); }; email; // TODO: re-implement or remove? // errorHandler: ErrorHandler encrypt = encrypt; extensions; /** * @description Find documents with criteria * @param options * @returns documents satisfying query */ find = async (options)=>{ const { find } = localOperations; return find(this, options); }; /** * @description Find document by ID * @param options * @returns document with specified ID */ findByID = async (options)=>{ const { findByID } = localOperations; return findByID(this, options); }; findGlobal = async (options)=>{ const { findOne } = localGlobalOperations; return findOne(this, options); }; /** * @description Find global version by ID * @param options * @returns global version with specified ID */ findGlobalVersionByID = async (options)=>{ const { findVersionByID } = localGlobalOperations; return findVersionByID(this, options); }; /** * @description Find global versions with criteria * @param options * @returns versions satisfying query */ findGlobalVersions = async (options)=>{ const { findVersions } = localGlobalOperations; return findVersions(this, options); }; /** * @description Find version by ID * @param options * @returns version with specified ID */ findVersionByID = async (options)=>{ const { findVersionByID } = localOperations; return findVersionByID(this, options); }; /** * @description Find versions with criteria * @param options * @returns versions satisfying query */ findVersions = async (options)=>{ const { findVersions } = localOperations; return findVersions(this, options); }; forgotPassword = async (options)=>{ const { forgotPassword } = localOperations.auth; return forgotPassword(this, options); }; getAPIURL = ()=>`${this.config.serverURL}${this.config.routes.api}`; getAdminURL = ()=>`${this.config.serverURL}${this.config.routes.admin}`; globals; logger; login = async (options)=>{ const { login } = localOperations.auth; return login(this, options); }; resetPassword = async (options)=>{ const { resetPassword } = localOperations.auth; return resetPassword(this, options); }; /** * @description Restore global version by ID * @param options * @returns version with specified ID */ restoreGlobalVersion = async (options)=>{ const { restoreVersion } = localGlobalOperations; return restoreVersion(this, options); }; /** * @description Restore version by ID * @param options * @returns version with specified ID */ restoreVersion = async (options)=>{ const { restoreVersion } = localOperations; return restoreVersion(this, options); }; schema; secret; sendEmail; types; unlock = async (options)=>{ const { unlock } = localOperations.auth; return unlock(this, options); }; updateGlobal = async (options)=>{ const { update } = localGlobalOperations; return update(this, options); }; validationRules; verifyEmail = async (options)=>{ const { verifyEmail } = localOperations.auth; return verifyEmail(this, options); }; versions = {}; delete(options) { const { deleteLocal } = localOperations; return deleteLocal(this, options); } /** * @description Initializes Payload * @param options */ async init(options) { if (!options?.config) { throw new Error('Error: the payload config is required to initialize payload.'); } this.logger = Logger('payload', options.loggerOptions, options.loggerDestination); this.config = await options.config; if (process.env.NODE_ENV !== 'production') { validateSchema(this.config, this.logger); } if (!this.config.secret) { throw new Error('Error: missing secret key. A secret key is needed to secure Payload.'); } this.secret = crypto.createHash('sha256').update(this.config.secret).digest('hex').slice(0, 32); this.globals = { config: this.config.globals }; this.config.collections.forEach((collection)=>{ const customID = flattenFields(collection.fields).find((field)=>fieldAffectsData(field) && field.name === 'id'); let customIDType; if (customID?.type === 'number' || customID?.type === 'text') customIDType = customID.type; this.collections[collection.slug] = { config: collection, customIDType }; }); this.db = this.config.db.init({ payload: this }); this.db.payload = this; if (this.db?.init) { await this.db.init(); } if (!options.disableDBConnect && this.db.connect) { await this.db.connect(); } // Load email adapter if (this.config.email instanceof Promise) { const awaitedAdapter = await this.config.email; this.email = awaitedAdapter({ payload: this }); } else if (this.config.email) { this.email = this.config.email({ payload: this }); } else { this.logger.warn(`No email adapter provided. Email will be written to console. More info at https://payloadcms.com/docs/email/overview.`); this.email = consoleEmailAdapter({ payload: this }); } this.sendEmail = this.email['sendEmail']; serverInitTelemetry(this); // 1. loop over collections, if collection has auth strategy, initialize and push to array let jwtStrategyEnabled = false; this.authStrategies = this.config.collections.reduce((authStrategies, collection)=>{ if (collection?.auth) { if (collection.auth.strategies.length > 0) { authStrategies.push(...collection.auth.strategies); } // 2. if api key enabled, push api key strategy into the array if (collection.auth?.useAPIKey) { authStrategies.push({ name: `${collection.slug}-api-key`, authenticate: APIKeyAuthentication(collection) }); } // 3. if localStrategy flag is true if (!collection.auth.disableLocalStrategy && !jwtStrategyEnabled) { jwtStrategyEnabled = true; } } return authStrategies; }, []); // 4. if enabled, push jwt strategy into authStrategies last if (jwtStrategyEnabled) { this.authStrategies.push({ name: 'local-jwt', authenticate: JWTAuthentication }); } if (!options.disableOnInit) { if (typeof options.onInit === 'function') await options.onInit(this); if (typeof this.config.onInit === 'function') await this.config.onInit(this); } return this; } update(options) { const { update } = localOperations; return update(this, options); } } const initialized = new BasePayload(); export default initialized; let cached = global._payload; if (!cached) { // eslint-disable-next-line no-multi-assign cached = global._payload = { payload: null, promise: null }; } export const getPayload = async (options)=>{ if (!options?.config) { throw new Error('Error: the payload config is required for getPayload to work.'); } if (cached.payload) { return cached.payload; } if (!cached.promise) { cached.promise = new BasePayload().init(options); } try { cached.payload = await cached.promise; } catch (e) { cached.promise = null; throw e; } return cached.payload; }; //# sourceMappingURL=index.js.map