@whaly/connector-sdk 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +192 -239
- package/dist/index.d.ts +192 -239
- package/dist/index.js +927 -834
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +922 -824
- package/dist/index.mjs.map +1 -1
- package/package.json +7 -3
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/sdk/utils.ts","../src/sdk/service/logger.ts","../src/sdk/models/resolver.ts","../src/resolvers/local-file/services/files.ts","../src/resolvers/local-file/hook/schemaHook.ts","../src/resolvers/local-file/resolver.ts","../src/sdk/service/metric.ts","../src/sdk/service/resolver.ts","../src/sdk/service/network.ts","../src/sdk/service/memory.ts","../src/sdk/service/exit.ts","../src/sdk/service/error.ts","../src/sdk/service/relationship.ts","../src/sdk/models/metadata.ts","../src/sdk/models/catalog.ts","../src/sdk/models/messages.ts","../src/sdk/models/state.ts","../src/sdk/constants/date.ts","../src/sdk/models/tap/authenticator.ts","../src/sdk/models/tap/restStream.ts","../src/sdk/models/tap/stream.ts","../src/sdk/helpers/typing.ts","../src/sdk/models/tap/tap.ts","../src/sdk/helpers/qs-logger.ts","../src/sdk/models/target/dbSync.ts","../src/sdk/models/target/error.ts","../src/sdk/models/target/record.ts","../src/sdk/models/target/renameColumnStore.ts","../src/sdk/models/target/schema.ts","../src/sdk/models/target/target.ts","../src/sdk/models/target/streamDbState.ts","../src/sdk/models/target/temporaryFile.ts"],"sourcesContent":["export * from \"./sdk/utils\";\nexport * from \"./sdk/service/network\";\nexport * from \"./sdk/service/logger\";\nexport * from \"./sdk/service/metric\";\nexport * from \"./sdk/service/memory\";\nexport * from \"./sdk/service/error\";\nexport * from \"./sdk/service/exit\";\nexport * from \"./sdk/service/relationship\";\n\nexport * from \"./sdk/models/models\";\nexport * from \"./sdk/models/catalog\";\nexport * from \"./sdk/models/error\";\nexport * from \"./sdk/models/http\";\nexport * from \"./sdk/models/messages\";\nexport * from \"./sdk/models/metadata\";\nexport * from \"./sdk/models/relationship\";\nexport * from \"./sdk/models/resolver\";\nexport * from \"./sdk/models/schema\";\nexport * from \"./sdk/models/state\";\n\nexport * from \"./sdk/models/tap/authenticator\";\nexport * from \"./sdk/models/tap/restStream\";\nexport * from \"./sdk/models/tap/stream\";\nexport * from \"./sdk/models/tap/tap\";\n\nexport * from \"./sdk/models/target/dbSync\";\nexport * from \"./sdk/models/target/error\";\nexport * from \"./sdk/models/target/models\";\nexport * from \"./sdk/models/target/record\";\nexport * from \"./sdk/models/target/renameColumnStore\";\nexport * from \"./sdk/models/target/schema\";\nexport * from \"./sdk/models/target/target\";\nexport * from \"./sdk/models/target/targetHook\";\nexport * from \"./sdk/models/target/temporaryFile\";","import { readFileSync } from \"fs\";\nimport { type CatalogFile } from \"./models/catalog.js\";\nimport { logger } from \"./service/logger.js\";\nimport { type ShoreConfig } from \"./models/models.js\";\nimport { Resolver } from \"./models/resolver.js\";\n\nexport const writeStateFile = (resolver: Resolver, state: string): Promise<void> => {\n logger.info(`📝 Writing the state file.`)\n return resolver.writeState(state);\n}\n\nexport const writeCatalogFile = (resolver: Resolver, catalog: CatalogFile): Promise<void> => {\n logger.info(`📝 Writing the catalog`)\n return resolver.writeCatalog(catalog);\n}\n\nexport const loadShoreConfig = (\n resolver: Resolver\n): Promise<ShoreConfig> => {\n\n const command = process.env.SHORE__COMMAND;\n if (!command) {\n throw new Error(`Env variable \\`SHORE__COMMAND\\` is not set. \n Did you forget to configure it?\n\n Possible values are: \\`DISCOVER\\`, \\`READ\\``)\n }\n\n if (command === `DISCOVER`) {\n logger.info(`🔎 Mode: discovery\n Shore will detect the available streams in the source and their configuration.`)\n } else if (command === `READ`) {\n logger.info(`🔁 Mode: Synchronizing data\n Shore will extract and push data from the source to the destination.`)\n } else {\n throw new Error(`Command: \\`${command}\\` is not supported.\n Did you properly configured env variable \\`SHORE__COMMAND\\`?`)\n }\n\n return resolver.getConfig(command);\n\n}\n\nfunction readFile(fileName: string, filePath: string) {\n try {\n return readFileSync(filePath);\n } catch (err) {\n logger.error(`Can't open file: \\`${fileName}\\` at path: \\`${filePath}\\`. Is it at the proper place?`)\n throw err;\n }\n}\n\nfunction parseFileContent(fileName: string, fileContent: Buffer) {\n try {\n return JSON.parse(fileContent.toString());\n } catch (err) {\n logger.error(`Can't parse file: \\`${fileName}\\` as JSON. Is it properly formatted?`)\n throw err;\n }\n}\n\nexport const loadJson = (fileName: string): any => {\n const filePath = process.cwd() + `/` + fileName\n const fileContent = readFile(fileName, filePath);\n return parseFileContent(fileName, fileContent);\n}\n\nexport const loadSchema = (streamId: string) => {\n const schema = loadJson(`schemas/${streamId}.json`)\n return schema;\n}\n\nexport const checkRequiredConfigKeys = (args: any, requiredConfigKeys: string[]) => {\n\n requiredConfigKeys.forEach(configKey => {\n if (!args[configKey]) {\n throw new Error(`Config is missing required key: ${configKey}`)\n }\n })\n\n}","import * as winston from \"winston\";\n\nimport { loadResolver } from \"./resolver\";\nexport const BATCH_INTERVAL_MS = 100;\n\nconst transports = {\n console: new winston.transports.Console({\n stderrLevels: [],\n level: 'info'\n })\n};\n\nconst getTransports = (): winston.transport[] => {\n return [\n transports.console\n ]\n}\n\nconst winstonLogger = winston.createLogger({\n format: loadResolver().getLogFormat(),\n transports: getTransports(),\n});\n\nlet isWinstonOpen = true;\nconst closeWinston = (cb: () => void) => {\n isWinstonOpen = false;\n winstonLogger.end();\n winstonLogger.on('finish', () => {\n setTimeout(() => {\n return cb()\n }, BATCH_INTERVAL_MS * 2)\n });\n}\n\ntype LogLevel = 'info' | 'error' | 'debug' | 'warn';\n\nconst log = (\n level: LogLevel,\n message: string | any,\n ...args: any[]\n): void => {\n if (isWinstonOpen) {\n winstonLogger[level](message, ...args);\n } else {\n console[level](message, ...args);\n }\n};\n\nexport const logger = {\n info: (message: string | any, ...args: any[]): void => log('info', message, ...args),\n error: (message: string | any, ...args: any[]): void => log('error', message, ...args),\n debug: (message: string | any, ...args: any[]): void => log('debug', message, ...args),\n warn: (message: string | any, ...args: any[]): void => log('warn', message, ...args),\n closeWinston\n}","import winston from \"winston\";\nimport { CatalogFile } from \"./catalog\"\nimport { ShoreCommand, ShoreConfig, SourceType } from \"./models\";\nimport { TargetSchemaHook } from \"./target/targetHook\";\nimport { type ErrorType } from \"./error\";\n\nexport abstract class Resolver {\n constructor() {}\n abstract checkIfCanSync(): Promise<boolean>;\n abstract markSyncStarted(): Promise<void>;\n abstract startVPNIfNeeded(): Promise<void>;\n abstract getConfig(command: ShoreCommand): Promise<ShoreConfig>;\n abstract writeCatalog(catalog: CatalogFile): Promise<void>;\n abstract writeState(state: string): Promise<void>;\n abstract markSyncFailed(): Promise<void>;\n abstract markSyncComplete(): Promise<void>;\n abstract markDiscoveryComplete(): Promise<void>;\n abstract flushMetrics(): Promise<void>;\n abstract onError(errorType: ErrorType, errorText: string, errorDebugText: string): Promise<void>;\n abstract getSchemaHooks(): TargetSchemaHook[];\n abstract updateSourceValue(\n optionKey: string,\n optionValue: string,\n ): Promise<void>;\n abstract getLogFormat(): winston.Logform.Format;\n}","import fs from \"fs\";\n\nexport const writeFile = (path: string, content: string): Promise<void> => {\n return Promise.resolve(fs.writeFileSync(path, content));\n}\n\nexport const readAndParseJSONFile = (path: string) => {\n if (!fs.existsSync(path)) {\n throw new Error(`File \\`${path}\\` wasn't found at: ${process.cwd()}`)\n }\n const raw = fs.readFileSync(path);\n const parsed = JSON.parse(raw.toString())\n\n return parsed;\n}","import { appendFile } from \"fs-extra\";\nimport { TargetSchemaHook, TargetSchemaHookInput } from \"../../../sdk/models/target/targetHook\";\n\nexport class LocalSchemaHook implements TargetSchemaHook {\n async writeSchema(input: TargetSchemaHookInput): Promise<void> {\n await appendFile(\"./schema.tmp\", JSON.stringify(input) + '\\n')\n }\n}","import { CatalogFile } from \"../../sdk/models/catalog\";\nimport { logger } from \"../../sdk/service/logger\";\nimport { DestinationType, ShoreCommand, ShoreConfig, SourceType } from \"../../sdk/models/models\";\nimport { Resolver } from \"../../sdk/models/resolver\";\nimport { readAndParseJSONFile, writeFile } from \"./services/files\";\nimport { LocalSchemaHook } from \"./hook/schemaHook\";\nimport winston from \"winston\";\nimport { getAllMetrics } from \"../../sdk/service/metric\";\nimport { TargetSchemaHook } from \"../../sdk/models/target/targetHook\";\n\nconst { combine, prettyPrint, timestamp, errors, splat } = winston.format;\n\nconst configPath = './config.json'\nconst targetConfigPath = './target-config.json'\nconst catalogPath = './catalog.json'\nconst statePath = './state.json'\nconst metricsPath = './metrics.json'\n\nexport class LocalFilesResolver extends Resolver {\n startVPNIfNeeded(): Promise<void> {\n // We can't start the VPN locally from here as it requires root access\n // See the doc in atlantis to boot it locally on your dev station\n return Promise.resolve();\n }\n\n checkIfCanSync(): Promise<boolean> {\n return Promise.resolve(true);\n }\n\n markSyncStarted(): Promise<void> {\n return Promise.resolve();\n }\n\n onError(errorType: any, errorText: string, errorDebugText: string): Promise<void> {\n const path = `./error.json`;\n return writeFile(path, JSON.stringify({\n errorType,\n errorText,\n errorDebugText\n }))\n }\n\n getSchemaHooks(): TargetSchemaHook[] {\n const wlyHook = new LocalSchemaHook();\n return [wlyHook];\n }\n\n writeSchema(): Promise<void> {\n return Promise.resolve();\n }\n\n constructor() {\n super();\n }\n\n getConfig(\n command: ShoreCommand\n ): Promise<ShoreConfig> {\n logger.info(`📁 Using the LOCAL resolver`)\n\n const config = readAndParseJSONFile(configPath);\n\n const targetConfig = readAndParseJSONFile(targetConfigPath);\n\n const destination = process.env.SHORE__DESTINATION as DestinationType;\n if (!destination) {\n throw new Error(`❌ Env variable \\`SHORE__DESTINATION\\` is not set.\n Did you forget to configure it?\n \n Possible values are: \\`GOOGLE_BIGQUERY\\`, \\`SNOWFLAKE\\``)\n }\n\n if (command === `READ`) {\n\n if (destination === `GOOGLE_BIGQUERY`) {\n const googleCredentials = process.env.GOOGLE_APPLICATION_CREDENTIALS;\n if (!googleCredentials) {\n throw new Error(`Env variable \\`GOOGLE_APPLICATION_CREDENTIALS\\` is not set. \n Did you forget to configure it?\n\n This variable should link to a file containing the proper Google Service Account credentials.\n `)\n }\n }\n\n const catalog = readAndParseJSONFile(catalogPath);\n\n const state = readAndParseJSONFile(statePath);\n\n return Promise.resolve({\n command,\n destination,\n config,\n targetConfig,\n catalog,\n state\n })\n } else {\n return Promise.resolve({\n command,\n destination,\n config,\n targetConfig\n })\n }\n }\n\n writeCatalog(catalog: CatalogFile): Promise<void> {\n return writeFile(catalogPath, JSON.stringify(catalog))\n }\n\n writeState(state: string): Promise<void> {\n return writeFile(statePath, state)\n }\n\n markSyncFailed(): Promise<void> {\n logger.info(`😢 Sync has failed.`)\n return Promise.resolve();\n }\n\n markSyncComplete(): Promise<void> {\n logger.info(`🎉 Sync is complete.`)\n return Promise.resolve();\n }\n\n markDiscoveryComplete(): Promise<void> {\n logger.info(`🎉 Discovery is complete.`)\n return Promise.resolve();\n }\n\n async flushMetrics(): Promise<void> {\n const allMetrics = getAllMetrics();\n\n const metricsOuput = allMetrics\n .map((metric) => {\n return {\n streamId: metric.getStreamId(),\n name: metric.getName(),\n value: metric.getValue()\n }\n })\n .map((obj) => JSON.stringify(obj))\n .join(`\\n`)\n\n return writeFile(metricsPath, metricsOuput);\n\n }\n\n updateSourceValue(optionKey: string, optionValue: string): Promise<void> {\n logger.info(`Updating source value ${optionKey} with value ${optionValue}`, { private: true })\n\n const config = readAndParseJSONFile(configPath);\n config[optionKey] = optionValue;\n return writeFile(configPath, JSON.stringify(config));\n\n }\n\n getLogFormat(): winston.Logform.Format {\n\n return combine(\n timestamp(),\n errors({ stack: true }),\n splat(),\n prettyPrint()\n )\n }\n\n}","const metricStore: {\n [streamId: string]: {\n [metricName: string]: CounterMetric\n }\n} = {};\n\nexport const ALL_STREAM_ID_KEYWORD = \"all\";\nexport const ROWS_SYNCED_METRIC_NAME = \"rows_synced_count\";\nexport const API_CALLS_METRIC_NAME = \"api_calls_count\";\nexport const EXECUTION_TIME_METRIC_NAME = \"execution_time_ms\";\n\n// We're using functions here so that the call is done lazily\n// when the stream is initialized and the proper isSilent + streamId is configured\n// otherwise we have the default streamId value here\nexport interface MetricConfiguration {\n isEnabled: () => boolean;\n getStreamIds?: () => string[];\n}\n\nexport const getCounterMetrics = (\n name: string,\n streamIds: string[]\n): CounterMetric[] => {\n return streamIds.map(streamId => {\n return getCounterMetric(name, streamId)\n })\n}\n\nexport const getCounterMetric = (\n name: string,\n streamId: string = ALL_STREAM_ID_KEYWORD\n): CounterMetric => {\n if (!metricStore[streamId]) {\n metricStore[streamId] = {};\n }\n const streamMetricStore = metricStore[streamId];\n\n if (!streamMetricStore[name]) {\n streamMetricStore[name] = new CounterMetric(name, streamId);\n }\n return streamMetricStore[name];\n}\n\nexport const getAllMetrics = (): CounterMetric[] => {\n return Object.keys(metricStore)\n .flatMap(streamId => {\n const streamMetricStore = metricStore[streamId];\n if (!streamMetricStore) {\n return [] as CounterMetric[];\n }\n return Object.keys(streamMetricStore)\n .map(metricName => streamMetricStore[metricName])\n .filter((m): m is CounterMetric => m !== undefined)\n })\n}\n\nexport class CounterMetric {\n private value: number = 0;\n name: string;\n streamId: string;\n\n constructor(\n name: string,\n streamId: string\n ) {\n this.name = name;\n this.streamId = streamId;\n }\n\n increment(inc: number = 1): void {\n this.value = this.value + inc;\n }\n\n getStreamId(): string {\n return this.streamId\n }\n\n getName(): string {\n return this.name\n }\n\n getValue(): number {\n return this.value\n }\n}","import { LocalFilesResolver } from \"../../resolvers/local-file/resolver\";\nimport { type ResolverType } from \"../models/models\";\nimport { type Resolver } from \"../models/resolver\";\n\nfunction initResolver(resolverType: ResolverType): Resolver {\n if (resolverType === \"LOCAL\") {\n return new LocalFilesResolver()\n } else {\n throw new Error(`❌ Unsupported configResolver: ${resolverType}`)\n }\n}\n\nexport const loadResolver = (): Resolver => {\n const configResolver = process.env.SHORE__CONFIG_RESOLVER;\n if (!configResolver) {\n throw new Error(`Env variable \\`SHORE__CONFIG_RESOLVER\\` is not set. \n Did you forget to configure it?\n\n Possible values are \\`LOCAL\\`, \\`WHALY\\`.\n Please read the documentation to get the full description of the behavior of each.\n `)\n }\n if (configResolver === \"WHALY\" || configResolver === \"LOCAL\") {\n return initResolver(configResolver);\n } else {\n throw new Error(`Resolver: ${configResolver} is not supported.\n Did you properly configure \\`SHORE__CONFIG_RESOLVER\\`?`)\n }\n}","import axios, { AxiosError, AxiosInstance, AxiosResponse, AxiosRequestConfig, AxiosRequestHeaders } from \"axios\";\nimport { URLSearchParams } from \"url\";\nimport * as fs from 'fs';\nimport * as qs from 'qs';\nimport axiosRetry, { isNetworkOrIdempotentRequestError } from 'axios-retry';\nimport { logger } from \"./logger\";\n\n// This retry regardless of whether the call is idempotent or not. \n// e.g. this will retry POST and PUT.\n// Hence, this service and all its function SHOULD not be used to create things as it is not safe. \n// This service should be only used for extracting data.\nconst shouldRetry = (error: AxiosError): boolean => {\n\n const statusCode = error.response ? error.response.status : 0;\n\n return error.code !== 'ECONNABORTED' // Triggered if there is not enough local socket. In those case, retrying will only make things worse\n && (\n !error.response\n || statusCode === 429\n || statusCode === 409\n || statusCode === 400\n || (statusCode >= 500 && statusCode < 599)\n );\n}\n\nexport const getAxiosInstance = (retryCount?: number): AxiosInstance => {\n const instance = axios.create({\n timeout: 120_000\n });\n axiosRetry(instance,\n {\n retries: retryCount || 24,\n retryDelay: (retryCount, error) => {\n logger.info(`🔁 Retrying for the ${retryCount}th time the call for \n method=${error.config?.method}\n url=${error.config?.url}\n params=%j\n body=%j`,\n error.config?.params,\n error.config?.data\n )\n if (retryCount > 6) {\n return 10000\n }\n return axiosRetry.exponentialDelay(retryCount)\n },\n retryCondition: (error: AxiosError): boolean => {\n logger.debug(`😱 Got an error for ${error.config?.method} ${error.config?.url}\n \n Status: ${error?.response?.status}\n Error code ${error.code}\n Error config method ${error}`)\n\n return isNetworkOrIdempotentRequestError(error)\n || shouldRetry(error)\n }\n });\n return instance;\n}\n\nexport interface GetConfig {\n qs?: { [key: string]: any },\n headers?: AxiosRequestHeaders,\n retryCount?: number\n}\n\nexport const getRawJSONApiCall = async <T>(\n endpoint: string,\n config: GetConfig,\n privateLogging?: boolean\n): Promise<AxiosResponse<T>> => {\n\n const instance = getAxiosInstance(config.retryCount);\n\n // Repeat the key/value pair multiple time when having arrays to be passed in the QS\n const paramsSerializer = (params: any) => {\n return qs.stringify(params, { arrayFormat: 'repeat' })\n }\n\n try {\n logger.info(`🤖 GET ${endpoint}`, { private: privateLogging })\n const requestConfig: AxiosRequestConfig = {\n params: config.qs,\n paramsSerializer: { serialize: (params) => qs.stringify(params, { arrayFormat: 'repeat' }) }\n };\n if (config.headers) {\n requestConfig.headers = config.headers;\n }\n const response = await instance.get(\n endpoint,\n requestConfig\n );\n return response;\n } catch (err: any) {\n if (err.response.status > 400) {\n throw new Error(`We got a \\`${err.response.status}\\` status code from endpoint: \\`${endpoint}\\`. \n\n headers response: ${JSON.stringify(err.response.headers)}\n\n Response body from the server: ${JSON.stringify(err.response.data)}`);\n }\n throw err;\n }\n}\n\nexport const getJSONApiCallWithFullResponse = async <T>(\n endpoint: string,\n config: GetConfig,\n privateLogging?: boolean\n) => {\n const instance = getAxiosInstance(config.retryCount);\n\n // Repeat the key/value pair multiple time when having arrays to be passed in the QS\n const paramsSerializer = (params: any) => {\n return qs.stringify(params, { arrayFormat: 'repeat' })\n }\n\n try {\n logger.info(`🤖 GET ${endpoint} with params: %s`, config.qs, { private: privateLogging })\n const requestConfig: AxiosRequestConfig = {\n params: config.qs,\n paramsSerializer: { serialize: (params) => qs.stringify(params, { arrayFormat: 'repeat' }) }\n };\n if (config.headers) {\n requestConfig.headers = config.headers;\n }\n const response = await instance.get(endpoint, requestConfig);\n return response;\n } catch (err) {\n if (err instanceof Error) {\n if (axios.isAxiosError(err)) {\n if ((err.response?.status || 0) > 400) {\n logger.warn(`We got a \\`${err.response?.status}\\` status code from endpoint: \\`${endpoint}\\`. \n\n Headers response: ${JSON.stringify(err.response?.headers)}\n\n Response body from the server: ${JSON.stringify(err.response?.data)}`);\n }\n }\n }\n throw err;\n }\n}\n\nexport const getJSONApiCall = async <T>(\n endpoint: string,\n config: GetConfig,\n privateLogging?: boolean\n): Promise<T> => {\n const fullResponse = await getJSONApiCallWithFullResponse(\n endpoint,\n config,\n privateLogging\n );\n return fullResponse.data;\n}\n\nexport const getDownloadFileApiCall = async <T>(\n endpoint: string,\n config: GetConfig,\n output: string,\n privateLogging?: boolean\n): Promise<{ outputDir: string }> => {\n\n const instance = getAxiosInstance(config.retryCount);\n\n const writer = fs.createWriteStream(output)\n\n const paramsSerializer = (params: any) => {\n return qs.stringify(params, { arrayFormat: 'repeat' })\n }\n\n logger.info(`🤖 GET ${endpoint}`, { private: privateLogging })\n\n return instance({\n method: \"GET\",\n url: endpoint,\n responseType: 'stream',\n params: config.qs,\n ...(config.headers ? { headers: config.headers } : {}),\n paramsSerializer: { serialize: (params) => qs.stringify(params, { arrayFormat: 'repeat' }) }\n }).then(response => {\n return new Promise<{ outputDir: string }>((resolve, reject) => {\n response.data.pipe(writer);\n let error: any = null;\n writer.on('error', err => {\n error = err;\n writer.close();\n reject(err);\n });\n writer.on('close', () => {\n if (!error) {\n resolve({ outputDir: output });\n }\n //no need to call the reject here, as it will have been called in the\n //'error' stream;\n });\n });\n });\n}\n\nexport interface PostConfig {\n qs?: { [key: string]: any },\n headers?: AxiosRequestHeaders,\n retryCount?: number\n}\n\nexport const postJSONApiCall = async <T>(\n endpoint: string,\n config: PostConfig,\n payload: any\n): Promise<T> => {\n\n const instance = getAxiosInstance(config.retryCount);\n try {\n const requestConfig: AxiosRequestConfig = { params: config.qs };\n if (config.headers) {\n requestConfig.headers = config.headers;\n }\n const response = await instance.post(\n endpoint,\n payload,\n requestConfig\n );\n return response.data;\n } catch (err: any) {\n if (err?.response?.status >= 400) {\n throw new Error(`We got a \\`${err.response.status}\\` status code from endpoint: \\`${endpoint}\\`. \n \n Response body from the server: ${JSON.stringify(err.response.data)}`);\n }\n throw err;\n }\n}\n\nexport const postFormDataApiCall = async <T>(endpoint: string, config: PostConfig, payload: any): Promise<T> => {\n\n const instance = getAxiosInstance(config.retryCount);\n\n try {\n const response = await instance({\n method: 'post',\n url: endpoint,\n headers: {\n ...(payload as any).getHeaders()\n },\n data: payload\n });\n return response.data;\n } catch (err: any) {\n if (err.response.status > 400) {\n throw new Error(`We got a \\`${err.response.status}\\` status code from endpoint: \\`${endpoint}\\`. \n \n Response body from the server: ${JSON.stringify(err.response.data)}`);\n }\n throw err;\n }\n}\n\nexport const postUrlEncodedApiCall = async (endpoint: string, config: PostConfig, payload: any) => {\n\n const instance = getAxiosInstance(config.retryCount);\n\n try {\n\n const params = new URLSearchParams(payload as any);\n\n const response = await instance.post(\n endpoint,\n params.toString(),\n {\n ...(config.headers ? { headers: config.headers } : {})\n });\n return response.data;\n } catch (err: any) {\n if (err.response.status > 400) {\n throw new Error(`We got a \\`${err.response.status}\\` status code from endpoint: \\`${endpoint}\\`. \n \n Response body from the server: ${JSON.stringify(err.response.data)}`);\n }\n throw err;\n }\n}","import { logger } from \"./logger\";\n\nconst formatMemoryUsage = (data: number) => `${Math.round(data / 1024 / 1024 * 100) / 100} MB`;\n\nexport const printMemoryFootprint = (prefix: string) => {\n const memoryData = process.memoryUsage();\n\n const memoryUsage = {\n rss: `${formatMemoryUsage(memoryData.rss)} -> Resident Set Size - total memory allocated for the process execution`,\n heapTotal: `${formatMemoryUsage(memoryData.heapTotal)} -> total size of the allocated heap`,\n heapUsed: `${formatMemoryUsage(memoryData.heapUsed)} -> actual memory used during the execution`,\n external: `${formatMemoryUsage(memoryData.external)} -> V8 external memory`,\n };\n\n logger.info(`${prefix}: %j`, memoryUsage);\n}","import { logger } from \"./logger\";\nimport { loadResolver } from \"./resolver\";\n\nexport async function gracefulExit(exitCode: number) {\n if(exitCode !== 0) {\n await loadResolver().markSyncFailed();\n }\n // Wait for winston to have logged all messages\n // Required as we are using HTTP transport\n const loggerFinish = new Promise<void>((resolve, reject) => {\n logger.closeWinston(resolve)\n })\n await loggerFinish;\n process.exit(exitCode);\n}","import { gracefulExit } from \"./exit\";\nimport { logger } from \"./logger\";\nimport { loadResolver } from \"./resolver\"\nimport { type ErrorType } from \"../models/error.js\";\n\nexport const haltAndCatchFire = async (\n errorType: ErrorType,\n errorText: string,\n errorDebugText: string\n): Promise<void> => {\n\n logger.error(\n `💥 Got a fatal error that will reported to the end user. Process will stop.\n errorType=%s\n errorText=%s\n errorDebugText=%s\n `,\n errorType,\n errorText,\n errorDebugText\n )\n const resolver = loadResolver();\n await resolver.onError(errorType, errorText, errorDebugText)\n // we return sucess but we let the sucess job pass the error params\n await gracefulExit(0);\n}","import { type StreamId } from \"../models/catalog\";\nimport { type DirectionalRelationships, type StreamRelationship } from \"../models/relationship\";\n\nexport const findRelatedRelationships = (\n streamId: StreamId,\n allRels: StreamRelationship[]\n): DirectionalRelationships => {\n\n return allRels.reduce<DirectionalRelationships>((acc, rel) => {\n const base = {\n type: rel.type,\n from: rel.from,\n to: rel.to\n }\n\n if (rel.left === streamId) {\n acc.right.push({\n streamId: rel.right,\n ...base\n })\n }\n if (rel.right === streamId) {\n acc.left.push({\n streamId: rel.left,\n ...base\n })\n }\n return acc;\n }, { left: [], right: [] })\n\n}","import { StreamId } from \"./catalog\";\nimport { ReplicationMethod } from \"./models\";\n\nexport type InclusionMode = \"available\" | \"automatic\" | \"unsupported\";\n\nexport interface MetadataEntry {\n /// From Singer Spec ///\n // ---------------------------------------------------------------------------------------\n // Non discoverable - Can't be written by the tap itself during discovery mode\n // Another system (ex. UI, Human being) should set those between the discovery and the sync\n // ---------------------------------------------------------------------------------------\n selected?: boolean,\n \"replication-method\"?: ReplicationMethod,\n \"replication-key\"?: string,\n \"view-key-properties\"?: string[], // Only for database tap\n\n // ---------------------------------------------------------------------------------------\n // Discovereable - The tap should write those when possible\n // ---------------------------------------------------------------------------------------\n \"inclusion\"?: InclusionMode,\n \"selected-by-default\"?: boolean,\n // Keys that will be presented to the end user to select the proper replication key\n \"valid-replication-keys\"?: string[],\n\n // Force the replication mecanism when set, end user can't control it anymore afterwards\n \"forced-replication-method\"?: ReplicationMethod,\n \"forced-replication-key\"?: string,\n\n \"table-key-properties\"?: string[],\n \"schema-name\"?: string, // Only for database tap\n \"is-view\"?: boolean, // Only for database tap\n \"row-count\"?: number, // Only for database tap\n \"database-name\"?: string, // Only for database tap\n \"sql-datatype\"?: string // Only for database tap\n\n /// Whaly extensions ///\n \"whaly-display-label\"?: string,\n \"whaly-description\"?: string,\n \"whaly-parent-stream\"?: StreamId\n}\n\nexport interface CatalogMetadata {\n breadcrumb: string[],\n metadata: MetadataEntry\n}\n\n// The default javascript Map is working with references when getting/setting when using arrays as keys\n// However, in our code we don't keep track of the arrays references, we want to work only with the arrays values\n// Hence we have to use a version that compares the values of the arrays when doing set/get\nclass MetadataMap extends Map<string[], MetadataEntry>{\n private areEquals(array1: string[], array2: string[]): boolean {\n return array1.length === array2.length\n && array1.every(function (value, index) { return value === array2[index] })\n }\n private findExistingEntry(key: string[]): [string[], MetadataEntry] | undefined {\n return Array.from(super.entries()).find(entry => {\n if (this.areEquals(entry[0], key)) {\n return true;\n }\n })\n }\n get(key: string[]) {\n const existingEntry = this.findExistingEntry(key);\n return existingEntry?.[1];\n }\n set(key: string[], value: MetadataEntry) {\n const existingKey = this.findExistingEntry(key);\n if (existingKey) {\n return super.set(existingKey?.[0], value);\n } else {\n return super.set(key, value);\n }\n }\n}\n\nexport class StreamMetadata {\n\n metadataByBreadcrumb: MetadataMap;\n\n constructor() {\n this.metadataByBreadcrumb = new MetadataMap();\n }\n\n fromCatalogStreamMetadata(metadataArr: CatalogMetadata[]) {\n metadataArr.forEach(metadata => {\n this.metadataByBreadcrumb.set(metadata.breadcrumb, metadata.metadata);\n })\n return this;\n }\n\n toString() {\n return this.metadataByBreadcrumb;\n }\n\n get(breadcrumb: string[]) {\n return this.metadataByBreadcrumb.get(breadcrumb);\n }\n\n write(breadcrumb: string[], key: string, value: any) {\n\n if (value === undefined) {\n throw new Error(`The value you're trying to write on the metadata at breadcrumb: \\`${breadcrumb}\\` and key: \\`${key}\\` is undefined.\n \n Writing an undefined value is not a valid operation. Is there something wrong with your value?`)\n }\n\n if (!this.metadataByBreadcrumb.get(breadcrumb)) {\n this.metadataByBreadcrumb.set(breadcrumb, {})\n }\n\n const previousValue = this.metadataByBreadcrumb.get(breadcrumb);\n const newValue: any = {};\n newValue[key] = value;\n\n this.metadataByBreadcrumb.set(breadcrumb, { ...previousValue, ...newValue });\n\n return this;\n }\n\n private getRootBreadcrumbMetadata(): MetadataEntry {\n const rootBreadcrumbMetadata = this.metadataByBreadcrumb.get([]);\n\n if (!rootBreadcrumbMetadata) {\n throw new Error(`No metadata was attached to the root breadcrumb \\`[\\`] while we need one to store metadata at the table level. \n \n Is your catalog properly generated?`)\n }\n\n return rootBreadcrumbMetadata;\n }\n\n isStreamSelected(): boolean {\n const rootBreadcrumbMetadata = this.getRootBreadcrumbMetadata();\n\n if (rootBreadcrumbMetadata.selected === false) {\n return false;\n }\n\n if (\n rootBreadcrumbMetadata.selected === true\n || rootBreadcrumbMetadata[\"selected-by-default\"] === true\n ) {\n return true;\n }\n\n return false;\n }\n\n getKeyProperties(): string[] {\n const rootBreadcrumbMetadata = this.getRootBreadcrumbMetadata();\n\n if (!rootBreadcrumbMetadata[\"table-key-properties\"]) {\n return []\n }\n\n return rootBreadcrumbMetadata[\"table-key-properties\"];\n }\n\n getReplicationKey(): string | undefined {\n const rootBreadcrumbMetadata = this.getRootBreadcrumbMetadata();\n\n if (!rootBreadcrumbMetadata[\"replication-key\"]) {\n return undefined\n }\n\n return rootBreadcrumbMetadata[\"replication-key\"];\n }\n\n getReplicationMethod(): ReplicationMethod | undefined {\n const rootBreadcrumbMetadata = this.getRootBreadcrumbMetadata();\n\n if (!rootBreadcrumbMetadata[\"replication-method\"]) {\n return undefined\n }\n\n return rootBreadcrumbMetadata[\"replication-method\"];\n }\n\n getForcedReplicationMethod(): ReplicationMethod | undefined {\n const rootBreadcrumbMetadata = this.getRootBreadcrumbMetadata();\n\n if (!rootBreadcrumbMetadata[\"forced-replication-method\"]) {\n return undefined\n }\n\n return rootBreadcrumbMetadata[\"forced-replication-method\"];\n }\n\n toList(): CatalogMetadata[] {\n return Array.from(this.metadataByBreadcrumb.keys()).map(breadcrumb => {\n const metadata = this.metadataByBreadcrumb.get(breadcrumb);\n\n if (!metadata) {\n throw new Error(`There was no metadata entry for breadcrumb: \\`${breadcrumb}\\` in metadata map: ${this.metadataByBreadcrumb.toString()}`)\n }\n\n return {\n breadcrumb,\n metadata: metadata\n }\n })\n }\n\n}","import { CatalogMetadata as CatalogStreamMetadata, StreamMetadata } from \"./metadata\";\nimport { loadJson } from \"../utils\";\nimport { logger } from \"../service/logger\";\nimport * as _ from \"lodash\";\n\nexport type StreamId = string;\nexport type StreamName = string;\n\nexport interface CatalogStream {\n tap_stream_id: StreamId;\n stream: StreamName;\n schema: any;\n metadata: CatalogStreamMetadata[];\n}\n\nexport interface CatalogFile {\n streams: CatalogStream[]\n}\n\nexport class Catalog {\n\n streams?: CatalogStream[];\n\n static fromFile(fileName: string) {\n const catalogFile: CatalogFile = loadJson(fileName);\n\n const catalog = new Catalog();\n catalog.streams = catalogFile.streams;\n return catalog;\n }\n\n static fromCatalogFile(catalogFile: CatalogFile) {\n const catalog = new Catalog();\n catalog.streams = catalogFile.streams;\n return catalog;\n }\n\n getSelectedStreams(): CatalogStream[] {\n\n if (!this.streams) {\n return [];\n }\n\n const directSelectedStreams = this.streams.filter(stream => {\n const metadata = new StreamMetadata();\n metadata.fromCatalogStreamMetadata(stream.metadata)\n return metadata.isStreamSelected();\n });\n\n logger.debug(`Directly selected streams: ${directSelectedStreams.map((stream) => stream.stream).join(\",\")}`)\n\n const getIndirectSelectedStreams = (\n stream: CatalogStream,\n ancestorsIds?: string[]\n ): string[] => {\n const currAncestorsIds = ancestorsIds || [];\n\n const rootBreadcrumbMetadata = stream.metadata.find((metadata) => metadata.breadcrumb.length === 0);\n\n const parentStreamId = rootBreadcrumbMetadata?.metadata?.[\"whaly-parent-stream\"];\n if (parentStreamId) {\n const parentStream = this.streams?.find(stream => stream.stream === parentStreamId);\n if (parentStream) {\n currAncestorsIds.push(parentStreamId);\n return getIndirectSelectedStreams(parentStream, currAncestorsIds)\n }\n }\n\n // Final point of the recursion\n return currAncestorsIds;\n }\n\n const indirectSelectedStreamIds = _.uniq(\n directSelectedStreams.\n flatMap((stream) => {\n return getIndirectSelectedStreams(stream);\n })\n )\n\n logger.debug(`Indirectly selected streams: ${indirectSelectedStreamIds.join(\",\")}`)\n\n // Todo: handle duplicated with directly selected streams\n const indirectSelectedStreams = indirectSelectedStreamIds\n .map((streamId) => {\n // In order to avoid selecting twice the same streams,\n // we check if it wasn't already directly selected\n if (!directSelectedStreams.find(stream => stream.stream === streamId)) {\n return this.streams?.find((stream) => stream.stream === streamId)\n }\n })\n .filter((stream): stream is CatalogStream => !!stream)\n\n return directSelectedStreams.concat(indirectSelectedStreams);\n }\n\n}","import { StreamId } from \"./catalog\";\nimport { ReplicationMethod } from \"./models\";\nimport { DirectionalRelationships } from \"./relationship\";\nimport { PropertiesMetadata } from \"./schema\";\n\nexport type MessageType = \"RECORD\" | \"STATE\" | \"SCHEMA\" | \"ACTIVATE_VERSION\" | \"REPLICATION_METHOD\";\n\nexport interface Message {\n type: MessageType;\n toString(): string;\n}\n\nexport class RecordMessage implements Message {\n\n type: MessageType = \"RECORD\"\n stream: StreamId;\n record: any;\n\n constructor(record: any, stream: StreamId) {\n this.record = record;\n this.stream = stream;\n }\n\n toString() {\n const result = {\n type: \"RECORD\",\n record: this.record,\n stream: this.stream\n }\n return JSON.stringify(result);\n }\n}\n\nexport class StateMessage implements Message {\n\n type: MessageType = \"STATE\"\n value: any\n\n constructor(value: any) {\n this.value = value\n }\n\n toString() {\n const result = {\n type: \"STATE\",\n value: this.value\n }\n return JSON.stringify(result);\n }\n}\n\nexport class ReplicationMethodMessage implements Message {\n\n type: MessageType = \"REPLICATION_METHOD\";\n stream: string;\n replication: ReplicationMethod;\n\n constructor(stream: string, version: ReplicationMethod) {\n this.stream = stream;\n this.replication = version;\n }\n\n toString() {\n const result = {\n type: \"REPLICATION_METHOD\",\n replication: this.replication,\n stream: this.stream\n }\n return JSON.stringify(result);\n }\n}\n\nexport class SchemaMessage implements Message {\n\n type: MessageType = \"SCHEMA\";\n stream: StreamId;\n schema: any;\n keyProperties: string[];\n bookmarkProperties: string[] | undefined;\n displayLabel: string | undefined;\n description: string | undefined;\n propertiesMetadata: PropertiesMetadata | undefined\n relationships: DirectionalRelationships;\n\n constructor(opts: {\n stream: StreamId,\n schema: any,\n keyProperties: string[],\n bookmarkProperties?: string[],\n displayLabel?: string,\n description?: string,\n relationships: DirectionalRelationships,\n propertiesMetadata?: PropertiesMetadata | undefined\n }) {\n const {\n stream,\n schema,\n keyProperties,\n bookmarkProperties,\n displayLabel,\n description,\n relationships,\n propertiesMetadata\n } = opts;\n\n this.stream = stream;\n this.schema = schema;\n this.keyProperties = keyProperties;\n this.bookmarkProperties = bookmarkProperties;\n this.displayLabel = displayLabel;\n this.description = description;\n this.relationships = relationships;\n this.propertiesMetadata = propertiesMetadata;\n }\n\n toString() {\n const result: any = {\n type: \"SCHEMA\",\n stream: this.stream,\n schema: this.schema,\n key_properties: this.keyProperties,\n label: this.displayLabel,\n description: this.description,\n relationships: this.relationships\n }\n\n if (this.bookmarkProperties) {\n result[\"bookmark_properties\"] = this.bookmarkProperties\n }\n\n return JSON.stringify(result);\n }\n}","import { StreamId } from \"./catalog\";\nimport { StateMessage } from \"./messages\";\nimport moment from \"moment\";\nimport { ITarget } from \"./target/target\";\nimport { defaultDateTimeFormat } from \"../constants/date\";\nimport { format } from \"util\";\n\nexport interface InputTapState {\n bookmarks?: {\n [streamId: string]: StreamState\n }\n}\n\nexport interface TapState {\n bookmarks: {\n [streamId: string]: StreamState\n }\n}\n\nexport interface Bookmark {\n replicationKey?: string;\n replicationKeyValue?: string; // Contains ISO 8601 string\n}\n\nexport interface StreamState extends Bookmark {\n progressMarkers?: ProgressMarkers\n replicationKeySignpost?: string\n}\n\nexport interface ProgressMarkers extends Bookmark {\n Note?: string;\n}\n\n// To deprecate\nexport interface State {\n bookmarks: Bookmarks;\n}\n\n// To deprecate\nexport interface Bookmarks {\n [streamId: string]: any;\n}\n\nconst PROGRESS_MARKERS = \"progressMarkers\"\nconst PROGRESS_MARKER_NOTE = \"Note\"\nconst SIGNPOST_MARKER = \"replicationKeySignpost\"\n\nexport const incrementStreamState = (\n state: StreamState,\n replicationKey: string,\n latestRecord: any,\n isSorted: boolean\n): StreamState => {\n\n let newRkValue = latestRecord[replicationKey] as string;\n if (!newRkValue) {\n throw new Error(format(`No value for replicationKey: ${replicationKey} in record with keys: %j`, Object.keys(latestRecord)))\n }\n let newRkValueMoment = moment(newRkValue);\n\n let prevRkValue: string | undefined;\n let prevRkValueMoment: moment.Moment | undefined;\n\n if (isSorted) {\n prevRkValue = state[\"replicationKeyValue\"];\n prevRkValueMoment = moment(prevRkValue);\n if (prevRkValue && prevRkValueMoment.isAfter(newRkValueMoment)) {\n throw new Error(\n `Unsorted data detected in stream. Latest value '${newRkValue}' is\n smaller than previous max '${prevRkValue}'.`\n )\n }\n }\n\n // For unsorted streams, we have to make sure that the \"new\" replication key is newer or equal than the previous one\n if (!isSorted) {\n\n // Progress markers are living only during the current sync\n // They are erased at the end of the sync and the stored value is used to write the new state\n if (!state[PROGRESS_MARKERS]) {\n const marker: ProgressMarkers = {};\n marker[PROGRESS_MARKER_NOTE] = \"Progress is not resumable if interrupted.\"\n state[PROGRESS_MARKERS] = marker;\n }\n prevRkValue = (state[PROGRESS_MARKERS] as any)[\"replicationKeyValue\"];\n\n // In case we don't have any previous value in the PROGRESS_MARKERS, \n // which happens for the first record of the current sync, we take the last state value\n prevRkValueMoment = moment(prevRkValue || state[\"replicationKeyValue\"]);\n\n // If we just got an \"old\" record, we keep the previous state as the max ts\n if (prevRkValue && prevRkValueMoment.isAfter(newRkValueMoment)) {\n newRkValueMoment = prevRkValueMoment;\n newRkValue = prevRkValue;\n }\n }\n\n // Signpost is the moment we start the current sync,\n // we make sure that our replication value can't be greater than the signpost\n const signpostMarker = state[SIGNPOST_MARKER];\n const replicationKeySignpostMoment = moment(signpostMarker);\n\n if (replicationKeySignpostMoment && replicationKeySignpostMoment.isBefore(newRkValueMoment)) {\n // Overflowed max bookmark threshold, reset to the max for this key:\n newRkValueMoment = replicationKeySignpostMoment\n newRkValue = replicationKeySignpostMoment.format(defaultDateTimeFormat);\n }\n\n if (isSorted === false) {\n (state[PROGRESS_MARKERS] as ProgressMarkers)['replicationKey'] = replicationKey;\n (state[PROGRESS_MARKERS] as ProgressMarkers)['replicationKeyValue'] = moment(newRkValueMoment).format(defaultDateTimeFormat);\n } else {\n state['replicationKey'] = replicationKey;\n state['replicationKeyValue'] = moment(newRkValueMoment).format(defaultDateTimeFormat);\n }\n\n return state;\n}\n\n/**\n * Promote or wipe progress markers once sync is complete.\"\"\"\n\n * @param state \n * @returns \n */\nexport const finalizeStateProgressMarkers = (state: StreamState): StreamState => {\n\n const signpostValue = state[SIGNPOST_MARKER];\n const progressMarkers = state[PROGRESS_MARKERS];\n if (progressMarkers && progressMarkers[\"replicationKey\"] && progressMarkers[\"replicationKeyValue\"]) {\n // Replication keys valid (only) after sync is complete\n state[\"replicationKey\"] = progressMarkers[\"replicationKey\"]\n let newRkValue = progressMarkers[\"replicationKeyValue\"]\n\n // Reset to signpost if needed\n if (signpostValue && _greaterThan(newRkValue, signpostValue)) {\n newRkValue = signpostValue\n }\n\n const previousReplicationValue = state[\"replicationKeyValue\"];\n if (!previousReplicationValue || (previousReplicationValue && _greaterThan(newRkValue, previousReplicationValue))) {\n state[\"replicationKeyValue\"] = newRkValue\n }\n }\n // Wipe any markers that have not been promoted\n delete state[PROGRESS_MARKERS];\n\n return state;\n}\n\nexport const _greaterThan = (aValue: string, bValue: string): boolean => {\n return moment(aValue).isAfter(moment(bValue));\n}\n\nexport const extractStateForStream = (state: InputTapState, streamId: StreamId) => {\n if (!state.bookmarks) {\n state.bookmarks = {}\n }\n if (!state.bookmarks[streamId]) {\n state.bookmarks[streamId] = {}\n }\n return state.bookmarks[streamId];\n}\n\nexport class StateService {\n\n private static instance: StateService;\n\n bookmarks: Bookmarks;\n\n constructor() {\n this.bookmarks = {}\n }\n\n static getInstance(): StateService {\n if (!this.instance) {\n this.instance = new this();\n }\n\n return this.instance;\n }\n\n // To be deprecated\n setBookmark(streamId: StreamId, ts: moment.Moment) {\n this.bookmarks[streamId] = ts.format(defaultDateTimeFormat)\n }\n\n setBookmarkV2(streamId: StreamId, streamState: StreamState) {\n this.bookmarks[streamId] = streamState;\n }\n\n setBookmarkSignpostV2(streamId: StreamId, signpostValue: string) {\n if (!this.bookmarks[streamId]) {\n this.bookmarks[streamId] = {}\n }\n this.bookmarks[streamId][SIGNPOST_MARKER] = signpostValue;\n }\n\n getBookmark(streamId: StreamId): moment.Moment {\n // This set the bookmarkTs at EPOCH time (1970) if it's not defined\n if (!this.bookmarks[streamId]) {\n return moment(0);\n }\n\n return moment(this.bookmarks[streamId])\n }\n\n getBookmarkV2(streamId: StreamId): StreamState {\n\n if (this.bookmarks[streamId]) {\n return this.bookmarks[streamId];\n } else {\n return {}\n }\n }\n\n clearState() {\n this.bookmarks = {};\n }\n\n get(): State {\n const state: State = {\n bookmarks: this.bookmarks\n }\n return state\n }\n\n async forwardStateToTarget(target: ITarget) {\n const state: State = {\n bookmarks: this.bookmarks\n }\n\n const message = new StateMessage(state);\n await target.state(message);\n }\n}","export const defaultDateTimeFormat = \"YYYY-MM-DDTHH:mm:ss.SSSSSSZ\"","import { HTTPHeaders, URLParams } from \"../http\";\n\n/**\n * C: The type of the tap config\n */\nexport class Authenticator<C> {\n\n getAuthHeaders(config: C): Promise<HTTPHeaders> {\n return Promise.resolve({})\n }\n\n getAuthQS(config: C): Promise<URLParams> {\n return Promise.resolve({})\n }\n\n}","import axios, { AxiosError, AxiosInstance, AxiosRequestConfig } from \"axios\";\nimport { Authenticator } from \"./authenticator\";\nimport { HTTPHeaders, HTTPMethod, URLParams } from \"../http\";\nimport * as qs from 'qs';\nimport { logger } from \"../../service/logger\";\nimport { StreamV2 } from \"./stream\";\nimport { InputTapState } from \"../state\";\nimport { ITarget } from \"../target/target\";\nimport { getAxiosInstance } from \"../../service/network\";\nimport { DEFAULT_MAX_CONCURRENT_STREAMS } from \"./tap\";\nimport { API_CALLS_METRIC_NAME, CounterMetric, getCounterMetrics, MetricConfiguration } from \"../../service/metric\";\nimport { getTruncatedParamsForLog } from \"../../helpers/qs-logger\";\nimport * as _ from \"lodash\";\n\n/**\n * R: Type of the API result\n * NPT: Type of the \"nextPageToken\"\n */\nexport abstract class RESTStreamV2<R, O, NPT, C, P = undefined>\n extends StreamV2<O, C, P> {\n\n axiosInstance: AxiosInstance | undefined;\n\n constructor(\n tapName: string,\n config: C,\n state: InputTapState,\n target: ITarget,\n childConcurrency: number = DEFAULT_MAX_CONCURRENT_STREAMS\n ) {\n super(tapName, config, state, target, childConcurrency);\n this.apiCallsMetricsConf = {\n isEnabled: () => !this.isSilent,\n getStreamIds: () => [this.streamId]\n }\n }\n\n // Internal\n // Those functions shouldn't be overriden (or it means that we fuck'ed up the SDK during the design phase)\n\n /**\n * Prepare an Axios request object.\n * Pagination information can be parsed from `nextPageToken` if `nextPageToken` is not undefined.\n * @param nextPageToken \n * @returns \n */\n _prepareRequest = async (nextPageToken: NPT | undefined, parent?: P)\n : Promise<AxiosRequestConfig> => {\n\n const method = this.httpMethod;\n const url = this.getUrl(parent);\n if (!url) {\n throw new Error(`StreamId: ${this.streamId} - URL is undefined. Did your properly define the URL for this stream?`)\n }\n\n const authenticator = this.authenticator\n\n const params = {\n ...this.getNextUrlParams(nextPageToken, parent),\n ...(await authenticator?.getAuthQS(this._config))\n }\n\n const requestBody = this.getRequestBodyForNextCall(nextPageToken, parent)\n let headers = this.getCustomHTTPHeaders(parent);\n if (!headers) {\n headers = {};\n }\n\n if (authenticator) {\n const authHeaders = await authenticator.getAuthHeaders(this._config)\n headers = {\n ...headers,\n ...authHeaders\n }\n }\n\n const paramsSerializer = (params: any) => {\n return qs.stringify(params, { arrayFormat: 'repeat' })\n }\n\n const request: AxiosRequestConfig = {\n url,\n method,\n data: requestBody,\n params,\n paramsSerializer,\n headers\n }\n return request\n }\n\n async _requestWithRetry(request: AxiosRequestConfig, privateLogging?: boolean): Promise<R | \"STOP_SYNC\"> {\n try {\n logger.debug(`🤖 ${request.method} ${request.url} with params: %j | body: %j`,\n request.params,\n request.data,\n { private: privateLogging });\n logger.info(`🤖 ${request.method} ${request.url} qs: %j`,\n getTruncatedParamsForLog(request.params),\n { private: privateLogging });\n const axiosInstance = this.axiosInstance;\n if (!axiosInstance) {\n throw new Error(`Axios Instance is not initialized!`)\n }\n const response = await axiosInstance.request<R>(request);\n return response.data;\n } catch (err) {\n if (axios.isAxiosError(err)) {\n logger.error(`🤖 Error on ${request.method} ${request.url} with params %j | body: %j | headers: %j - getting error %s - response body: %j`,\n request.params,\n request.data,\n request.headers,\n err.message,\n err.response?.data\n )\n const recoveredValue = await this.httpErrorHandler(request.url, err);\n if (recoveredValue === undefined) {\n return \"STOP_SYNC\"\n } else {\n return recoveredValue;\n }\n } else {\n throw err;\n }\n }\n }\n\n async *_requestRecords(parent?: P): AsyncIterable<O> {\n let nextPageToken: NPT | undefined = undefined;\n let finished = false;\n\n let apiCallsMetrics: CounterMetric[] = [];\n if (this.apiCallsMetricsConf.isEnabled() === true) {\n apiCallsMetrics = getCounterMetrics(\n API_CALLS_METRIC_NAME,\n this.apiCallsMetricsConf.getStreamIds\n ? this.apiCallsMetricsConf.getStreamIds()\n : []\n )\n }\n\n // We reset the axios instance here to use the value of `httpRetryCount` after the initialization of custom values defined in the Streams impl.\n // Doing it in the constructor is givingf us access only to the default value of `httpRetryCount`\n this.axiosInstance = getAxiosInstance(this.httpRetryCount);\n\n while (!finished) {\n const preparedRequest = await this._prepareRequest(nextPageToken, parent);\n const resp = await this._requestWithRetry(preparedRequest);\n\n apiCallsMetrics.forEach(metric => {\n metric.increment();\n })\n\n // We stop the sync for this stream\n if (resp === \"STOP_SYNC\") {\n return;\n }\n const rows = this.parseResponse(resp, parent, nextPageToken);\n for await (const row of rows) {\n yield row\n }\n\n const previousToken = _.cloneDeep(nextPageToken);\n nextPageToken = this.getNextPageToken(resp, previousToken);\n\n if (nextPageToken && _.isEqual(nextPageToken, previousToken)) {\n throw new Error(\n `${this.streamId} - Loop detected in pagination. \"\n Pagination token: \\`${JSON.stringify(nextPageToken)}\\` is identical to prior token \\`${JSON.stringify(previousToken)}\\`.`\n )\n }\n // Cycle until getNextPageToken() no longer returns a value\n finished = !nextPageToken\n }\n }\n\n async *_getRecords(parent?: P): AsyncIterable<O> {\n for await (const row of this._requestRecords(parent)) {\n yield row\n }\n }\n\n // Overridable\n // Even if the default impl. of some function can be used as-is, those functions\n // are meant to be overriden when necessary to match the API needs.\n httpMethod: HTTPMethod = \"GET\";\n baseUrl: string = \"\";\n path: string = \"\";\n httpRetryCount = 24;\n authenticator?: Authenticator<C>;\n\n apiCallsMetricsConf: MetricConfiguration\n\n // When undefined is returned, we should stop the sync without any error\n async httpErrorHandler(url: string | undefined, err: AxiosError): Promise<R | undefined> {\n if ((err.response?.status || 0) > 400) {\n throw new Error(`We got a \\`${err.response?.status}\\` status code from endpoint: \\`${url}\\`. \n\n Response body from the server: ${JSON.stringify(err.response?.data)}`);\n }\n throw err;\n }\n\n /** \n * Return a dictionary of values to be used in URL parameterization.\n * If paging is supported, developers may override with specific paging logic.\n * \n * By default, no params are passed.\n */\n getNextUrlParams(nextPageToken: NPT | undefined, parent?: P): URLParams {\n return {}\n }\n\n /** \n * Prepare the data payload for the REST API request.\n * Useful when working with POST APIs.\n * \n * By default, no payload will be sent (return undefined).\n */\n getRequestBodyForNextCall(nextPageToken: NPT | undefined, parent?: P): any {\n return undefined\n }\n\n /**\n * Return token identifying next page or undefined if all records have been read.\n * \n * By default, no token will be returned and a single API call will be made.\n * \n * @param response \n * @param previousToken \n * @returns \n */\n getNextPageToken(response: R, previousToken?: NPT): NPT | undefined {\n return undefined;\n }\n\n /**\n * Return custom headers to be used for HTTP requests.\n * \n * By default, no additional header will be added\n */\n getCustomHTTPHeaders(parent?: P): HTTPHeaders | undefined {\n return undefined;\n }\n\n /**\n * Return a URL, optionally targeted to a specific partition.\n * This can be overriden to perform dynamic URL generation.\n * \n * TODO: Make URL + Path templatisable and replace those with Extractor (or Tap) config\n * @returns \n */\n getUrl(parent?: P): string {\n const urlPattern = [this.baseUrl, this.path].join(\"\")\n return urlPattern;\n }\n\n /**\n * Parse the response and return an iterator of result rows.\n * \n * Default impl assume that R = O or R = O[]\n * @param response\n */\n async *parseResponse(\n response: R,\n parent?: P,\n nextPageToken?: NPT\n ): AsyncIterable<O> {\n if (Array.isArray(response)) {\n for (const row of response) {\n yield row as any as O\n }\n } else {\n yield response as any as O\n }\n }\n\n}","import moment from \"moment\";\nimport { defaultDateTimeFormat } from \"../../constants/date\";\nimport { isDatetimeType } from \"../../helpers/typing\";\nimport { logger } from \"../../service/logger\";\nimport { findRelatedRelationships } from \"../../service/relationship\";\nimport { loadJson } from \"../../utils\";\nimport { StreamId } from \"../catalog\";\nimport { RecordMessage, ReplicationMethodMessage, SchemaMessage, StateMessage } from \"../messages\";\nimport { MetadataEntry } from \"../metadata\";\nimport { ReplicationMethod } from \"../models\";\nimport { extractStateForStream, finalizeStateProgressMarkers, incrementStreamState, InputTapState, StateService } from \"../state\";\nimport { ITarget } from \"../target/target\";\nimport * as _ from \"lodash\";\nimport { StreamRelationship } from \"../relationship\";\nimport { Schema } from \"../schema\";\nimport { Promise as BPromise } from \"bluebird\";\nimport { DEFAULT_MAX_CONCURRENT_STREAMS } from \"./tap\";\nimport { CounterMetric, EXECUTION_TIME_METRIC_NAME, getCounterMetrics, MetricConfiguration, ROWS_SYNCED_METRIC_NAME } from \"../../service/metric\";\nimport { format } from \"util\";\n\n/**\n * TODO: Handle non timestamp based replication key\n *\n * O: Type of a resulted row after post processing\n * C: Type of the tap configuration\n * P: For children Streams, this is the type of the parent\n */\nexport abstract class StreamV2<O = any, C = any, P = undefined> {\n\n // Runtime values, can't be overriden\n _config: C;\n _tapName: string = \"default\";\n _tapState: InputTapState;\n _target: ITarget;\n // Contains the root metadata entry of the catalog stream configuration\n // contains some end user schema configuration\n rootMetadataEntry: MetadataEntry | undefined;\n\n // Compile time values, can be overriden\n // Replication method that can be forced in the stream implemenation. Will prevail over any user/catalog choice\n forcedReplicationMethod: ReplicationMethod | undefined = undefined;\n selectedByDefault: boolean = true;\n STATE_MSG_FREQUENCY: number = 10;\n streamId: StreamId = \"default\";\n schemaPath: string | undefined = undefined;\n displayLabel: string | undefined = undefined;\n description: string | undefined = undefined;\n primaryKey: string[] = [];\n forcedReplicationKey: string | undefined = undefined;\n // When set, use the state from another stream for this stream\n useStateFromStreamId: string | undefined = undefined;\n\n relationships: StreamRelationship[] = []\n\n children: StreamV2<any, any, O | O[]>[] = [];\n // If true, it means that the records in this stream are sorted by replicationKey.\n // If false, then the records are coming in an unsorted manner.\n isSorted: boolean = false;\n // If true, then no SCHEMA / RECORD messages will be sent for this Stream.\n // However, a STATE will still be emitted if the Stream is using an incremental sync type.\n isSilent: boolean = false;\n\n childConcurrency: number;\n\n // Metrics configuration\n rowsSyncedMetricsConf: MetricConfiguration\n executionTimeMetricsConf: MetricConfiguration\n\n constructor(\n tapName: string,\n config: C,\n state: InputTapState,\n target: ITarget,\n childConcurrency: number = DEFAULT_MAX_CONCURRENT_STREAMS\n ) {\n this._tapName = tapName;\n this._config = config;\n this._tapState = _.cloneDeep(state);\n this._target = target;\n this.childConcurrency = childConcurrency;\n\n // Default metric configuration\n this.rowsSyncedMetricsConf = {\n isEnabled: () => !this.isSilent,\n getStreamIds: () => [this.streamId]\n }\n this.executionTimeMetricsConf = {\n isEnabled: () => !this.isSilent,\n getStreamIds: () => [this.streamId]\n }\n }\n\n setRootMetadataEntry = (rootMetadataEntry: MetadataEntry) => {\n this.rootMetadataEntry = rootMetadataEntry;\n }\n\n /**\n * Sync this stream\n * Called only for streams with no parents, aka. \"root tap streams\"\n * @returns \n */\n sync = async (): Promise<void> => {\n try {\n const replicationMethod = this.configuredReplicationConfig().replicationMethod;\n logger.info(\n `🎬 Beginning ${replicationMethod} sync of stream '${this.streamId}'...`\n )\n\n await this.asyncInit();\n\n // Send a SCHEMA message to the downstream target\n await this._writeSchemaMessage();\n\n await this._writeReplicationMethodMessage();\n\n // Write the signpost\n await this._writeSignpostInState();\n\n // Sync the records themselves\n await this._syncRecords();\n\n // Flush the stream\n return this.flush();\n } catch (err) {\n if (err instanceof Error) {\n throw new Error(format(`got an error while syncing streamId=%s, err: %s`, this.streamId, err.message))\n }\n throw err;\n }\n }\n\n flush = async (): Promise<void> => {\n const replicationMethod = this.configuredReplicationConfig().replicationMethod;\n logger.info(\n `🚽 Flushing ${replicationMethod} sync of stream '${this.streamId}' + all of its children...`\n )\n\n await this._flush();\n\n await BPromise.map(this.children, child => {\n return child.flush();\n }, { concurrency: 3 });\n }\n\n // Private message authoring methods:\n\n /**\n * Write out a STATE message with the latest state.\n */\n _writeStateMessage = (): Promise<void> => {\n const message = new StateMessage(StateService.getInstance().get());\n return this._target.state(message);\n }\n\n /**\n * Write out a ACTIVATE_VERSION message.\n */\n _writeReplicationMethodMessage = async (): Promise<void> => {\n const method = this.configuredReplicationConfig().replicationMethod;\n const message = new ReplicationMethodMessage(this.streamId, method);\n\n await BPromise.map(this.children, async c => {\n return c._writeReplicationMethodMessage()\n }, { concurrency: 3 })\n await this._target.replicationMethod(message);\n }\n\n /**\n * Write out a SCHEMA message with the stream schema.\n */\n _writeSchemaMessage = async (skipChildrenSchema?: boolean): Promise<void> => {\n\n if (!this.isSilent) {\n const schema = await this.getSchema();\n if (schema !== undefined) {\n const relatedRels = findRelatedRelationships(this.streamId, this.relationships);\n const replicationConfig = this.configuredReplicationConfig();\n\n const message = new SchemaMessage({\n keyProperties: this.primaryKey,\n stream: this.streamId,\n schema: schema.jsonSchema,\n relationships: relatedRels,\n ...(replicationConfig.replicationKey ? { bookmarkProperties: [replicationConfig.replicationKey] } : {}),\n ...(this.displayLabel ? { displayLabel: this.displayLabel } : {}),\n ...(this.description ? { description: this.description } : {}),\n ...(schema.propertiesMetadata ? { propertiesMetadata: schema.propertiesMetadata } : {})\n })\n await this._target.schema(message);\n }\n }\n\n if (skipChildrenSchema !== true) {\n await BPromise.map(this.children, async (child) => {\n await child._writeSchemaMessage();\n }, { concurrency: 3 });\n }\n }\n\n // Private bookmarking methods\n\n _writeSignpostInState = async () => {\n const signpostMoment = await this.getReplicationKeySignpost();\n const signpostValue = signpostMoment?.format(defaultDateTimeFormat);\n\n if (signpostValue) {\n StateService.getInstance().setBookmarkSignpostV2(this.streamId, signpostValue);\n }\n }\n\n /**\n * Update state of stream with data from the provided record. \n */\n _incrementStreamState = (latestRecord: O): void => {\n\n if (latestRecord) {\n const replicationConfig = this.configuredReplicationConfig()\n if ([\n \"INCREMENTAL\",\n \"LOG_BASED\",\n ].includes(replicationConfig.replicationMethod)) {\n // If the stream is using another stream state, it doesn't own the state and can't increment it\n if (this.useStateFromStreamId) {\n return;\n }\n // If the replication method was forced, it can be that the stream is the child of anohter stream that is managing the state (ex. a paginated stream). \n // The state is not owned by the current stream then.\n if (this.forcedReplicationMethod && !this.forcedReplicationKey) {\n return;\n }\n\n // If the stream has been detected as being incremental and has no excuses for not owning its state, it should have the replicationKey\n if (!replicationConfig.replicationKey) {\n throw new Error(`Could not detect replication key for '${this.streamId}' stream\"\n replication method=${replicationConfig.replicationMethod})`\n )\n }\n\n const stateServiceInst = StateService.getInstance();\n const state = stateServiceInst.getBookmarkV2(this.streamId);\n\n const newState = incrementStreamState(\n state,\n replicationConfig.replicationKey,\n latestRecord,\n this.isSorted\n )\n\n StateService.getInstance().setBookmarkV2(this.streamId, newState)\n }\n }\n }\n\n /**\n * Return True if the stream uses a timestamp-based replication key.\n * \n * Developers can override with `is_timestamp_replication_key = True` in\n order to force this value.\n */\n isTimestampReplicationKey = async (): Promise<boolean> => {\n\n const replicationConfig = this.configuredReplicationConfig()\n\n if (!replicationConfig.replicationKey) {\n return false;\n }\n\n const schema = await this.getSchema();\n if (!schema || !schema.jsonSchema || !schema.jsonSchema.properties) {\n return false;\n }\n\n const typeFromSchema = schema.jsonSchema[\"properties\"][replicationConfig.replicationKey]\n if (!typeFromSchema) {\n return false;\n }\n\n return isDatetimeType(typeFromSchema);\n }\n\n /**\n * Return state timestamp if set for the stream, \n * or `start_date` config if set, \n * or the UNIX Epoch\n **/\n getStartingTimestamp(): moment.Moment {\n const streamIdToReadFrom = this.useStateFromStreamId ? this.useStateFromStreamId : this.streamId;\n const state = extractStateForStream(this._tapState, streamIdToReadFrom);\n\n const startDate = (this._config as any).start_date as string | undefined;\n const replicationConfig = this.configuredReplicationConfig();\n\n logger.debug(`${this.streamId}: state.replicationKeyValue: ${state.replicationKeyValue}, \n state.replicationKey: ${state.replicationKey},\n this.replicationKey: ${replicationConfig.replicationKey}`)\n\n if (state.replicationKeyValue) {\n logger.debug(`${this.streamId} - getStartingTimestamp -> Returning replication key value: ${state.replicationKeyValue}`)\n return moment(state.replicationKeyValue);\n } else if (startDate) {\n logger.debug(`${this.streamId} - getStartingTimestamp -> Returning config start date: ${startDate}`)\n return moment(startDate)\n } else {\n logger.debug(`${this.streamId} - getStartingTimestamp -> Returning EPOCH (1970)`)\n return moment(0);\n }\n }\n\n /**\n * Return the max allowable bookmark value for this stream's replication key.\n * \n * For timestamp-based replication keys, this defaults to `moment()`. For\n * non-timestamp replication keys, default to `undefined`.\n * \n * Override this value to prevent bookmarks from being advanced in cases where we\n * may only have a partial set of records.\n */\n getReplicationKeySignpost = async (): Promise<moment.Moment | undefined> => {\n\n if (await this.isTimestampReplicationKey()) {\n return moment()\n }\n\n return undefined\n }\n\n /**\n * Return the default replication method for the stream that will be used to write the catalog.\n */\n defaultReplicationConfig = (): {\n replicationMethod: ReplicationMethod,\n replicationKey: string | undefined,\n // When replication method is forced, it means that end user can't override it.\n isForced: boolean\n } => {\n if (this.forcedReplicationMethod) {\n return {\n replicationMethod: this.forcedReplicationMethod,\n replicationKey: this.forcedReplicationKey,\n isForced: true\n }\n }\n if (this.forcedReplicationKey || this.useStateFromStreamId) {\n return {\n replicationMethod: \"INCREMENTAL\",\n replicationKey: this.forcedReplicationKey,\n isForced: true\n }\n }\n\n return {\n replicationMethod: \"FULL_TABLE\",\n replicationKey: undefined,\n isForced: false\n }\n }\n\n /**\n * Return the configured replication method that will be used for the sync.\n */\n configuredReplicationConfig = (): {\n replicationMethod: ReplicationMethod,\n replicationKey: string | undefined\n } => {\n\n const defaultReplicationMethod = this.defaultReplicationConfig();\n\n if (defaultReplicationMethod.isForced) {\n return {\n replicationMethod: defaultReplicationMethod.replicationMethod,\n replicationKey: defaultReplicationMethod.replicationKey\n };\n }\n\n return {\n replicationMethod: this.rootMetadataEntry?.[\"replication-method\"] || defaultReplicationMethod.replicationMethod,\n replicationKey: this.rootMetadataEntry?.[\"replication-key\"] || defaultReplicationMethod.replicationKey\n }\n }\n\n // Private sync methods:\n async _syncRecords(parent?: P): Promise<void> {\n let rowsSent = 0;\n\n let recordSyncedMetrics: CounterMetric[] = [];\n if (this.rowsSyncedMetricsConf.isEnabled() === true) {\n recordSyncedMetrics = getCounterMetrics(\n ROWS_SYNCED_METRIC_NAME,\n this.rowsSyncedMetricsConf.getStreamIds\n ? this.rowsSyncedMetricsConf.getStreamIds()\n : []\n )\n }\n\n let executionTimeMetrics: CounterMetric[] = [];\n if (this.executionTimeMetricsConf.isEnabled() === true) {\n executionTimeMetrics = getCounterMetrics(\n EXECUTION_TIME_METRIC_NAME,\n this.executionTimeMetricsConf.getStreamIds\n ? this.executionTimeMetricsConf.getStreamIds()\n : []\n )\n }\n\n const startTime = new Date().getTime();\n\n for await (const row of this._getRecords(parent)) {\n\n if ((rowsSent - 1) % this.STATE_MSG_FREQUENCY == 0) {\n await this._writeStateMessage()\n }\n\n const recordMessage = new RecordMessage(\n { ...row },\n this.streamId\n )\n\n if (!this.isSilent) {\n await this._target.record(recordMessage);\n }\n\n await BPromise.map(this.children, async (child) => {\n await child.asyncInit(row);\n return child._syncRecords(row);\n },\n {\n concurrency: this.childConcurrency\n });\n this._incrementStreamState(row);\n recordSyncedMetrics.forEach((metric) => {\n metric.increment();\n })\n rowsSent += 1;\n }\n\n const stateServiceInst = StateService.getInstance();\n const state = stateServiceInst.getBookmarkV2(this.streamId);\n const newState = finalizeStateProgressMarkers(state);\n stateServiceInst.setBookmarkV2(this.streamId, newState);\n\n if (!parent) {\n logger.info(`✅ Completed sync for stream: ${this.streamId} (${rowsSent} records)`);\n } else {\n logger.debug(`✅ Completed sync for sub-stream: ${this.streamId} (${rowsSent} records)`);\n }\n\n await this._writeStateMessage();\n const endTime = new Date().getTime();\n const executionTimeMs = endTime - startTime;\n executionTimeMetrics.forEach(metric => {\n metric.increment(executionTimeMs);\n })\n\n }\n\n // Overridable Methods\n\n asyncInit(parent?: P): Promise<void> {\n return Promise.resolve()\n }\n\n /**\n * Return the stream schema.\n * \n * Can be overriden to return a dynamic schema\n */\n getSchema(): Promise<Schema | undefined> {\n logger.debug(`stream: ${this.streamId} - getSchema() is called`)\n if (this.schemaPath) {\n const schema = loadJson(`schemas/${this._tapName}/${this.schemaPath}`)\n return Promise.resolve({ jsonSchema: schema });\n } else {\n if (this.isSilent) {\n return Promise.resolve(undefined);\n }\n throw new Error(`Stream=${this.streamId} - No schema path was passed.\n Either you forgot to fill the the \\`schemaPath\\` property,\n or to override the getSchema() method.`)\n }\n }\n\n getRowCount(): Promise<number | undefined> {\n return Promise.resolve(undefined)\n }\n\n /**\n * Abstract row generator function. Must be overridden by the child class.\n */\n _getRecords(parent?: P): AsyncIterable<O> {\n throw new Error(`Stream._getRecords() - Should be implemented by child class`);\n }\n\n /**\n * Return the list of keys that can be configured in the UI by the end user as the replication key\n * @returns \n */\n getValidReplicationKeys(): Promise<string[]> {\n return Promise.resolve([]);\n }\n\n /**\n * Called at the end of the sync. Use to flush all records before closing the Stream.\n * @returns \n */\n async _flush(): Promise<void> {\n await Promise.resolve();\n }\n}","\ninterface TypeDef {\n anyOf?: TypeDef[]\n type: string | string[]\n format?: \"date-time\"\n}\n/**\n * Return True if JSON Schema type definition is a 'date-time' type.\n * \n * Also returns True if 'date-time' is nested within an 'anyOf' type Array.\n\n * @param typeDef \n * @returns \n */\nexport const isDatetimeType = (typeDef: TypeDef): boolean => {\n\n if (!typeDef) {\n throw new Error(\"Could not detect type from empty typeDef param.\")\n }\n\n if (typeDef[\"anyOf\"] !== undefined) {\n for (const subTypeDef of typeDef[\"anyOf\"]) {\n if (isDatetimeType(subTypeDef)) {\n return true\n }\n }\n return false\n }\n\n else if (typeDef[\"type\"] !== undefined) {\n return typeDef[\"format\"] === \"date-time\"\n }\n\n throw new Error(\n `Could not detect type of key using schema '${typeDef}'`\n )\n\n}","import { logger } from \"../../service/logger\";\nimport { CatalogFile, Catalog } from \"../catalog\";\nimport { CatalogMetadata, StreamMetadata } from \"../metadata\";\nimport { StateService } from \"../state\";\nimport { ITarget } from \"../target/target\";\nimport { StreamV2 } from \"./stream\";\nimport { Promise as BPromise } from \"bluebird\";\nimport { DepGraph } from \"dependency-graph\";\n\nexport const DEFAULT_MAX_CONCURRENT_STREAMS = 5;\n\nexport abstract class Tap<C> {\n _target: ITarget;\n _config: C;\n _streams: StreamV2[];\n _concurrency: number = DEFAULT_MAX_CONCURRENT_STREAMS;\n\n abstract init(): Promise<void>;\n abstract requiredConfigKeys(): string[];\n\n constructor(\n target: ITarget,\n config: C\n ) {\n this._streams = [];\n this._target = target;\n this._config = config\n }\n\n discover = async (\n existingCatalog: CatalogFile | undefined\n ): Promise<CatalogFile> => {\n\n logger.debug('Loading schemas');\n\n const streamDepGraph = new DepGraph<StreamV2<any, any, any>>();\n\n const buildDependencyGraph = (\n streams: StreamV2<any, any, any>[],\n parentId?: string\n ): void => {\n streams.forEach(s => {\n streamDepGraph.addNode(s.streamId, s);\n if (parentId) {\n streamDepGraph.addDependency(s.streamId, parentId)\n }\n if (s.children) {\n return buildDependencyGraph(s.children, s.streamId);\n }\n })\n }\n\n buildDependencyGraph(this._streams);\n\n const discoveredStreamCatalogEntries = await BPromise.map(\n streamDepGraph.overallOrder(),\n async streamId => {\n logger.info(`✨ Loading schema for ${streamId}`)\n const stream = streamDepGraph.getNodeData(streamId);\n const schema = await stream.getSchema();\n const parentStreamIds = streamDepGraph.directDependenciesOf(streamId);\n if (parentStreamIds.length > 1) {\n throw new Error(`StreamId=${streamId} directly depends on more than 1 stream, e.g. ${parentStreamIds.join(\",\")} which is not supported!`)\n }\n const parentStreamId = parentStreamIds?.[0];\n const { metadata } = await this.generateMetadataFromStream(stream, parentStreamId);\n return {\n schema,\n metadata,\n stream: stream.streamId,\n tap_stream_id: stream.streamId,\n }\n },\n { concurrency: this._concurrency }\n );\n\n // We want to keep the catalog configuration of already discovered streams to keep end user configuration\n // So we detect newly discovered streams and we only append those to the catalog\n const existingCatalogStreamIds = (existingCatalog?.streams || []).map(entry => {\n return entry.stream;\n });\n\n const newlyDiscoveredStreamCatalogEntries = discoveredStreamCatalogEntries\n .filter((entry) => {\n if (existingCatalogStreamIds.includes(entry.stream)) {\n return false;\n } else {\n return true;\n }\n })\n\n logger.debug(`Newly discovered streams: %j`, newlyDiscoveredStreamCatalogEntries);\n\n const allDiscoveredStreamIds = discoveredStreamCatalogEntries\n .map(entry => {\n return entry.stream\n })\n\n const existingCatalogMinusDeletedStreams = (existingCatalog?.streams || [])\n .filter(entry => {\n if (!allDiscoveredStreamIds.includes(entry.stream)) {\n logger.debug(`Stream %s was deleted, removing it from the catalog`, entry.stream)\n return false\n } else {\n return true;\n }\n })\n\n // This is used to make some updates on the existing catalog entries by overriding the values with the ones from the current discovery result\n // This is currently used:\n // - to override the parent stream value in case of a streamId change in the connector code\n // - to update the rowCount value on streams which is dynamic\n // - to update the forced replication config in case of a change in the connector code\n // - to publish the valid replication keys in case of a change in the connector code\n const updatedExistingCatalog = existingCatalogMinusDeletedStreams\n .map(existingCatalogEntry => {\n const matchingDiscoveredCatalogEntry = discoveredStreamCatalogEntries.find(entry => entry.stream === existingCatalogEntry.stream)\n if (matchingDiscoveredCatalogEntry) {\n const existingRootMetadata = existingCatalogEntry.metadata.find(metadata => metadata.breadcrumb.length === 0);\n const discoveredRootMetadata = matchingDiscoveredCatalogEntry.metadata.find(metadata => metadata.breadcrumb.length === 0);\n if (existingRootMetadata) {\n // As `existingRootMetadata` is a reference to the proper item of the array, this will have a side effect on existingCatalogEntry\n const parentStreamVal = discoveredRootMetadata?.metadata[\"whaly-parent-stream\"];\n if (parentStreamVal !== undefined) {\n existingRootMetadata.metadata[\"whaly-parent-stream\"] = parentStreamVal;\n }\n const forcedReplicationMethodVal = discoveredRootMetadata?.metadata[\"forced-replication-method\"];\n if (forcedReplicationMethodVal !== undefined) {\n existingRootMetadata.metadata[\"forced-replication-method\"] = forcedReplicationMethodVal;\n }\n const forcedReplicationKeyVal = discoveredRootMetadata?.metadata[\"forced-replication-key\"];\n if (forcedReplicationKeyVal !== undefined) {\n existingRootMetadata.metadata[\"forced-replication-key\"] = forcedReplicationKeyVal;\n }\n const validReplicationKeysVal = discoveredRootMetadata?.metadata[\"valid-replication-keys\"];\n if (validReplicationKeysVal !== undefined) {\n existingRootMetadata.metadata[\"valid-replication-keys\"] = validReplicationKeysVal;\n }\n const rowCountVal = discoveredRootMetadata?.metadata[\"row-count\"];\n if (rowCountVal !== undefined) {\n existingRootMetadata.metadata[\"row-count\"] = rowCountVal;\n }\n }\n }\n return existingCatalogEntry\n })\n\n const streams = updatedExistingCatalog.concat(newlyDiscoveredStreamCatalogEntries)\n return { streams };\n }\n\n sync = async (catalog: Catalog): Promise<void> => {\n await this.initiateSync(catalog);\n logger.debug(`[TAP] All streams have finished syncing. We send the [complete] signal to the target.`)\n await this._target.complete();\n return Promise.resolve();\n };\n\n async generateMetadataFromStream(\n stream: StreamV2,\n parentStreamId: string | undefined\n ): Promise<{ metadata: CatalogMetadata[]; }> {\n const metadata = new StreamMetadata();\n\n metadata.write([], \"table-key-properties\", stream.primaryKey);\n const defaultReplicationConfig = stream.defaultReplicationConfig();\n\n // Default value for catalog generation, will be overriden by end user in the interface if needed\n metadata.write([], \"replication-method\", defaultReplicationConfig.replicationMethod);\n\n const validReplicationkeys = await stream.getValidReplicationKeys();\n metadata.write([], \"valid-replication-keys\", validReplicationkeys);\n\n if (defaultReplicationConfig.isForced) {\n metadata.write([], \"forced-replication-method\", defaultReplicationConfig.replicationMethod);\n if (stream.forcedReplicationKey) {\n metadata.write([], \"forced-replication-key\", stream.forcedReplicationKey);\n }\n }\n\n const rowCount = await stream.getRowCount();\n if (rowCount !== undefined) {\n metadata.write([], \"row-count\", rowCount);\n }\n\n // We hide from the UI the silent streams that are technical\n if (stream.isSilent === true) {\n metadata.write([], \"whaly-is-hidden\", stream.isSilent);\n }\n\n // We only select by default the non silent stream, as those will be the only ones to be configurable in the UI\n if (stream.isSilent === false) {\n metadata.write([], \"selected-by-default\", stream.selectedByDefault);\n }\n\n if (stream.displayLabel) {\n metadata.write([], \"whaly-display-label\", stream.displayLabel);\n }\n\n if (stream.description) {\n metadata.write([], \"whaly-description\", stream.description);\n }\n\n if (parentStreamId !== undefined) {\n metadata.write([], \"whaly-parent-stream\", parentStreamId);\n }\n\n return { metadata: metadata.toList() }\n }\n\n async initiateSync(catalog: Catalog) {\n\n logger.info(`🚀 Start syncing`)\n\n const state = StateService.getInstance().get();\n\n logger.info(`📍 Received state: %j`, state)\n logger.debug(`📚 Received catalog: %j`, catalog)\n\n const selectedStreams = catalog.getSelectedStreams();\n\n if (selectedStreams.length === 0) {\n logger.info(`😱 There is no stream to sync. \n \n Did you update the \\`catalog.json\\` to add \\`\"selected\": true\\` in the table metadata associated with the root breadcrumb (e.g. \\`[]\\`)`);\n return\n }\n\n const selectedStreamIds = selectedStreams.map(stream => stream.stream);\n logger.info(`🥳 Syncing selected streams: %s`, selectedStreamIds.join(\",\"))\n\n await BPromise.map(this._streams, (stream) => {\n if (selectedStreamIds.includes(stream.streamId)) {\n const selectedStream = selectedStreams.find((selectedStream => selectedStream.stream === stream.streamId))\n const rootMetadataEntry = selectedStream?.metadata.find(streamMdt => streamMdt.breadcrumb.length === 0);\n if (!rootMetadataEntry) {\n throw new Error(`Can't find a catalog root metadata entry for StreamId=${stream.streamId}`)\n }\n stream.setRootMetadataEntry(rootMetadataEntry.metadata);\n return stream.sync();\n }\n },\n {\n concurrency: this._concurrency\n });\n\n }\n\n // Used to clean up any ressource before exit\n end(): Promise<void> {\n return Promise.resolve()\n }\n}","import * as _ from \"lodash\";\n\n// Truncate potentially large query params for logging efficiency\nconst MAX_QS_KEYS = 10;\nconst MAX_QS_STRING_LENGTH = 200;\nconst MAX_QS_ARRAY_ITEMS = 5;\nconst MAX_QS_DEPTH = 2;\n\nfunction truncateQueryParams(value: any, depth: number = 0): any {\n if (value == null) return value;\n if (depth >= MAX_QS_DEPTH) return \"[…]\";\n\n if (typeof value === \"string\") {\n if (value.length <= MAX_QS_STRING_LENGTH) return value;\n const truncated = value.slice(0, MAX_QS_STRING_LENGTH);\n return `${truncated}…(+${value.length - MAX_QS_STRING_LENGTH} chars)`;\n }\n\n if (Array.isArray(value)) {\n const items = value\n .slice(0, MAX_QS_ARRAY_ITEMS)\n .map((v) => truncateQueryParams(v, depth + 1));\n const omittedCount = Math.max(0, value.length - MAX_QS_ARRAY_ITEMS);\n if (omittedCount > 0) {\n items.push(`[… ${omittedCount} more items]`);\n }\n return items;\n }\n\n if (_.isPlainObject(value)) {\n const keys = Object.keys(value);\n const result: Record<string, any> = {};\n for (const key of keys.slice(0, MAX_QS_KEYS)) {\n result[key] = truncateQueryParams((value as any)[key], depth + 1);\n }\n const omittedCount = Math.max(0, keys.length - MAX_QS_KEYS);\n if (omittedCount > 0) {\n (result as any)[\"__omittedKeys\"] = omittedCount;\n }\n return result;\n }\n\n return value;\n}\n\nexport function getTruncatedParamsForLog(params: any): any {\n try {\n return truncateQueryParams(params);\n } catch {\n return \"[unserializable params]\";\n }\n}","import { logger } from \"../../service/logger\";\nimport { StreamId } from \"../catalog\";\nimport { ReplicationMethod } from \"../models\";\nimport { FlattenedSchema, InternalTableField, JSONSchemaFieldDefinition, WarehouseTableField } from \"./models\";\nimport { RenameColumnStore } from \"./renameColumnStore\";\nimport retry from 'async-retry';\n\n// This class is a Stateless interface with the APIs of a Warehouse when it comes to dealing with\n// loading a stream into a table.\n\n// TODO: Move flattenedSchema + renamedColumnStore into the StreamDbState class.\nexport abstract class StreamWarehouseSyncService {\n\n streamId: StreamId;\n database: string;\n schema: string;\n table: string;\n\n flattenedSchema: FlattenedSchema;\n primaryKeys: string[];\n maxRetryCount = 5;\n\n renamedColumnStore: RenameColumnStore;\n\n constructor(\n streamId: StreamId,\n database: string,\n schema: string,\n table: string,\n renameColumnStore: RenameColumnStore\n ) {\n this.streamId = streamId;\n this.database = database;\n this.schema = schema;\n this.table = table;\n\n this.primaryKeys = [];\n this.flattenedSchema = {};\n this.renamedColumnStore = renameColumnStore;\n }\n\n /////////////////////////////////////////////////////////////////\n ///////// Functions to be implented for each Warehouse //////////\n /////////////////////////////////////////////////////////////////\n\n // Function to adapt to the Warehouse SQL dialect\n abstract safeColumnName: (unsafe: string) => string;\n abstract getWarehouseTypeFromJSONSchema: (definition: JSONSchemaFieldDefinition) => string | undefined;\n getcolumnNameWithTypeSuffix(colName: string, warehouseType: string | undefined): string {\n return `${colName}__${warehouseType}`\n }\n // In order to not overload Warehouse, we update the destination table by chunks of columns as updating all the columns at once is generating a too complex query\n abstract getMergeQueries: () => string[]\n abstract getReplaceQueries: () => string[]\n\n // Functions to provision the tables, columns, etc.\n abstract createDatabaseAndSchemaIfNotExists: (retryCount: number) => Promise<void>;\n abstract createTable: () => Promise<void>;\n abstract addColumns: (fields: InternalTableField[]) => Promise<void>;\n\n // Functions to deal with the staging area that will be used to load data in the Warehouse\n abstract createStagingArea: () => Promise<void>;\n abstract loadStreamInStagingArea: (localFilePath: string) => Promise<void>;\n abstract deleteStagingArea: () => Promise<void>;\n\n // Function to read from the Warehouse\n abstract getTablesInSchema: () => Promise<{ tableName: string }[]>;\n abstract getTableColumnsFromWarehouse: () => Promise<WarehouseTableField[]>;\n\n // Function to execute queries on the warehouse\n abstract runQueries: (queries: string[]) => Promise<void>;\n\n // Function to serialize the record\n abstract getSerializedRecord: (record: any) => string;\n\n // Orchestration functions\n updateSchemaInWarehouse = async (\n flattenedSchema: FlattenedSchema,\n primaryKeys: string[]\n ) => {\n await this.createDatabaseAndSchemaIfNotExists(0);\n\n this.flattenedSchema = flattenedSchema;\n\n this.renamedColumnStore.computeColumnNameForStream(\n this.streamId,\n flattenedSchema\n )\n\n this.primaryKeys = primaryKeys.map(pk => {\n return this.renamedColumnStore.getColumnTranslation(this.streamId, pk)!;\n });\n\n await this.syncTableSchemaWithWarehouse();\n }\n\n renameColumns(record: any): any {\n const renamedColsRecord: any = {}\n\n Object.keys(record).forEach(originalColName => {\n renamedColsRecord[this.renamedColumnStore.getColumnTranslation(this.streamId, originalColName)!] = record[originalColName]\n })\n return renamedColsRecord;\n }\n\n // Function to execute queries on the warehouse\n protected runQueriesWithRetry = async (queries: string[]): Promise<void> => {\n await retry(\n async () => {\n await this.runQueries(queries);\n },\n {\n retries: 5,\n }\n );\n };\n\n private syncTableSchemaWithWarehouse = async () => {\n\n const tables = await this.getTablesInSchema();\n const foundTables = tables.filter(table => this.table === table.tableName);\n\n if (foundTables.length === 0) {\n logger.info(`🐣 Database: \\`${this.database}\\`, Schema: \\`${this.schema}\\`, Table: \\`${this.table}\\` does not exist in Warehouse. Creating it...`)\n await this.createTable();\n } else if (foundTables.length === 1) {\n logger.info(`👋 Database: \\`${this.database}\\`, Schema: \\`${this.schema}\\`, Table: \\`${this.table}\\` already exists. Updating the columns if needed.`);\n await this.updateTableColumns();\n }\n }\n\n /**\n * When there is a conflict between the synced data type and the data type of an\n * already existing column in the Warehouse, this create a new column in Warehouse with the new\n * datatype as suffix.\n * \n * This refer the fact that data should now be synced with the new column.\n * \n * @param tableFields \n */\n private addVersionedColumns = async (tableFields: InternalTableField[]) => {\n\n if (tableFields.length > 0) {\n logger.info(`🛂 Stream: ${this.streamId} - Versionning following columns in Warehouse schema: ${JSON.stringify(tableFields)}`)\n\n const columnsFromWarehouse = await this.getTableColumnsFromWarehouse();\n const columnNamesFromWarehouse = columnsFromWarehouse.map(col => col.name);\n\n let columnsToBeAddedInWarehouse: InternalTableField[] = [];\n tableFields.forEach(tblField => {\n const safeName = tblField.name as string;\n const warehouseTypeToBeUsed = this.getWarehouseTypeFromJSONSchema(tblField.definition)\n const columnNameWithTypeSuffix = this.getcolumnNameWithTypeSuffix(safeName, warehouseTypeToBeUsed)\n\n // Rewrite the safe mapping of the column to the versionned column\n this.renamedColumnStore.getUnsafeToSafeColumnMapping(this.streamId)[tblField.unsafeName] = columnNameWithTypeSuffix;\n\n if (!columnNamesFromWarehouse.includes(columnNameWithTypeSuffix)) {\n columnsToBeAddedInWarehouse.push({\n unsafeName: columnNameWithTypeSuffix,\n name: columnNameWithTypeSuffix,\n definition: tblField.definition\n })\n }\n })\n\n if (columnsToBeAddedInWarehouse.length > 0) {\n await this.addColumns(columnsToBeAddedInWarehouse);\n }\n }\n }\n\n private updateTableColumns = async () => {\n\n const columnsFromWarehouse = await this.getTableColumnsFromWarehouse();\n const columnNamesFromWarehouse = columnsFromWarehouse.map(col => col.name);\n\n const columnsMappingStore = this.renamedColumnStore.getUnsafeToSafeColumnMapping(this.streamId);\n const columnsToAdd: InternalTableField[] = Object.keys(columnsMappingStore)\n .filter(unsafeColumnKey => {\n const safeColumnName = columnsMappingStore[unsafeColumnKey];\n if (!safeColumnName) {\n return false;\n }\n return !columnNamesFromWarehouse.includes(safeColumnName);\n })\n .map(unsafeColumnKey => {\n const safeColumnName = columnsMappingStore[unsafeColumnKey];\n const definition = this.flattenedSchema[unsafeColumnKey];\n if (!safeColumnName || !definition) {\n return undefined as unknown as InternalTableField;\n }\n return {\n unsafeName: unsafeColumnKey,\n name: safeColumnName,\n definition\n }\n })\n .filter((item): item is InternalTableField => !!item)\n\n await this.addColumns(columnsToAdd);\n\n const columnsToVersion: InternalTableField[] = Object.keys(this.flattenedSchema)\n // We keep only the columns already declared in Warehouse but with a different type\n .filter(unsafeColumnKey => {\n const definition = this.flattenedSchema[unsafeColumnKey];\n if (!definition) {\n return false;\n }\n const warehouseTypeToBeUsed = this.getWarehouseTypeFromJSONSchema(definition)\n if (warehouseTypeToBeUsed) {\n const safeName = this.safeColumnName(unsafeColumnKey);\n if (columnNamesFromWarehouse.includes(safeName)) {\n const columnFromWarehouse = columnsFromWarehouse.find(col => col.name === safeName);\n\n if (!columnFromWarehouse) {\n throw new Error(`We can't find in Warehouse schema any column definition for colName: ${safeName}`);\n }\n\n const { type } = columnFromWarehouse;\n\n if (warehouseTypeToBeUsed !== type) {\n return true;\n }\n }\n }\n return false;\n })\n .map(unsafeColumnKey => {\n const definition = this.flattenedSchema[unsafeColumnKey];\n if (!definition) {\n return undefined as unknown as InternalTableField;\n }\n return {\n unsafeName: unsafeColumnKey,\n name: this.safeColumnName(unsafeColumnKey),\n definition\n }\n })\n .filter((tableField): tableField is InternalTableField => !!tableField);\n\n await this.addVersionedColumns(columnsToVersion);\n\n }\n\n mergeTempTableWithDestination = async (\n replicationMethod: ReplicationMethod\n ) => {\n\n let mergeQueries: string[] = [];\n if (replicationMethod === \"FULL_TABLE\") {\n mergeQueries = this.getReplaceQueries();\n } else if (replicationMethod === \"INCREMENTAL\") {\n mergeQueries = this.getMergeQueries();\n } else if (replicationMethod === \"LOG_BASED\") {\n mergeQueries = this.getMergeQueries();\n }\n\n logger.info(`🍆 Table=${this.table} - Merging staging data with method ${replicationMethod}`);\n logger.debug(`Table=${this.table} - Merge queries: %j`, mergeQueries);\n\n await this.runQueriesWithRetry(mergeQueries);\n\n }\n\n}","import { ValidationError } from \"jsonschema\";\nimport { StreamId } from \"../catalog\";\n\nexport class SchemaValidationError extends Error {\n\n streamId: StreamId;\n validationErrors: ValidationError[];\n\n constructor(message: string, streamId: StreamId, errors: ValidationError[]) {\n super(message); // (1)\n this.name = \"SchemaValidationError\"; // (2)\n this.streamId = streamId;\n this.validationErrors = errors;\n }\n\n}\n\nexport class MissingFieldInSchemaError extends Error {\n\n streamId: StreamId;\n\n constructor(message: string, streamId: StreamId) {\n super(message); // (1)\n this.name = \"MissingFieldInSchemaError\"; // (2)\n this.streamId = streamId;\n }\n\n}\n\nexport class MissingSchemaError extends Error {\n\n streamId: StreamId;\n\n constructor(message: string, streamId: StreamId) {\n super(message); // (1)\n this.name = \"MissingSchemaError\"; // (2)\n this.streamId = streamId;\n }\n\n}","import { FlattenedSchema } from \"./models\";\n\nexport const removeParasiteProperties = (record: any, schema: FlattenedSchema) => {\n const schemaKeys = Object.keys(schema);\n Object.keys(record).forEach(key => {\n if (!schemaKeys.includes(key)) {\n delete record[key]\n }\n })\n\n return record;\n}\n\nexport const addWhalyFields = (record: any, batchDate: string) => {\n return {\n ...record,\n _whaly_synced: batchDate\n }\n}","import { logger } from \"../../service/logger\";\nimport { FlattenedSchema } from \"./models\";\n\n// { \"streamId\": { \"originalColumnName\": \"renamedColumnName\" } }\nexport interface ColumnMappingStoreUnsafeToSafe {\n [originalColumnName: string]: string\n}\n\nexport type SafeColumnNameConverterFn = (unsafe: string) => string\n\n/**\n * This stateful class is to be used to store all the columns names mapping between the \"raw\" column name\n * found in the records and the destination column in the data warehouse\n * \n * A mapping exists between the fields declared by the Tap and the reality in the Warehouse for those reasons:\n * - Columns that are versionned due to type changes since the last load\n * - Columns that have a name conflict after \"Warehouse\" sanitization\n */\nexport class RenameColumnStore {\n\n // Store all the mappings store for all streamId\n private renamedColumns: { [streamId: string]: ColumnMappingStoreUnsafeToSafe };\n\n private safeColumnNameConverter?: SafeColumnNameConverterFn;\n\n constructor() {\n this.renamedColumns = {};\n }\n\n setSafeColumnNameConverter = (fn: SafeColumnNameConverterFn): void => {\n this.safeColumnNameConverter = fn;\n }\n\n // This function has a side effect on:\n // - `this.renamedColumns`\n // This isn't very clean and should be updated to write a pure version of this function\n computeColumnNameForStream = (\n streamId: string,\n flattenedSchema: FlattenedSchema,\n ) => {\n const safeColNameConv = this.safeColumnNameConverter;\n if (!safeColNameConv) {\n throw new Error(`safeColumnNameConverter is not defined!`)\n }\n const colSafeToUnsafeMapping = Object.keys(flattenedSchema)\n .sort()\n .reduce<{ [safeColName: string]: string }>((acc, unsafeColName) => {\n const safeColName = safeColNameConv(unsafeColName);\n if (!acc[safeColName]) {\n acc[safeColName] = unsafeColName;\n } else {\n logger.info(`🚨 Stream: ${streamId} - We have a column name conflict after sanitization for column unsafe=${unsafeColName}. We'll rename the sanitized name to a non taken name.\n Details: unsafeColName=${unsafeColName} is colliding with: ${acc[safeColName]}`)\n for (let i = 1; ; i++) {\n if (!acc[`${safeColName}_${i}`]) {\n acc[`${safeColName}_${i}`] = unsafeColName;\n break;\n }\n }\n }\n return acc;\n }, {});\n\n const colUnsafeToSafeMapping = Object.keys(colSafeToUnsafeMapping)\n .reduce<{ [unssafeColName: string]: string }>((acc, safeColName) => {\n const unsafeColname = colSafeToUnsafeMapping[safeColName];\n if (unsafeColname) {\n acc[unsafeColname] = safeColName;\n }\n return acc;\n }, {})\n\n // Init the renamedColumns dict\n const mapping = this.renamedColumns[streamId] || {};\n this.renamedColumns[streamId] = mapping;\n Object.keys(colUnsafeToSafeMapping).forEach(unsafeColName => {\n const safeName = colUnsafeToSafeMapping[unsafeColName];\n if (safeName) {\n mapping[unsafeColName] = safeName;\n }\n });\n }\n\n getColumnTranslation = (\n streamId: string,\n originalColumnName: string\n ): string => {\n if (!this.renamedColumns[streamId]) {\n throw new Error(\n `StreamId=${streamId} - Columns Mapping Store is not initialized! \n Trying to get renamed value for column '${originalColumnName}'`\n )\n }\n const value = this.renamedColumns[streamId][originalColumnName];\n if (!value) {\n throw new Error(`StreamId=${streamId} - No renamed value found for column '${originalColumnName}'`)\n }\n return value;\n }\n\n getUnsafeToSafeColumnMapping = (streamId: string): ColumnMappingStoreUnsafeToSafe => {\n const mapping = this.renamedColumns[streamId];\n if (!mapping) {\n throw new Error(`StreamId=${streamId} - Columns Mapping Store is not initialized!`)\n }\n return mapping;\n }\n\n isReady = (streamId: string): boolean => {\n if (!this.renamedColumns[streamId]) {\n return false;\n } else {\n return true;\n }\n }\n}","import { StreamId } from \"../catalog\";\nimport { FlattenedSchema } from \"./models\";\nimport { logger } from \"../../service/logger\";\nimport { gracefulExit } from \"../../service/exit\";\n\nexport const flattenSchema = <T>(streamId: StreamId, schema: T): FlattenedSchema => {\n\n logger.debug(`Flattening schema for stream: ${streamId}`)\n\n try {\n const mSchema = schema as any;\n\n if (!mSchema[\"properties\"]) {\n return {};\n }\n\n const properties = mSchema[\"properties\"];\n\n const flattenedSchema = Object.keys(properties).reduce<FlattenedSchema>((acc, propertyName) => {\n const propertySchema = properties[propertyName];\n const columnName = propertyName;\n\n if (!propertySchema) {\n return acc;\n }\n\n if (!propertySchema[\"type\"]) {\n throw new Error(`We don't have any \\`type\\` for the property: \\`${propertyName}\\`.\n Schema of the property is: ${JSON.stringify(propertySchema)}`)\n }\n\n acc[columnName] = {\n type: propertySchema[\"type\"],\n format: propertySchema[\"format\"],\n items: propertySchema[\"items\"]\n };\n\n return acc;\n }, {});\n\n return flattenedSchema;\n } catch (err: any) {\n logger.error(`There was an error when processing the schema of stream:\\`${streamId}\\`: err: ${err.message} - ${err.stack}.\n Processed schema: ${JSON.stringify(schema)}`);\n gracefulExit(1);\n return {};\n }\n\n}","import { ReplicationMethodMessage, RecordMessage, SchemaMessage, StateMessage } from \"../messages\";\nimport { Resolver } from \"../resolver\";\nimport { TargetSchemaHook, TargetSchemaHookInput } from \"./targetHook\";\nimport { Validator } from \"jsonschema\";\nimport moment from \"moment\";\nimport { RenameColumnStore, SafeColumnNameConverterFn } from \"./renameColumnStore\";\nimport { StreamState } from \"./streamDbState\";\nimport { logger } from \"../../service/logger\";\nimport { MissingSchemaError, SchemaValidationError } from \"./error\";\nimport { addWhalyFields, removeParasiteProperties } from \"./record\";\nimport { BaseConfig, FlattenedSchema } from \"./models\";\nimport { flattenSchema } from \"./schema\";\nimport { writeStateFile } from \"../../utils\";\nimport { loadResolver } from \"../../service/resolver\";\nimport { StreamId } from \"../catalog\";\nimport { StreamWarehouseSyncService } from \"./dbSync\";\nimport { Semaphore } from \"async-mutex\";\nimport { ReplicationMethod } from \"../models\";\nimport { Promise as BPromise } from \"bluebird\";\n\nconst semaphore = new Semaphore(1);\n\nexport abstract class ITarget<C extends BaseConfig = BaseConfig> {\n config: C;\n schemaHooks: TargetSchemaHook[]\n resolver: Resolver;\n syncTime: moment.Moment;\n\n // Latest state message received from the Tap\n // Not yet flushed as we didn't upload the stream data since receiving it \n batchedState: any;\n\n // Latest \"flushed\" state message\n // A state message is flushed when we do a stream upload.\n flushedState: any;\n\n renameColumnStore: RenameColumnStore;\n\n streams: {\n [streamName: string]: StreamState\n }\n\n // JSON Schema validator\n validator: Validator\n\n constructor(config: C, resolver: Resolver) {\n this.config = config;\n this.resolver = resolver;\n this.schemaHooks = resolver.getSchemaHooks();\n\n this.streams = {}\n\n this.batchedState = {}\n this.flushedState = {}\n\n this.validator = new Validator();\n this.syncTime = moment();\n\n this.renameColumnStore = new RenameColumnStore()\n }\n\n ///////////////////////////////////////////\n //// To be overriden by child classes /////\n ///////////////////////////////////////////\n static requiredConfigKeys: string[] = [];\n // Generate instance of DBSync\n abstract newDBSyncInstance: (\n streamId: StreamId,\n database: string,\n schema: string,\n table: string\n ) => StreamWarehouseSyncService;\n // Function to render safe table names\n abstract genTableName: (streamId: string) => string;\n // Function to render safe column names\n abstract safeColumnNameConverter: SafeColumnNameConverterFn;\n // Convert the date values of a record into valid ones for the Warehouse\n abstract validateDateRange: (reacord: any, schema: FlattenedSchema) => any;\n // Convert the number values of a record into valid ones for the Warehouse\n abstract convertNumberIntoDecimal: (record: any, schema: FlattenedSchema) => any;\n\n ////////////////////////////////////////////\n /////////// Implementation /////////////////\n ////////////////////////////////////////////\n\n // Analyze schema changes to determine if they are breaking or non-breaking\n private analyzeSchemaChanges = (\n previousSchema: FlattenedSchema,\n newSchema: FlattenedSchema,\n streamId: string\n ): { hasBreakingChanges: boolean; changes: string[] } => {\n const changes: string[] = [];\n let hasBreakingChanges = false;\n\n // Get all column names from both schemas\n const prevColumns = new Set(Object.keys(previousSchema).filter(col => !col.startsWith(\"_whaly\")));\n const newColumns = new Set(Object.keys(newSchema).filter(col => !col.startsWith(\"_whaly\")));\n\n // Check for new columns (non-breaking)\n for (const columnName of newColumns) {\n if (!prevColumns.has(columnName)) {\n changes.push(`Added column '${columnName}'`);\n }\n }\n\n // Check for removed columns (breaking)\n for (const columnName of prevColumns) {\n if (!newColumns.has(columnName)) {\n changes.push(`Removed column '${columnName}'`);\n hasBreakingChanges = true;\n }\n }\n\n // Check for type changes in existing columns (breaking)\n for (const columnName of prevColumns) {\n if (newColumns.has(columnName)) {\n const prevType = previousSchema[columnName];\n const newType = newSchema[columnName];\n\n // Compare the type definitions\n if (JSON.stringify(prevType) !== JSON.stringify(newType)) {\n changes.push(`Changed type of column '${columnName}'`);\n hasBreakingChanges = true;\n }\n }\n }\n\n if (changes.length === 0) {\n changes.push('No schema changes detected');\n }\n\n logger.debug(`StreamId=${streamId} - Schema analysis: ${hasBreakingChanges ? 'BREAKING' : 'NON-BREAKING'} changes found: ${changes.join(', ')}`);\n\n return { hasBreakingChanges, changes };\n }\n\n // Serialize a RECORD message into a line that will be uploaded in the staging area\n getSerializedRecord = (streamId: string, record: any): string => {\n const stream = this.streams[streamId];\n if (!stream) {\n throw new MissingSchemaError(`A record for stream:\\`${streamId}\\` was encountered before a corresponding schema.`, streamId)\n }\n return stream.getDbSync().getSerializedRecord(record)\n }\n\n record = async (message: RecordMessage): Promise<void> => {\n try {\n\n const streamId = message.stream;\n const stream = this.streams[streamId];\n\n if (!stream) {\n throw new MissingSchemaError(`A record for stream:\\`${streamId}\\` was encountered before a corresponding schema.`, streamId)\n }\n\n // To avoid getting any conflicts when loading data in the warehouse, we run a semaphore to have a concurrency of 1\n await semaphore.runExclusive(async () => {\n const shouldUploadIntermediateBatch = this.shouldUploadIntermediateBatch(streamId)\n if (shouldUploadIntermediateBatch) {\n await this.loadAllStreamsInWarehouse({ isFinalLoad: false })\n }\n })\n\n const record = message.record;\n const schema = stream.getSchema();\n\n if (!schema) {\n logger.warn(`Stream: ${streamId} - Received a RECORD message while schema is undefined. Dropping message.`)\n return;\n }\n\n const recordWithoutParasiteProperties = removeParasiteProperties(record, schema);\n\n const recordWithWhalyFields = addWhalyFields(recordWithoutParasiteProperties, stream.getBatchDate());\n\n // Checking that the RECORD is valid compared to the previously received SCHEMA\n const validationResult = this.validator.validate(recordWithWhalyFields, schema);\n if (!validationResult.valid) {\n throw new SchemaValidationError(`Stream: ${streamId} - Record is not valid according to schema.\n Validation errors: ${JSON.stringify(validationResult.errors)}\n\n Record: ${JSON.stringify(recordWithoutParasiteProperties)}\n Schema: ${JSON.stringify(stream.getSchema())}`, streamId, validationResult.errors)\n }\n\n // Making sure that the date are in valid range supported by Warehouse\n const recordWithValidDate = this.validateDateRange(recordWithWhalyFields, schema);\n // Working with Decimal.js is better as the JS `number` type is quite imprecise\n const recordWithDecimal = this.convertNumberIntoDecimal(recordWithValidDate, schema)\n\n // Columns should be renamed to:\n // - Be \"safe\" for Warehouse\n // - Handle the case where there are conflicts in column names after sanitization\n // - There is a column versionning due to a column type change since the last sync\n const dbSyncInstance = stream.getDbSync();\n const recordWithrenamedColumns = dbSyncInstance.renameColumns(recordWithDecimal);\n\n const serializedRecord = this.getSerializedRecord(streamId, recordWithrenamedColumns);\n\n return new Promise((resolve, reject) => {\n stream.getFileToLoad().stream.write(serializedRecord, (error) => {\n if (error) {\n reject(error);\n }\n\n stream.incrementBatchedRowCount();\n resolve();\n });\n })\n\n } catch (err) {\n logger.error(`Error when handling \"record\" message`);\n throw err;\n }\n }\n\n private initStreamStateAndSyncService(\n streamId: string,\n replicationMethod?: ReplicationMethod\n ): void {\n const dbSyncInstance = this.newDBSyncInstance(\n streamId,\n this.config.database,\n this.config.schema,\n this.genTableName(streamId)\n )\n this.streams[streamId] = new StreamState(\n streamId,\n dbSyncInstance,\n replicationMethod || \"FULL_TABLE\"\n );\n }\n\n replicationMethod = (message: ReplicationMethodMessage): void => {\n\n try {\n logger.info(`👈 Received replicationMethod message: %j`, message)\n const streamId = message.stream;\n if (!this.streams[streamId]) {\n this.initStreamStateAndSyncService(streamId, message.replication)\n } else {\n this.streams[streamId].setReplicationMethod(message.replication);\n }\n } catch (err) {\n logger.error(`Error when handling \"replicationMethod\" event`)\n throw err;\n }\n }\n\n schema = async (message: SchemaMessage): Promise<void> => {\n\n try {\n const streamId = message.stream;\n\n logger.info(`Stream: ${streamId} - Got a SCHEMA message from the tap`);\n logger.debug(`Stream: ${streamId} - Got a SCHEMA message from the tap: %j`, message);\n\n if (!this.streams[streamId]) {\n this.initStreamStateAndSyncService(streamId)\n } else {\n // Load the previous batched data as there can be schema changes\n const prevStreamState = this.streams[streamId];\n if (prevStreamState.batchedRowCount > 0) {\n const prevSchema = prevStreamState.getSchema();\n if(prevSchema) {\n // Flatten the new schema to compare with the previous one\n const newFlattenedSchema = flattenSchema(streamId, message.schema);\n // Check if schema changes are breaking or non-breaking\n const { hasBreakingChanges, changes } = this.analyzeSchemaChanges(prevSchema, newFlattenedSchema, streamId);\n if (hasBreakingChanges) {\n logger.info(`🔥 StreamId=${streamId} - Detected BREAKING schema changes: ${changes.join(', ')}. Loading batched records before applying new schema.`);\n await ITarget.uploadSingleStreamToWarehouse(prevStreamState);\n } else {\n logger.info(`✅ StreamId=${streamId} - Detected NON-BREAKING schema changes: ${changes.join(', ')}. Continuing without uploading batched records.`);\n }\n }\n }\n }\n\n const streamState = this.streams[streamId];\n if (!streamState) {\n throw new MissingSchemaError(`Stream: ${streamId} - Received SCHEMA message before stream state was initialized.`, streamId)\n }\n const schema = flattenSchema(streamId, message.schema);\n\n // Add Whaly specific columns\n schema[\"_whaly_synced\"] = {\n format: \"date-time\",\n type: [\"null\", \"string\"]\n }\n\n const dbSync = streamState.getDbSync();\n Object.keys(schema).forEach(fieldUnsafeKey => {\n // Remove the key associated to no warehouse type\n const fieldDef = schema[fieldUnsafeKey];\n const targetWarehouseType = fieldDef ? dbSync.getWarehouseTypeFromJSONSchema(fieldDef) : undefined;\n\n if (!targetWarehouseType) {\n delete schema[fieldUnsafeKey]\n }\n })\n\n streamState.setSchema(schema);\n\n if (message.keyProperties.length === 0) {\n throw new Error(`StreamId: ${message.stream} - \\`key_properties\\` field is required and can't be empty in SCHEMA message.\n Received SCHEMA message: ${JSON.stringify(message)}`)\n }\n\n streamState.setKeyProperties(message.keyProperties);\n\n await dbSync.updateSchemaInWarehouse(schema, message.keyProperties);\n\n const {\n database: databaseName,\n schema: schemaName\n } = this.config;\n\n const tableName = this.genTableName(streamId);\n\n const formattedRelationshipMessage: SchemaMessage = {\n ...message,\n keyProperties: message.keyProperties.map(k => {\n const translation = streamState.getDbSync().renamedColumnStore.getColumnTranslation(message.stream, k);\n if (translation) {\n return translation;\n }\n return k\n }),\n relationships: {\n left: message.relationships.left.flatMap(l => {\n // If the other stream in the relationship have not been processed, they are not ready and we can't declare the relationship.\n // It'll be declared when those other streams are processed\n if (\n this.renameColumnStore.isReady(l.streamId)\n && this.renameColumnStore.isReady(message.stream)\n ) {\n const from = this.renameColumnStore.getColumnTranslation(l.streamId, l.from);\n const to = this.renameColumnStore.getColumnTranslation(message.stream, l.to);\n if (from && to) {\n return [{\n type: l.type,\n streamId: l.streamId,\n from: from,\n to: to\n }]\n }\n }\n // Default case\n return []\n }),\n right: message.relationships.right.flatMap(r => {\n // If the other stream in the relationship have not been processed, they are not ready and we can't declare the relationship.\n // It'll be declared when those other streams are processed\n if (\n this.renameColumnStore.isReady(message.stream)\n && this.renameColumnStore.isReady(r.streamId)\n ) {\n const from = this.renameColumnStore.getColumnTranslation(message.stream, r.from);\n const to = this.renameColumnStore.getColumnTranslation(r.streamId, r.to);\n if (from && to) {\n return [{\n type: r.type,\n streamId: r.streamId,\n from: from,\n to: to\n }]\n }\n }\n // Default case\n return []\n }),\n }\n }\n\n await BPromise.map(this.schemaHooks, async (hook) => {\n const input: TargetSchemaHookInput = {\n databaseName,\n schemaName,\n tableName,\n message: formattedRelationshipMessage,\n }\n await hook.writeSchema(input);\n }, { concurrency: 3 })\n\n return Promise.resolve();\n } catch (err) {\n logger.error(`Error when handling schema event.`, err)\n throw err;\n }\n }\n\n state = (message: StateMessage): Promise<void> => {\n\n try {\n this.batchedState = message.value;\n\n if (!this.flushedState) {\n this.flushedState = Object.assign({}, this.state);\n }\n return Promise.resolve()\n } catch (err) {\n logger.error(`Error while handling state event.`)\n throw err;\n }\n }\n\n complete = async (): Promise<void> => {\n\n try {\n logger.info(`👍 Data Extraction is complete. Will load remaining batched stream records.`)\n\n await this.loadAllStreamsInWarehouse({ isFinalLoad: true });\n const configResolver = loadResolver();\n await configResolver.markSyncComplete();\n await configResolver.flushMetrics();\n return Promise.resolve();\n } catch (err) {\n logger.error(`Error while handling complete event.`)\n throw err;\n }\n }\n\n private shouldUploadIntermediateBatch = (streamId: string): boolean => {\n const stream = this.streams[streamId];\n if (!stream) {\n return false;\n }\n const batchedRecords = stream.getBatchedRowCount()\n if (stream.getReplicationMethod() === \"INCREMENTAL\" && batchedRecords > 1_000_000) {\n logger.info(`🧊 Stream=${streamId} has reached the maximum amount of batched records. We'll trigger a flush of ALL streams in the Warehouse.`)\n return true;\n } else {\n return false;\n }\n }\n\n private loadAllStreamsInWarehouse = async (opts: { isFinalLoad: boolean }): Promise<void> => {\n logger.info(`🚛🚛🚛 Loading ALL Streams in Warehouse.`)\n const { isFinalLoad } = opts;\n const streamsWithRemainingRecords = Object\n .keys(this.streams)\n .filter(streamId => {\n // FULL TABLE streams are removed from the load if it's not the final load\n const s = this.streams[streamId];\n if (!s) {\n return false;\n }\n if (!isFinalLoad && s.getReplicationMethod() === \"FULL_TABLE\") {\n return false;\n }\n return s.getBatchedRowCount() > 0\n });\n\n if (streamsWithRemainingRecords.length > 0) {\n this.flushedState = await this.uploadStreamsToWarehouse(streamsWithRemainingRecords)\n }\n\n if (Object.keys(this.flushedState).length > 0) {\n await this.emitState(Object.assign({}, this.flushedState))\n // Special case where nothing was written in the warehouse (nothing to sync then)\n // We keep the previous state\n } else {\n await this.emitState(Object.assign({}, this.state))\n }\n }\n\n private emitState = (state: any): Promise<void> => {\n const configResolver = loadResolver();\n return writeStateFile(configResolver, JSON.stringify(state));\n }\n\n private uploadStreamsToWarehouse = async (\n streamsToUpload: string[]\n ) => {\n\n try {\n await BPromise.map(streamsToUpload, async (streamId) => {\n logger.info(`📤 Upload stream: ${streamId} to Warehouse`)\n const streamState = this.streams[streamId];\n if (streamState) {\n await ITarget.uploadSingleStreamToWarehouse(streamState)\n }\n }, { concurrency: 3 });\n\n return this.batchedState;\n } catch (err) {\n logger.error(`Error while uploading all streams + merging them.`)\n throw err;\n }\n }\n\n static uploadSingleStreamToWarehouse = async (\n streamState: StreamState\n ) => {\n\n const dbSync = streamState.getDbSync();\n\n try {\n const replicationMethod = streamState.getReplicationMethod();\n const fileToLoad = streamState.getFileToLoad();\n\n await dbSync.createStagingArea();\n await dbSync.loadStreamInStagingArea(fileToLoad.path);\n await dbSync.mergeTempTableWithDestination(replicationMethod);\n await dbSync.deleteStagingArea();\n streamState.setHasBeenLoadedYet();\n streamState.resetFileToLoad();\n } catch (err) {\n if (err instanceof Error) {\n logger.error(`StreamId=${dbSync.streamId} - Couldn't upload stream due to an error: %s`, err.message);\n throw err;\n } else {\n throw new Error('Unknown error')\n }\n }\n }\n}","import moment from \"moment\";\nimport { defaultDateTimeFormat } from \"../../constants/date\";\nimport { StreamId } from \"../catalog\";\nimport { ReplicationMethod } from \"../models\";\nimport { StreamWarehouseSyncService } from \"./dbSync\";\nimport { FlattenedSchema, TempFile } from \"./models\";\nimport { createTemporaryFileStream } from \"./temporaryFile\";\nimport * as fs from \"fs\";\n\n// This class is here to manage the State of a stream being loaded into a Warehouse\nexport class StreamState {\n streamId: StreamId;\n schema?: FlattenedSchema;\n dbSync: StreamWarehouseSyncService;\n\n batchDate: moment.Moment;\n\n // Count rows batched in the local file, waiting for Warehouse upload\n batchedRowCount: number;\n // Local CSV files written to be sent to Warehouse\n fileToLoad: TempFile;\n // Count rows sent to Warehouse\n syncedRowCount: number;\n keyProperties: string[];\n\n // When a FULL_TABLE stream is loaded multiple times, the query used for the 2nd+ loads\n // needs to be different than the 1st merge query -> 1st load is dropping the existing table, 2nd+ loads are merging with the existing table (otherwise the previous load data are dropped)\n // So we need to keep track of whether we are at the first load or not\n _hasBeenLoadedYetDuringThisSync: boolean\n\n replicationMethod: ReplicationMethod\n\n constructor(\n streamId: StreamId, \n dbSync: StreamWarehouseSyncService, \n replicationMethod: ReplicationMethod, \n ) {\n this.streamId = streamId;\n this.dbSync = dbSync;\n\n this.batchedRowCount = 0;\n this.fileToLoad = createTemporaryFileStream(streamId);\n this.syncedRowCount = 0;\n this.keyProperties = [];\n this.batchDate = moment();\n this.replicationMethod = replicationMethod;\n this._hasBeenLoadedYetDuringThisSync = false;\n }\n\n setSchema(schema: FlattenedSchema) {\n this.schema = schema;\n }\n\n getSchema(): FlattenedSchema | undefined {\n return this.schema;\n }\n\n getBatchDate(): string {\n return this.batchDate.format(defaultDateTimeFormat);\n }\n\n getBatchedRowCount(): number {\n return this.batchedRowCount;\n }\n\n incrementBatchedRowCount() {\n this.batchedRowCount += 1;\n }\n\n getFileToLoad(): TempFile {\n return this.fileToLoad;\n }\n\n resetFileToLoad() {\n this.fileToLoad.stream.close();\n const oldPath = this.fileToLoad.path;\n // Delete the old file to make some space\n fs.unlinkSync(oldPath);\n this.fileToLoad = createTemporaryFileStream(this.streamId);\n this.batchedRowCount = 0;\n }\n\n getKeyProperties(): string[] {\n return this.keyProperties;\n }\n\n setKeyProperties(keyProperties: string[]) {\n this.keyProperties = keyProperties\n }\n\n getDbSync(): StreamWarehouseSyncService {\n return this.dbSync\n }\n\n getReplicationMethod(): ReplicationMethod {\n return this.replicationMethod\n }\n\n setReplicationMethod(r: ReplicationMethod) {\n this.replicationMethod = r;\n }\n\n setHasBeenLoadedYet() {\n this._hasBeenLoadedYetDuringThisSync = true;\n }\n}","import fs from 'fs-extra';\nimport { uniqueId } from 'lodash';\nimport { StreamId } from '../catalog';\nimport { TempFile } from './models';\n\nexport const createTemporaryFileStream = (streamId: StreamId): TempFile => {\n fs.ensureDirSync(\"./tmp\")\n const path = `./tmp/${safePath(streamId)}-${uniqueId()}.tmp`;\n const writeStream = fs.createWriteStream(path, {flags: \"w\"});\n\n return {\n stream: writeStream,\n path\n };\n}\n\nexport function safePath(path: string): string {\n let formattedPath = path;\n formattedPath = formattedPath.replace(/^The\\s+/gi, '');\n formattedPath = formattedPath.replace(/\\s+(?:\\(|\\[)?Dis(?:c|k) (?:One|Two|Three|Four|Five|Six|Seven|Eight|Nine|Ten|\\d)+(?:\\)|\\])?/gi, '');\n formattedPath = formattedPath.replace(/\\s+/gi, '_');\n formattedPath = formattedPath.replace(/(?:\\'|`)/gi, '');\n formattedPath = replaceAccented(formattedPath);\n formattedPath = replaceSymbols(formattedPath);\n formattedPath = formattedPath.replace(/(?:[^a-z0-9])+/gi, '_');\n\n return formattedPath;\n};\n\nfunction replaceAccented(str: string) {\n str = str.replace(/(?:\\xC0|\\xC1|\\xC2|\\xC3|\\xC4|\\xC5)/g, 'A');\n str = str.replace(/(?:\\xC7)/g, 'C');\n str = str.replace(/(?:\\xC8|\\xC9|\\xCA|\\xCB)/g, 'E');\n str = str.replace(/(?:\\xCC|\\xCD|\\xCE|\\xCF)/g, 'I');\n str = str.replace(/(?:\\xD2|\\xD3|\\xD4|\\xD6|\\xD5)/g, 'O');\n str = str.replace(/(?:\\xD9|\\xDA|\\xDB|\\xDC)/g, 'U');\n str = str.replace(/(?:\\xDD|\\x9F)/g, 'Y');\n str = str.replace(/(?:\\xD1)/g, 'N');\n str = str.replace(/(?:\\xC6)/g, 'Ae');\n str = str.replace(/(?:\\xDF)/g, 'ss');\n str = str.replace(/(?:\\xE0|\\xE1|\\xE2|\\xE4|\\xE5|\\xE3)/g, 'a');\n str = str.replace(/(?:\\xE7)/g, 'c');\n str = str.replace(/(?:\\xE8|\\xE9|\\xEA|\\xEB)/g, 'e');\n str = str.replace(/(?:\\xEC|\\xED|\\xEE|\\xEF)/g, 'i');\n str = str.replace(/(?:\\xF2|\\xF3|\\xF4|\\xF6|\\xF5)/g, 'o');\n str = str.replace(/(?:\\xF9|\\xFA|\\xFB|\\xFC)/g, 'u');\n str = str.replace(/(?:\\xFD|\\xFF)/g, 'y');\n str = str.replace(/(?:\\xF1)/g, 'n');\n str = str.replace(/(?:\\xE6)/g, 'ae');\n return str;\n}\n\nfunction replaceSymbols(str: string) {\n str = str.replace(/(?:\\(|\\))/g, '');\n str = str.replace(/(?:\\.|\\?)/g, '');\n str = str.replace(/(?:_+)/g, '_');\n str = str.replace(/(?:\\$+)/g, 's');\n return str;\n}"],"mappings":"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","names":["import_fs","winston","fs","winston","transports","fs","axios","axiosRetry","retryCount","stream","moment","import_axios","qs","import_moment","_","import_bluebird","streams","BPromise","selectedStream","import_util","BPromise","moment","_","_","params","axios","retry","errors","import_moment","import_moment","import_fs_extra","fs","fs","moment","import_bluebird","moment","BPromise"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/sdk/utils.ts","../src/sdk/service/logger.ts","../src/sdk/service/network.ts","../src/sdk/service/metric.ts","../src/sdk/service/memory.ts","../src/sdk/service/exit.ts","../src/sdk/service/error.ts","../src/sdk/models/replication.ts","../src/sdk/models/messages.ts","../src/sdk/models/state.ts","../src/sdk/constants/date.ts","../src/sdk/models/tap/authenticator.ts","../src/sdk/models/tap/restStream.ts","../src/sdk/models/tap/stream.ts","../src/sdk/helpers/typing.ts","../src/sdk/models/tap/tap.ts","../src/sdk/helpers/qs-logger.ts","../src/sdk/models/target/dbSync.ts","../src/sdk/models/target/error.ts","../src/sdk/models/target/record.ts","../src/sdk/models/target/renameColumnStore.ts","../src/sdk/models/target/schema.ts","../src/sdk/models/target/target.ts","../src/sdk/models/target/streamDbState.ts","../src/sdk/models/target/temporaryFile.ts","../src/targets/bigquery/helpers.ts","../src/targets/bigquery/service/record.ts","../src/targets/bigquery/service/dbSync.ts","../src/targets/bigquery/service/bigquery.ts","../src/targets/bigquery/service/cloudStorage.ts","../node_modules/uuid/dist/esm-node/rng.js","../node_modules/uuid/dist/esm-node/regex.js","../node_modules/uuid/dist/esm-node/validate.js","../node_modules/uuid/dist/esm-node/stringify.js","../node_modules/uuid/dist/esm-node/v4.js","../src/targets/bigquery/main.ts","../src/sdk/service/gcs.ts","../src/state-providers/gcs/main.ts"],"sourcesContent":["export * from \"./sdk/utils\";\nexport * from \"./sdk/service/network\";\nexport * from \"./sdk/service/logger\";\nexport * from \"./sdk/service/metric\";\nexport * from \"./sdk/service/memory\";\nexport * from \"./sdk/service/error\";\nexport * from \"./sdk/service/exit\";\n\nexport * from \"./sdk/models/replication\";\nexport * from \"./sdk/models/error\";\nexport * from \"./sdk/models/http\";\nexport * from \"./sdk/models/messages\";\nexport * from \"./sdk/models/metadata\";\nexport * from \"./sdk/models/schema\";\nexport * from \"./sdk/models/state\";\n\n/**\n * Taps\n */\nexport * from \"./sdk/models/tap/authenticator\";\nexport * from \"./sdk/models/tap/restStream\";\nexport * from \"./sdk/models/tap/stream\";\nexport * from \"./sdk/models/tap/tap\";\n\n/**\n * State Providers\n */\nexport * from \"./sdk/models/state-provider/types\";\n\n/**\n * Targets\n */\nexport * from \"./sdk/models/target/dbSync\";\nexport * from \"./sdk/models/target/error\";\nexport * from \"./sdk/models/target/models\";\nexport * from \"./sdk/models/target/record\";\nexport * from \"./sdk/models/target/renameColumnStore\";\nexport * from \"./sdk/models/target/schema\";\nexport * from \"./sdk/models/target/target\";\nexport * from \"./sdk/models/target/targetHook\";\nexport * from \"./sdk/models/target/temporaryFile\";\n\n/** The SDK is including some major targets and state providers implemantations */\nexport * from \"./targets/bigquery/main\";\nexport * from \"./targets/bigquery/models/config\";\nexport * from \"./state-providers/gcs/main\";","import { readFileSync } from \"fs\";\nimport { logger } from \"./service/logger.js\";\n\nfunction readFile(fileName: string, filePath: string) {\n try {\n return readFileSync(filePath);\n } catch (err) {\n logger.error(`Can't open file: \\`${fileName}\\` at path: \\`${filePath}\\`. Is it at the proper place?`)\n throw err;\n }\n}\n\nfunction parseFileContent(fileName: string, fileContent: Buffer) {\n try {\n return JSON.parse(fileContent.toString());\n } catch (err) {\n logger.error(`Can't parse file: \\`${fileName}\\` as JSON. Is it properly formatted?`)\n throw err;\n }\n}\n\nexport const loadJson = (fileName: string): any => {\n const filePath = process.cwd() + `/` + fileName\n const fileContent = readFile(fileName, filePath);\n return parseFileContent(fileName, fileContent);\n}\n\nexport const loadSchema = (streamId: string) => {\n const schema = loadJson(`schemas/${streamId}.json`)\n return schema;\n}","import * as winston from \"winston\";\nexport const BATCH_INTERVAL_MS = 100;\n\nconst transports = {\n console: new winston.transports.Console({\n stderrLevels: [],\n level: 'info'\n })\n};\n\nconst getTransports = (): winston.transport[] => {\n return [\n transports.console\n ]\n}\n\nconst { combine, prettyPrint, timestamp, errors, splat } = winston.format;\n\nconst winstonLogger = winston.createLogger({\n format: combine(\n timestamp(),\n errors({ stack: true }),\n splat(),\n prettyPrint()\n ),\n transports: getTransports(),\n});\n\nlet isWinstonOpen = true;\nconst closeWinston = (cb: () => void) => {\n isWinstonOpen = false;\n winstonLogger.end();\n winstonLogger.on('finish', () => {\n setTimeout(() => {\n return cb()\n }, BATCH_INTERVAL_MS * 2)\n });\n}\n\ntype LogLevel = 'info' | 'error' | 'debug' | 'warn';\n\nconst log = (\n level: LogLevel,\n message: string | any,\n ...args: any[]\n): void => {\n if (isWinstonOpen) {\n winstonLogger[level](message, ...args);\n } else {\n console[level](message, ...args);\n }\n};\n\nexport const logger = {\n info: (message: string | any, ...args: any[]): void => log('info', message, ...args),\n error: (message: string | any, ...args: any[]): void => log('error', message, ...args),\n debug: (message: string | any, ...args: any[]): void => log('debug', message, ...args),\n warn: (message: string | any, ...args: any[]): void => log('warn', message, ...args),\n closeWinston\n}","import axios, { AxiosError, AxiosInstance, AxiosResponse, AxiosRequestConfig, AxiosRequestHeaders } from \"axios\";\nimport { URLSearchParams } from \"url\";\nimport * as fs from 'fs';\nimport * as qs from 'qs';\nimport axiosRetry, { isNetworkOrIdempotentRequestError } from 'axios-retry';\nimport { logger } from \"./logger\";\n\n// This retry regardless of whether the call is idempotent or not. \n// e.g. this will retry POST and PUT.\n// Hence, this service and all its function SHOULD not be used to create things as it is not safe. \n// This service should be only used for extracting data.\nconst shouldRetry = (error: AxiosError): boolean => {\n\n const statusCode = error.response ? error.response.status : 0;\n\n return error.code !== 'ECONNABORTED' // Triggered if there is not enough local socket. In those case, retrying will only make things worse\n && (\n !error.response\n || statusCode === 429\n || statusCode === 409\n || statusCode === 400\n || (statusCode >= 500 && statusCode < 599)\n );\n}\n\nexport const getAxiosInstance = (retryCount?: number): AxiosInstance => {\n const instance = axios.create({\n timeout: 120_000\n });\n axiosRetry(instance,\n {\n retries: retryCount || 24,\n retryDelay: (retryCount, error) => {\n logger.info(`🔁 Retrying for the ${retryCount}th time the call for \n method=${error.config?.method}\n url=${error.config?.url}\n params=%j\n body=%j`,\n error.config?.params,\n error.config?.data\n )\n if (retryCount > 6) {\n return 10000\n }\n return axiosRetry.exponentialDelay(retryCount)\n },\n retryCondition: (error: AxiosError): boolean => {\n logger.debug(`😱 Got an error for ${error.config?.method} ${error.config?.url}\n \n Status: ${error?.response?.status}\n Error code ${error.code}\n Error config method ${error}`)\n\n return isNetworkOrIdempotentRequestError(error)\n || shouldRetry(error)\n }\n });\n return instance;\n}\n\nexport interface GetConfig {\n qs?: { [key: string]: any },\n headers?: AxiosRequestHeaders,\n retryCount?: number\n}\n\nexport const getRawJSONApiCall = async <T>(\n endpoint: string,\n config: GetConfig,\n privateLogging?: boolean\n): Promise<AxiosResponse<T>> => {\n\n const instance = getAxiosInstance(config.retryCount);\n\n // Repeat the key/value pair multiple time when having arrays to be passed in the QS\n const paramsSerializer = (params: any) => {\n return qs.stringify(params, { arrayFormat: 'repeat' })\n }\n\n try {\n logger.info(`🤖 GET ${endpoint}`, { private: privateLogging })\n const requestConfig: AxiosRequestConfig = {\n params: config.qs,\n paramsSerializer: { serialize: (params) => qs.stringify(params, { arrayFormat: 'repeat' }) }\n };\n if (config.headers) {\n requestConfig.headers = config.headers;\n }\n const response = await instance.get(\n endpoint,\n requestConfig\n );\n return response;\n } catch (err: any) {\n if (err.response.status > 400) {\n throw new Error(`We got a \\`${err.response.status}\\` status code from endpoint: \\`${endpoint}\\`. \n\n headers response: ${JSON.stringify(err.response.headers)}\n\n Response body from the server: ${JSON.stringify(err.response.data)}`);\n }\n throw err;\n }\n}\n\nexport const getJSONApiCallWithFullResponse = async <T>(\n endpoint: string,\n config: GetConfig,\n privateLogging?: boolean\n) => {\n const instance = getAxiosInstance(config.retryCount);\n\n // Repeat the key/value pair multiple time when having arrays to be passed in the QS\n const paramsSerializer = (params: any) => {\n return qs.stringify(params, { arrayFormat: 'repeat' })\n }\n\n try {\n logger.info(`🤖 GET ${endpoint} with params: %s`, config.qs, { private: privateLogging })\n const requestConfig: AxiosRequestConfig = {\n params: config.qs,\n paramsSerializer: { serialize: (params) => qs.stringify(params, { arrayFormat: 'repeat' }) }\n };\n if (config.headers) {\n requestConfig.headers = config.headers;\n }\n const response = await instance.get(endpoint, requestConfig);\n return response;\n } catch (err) {\n if (err instanceof Error) {\n if (axios.isAxiosError(err)) {\n if ((err.response?.status || 0) > 400) {\n logger.warn(`We got a \\`${err.response?.status}\\` status code from endpoint: \\`${endpoint}\\`. \n\n Headers response: ${JSON.stringify(err.response?.headers)}\n\n Response body from the server: ${JSON.stringify(err.response?.data)}`);\n }\n }\n }\n throw err;\n }\n}\n\nexport const getJSONApiCall = async <T>(\n endpoint: string,\n config: GetConfig,\n privateLogging?: boolean\n): Promise<T> => {\n const fullResponse = await getJSONApiCallWithFullResponse(\n endpoint,\n config,\n privateLogging\n );\n return fullResponse.data;\n}\n\nexport const getDownloadFileApiCall = async <T>(\n endpoint: string,\n config: GetConfig,\n output: string,\n privateLogging?: boolean\n): Promise<{ outputDir: string }> => {\n\n const instance = getAxiosInstance(config.retryCount);\n\n const writer = fs.createWriteStream(output)\n\n const paramsSerializer = (params: any) => {\n return qs.stringify(params, { arrayFormat: 'repeat' })\n }\n\n logger.info(`🤖 GET ${endpoint}`, { private: privateLogging })\n\n return instance({\n method: \"GET\",\n url: endpoint,\n responseType: 'stream',\n params: config.qs,\n ...(config.headers ? { headers: config.headers } : {}),\n paramsSerializer: { serialize: (params) => qs.stringify(params, { arrayFormat: 'repeat' }) }\n }).then(response => {\n return new Promise<{ outputDir: string }>((resolve, reject) => {\n response.data.pipe(writer);\n let error: any = null;\n writer.on('error', err => {\n error = err;\n writer.close();\n reject(err);\n });\n writer.on('close', () => {\n if (!error) {\n resolve({ outputDir: output });\n }\n //no need to call the reject here, as it will have been called in the\n //'error' stream;\n });\n });\n });\n}\n\nexport interface PostConfig {\n qs?: { [key: string]: any },\n headers?: AxiosRequestHeaders,\n retryCount?: number\n}\n\nexport const postJSONApiCall = async <T>(\n endpoint: string,\n config: PostConfig,\n payload: any\n): Promise<T> => {\n\n const instance = getAxiosInstance(config.retryCount);\n try {\n const requestConfig: AxiosRequestConfig = { params: config.qs };\n if (config.headers) {\n requestConfig.headers = config.headers;\n }\n const response = await instance.post(\n endpoint,\n payload,\n requestConfig\n );\n return response.data;\n } catch (err: any) {\n if (err?.response?.status >= 400) {\n throw new Error(`We got a \\`${err.response.status}\\` status code from endpoint: \\`${endpoint}\\`. \n \n Response body from the server: ${JSON.stringify(err.response.data)}`);\n }\n throw err;\n }\n}\n\nexport const postFormDataApiCall = async <T>(endpoint: string, config: PostConfig, payload: any): Promise<T> => {\n\n const instance = getAxiosInstance(config.retryCount);\n\n try {\n const response = await instance({\n method: 'post',\n url: endpoint,\n headers: {\n ...(payload as any).getHeaders()\n },\n data: payload\n });\n return response.data;\n } catch (err: any) {\n if (err.response.status > 400) {\n throw new Error(`We got a \\`${err.response.status}\\` status code from endpoint: \\`${endpoint}\\`. \n \n Response body from the server: ${JSON.stringify(err.response.data)}`);\n }\n throw err;\n }\n}\n\nexport const postUrlEncodedApiCall = async (endpoint: string, config: PostConfig, payload: any) => {\n\n const instance = getAxiosInstance(config.retryCount);\n\n try {\n\n const params = new URLSearchParams(payload as any);\n\n const response = await instance.post(\n endpoint,\n params.toString(),\n {\n ...(config.headers ? { headers: config.headers } : {})\n });\n return response.data;\n } catch (err: any) {\n if (err.response.status > 400) {\n throw new Error(`We got a \\`${err.response.status}\\` status code from endpoint: \\`${endpoint}\\`. \n \n Response body from the server: ${JSON.stringify(err.response.data)}`);\n }\n throw err;\n }\n}","const metricStore: {\n [streamId: string]: {\n [metricName: string]: CounterMetric\n }\n} = {};\n\nexport const ALL_STREAM_ID_KEYWORD = \"all\";\nexport const ROWS_SYNCED_METRIC_NAME = \"rows_synced_count\";\nexport const API_CALLS_METRIC_NAME = \"api_calls_count\";\nexport const EXECUTION_TIME_METRIC_NAME = \"execution_time_ms\";\n\n// We're using functions here so that the call is done lazily\n// when the stream is initialized and the proper isSilent + streamId is configured\n// otherwise we have the default streamId value here\nexport interface MetricConfiguration {\n isEnabled: () => boolean;\n getStreamIds?: () => string[];\n}\n\nexport const getCounterMetrics = (\n name: string,\n streamIds: string[]\n): CounterMetric[] => {\n return streamIds.map(streamId => {\n return getCounterMetric(name, streamId)\n })\n}\n\nexport const getCounterMetric = (\n name: string,\n streamId: string = ALL_STREAM_ID_KEYWORD\n): CounterMetric => {\n if (!metricStore[streamId]) {\n metricStore[streamId] = {};\n }\n const streamMetricStore = metricStore[streamId];\n\n if (!streamMetricStore[name]) {\n streamMetricStore[name] = new CounterMetric(name, streamId);\n }\n return streamMetricStore[name];\n}\n\nexport const getAllMetrics = (): CounterMetric[] => {\n return Object.keys(metricStore)\n .flatMap(streamId => {\n const streamMetricStore = metricStore[streamId];\n if (!streamMetricStore) {\n return [] as CounterMetric[];\n }\n return Object.keys(streamMetricStore)\n .map(metricName => streamMetricStore[metricName])\n .filter((m): m is CounterMetric => m !== undefined)\n })\n}\n\nexport class CounterMetric {\n private value: number = 0;\n name: string;\n streamId: string;\n\n constructor(\n name: string,\n streamId: string\n ) {\n this.name = name;\n this.streamId = streamId;\n }\n\n increment(inc: number = 1): void {\n this.value = this.value + inc;\n }\n\n getStreamId(): string {\n return this.streamId\n }\n\n getName(): string {\n return this.name\n }\n\n getValue(): number {\n return this.value\n }\n}","import { logger } from \"./logger\";\n\nconst formatMemoryUsage = (data: number) => `${Math.round(data / 1024 / 1024 * 100) / 100} MB`;\n\nexport const printMemoryFootprint = (prefix: string) => {\n const memoryData = process.memoryUsage();\n\n const memoryUsage = {\n rss: `${formatMemoryUsage(memoryData.rss)} -> Resident Set Size - total memory allocated for the process execution`,\n heapTotal: `${formatMemoryUsage(memoryData.heapTotal)} -> total size of the allocated heap`,\n heapUsed: `${formatMemoryUsage(memoryData.heapUsed)} -> actual memory used during the execution`,\n external: `${formatMemoryUsage(memoryData.external)} -> V8 external memory`,\n };\n\n logger.info(`${prefix}: %j`, memoryUsage);\n}","import { logger } from \"./logger\";\n\nexport async function gracefulExit(exitCode: number) {\n // Wait for winston to have logged all messages\n // Required as we are using HTTP transport\n const loggerFinish = new Promise<void>((resolve, reject) => {\n logger.closeWinston(resolve)\n })\n await loggerFinish;\n process.exit(exitCode);\n}","import { gracefulExit } from \"./exit\";\nimport { logger } from \"./logger\";\nimport { ErrorType } from \"../models/error\";\n\nexport const haltAndCatchFire = async (\n errorType: ErrorType,\n errorText: string,\n errorDebugText: string\n): Promise<void> => {\n\n logger.error(\n `💥 Got a fatal error that will reported to the end user. Process will stop.\n errorType=%s\n errorText=%s\n errorDebugText=%s\n `,\n errorType,\n errorText,\n errorDebugText\n )\n // we return sucess but we let the sucess job pass the error params\n await gracefulExit(0);\n}","export enum ReplicationMethod {\n INCREMENTAL = \"INCREMENTAL\",\n FULL_TABLE = \"FULL_TABLE\"\n}","import { StreamId } from \"./metadata\";\nimport { ReplicationMethod } from \"./replication\";\nimport { PropertiesMetadata } from \"./schema\";\n\nexport type MessageType = \"RECORD\" | \"STATE\" | \"SCHEMA\" | \"ACTIVATE_VERSION\" | \"REPLICATION_METHOD\";\n\nexport interface Message {\n type: MessageType;\n toString(): string;\n}\n\nexport class RecordMessage implements Message {\n\n type: MessageType = \"RECORD\"\n stream: StreamId;\n record: any;\n\n constructor(record: any, stream: StreamId) {\n this.record = record;\n this.stream = stream;\n }\n\n toString() {\n const result = {\n type: \"RECORD\",\n record: this.record,\n stream: this.stream\n }\n return JSON.stringify(result);\n }\n}\n\nexport class StateMessage implements Message {\n\n type: MessageType = \"STATE\"\n value: any\n\n constructor(value: any) {\n this.value = value\n }\n\n toString() {\n const result = {\n type: \"STATE\",\n value: this.value\n }\n return JSON.stringify(result);\n }\n}\n\nexport class ReplicationMethodMessage implements Message {\n\n type: MessageType = \"REPLICATION_METHOD\";\n stream: string;\n replication: ReplicationMethod;\n\n constructor(stream: string, version: ReplicationMethod) {\n this.stream = stream;\n this.replication = version;\n }\n\n toString() {\n const result = {\n type: \"REPLICATION_METHOD\",\n replication: this.replication,\n stream: this.stream\n }\n return JSON.stringify(result);\n }\n}\n\nexport class SchemaMessage implements Message {\n\n type: MessageType = \"SCHEMA\";\n stream: StreamId;\n schema: any;\n keyProperties: string[];\n bookmarkProperties: string[] | undefined;\n displayLabel: string | undefined;\n description: string | undefined;\n propertiesMetadata: PropertiesMetadata | undefined\n\n constructor(opts: {\n stream: StreamId,\n schema: any,\n keyProperties: string[],\n bookmarkProperties?: string[],\n displayLabel?: string,\n description?: string,\n propertiesMetadata?: PropertiesMetadata | undefined\n }) {\n const {\n stream,\n schema,\n keyProperties,\n bookmarkProperties,\n displayLabel,\n description,\n propertiesMetadata\n } = opts;\n\n this.stream = stream;\n this.schema = schema;\n this.keyProperties = keyProperties;\n this.bookmarkProperties = bookmarkProperties;\n this.displayLabel = displayLabel;\n this.description = description;\n this.propertiesMetadata = propertiesMetadata;\n }\n\n toString() {\n const result: any = {\n type: \"SCHEMA\",\n stream: this.stream,\n schema: this.schema,\n key_properties: this.keyProperties,\n label: this.displayLabel,\n description: this.description,\n }\n\n if (this.bookmarkProperties) {\n result[\"bookmark_properties\"] = this.bookmarkProperties\n }\n\n return JSON.stringify(result);\n }\n}","import { StreamId } from \"./metadata\";\nimport { StateMessage } from \"./messages\";\nimport dayjs, { Dayjs } from \"dayjs\";\nimport { ITarget } from \"./target/target\";\nimport { defaultDateTimeFormat } from \"../constants/date\";\nimport { format } from \"util\";\n\nexport interface InputTapState {\n bookmarks?: {\n [streamId: string]: StreamState\n }\n}\n\nexport interface TapState {\n bookmarks: {\n [streamId: string]: StreamState\n }\n}\n\nexport interface Bookmark {\n replicationKey?: string;\n replicationKeyValue?: string; // Contains ISO 8601 string\n}\n\nexport interface StreamState extends Bookmark {\n progressMarkers?: ProgressMarkers\n replicationKeySignpost?: string\n}\n\nexport interface ProgressMarkers extends Bookmark {\n Note?: string;\n}\n\n// To deprecate\nexport interface State {\n bookmarks: Bookmarks;\n}\n\n// To deprecate\nexport interface Bookmarks {\n [streamId: string]: any;\n}\n\nconst PROGRESS_MARKERS = \"progressMarkers\"\nconst PROGRESS_MARKER_NOTE = \"Note\"\nconst SIGNPOST_MARKER = \"replicationKeySignpost\"\n\nexport const incrementStreamState = (\n state: StreamState,\n replicationKey: string,\n latestRecord: any,\n isSorted: boolean\n): StreamState => {\n\n let newRkValue = latestRecord[replicationKey] as string;\n if (!newRkValue) {\n throw new Error(format(`No value for replicationKey: ${replicationKey} in record with keys: %j`, Object.keys(latestRecord)))\n }\n let newRkValueMoment = dayjs(newRkValue);\n\n let prevRkValue: string | undefined;\n let prevRkValueMoment: Dayjs | undefined;\n\n if (isSorted) {\n prevRkValue = state[\"replicationKeyValue\"];\n prevRkValueMoment = dayjs(prevRkValue);\n if (prevRkValue && prevRkValueMoment.isAfter(newRkValueMoment)) {\n throw new Error(\n `Unsorted data detected in stream. Latest value '${newRkValue}' is\n smaller than previous max '${prevRkValue}'.`\n )\n }\n }\n\n // For unsorted streams, we have to make sure that the \"new\" replication key is newer or equal than the previous one\n if (!isSorted) {\n\n // Progress markers are living only during the current sync\n // They are erased at the end of the sync and the stored value is used to write the new state\n if (!state[PROGRESS_MARKERS]) {\n const marker: ProgressMarkers = {};\n marker[PROGRESS_MARKER_NOTE] = \"Progress is not resumable if interrupted.\"\n state[PROGRESS_MARKERS] = marker;\n }\n prevRkValue = (state[PROGRESS_MARKERS] as any)[\"replicationKeyValue\"];\n\n // In case we don't have any previous value in the PROGRESS_MARKERS, \n // which happens for the first record of the current sync, we take the last state value\n prevRkValueMoment = dayjs(prevRkValue || state[\"replicationKeyValue\"]);\n\n // If we just got an \"old\" record, we keep the previous state as the max ts\n if (prevRkValue && prevRkValueMoment.isAfter(newRkValueMoment)) {\n newRkValueMoment = prevRkValueMoment;\n newRkValue = prevRkValue;\n }\n }\n\n // Signpost is the moment we start the current sync,\n // we make sure that our replication value can't be greater than the signpost\n const signpostMarker = state[SIGNPOST_MARKER];\n const replicationKeySignpostMoment = dayjs(signpostMarker);\n\n if (replicationKeySignpostMoment && replicationKeySignpostMoment.isBefore(newRkValueMoment)) {\n // Overflowed max bookmark threshold, reset to the max for this key:\n newRkValueMoment = replicationKeySignpostMoment\n newRkValue = replicationKeySignpostMoment.format(defaultDateTimeFormat);\n }\n\n if (isSorted === false) {\n (state[PROGRESS_MARKERS] as ProgressMarkers)['replicationKey'] = replicationKey;\n (state[PROGRESS_MARKERS] as ProgressMarkers)['replicationKeyValue'] = dayjs(newRkValueMoment).format(defaultDateTimeFormat);\n } else {\n state['replicationKey'] = replicationKey;\n state['replicationKeyValue'] = dayjs(newRkValueMoment).format(defaultDateTimeFormat);\n }\n\n return state;\n}\n\n/**\n * Promote or wipe progress markers once sync is complete.\"\"\"\n\n * @param state \n * @returns \n */\nexport const finalizeStateProgressMarkers = (state: StreamState): StreamState => {\n\n const signpostValue = state[SIGNPOST_MARKER];\n const progressMarkers = state[PROGRESS_MARKERS];\n if (progressMarkers && progressMarkers[\"replicationKey\"] && progressMarkers[\"replicationKeyValue\"]) {\n // Replication keys valid (only) after sync is complete\n state[\"replicationKey\"] = progressMarkers[\"replicationKey\"]\n let newRkValue = progressMarkers[\"replicationKeyValue\"]\n\n // Reset to signpost if needed\n if (signpostValue && _greaterThan(newRkValue, signpostValue)) {\n newRkValue = signpostValue\n }\n\n const previousReplicationValue = state[\"replicationKeyValue\"];\n if (!previousReplicationValue || (previousReplicationValue && _greaterThan(newRkValue, previousReplicationValue))) {\n state[\"replicationKeyValue\"] = newRkValue\n }\n }\n // Wipe any markers that have not been promoted\n delete state[PROGRESS_MARKERS];\n\n return state;\n}\n\nexport const _greaterThan = (aValue: string, bValue: string): boolean => {\n return dayjs(aValue).isAfter(dayjs(bValue));\n}\n\nexport const extractStateForStream = (state: InputTapState, streamId: StreamId) => {\n if (!state.bookmarks) {\n state.bookmarks = {}\n }\n if (!state.bookmarks[streamId]) {\n state.bookmarks[streamId] = {}\n }\n return state.bookmarks[streamId];\n}\n\nexport class StateService {\n\n private static instance: StateService;\n\n bookmarks: Bookmarks;\n\n constructor() {\n this.bookmarks = {}\n }\n\n static getInstance(): StateService {\n if (!this.instance) {\n this.instance = new this();\n }\n\n return this.instance;\n }\n\n setBookmark(streamId: StreamId, streamState: StreamState) {\n this.bookmarks[streamId] = streamState;\n }\n\n setBookmarkSignpost(streamId: StreamId, signpostValue: string) {\n if (!this.bookmarks[streamId]) {\n this.bookmarks[streamId] = {}\n }\n this.bookmarks[streamId][SIGNPOST_MARKER] = signpostValue;\n }\n\n getBookmark(streamId: StreamId): StreamState {\n if (this.bookmarks[streamId]) {\n return this.bookmarks[streamId];\n } else {\n return {}\n }\n }\n\n clearState() {\n this.bookmarks = {};\n }\n\n get(): State {\n const state: State = {\n bookmarks: this.bookmarks\n }\n return state\n }\n\n async forwardStateToTarget(target: ITarget) {\n const state: State = {\n bookmarks: this.bookmarks\n }\n\n const message = new StateMessage(state);\n await target.state(message);\n }\n}","export const defaultDateTimeFormat = \"YYYY-MM-DDTHH:mm:ss.SSSSSSZ\"","import { HTTPHeaders, URLParams } from \"../http\";\n\n/**\n * C: The type of the tap config\n */\nexport class Authenticator<C> {\n\n getAuthHeaders(config: C): Promise<HTTPHeaders> {\n return Promise.resolve({})\n }\n\n getAuthQS(config: C): Promise<URLParams> {\n return Promise.resolve({})\n }\n\n}","import axios, { AxiosError, AxiosInstance, AxiosRequestConfig } from \"axios\";\nimport { Authenticator } from \"./authenticator\";\nimport { HTTPHeaders, HTTPMethod, URLParams } from \"../http\";\nimport * as qs from 'qs';\nimport { logger } from \"../../service/logger\";\nimport { Stream } from \"./stream\";\nimport { InputTapState } from \"../state\";\nimport { ITarget } from \"../target/target\";\nimport { getAxiosInstance } from \"../../service/network\";\nimport { DEFAULT_MAX_CONCURRENT_STREAMS } from \"./tap\";\nimport { API_CALLS_METRIC_NAME, CounterMetric, getCounterMetrics, MetricConfiguration } from \"../../service/metric\";\nimport { getTruncatedParamsForLog } from \"../../helpers/qs-logger\";\nimport cloneDeep from \"lodash/cloneDeep.js\";\nimport isEqual from \"lodash/isEqual.js\";\n\n/**\n * R: Type of the API result\n * NPT: Type of the \"nextPageToken\"\n */\nexport abstract class RESTStream<R, O, NPT, C, P = undefined>\n extends Stream<O, C, P> {\n\n axiosInstance: AxiosInstance | undefined;\n\n constructor(\n config: C,\n state: InputTapState,\n target: ITarget,\n childConcurrency: number = DEFAULT_MAX_CONCURRENT_STREAMS\n ) {\n super(config, state, target, childConcurrency);\n this.apiCallsMetricsConf = {\n isEnabled: () => !this.isSilent,\n getStreamIds: () => [this.streamId]\n }\n }\n\n // Internal\n // Those functions shouldn't be overriden (or it means that we fuck'ed up the SDK during the design phase)\n\n /**\n * Prepare an Axios request object.\n * Pagination information can be parsed from `nextPageToken` if `nextPageToken` is not undefined.\n * @param nextPageToken \n * @returns \n */\n _prepareRequest = async (nextPageToken: NPT | undefined, parent?: P)\n : Promise<AxiosRequestConfig> => {\n\n const method = this.httpMethod;\n const url = this.getNextUrl(nextPageToken, parent);\n if (!url) {\n throw new Error(`StreamId: ${this.streamId} - URL is undefined. Did your properly define the URL for this stream?`)\n }\n\n const authenticator = this.authenticator\n\n // If getNextUrl returns a URL that already contains query string parameters,\n // extract them and merge into params. We remove the query part from the URL\n // to avoid duplication with axios params handling.\n let finalUrl = url;\n let urlQueryParams: Record<string, any> = {};\n const queryIndex = url.indexOf(\"?\");\n if (queryIndex !== -1) {\n finalUrl = url.substring(0, queryIndex);\n const rawQueryString = url.substring(queryIndex + 1);\n urlQueryParams = qs.parse(rawQueryString) as Record<string, any>;\n }\n\n const params = {\n ...this.getNextUrlParams(nextPageToken, parent),\n // Query params embedded in URL should override computed pagination params\n // but should not override auth params which are appended last\n ...urlQueryParams,\n ...(await authenticator?.getAuthQS(this.config))\n }\n\n const requestBody = this.getRequestBodyForNextCall(nextPageToken, parent)\n let headers = this.getCustomHTTPHeaders(parent);\n if (!headers) {\n headers = {};\n }\n\n if (authenticator) {\n const authHeaders = await authenticator.getAuthHeaders(this.config)\n headers = {\n ...headers,\n ...authHeaders\n }\n }\n\n const paramsSerializer = (params: any) => {\n return qs.stringify(params, { arrayFormat: 'repeat' })\n }\n\n const request: AxiosRequestConfig = {\n url: finalUrl,\n method,\n data: requestBody,\n params,\n paramsSerializer,\n headers\n }\n return request\n }\n\n async _requestWithRetry(request: AxiosRequestConfig, privateLogging?: boolean): Promise<R | \"STOP_SYNC\"> {\n try {\n logger.debug(`🤖 ${request.method} ${request.url} with params: %j | body: %j`,\n request.params,\n request.data,\n { private: privateLogging });\n logger.info(`🤖 ${request.method} ${request.url} qs: %j`,\n getTruncatedParamsForLog(request.params),\n { private: privateLogging });\n const axiosInstance = this.axiosInstance;\n if (!axiosInstance) {\n throw new Error(`Axios Instance is not initialized!`)\n }\n const response = await axiosInstance.request<R>(request);\n return response.data;\n } catch (err) {\n if (axios.isAxiosError(err)) {\n logger.error(`🤖 Error on ${request.method} ${request.url} with params %j | body: %j | headers: %j - getting error %s - response body: %j`,\n request.params,\n request.data,\n request.headers,\n err.message,\n err.response?.data\n )\n const recoveredValue = await this.httpErrorHandler(request.url, err);\n if (recoveredValue === undefined) {\n return \"STOP_SYNC\"\n } else {\n return recoveredValue;\n }\n } else {\n throw err;\n }\n }\n }\n\n async *_requestRecords(parent?: P): AsyncIterable<O> {\n let nextPageToken: NPT | undefined = undefined;\n let finished = false;\n\n let apiCallsMetrics: CounterMetric[] = [];\n if (this.apiCallsMetricsConf.isEnabled() === true) {\n apiCallsMetrics = getCounterMetrics(\n API_CALLS_METRIC_NAME,\n this.apiCallsMetricsConf.getStreamIds\n ? this.apiCallsMetricsConf.getStreamIds()\n : []\n )\n }\n\n // We reset the axios instance here to use the value of `httpRetryCount` after the initialization of custom values defined in the Streams impl.\n // Doing it in the constructor is givingf us access only to the default value of `httpRetryCount`\n this.axiosInstance = getAxiosInstance(this.httpRetryCount);\n\n while (!finished) {\n const preparedRequest = await this._prepareRequest(nextPageToken, parent);\n const resp = await this._requestWithRetry(preparedRequest);\n\n apiCallsMetrics.forEach(metric => {\n metric.increment();\n })\n\n // We stop the sync for this stream\n if (resp === \"STOP_SYNC\") {\n return;\n }\n const rows = this.parseResponse(resp, parent, nextPageToken);\n for await (const row of rows) {\n yield row\n }\n\n const previousToken = cloneDeep(nextPageToken);\n nextPageToken = this.getNextPageToken(resp, previousToken);\n\n if (nextPageToken && isEqual(nextPageToken, previousToken)) {\n throw new Error(\n `${this.streamId} - Loop detected in pagination. \"\n Pagination token: \\`${JSON.stringify(nextPageToken)}\\` is identical to prior token \\`${JSON.stringify(previousToken)}\\`.`\n )\n }\n // Cycle until getNextPageToken() no longer returns a value\n finished = !nextPageToken\n }\n }\n\n async *_getRecords(parent?: P): AsyncIterable<O> {\n for await (const row of this._requestRecords(parent)) {\n yield row\n }\n }\n\n // Overridable\n // Even if the default impl. of some function can be used as-is, those functions\n // are meant to be overriden when necessary to match the API needs.\n httpMethod: HTTPMethod = \"GET\";\n baseUrl: string = \"\";\n path: string = \"\";\n httpRetryCount = 24;\n authenticator?: Authenticator<C>;\n\n apiCallsMetricsConf: MetricConfiguration\n\n // When undefined is returned, we should stop the sync without any error\n async httpErrorHandler(url: string | undefined, err: AxiosError): Promise<R | undefined> {\n if ((err.response?.status || 0) > 400) {\n throw new Error(`We got a \\`${err.response?.status}\\` status code from endpoint: \\`${url}\\`. \n\n Response body from the server: ${JSON.stringify(err.response?.data)}`);\n }\n throw err;\n }\n\n /** \n * Return a dictionary of values to be used in URL parameterization.\n * If paging is supported, developers may override with specific paging logic.\n * \n * By default, no params are passed.\n */\n getNextUrlParams(nextPageToken: NPT | undefined, parent?: P): URLParams {\n return {}\n }\n\n /** \n * Prepare the data payload for the REST API request.\n * Useful when working with POST APIs.\n * \n * By default, no payload will be sent (return undefined).\n */\n getRequestBodyForNextCall(nextPageToken: NPT | undefined, parent?: P): any {\n return undefined\n }\n\n /**\n * Return token identifying next page or undefined if all records have been read.\n * \n * By default, no token will be returned and a single API call will be made.\n * \n * @param response \n * @param previousToken \n * @returns \n */\n getNextPageToken(response: R, previousToken?: NPT): NPT | undefined {\n return undefined;\n }\n\n /**\n * Return custom headers to be used for HTTP requests.\n * \n * By default, no additional header will be added\n */\n getCustomHTTPHeaders(parent?: P): HTTPHeaders | undefined {\n return undefined;\n }\n\n /**\n * Return a URL, optionally targeted to a specific partition.\n * This can be overriden to perform dynamic URL generation.\n * \n * TODO: Make URL + Path templatisable and replace those with Extractor (or Tap) config\n * @returns \n */\n getNextUrl(previousToken?: NPT,parent?: P): string {\n const urlPattern = [this.baseUrl, this.path].join(\"\")\n return urlPattern;\n }\n\n /**\n * Parse the response and return an iterator of result rows.\n * \n * Default impl assume that R = O or R = O[]\n * @param response\n */\n async *parseResponse(\n response: R,\n parent?: P,\n nextPageToken?: NPT\n ): AsyncIterable<O> {\n if (Array.isArray(response)) {\n for (const row of response) {\n yield row as any as O\n }\n } else {\n yield response as any as O\n }\n }\n\n}","import dayjs, { Dayjs } from \"dayjs\";\nimport { defaultDateTimeFormat } from \"../../constants/date\";\nimport { isDatetimeType } from \"../../helpers/typing\";\nimport { logger } from \"../../service/logger\";\nimport { loadJson } from \"../../utils\";\nimport { StreamId } from \"../metadata\";\nimport { RecordMessage, ReplicationMethodMessage, SchemaMessage, StateMessage } from \"../messages\";\nimport { ReplicationMethod } from \"../replication\";\nimport { extractStateForStream, finalizeStateProgressMarkers, incrementStreamState, InputTapState, StateService } from \"../state\";\nimport { ITarget } from \"../target/target\";\nimport cloneDeep from \"lodash/cloneDeep.js\";\nimport { Schema } from \"../schema\";\nimport Bluebird from \"bluebird\";\nimport { DEFAULT_MAX_CONCURRENT_STREAMS } from \"./tap\";\nimport { CounterMetric, EXECUTION_TIME_METRIC_NAME, getCounterMetrics, MetricConfiguration, ROWS_SYNCED_METRIC_NAME } from \"../../service/metric\";\nimport { format } from \"util\";\n\n/**\n * TODO: Handle non timestamp based replication key\n *\n * O: Type of a resulted row after post processing\n * C: Type of the tap configuration\n * P: For children Streams, this is the type of the parent\n */\nexport abstract class Stream<O = any, C = any, P = undefined> {\n\n // Runtime values, can't be overriden\n config: C;\n tapState: InputTapState;\n target: ITarget;\n\n replicationMethod: ReplicationMethod | undefined = undefined;\n selectedByDefault: boolean = true;\n STATE_MSG_FREQUENCY: number = 10;\n streamId: StreamId = \"default\";\n schemaPath: string | undefined = undefined;\n displayLabel: string | undefined = undefined;\n description: string | undefined = undefined;\n primaryKey: string[] = [];\n replicationKey: string | undefined = undefined;\n // When set, use the state from another stream for this stream\n useStateFromStreamId: string | undefined = undefined;\n\n children: Stream<any, any, O | O[]>[] = [];\n // If true, it means that the records in this stream are sorted by replicationKey.\n // If false, then the records are coming in an unsorted manner.\n isSorted: boolean = false;\n // If true, then no SCHEMA / RECORD messages will be sent for this Stream.\n // However, a STATE will still be emitted if the Stream is using an incremental sync type.\n isSilent: boolean = false;\n\n childConcurrency: number;\n\n // Metrics configuration\n rowsSyncedMetricsConf: MetricConfiguration\n executionTimeMetricsConf: MetricConfiguration\n\n constructor(\n config: C,\n tapState: InputTapState,\n target: ITarget,\n childConcurrency: number = DEFAULT_MAX_CONCURRENT_STREAMS\n ) {\n this.config = config;\n this.tapState = cloneDeep(tapState);\n this.target = target;\n this.childConcurrency = childConcurrency;\n\n // Default metric configuration\n this.rowsSyncedMetricsConf = {\n isEnabled: () => !this.isSilent,\n getStreamIds: () => [this.streamId]\n }\n this.executionTimeMetricsConf = {\n isEnabled: () => !this.isSilent,\n getStreamIds: () => [this.streamId]\n }\n }\n\n // No root metadata: replication config is derived from stream defaults only\n\n /**\n * Sync this stream\n * Called only for streams with no parents, aka. \"root tap streams\"\n * @returns \n */\n sync = async (): Promise<void> => {\n try {\n const replicationMethod = this.configuredReplicationConfig().replicationMethod;\n logger.info(\n `🎬 Beginning ${replicationMethod} sync of stream '${this.streamId}'...`\n )\n\n await this.asyncInit();\n\n // Send a SCHEMA message to the downstream target\n await this._writeSchemaMessage();\n\n await this._writeReplicationMethodMessage();\n\n // Write the signpost\n await this._writeSignpostInState();\n\n // Sync the records themselves\n await this._syncRecords();\n\n // Flush the stream\n return this.flush();\n } catch (err) {\n if (err instanceof Error) {\n throw new Error(format(`got an error while syncing streamId=%s, err: %s`, this.streamId, err.message))\n }\n throw err;\n }\n }\n\n flush = async (): Promise<void> => {\n const replicationMethod = this.configuredReplicationConfig().replicationMethod;\n logger.info(\n `🚽 Flushing ${replicationMethod} sync of stream '${this.streamId}' + all of its children...`\n )\n\n await this._flush();\n\n await Bluebird.map(this.children, child => {\n return child.flush();\n }, { concurrency: 3 });\n }\n\n // Private message authoring methods:\n\n /**\n * Write out a STATE message with the latest state.\n */\n _writeStateMessage = (): Promise<void> => {\n const message = new StateMessage(StateService.getInstance().get());\n return this.target.state(message);\n }\n\n /**\n * Write out a ACTIVATE_VERSION message.\n */\n _writeReplicationMethodMessage = async (): Promise<void> => {\n const method = this.configuredReplicationConfig().replicationMethod;\n const message = new ReplicationMethodMessage(this.streamId, method);\n\n await Bluebird.map(this.children, async c => {\n return c._writeReplicationMethodMessage()\n }, { concurrency: 3 })\n await this.target.replicationMethod(message);\n }\n\n /**\n * Write out a SCHEMA message with the stream schema.\n */\n _writeSchemaMessage = async (skipChildrenSchema?: boolean): Promise<void> => {\n\n if (!this.isSilent) {\n const schema = await this.getSchema();\n if (schema !== undefined) {\n const replicationConfig = this.configuredReplicationConfig();\n\n const message = new SchemaMessage({\n keyProperties: this.primaryKey,\n stream: this.streamId,\n schema: schema.jsonSchema,\n ...(replicationConfig.replicationKey ? { bookmarkProperties: [replicationConfig.replicationKey] } : {}),\n ...(this.displayLabel ? { displayLabel: this.displayLabel } : {}),\n ...(this.description ? { description: this.description } : {}),\n ...(schema.propertiesMetadata ? { propertiesMetadata: schema.propertiesMetadata } : {})\n })\n await this.target.schema(message);\n }\n }\n\n if (skipChildrenSchema !== true) {\n await Bluebird.map(this.children, async (child) => {\n await child._writeSchemaMessage();\n }, { concurrency: 3 });\n }\n }\n\n // Private bookmarking methods\n\n _writeSignpostInState = async () => {\n const signpostMoment = await this.getReplicationKeySignpost();\n const signpostValue = signpostMoment?.format(defaultDateTimeFormat);\n\n if (signpostValue) {\n StateService.getInstance().setBookmarkSignpost(this.streamId, signpostValue);\n }\n }\n\n /**\n * Update state of stream with data from the provided record. \n */\n _incrementStreamState = (latestRecord: O): void => {\n\n if (latestRecord) {\n const replicationConfig = this.configuredReplicationConfig()\n if ([\n \"INCREMENTAL\",\n \"LOG_BASED\",\n ].includes(replicationConfig.replicationMethod)) {\n // If the stream is using another stream state, it doesn't own the state and can't increment it\n if (this.useStateFromStreamId) {\n return;\n }\n // If the replication method was forced, it can be that the stream is the child of anohter stream that is managing the state (ex. a paginated stream). \n // The state is not owned by the current stream then.\n if (this.replicationMethod && !this.replicationKey) {\n return;\n }\n\n // If the stream has been detected as being incremental and has no excuses for not owning its state, it should have the replicationKey\n if (!replicationConfig.replicationKey) {\n throw new Error(`Could not detect replication key for '${this.streamId}' stream\"\n replication method=${replicationConfig.replicationMethod})`\n )\n }\n\n const stateServiceInst = StateService.getInstance();\n const state = stateServiceInst.getBookmark(this.streamId);\n\n const newState = incrementStreamState(\n state,\n replicationConfig.replicationKey,\n latestRecord,\n this.isSorted\n )\n\n StateService.getInstance().setBookmark(this.streamId, newState)\n }\n }\n }\n\n /**\n * Return True if the stream uses a timestamp-based replication key.\n * \n * Developers can override with `is_timestamp_replication_key = True` in\n order to force this value.\n */\n isTimestampReplicationKey = async (): Promise<boolean> => {\n\n const replicationConfig = this.configuredReplicationConfig()\n\n if (!replicationConfig.replicationKey) {\n return false;\n }\n\n const schema = await this.getSchema();\n if (!schema || !schema.jsonSchema || !schema.jsonSchema.properties) {\n return false;\n }\n\n const typeFromSchema = schema.jsonSchema[\"properties\"][replicationConfig.replicationKey]\n if (!typeFromSchema) {\n return false;\n }\n\n return isDatetimeType(typeFromSchema);\n }\n\n /**\n * Return state timestamp if set for the stream, \n * or `start_date` config if set, \n * or the UNIX Epoch\n **/\n getStartingTimestamp(): Dayjs {\n const streamIdToReadFrom = this.useStateFromStreamId\n ? this.useStateFromStreamId\n : this.streamId;\n const state = extractStateForStream(this.tapState, streamIdToReadFrom);\n\n const startDate = (this.config as any).start_date as string | undefined;\n const replicationConfig = this.configuredReplicationConfig();\n\n logger.debug(`${this.streamId}: state.replicationKeyValue: ${state.replicationKeyValue}, \n state.replicationKey: ${state.replicationKey},\n this.replicationKey: ${replicationConfig.replicationKey}`)\n\n if (state.replicationKeyValue) {\n logger.debug(`${this.streamId} - getStartingTimestamp -> Returning replication key value: ${state.replicationKeyValue}`)\n return dayjs(state.replicationKeyValue);\n } else if (startDate) {\n logger.debug(`${this.streamId} - getStartingTimestamp -> Returning config start date: ${startDate}`)\n return dayjs(startDate)\n } else {\n logger.debug(`${this.streamId} - getStartingTimestamp -> Returning EPOCH (1970)`)\n return dayjs(0);\n }\n }\n\n /**\n * Return the max allowable bookmark value for this stream's replication key.\n * \n * For timestamp-based replication keys, this defaults to `dayjs()`. For\n * non-timestamp replication keys, default to `undefined`.\n * \n * Override this value to prevent bookmarks from being advanced in cases where we\n * may only have a partial set of records.\n */\n getReplicationKeySignpost = async (): Promise<Dayjs | undefined> => {\n\n if (await this.isTimestampReplicationKey()) {\n return dayjs()\n }\n\n return undefined\n }\n\n /**\n * Return the default replication method for the stream that will be used to write the catalog.\n */\n defaultReplicationConfig = (): {\n replicationMethod: ReplicationMethod,\n replicationKey: string | undefined,\n // When replication method is forced, it means that end user can't override it.\n isForced: boolean\n } => {\n if (this.replicationMethod) {\n return {\n replicationMethod: this.replicationMethod,\n replicationKey: this.replicationKey,\n isForced: true\n }\n }\n if (this.replicationKey || this.useStateFromStreamId) {\n return {\n replicationMethod: ReplicationMethod.INCREMENTAL,\n replicationKey: this.replicationKey,\n isForced: true\n }\n }\n\n return {\n replicationMethod: ReplicationMethod.FULL_TABLE,\n replicationKey: undefined,\n isForced: false\n }\n }\n\n /**\n * Return the configured replication method that will be used for the sync.\n */\n configuredReplicationConfig = (): {\n replicationMethod: ReplicationMethod,\n replicationKey: string | undefined\n } => {\n const defaults = this.defaultReplicationConfig();\n return {\n replicationMethod: defaults.replicationMethod,\n replicationKey: defaults.replicationKey\n }\n }\n\n // Private sync methods:\n async _syncRecords(parent?: P): Promise<void> {\n let rowsSent = 0;\n\n let recordSyncedMetrics: CounterMetric[] = [];\n if (this.rowsSyncedMetricsConf.isEnabled() === true) {\n recordSyncedMetrics = getCounterMetrics(\n ROWS_SYNCED_METRIC_NAME,\n this.rowsSyncedMetricsConf.getStreamIds\n ? this.rowsSyncedMetricsConf.getStreamIds()\n : []\n )\n }\n\n let executionTimeMetrics: CounterMetric[] = [];\n if (this.executionTimeMetricsConf.isEnabled() === true) {\n executionTimeMetrics = getCounterMetrics(\n EXECUTION_TIME_METRIC_NAME,\n this.executionTimeMetricsConf.getStreamIds\n ? this.executionTimeMetricsConf.getStreamIds()\n : []\n )\n }\n\n const startTime = new Date().getTime();\n\n for await (const row of this._getRecords(parent)) {\n\n if ((rowsSent - 1) % this.STATE_MSG_FREQUENCY == 0) {\n await this._writeStateMessage()\n }\n\n const recordMessage = new RecordMessage(\n { ...row },\n this.streamId\n )\n\n if (!this.isSilent) {\n await this.target.record(recordMessage);\n }\n\n await Bluebird.map(this.children, async (child) => {\n await child.asyncInit(row);\n return child._syncRecords(row);\n },\n {\n concurrency: this.childConcurrency\n });\n this._incrementStreamState(row);\n recordSyncedMetrics.forEach((metric) => {\n metric.increment();\n })\n rowsSent += 1;\n }\n\n const stateServiceInst = StateService.getInstance();\n const state = stateServiceInst.getBookmark(this.streamId);\n const newState = finalizeStateProgressMarkers(state);\n stateServiceInst.setBookmark(this.streamId, newState);\n\n if (!parent) {\n logger.info(`✅ Completed sync for stream: ${this.streamId} (${rowsSent} records)`);\n } else {\n logger.debug(`✅ Completed sync for sub-stream: ${this.streamId} (${rowsSent} records)`);\n }\n\n await this._writeStateMessage();\n const endTime = new Date().getTime();\n const executionTimeMs = endTime - startTime;\n executionTimeMetrics.forEach(metric => {\n metric.increment(executionTimeMs);\n })\n\n }\n\n // Overridable Methods\n\n asyncInit(parent?: P): Promise<void> {\n return Promise.resolve()\n }\n\n /**\n * Return the stream schema.\n * \n * Can be overriden to return a dynamic schema\n */\n getSchema(): Promise<Schema | undefined> {\n logger.debug(`stream: ${this.streamId} - getSchema() is called`)\n if (this.schemaPath) {\n const schema = loadJson(`schemas/${this.schemaPath}`)\n return Promise.resolve({ jsonSchema: schema });\n } else {\n if (this.isSilent) {\n return Promise.resolve(undefined);\n }\n throw new Error(`Stream=${this.streamId} - No schema path was passed.\n Either you forgot to fill the the \\`schemaPath\\` property,\n or to override the getSchema() method.`)\n }\n }\n\n getRowCount(): Promise<number | undefined> {\n return Promise.resolve(undefined)\n }\n\n /**\n * Abstract row generator function. Must be overridden by the child class.\n */\n _getRecords(parent?: P): AsyncIterable<O> {\n throw new Error(`Stream._getRecords() - Should be implemented by child class`);\n }\n\n /**\n * Return the list of keys that can be configured in the UI by the end user as the replication key\n * @returns \n */\n getValidReplicationKeys(): Promise<string[]> {\n return Promise.resolve([]);\n }\n\n /**\n * Called at the end of the sync. Use to flush all records before closing the Stream.\n * @returns \n */\n async _flush(): Promise<void> {\n await Promise.resolve();\n }\n}","\ninterface TypeDef {\n anyOf?: TypeDef[]\n type: string | string[]\n format?: \"date-time\"\n}\n/**\n * Return True if JSON Schema type definition is a 'date-time' type.\n * \n * Also returns True if 'date-time' is nested within an 'anyOf' type Array.\n\n * @param typeDef \n * @returns \n */\nexport const isDatetimeType = (typeDef: TypeDef): boolean => {\n\n if (!typeDef) {\n throw new Error(\"Could not detect type from empty typeDef param.\")\n }\n\n if (typeDef[\"anyOf\"] !== undefined) {\n for (const subTypeDef of typeDef[\"anyOf\"]) {\n if (isDatetimeType(subTypeDef)) {\n return true\n }\n }\n return false\n }\n\n else if (typeDef[\"type\"] !== undefined) {\n return typeDef[\"format\"] === \"date-time\"\n }\n\n throw new Error(\n `Could not detect type of key using schema '${typeDef}'`\n )\n\n}","import cloneDeep from \"lodash/cloneDeep.js\";\nimport { logger } from \"../../service/logger\";\nimport { InputTapState, StateService } from \"../state\";\nimport { StateProvider } from \"../state-provider/types\";\nimport { ITarget } from \"../target/target\";\nimport { Stream } from \"./stream\";\nimport Bluebird from \"bluebird\";\n\nexport const DEFAULT_MAX_CONCURRENT_STREAMS = 5;\n\nexport type SyncOptions = { include?: string[]; exclude?: string[] };\n\nexport abstract class Tap<C> {\n target: ITarget;\n config: C;\n streams: Stream[];\n concurrency: number = DEFAULT_MAX_CONCURRENT_STREAMS;\n stateProvider: StateProvider;\n tapState: InputTapState;\n\n // To be implemented by the concrete tap implementation\n abstract init(): Promise<void>;\n\n constructor(\n target: ITarget,\n config: C,\n stateProvider: StateProvider\n ) {\n this.streams = [];\n this.target = target;\n this.config = config\n this.stateProvider = stateProvider;\n this.tapState = { bookmarks: {} };\n }\n sync = async (options?: SyncOptions): Promise<void> => {\n\n // Set the initial state from the state provider\n const initialState = await this.stateProvider.getState();\n if(initialState.state && initialState.state.bookmarks) {\n this.tapState = cloneDeep(initialState.state);\n }\n\n await this.init();\n logger.info(`🚀 Start syncing`)\n\n const state = StateService.getInstance().get();\n logger.info(`📍 Received state: %j`, state)\n\n const envInclude = process.env.TAP_STREAMS\n ? process.env.TAP_STREAMS.split(',').map(s => s.trim()).filter(s => s.length > 0)\n : undefined;\n\n const include = options?.include && options.include.length > 0\n ? options.include\n : envInclude;\n const exclude = new Set((options?.exclude || []).map(s => s.trim()))\n\n let streamsToRun = this.streams.filter(s => !s.isSilent);\n if (include && include.length > 0) {\n const includeSet = new Set(include);\n streamsToRun = streamsToRun.filter(s => includeSet.has(s.streamId));\n }\n if (exclude.size > 0) {\n streamsToRun = streamsToRun.filter(s => !exclude.has(s.streamId));\n }\n\n const selectedStreamIds = streamsToRun.map(s => s.streamId);\n logger.info(`🥳 Syncing streams: %s`, selectedStreamIds.join(\",\"))\n\n await Bluebird.map(streamsToRun, (stream) => {\n return stream.sync();\n }, { concurrency: this.concurrency });\n\n logger.debug(`[TAP] All streams have finished syncing. We send the [complete] signal to the target.`)\n await this.target.complete();\n return Promise.resolve();\n };\n\n // Used to clean up any ressource before exit\n end(): Promise<void> {\n return Promise.resolve()\n }\n}","import isPlainObject from \"lodash/isPlainObject.js\";\n\n// Truncate potentially large query params for logging efficiency\nconst MAX_QS_KEYS = 10;\nconst MAX_QS_STRING_LENGTH = 200;\nconst MAX_QS_ARRAY_ITEMS = 5;\nconst MAX_QS_DEPTH = 2;\n\nfunction truncateQueryParams(value: any, depth: number = 0): any {\n if (value == null) return value;\n if (depth >= MAX_QS_DEPTH) return \"[…]\";\n\n if (typeof value === \"string\") {\n if (value.length <= MAX_QS_STRING_LENGTH) return value;\n const truncated = value.slice(0, MAX_QS_STRING_LENGTH);\n return `${truncated}…(+${value.length - MAX_QS_STRING_LENGTH} chars)`;\n }\n\n if (Array.isArray(value)) {\n const items = value\n .slice(0, MAX_QS_ARRAY_ITEMS)\n .map((v) => truncateQueryParams(v, depth + 1));\n const omittedCount = Math.max(0, value.length - MAX_QS_ARRAY_ITEMS);\n if (omittedCount > 0) {\n items.push(`[… ${omittedCount} more items]`);\n }\n return items;\n }\n\n if (isPlainObject(value)) {\n const keys = Object.keys(value);\n const result: Record<string, any> = {};\n for (const key of keys.slice(0, MAX_QS_KEYS)) {\n result[key] = truncateQueryParams((value as any)[key], depth + 1);\n }\n const omittedCount = Math.max(0, keys.length - MAX_QS_KEYS);\n if (omittedCount > 0) {\n (result as any)[\"__omittedKeys\"] = omittedCount;\n }\n return result;\n }\n\n return value;\n}\n\nexport function getTruncatedParamsForLog(params: any): any {\n try {\n return truncateQueryParams(params);\n } catch {\n return \"[unserializable params]\";\n }\n}","import { logger } from \"../../service/logger\";\nimport { StreamId } from \"../metadata\";\nimport { ReplicationMethod } from \"../replication\";\nimport { FlattenedSchema, InternalTableField, JSONSchemaFieldDefinition, WarehouseTableField } from \"./models\";\nimport { RenameColumnStore } from \"./renameColumnStore\";\nimport retry from 'async-retry';\n\n// This class is a Stateless interface with the APIs of a Warehouse when it comes to dealing with\n// loading a stream into a table.\n\n// TODO: Move flattenedSchema + renamedColumnStore into the StreamDbState class.\nexport abstract class StreamWarehouseSyncService {\n\n streamId: StreamId;\n database: string;\n schema: string;\n table: string;\n\n flattenedSchema: FlattenedSchema;\n primaryKeys: string[];\n maxRetryCount = 5;\n\n renamedColumnStore: RenameColumnStore;\n\n constructor(\n streamId: StreamId,\n database: string,\n schema: string,\n table: string,\n renameColumnStore: RenameColumnStore\n ) {\n this.streamId = streamId;\n this.database = database;\n this.schema = schema;\n this.table = table;\n\n this.primaryKeys = [];\n this.flattenedSchema = {};\n this.renamedColumnStore = renameColumnStore;\n }\n\n /////////////////////////////////////////////////////////////////\n ///////// Functions to be implented for each Warehouse //////////\n /////////////////////////////////////////////////////////////////\n\n // Function to adapt to the Warehouse SQL dialect\n abstract safeColumnName: (unsafe: string) => string;\n abstract getWarehouseTypeFromJSONSchema: (definition: JSONSchemaFieldDefinition) => string | undefined;\n getcolumnNameWithTypeSuffix(colName: string, warehouseType: string | undefined): string {\n return `${colName}__${warehouseType}`\n }\n // In order to not overload Warehouse, we update the destination table by chunks of columns as updating all the columns at once is generating a too complex query\n abstract getMergeQueries: () => string[]\n abstract getReplaceQueries: () => string[]\n\n // Functions to provision the tables, columns, etc.\n abstract createDatabaseAndSchemaIfNotExists: (retryCount: number) => Promise<void>;\n abstract createTable: () => Promise<void>;\n abstract addColumns: (fields: InternalTableField[]) => Promise<void>;\n\n // Functions to deal with the staging area that will be used to load data in the Warehouse\n abstract createStagingArea: () => Promise<void>;\n abstract loadStreamInStagingArea: (localFilePath: string) => Promise<void>;\n abstract deleteStagingArea: () => Promise<void>;\n\n // Function to read from the Warehouse\n abstract getTablesInSchema: () => Promise<{ tableName: string }[]>;\n abstract getTableColumnsFromWarehouse: () => Promise<WarehouseTableField[]>;\n\n // Function to execute queries on the warehouse\n abstract runQueries: (queries: string[]) => Promise<void>;\n\n // Function to serialize the record\n abstract getSerializedRecord: (record: any) => string;\n\n // Orchestration functions\n updateSchemaInWarehouse = async (\n flattenedSchema: FlattenedSchema,\n primaryKeys: string[]\n ) => {\n await this.createDatabaseAndSchemaIfNotExists(0);\n\n this.flattenedSchema = flattenedSchema;\n\n this.renamedColumnStore.computeColumnNameForStream(\n this.streamId,\n flattenedSchema\n )\n\n this.primaryKeys = primaryKeys.map(pk => {\n return this.renamedColumnStore.getColumnTranslation(this.streamId, pk)!;\n });\n\n await this.syncTableSchemaWithWarehouse();\n }\n\n renameColumns(record: any): any {\n const renamedColsRecord: any = {}\n\n Object.keys(record).forEach(originalColName => {\n renamedColsRecord[this.renamedColumnStore.getColumnTranslation(this.streamId, originalColName)!] = record[originalColName]\n })\n return renamedColsRecord;\n }\n\n // Function to execute queries on the warehouse\n protected runQueriesWithRetry = async (queries: string[]): Promise<void> => {\n await retry(\n async () => {\n await this.runQueries(queries);\n },\n {\n retries: 5,\n }\n );\n };\n\n private syncTableSchemaWithWarehouse = async () => {\n\n const tables = await this.getTablesInSchema();\n const foundTables = tables.filter(table => this.table === table.tableName);\n\n if (foundTables.length === 0) {\n logger.info(`🐣 Database: \\`${this.database}\\`, Schema: \\`${this.schema}\\`, Table: \\`${this.table}\\` does not exist in Warehouse. Creating it...`)\n await this.createTable();\n } else if (foundTables.length === 1) {\n logger.info(`👋 Database: \\`${this.database}\\`, Schema: \\`${this.schema}\\`, Table: \\`${this.table}\\` already exists. Updating the columns if needed.`);\n await this.updateTableColumns();\n }\n }\n\n /**\n * When there is a conflict between the synced data type and the data type of an\n * already existing column in the Warehouse, this create a new column in Warehouse with the new\n * datatype as suffix.\n * \n * This refer the fact that data should now be synced with the new column.\n * \n * @param tableFields \n */\n private addVersionedColumns = async (tableFields: InternalTableField[]) => {\n\n if (tableFields.length > 0) {\n logger.info(`🛂 Stream: ${this.streamId} - Versionning following columns in Warehouse schema: ${JSON.stringify(tableFields)}`)\n\n const columnsFromWarehouse = await this.getTableColumnsFromWarehouse();\n const columnNamesFromWarehouse = columnsFromWarehouse.map(col => col.name);\n\n let columnsToBeAddedInWarehouse: InternalTableField[] = [];\n tableFields.forEach(tblField => {\n const safeName = tblField.name as string;\n const warehouseTypeToBeUsed = this.getWarehouseTypeFromJSONSchema(tblField.definition)\n const columnNameWithTypeSuffix = this.getcolumnNameWithTypeSuffix(safeName, warehouseTypeToBeUsed)\n\n // Rewrite the safe mapping of the column to the versionned column\n this.renamedColumnStore.getUnsafeToSafeColumnMapping(this.streamId)[tblField.unsafeName] = columnNameWithTypeSuffix;\n\n if (!columnNamesFromWarehouse.includes(columnNameWithTypeSuffix)) {\n columnsToBeAddedInWarehouse.push({\n unsafeName: columnNameWithTypeSuffix,\n name: columnNameWithTypeSuffix,\n definition: tblField.definition\n })\n }\n })\n\n if (columnsToBeAddedInWarehouse.length > 0) {\n await this.addColumns(columnsToBeAddedInWarehouse);\n }\n }\n }\n\n private updateTableColumns = async () => {\n\n const columnsFromWarehouse = await this.getTableColumnsFromWarehouse();\n const columnNamesFromWarehouse = columnsFromWarehouse.map(col => col.name);\n\n const columnsMappingStore = this.renamedColumnStore.getUnsafeToSafeColumnMapping(this.streamId);\n const columnsToAdd: InternalTableField[] = Object.keys(columnsMappingStore)\n .filter(unsafeColumnKey => {\n const safeColumnName = columnsMappingStore[unsafeColumnKey];\n if (!safeColumnName) {\n return false;\n }\n return !columnNamesFromWarehouse.includes(safeColumnName);\n })\n .map(unsafeColumnKey => {\n const safeColumnName = columnsMappingStore[unsafeColumnKey];\n const definition = this.flattenedSchema[unsafeColumnKey];\n if (!safeColumnName || !definition) {\n return undefined as unknown as InternalTableField;\n }\n return {\n unsafeName: unsafeColumnKey,\n name: safeColumnName,\n definition\n }\n })\n .filter((item): item is InternalTableField => !!item)\n\n await this.addColumns(columnsToAdd);\n\n const columnsToVersion: InternalTableField[] = Object.keys(this.flattenedSchema)\n // We keep only the columns already declared in Warehouse but with a different type\n .filter(unsafeColumnKey => {\n const definition = this.flattenedSchema[unsafeColumnKey];\n if (!definition) {\n return false;\n }\n const warehouseTypeToBeUsed = this.getWarehouseTypeFromJSONSchema(definition)\n if (warehouseTypeToBeUsed) {\n const safeName = this.safeColumnName(unsafeColumnKey);\n if (columnNamesFromWarehouse.includes(safeName)) {\n const columnFromWarehouse = columnsFromWarehouse.find(col => col.name === safeName);\n\n if (!columnFromWarehouse) {\n throw new Error(`We can't find in Warehouse schema any column definition for colName: ${safeName}`);\n }\n\n const { type } = columnFromWarehouse;\n\n if (warehouseTypeToBeUsed !== type) {\n return true;\n }\n }\n }\n return false;\n })\n .map(unsafeColumnKey => {\n const definition = this.flattenedSchema[unsafeColumnKey];\n if (!definition) {\n return undefined as unknown as InternalTableField;\n }\n return {\n unsafeName: unsafeColumnKey,\n name: this.safeColumnName(unsafeColumnKey),\n definition\n }\n })\n .filter((tableField): tableField is InternalTableField => !!tableField);\n\n await this.addVersionedColumns(columnsToVersion);\n\n }\n\n mergeTempTableWithDestination = async (\n replicationMethod: ReplicationMethod\n ) => {\n\n let mergeQueries: string[] = [];\n if (replicationMethod === \"FULL_TABLE\") {\n mergeQueries = this.getReplaceQueries();\n } else if (replicationMethod === \"INCREMENTAL\") {\n mergeQueries = this.getMergeQueries();\n } else if (replicationMethod === \"LOG_BASED\") {\n mergeQueries = this.getMergeQueries();\n }\n\n logger.info(`🍆 Table=${this.table} - Merging staging data with method ${replicationMethod}`);\n logger.debug(`Table=${this.table} - Merge queries: %j`, mergeQueries);\n\n await this.runQueriesWithRetry(mergeQueries);\n\n }\n\n}","import { ValidationError } from \"jsonschema\";\nimport { StreamId } from \"../metadata\";\n\nexport class SchemaValidationError extends Error {\n\n streamId: StreamId;\n validationErrors: ValidationError[];\n\n constructor(message: string, streamId: StreamId, errors: ValidationError[]) {\n super(message); // (1)\n this.name = \"SchemaValidationError\"; // (2)\n this.streamId = streamId;\n this.validationErrors = errors;\n }\n\n}\n\nexport class MissingFieldInSchemaError extends Error {\n\n streamId: StreamId;\n\n constructor(message: string, streamId: StreamId) {\n super(message); // (1)\n this.name = \"MissingFieldInSchemaError\"; // (2)\n this.streamId = streamId;\n }\n\n}\n\nexport class MissingSchemaError extends Error {\n\n streamId: StreamId;\n\n constructor(message: string, streamId: StreamId) {\n super(message); // (1)\n this.name = \"MissingSchemaError\"; // (2)\n this.streamId = streamId;\n }\n\n}","import { FlattenedSchema } from \"./models\";\n\nexport const removeParasiteProperties = (record: any, schema: FlattenedSchema) => {\n const schemaKeys = Object.keys(schema);\n Object.keys(record).forEach(key => {\n if (!schemaKeys.includes(key)) {\n delete record[key]\n }\n })\n\n return record;\n}\n\nexport const addWhalyFields = (record: any, batchDate: string) => {\n return {\n ...record,\n _whaly_synced: batchDate\n }\n}","import { logger } from \"../../service/logger\";\nimport { FlattenedSchema } from \"./models\";\n\n// { \"streamId\": { \"originalColumnName\": \"renamedColumnName\" } }\nexport interface ColumnMappingStoreUnsafeToSafe {\n [originalColumnName: string]: string\n}\n\nexport type SafeColumnNameConverterFn = (unsafe: string) => string\n\n/**\n * This stateful class is to be used to store all the columns names mapping between the \"raw\" column name\n * found in the records and the destination column in the data warehouse\n * \n * A mapping exists between the fields declared by the Tap and the reality in the Warehouse for those reasons:\n * - Columns that are versionned due to type changes since the last load\n * - Columns that have a name conflict after \"Warehouse\" sanitization\n */\nexport class RenameColumnStore {\n\n // Store all the mappings store for all streamId\n private renamedColumns: { [streamId: string]: ColumnMappingStoreUnsafeToSafe };\n\n private safeColumnNameConverter?: SafeColumnNameConverterFn;\n\n constructor() {\n this.renamedColumns = {};\n }\n\n setSafeColumnNameConverter = (fn: SafeColumnNameConverterFn): void => {\n this.safeColumnNameConverter = fn;\n }\n\n // This function has a side effect on:\n // - `this.renamedColumns`\n // This isn't very clean and should be updated to write a pure version of this function\n computeColumnNameForStream = (\n streamId: string,\n flattenedSchema: FlattenedSchema,\n ) => {\n const safeColNameConv = this.safeColumnNameConverter;\n if (!safeColNameConv) {\n throw new Error(`safeColumnNameConverter is not defined!`)\n }\n const colSafeToUnsafeMapping = Object.keys(flattenedSchema)\n .sort()\n .reduce<{ [safeColName: string]: string }>((acc, unsafeColName) => {\n const safeColName = safeColNameConv(unsafeColName);\n if (!acc[safeColName]) {\n acc[safeColName] = unsafeColName;\n } else {\n logger.info(`🚨 Stream: ${streamId} - We have a column name conflict after sanitization for column unsafe=${unsafeColName}. We'll rename the sanitized name to a non taken name.\n Details: unsafeColName=${unsafeColName} is colliding with: ${acc[safeColName]}`)\n for (let i = 1; ; i++) {\n if (!acc[`${safeColName}_${i}`]) {\n acc[`${safeColName}_${i}`] = unsafeColName;\n break;\n }\n }\n }\n return acc;\n }, {});\n\n const colUnsafeToSafeMapping = Object.keys(colSafeToUnsafeMapping)\n .reduce<{ [unssafeColName: string]: string }>((acc, safeColName) => {\n const unsafeColname = colSafeToUnsafeMapping[safeColName];\n if (unsafeColname) {\n acc[unsafeColname] = safeColName;\n }\n return acc;\n }, {})\n\n // Init the renamedColumns dict\n const mapping = this.renamedColumns[streamId] || {};\n this.renamedColumns[streamId] = mapping;\n Object.keys(colUnsafeToSafeMapping).forEach(unsafeColName => {\n const safeName = colUnsafeToSafeMapping[unsafeColName];\n if (safeName) {\n mapping[unsafeColName] = safeName;\n }\n });\n }\n\n getColumnTranslation = (\n streamId: string,\n originalColumnName: string\n ): string => {\n if (!this.renamedColumns[streamId]) {\n throw new Error(\n `StreamId=${streamId} - Columns Mapping Store is not initialized! \n Trying to get renamed value for column '${originalColumnName}'`\n )\n }\n const value = this.renamedColumns[streamId][originalColumnName];\n if (!value) {\n throw new Error(`StreamId=${streamId} - No renamed value found for column '${originalColumnName}'`)\n }\n return value;\n }\n\n getUnsafeToSafeColumnMapping = (streamId: string): ColumnMappingStoreUnsafeToSafe => {\n const mapping = this.renamedColumns[streamId];\n if (!mapping) {\n throw new Error(`StreamId=${streamId} - Columns Mapping Store is not initialized!`)\n }\n return mapping;\n }\n\n isReady = (streamId: string): boolean => {\n if (!this.renamedColumns[streamId]) {\n return false;\n } else {\n return true;\n }\n }\n}","import { StreamId } from \"../metadata\";\nimport { FlattenedSchema } from \"./models\";\nimport { logger } from \"../../service/logger\";\nimport { gracefulExit } from \"../../service/exit\";\n\nexport const flattenSchema = <T>(streamId: StreamId, schema: T): FlattenedSchema => {\n\n logger.debug(`Flattening schema for stream: ${streamId}`)\n\n try {\n const mSchema = schema as any;\n\n if (!mSchema[\"properties\"]) {\n return {};\n }\n\n const properties = mSchema[\"properties\"];\n\n const flattenedSchema = Object.keys(properties).reduce<FlattenedSchema>((acc, propertyName) => {\n const propertySchema = properties[propertyName];\n const columnName = propertyName;\n\n if (!propertySchema) {\n return acc;\n }\n\n if (!propertySchema[\"type\"]) {\n throw new Error(`We don't have any \\`type\\` for the property: \\`${propertyName}\\`.\n Schema of the property is: ${JSON.stringify(propertySchema)}`)\n }\n\n acc[columnName] = {\n type: propertySchema[\"type\"],\n format: propertySchema[\"format\"],\n items: propertySchema[\"items\"]\n };\n\n return acc;\n }, {});\n\n return flattenedSchema;\n } catch (err: any) {\n logger.error(`There was an error when processing the schema of stream:\\`${streamId}\\`: err: ${err.message} - ${err.stack}.\n Processed schema: ${JSON.stringify(schema)}`);\n gracefulExit(1);\n return {};\n }\n\n}","import { ReplicationMethodMessage, RecordMessage, SchemaMessage, StateMessage } from \"../messages\";\nimport { TargetSchemaHook, TargetSchemaHookInput } from \"./targetHook\";\nimport { Validator } from \"jsonschema\";\nimport dayjs, { Dayjs } from \"dayjs\";\nimport { RenameColumnStore, SafeColumnNameConverterFn } from \"./renameColumnStore\";\nimport { StreamState } from \"./streamDbState\";\nimport { logger } from \"../../service/logger\";\nimport { MissingSchemaError, SchemaValidationError } from \"./error\";\nimport { addWhalyFields, removeParasiteProperties } from \"./record\";\nimport { BaseConfig, FlattenedSchema } from \"./models\";\nimport { flattenSchema } from \"./schema\";\nimport { StreamWarehouseSyncService } from \"./dbSync\";\nimport { Semaphore } from \"async-mutex\";\nimport { ReplicationMethod } from \"../replication\";\nimport Bluebird from \"bluebird\";\nimport { StateProvider } from \"../state-provider/types\";\nimport { StreamId } from \"../metadata\";\n\nconst semaphore = new Semaphore(1);\n\nexport abstract class ITarget<C extends BaseConfig = BaseConfig> {\n config: C;\n schemaHooks: TargetSchemaHook[]\n syncTime: Dayjs;\n stateProvider: StateProvider;\n\n // Latest state message received from the Tap\n // Not yet flushed as we didn't upload the stream data since receiving it \n batchedState: any;\n\n // Latest \"flushed\" state message\n // A state message is flushed when we do a stream upload.\n flushedState: any;\n\n renameColumnStore: RenameColumnStore;\n\n streams: {\n [streamName: string]: StreamState\n }\n\n // JSON Schema validator\n validator: Validator\n\n constructor(config: C, stateProvider: StateProvider) {\n this.config = config;\n this.stateProvider = stateProvider;\n this.schemaHooks = [];\n\n this.streams = {}\n\n this.batchedState = {}\n this.flushedState = {}\n\n this.validator = new Validator();\n this.syncTime = dayjs();\n\n this.renameColumnStore = new RenameColumnStore()\n }\n\n ///////////////////////////////////////////\n //// To be overriden by child classes /////\n ///////////////////////////////////////////\n static requiredConfigKeys: string[] = [];\n // Generate instance of DBSync\n abstract newDBSyncInstance: (\n streamId: StreamId,\n database: string,\n schema: string,\n table: string\n ) => StreamWarehouseSyncService;\n // Function to render safe table names\n abstract genTableName: (streamId: string) => string;\n // Function to render safe column names\n abstract safeColumnNameConverter: SafeColumnNameConverterFn;\n // Convert the date values of a record into valid ones for the Warehouse\n abstract validateDateRange: (reacord: any, schema: FlattenedSchema) => any;\n // Convert the number values of a record into valid ones for the Warehouse\n abstract convertNumberIntoDecimal: (record: any, schema: FlattenedSchema) => any;\n\n ////////////////////////////////////////////\n /////////// Implementation /////////////////\n ////////////////////////////////////////////\n\n // Analyze schema changes to determine if they are breaking or non-breaking\n private analyzeSchemaChanges = (\n previousSchema: FlattenedSchema,\n newSchema: FlattenedSchema,\n streamId: string\n ): { hasBreakingChanges: boolean; changes: string[] } => {\n const changes: string[] = [];\n let hasBreakingChanges = false;\n\n // Get all column names from both schemas\n const prevColumns = new Set(Object.keys(previousSchema).filter(col => !col.startsWith(\"_whaly\")));\n const newColumns = new Set(Object.keys(newSchema).filter(col => !col.startsWith(\"_whaly\")));\n\n // Check for new columns (non-breaking)\n for (const columnName of newColumns) {\n if (!prevColumns.has(columnName)) {\n changes.push(`Added column '${columnName}'`);\n }\n }\n\n // Check for removed columns (breaking)\n for (const columnName of prevColumns) {\n if (!newColumns.has(columnName)) {\n changes.push(`Removed column '${columnName}'`);\n hasBreakingChanges = true;\n }\n }\n\n // Check for type changes in existing columns (breaking)\n for (const columnName of prevColumns) {\n if (newColumns.has(columnName)) {\n const prevType = previousSchema[columnName];\n const newType = newSchema[columnName];\n\n // Compare the type definitions\n if (JSON.stringify(prevType) !== JSON.stringify(newType)) {\n changes.push(`Changed type of column '${columnName}'`);\n hasBreakingChanges = true;\n }\n }\n }\n\n if (changes.length === 0) {\n changes.push('No schema changes detected');\n }\n\n logger.debug(`StreamId=${streamId} - Schema analysis: ${hasBreakingChanges ? 'BREAKING' : 'NON-BREAKING'} changes found: ${changes.join(', ')}`);\n\n return { hasBreakingChanges, changes };\n }\n\n // Serialize a RECORD message into a line that will be uploaded in the staging area\n getSerializedRecord = (streamId: string, record: any): string => {\n const stream = this.streams[streamId];\n if (!stream) {\n throw new MissingSchemaError(`A record for stream:\\`${streamId}\\` was encountered before a corresponding schema.`, streamId)\n }\n return stream.getDbSync().getSerializedRecord(record)\n }\n\n record = async (message: RecordMessage): Promise<void> => {\n try {\n\n const streamId = message.stream;\n const stream = this.streams[streamId];\n\n if (!stream) {\n throw new MissingSchemaError(`A record for stream:\\`${streamId}\\` was encountered before a corresponding schema.`, streamId)\n }\n\n // To avoid getting any conflicts when loading data in the warehouse, we run a semaphore to have a concurrency of 1\n await semaphore.runExclusive(async () => {\n const shouldUploadIntermediateBatch = this.shouldUploadIntermediateBatch(streamId)\n if (shouldUploadIntermediateBatch) {\n await this.loadAllStreamsInWarehouse({ isFinalLoad: false })\n }\n })\n\n const record = message.record;\n const schema = stream.getSchema();\n\n if (!schema) {\n logger.warn(`Stream: ${streamId} - Received a RECORD message while schema is undefined. Dropping message.`)\n return;\n }\n\n const recordWithoutParasiteProperties = removeParasiteProperties(record, schema);\n\n const recordWithWhalyFields = addWhalyFields(recordWithoutParasiteProperties, stream.getBatchDate());\n\n // Checking that the RECORD is valid compared to the previously received SCHEMA\n const validationResult = this.validator.validate(recordWithWhalyFields, schema);\n if (!validationResult.valid) {\n throw new SchemaValidationError(`Stream: ${streamId} - Record is not valid according to schema.\n Validation errors: ${JSON.stringify(validationResult.errors)}\n\n Record: ${JSON.stringify(recordWithoutParasiteProperties)}\n Schema: ${JSON.stringify(stream.getSchema())}`, streamId, validationResult.errors)\n }\n\n // Making sure that the date are in valid range supported by Warehouse\n const recordWithValidDate = this.validateDateRange(recordWithWhalyFields, schema);\n // Working with Decimal.js is better as the JS `number` type is quite imprecise\n const recordWithDecimal = this.convertNumberIntoDecimal(recordWithValidDate, schema)\n\n // Columns should be renamed to:\n // - Be \"safe\" for Warehouse\n // - Handle the case where there are conflicts in column names after sanitization\n // - There is a column versionning due to a column type change since the last sync\n const dbSyncInstance = stream.getDbSync();\n const recordWithrenamedColumns = dbSyncInstance.renameColumns(recordWithDecimal);\n\n const serializedRecord = this.getSerializedRecord(streamId, recordWithrenamedColumns);\n\n return new Promise((resolve, reject) => {\n stream.getFileToLoad().stream.write(serializedRecord, (error) => {\n if (error) {\n reject(error);\n }\n\n stream.incrementBatchedRowCount();\n resolve();\n });\n })\n\n } catch (err) {\n logger.error(`Error when handling \"record\" message`);\n throw err;\n }\n }\n\n private initStreamStateAndSyncService(\n streamId: string,\n replicationMethod?: ReplicationMethod\n ): void {\n const dbSyncInstance = this.newDBSyncInstance(\n streamId,\n this.config.database,\n this.config.schema,\n this.genTableName(streamId)\n )\n this.streams[streamId] = new StreamState(\n streamId,\n dbSyncInstance,\n replicationMethod || ReplicationMethod.FULL_TABLE\n );\n }\n\n replicationMethod = (message: ReplicationMethodMessage): void => {\n\n try {\n logger.info(`👈 Received replicationMethod message: %j`, message)\n const streamId = message.stream;\n if (!this.streams[streamId]) {\n this.initStreamStateAndSyncService(streamId, message.replication)\n } else {\n this.streams[streamId].setReplicationMethod(message.replication);\n }\n } catch (err) {\n logger.error(`Error when handling \"replicationMethod\" event`)\n throw err;\n }\n }\n\n schema = async (message: SchemaMessage): Promise<void> => {\n\n try {\n const streamId = message.stream;\n\n logger.info(`Stream: ${streamId} - Got a SCHEMA message from the tap`);\n logger.debug(`Stream: ${streamId} - Got a SCHEMA message from the tap: %j`, message);\n\n if (!this.streams[streamId]) {\n this.initStreamStateAndSyncService(streamId)\n } else {\n // Load the previous batched data as there can be schema changes\n const prevStreamState = this.streams[streamId];\n if (prevStreamState.batchedRowCount > 0) {\n const prevSchema = prevStreamState.getSchema();\n if(prevSchema) {\n // Flatten the new schema to compare with the previous one\n const newFlattenedSchema = flattenSchema(streamId, message.schema);\n // Check if schema changes are breaking or non-breaking\n const { hasBreakingChanges, changes } = this.analyzeSchemaChanges(prevSchema, newFlattenedSchema, streamId);\n if (hasBreakingChanges) {\n logger.info(`🔥 StreamId=${streamId} - Detected BREAKING schema changes: ${changes.join(', ')}. Loading batched records before applying new schema.`);\n await ITarget.uploadSingleStreamToWarehouse(prevStreamState);\n } else {\n logger.info(`✅ StreamId=${streamId} - Detected NON-BREAKING schema changes: ${changes.join(', ')}. Continuing without uploading batched records.`);\n }\n }\n }\n }\n\n const streamState = this.streams[streamId];\n if (!streamState) {\n throw new MissingSchemaError(`Stream: ${streamId} - Received SCHEMA message before stream state was initialized.`, streamId)\n }\n const schema = flattenSchema(streamId, message.schema);\n\n // Add Whaly specific columns\n schema[\"_whaly_synced\"] = {\n format: \"date-time\",\n type: [\"null\", \"string\"]\n }\n\n const dbSync = streamState.getDbSync();\n Object.keys(schema).forEach(fieldUnsafeKey => {\n // Remove the key associated to no warehouse type\n const fieldDef = schema[fieldUnsafeKey];\n const targetWarehouseType = fieldDef ? dbSync.getWarehouseTypeFromJSONSchema(fieldDef) : undefined;\n\n if (!targetWarehouseType) {\n delete schema[fieldUnsafeKey]\n }\n })\n\n streamState.setSchema(schema);\n\n if (message.keyProperties.length === 0) {\n throw new Error(`StreamId: ${message.stream} - \\`key_properties\\` field is required and can't be empty in SCHEMA message.\n Received SCHEMA message: ${JSON.stringify(message)}`)\n }\n\n streamState.setKeyProperties(message.keyProperties);\n\n await dbSync.updateSchemaInWarehouse(schema, message.keyProperties);\n\n const {\n database: databaseName,\n schema: schemaName\n } = this.config;\n\n const tableName = this.genTableName(streamId);\n\n const formattedRelationshipMessage: SchemaMessage = {\n ...message,\n keyProperties: message.keyProperties.map(k => {\n const translation = streamState.getDbSync().renamedColumnStore.getColumnTranslation(message.stream, k);\n if (translation) {\n return translation;\n }\n return k\n })\n }\n\n await Bluebird.map(this.schemaHooks, async (hook) => {\n const input: TargetSchemaHookInput = {\n databaseName,\n schemaName,\n tableName,\n message: formattedRelationshipMessage,\n }\n await hook.writeSchema(input);\n }, { concurrency: 3 })\n\n return Promise.resolve();\n } catch (err) {\n logger.error(`Error when handling schema event.`, err)\n throw err;\n }\n }\n\n state = (message: StateMessage): Promise<void> => {\n\n try {\n this.batchedState = message.value;\n\n if (!this.flushedState) {\n this.flushedState = Object.assign({}, this.state);\n }\n return Promise.resolve()\n } catch (err) {\n logger.error(`Error while handling state event.`)\n throw err;\n }\n }\n\n complete = async (): Promise<void> => {\n\n try {\n logger.info(`👍 Data Extraction is complete. Will load remaining batched stream records.`)\n\n await this.loadAllStreamsInWarehouse({ isFinalLoad: true });\n return Promise.resolve();\n } catch (err) {\n logger.error(`Error while handling complete event.`)\n throw err;\n }\n }\n\n private shouldUploadIntermediateBatch = (streamId: string): boolean => {\n const stream = this.streams[streamId];\n if (!stream) {\n return false;\n }\n const batchedRecords = stream.getBatchedRowCount()\n if (stream.getReplicationMethod() === \"INCREMENTAL\" && batchedRecords > 1_000_000) {\n logger.info(`🧊 Stream=${streamId} has reached the maximum amount of batched records. We'll trigger a flush of ALL streams in the Warehouse.`)\n return true;\n } else {\n return false;\n }\n }\n\n private loadAllStreamsInWarehouse = async (opts: { isFinalLoad: boolean }): Promise<void> => {\n logger.info(`🚛🚛🚛 Loading ALL Streams in Warehouse.`)\n const { isFinalLoad } = opts;\n const streamsWithRemainingRecords = Object\n .keys(this.streams)\n .filter(streamId => {\n // FULL TABLE streams are removed from the load if it's not the final load\n const s = this.streams[streamId];\n if (!s) {\n return false;\n }\n if (!isFinalLoad && s.getReplicationMethod() === \"FULL_TABLE\") {\n return false;\n }\n return s.getBatchedRowCount() > 0\n });\n\n if (streamsWithRemainingRecords.length > 0) {\n this.flushedState = await this.uploadStreamsToWarehouse(streamsWithRemainingRecords)\n }\n\n if (Object.keys(this.flushedState).length > 0) {\n await this.emitState(Object.assign({}, this.flushedState))\n // Special case where nothing was written in the warehouse (nothing to sync then)\n // We keep the previous state\n } else {\n await this.emitState(Object.assign({}, this.state))\n }\n }\n\n private emitState = (state: any): Promise<void> => {\n return this.stateProvider.writeState(JSON.stringify(state));\n }\n\n private uploadStreamsToWarehouse = async (\n streamsToUpload: string[]\n ) => {\n\n try {\n await Bluebird.map(streamsToUpload, async (streamId) => {\n logger.info(`📤 Upload stream: ${streamId} to Warehouse`)\n const streamState = this.streams[streamId];\n if (streamState) {\n await ITarget.uploadSingleStreamToWarehouse(streamState)\n }\n }, { concurrency: 3 });\n\n return this.batchedState;\n } catch (err) {\n logger.error(`Error while uploading all streams + merging them.`)\n throw err;\n }\n }\n\n static uploadSingleStreamToWarehouse = async (\n streamState: StreamState\n ) => {\n\n const dbSync = streamState.getDbSync();\n\n try {\n const replicationMethod = streamState.getReplicationMethod();\n const fileToLoad = streamState.getFileToLoad();\n\n await dbSync.createStagingArea();\n await dbSync.loadStreamInStagingArea(fileToLoad.path);\n await dbSync.mergeTempTableWithDestination(replicationMethod);\n await dbSync.deleteStagingArea();\n streamState.setHasBeenLoadedYet();\n streamState.resetFileToLoad();\n } catch (err) {\n if (err instanceof Error) {\n logger.error(`StreamId=${dbSync.streamId} - Couldn't upload stream due to an error: %s`, err.message);\n throw err;\n } else {\n throw new Error('Unknown error')\n }\n }\n }\n}","import dayjs, { Dayjs } from \"dayjs\";\nimport { defaultDateTimeFormat } from \"../../constants/date\";\nimport { StreamId } from \"../metadata\";\nimport { ReplicationMethod } from \"../replication\";\nimport { StreamWarehouseSyncService } from \"./dbSync\";\nimport { FlattenedSchema, TempFile } from \"./models\";\nimport { createTemporaryFileStream } from \"./temporaryFile\";\nimport * as fs from \"fs\";\n\n// This class is here to manage the State of a stream being loaded into a Warehouse\nexport class StreamState {\n streamId: StreamId;\n schema?: FlattenedSchema;\n dbSync: StreamWarehouseSyncService;\n\n batchDate: Dayjs;\n\n // Count rows batched in the local file, waiting for Warehouse upload\n batchedRowCount: number;\n // Local CSV files written to be sent to Warehouse\n fileToLoad: TempFile;\n // Count rows sent to Warehouse\n syncedRowCount: number;\n keyProperties: string[];\n\n // When a FULL_TABLE stream is loaded multiple times, the query used for the 2nd+ loads\n // needs to be different than the 1st merge query -> 1st load is dropping the existing table, 2nd+ loads are merging with the existing table (otherwise the previous load data are dropped)\n // So we need to keep track of whether we are at the first load or not\n _hasBeenLoadedYetDuringThisSync: boolean\n\n replicationMethod: ReplicationMethod\n\n constructor(\n streamId: StreamId, \n dbSync: StreamWarehouseSyncService, \n replicationMethod: ReplicationMethod, \n ) {\n this.streamId = streamId;\n this.dbSync = dbSync;\n\n this.batchedRowCount = 0;\n this.fileToLoad = createTemporaryFileStream(streamId);\n this.syncedRowCount = 0;\n this.keyProperties = [];\n this.batchDate = dayjs();\n this.replicationMethod = replicationMethod;\n this._hasBeenLoadedYetDuringThisSync = false;\n }\n\n setSchema(schema: FlattenedSchema) {\n this.schema = schema;\n }\n\n getSchema(): FlattenedSchema | undefined {\n return this.schema;\n }\n\n getBatchDate(): string {\n return this.batchDate.format(defaultDateTimeFormat);\n }\n\n getBatchedRowCount(): number {\n return this.batchedRowCount;\n }\n\n incrementBatchedRowCount() {\n this.batchedRowCount += 1;\n }\n\n getFileToLoad(): TempFile {\n return this.fileToLoad;\n }\n\n resetFileToLoad() {\n this.fileToLoad.stream.close();\n const oldPath = this.fileToLoad.path;\n // Delete the old file to make some space\n fs.unlinkSync(oldPath);\n this.fileToLoad = createTemporaryFileStream(this.streamId);\n this.batchedRowCount = 0;\n }\n\n getKeyProperties(): string[] {\n return this.keyProperties;\n }\n\n setKeyProperties(keyProperties: string[]) {\n this.keyProperties = keyProperties\n }\n\n getDbSync(): StreamWarehouseSyncService {\n return this.dbSync\n }\n\n getReplicationMethod(): ReplicationMethod {\n return this.replicationMethod\n }\n\n setReplicationMethod(r: ReplicationMethod) {\n this.replicationMethod = r;\n }\n\n setHasBeenLoadedYet() {\n this._hasBeenLoadedYetDuringThisSync = true;\n }\n}","import fs from 'fs-extra';\nimport uniqueId from 'lodash/uniqueId.js';\nimport { StreamId } from '../metadata';\nimport { TempFile } from './models';\n\nexport const createTemporaryFileStream = (streamId: StreamId): TempFile => {\n fs.ensureDirSync(\"./tmp\")\n const path = `./tmp/${safePath(streamId)}-${uniqueId()}.tmp`;\n const writeStream = fs.createWriteStream(path, {flags: \"w\"});\n\n return {\n stream: writeStream,\n path\n };\n}\n\nexport function safePath(path: string): string {\n let formattedPath = path;\n formattedPath = formattedPath.replace(/^The\\s+/gi, '');\n formattedPath = formattedPath.replace(/\\s+(?:\\(|\\[)?Dis(?:c|k) (?:One|Two|Three|Four|Five|Six|Seven|Eight|Nine|Ten|\\d)+(?:\\)|\\])?/gi, '');\n formattedPath = formattedPath.replace(/\\s+/gi, '_');\n formattedPath = formattedPath.replace(/(?:\\'|`)/gi, '');\n formattedPath = replaceAccented(formattedPath);\n formattedPath = replaceSymbols(formattedPath);\n formattedPath = formattedPath.replace(/(?:[^a-z0-9])+/gi, '_');\n\n return formattedPath;\n};\n\nfunction replaceAccented(str: string) {\n str = str.replace(/(?:\\xC0|\\xC1|\\xC2|\\xC3|\\xC4|\\xC5)/g, 'A');\n str = str.replace(/(?:\\xC7)/g, 'C');\n str = str.replace(/(?:\\xC8|\\xC9|\\xCA|\\xCB)/g, 'E');\n str = str.replace(/(?:\\xCC|\\xCD|\\xCE|\\xCF)/g, 'I');\n str = str.replace(/(?:\\xD2|\\xD3|\\xD4|\\xD6|\\xD5)/g, 'O');\n str = str.replace(/(?:\\xD9|\\xDA|\\xDB|\\xDC)/g, 'U');\n str = str.replace(/(?:\\xDD|\\x9F)/g, 'Y');\n str = str.replace(/(?:\\xD1)/g, 'N');\n str = str.replace(/(?:\\xC6)/g, 'Ae');\n str = str.replace(/(?:\\xDF)/g, 'ss');\n str = str.replace(/(?:\\xE0|\\xE1|\\xE2|\\xE4|\\xE5|\\xE3)/g, 'a');\n str = str.replace(/(?:\\xE7)/g, 'c');\n str = str.replace(/(?:\\xE8|\\xE9|\\xEA|\\xEB)/g, 'e');\n str = str.replace(/(?:\\xEC|\\xED|\\xEE|\\xEF)/g, 'i');\n str = str.replace(/(?:\\xF2|\\xF3|\\xF4|\\xF6|\\xF5)/g, 'o');\n str = str.replace(/(?:\\xF9|\\xFA|\\xFB|\\xFC)/g, 'u');\n str = str.replace(/(?:\\xFD|\\xFF)/g, 'y');\n str = str.replace(/(?:\\xF1)/g, 'n');\n str = str.replace(/(?:\\xE6)/g, 'ae');\n return str;\n}\n\nfunction replaceSymbols(str: string) {\n str = str.replace(/(?:\\(|\\))/g, '');\n str = str.replace(/(?:\\.|\\?)/g, '');\n str = str.replace(/(?:_+)/g, '_');\n str = str.replace(/(?:\\$+)/g, 's');\n return str;\n}","// https://cloud.google.com/bigquery/docs/schemas#column_names\nexport const safeColumnName = (key: string): string => {\n\n let returnString = key;\n // Remove unsupported prefix\n const shouldNotStartWith = [\"_TABLE_\", \"_FILE_\", \"_PARTITION\"]\n shouldNotStartWith.forEach(snm => {\n if (returnString.startsWith(snm)) {\n returnString = returnString.replace(snm, \"\")\n }\n })\n\n // remove begining numeric characters\n returnString = returnString.replace(/^[-\\d\\s]*/g, \"\")\n\n // Go in lowercase\n returnString = returnString.toLowerCase()\n\n // Remove ticks\n returnString = returnString.replace('`', '')\n\n // Remove accents in a nice way\n returnString = returnString.normalize(\"NFD\").replace(/[\\u0300-\\u036f]/g, \"\")\n\n // Trim to first 300 characters\n if (returnString.length > 300) {\n returnString = returnString.substr(0, 300);\n }\n\n // Remove non alphabetic characters\n const pattern = /[^a-zA-Z0-9_]/gm\n return returnString.replace(pattern, '_');\n}\n\n// https://cloud.google.com/bigquery/docs/tables#table_naming\nexport const safeTableName = (key: string) => {\n\n let returnString = key;\n\n // Go in lowercase\n returnString = returnString.toLowerCase()\n\n // Remove ticks\n returnString = returnString.replace('`', '')\n\n // Remove accents in a nice way\n returnString = returnString.normalize(\"NFD\").replace(/[\\u0300-\\u036f]/g, \"\")\n\n // Trim to first 300 characters\n if (returnString.length > 1024) {\n returnString = returnString.substr(0, 1024);\n }\n\n // Remove non alphabetic characters\n const pattern = /[^a-zA-Z0-9_]/gm\n return returnString.replace(pattern, '_');\n}","import Decimal from \"decimal.js\";\nimport dayjs from \"dayjs\";\nimport { defaultDateTimeFormat } from \"../../../sdk/constants/date\";\nimport { FlattenedSchema } from \"../../../sdk/models/target/models\";\nimport { logger } from \"../../../sdk/service/logger\";\n\n//TODO: Check that the date-time are in the BigQuery limits\n// Eg. From 0001-01-01 00:00:00 to 9999-12-31 23:59:59.999999\nexport const validateDateRange = (record: any, schema: FlattenedSchema): any => {\n\n Object.keys(schema).forEach(key => {\n const { format } = schema[key];\n\n if (format === \"date-time\") {\n if (record[key]) {\n const formattedDate = dayjs(record[key]).format(defaultDateTimeFormat);\n // sometimes we have dayjs that cannot convert a value that seemed appropriate previously so we need to skip it\n // ie: in the tap we had as an output from dayjs \"20222-07-01T00:00:00.000000+00:00\"\n // and reading it back in the target gives \"Invalid date\"\n\n // we also need to check it the date is greater that the limit in order to avoid chaos\n const isNotTooMuchInTheFuture = dayjs(record[key]).isBefore(dayjs(\"9999-12-31 23:59:59.999999\"));\n const isNotTooMuchInThePast = dayjs(record[key]).isAfter(dayjs(\"0001-01-01 00:00:00\"))\n if (formattedDate !== \"Invalid date\" && isNotTooMuchInTheFuture && isNotTooMuchInThePast) {\n record[key] = formattedDate\n } else {\n record[key] = undefined;\n logger.info(\"Skipping date for key %s for being invalid\", key)\n }\n }\n }\n\n })\n\n return record;\n}\n\nexport const maxBQNumericValue = new Decimal(\"9.9999999999999999999999999999999999999E+28\");\n\nexport const convertNumberIntoDecimal = (record: any, schema: FlattenedSchema) => {\n Object.keys(record).forEach(key => {\n\n if (schema[key]) {\n const { type, items } = schema[key];\n const types = type instanceof Array ? type : [type];\n\n if (types.includes(\"number\")) {\n if (typeof record[key] === 'number' || record[key] instanceof Decimal) {\n const decimal = new Decimal(record[key]).toDecimalPlaces(9);\n if (decimal.greaterThanOrEqualTo(maxBQNumericValue)) {\n record[key] = null;\n } else {\n record[key] = decimal;\n }\n } else {\n record[key] = null;\n }\n } else if(types.includes(\"array\") && items?.type.includes(\"number\")) {\n if (Array.isArray(record[key])) {\n const rawArr = record[key];\n const newArr = rawArr.map((item: any) => {\n if(typeof item === 'number' || item instanceof Decimal) {\n const parsed = new Decimal(item).toDecimalPlaces(9);\n if (parsed.greaterThanOrEqualTo(maxBQNumericValue)) {\n return undefined\n } else {\n return parsed;\n }\n } else {\n return undefined;\n }\n }).filter((item: any) => !!item);\n record[key] = newArr;\n } else {\n record[key] = null;\n }\n }\n }\n })\n\n return record;\n}","import { StreamId } from \"../../../sdk/models/metadata\";\nimport { logger } from \"../../../sdk/service/logger\";\nimport { Dataset, TableMetadata, TableField, Table, BigQuery, JobLoadMetadata } from \"@google-cloud/bigquery\";\nimport dayjs from \"dayjs\";\nimport { BqClientHolder } from \"./bigquery\";\nimport { File } from '@google-cloud/storage';\nimport { uploadFileInBucket } from \"./cloudStorage\";\nimport { safeColumnName } from \"../helpers\";\nimport chunk from \"lodash/chunk.js\";\nimport { haltAndCatchFire } from \"../../../sdk/service/error\";\nimport { StreamWarehouseSyncService } from \"../../../sdk/models/target/dbSync\";\nimport { InternalTableField, JSONSchemaFieldDefinition, WarehouseTableField } from \"../../../sdk/models/target/models\";\nimport { BigQueryConfig } from \"../models/config\";\nimport { RenameColumnStore } from \"../../../sdk/models/target/renameColumnStore\";\nimport { Semaphore } from \"async-mutex\";\nimport { gracefulExit } from \"../../../sdk/service/exit\";\n\nconst semaphore = new Semaphore(1);\n\nexport class BigQueryDBSync extends StreamWarehouseSyncService {\n\n config: BigQueryConfig;\n bqClient: BigQuery;\n bqDataset: Dataset;\n bqTable: Table;\n bqStagingTable: Table;\n tableName: string;\n stagingTableName: string;\n sqlTableId: string;\n sqlStagingTableId: string;\n\n constructor(\n config: BigQueryConfig,\n streamId: StreamId,\n database: string,\n schema: string,\n table: string,\n renameColumnStore: RenameColumnStore,\n ) {\n super(\n streamId,\n database,\n schema,\n table,\n renameColumnStore\n )\n this.config = config;\n this.bqClient = BqClientHolder.client(config);\n this.bqDataset = this.bqClient.dataset(schema, { location: config.location || \"EU\" });\n this.bqTable = this.bqDataset.table(table, { location: config.location || \"EU\" });\n this.tableName = table;\n this.stagingTableName = `${table}_temp`;\n this.bqStagingTable = this.bqDataset.table(this.stagingTableName, { location: config.location || \"EU\" });\n this.sqlTableId = `${schema}.${table}`;\n this.sqlStagingTableId = `${this.sqlTableId}_temp`;\n }\n\n // Implementation of abstract classes\n\n getSerializedRecord = (record: any): string => {\n return JSON.stringify(record) + `\\n`;\n }\n\n safeColumnName = safeColumnName\n\n getWarehouseTypeFromJSONSchema = (\n definition: JSONSchemaFieldDefinition\n ): string => {\n\n const type = definition.type;\n const format = definition.format;\n\n // Converting `string | string[]` into `string[]` is easier for later processing\n let typeArr: string[];\n\n if (type instanceof Array) {\n typeArr = type;\n } else {\n typeArr = [type];\n }\n\n if (format) {\n switch (format) {\n case \"date-time\":\n return \"TIMESTAMP\";\n case \"json\":\n return \"STRING\";\n default:\n throw new Error(`StreamId: ${this.streamId} - Unsupported format: ${format}`)\n }\n }\n else if (typeArr.includes('number')) {\n return \"NUMERIC\"\n }\n else if (typeArr.includes('integer') && type.includes('string')) {\n return \"NUMERIC\"\n }\n else if (typeArr.includes('integer')) {\n return \"INTEGER\"\n }\n else if (typeArr.includes('boolean')) {\n return \"BOOLEAN\"\n }\n else if (typeArr.includes('string')) {\n return \"STRING\"\n }\n else if (typeArr.includes('array')) {\n const items = definition.items;\n if (items) {\n return this.getWarehouseTypeFromJSONSchema(items)\n }\n throw new Error(`StreamId: ${this.streamId} - Unsupported array schema field definition: ${JSON.stringify(definition)}`)\n }\n else {\n throw new Error(`StreamId: ${this.streamId} - Unsupported schema field definition: ${JSON.stringify(definition)}`)\n }\n };\n\n getMergeQueries = (): string[] => {\n\n const primaryKeyCondition = this.primaryKeys\n .map(pk => {\n return `\\`sourced\\`.\\`${pk}\\` = \\`destination\\`.\\`${pk}\\``\n })\n .join(` AND `);\n\n const primaryKeys = this.primaryKeys.map(pk => `\\`${pk}\\``).join(` ,`)\n\n const columnUnsafeToSafeMapping = this.renamedColumnStore.getUnsafeToSafeColumnMapping(this.streamId);\n\n const columns = Object.keys(columnUnsafeToSafeMapping)\n .map(column => {\n return {\n isUnsafe: true,\n colName: column\n }\n });\n const columnsChunks = chunk(columns, 300)\n // We need to make sure that the PKs keys are in all chunks so that they are written in the first chunk in the destination table\n // Otherwise we write \"null\" in the PK cols in a first batch and then we can't the proper lines in subsequent batchs\n .map(chunk => {\n this.primaryKeys.forEach(pk => {\n if (!chunk.map(c => columnUnsafeToSafeMapping[c.colName]).includes(pk)) {\n chunk.push({\n isUnsafe: false,\n colName: pk\n });\n }\n })\n return chunk;\n });\n\n return columnsChunks.map(chunk => {\n\n const setValues = chunk\n .map(column => {\n if (column.isUnsafe) {\n return `\\`destination\\`.\\`${columnUnsafeToSafeMapping[column.colName]}\\` = \\`sourced\\`.\\`${columnUnsafeToSafeMapping[column.colName]}\\``\n } else {\n return `\\`destination\\`.\\`${column.colName}\\` = \\`sourced\\`.\\`${column.colName}\\``\n }\n }).join(`, `);\n\n const renamedCols = chunk\n .map(column => {\n if (column.isUnsafe) {\n return `\\`${columnUnsafeToSafeMapping[column.colName]}\\``\n } else {\n return `\\`${column.colName}\\``\n }\n }).join(`, `);\n\n const query = `\n MERGE ${this.sqlTableId} destination\n USING (\n WITH all_staging_rows AS (\n SELECT *\n FROM ${this.sqlStagingTableId}\n ),\n numbered_rows AS (\n SELECT *, \n ROW_NUMBER() OVER (PARTITION BY ${primaryKeys}) as _wly_row_nb,\n COUNT(1) OVER (PARTITION BY ${primaryKeys}) AS _wly_partition_size,\n FROM all_staging_rows\n ),\n staging_deduped AS (\n SELECT * EXCEPT(_wly_partition_size, _wly_row_nb)\n FROM numbered_rows \n WHERE _wly_partition_size = _wly_row_nb\n )\n SELECT *\n FROM staging_deduped\n ) AS sourced\n ON ${primaryKeyCondition}\n WHEN MATCHED THEN\n UPDATE SET ${setValues}\n WHEN NOT MATCHED THEN\n INSERT (${renamedCols}) VALUES (${renamedCols});\n `\n return query;\n });\n }\n\n getReplaceQueries = (): string[] => {\n return [\n `TRUNCATE TABLE ${this.sqlTableId};`,\n ...this.getMergeQueries()\n ];\n }\n\n createDatabaseAndSchemaIfNotExists = async (retryCount: number) => {\n try {\n // To avoid checking / creating the dataset multiple times when evaluating streams concurrently\n // We make sure that this portion of the code is run with a concurrency of 1\n await semaphore.runExclusive(async () => {\n const [exists] = await this.bqDataset.exists();\n if (!exists) {\n logger.info(`🐣 Creating dataset: ${this.bqDataset.id} on BigQuery`)\n await this.bqDataset.create();\n } else {\n const [metadata] = await this.bqDataset.getMetadata()\n const alreadyExistinglocation = metadata.location;\n if (this.config.location && this.config.location !== alreadyExistinglocation) {\n await haltAndCatchFire(\n `unknown`,\n `A BigQuery dataset called '${this.bqDataset.id}' already exists in location: '${alreadyExistinglocation}' 😅\n \n This connector is configured to load data into the location '${this.config.location}' which is not possible as 2 datasets sharing the same name can't exist in different location on Google Cloud 😿\n\n To fix this issue, could you either: a. Delete the already existing dataset? b. Change the configured destination schema name to avoid the name conflict? 🙏\n \n Please relaunch the connector once it's done to fix the issue 🤗\n `,\n `\n We have a conflict between an already existing dataset in location ${alreadyExistinglocation} and the configured location: ${this.config.location}\n `\n )\n throw Error()\n }\n logger.info(`👋 Dataset: ${this.bqDataset.id} already exists on BigQuery, reusing it.`)\n }\n });\n } catch (err: any) {\n if (err.code === 400) {\n await haltAndCatchFire(\n `unauthorized`,\n `We can't connect to your BigQuery account 😔\n\n Here is the message from BigQuery: ${err.message}\n \n Can you check that your Warehouse credentials and Source target schema are properly configured and try to sync again the source? 🙏\n `,\n `Got error when trying to get Dataset from BigQuery: ${err.message} - ${err.code}`\n )\n return;\n }\n if (retryCount && retryCount > this.maxRetryCount) {\n logger.error(`StreamId: ${this.streamId} - Error when checking if dataset already exists. ${err.message} - ${err.code}`)\n gracefulExit(1);\n } else {\n logger.error(`StreamId: ${this.streamId} - Error when checking if dataset already exists. Retrying... ${err.message} - ${err.code}`)\n await new Promise((resolve, reject) => setTimeout(resolve, 1000 * (retryCount)))\n await this.createDatabaseAndSchemaIfNotExists(retryCount + 1)\n }\n }\n return Promise.resolve();\n }\n\n createTable = async () => {\n\n try {\n const tableName = this.tableName;\n const schema = this.generateBigquerySchema();\n\n logger.info(`🐣 Creating table: ${tableName} on BigQuery`)\n\n const createTableOptions: TableMetadata = {\n schema\n }\n\n await this.bqDataset.createTable(\n tableName,\n createTableOptions\n )\n\n return;\n } catch (err: any) {\n throw new Error(`StreamId: ${this.streamId} - Issue when creating table in BigQuery\n\n Error: ${err.message}\n Stack: ${err.stack}`)\n }\n }\n\n addColumns = async (tableFields: InternalTableField[]): Promise<void> => {\n\n if (tableFields.length > 0) {\n logger.info(`🆕 Stream: ${this.streamId} - Adding following columns in BigQuery schema: ${JSON.stringify(tableFields)}`)\n const [metadata] = await this.bqTable.getMetadata();\n\n const bgTableFields = tableFields.map(tblField => {\n return this.getBigqueryTableFieldFromInternalSchemaFieldDefinition(tblField.name, tblField.definition)\n }).filter(fld => {\n return !!fld\n })\n const schema = metadata.schema;\n const new_schema = {\n ...schema,\n fields: schema.fields.concat(bgTableFields)\n };\n metadata.schema = new_schema;\n\n await this.bqTable.setMetadata(metadata);\n return;\n }\n\n }\n\n createStagingArea = async () => {\n\n try {\n const tableName = this.stagingTableName;\n\n // A temporary table from a previous load could still be there\n const [exists] = await this.bqDataset.table(tableName).exists();\n if (exists) {\n logger.info(`👴 Temporary table ${tableName} already exists, it should be a relic form the past.\n Dropping it.`)\n await this.deleteStagingArea();\n }\n\n const schema = this.generateBigquerySchema();\n const expirationTime = dayjs().add(1, \"day\").valueOf().toString();\n const createTableOptions: TableMetadata = {\n schema,\n expirationTime\n }\n\n logger.info(`🐣 Creating staging table: ${tableName} on BigQuery`)\n\n await this.bqDataset.createTable(\n tableName,\n createTableOptions\n )\n\n return;\n } catch (err: any) {\n throw new Error(`StreamId: ${this.streamId} - Issue when creating table in BigQuery\n\n Error: ${err.message}\n Stack: ${err.stack}`)\n }\n }\n\n loadStreamInStagingArea = async (localFilePath: string) => {\n\n try {\n\n const file = await uploadFileInBucket(\n this.streamId,\n this.config.loading_deck_gcs_bucket_name,\n this.config.connector_id,\n localFilePath\n );\n\n const metadata: JobLoadMetadata = {\n sourceFormat: 'NEWLINE_DELIMITED_JSON',\n writeDisposition: \"WRITE_TRUNCATE\",\n };\n\n await this.loadGCSFileInTable(this.sqlStagingTableId, file, metadata);\n\n } catch (err) {\n logger.error(`StreamId: ${this.streamId} - Error while uploading stream.`)\n throw err;\n }\n }\n\n deleteStagingArea = () => {\n const query = `DROP TABLE IF EXISTS ${this.sqlStagingTableId};`;\n return this.runQueriesWithRetry([query]);\n }\n\n getTablesInSchema = async (): Promise<{ tableName: string }[]> => {\n const [bqTables] = await this.bqDataset.getTables();\n const foundTables = bqTables\n .filter(tbl => {\n return !!tbl.id\n })\n .map(bqTable => {\n return {\n tableName: bqTable.id\n }\n });\n\n return foundTables as { tableName: string }[];\n }\n\n getTableColumnsFromWarehouse = async (): Promise<WarehouseTableField[]> => {\n const [table] = await this.bqTable.getMetadata();\n return table.schema.fields;\n }\n\n runQueries = async (queries: string[]): Promise<void> => {\n const sqlQuery = `\n BEGIN\n ${queries.join(`\n `)}\n END;\n `;\n await this.bqClient.query(sqlQuery);\n }\n\n // Specific methods\n /**\n * \n * Generate a TableField definition object that can be passed to BigQuery APIs to define a column on a table\n * \n * @param colName \n * @param schemaFieldDefinition \n * @returns \n */\n private getBigqueryTableFieldFromInternalSchemaFieldDefinition = (\n colName: string,\n schemaFieldDefinition: JSONSchemaFieldDefinition | undefined\n ): TableField | undefined => {\n\n const name = colName;\n\n if (!schemaFieldDefinition) {\n throw new Error(`StreamId: ${this.streamId} - Schema is unknown for colName=${colName}, so we can't infer the proper BigQuery definition for this column.`)\n }\n const type = schemaFieldDefinition.type;\n\n // Converting `string | string[]` into `string[]` is easier for later processing\n let typeArr: string[];\n\n if (type instanceof Array) {\n typeArr = type;\n } else {\n typeArr = [type];\n }\n\n if (typeArr.includes('array')) {\n return {\n name,\n mode: \"REPEATED\",\n type: this.getWarehouseTypeFromJSONSchema(schemaFieldDefinition)\n }\n } else {\n // Only supported mode is NULLABLE as:\n // REQUIRED is not working great with adding columns later on so we keep NULLABLE\n let nullableMode = \"NULLABLE\";\n return {\n name,\n mode: nullableMode,\n type: this.getWarehouseTypeFromJSONSchema(schemaFieldDefinition)\n }\n }\n\n }\n\n private generateBigquerySchema = (): TableField[] => {\n const unsafeToSafeMappingColumnsFromColumnStore = this.renamedColumnStore.getUnsafeToSafeColumnMapping(this.streamId);\n if (!unsafeToSafeMappingColumnsFromColumnStore) {\n throw new Error(`StreamId: ${this.streamId} - There is no unsafe->safe column mapping`)\n }\n return Object.keys(unsafeToSafeMappingColumnsFromColumnStore).reduce<TableField[]>((acc, unsafeKey) => {\n\n const renamedColName = this.renamedColumnStore.getColumnTranslation(this.streamId, unsafeKey)!;\n const bigqueryTableField = this.getBigqueryTableFieldFromInternalSchemaFieldDefinition(renamedColName, this.flattenedSchema[unsafeKey]);\n if (bigqueryTableField) {\n acc.push(bigqueryTableField);\n }\n\n return acc;\n }, [])\n }\n\n private loadGCSFileInTable = async (\n tableName: string,\n file: File,\n metadata: JobLoadMetadata\n ): Promise<void> => {\n try {\n const [job] = await this.bqStagingTable.load(file, metadata);\n\n logger.info(`🚚 Loaded GCS file \\`${file.id}\\` in BigQuery table: ${tableName} with Job: \\`${job.id}\\``);\n logger.debug(`Upload Stats: ${JSON.stringify(job.statistics)}`)\n\n // Check the job's status for errors\n const errors = job.status?.errors;\n if (errors && errors.length > 0) {\n throw errors;\n }\n } catch (err: any) {\n logger.error(err)\n throw new Error(`StreamId: ${this.streamId} - Issue when loading file in BigQuery table | fileName: ${file.name}, tableName: ${tableName}\n\n Error: ${err.message}\n Stack: ${err.stack}`)\n }\n }\n\n}","import { BigQueryConfig } from \"../models/config\";\nimport { BigQuery } from \"@google-cloud/bigquery\";\n\nexport class BqClientHolder {\n private static instance: BqClientHolder;\n\n client: BigQuery;\n\n constructor(config: BigQueryConfig) {\n\n const retryOptions = {\n autoRetry: true,\n maxRetries: 3\n }\n\n this.client = new BigQuery({\n projectId: config.database.trim(),\n ...retryOptions\n });\n }\n\n static client(config: BigQueryConfig): BigQuery {\n if (!this.instance) {\n this.instance = new this(config);\n }\n\n return this.instance.client;\n }\n\n}","import { Storage, File } from '@google-cloud/storage';\nimport { v4 as uuidv4 } from 'uuid';\nimport { StreamId } from '../../../sdk/models/metadata';\nimport { haltAndCatchFire } from '../../../sdk/service/error';\nimport { logger } from '../../../sdk/service/logger';\n\nexport const uploadFileInBucket = async (\n streamId: StreamId,\n gcsBuckerName: string,\n connectorId: string,\n filePath: string,\n): Promise<File> => {\n\n try {\n const retryOptions = { autoRetry: true, maxRetries: 20 }\n\n let storage: Storage = new Storage({ retryOptions: retryOptions });\n\n const bucketRef = storage.bucket(gcsBuckerName);\n\n // Bucket should already have been created on the proper Google Cloud region\n await bucketRef.get({ autoCreate: false });\n\n const destinationFileName = `${connectorId}/${streamId}-${uuidv4()}.jsonnl`;\n\n await bucketRef.upload(filePath, {\n destination: destinationFileName\n })\n\n logger.info(`🗳 Uploaded ${filePath} into ${gcsBuckerName}/${destinationFileName} GCS File`);\n\n return bucketRef.file(destinationFileName);\n } catch (err: any) {\n logger.error(`Issue when uploading file into GCS bucket for stream: ${streamId}\n \n Error: ${err.message}\n Stack: ${err.stack}\n Code: ${err.code}\n `)\n\n if (err.code < 500) {\n await haltAndCatchFire(\n `unauthorized`,\n `We couldn't connect to your Cloud Storage bucket 😔\n \n The error from Google is: '${err.message}' 👀\n \n Could you troubleshoot your Cloud Storage configuration in Google Cloud and sync again the source? 🙏`,\n `Got error from cloud storage lib`\n )\n }\n throw err;\n }\n}\n","import crypto from 'crypto';\nconst rnds8Pool = new Uint8Array(256); // # of random values to pre-allocate\n\nlet poolPtr = rnds8Pool.length;\nexport default function rng() {\n if (poolPtr > rnds8Pool.length - 16) {\n crypto.randomFillSync(rnds8Pool);\n poolPtr = 0;\n }\n\n return rnds8Pool.slice(poolPtr, poolPtr += 16);\n}","export default /^(?:[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}|00000000-0000-0000-0000-000000000000)$/i;","import REGEX from './regex.js';\n\nfunction validate(uuid) {\n return typeof uuid === 'string' && REGEX.test(uuid);\n}\n\nexport default validate;","import validate from './validate.js';\n/**\n * Convert array of 16 byte values to UUID string format of the form:\n * XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX\n */\n\nconst byteToHex = [];\n\nfor (let i = 0; i < 256; ++i) {\n byteToHex.push((i + 0x100).toString(16).substr(1));\n}\n\nfunction stringify(arr, offset = 0) {\n // Note: Be careful editing this code! It's been tuned for performance\n // and works in ways you may not expect. See https://github.com/uuidjs/uuid/pull/434\n const uuid = (byteToHex[arr[offset + 0]] + byteToHex[arr[offset + 1]] + byteToHex[arr[offset + 2]] + byteToHex[arr[offset + 3]] + '-' + byteToHex[arr[offset + 4]] + byteToHex[arr[offset + 5]] + '-' + byteToHex[arr[offset + 6]] + byteToHex[arr[offset + 7]] + '-' + byteToHex[arr[offset + 8]] + byteToHex[arr[offset + 9]] + '-' + byteToHex[arr[offset + 10]] + byteToHex[arr[offset + 11]] + byteToHex[arr[offset + 12]] + byteToHex[arr[offset + 13]] + byteToHex[arr[offset + 14]] + byteToHex[arr[offset + 15]]).toLowerCase(); // Consistency check for valid UUID. If this throws, it's likely due to one\n // of the following:\n // - One or more input array values don't map to a hex octet (leading to\n // \"undefined\" in the uuid)\n // - Invalid input values for the RFC `version` or `variant` fields\n\n if (!validate(uuid)) {\n throw TypeError('Stringified UUID is invalid');\n }\n\n return uuid;\n}\n\nexport default stringify;","import rng from './rng.js';\nimport stringify from './stringify.js';\n\nfunction v4(options, buf, offset) {\n options = options || {};\n const rnds = options.random || (options.rng || rng)(); // Per 4.4, set bits for version and `clock_seq_hi_and_reserved`\n\n rnds[6] = rnds[6] & 0x0f | 0x40;\n rnds[8] = rnds[8] & 0x3f | 0x80; // Copy bytes to buffer, if provided\n\n if (buf) {\n offset = offset || 0;\n\n for (let i = 0; i < 16; ++i) {\n buf[offset + i] = rnds[i];\n }\n\n return buf;\n }\n\n return stringify(rnds);\n}\n\nexport default v4;","import { ITarget } from \"../../sdk/models/target/target\"\nimport { BigQueryConfig } from \"./models/config\";\n\nimport { safeColumnName, safeTableName } from \"./helpers\";\nimport { convertNumberIntoDecimal, validateDateRange } from \"./service/record\";\nimport { BigQueryDBSync } from \"./service/dbSync\";\nimport { StreamId } from \"../../sdk/models/metadata\";\nimport { StateProvider } from \"../../sdk/models/state-provider/types\";\n\nexport class BigQueryTarget extends ITarget<BigQueryConfig> {\n\n\n constructor(config: BigQueryConfig, stateProvider: StateProvider) {\n super(config, stateProvider);\n this.renameColumnStore.setSafeColumnNameConverter(this.safeColumnNameConverter);\n }\n static requiredConfigKeys = [\n \"schema\",\n \"project_id\",\n \"loading_deck_gcs_bucket_name\"\n ]\n\n newDBSyncInstance = (\n streamId: StreamId,\n database: string,\n schema: string,\n table: string,\n ): BigQueryDBSync => {\n return new BigQueryDBSync(\n this.config,\n streamId,\n database,\n schema,\n table,\n this.renameColumnStore,\n )\n };\n\n genTableName = safeTableName;\n safeColumnNameConverter = safeColumnName;\n validateDateRange = validateDateRange;\n convertNumberIntoDecimal = convertNumberIntoDecimal;\n\n}","import { Storage } from '@google-cloud/storage';\nimport { logger } from './logger';\nimport { format } from 'util';\n\nconst getStorage = () => new Storage({ retryOptions: { autoRetry: true, maxRetries: 20 } });\n\nexport const readObjectAsString = async (\n bucketName: string,\n objectPath: string,\n): Promise<string> => {\n try {\n const storage = getStorage();\n const bucketRef = storage.bucket(bucketName);\n await bucketRef.get({ autoCreate: false });\n const fileRef = bucketRef.file(objectPath);\n const [exists] = await fileRef.exists();\n if (!exists) {\n throw new Error(`GCS object not found: gs://${bucketName}/${objectPath}`);\n }\n const [contents] = await fileRef.download();\n return contents.toString('utf8');\n } catch (err: any) {\n throw new Error(format(`error reading GCS object gs://${bucketName}/${objectPath}, err: %s`, err?.message));\n }\n}\n\nexport const writeStringObject = async (\n bucketName: string,\n objectPath: string,\n contents: string,\n): Promise<void> => {\n try {\n const storage = getStorage();\n const bucketRef = storage.bucket(bucketName);\n await bucketRef.get({ autoCreate: false });\n const fileRef = bucketRef.file(objectPath);\n await fileRef.save(contents, { contentType: 'application/json' });\n logger.info(`🗳 Uploaded object to gs://${bucketName}/${objectPath}`);\n } catch (err: any) {\n throw new Error(format(`error writing GCS object gs://${bucketName}/${objectPath}, err: %s`, err?.message));\n }\n}\n\n\n","import { logger } from \"../../sdk/service/logger\";\nimport { readObjectAsString, writeStringObject } from \"../../sdk/service/gcs\";\nimport { StateHolder, StateProvider } from \"../../sdk/models/state-provider/types\";\nimport { format } from \"util\";\n\nexport class GCSStateProvider implements StateProvider {\n private bucketName: string;\n private connectorId: string;\n\n constructor(connectorId: string, bucketName: string) {\n this.connectorId = connectorId;\n this.bucketName = bucketName;\n }\n\n private getObjectPath(): string {\n return `${this.connectorId}/state.json`;\n }\n\n async getState(): Promise<StateHolder> {\n const objectPath = this.getObjectPath();\n try {\n logger.info(`📁 Loading state from gs://${this.bucketName}/${objectPath}`);\n const raw = await readObjectAsString(this.bucketName, objectPath);\n const parsed = JSON.parse(raw);\n return { state: parsed };\n } catch (err: any) {\n logger.warn(format(`error loading state from gs://${this.bucketName}/${objectPath}, will start with empty state, err: %s`, err?.message));\n return { state: undefined };\n }\n }\n\n async writeState(state: string): Promise<void> {\n const objectPath = this.getObjectPath();\n try {\n logger.info(`📝 Writing state to gs://${this.bucketName}/${objectPath}`);\n await writeStringObject(this.bucketName, objectPath, state);\n } catch (err: any) {\n logger.error(format(`💥 Error while writing state to gs://${this.bucketName}/${objectPath}, err: %s`, err?.message));\n throw new Error(format(`error writing state to gs://${this.bucketName}/${objectPath}, err: %s`, err?.message));\n }\n }\n}"],"mappings":"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","names":["transports","axios","axiosRetry","retryCount","ReplicationMethod","dayjs","import_axios","qs","import_dayjs","import_cloneDeep","import_bluebird","cloneDeep","Bluebird","import_util","cloneDeep","Bluebird","dayjs","isPlainObject","import_cloneDeep","params","axios","cloneDeep","isEqual","retry","safeColumnName","errors","import_dayjs","import_dayjs","fs","uniqueId","fs","dayjs","import_bluebird","dayjs","Bluebird","import_dayjs","format","dayjs","Decimal","import_dayjs","crypto","stringify","import_async_mutex","semaphore","format","chunk","dayjs","errors","import_storage","import_util","import_util"]}
|