UNPKG

@puls-atlas/cli

Version:

The Puls Atlas CLI tool for managing Atlas projects

182 lines 8.3 kB
import { isPlainObject } from 'es-toolkit/compat'; import { normalizeOptionalString } from '../../../utils/value.js'; import { resolveSearchSourceCapabilities } from './capabilities.js'; const normalizeStringArray = value => { if (!Array.isArray(value)) { return []; } return [...new Set(value.map(entry => normalizeOptionalString(entry)).filter(Boolean))]; }; const filterNullEntries = value => Object.fromEntries(Object.entries(value).filter(([, entry]) => entry !== null)); const normalizeOptionalStringRecord = value => { if (!isPlainObject(value)) { return null; } const normalizedEntries = filterNullEntries(Object.fromEntries(Object.entries(value).map(([key, entryValue]) => [key, normalizeOptionalString(entryValue)]))); return Object.keys(normalizedEntries).length > 0 ? normalizedEntries : null; }; const normalizeOptionalObject = value => isPlainObject(value) ? value : null; const normalizeSearchSourceEventarcConfig = eventarcConfig => { if (!isPlainObject(eventarcConfig)) { return null; } return filterNullEntries({ database: normalizeOptionalString(eventarcConfig.database), documentPathPattern: normalizeOptionalString(eventarcConfig.documentPathPattern), triggerRegion: normalizeOptionalString(eventarcConfig.triggerRegion) }); }; const normalizeSearchSourceRequestConfig = requestConfig => { if (!isPlainObject(requestConfig)) { return null; } return filterNullEntries({ body: normalizeOptionalObject(requestConfig.body), headers: normalizeOptionalStringRecord(requestConfig.headers), method: normalizeOptionalString(requestConfig.method), query: normalizeOptionalStringRecord(requestConfig.query), url: normalizeOptionalString(requestConfig.url) }); }; const normalizeSearchSourceIncrementalCursorRequestConfig = cursorRequestConfig => { if (!isPlainObject(cursorRequestConfig)) { return null; } return filterNullEntries({ bodyPath: normalizeOptionalString(cursorRequestConfig.bodyPath), headerName: normalizeOptionalString(cursorRequestConfig.headerName), queryParam: normalizeOptionalString(cursorRequestConfig.queryParam) }); }; const normalizeSearchSourceIncrementalCursorResponseConfig = cursorResponseConfig => { if (!isPlainObject(cursorResponseConfig)) { return null; } return filterNullEntries({ hasMorePath: normalizeOptionalString(cursorResponseConfig.hasMorePath), nextCursorPath: normalizeOptionalString(cursorResponseConfig.nextCursorPath) }); }; const normalizeSearchSourceIncrementalCursorConfig = cursorConfig => { if (!isPlainObject(cursorConfig)) { return null; } return filterNullEntries({ idColumn: normalizeOptionalString(cursorConfig.idColumn), request: normalizeSearchSourceIncrementalCursorRequestConfig(cursorConfig.request), response: normalizeSearchSourceIncrementalCursorResponseConfig(cursorConfig.response), versionColumn: normalizeOptionalString(cursorConfig.versionColumn) }); }; const normalizeSearchSourceIncrementalMappingConfig = mappingConfig => { if (!isPlainObject(mappingConfig)) { return null; } return filterNullEntries({ afterPath: normalizeOptionalString(mappingConfig.afterPath), beforePath: normalizeOptionalString(mappingConfig.beforePath), deletedPath: normalizeOptionalString(mappingConfig.deletedPath), idPath: normalizeOptionalString(mappingConfig.idPath), versionPath: normalizeOptionalString(mappingConfig.versionPath) }); }; const normalizeSearchSourceIncrementalResponseConfig = responseConfig => { if (!isPlainObject(responseConfig)) { return null; } return filterNullEntries({ itemsPath: normalizeOptionalString(responseConfig.itemsPath) }); }; const normalizeSearchSourceIncrementalConfig = incrementalConfig => { if (!isPlainObject(incrementalConfig)) { return null; } return filterNullEntries({ batchSize: Number.isInteger(incrementalConfig.batchSize) && incrementalConfig.batchSize > 0 ? incrementalConfig.batchSize : null, cursor: normalizeSearchSourceIncrementalCursorConfig(incrementalConfig.cursor), deleteStrategy: normalizeOptionalString(incrementalConfig.deleteStrategy), deletedColumn: normalizeOptionalString(incrementalConfig.deletedColumn), idColumn: normalizeOptionalString(incrementalConfig.idColumn), mapping: normalizeSearchSourceIncrementalMappingConfig(incrementalConfig.mapping), response: normalizeSearchSourceIncrementalResponseConfig(incrementalConfig.response), safetyLag: normalizeOptionalString(incrementalConfig.safetyLag), sql: normalizeOptionalString(incrementalConfig.sql), strategy: normalizeOptionalString(incrementalConfig.strategy), versionColumn: normalizeOptionalString(incrementalConfig.versionColumn) }); }; const normalizeSearchSourceSnapshotPaginationConfig = paginationConfig => { if (!isPlainObject(paginationConfig)) { return null; } return filterNullEntries({ batchSize: Number.isInteger(paginationConfig.batchSize) && paginationConfig.batchSize > 0 ? paginationConfig.batchSize : null, keyColumn: normalizeOptionalString(paginationConfig.keyColumn), mode: normalizeOptionalString(paginationConfig.mode) }); }; const normalizeSearchSourceSnapshotConfig = snapshotConfig => { if (!isPlainObject(snapshotConfig)) { return null; } return filterNullEntries({ pagination: normalizeSearchSourceSnapshotPaginationConfig(snapshotConfig.pagination), sql: normalizeOptionalString(snapshotConfig.sql) }); }; const normalizeSearchSourcePromotionConfig = promotionConfig => { if (!isPlainObject(promotionConfig)) { return null; } return filterNullEntries({ mode: normalizeOptionalString(promotionConfig.mode), rollbackGrace: normalizeOptionalString(promotionConfig.rollbackGrace) }); }; export const normalizeSearchSourceConfig = (sourceName, sourceConfig) => { const normalizedSourceConfig = { capabilities: resolveSearchSourceCapabilities(sourceConfig), collection: normalizeOptionalString(sourceConfig?.collection), connectionSecret: normalizeOptionalString(sourceConfig?.connectionSecret), description: normalizeOptionalString(sourceConfig?.description), driver: normalizeOptionalString(sourceConfig?.driver), enabled: sourceConfig?.enabled !== false, eventarc: normalizeSearchSourceEventarcConfig(sourceConfig?.eventarc), incremental: normalizeSearchSourceIncrementalConfig(sourceConfig?.incremental), indexes: normalizeStringArray(sourceConfig?.indexes), mapper: normalizeOptionalString(sourceConfig?.mapper), promotion: normalizeSearchSourcePromotionConfig(sourceConfig?.promotion), request: normalizeSearchSourceRequestConfig(sourceConfig?.request), routeTemplate: normalizeOptionalString(sourceConfig?.routeTemplate), schedule: normalizeOptionalString(sourceConfig?.schedule), snapshot: normalizeSearchSourceSnapshotConfig(sourceConfig?.snapshot), sourceName, syncClass: normalizeOptionalString(sourceConfig?.syncClass), type: normalizeOptionalString(sourceConfig?.type) }; return filterNullEntries(normalizedSourceConfig); }; const createRuntimeSourceConfigFromCollection = (collectionName, collectionConfig) => normalizeSearchSourceConfig(collectionName, { collection: collectionName, enabled: collectionConfig?.enabled !== false, eventarc: { documentPathPattern: normalizeOptionalString(collectionConfig?.sourcePathPattern) ?? `${collectionName}/*` }, indexes: collectionConfig?.indexes, mapper: collectionConfig?.mapper, routeTemplate: collectionConfig?.routeTemplate, syncClass: 'delta-merge', type: 'firestore' }); export const resolveSearchRuntimeSources = context => { const configuredSources = context.config.sources ?? {}; if (Object.keys(configuredSources).length > 0) { return Object.fromEntries(Object.entries(configuredSources).map(([sourceName, sourceConfig]) => [sourceName, normalizeSearchSourceConfig(sourceName, sourceConfig)])); } return Object.fromEntries(Object.entries(context.config.collections ?? {}).map(([collectionName, collectionConfig]) => [collectionName, createRuntimeSourceConfigFromCollection(collectionName, collectionConfig)])); }; export default { normalizeSearchSourceConfig, resolveSearchRuntimeSources };