UNPKG

@energica-city/shared-amplify-utils

Version:

Shared utilities for AWS Amplify projects

131 lines 16.7 kB
import { logger } from '../../log'; import { initializeRestMiddleware, getErrorMessage } from './utils'; /** * Creates REST model initializer middleware for Amplify database access * * This middleware initializes Amplify model instances and makes them available * to subsequent middleware and handlers through the input.models property. * * Features: * - Singleton pattern: models are initialized once and reused * - Timeout protection: prevents hanging on initialization failures * - Type safety: provides fully typed model instances * - Error handling: throws errors that are caught by error handler middleware * * @template TSchema - Amplify schema type with models property * @template TTypes - Record mapping model names to their Amplify types * @template TReturn - Return type of the middleware chain * * @param config - Configuration for model initialization * @returns Middleware function that initializes and provides model instances * * @example * ```typescript * // Define your schema and types * type MySchema = { models: { User: any; Post: any } }; * type MyTypes = { User: UserType; Post: PostType }; * * // Create the middleware * const modelInitializer = createRestModelInitializer<MySchema, MyTypes>({ * schema: myAmplifySchema, * amplifyOutputs: myAmplifyOutputs, * entities: ['User', 'Post'], // Optional: specific models only * timeout: 10000 // Optional: custom timeout * }); * * // Use in middleware chain * chain.use('models', modelInitializer); * * // Access in handler * const handler = async (input: RestInputWithModels<MyTypes>) => { * const user = await input.models.User.create({ input: userData }); * return createSuccessResponse(user); * }; * ``` */ export function createRestModelInitializer(config) { const { schema, amplifyOutputs, entities, clientKey = 'default', timeout = 5000, } = config; let isInitialized = false; let initPromise = null; /** * Internal function that performs the actual model initialization * @param input - REST input for logging context * @returns Promise resolving to initialized model instances * @throws Error if initialization fails or times out */ const initialize = async (input) => { const { context } = initializeRestMiddleware(input, { operation: 'modelInitializer', }); try { const { initializeQueries } = await import('../../queries'); logger.debug('REST Model Initializer - Initializing queries', { ...context, entities: entities ?? 'all', }); const db = await Promise.race([ initializeQueries({ amplifyOutputs, schema, entities, clientKey, }), new Promise((_, reject) => setTimeout(() => reject(new Error(`Initialization timeout after ${timeout}ms`)), timeout)), ]); const models = {}; const modelKeys = entities ?? Object.keys(schema.models || {}); for (const modelName of modelKeys) { const instance = db[modelName]; if (instance) { models[modelName] = instance; } } logger.info('REST Model Initializer - Models initialized successfully', { ...context, modelCount: Object.keys(models).length, models: Object.keys(models), }); return models; } catch (error) { logger.error('REST Model Initializer - Initialization failed', { ...context, error: getErrorMessage(error), }); throw error; } }; return async (input, next) => { const { context } = initializeRestMiddleware(input, { operation: 'modelInitializer', }); try { if (isInitialized && initPromise) { const models = await initPromise; return await next({ ...input, models }); } if (!initPromise) { logger.info('REST Model Initializer - Starting', context); initPromise = initialize(input); } const models = await initPromise; isInitialized = true; logger.info('REST Model Initializer - Complete', { ...context, modelCount: Object.keys(models).length, }); return await next({ ...input, models }); } catch (error) { const message = getErrorMessage(error); logger.error('REST Model Initializer - Failed', { ...context, error: message, }); isInitialized = false; initPromise = null; throw new Error(`Model initialization failed: ${message}`); } }; } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiUmVzdE1vZGVsSW5pdGlhbGl6ZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9taWRkbGV3YXJlL3Jlc3QvUmVzdE1vZGVsSW5pdGlhbGl6ZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLE1BQU0sRUFBRSxNQUFNLFdBQVcsQ0FBQztBQVNuQyxPQUFPLEVBQUUsd0JBQXdCLEVBQUUsZUFBZSxFQUFFLE1BQU0sU0FBUyxDQUFDO0FBRXBFOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0EwQ0c7QUFDSCxNQUFNLFVBQVUsMEJBQTBCLENBS3hDLE1BQW1EO0lBRW5ELE1BQU0sRUFDSixNQUFNLEVBQ04sY0FBYyxFQUNkLFFBQVEsRUFDUixTQUFTLEdBQUcsU0FBUyxFQUNyQixPQUFPLEdBQUcsSUFBSSxHQUNmLEdBQUcsTUFBTSxDQUFDO0lBRVgsSUFBSSxhQUFhLEdBQUcsS0FBSyxDQUFDO0lBQzFCLElBQUksV0FBVyxHQUVILElBQUksQ0FBQztJQUVqQjs7Ozs7T0FLRztJQUNILE1BQU0sVUFBVSxHQUFHLEtBQUssRUFDdEIsS0FBa0MsRUFHakMsRUFBRTtRQUNILE1BQU0sRUFBRSxPQUFPLEVBQUUsR0FBRyx3QkFBd0IsQ0FBQyxLQUE0QixFQUFFO1lBQ3pFLFNBQVMsRUFBRSxrQkFBa0I7U0FDOUIsQ0FBQyxDQUFDO1FBRUgsSUFBSSxDQUFDO1lBQ0gsTUFBTSxFQUFFLGlCQUFpQixFQUFFLEdBQUcsTUFBTSxNQUFNLENBQUMsZUFBZSxDQUFDLENBQUM7WUFFNUQsTUFBTSxDQUFDLEtBQUssQ0FBQywrQ0FBK0MsRUFBRTtnQkFDNUQsR0FBRyxPQUFPO2dCQUNWLFFBQVEsRUFBRSxRQUFRLElBQUksS0FBSzthQUM1QixDQUFDLENBQUM7WUFFSCxNQUFNLEVBQUUsR0FBRyxNQUFNLE9BQU8sQ0FBQyxJQUFJLENBQUM7Z0JBQzVCLGlCQUFpQixDQUFrQjtvQkFDakMsY0FB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SSxDQUFDO1lBRW5CLE1BQU0sSUFBSSxLQUFLLENBQUMsZ0NBQWdDLE9BQU8sRUFBRSxDQUFDLENBQUM7UUFDN0QsQ0FBQztJQUNILENBQUMsQ0FBQztBQUNKLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBsb2dnZXIgfSBmcm9tICcuLi8uLi9sb2cnO1xuaW1wb3J0IHR5cGUge1xuICBSZXN0TW9kZWxJbml0aWFsaXplckNvbmZpZyxcbiAgUmVzdElucHV0V2l0aE1vZGVscyxcbiAgUmVzdEhhbmRsZXJSZXR1cm4sXG4gIFJlc3RSZXNwb25zZSxcbn0gZnJvbSAnLi90eXBlcyc7XG5pbXBvcnQgdHlwZSB7IE1pZGRsZXdhcmUgfSBmcm9tICcuLi9taWRkbGV3YXJlQ2hhaW4nO1xuaW1wb3J0IHR5cGUgeyBBbXBsaWZ5TW9kZWxUeXBlLCBRdWVyeUZhY3RvcnlSZXN1bHQgfSBmcm9tICcuLi8uLi9xdWVyaWVzL3R5cGVzJztcbmltcG9ydCB7IGluaXRpYWxpemVSZXN0TWlkZGxld2FyZSwgZ2V0RXJyb3JNZXNzYWdlIH0gZnJvbSAnLi91dGlscyc7XG5cbi8qKlxuICogQ3JlYXRlcyBSRVNUIG1vZGVsIGluaXRpYWxpemVyIG1pZGRsZXdhcmUgZm9yIEFtcGxpZnkgZGF0YWJhc2UgYWNjZXNzXG4gKlxuICogVGhpcyBtaWRkbGV3YXJlIGluaXRpYWxpemVzIEFtcGxpZnkgbW9kZWwgaW5zdGFuY2VzIGFuZCBtYWtlcyB0aGVtIGF2YWlsYWJsZVxuICogdG8gc3Vic2VxdWVudCBtaWRkbGV3YXJlIGFuZCBoYW5kbGVycyB0aHJvdWdoIHRoZSBpbnB1dC5tb2RlbHMgcHJvcGVydHkuXG4gKlxuICogRmVhdHVyZXM6XG4gKiAtIFNpbmdsZXRvbiBwYXR0ZXJuOiBtb2RlbHMgYXJlIGluaXRpYWxpemVkIG9uY2UgYW5kIHJldXNlZFxuICogLSBUaW1lb3V0IHByb3RlY3Rpb246IHByZXZlbnRzIGhhbmdpbmcgb24gaW5pdGlhbGl6YXRpb24gZmFpbHVyZXNcbiAqIC0gVHlwZSBzYWZldHk6IHByb3ZpZGVzIGZ1bGx5IHR5cGVkIG1vZGVsIGluc3RhbmNlc1xuICogLSBFcnJvciBoYW5kbGluZzogdGhyb3dzIGVycm9ycyB0aGF0IGFyZSBjYXVnaHQgYnkgZXJyb3IgaGFuZGxlciBtaWRkbGV3YXJlXG4gKlxuICogQHRlbXBsYXRlIFRTY2hlbWEgLSBBbXBsaWZ5IHNjaGVtYSB0eXBlIHdpdGggbW9kZWxzIHByb3BlcnR5XG4gKiBAdGVtcGxhdGUgVFR5cGVzIC0gUmVjb3JkIG1hcHBpbmcgbW9kZWwgbmFtZXMgdG8gdGhlaXIgQW1wbGlmeSB0eXBlc1xuICogQHRlbXBsYXRlIFRSZXR1cm4gLSBSZXR1cm4gdHlwZSBvZiB0aGUgbWlkZGxld2FyZSBjaGFpblxuICpcbiAqIEBwYXJhbSBjb25maWcgLSBDb25maWd1cmF0aW9uIGZvciBtb2RlbCBpbml0aWFsaXphdGlvblxuICogQHJldHVybnMgTWlkZGxld2FyZSBmdW5jdGlvbiB0aGF0IGluaXRpYWxpemVzIGFuZCBwcm92aWRlcyBtb2RlbCBpbnN0YW5jZXNcbiAqXG4gKiBAZXhhbXBsZVxuICogYGBgdHlwZXNjcmlwdFxuICogLy8gRGVmaW5lIHlvdXIgc2NoZW1hIGFuZCB0eXBlc1xuICogdHlwZSBNeVNjaGVtYSA9IHsgbW9kZWxzOiB7IFVzZXI6IGFueTsgUG9zdDogYW55IH0gfTtcbiAqIHR5cGUgTXlUeXBlcyA9IHsgVXNlcjogVXNlclR5cGU7IFBvc3Q6IFBvc3RUeXBlIH07XG4gKlxuICogLy8gQ3JlYXRlIHRoZSBtaWRkbGV3YXJlXG4gKiBjb25zdCBtb2RlbEluaXRpYWxpemVyID0gY3JlYXRlUmVzdE1vZGVsSW5pdGlhbGl6ZXI8TXlTY2hlbWEsIE15VHlwZXM+KHtcbiAqICAgc2NoZW1hOiBteUFtcGxpZnlTY2hlbWEsXG4gKiAgIGFtcGxpZnlPdXRwdXRzOiBteUFtcGxpZnlPdXRwdXRzLFxuICogICBlbnRpdGllczogWydVc2VyJywgJ1Bvc3QnXSwgLy8gT3B0aW9uYWw6IHNwZWNpZmljIG1vZGVscyBvbmx5XG4gKiAgIHRpbWVvdXQ6IDEwMDAwIC8vIE9wdGlvbmFsOiBjdXN0b20gdGltZW91dFxuICogfSk7XG4gKlxuICogLy8gVXNlIGluIG1pZGRsZXdhcmUgY2hhaW5cbiAqIGNoYWluLnVzZSgnbW9kZWxzJywgbW9kZWxJbml0aWFsaXplcik7XG4gKlxuICogLy8gQWNjZXNzIGluIGhhbmRsZXJcbiAqIGNvbnN0IGhhbmRsZXIgPSBhc3luYyAoaW5wdXQ6IFJlc3RJbnB1dFdpdGhNb2RlbHM8TXlUeXBlcz4pID0+IHtcbiAqICAgY29uc3QgdXNlciA9IGF3YWl0IGlucHV0Lm1vZGVscy5Vc2VyLmNyZWF0ZSh7IGlucHV0OiB1c2VyRGF0YSB9KTtcbiAqICAgcmV0dXJuIGNyZWF0ZVN1Y2Nlc3NSZXNwb25zZSh1c2VyKTtcbiAqIH07XG4gKiBgYGBcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNyZWF0ZVJlc3RNb2RlbEluaXRpYWxpemVyPFxuICBUU2NoZW1hIGV4dGVuZHMgeyBtb2RlbHM6IFJlY29yZDxzdHJpbmcsIHVua25vd24+IH0sXG4gIFRUeXBlcyBleHRlbmRzIFJlY29yZDxzdHJpbmcsIEFtcGxpZnlNb2RlbFR5cGU+LFxuICBUUmV0dXJuIGV4dGVuZHMgUmVzdEhhbmRsZXJSZXR1cm4gPSBSZXN0UmVzcG9uc2UsXG4+KFxuICBjb25maWc6IFJlc3RNb2RlbEluaXRpYWxpemVyQ29uZmlnPFRTY2hlbWEsIFRUeXBlcz4sXG4pOiBNaWRkbGV3YXJlPFJlc3RJbnB1dFdpdGhNb2RlbHM8VFR5cGVzPiwgVFJldHVybj4ge1xuICBjb25zdCB7XG4gICAgc2NoZW1hLFxuICAgIGFtcGxpZnlPdXRwdXRzLFxuICAgIGVudGl0aWVzLFxuICAgIGNsaWVudEtleSA9ICdkZWZhdWx0JyxcbiAgICB0aW1lb3V0ID0gNTAwMCxcbiAgfSA9IGNvbmZpZztcblxuICBsZXQgaXNJbml0aWFsaXplZCA9IGZhbHNlO1xuICBsZXQgaW5pdFByb21pc2U6IFByb21pc2U8e1xuICAgIFtLIGluIGtleW9mIFRUeXBlc106IFF1ZXJ5RmFjdG9yeVJlc3VsdDxLICYgc3RyaW5nLCBUVHlwZXM+O1xuICB9PiB8IG51bGwgPSBudWxsO1xuXG4gIC8qKlxuICAgKiBJbnRlcm5hbCBmdW5jdGlvbiB0aGF0IHBlcmZvcm1zIHRoZSBhY3R1YWwgbW9kZWwgaW5pdGlhbGl6YXRpb25cbiAgICogQHBhcmFtIGlucHV0IC0gUkVTVCBpbnB1dCBmb3IgbG9nZ2luZyBjb250ZXh0XG4gICAqIEByZXR1cm5zIFByb21pc2UgcmVzb2x2aW5nIHRvIGluaXRpYWxpemVkIG1vZGVsIGluc3RhbmNlc1xuICAgKiBAdGhyb3dzIEVycm9yIGlmIGluaXRpYWxpemF0aW9uIGZhaWxzIG9yIHRpbWVzIG91dFxuICAgKi9cbiAgY29uc3QgaW5pdGlhbGl6ZSA9IGFzeW5jIChcbiAgICBpbnB1dDogUmVzdElucHV0V2l0aE1vZGVsczxUVHlwZXM+LFxuICApOiBQcm9taXNlPHtcbiAgICBbSyBpbiBrZXlvZiBUVHlwZXNdOiBRdWVyeUZhY3RvcnlSZXN1bHQ8SyAmIHN0cmluZywgVFR5cGVzPjtcbiAgfT4gPT4ge1xuICAgIGNvbnN0IHsgY29udGV4dCB9ID0gaW5pdGlhbGl6ZVJlc3RNaWRkbGV3YXJlKGlucHV0IGFzIFJlc3RJbnB1dFdpdGhNb2RlbHMsIHtcbiAgICAgIG9wZXJhdGlvbjogJ21vZGVsSW5pdGlhbGl6ZXInLFxuICAgIH0pO1xuXG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHsgaW5pdGlhbGl6ZVF1ZXJpZXMgfSA9IGF3YWl0IGltcG9ydCgnLi4vLi4vcXVlcmllcycpO1xuXG4gICAgICBsb2dnZXIuZGVidWcoJ1JFU1QgTW9kZWwgSW5pdGlhbGl6ZXIgLSBJbml0aWFsaXppbmcgcXVlcmllcycsIHtcbiAgICAgICAgLi4uY29udGV4dCxcbiAgICAgICAgZW50aXRpZXM6IGVudGl0aWVzID8/ICdhbGwnLFxuICAgICAgfSk7XG5cbiAgICAgIGNvbnN0IGRiID0gYXdhaXQgUHJvbWlzZS5yYWNlKFtcbiAgICAgICAgaW5pdGlhbGl6ZVF1ZXJpZXM8VFNjaGVtYSwgVFR5cGVzPih7XG4gICAgICAgICAgYW1wbGlmeU91dHB1dHMsXG4gICAgICAgICAgc2NoZW1hLFxuICAgICAgICAgIGVudGl0aWVzLFxuICAgICAgICAgIGNsaWVudEtleSxcbiAgICAgICAgfSksXG4gICAgICAgIG5ldyBQcm9taXNlPG5ldmVyPigoXywgcmVqZWN0KSA9PlxuICAgICAgICAgIHNldFRpbWVvdXQoXG4gICAgICAgICAgICAoKSA9PlxuICAgICAgICAgICAgICByZWplY3QobmV3IEVycm9yKGBJbml0aWFsaXphdGlvbiB0aW1lb3V0IGFmdGVyICR7dGltZW91dH1tc2ApKSxcbiAgICAgICAgICAgIHRpbWVvdXQsXG4gICAgICAgICAgKSxcbiAgICAgICAgKSxcbiAgICAgIF0pO1xuXG4gICAgICBjb25zdCBtb2RlbHM6IHtcbiAgICAgICAgW0sgaW4ga2V5b2YgVFR5cGVzXTogUXVlcnlGYWN0b3J5UmVzdWx0PEsgJiBzdHJpbmcsIFRUeXBlcz47XG4gICAgICB9ID0ge30gYXMge1xuICAgICAgICBbSyBpbiBrZXlvZiBUVHlwZXNdOiBRdWVyeUZhY3RvcnlSZXN1bHQ8SyAmIHN0cmluZywgVFR5cGVzPjtcbiAgICAgIH07XG5cbiAgICAgIGNvbnN0IG1vZGVsS2V5cyA9IGVudGl0aWVzID8/IE9iamVjdC5rZXlzKHNjaGVtYS5tb2RlbHMgfHwge30pO1xuXG4gICAgICBmb3IgKGNvbnN0IG1vZGVsTmFtZSBvZiBtb2RlbEtleXMpIHtcbiAgICAgICAgY29uc3QgaW5zdGFuY2UgPSBkYlttb2RlbE5hbWUgYXMga2V5b2YgdHlwZW9mIGRiXTtcbiAgICAgICAgaWYgKGluc3RhbmNlKSB7XG4gICAgICAgICAgbW9kZWxzW21vZGVsTmFtZSBhcyBrZXlvZiBUVHlwZXNdID0gaW5zdGFuY2UgYXMgUXVlcnlGYWN0b3J5UmVzdWx0PFxuICAgICAgICAgICAgdHlwZW9mIG1vZGVsTmFtZSAmIHN0cmluZyxcbiAgICAgICAgICAgIFRUeXBlc1xuICAgICAgICAgID47XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgbG9nZ2VyLmluZm8oJ1JFU1QgTW9kZWwgSW5pdGlhbGl6ZXIgLSBNb2RlbHMgaW5pdGlhbGl6ZWQgc3VjY2Vzc2Z1bGx5Jywge1xuICAgICAgICAuLi5jb250ZXh0LFxuICAgICAgICBtb2RlbENvdW50OiBPYmplY3Qua2V5cyhtb2RlbHMpLmxlbmd0aCxcbiAgICAgICAgbW9kZWxzOiBPYmplY3Qua2V5cyhtb2RlbHMpLFxuICAgICAgfSk7XG5cbiAgICAgIHJldHVybiBtb2RlbHM7XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIGxvZ2dlci5lcnJvcignUkVTVCBNb2RlbCBJbml0aWFsaXplciAtIEluaXRpYWxpemF0aW9uIGZhaWxlZCcsIHtcbiAgICAgICAgLi4uY29udGV4dCxcbiAgICAgICAgZXJyb3I6IGdldEVycm9yTWVzc2FnZShlcnJvciksXG4gICAgICB9KTtcbiAgICAgIHRocm93IGVycm9yO1xuICAgIH1cbiAgfTtcblxuICByZXR1cm4gYXN5bmMgKGlucHV0LCBuZXh0KSA9PiB7XG4gICAgY29uc3QgeyBjb250ZXh0IH0gPSBpbml0aWFsaXplUmVzdE1pZGRsZXdhcmUoaW5wdXQgYXMgUmVzdElucHV0V2l0aE1vZGVscywge1xuICAgICAgb3BlcmF0aW9uOiAnbW9kZWxJbml0aWFsaXplcicsXG4gICAgfSk7XG5cbiAgICB0cnkge1xuICAgICAgaWYgKGlzSW5pdGlhbGl6ZWQgJiYgaW5pdFByb21pc2UpIHtcbiAgICAgICAgY29uc3QgbW9kZWxzID0gYXdhaXQgaW5pdFByb21pc2U7XG4gICAgICAgIHJldHVybiBhd2FpdCBuZXh0KHsgLi4uaW5wdXQsIG1vZGVscyB9KTtcbiAgICAgIH1cblxuICAgICAgaWYgKCFpbml0UHJvbWlzZSkge1xuICAgICAgICBsb2dnZXIuaW5mbygnUkVTVCBNb2RlbCBJbml0aWFsaXplciAtIFN0YXJ0aW5nJywgY29udGV4dCk7XG4gICAgICAgIGluaXRQcm9taXNlID0gaW5pdGlhbGl6ZShpbnB1dCk7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IG1vZGVscyA9IGF3YWl0IGluaXRQcm9taXNlO1xuICAgICAgaXNJbml0aWFsaXplZCA9IHRydWU7XG5cbiAgICAgIGxvZ2dlci5pbmZvKCdSRVNUIE1vZGVsIEluaXRpYWxpemVyIC0gQ29tcGxldGUnLCB7XG4gICAgICAgIC4uLmNvbnRleHQsXG4gICAgICAgIG1vZGVsQ291bnQ6IE9iamVjdC5rZXlzKG1vZGVscykubGVuZ3RoLFxuICAgICAgfSk7XG5cbiAgICAgIHJldHVybiBhd2FpdCBuZXh0KHsgLi4uaW5wdXQsIG1vZGVscyB9KTtcbiAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgY29uc3QgbWVzc2FnZSA9IGdldEVycm9yTWVzc2FnZShlcnJvcik7XG4gICAgICBsb2dnZXIuZXJyb3IoJ1JFU1QgTW9kZWwgSW5pdGlhbGl6ZXIgLSBGYWlsZWQnLCB7XG4gICAgICAgIC4uLmNvbnRleHQsXG4gICAgICAgIGVycm9yOiBtZXNzYWdlLFxuICAgICAgfSk7XG5cbiAgICAgIGlzSW5pdGlhbGl6ZWQgPSBmYWxzZTtcbiAgICAgIGluaXRQcm9taXNlID0gbnVsbDtcblxuICAgICAgdGhyb3cgbmV3IEVycm9yKGBNb2RlbCBpbml0aWFsaXphdGlvbiBmYWlsZWQ6ICR7bWVzc2FnZX1gKTtcbiAgICB9XG4gIH07XG59XG4iXX0=