@whaly/connector-sdk 0.1.0 → 0.1.1

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.js CHANGED
@@ -34,14 +34,14 @@ __export(index_exports, {
34
34
  API_CALLS_METRIC_NAME: () => API_CALLS_METRIC_NAME,
35
35
  Authenticator: () => Authenticator,
36
36
  BATCH_INTERVAL_MS: () => BATCH_INTERVAL_MS,
37
- Catalog: () => Catalog,
37
+ BigQueryTarget: () => BigQueryTarget,
38
38
  CounterMetric: () => CounterMetric,
39
39
  DEFAULT_MAX_CONCURRENT_STREAMS: () => DEFAULT_MAX_CONCURRENT_STREAMS,
40
40
  EXECUTION_TIME_METRIC_NAME: () => EXECUTION_TIME_METRIC_NAME,
41
41
  ITarget: () => ITarget,
42
42
  MissingFieldInSchemaError: () => MissingFieldInSchemaError,
43
43
  MissingSchemaError: () => MissingSchemaError,
44
- RESTStreamV2: () => RESTStreamV2,
44
+ RESTStream: () => RESTStream,
45
45
  ROWS_SYNCED_METRIC_NAME: () => ROWS_SYNCED_METRIC_NAME,
46
46
  RecordMessage: () => RecordMessage,
47
47
  RenameColumnStore: () => RenameColumnStore,
@@ -51,13 +51,12 @@ __export(index_exports, {
51
51
  SchemaValidationError: () => SchemaValidationError,
52
52
  StateMessage: () => StateMessage,
53
53
  StateService: () => StateService,
54
+ Stream: () => Stream,
54
55
  StreamMetadata: () => StreamMetadata,
55
- StreamV2: () => StreamV2,
56
56
  StreamWarehouseSyncService: () => StreamWarehouseSyncService,
57
57
  Tap: () => Tap,
58
58
  _greaterThan: () => _greaterThan,
59
59
  addWhalyFields: () => addWhalyFields,
60
- checkRequiredConfigKeys: () => checkRequiredConfigKeys,
61
60
  createTemporaryFileStream: () => createTemporaryFileStream,
62
61
  extractStateForStream: () => extractStateForStream,
63
62
  finalizeStateProgressMarkers: () => finalizeStateProgressMarkers,
@@ -75,8 +74,8 @@ __export(index_exports, {
75
74
  haltAndCatchFire: () => haltAndCatchFire,
76
75
  incrementStreamState: () => incrementStreamState,
77
76
  loadJson: () => loadJson,
77
+ loadResolver: () => loadResolver,
78
78
  loadSchema: () => loadSchema,
79
- loadShoreConfig: () => loadShoreConfig,
80
79
  logger: () => logger,
81
80
  postFormDataApiCall: () => postFormDataApiCall,
82
81
  postJSONApiCall: () => postJSONApiCall,
@@ -84,7 +83,6 @@ __export(index_exports, {
84
83
  printMemoryFootprint: () => printMemoryFootprint,
85
84
  removeParasiteProperties: () => removeParasiteProperties,
86
85
  safePath: () => safePath,
87
- writeCatalogFile: () => writeCatalogFile,
88
86
  writeStateFile: () => writeStateFile
89
87
  });
90
88
  module.exports = __toCommonJS(index_exports);
@@ -116,10 +114,10 @@ var readAndParseJSONFile = (path) => {
116
114
  };
117
115
 
118
116
  // src/resolvers/local-file/hook/schemaHook.ts
119
- var import_fs_extra = require("fs-extra");
117
+ var import_fs_extra = __toESM(require("fs-extra"));
120
118
  var LocalSchemaHook = class {
121
119
  async writeSchema(input) {
122
- await (0, import_fs_extra.appendFile)("./schema.tmp", JSON.stringify(input) + "\n");
120
+ await import_fs_extra.default.appendFile("./schema.tmp", JSON.stringify(input) + "\n");
123
121
  }
124
122
  };
125
123
 
@@ -180,15 +178,9 @@ var CounterMetric = class {
180
178
 
181
179
  // src/resolvers/local-file/resolver.ts
182
180
  var { combine, prettyPrint, timestamp, errors, splat } = import_winston.default.format;
183
- var configPath = "./config.json";
184
- var targetConfigPath = "./target-config.json";
185
- var catalogPath = "./catalog.json";
186
181
  var statePath = "./state.json";
187
182
  var metricsPath = "./metrics.json";
188
183
  var LocalFilesResolver = class extends Resolver {
189
- startVPNIfNeeded() {
190
- return Promise.resolve();
191
- }
192
184
  checkIfCanSync() {
193
185
  return Promise.resolve(true);
194
186
  }
@@ -213,49 +205,15 @@ var LocalFilesResolver = class extends Resolver {
213
205
  constructor() {
214
206
  super();
215
207
  }
216
- getConfig(command) {
208
+ getState() {
217
209
  logger.info(`\u{1F4C1} Using the LOCAL resolver`);
218
- const config = readAndParseJSONFile(configPath);
219
- const targetConfig = readAndParseJSONFile(targetConfigPath);
220
- const destination = process.env.SHORE__DESTINATION;
221
- if (!destination) {
222
- throw new Error(`\u274C Env variable \`SHORE__DESTINATION\` is not set.
223
- Did you forget to configure it?
224
-
225
- Possible values are: \`GOOGLE_BIGQUERY\`, \`SNOWFLAKE\``);
226
- }
227
- if (command === `READ`) {
228
- if (destination === `GOOGLE_BIGQUERY`) {
229
- const googleCredentials = process.env.GOOGLE_APPLICATION_CREDENTIALS;
230
- if (!googleCredentials) {
231
- throw new Error(`Env variable \`GOOGLE_APPLICATION_CREDENTIALS\` is not set.
232
- Did you forget to configure it?
233
-
234
- This variable should link to a file containing the proper Google Service Account credentials.
235
- `);
236
- }
237
- }
238
- const catalog = readAndParseJSONFile(catalogPath);
239
- const state = readAndParseJSONFile(statePath);
240
- return Promise.resolve({
241
- command,
242
- destination,
243
- config,
244
- targetConfig,
245
- catalog,
246
- state
247
- });
248
- } else {
249
- return Promise.resolve({
250
- command,
251
- destination,
252
- config,
253
- targetConfig
254
- });
255
- }
210
+ const state = readAndParseJSONFile(statePath);
211
+ return Promise.resolve({
212
+ state
213
+ });
256
214
  }
257
215
  writeCatalog(catalog) {
258
- return writeFile(catalogPath, JSON.stringify(catalog));
216
+ return Promise.resolve();
259
217
  }
260
218
  writeState(state) {
261
219
  return writeFile(statePath, state);
@@ -286,9 +244,7 @@ var LocalFilesResolver = class extends Resolver {
286
244
  }
287
245
  updateSourceValue(optionKey, optionValue) {
288
246
  logger.info(`Updating source value ${optionKey} with value ${optionValue}`, { private: true });
289
- const config = readAndParseJSONFile(configPath);
290
- config[optionKey] = optionValue;
291
- return writeFile(configPath, JSON.stringify(config));
247
+ return Promise.resolve();
292
248
  }
293
249
  getLogFormat() {
294
250
  return combine(
@@ -301,29 +257,8 @@ var LocalFilesResolver = class extends Resolver {
301
257
  };
302
258
 
303
259
  // src/sdk/service/resolver.ts
304
- function initResolver(resolverType) {
305
- if (resolverType === "LOCAL") {
306
- return new LocalFilesResolver();
307
- } else {
308
- throw new Error(`\u274C Unsupported configResolver: ${resolverType}`);
309
- }
310
- }
311
260
  var loadResolver = () => {
312
- const configResolver = process.env.SHORE__CONFIG_RESOLVER;
313
- if (!configResolver) {
314
- throw new Error(`Env variable \`SHORE__CONFIG_RESOLVER\` is not set.
315
- Did you forget to configure it?
316
-
317
- Possible values are \`LOCAL\`, \`WHALY\`.
318
- Please read the documentation to get the full description of the behavior of each.
319
- `);
320
- }
321
- if (configResolver === "WHALY" || configResolver === "LOCAL") {
322
- return initResolver(configResolver);
323
- } else {
324
- throw new Error(`Resolver: ${configResolver} is not supported.
325
- Did you properly configure \`SHORE__CONFIG_RESOLVER\`?`);
326
- }
261
+ return new LocalFilesResolver();
327
262
  };
328
263
 
329
264
  // src/sdk/service/logger.ts
@@ -373,30 +308,6 @@ var writeStateFile = (resolver, state) => {
373
308
  logger.info(`\u{1F4DD} Writing the state file.`);
374
309
  return resolver.writeState(state);
375
310
  };
376
- var writeCatalogFile = (resolver, catalog) => {
377
- logger.info(`\u{1F4DD} Writing the catalog`);
378
- return resolver.writeCatalog(catalog);
379
- };
380
- var loadShoreConfig = (resolver) => {
381
- const command = process.env.SHORE__COMMAND;
382
- if (!command) {
383
- throw new Error(`Env variable \`SHORE__COMMAND\` is not set.
384
- Did you forget to configure it?
385
-
386
- Possible values are: \`DISCOVER\`, \`READ\``);
387
- }
388
- if (command === `DISCOVER`) {
389
- logger.info(`\u{1F50E} Mode: discovery
390
- Shore will detect the available streams in the source and their configuration.`);
391
- } else if (command === `READ`) {
392
- logger.info(`\u{1F501} Mode: Synchronizing data
393
- Shore will extract and push data from the source to the destination.`);
394
- } else {
395
- throw new Error(`Command: \`${command}\` is not supported.
396
- Did you properly configured env variable \`SHORE__COMMAND\`?`);
397
- }
398
- return resolver.getConfig(command);
399
- };
400
311
  function readFile(fileName, filePath) {
401
312
  try {
402
313
  return (0, import_fs2.readFileSync)(filePath);
@@ -422,13 +333,6 @@ var loadSchema = (streamId) => {
422
333
  const schema = loadJson(`schemas/${streamId}.json`);
423
334
  return schema;
424
335
  };
425
- var checkRequiredConfigKeys = (args, requiredConfigKeys) => {
426
- requiredConfigKeys.forEach((configKey) => {
427
- if (!args[configKey]) {
428
- throw new Error(`Config is missing required key: ${configKey}`);
429
- }
430
- });
431
- };
432
336
 
433
337
  // src/sdk/service/network.ts
434
338
  var import_axios = __toESM(require("axios"));
@@ -706,6 +610,102 @@ var findRelatedRelationships = (streamId, allRels) => {
706
610
  }, { left: [], right: [] });
707
611
  };
708
612
 
613
+ // src/sdk/models/messages.ts
614
+ var RecordMessage = class {
615
+ type = "RECORD";
616
+ stream;
617
+ record;
618
+ constructor(record, stream) {
619
+ this.record = record;
620
+ this.stream = stream;
621
+ }
622
+ toString() {
623
+ const result = {
624
+ type: "RECORD",
625
+ record: this.record,
626
+ stream: this.stream
627
+ };
628
+ return JSON.stringify(result);
629
+ }
630
+ };
631
+ var StateMessage = class {
632
+ type = "STATE";
633
+ value;
634
+ constructor(value) {
635
+ this.value = value;
636
+ }
637
+ toString() {
638
+ const result = {
639
+ type: "STATE",
640
+ value: this.value
641
+ };
642
+ return JSON.stringify(result);
643
+ }
644
+ };
645
+ var ReplicationMethodMessage = class {
646
+ type = "REPLICATION_METHOD";
647
+ stream;
648
+ replication;
649
+ constructor(stream, version) {
650
+ this.stream = stream;
651
+ this.replication = version;
652
+ }
653
+ toString() {
654
+ const result = {
655
+ type: "REPLICATION_METHOD",
656
+ replication: this.replication,
657
+ stream: this.stream
658
+ };
659
+ return JSON.stringify(result);
660
+ }
661
+ };
662
+ var SchemaMessage = class {
663
+ type = "SCHEMA";
664
+ stream;
665
+ schema;
666
+ keyProperties;
667
+ bookmarkProperties;
668
+ displayLabel;
669
+ description;
670
+ propertiesMetadata;
671
+ relationships;
672
+ constructor(opts) {
673
+ const {
674
+ stream,
675
+ schema,
676
+ keyProperties,
677
+ bookmarkProperties,
678
+ displayLabel,
679
+ description,
680
+ relationships,
681
+ propertiesMetadata
682
+ } = opts;
683
+ this.stream = stream;
684
+ this.schema = schema;
685
+ this.keyProperties = keyProperties;
686
+ this.bookmarkProperties = bookmarkProperties;
687
+ this.displayLabel = displayLabel;
688
+ this.description = description;
689
+ this.relationships = relationships;
690
+ this.propertiesMetadata = propertiesMetadata;
691
+ }
692
+ toString() {
693
+ const result = {
694
+ type: "SCHEMA",
695
+ stream: this.stream,
696
+ schema: this.schema,
697
+ key_properties: this.keyProperties,
698
+ label: this.displayLabel,
699
+ description: this.description,
700
+ relationships: this.relationships
701
+ };
702
+ if (this.bookmarkProperties) {
703
+ result["bookmark_properties"] = this.bookmarkProperties;
704
+ }
705
+ return JSON.stringify(result);
706
+ }
707
+ };
708
+
709
709
  // src/sdk/models/metadata.ts
710
710
  var MetadataMap = class extends Map {
711
711
  areEquals(array1, array2) {
@@ -826,155 +826,6 @@ var StreamMetadata = class {
826
826
  }
827
827
  };
828
828
 
829
- // src/sdk/models/catalog.ts
830
- var _ = __toESM(require("lodash"));
831
- var Catalog = class _Catalog {
832
- streams;
833
- static fromFile(fileName) {
834
- const catalogFile = loadJson(fileName);
835
- const catalog = new _Catalog();
836
- catalog.streams = catalogFile.streams;
837
- return catalog;
838
- }
839
- static fromCatalogFile(catalogFile) {
840
- const catalog = new _Catalog();
841
- catalog.streams = catalogFile.streams;
842
- return catalog;
843
- }
844
- getSelectedStreams() {
845
- if (!this.streams) {
846
- return [];
847
- }
848
- const directSelectedStreams = this.streams.filter((stream) => {
849
- const metadata = new StreamMetadata();
850
- metadata.fromCatalogStreamMetadata(stream.metadata);
851
- return metadata.isStreamSelected();
852
- });
853
- logger.debug(`Directly selected streams: ${directSelectedStreams.map((stream) => stream.stream).join(",")}`);
854
- const getIndirectSelectedStreams = (stream, ancestorsIds) => {
855
- const currAncestorsIds = ancestorsIds || [];
856
- const rootBreadcrumbMetadata = stream.metadata.find((metadata) => metadata.breadcrumb.length === 0);
857
- const parentStreamId = rootBreadcrumbMetadata?.metadata?.["whaly-parent-stream"];
858
- if (parentStreamId) {
859
- const parentStream = this.streams?.find((stream2) => stream2.stream === parentStreamId);
860
- if (parentStream) {
861
- currAncestorsIds.push(parentStreamId);
862
- return getIndirectSelectedStreams(parentStream, currAncestorsIds);
863
- }
864
- }
865
- return currAncestorsIds;
866
- };
867
- const indirectSelectedStreamIds = _.uniq(
868
- directSelectedStreams.flatMap((stream) => {
869
- return getIndirectSelectedStreams(stream);
870
- })
871
- );
872
- logger.debug(`Indirectly selected streams: ${indirectSelectedStreamIds.join(",")}`);
873
- const indirectSelectedStreams = indirectSelectedStreamIds.map((streamId) => {
874
- if (!directSelectedStreams.find((stream) => stream.stream === streamId)) {
875
- return this.streams?.find((stream) => stream.stream === streamId);
876
- }
877
- }).filter((stream) => !!stream);
878
- return directSelectedStreams.concat(indirectSelectedStreams);
879
- }
880
- };
881
-
882
- // src/sdk/models/messages.ts
883
- var RecordMessage = class {
884
- type = "RECORD";
885
- stream;
886
- record;
887
- constructor(record, stream) {
888
- this.record = record;
889
- this.stream = stream;
890
- }
891
- toString() {
892
- const result = {
893
- type: "RECORD",
894
- record: this.record,
895
- stream: this.stream
896
- };
897
- return JSON.stringify(result);
898
- }
899
- };
900
- var StateMessage = class {
901
- type = "STATE";
902
- value;
903
- constructor(value) {
904
- this.value = value;
905
- }
906
- toString() {
907
- const result = {
908
- type: "STATE",
909
- value: this.value
910
- };
911
- return JSON.stringify(result);
912
- }
913
- };
914
- var ReplicationMethodMessage = class {
915
- type = "REPLICATION_METHOD";
916
- stream;
917
- replication;
918
- constructor(stream, version) {
919
- this.stream = stream;
920
- this.replication = version;
921
- }
922
- toString() {
923
- const result = {
924
- type: "REPLICATION_METHOD",
925
- replication: this.replication,
926
- stream: this.stream
927
- };
928
- return JSON.stringify(result);
929
- }
930
- };
931
- var SchemaMessage = class {
932
- type = "SCHEMA";
933
- stream;
934
- schema;
935
- keyProperties;
936
- bookmarkProperties;
937
- displayLabel;
938
- description;
939
- propertiesMetadata;
940
- relationships;
941
- constructor(opts) {
942
- const {
943
- stream,
944
- schema,
945
- keyProperties,
946
- bookmarkProperties,
947
- displayLabel,
948
- description,
949
- relationships,
950
- propertiesMetadata
951
- } = opts;
952
- this.stream = stream;
953
- this.schema = schema;
954
- this.keyProperties = keyProperties;
955
- this.bookmarkProperties = bookmarkProperties;
956
- this.displayLabel = displayLabel;
957
- this.description = description;
958
- this.relationships = relationships;
959
- this.propertiesMetadata = propertiesMetadata;
960
- }
961
- toString() {
962
- const result = {
963
- type: "SCHEMA",
964
- stream: this.stream,
965
- schema: this.schema,
966
- key_properties: this.keyProperties,
967
- label: this.displayLabel,
968
- description: this.description,
969
- relationships: this.relationships
970
- };
971
- if (this.bookmarkProperties) {
972
- result["bookmark_properties"] = this.bookmarkProperties;
973
- }
974
- return JSON.stringify(result);
975
- }
976
- };
977
-
978
829
  // src/sdk/models/state.ts
979
830
  var import_moment = __toESM(require("moment"));
980
831
 
@@ -1155,186 +1006,46 @@ var isDatetimeType = (typeDef) => {
1155
1006
  };
1156
1007
 
1157
1008
  // src/sdk/models/tap/stream.ts
1158
- var _2 = __toESM(require("lodash"));
1159
- var import_bluebird2 = require("bluebird");
1009
+ var import_cloneDeep = __toESM(require("lodash/cloneDeep.js"));
1010
+ var import_bluebird2 = __toESM(require("bluebird"));
1160
1011
 
1161
1012
  // src/sdk/models/tap/tap.ts
1162
- var import_bluebird = require("bluebird");
1163
- var import_dependency_graph = require("dependency-graph");
1013
+ var import_bluebird = __toESM(require("bluebird"));
1164
1014
  var DEFAULT_MAX_CONCURRENT_STREAMS = 5;
1165
1015
  var Tap = class {
1166
- _target;
1167
- _config;
1168
- _streams;
1169
- _concurrency = DEFAULT_MAX_CONCURRENT_STREAMS;
1016
+ target;
1017
+ config;
1018
+ streams;
1019
+ concurrency = DEFAULT_MAX_CONCURRENT_STREAMS;
1170
1020
  constructor(target, config) {
1171
- this._streams = [];
1172
- this._target = target;
1173
- this._config = config;
1174
- }
1175
- discover = async (existingCatalog) => {
1176
- logger.debug("Loading schemas");
1177
- const streamDepGraph = new import_dependency_graph.DepGraph();
1178
- const buildDependencyGraph = (streams2, parentId) => {
1179
- streams2.forEach((s) => {
1180
- streamDepGraph.addNode(s.streamId, s);
1181
- if (parentId) {
1182
- streamDepGraph.addDependency(s.streamId, parentId);
1183
- }
1184
- if (s.children) {
1185
- return buildDependencyGraph(s.children, s.streamId);
1186
- }
1187
- });
1188
- };
1189
- buildDependencyGraph(this._streams);
1190
- const discoveredStreamCatalogEntries = await import_bluebird.Promise.map(
1191
- streamDepGraph.overallOrder(),
1192
- async (streamId) => {
1193
- logger.info(`\u2728 Loading schema for ${streamId}`);
1194
- const stream = streamDepGraph.getNodeData(streamId);
1195
- const schema = await stream.getSchema();
1196
- const parentStreamIds = streamDepGraph.directDependenciesOf(streamId);
1197
- if (parentStreamIds.length > 1) {
1198
- throw new Error(`StreamId=${streamId} directly depends on more than 1 stream, e.g. ${parentStreamIds.join(",")} which is not supported!`);
1199
- }
1200
- const parentStreamId = parentStreamIds?.[0];
1201
- const { metadata } = await this.generateMetadataFromStream(stream, parentStreamId);
1202
- return {
1203
- schema,
1204
- metadata,
1205
- stream: stream.streamId,
1206
- tap_stream_id: stream.streamId
1207
- };
1208
- },
1209
- { concurrency: this._concurrency }
1210
- );
1211
- const existingCatalogStreamIds = (existingCatalog?.streams || []).map((entry) => {
1212
- return entry.stream;
1213
- });
1214
- const newlyDiscoveredStreamCatalogEntries = discoveredStreamCatalogEntries.filter((entry) => {
1215
- if (existingCatalogStreamIds.includes(entry.stream)) {
1216
- return false;
1217
- } else {
1218
- return true;
1219
- }
1220
- });
1221
- logger.debug(`Newly discovered streams: %j`, newlyDiscoveredStreamCatalogEntries);
1222
- const allDiscoveredStreamIds = discoveredStreamCatalogEntries.map((entry) => {
1223
- return entry.stream;
1224
- });
1225
- const existingCatalogMinusDeletedStreams = (existingCatalog?.streams || []).filter((entry) => {
1226
- if (!allDiscoveredStreamIds.includes(entry.stream)) {
1227
- logger.debug(`Stream %s was deleted, removing it from the catalog`, entry.stream);
1228
- return false;
1229
- } else {
1230
- return true;
1231
- }
1232
- });
1233
- const updatedExistingCatalog = existingCatalogMinusDeletedStreams.map((existingCatalogEntry) => {
1234
- const matchingDiscoveredCatalogEntry = discoveredStreamCatalogEntries.find((entry) => entry.stream === existingCatalogEntry.stream);
1235
- if (matchingDiscoveredCatalogEntry) {
1236
- const existingRootMetadata = existingCatalogEntry.metadata.find((metadata) => metadata.breadcrumb.length === 0);
1237
- const discoveredRootMetadata = matchingDiscoveredCatalogEntry.metadata.find((metadata) => metadata.breadcrumb.length === 0);
1238
- if (existingRootMetadata) {
1239
- const parentStreamVal = discoveredRootMetadata?.metadata["whaly-parent-stream"];
1240
- if (parentStreamVal !== void 0) {
1241
- existingRootMetadata.metadata["whaly-parent-stream"] = parentStreamVal;
1242
- }
1243
- const forcedReplicationMethodVal = discoveredRootMetadata?.metadata["forced-replication-method"];
1244
- if (forcedReplicationMethodVal !== void 0) {
1245
- existingRootMetadata.metadata["forced-replication-method"] = forcedReplicationMethodVal;
1246
- }
1247
- const forcedReplicationKeyVal = discoveredRootMetadata?.metadata["forced-replication-key"];
1248
- if (forcedReplicationKeyVal !== void 0) {
1249
- existingRootMetadata.metadata["forced-replication-key"] = forcedReplicationKeyVal;
1250
- }
1251
- const validReplicationKeysVal = discoveredRootMetadata?.metadata["valid-replication-keys"];
1252
- if (validReplicationKeysVal !== void 0) {
1253
- existingRootMetadata.metadata["valid-replication-keys"] = validReplicationKeysVal;
1254
- }
1255
- const rowCountVal = discoveredRootMetadata?.metadata["row-count"];
1256
- if (rowCountVal !== void 0) {
1257
- existingRootMetadata.metadata["row-count"] = rowCountVal;
1258
- }
1259
- }
1260
- }
1261
- return existingCatalogEntry;
1262
- });
1263
- const streams = updatedExistingCatalog.concat(newlyDiscoveredStreamCatalogEntries);
1264
- return { streams };
1265
- };
1266
- sync = async (catalog) => {
1267
- await this.initiateSync(catalog);
1268
- logger.debug(`[TAP] All streams have finished syncing. We send the [complete] signal to the target.`);
1269
- await this._target.complete();
1270
- return Promise.resolve();
1271
- };
1272
- async generateMetadataFromStream(stream, parentStreamId) {
1273
- const metadata = new StreamMetadata();
1274
- metadata.write([], "table-key-properties", stream.primaryKey);
1275
- const defaultReplicationConfig = stream.defaultReplicationConfig();
1276
- metadata.write([], "replication-method", defaultReplicationConfig.replicationMethod);
1277
- const validReplicationkeys = await stream.getValidReplicationKeys();
1278
- metadata.write([], "valid-replication-keys", validReplicationkeys);
1279
- if (defaultReplicationConfig.isForced) {
1280
- metadata.write([], "forced-replication-method", defaultReplicationConfig.replicationMethod);
1281
- if (stream.forcedReplicationKey) {
1282
- metadata.write([], "forced-replication-key", stream.forcedReplicationKey);
1283
- }
1284
- }
1285
- const rowCount = await stream.getRowCount();
1286
- if (rowCount !== void 0) {
1287
- metadata.write([], "row-count", rowCount);
1288
- }
1289
- if (stream.isSilent === true) {
1290
- metadata.write([], "whaly-is-hidden", stream.isSilent);
1291
- }
1292
- if (stream.isSilent === false) {
1293
- metadata.write([], "selected-by-default", stream.selectedByDefault);
1294
- }
1295
- if (stream.displayLabel) {
1296
- metadata.write([], "whaly-display-label", stream.displayLabel);
1297
- }
1298
- if (stream.description) {
1299
- metadata.write([], "whaly-description", stream.description);
1300
- }
1301
- if (parentStreamId !== void 0) {
1302
- metadata.write([], "whaly-parent-stream", parentStreamId);
1303
- }
1304
- return { metadata: metadata.toList() };
1021
+ this.streams = [];
1022
+ this.target = target;
1023
+ this.config = config;
1305
1024
  }
1306
- async initiateSync(catalog) {
1025
+ sync = async (options) => {
1307
1026
  logger.info(`\u{1F680} Start syncing`);
1308
1027
  const state = StateService.getInstance().get();
1309
1028
  logger.info(`\u{1F4CD} Received state: %j`, state);
1310
- logger.debug(`\u{1F4DA} Received catalog: %j`, catalog);
1311
- const selectedStreams = catalog.getSelectedStreams();
1312
- if (selectedStreams.length === 0) {
1313
- logger.info(`\u{1F631} There is no stream to sync.
1314
-
1315
- Did you update the \`catalog.json\` to add \`"selected": true\` in the table metadata associated with the root breadcrumb (e.g. \`[]\`)`);
1316
- return;
1317
- }
1318
- const selectedStreamIds = selectedStreams.map((stream) => stream.stream);
1319
- logger.info(`\u{1F973} Syncing selected streams: %s`, selectedStreamIds.join(","));
1320
- await import_bluebird.Promise.map(
1321
- this._streams,
1322
- (stream) => {
1323
- if (selectedStreamIds.includes(stream.streamId)) {
1324
- const selectedStream = selectedStreams.find(((selectedStream2) => selectedStream2.stream === stream.streamId));
1325
- const rootMetadataEntry = selectedStream?.metadata.find((streamMdt) => streamMdt.breadcrumb.length === 0);
1326
- if (!rootMetadataEntry) {
1327
- throw new Error(`Can't find a catalog root metadata entry for StreamId=${stream.streamId}`);
1328
- }
1329
- stream.setRootMetadataEntry(rootMetadataEntry.metadata);
1330
- return stream.sync();
1331
- }
1332
- },
1333
- {
1334
- concurrency: this._concurrency
1335
- }
1336
- );
1337
- }
1029
+ const envInclude = process.env.TAP_STREAMS ? process.env.TAP_STREAMS.split(",").map((s) => s.trim()).filter((s) => s.length > 0) : void 0;
1030
+ const include = options?.include && options.include.length > 0 ? options.include : envInclude;
1031
+ const exclude = new Set((options?.exclude || []).map((s) => s.trim()));
1032
+ let streamsToRun = this.streams.filter((s) => !s.isSilent);
1033
+ if (include && include.length > 0) {
1034
+ const includeSet = new Set(include);
1035
+ streamsToRun = streamsToRun.filter((s) => includeSet.has(s.streamId));
1036
+ }
1037
+ if (exclude.size > 0) {
1038
+ streamsToRun = streamsToRun.filter((s) => !exclude.has(s.streamId));
1039
+ }
1040
+ const selectedStreamIds = streamsToRun.map((s) => s.streamId);
1041
+ logger.info(`\u{1F973} Syncing streams: %s`, selectedStreamIds.join(","));
1042
+ await import_bluebird.default.map(streamsToRun, (stream) => {
1043
+ return stream.sync();
1044
+ }, { concurrency: this.concurrency });
1045
+ logger.debug(`[TAP] All streams have finished syncing. We send the [complete] signal to the target.`);
1046
+ await this.target.complete();
1047
+ return Promise.resolve();
1048
+ };
1338
1049
  // Used to clean up any ressource before exit
1339
1050
  end() {
1340
1051
  return Promise.resolve();
@@ -1343,15 +1054,11 @@ var Tap = class {
1343
1054
 
1344
1055
  // src/sdk/models/tap/stream.ts
1345
1056
  var import_util2 = require("util");
1346
- var StreamV2 = class {
1057
+ var Stream = class {
1347
1058
  // Runtime values, can't be overriden
1348
- _config;
1349
- _tapName = "default";
1350
- _tapState;
1351
- _target;
1352
- // Contains the root metadata entry of the catalog stream configuration
1353
- // contains some end user schema configuration
1354
- rootMetadataEntry;
1059
+ config;
1060
+ tapState;
1061
+ target;
1355
1062
  // Compile time values, can be overriden
1356
1063
  // Replication method that can be forced in the stream implemenation. Will prevail over any user/catalog choice
1357
1064
  forcedReplicationMethod = void 0;
@@ -1377,11 +1084,10 @@ var StreamV2 = class {
1377
1084
  // Metrics configuration
1378
1085
  rowsSyncedMetricsConf;
1379
1086
  executionTimeMetricsConf;
1380
- constructor(tapName, config, state, target, childConcurrency = DEFAULT_MAX_CONCURRENT_STREAMS) {
1381
- this._tapName = tapName;
1382
- this._config = config;
1383
- this._tapState = _2.cloneDeep(state);
1384
- this._target = target;
1087
+ constructor(config, state, target, childConcurrency = DEFAULT_MAX_CONCURRENT_STREAMS) {
1088
+ this.config = config;
1089
+ this.tapState = (0, import_cloneDeep.default)(state);
1090
+ this.target = target;
1385
1091
  this.childConcurrency = childConcurrency;
1386
1092
  this.rowsSyncedMetricsConf = {
1387
1093
  isEnabled: () => !this.isSilent,
@@ -1392,9 +1098,7 @@ var StreamV2 = class {
1392
1098
  getStreamIds: () => [this.streamId]
1393
1099
  };
1394
1100
  }
1395
- setRootMetadataEntry = (rootMetadataEntry) => {
1396
- this.rootMetadataEntry = rootMetadataEntry;
1397
- };
1101
+ // No root metadata: replication config is derived from stream defaults only
1398
1102
  /**
1399
1103
  * Sync this stream
1400
1104
  * Called only for streams with no parents, aka. "root tap streams"
@@ -1425,7 +1129,7 @@ var StreamV2 = class {
1425
1129
  `\u{1F6BD} Flushing ${replicationMethod} sync of stream '${this.streamId}' + all of its children...`
1426
1130
  );
1427
1131
  await this._flush();
1428
- await import_bluebird2.Promise.map(this.children, (child) => {
1132
+ await import_bluebird2.default.map(this.children, (child) => {
1429
1133
  return child.flush();
1430
1134
  }, { concurrency: 3 });
1431
1135
  };
@@ -1435,7 +1139,7 @@ var StreamV2 = class {
1435
1139
  */
1436
1140
  _writeStateMessage = () => {
1437
1141
  const message = new StateMessage(StateService.getInstance().get());
1438
- return this._target.state(message);
1142
+ return this.target.state(message);
1439
1143
  };
1440
1144
  /**
1441
1145
  * Write out a ACTIVATE_VERSION message.
@@ -1443,10 +1147,10 @@ var StreamV2 = class {
1443
1147
  _writeReplicationMethodMessage = async () => {
1444
1148
  const method = this.configuredReplicationConfig().replicationMethod;
1445
1149
  const message = new ReplicationMethodMessage(this.streamId, method);
1446
- await import_bluebird2.Promise.map(this.children, async (c) => {
1150
+ await import_bluebird2.default.map(this.children, async (c) => {
1447
1151
  return c._writeReplicationMethodMessage();
1448
1152
  }, { concurrency: 3 });
1449
- await this._target.replicationMethod(message);
1153
+ await this.target.replicationMethod(message);
1450
1154
  };
1451
1155
  /**
1452
1156
  * Write out a SCHEMA message with the stream schema.
@@ -1467,11 +1171,11 @@ var StreamV2 = class {
1467
1171
  ...this.description ? { description: this.description } : {},
1468
1172
  ...schema.propertiesMetadata ? { propertiesMetadata: schema.propertiesMetadata } : {}
1469
1173
  });
1470
- await this._target.schema(message);
1174
+ await this.target.schema(message);
1471
1175
  }
1472
1176
  }
1473
1177
  if (skipChildrenSchema !== true) {
1474
- await import_bluebird2.Promise.map(this.children, async (child) => {
1178
+ await import_bluebird2.default.map(this.children, async (child) => {
1475
1179
  await child._writeSchemaMessage();
1476
1180
  }, { concurrency: 3 });
1477
1181
  }
@@ -1546,8 +1250,8 @@ var StreamV2 = class {
1546
1250
  **/
1547
1251
  getStartingTimestamp() {
1548
1252
  const streamIdToReadFrom = this.useStateFromStreamId ? this.useStateFromStreamId : this.streamId;
1549
- const state = extractStateForStream(this._tapState, streamIdToReadFrom);
1550
- const startDate = this._config.start_date;
1253
+ const state = extractStateForStream(this.tapState, streamIdToReadFrom);
1254
+ const startDate = this.config.start_date;
1551
1255
  const replicationConfig = this.configuredReplicationConfig();
1552
1256
  logger.debug(`${this.streamId}: state.replicationKeyValue: ${state.replicationKeyValue},
1553
1257
  state.replicationKey: ${state.replicationKey},
@@ -1606,16 +1310,10 @@ var StreamV2 = class {
1606
1310
  * Return the configured replication method that will be used for the sync.
1607
1311
  */
1608
1312
  configuredReplicationConfig = () => {
1609
- const defaultReplicationMethod = this.defaultReplicationConfig();
1610
- if (defaultReplicationMethod.isForced) {
1611
- return {
1612
- replicationMethod: defaultReplicationMethod.replicationMethod,
1613
- replicationKey: defaultReplicationMethod.replicationKey
1614
- };
1615
- }
1313
+ const defaults = this.defaultReplicationConfig();
1616
1314
  return {
1617
- replicationMethod: this.rootMetadataEntry?.["replication-method"] || defaultReplicationMethod.replicationMethod,
1618
- replicationKey: this.rootMetadataEntry?.["replication-key"] || defaultReplicationMethod.replicationKey
1315
+ replicationMethod: defaults.replicationMethod,
1316
+ replicationKey: defaults.replicationKey
1619
1317
  };
1620
1318
  };
1621
1319
  // Private sync methods:
@@ -1645,9 +1343,9 @@ var StreamV2 = class {
1645
1343
  this.streamId
1646
1344
  );
1647
1345
  if (!this.isSilent) {
1648
- await this._target.record(recordMessage);
1346
+ await this.target.record(recordMessage);
1649
1347
  }
1650
- await import_bluebird2.Promise.map(
1348
+ await import_bluebird2.default.map(
1651
1349
  this.children,
1652
1350
  async (child) => {
1653
1351
  await child.asyncInit(row);
@@ -1691,7 +1389,7 @@ var StreamV2 = class {
1691
1389
  getSchema() {
1692
1390
  logger.debug(`stream: ${this.streamId} - getSchema() is called`);
1693
1391
  if (this.schemaPath) {
1694
- const schema = loadJson(`schemas/${this._tapName}/${this.schemaPath}`);
1392
+ const schema = loadJson(`schemas/${this.schemaPath}`);
1695
1393
  return Promise.resolve({ jsonSchema: schema });
1696
1394
  } else {
1697
1395
  if (this.isSilent) {
@@ -1728,7 +1426,7 @@ var StreamV2 = class {
1728
1426
  };
1729
1427
 
1730
1428
  // src/sdk/helpers/qs-logger.ts
1731
- var _3 = __toESM(require("lodash"));
1429
+ var import_isPlainObject = __toESM(require("lodash/isPlainObject.js"));
1732
1430
  var MAX_QS_KEYS = 10;
1733
1431
  var MAX_QS_STRING_LENGTH = 200;
1734
1432
  var MAX_QS_ARRAY_ITEMS = 5;
@@ -1749,7 +1447,7 @@ function truncateQueryParams(value, depth = 0) {
1749
1447
  }
1750
1448
  return items;
1751
1449
  }
1752
- if (_3.isPlainObject(value)) {
1450
+ if ((0, import_isPlainObject.default)(value)) {
1753
1451
  const keys = Object.keys(value);
1754
1452
  const result = {};
1755
1453
  for (const key of keys.slice(0, MAX_QS_KEYS)) {
@@ -1772,11 +1470,12 @@ function getTruncatedParamsForLog(params) {
1772
1470
  }
1773
1471
 
1774
1472
  // src/sdk/models/tap/restStream.ts
1775
- var _4 = __toESM(require("lodash"));
1776
- var RESTStreamV2 = class extends StreamV2 {
1473
+ var import_cloneDeep2 = __toESM(require("lodash/cloneDeep.js"));
1474
+ var import_isEqual = __toESM(require("lodash/isEqual.js"));
1475
+ var RESTStream = class extends Stream {
1777
1476
  axiosInstance;
1778
- constructor(tapName, config, state, target, childConcurrency = DEFAULT_MAX_CONCURRENT_STREAMS) {
1779
- super(tapName, config, state, target, childConcurrency);
1477
+ constructor(config, state, target, childConcurrency = DEFAULT_MAX_CONCURRENT_STREAMS) {
1478
+ super(config, state, target, childConcurrency);
1780
1479
  this.apiCallsMetricsConf = {
1781
1480
  isEnabled: () => !this.isSilent,
1782
1481
  getStreamIds: () => [this.streamId]
@@ -1799,7 +1498,7 @@ var RESTStreamV2 = class extends StreamV2 {
1799
1498
  const authenticator = this.authenticator;
1800
1499
  const params = {
1801
1500
  ...this.getNextUrlParams(nextPageToken, parent),
1802
- ...await authenticator?.getAuthQS(this._config)
1501
+ ...await authenticator?.getAuthQS(this.config)
1803
1502
  };
1804
1503
  const requestBody = this.getRequestBodyForNextCall(nextPageToken, parent);
1805
1504
  let headers = this.getCustomHTTPHeaders(parent);
@@ -1807,7 +1506,7 @@ var RESTStreamV2 = class extends StreamV2 {
1807
1506
  headers = {};
1808
1507
  }
1809
1508
  if (authenticator) {
1810
- const authHeaders = await authenticator.getAuthHeaders(this._config);
1509
+ const authHeaders = await authenticator.getAuthHeaders(this.config);
1811
1510
  headers = {
1812
1511
  ...headers,
1813
1512
  ...authHeaders
@@ -1890,9 +1589,9 @@ var RESTStreamV2 = class extends StreamV2 {
1890
1589
  for await (const row of rows) {
1891
1590
  yield row;
1892
1591
  }
1893
- const previousToken = _4.cloneDeep(nextPageToken);
1592
+ const previousToken = (0, import_cloneDeep2.default)(nextPageToken);
1894
1593
  nextPageToken = this.getNextPageToken(resp, previousToken);
1895
- if (nextPageToken && _4.isEqual(nextPageToken, previousToken)) {
1594
+ if (nextPageToken && (0, import_isEqual.default)(nextPageToken, previousToken)) {
1896
1595
  throw new Error(
1897
1596
  `${this.streamId} - Loop detected in pagination. "
1898
1597
  Pagination token: \`${JSON.stringify(nextPageToken)}\` is identical to prior token \`${JSON.stringify(previousToken)}\`.`
@@ -2093,20 +1792,20 @@ var StreamWarehouseSyncService = class {
2093
1792
  const columnNamesFromWarehouse = columnsFromWarehouse.map((col) => col.name);
2094
1793
  const columnsMappingStore = this.renamedColumnStore.getUnsafeToSafeColumnMapping(this.streamId);
2095
1794
  const columnsToAdd = Object.keys(columnsMappingStore).filter((unsafeColumnKey) => {
2096
- const safeColumnName = columnsMappingStore[unsafeColumnKey];
2097
- if (!safeColumnName) {
1795
+ const safeColumnName2 = columnsMappingStore[unsafeColumnKey];
1796
+ if (!safeColumnName2) {
2098
1797
  return false;
2099
1798
  }
2100
- return !columnNamesFromWarehouse.includes(safeColumnName);
1799
+ return !columnNamesFromWarehouse.includes(safeColumnName2);
2101
1800
  }).map((unsafeColumnKey) => {
2102
- const safeColumnName = columnsMappingStore[unsafeColumnKey];
1801
+ const safeColumnName2 = columnsMappingStore[unsafeColumnKey];
2103
1802
  const definition = this.flattenedSchema[unsafeColumnKey];
2104
- if (!safeColumnName || !definition) {
1803
+ if (!safeColumnName2 || !definition) {
2105
1804
  return void 0;
2106
1805
  }
2107
1806
  return {
2108
1807
  unsafeName: unsafeColumnKey,
2109
- name: safeColumnName,
1808
+ name: safeColumnName2,
2110
1809
  definition
2111
1810
  };
2112
1811
  }).filter((item) => !!item);
@@ -2328,10 +2027,10 @@ var import_moment3 = __toESM(require("moment"));
2328
2027
 
2329
2028
  // src/sdk/models/target/temporaryFile.ts
2330
2029
  var import_fs_extra2 = __toESM(require("fs-extra"));
2331
- var import_lodash = require("lodash");
2030
+ var import_uniqueId = __toESM(require("lodash/uniqueId.js"));
2332
2031
  var createTemporaryFileStream = (streamId) => {
2333
2032
  import_fs_extra2.default.ensureDirSync("./tmp");
2334
- const path = `./tmp/${safePath(streamId)}-${(0, import_lodash.uniqueId)()}.tmp`;
2033
+ const path = `./tmp/${safePath(streamId)}-${(0, import_uniqueId.default)()}.tmp`;
2335
2034
  const writeStream = import_fs_extra2.default.createWriteStream(path, { flags: "w" });
2336
2035
  return {
2337
2036
  stream: writeStream,
@@ -2456,7 +2155,7 @@ var StreamState = class {
2456
2155
 
2457
2156
  // src/sdk/models/target/target.ts
2458
2157
  var import_async_mutex = require("async-mutex");
2459
- var import_bluebird3 = require("bluebird");
2158
+ var import_bluebird3 = __toESM(require("bluebird"));
2460
2159
  var semaphore = new import_async_mutex.Semaphore(1);
2461
2160
  var ITarget = class _ITarget {
2462
2161
  config;
@@ -2701,7 +2400,7 @@ var ITarget = class _ITarget {
2701
2400
  })
2702
2401
  }
2703
2402
  };
2704
- await import_bluebird3.Promise.map(this.schemaHooks, async (hook) => {
2403
+ await import_bluebird3.default.map(this.schemaHooks, async (hook) => {
2705
2404
  const input = {
2706
2405
  databaseName,
2707
2406
  schemaName,
@@ -2782,7 +2481,7 @@ var ITarget = class _ITarget {
2782
2481
  };
2783
2482
  uploadStreamsToWarehouse = async (streamsToUpload) => {
2784
2483
  try {
2785
- await import_bluebird3.Promise.map(streamsToUpload, async (streamId) => {
2484
+ await import_bluebird3.default.map(streamsToUpload, async (streamId) => {
2786
2485
  logger.info(`\u{1F4E4} Upload stream: ${streamId} to Warehouse`);
2787
2486
  const streamState = this.streams[streamId];
2788
2487
  if (streamState) {
@@ -2816,20 +2515,644 @@ var ITarget = class _ITarget {
2816
2515
  }
2817
2516
  };
2818
2517
  };
2518
+
2519
+ // src/targets/bigquery/helpers.ts
2520
+ var safeColumnName = (key) => {
2521
+ let returnString = key;
2522
+ const shouldNotStartWith = ["_TABLE_", "_FILE_", "_PARTITION"];
2523
+ shouldNotStartWith.forEach((snm) => {
2524
+ if (returnString.startsWith(snm)) {
2525
+ returnString = returnString.replace(snm, "");
2526
+ }
2527
+ });
2528
+ returnString = returnString.replace(/^[-\d\s]*/g, "");
2529
+ returnString = returnString.toLowerCase();
2530
+ returnString = returnString.replace("`", "");
2531
+ returnString = returnString.normalize("NFD").replace(/[\u0300-\u036f]/g, "");
2532
+ if (returnString.length > 300) {
2533
+ returnString = returnString.substr(0, 300);
2534
+ }
2535
+ const pattern = /[^a-zA-Z0-9_]/gm;
2536
+ return returnString.replace(pattern, "_");
2537
+ };
2538
+ var safeTableName = (key) => {
2539
+ let returnString = key;
2540
+ returnString = returnString.toLowerCase();
2541
+ returnString = returnString.replace("`", "");
2542
+ returnString = returnString.normalize("NFD").replace(/[\u0300-\u036f]/g, "");
2543
+ if (returnString.length > 1024) {
2544
+ returnString = returnString.substr(0, 1024);
2545
+ }
2546
+ const pattern = /[^a-zA-Z0-9_]/gm;
2547
+ return returnString.replace(pattern, "_");
2548
+ };
2549
+
2550
+ // src/targets/bigquery/service/record.ts
2551
+ var import_decimal = __toESM(require("decimal.js"));
2552
+ var import_moment5 = __toESM(require("moment"));
2553
+ var validateDateRange = (record, schema) => {
2554
+ Object.keys(schema).forEach((key) => {
2555
+ const { format: format3 } = schema[key];
2556
+ if (format3 === "date-time") {
2557
+ if (record[key]) {
2558
+ const formattedDate = (0, import_moment5.default)(record[key]).format(defaultDateTimeFormat);
2559
+ const isNotTooMuchInTheFuture = (0, import_moment5.default)(record[key]).isBefore((0, import_moment5.default)("9999-12-31 23:59:59.999999"));
2560
+ const isNotTooMuchInThePast = (0, import_moment5.default)(record[key]).isAfter((0, import_moment5.default)("0001-01-01 00:00:00"));
2561
+ if (formattedDate !== "Invalid date" && isNotTooMuchInTheFuture && isNotTooMuchInThePast) {
2562
+ record[key] = formattedDate;
2563
+ } else {
2564
+ record[key] = void 0;
2565
+ logger.info("Skipping date for key %s for being invalid", key);
2566
+ }
2567
+ }
2568
+ }
2569
+ });
2570
+ return record;
2571
+ };
2572
+ var maxBQNumericValue = new import_decimal.default("9.9999999999999999999999999999999999999E+28");
2573
+ var convertNumberIntoDecimal = (record, schema) => {
2574
+ Object.keys(record).forEach((key) => {
2575
+ if (schema[key]) {
2576
+ const { type, items } = schema[key];
2577
+ const types = type instanceof Array ? type : [type];
2578
+ if (types.includes("number")) {
2579
+ if (typeof record[key] === "number" || record[key] instanceof import_decimal.default) {
2580
+ const decimal = new import_decimal.default(record[key]).toDecimalPlaces(9);
2581
+ if (decimal.greaterThanOrEqualTo(maxBQNumericValue)) {
2582
+ record[key] = null;
2583
+ } else {
2584
+ record[key] = decimal;
2585
+ }
2586
+ } else {
2587
+ record[key] = null;
2588
+ }
2589
+ } else if (types.includes("array") && items?.type.includes("number")) {
2590
+ if (Array.isArray(record[key])) {
2591
+ const rawArr = record[key];
2592
+ const newArr = rawArr.map((item) => {
2593
+ if (typeof item === "number" || item instanceof import_decimal.default) {
2594
+ const parsed = new import_decimal.default(item).toDecimalPlaces(9);
2595
+ if (parsed.greaterThanOrEqualTo(maxBQNumericValue)) {
2596
+ return void 0;
2597
+ } else {
2598
+ return parsed;
2599
+ }
2600
+ } else {
2601
+ return void 0;
2602
+ }
2603
+ }).filter((item) => !!item);
2604
+ record[key] = newArr;
2605
+ } else {
2606
+ record[key] = null;
2607
+ }
2608
+ }
2609
+ }
2610
+ });
2611
+ return record;
2612
+ };
2613
+
2614
+ // src/targets/bigquery/service/dbSync.ts
2615
+ var import_moment6 = __toESM(require("moment"));
2616
+
2617
+ // src/targets/bigquery/service/bigquery.ts
2618
+ var import_bigquery = require("@google-cloud/bigquery");
2619
+ var BqClientHolder = class {
2620
+ static instance;
2621
+ client;
2622
+ constructor(config) {
2623
+ const retryOptions = {
2624
+ autoRetry: true,
2625
+ maxRetries: 3
2626
+ };
2627
+ this.client = new import_bigquery.BigQuery({
2628
+ projectId: config.database.trim(),
2629
+ ...retryOptions
2630
+ });
2631
+ }
2632
+ static client(config) {
2633
+ if (!this.instance) {
2634
+ this.instance = new this(config);
2635
+ }
2636
+ return this.instance.client;
2637
+ }
2638
+ };
2639
+
2640
+ // src/targets/bigquery/service/cloudStorage.ts
2641
+ var import_storage = require("@google-cloud/storage");
2642
+
2643
+ // node_modules/uuid/dist/esm-node/rng.js
2644
+ var import_crypto = __toESM(require("crypto"));
2645
+ var rnds8Pool = new Uint8Array(256);
2646
+ var poolPtr = rnds8Pool.length;
2647
+ function rng() {
2648
+ if (poolPtr > rnds8Pool.length - 16) {
2649
+ import_crypto.default.randomFillSync(rnds8Pool);
2650
+ poolPtr = 0;
2651
+ }
2652
+ return rnds8Pool.slice(poolPtr, poolPtr += 16);
2653
+ }
2654
+
2655
+ // node_modules/uuid/dist/esm-node/regex.js
2656
+ var regex_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;
2657
+
2658
+ // node_modules/uuid/dist/esm-node/validate.js
2659
+ function validate(uuid) {
2660
+ return typeof uuid === "string" && regex_default.test(uuid);
2661
+ }
2662
+ var validate_default = validate;
2663
+
2664
+ // node_modules/uuid/dist/esm-node/stringify.js
2665
+ var byteToHex = [];
2666
+ for (let i = 0; i < 256; ++i) {
2667
+ byteToHex.push((i + 256).toString(16).substr(1));
2668
+ }
2669
+ function stringify3(arr, offset = 0) {
2670
+ 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();
2671
+ if (!validate_default(uuid)) {
2672
+ throw TypeError("Stringified UUID is invalid");
2673
+ }
2674
+ return uuid;
2675
+ }
2676
+ var stringify_default = stringify3;
2677
+
2678
+ // node_modules/uuid/dist/esm-node/v4.js
2679
+ function v4(options, buf, offset) {
2680
+ options = options || {};
2681
+ const rnds = options.random || (options.rng || rng)();
2682
+ rnds[6] = rnds[6] & 15 | 64;
2683
+ rnds[8] = rnds[8] & 63 | 128;
2684
+ if (buf) {
2685
+ offset = offset || 0;
2686
+ for (let i = 0; i < 16; ++i) {
2687
+ buf[offset + i] = rnds[i];
2688
+ }
2689
+ return buf;
2690
+ }
2691
+ return stringify_default(rnds);
2692
+ }
2693
+ var v4_default = v4;
2694
+
2695
+ // src/targets/bigquery/service/cloudStorage.ts
2696
+ var uploadFileInBucket = async (streamId, gcsBuckerName, filePath) => {
2697
+ try {
2698
+ const retryOptions = { autoRetry: true, maxRetries: 20 };
2699
+ let storage = new import_storage.Storage({ retryOptions });
2700
+ const bucketRef = storage.bucket(gcsBuckerName);
2701
+ await bucketRef.get({ autoCreate: false });
2702
+ const destinationFileName = `${streamId}-${v4_default()}.jsonnl`;
2703
+ await bucketRef.upload(filePath, {
2704
+ destination: destinationFileName
2705
+ });
2706
+ logger.info(`\u{1F5F3} Uploaded ${filePath} into ${gcsBuckerName}/${destinationFileName} GCS File`);
2707
+ return bucketRef.file(destinationFileName);
2708
+ } catch (err) {
2709
+ logger.error(`Issue when uploading file into GCS bucket for stream: ${streamId}
2710
+
2711
+ Error: ${err.message}
2712
+ Stack: ${err.stack}
2713
+ Code: ${err.code}
2714
+ `);
2715
+ if (err.code < 500) {
2716
+ await haltAndCatchFire(
2717
+ `unauthorized`,
2718
+ `We couldn't connect to your Cloud Storage bucket \u{1F614}
2719
+
2720
+ The error from Google is: '${err.message}' \u{1F440}
2721
+
2722
+ Could you troubleshoot your Cloud Storage configuration in Google Cloud and sync again the source? \u{1F64F}`,
2723
+ `Got error from cloud storage lib`
2724
+ );
2725
+ }
2726
+ throw err;
2727
+ }
2728
+ };
2729
+
2730
+ // src/targets/bigquery/service/dbSync.ts
2731
+ var import_chunk = __toESM(require("lodash/chunk.js"));
2732
+ var import_async_mutex2 = require("async-mutex");
2733
+ var semaphore2 = new import_async_mutex2.Semaphore(1);
2734
+ var BigQueryDBSync = class extends StreamWarehouseSyncService {
2735
+ config;
2736
+ bqClient;
2737
+ bqDataset;
2738
+ bqTable;
2739
+ bqStagingTable;
2740
+ tableName;
2741
+ stagingTableName;
2742
+ sqlTableId;
2743
+ sqlStagingTableId;
2744
+ constructor(config, streamId, database, schema, table, renameColumnStore) {
2745
+ super(
2746
+ streamId,
2747
+ database,
2748
+ schema,
2749
+ table,
2750
+ renameColumnStore
2751
+ );
2752
+ this.config = config;
2753
+ this.bqClient = BqClientHolder.client(config);
2754
+ this.bqDataset = this.bqClient.dataset(schema, { location: config.location || "EU" });
2755
+ this.bqTable = this.bqDataset.table(table, { location: config.location || "EU" });
2756
+ this.tableName = table;
2757
+ this.stagingTableName = `${table}_temp`;
2758
+ this.bqStagingTable = this.bqDataset.table(this.stagingTableName, { location: config.location || "EU" });
2759
+ this.sqlTableId = `${schema}.${table}`;
2760
+ this.sqlStagingTableId = `${this.sqlTableId}_temp`;
2761
+ }
2762
+ // Implementation of abstract classes
2763
+ getSerializedRecord = (record) => {
2764
+ return JSON.stringify(record) + `
2765
+ `;
2766
+ };
2767
+ safeColumnName = safeColumnName;
2768
+ getWarehouseTypeFromJSONSchema = (definition) => {
2769
+ const type = definition.type;
2770
+ const format3 = definition.format;
2771
+ let typeArr;
2772
+ if (type instanceof Array) {
2773
+ typeArr = type;
2774
+ } else {
2775
+ typeArr = [type];
2776
+ }
2777
+ if (format3) {
2778
+ switch (format3) {
2779
+ case "date-time":
2780
+ return "TIMESTAMP";
2781
+ case "json":
2782
+ return "STRING";
2783
+ default:
2784
+ throw new Error(`StreamId: ${this.streamId} - Unsupported format: ${format3}`);
2785
+ }
2786
+ } else if (typeArr.includes("number")) {
2787
+ return "NUMERIC";
2788
+ } else if (typeArr.includes("integer") && type.includes("string")) {
2789
+ return "NUMERIC";
2790
+ } else if (typeArr.includes("integer")) {
2791
+ return "INTEGER";
2792
+ } else if (typeArr.includes("boolean")) {
2793
+ return "BOOLEAN";
2794
+ } else if (typeArr.includes("string")) {
2795
+ return "STRING";
2796
+ } else if (typeArr.includes("array")) {
2797
+ const items = definition.items;
2798
+ if (items) {
2799
+ return this.getWarehouseTypeFromJSONSchema(items);
2800
+ }
2801
+ throw new Error(`StreamId: ${this.streamId} - Unsupported array schema field definition: ${JSON.stringify(definition)}`);
2802
+ } else {
2803
+ throw new Error(`StreamId: ${this.streamId} - Unsupported schema field definition: ${JSON.stringify(definition)}`);
2804
+ }
2805
+ };
2806
+ getMergeQueries = () => {
2807
+ const primaryKeyCondition = this.primaryKeys.map((pk) => {
2808
+ return `\`sourced\`.\`${pk}\` = \`destination\`.\`${pk}\``;
2809
+ }).join(` AND `);
2810
+ const primaryKeys = this.primaryKeys.map((pk) => `\`${pk}\``).join(` ,`);
2811
+ const columnUnsafeToSafeMapping = this.renamedColumnStore.getUnsafeToSafeColumnMapping(this.streamId);
2812
+ const columns = Object.keys(columnUnsafeToSafeMapping).map((column) => {
2813
+ return {
2814
+ isUnsafe: true,
2815
+ colName: column
2816
+ };
2817
+ });
2818
+ const columnsChunks = (0, import_chunk.default)(columns, 300).map((chunk2) => {
2819
+ this.primaryKeys.forEach((pk) => {
2820
+ if (!chunk2.map((c) => columnUnsafeToSafeMapping[c.colName]).includes(pk)) {
2821
+ chunk2.push({
2822
+ isUnsafe: false,
2823
+ colName: pk
2824
+ });
2825
+ }
2826
+ });
2827
+ return chunk2;
2828
+ });
2829
+ return columnsChunks.map((chunk2) => {
2830
+ const setValues = chunk2.map((column) => {
2831
+ if (column.isUnsafe) {
2832
+ return `\`destination\`.\`${columnUnsafeToSafeMapping[column.colName]}\` = \`sourced\`.\`${columnUnsafeToSafeMapping[column.colName]}\``;
2833
+ } else {
2834
+ return `\`destination\`.\`${column.colName}\` = \`sourced\`.\`${column.colName}\``;
2835
+ }
2836
+ }).join(`, `);
2837
+ const renamedCols = chunk2.map((column) => {
2838
+ if (column.isUnsafe) {
2839
+ return `\`${columnUnsafeToSafeMapping[column.colName]}\``;
2840
+ } else {
2841
+ return `\`${column.colName}\``;
2842
+ }
2843
+ }).join(`, `);
2844
+ const query = `
2845
+ MERGE ${this.sqlTableId} destination
2846
+ USING (
2847
+ WITH all_staging_rows AS (
2848
+ SELECT *
2849
+ FROM ${this.sqlStagingTableId}
2850
+ ),
2851
+ numbered_rows AS (
2852
+ SELECT *,
2853
+ ROW_NUMBER() OVER (PARTITION BY ${primaryKeys}) as _wly_row_nb,
2854
+ COUNT(1) OVER (PARTITION BY ${primaryKeys}) AS _wly_partition_size,
2855
+ FROM all_staging_rows
2856
+ ),
2857
+ staging_deduped AS (
2858
+ SELECT * EXCEPT(_wly_partition_size, _wly_row_nb)
2859
+ FROM numbered_rows
2860
+ WHERE _wly_partition_size = _wly_row_nb
2861
+ )
2862
+ SELECT *
2863
+ FROM staging_deduped
2864
+ ) AS sourced
2865
+ ON ${primaryKeyCondition}
2866
+ WHEN MATCHED THEN
2867
+ UPDATE SET ${setValues}
2868
+ WHEN NOT MATCHED THEN
2869
+ INSERT (${renamedCols}) VALUES (${renamedCols});
2870
+ `;
2871
+ return query;
2872
+ });
2873
+ };
2874
+ getReplaceQueries = () => {
2875
+ return [
2876
+ `TRUNCATE TABLE ${this.sqlTableId};`,
2877
+ ...this.getMergeQueries()
2878
+ ];
2879
+ };
2880
+ createDatabaseAndSchemaIfNotExists = async (retryCount) => {
2881
+ try {
2882
+ await semaphore2.runExclusive(async () => {
2883
+ const [exists] = await this.bqDataset.exists();
2884
+ if (!exists) {
2885
+ logger.info(`\u{1F423} Creating dataset: ${this.bqDataset.id} on BigQuery`);
2886
+ await this.bqDataset.create();
2887
+ } else {
2888
+ const [metadata] = await this.bqDataset.getMetadata();
2889
+ const alreadyExistinglocation = metadata.location;
2890
+ if (this.config.location && this.config.location !== alreadyExistinglocation) {
2891
+ await haltAndCatchFire(
2892
+ `unknown`,
2893
+ `A BigQuery dataset called '${this.bqDataset.id}' already exists in location: '${alreadyExistinglocation}' \u{1F605}
2894
+
2895
+ 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 \u{1F63F}
2896
+
2897
+ 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? \u{1F64F}
2898
+
2899
+ Please relaunch the connector once it's done to fix the issue \u{1F917}
2900
+ `,
2901
+ `
2902
+ We have a conflict between an already existing dataset in location ${alreadyExistinglocation} and the configured location: ${this.config.location}
2903
+ `
2904
+ );
2905
+ throw Error();
2906
+ }
2907
+ logger.info(`\u{1F44B} Dataset: ${this.bqDataset.id} already exists on BigQuery, reusing it.`);
2908
+ }
2909
+ });
2910
+ } catch (err) {
2911
+ if (err.code === 400) {
2912
+ await haltAndCatchFire(
2913
+ `unauthorized`,
2914
+ `We can't connect to your BigQuery account \u{1F614}
2915
+
2916
+ Here is the message from BigQuery: ${err.message}
2917
+
2918
+ Can you check that your Warehouse credentials and Source target schema are properly configured and try to sync again the source? \u{1F64F}
2919
+ `,
2920
+ `Got error when trying to get Dataset from BigQuery: ${err.message} - ${err.code}`
2921
+ );
2922
+ return;
2923
+ }
2924
+ if (retryCount && retryCount > this.maxRetryCount) {
2925
+ logger.error(`StreamId: ${this.streamId} - Error when checking if dataset already exists. ${err.message} - ${err.code}`);
2926
+ gracefulExit(1);
2927
+ } else {
2928
+ logger.error(`StreamId: ${this.streamId} - Error when checking if dataset already exists. Retrying... ${err.message} - ${err.code}`);
2929
+ await new Promise((resolve, reject) => setTimeout(resolve, 1e3 * retryCount));
2930
+ await this.createDatabaseAndSchemaIfNotExists(retryCount + 1);
2931
+ }
2932
+ }
2933
+ return Promise.resolve();
2934
+ };
2935
+ createTable = async () => {
2936
+ try {
2937
+ const tableName = this.tableName;
2938
+ const schema = this.generateBigquerySchema();
2939
+ logger.info(`\u{1F423} Creating table: ${tableName} on BigQuery`);
2940
+ const createTableOptions = {
2941
+ schema
2942
+ };
2943
+ await this.bqDataset.createTable(
2944
+ tableName,
2945
+ createTableOptions
2946
+ );
2947
+ return;
2948
+ } catch (err) {
2949
+ throw new Error(`StreamId: ${this.streamId} - Issue when creating table in BigQuery
2950
+
2951
+ Error: ${err.message}
2952
+ Stack: ${err.stack}`);
2953
+ }
2954
+ };
2955
+ addColumns = async (tableFields) => {
2956
+ if (tableFields.length > 0) {
2957
+ logger.info(`\u{1F195} Stream: ${this.streamId} - Adding following columns in BigQuery schema: ${JSON.stringify(tableFields)}`);
2958
+ const [metadata] = await this.bqTable.getMetadata();
2959
+ const bgTableFields = tableFields.map((tblField) => {
2960
+ return this.getBigqueryTableFieldFromInternalSchemaFieldDefinition(tblField.name, tblField.definition);
2961
+ }).filter((fld) => {
2962
+ return !!fld;
2963
+ });
2964
+ const schema = metadata.schema;
2965
+ const new_schema = {
2966
+ ...schema,
2967
+ fields: schema.fields.concat(bgTableFields)
2968
+ };
2969
+ metadata.schema = new_schema;
2970
+ await this.bqTable.setMetadata(metadata);
2971
+ return;
2972
+ }
2973
+ };
2974
+ createStagingArea = async () => {
2975
+ try {
2976
+ const tableName = this.stagingTableName;
2977
+ const [exists] = await this.bqDataset.table(tableName).exists();
2978
+ if (exists) {
2979
+ logger.info(`\u{1F474} Temporary table ${tableName} already exists, it should be a relic form the past.
2980
+ Dropping it.`);
2981
+ await this.deleteStagingArea();
2982
+ }
2983
+ const schema = this.generateBigquerySchema();
2984
+ const expirationTime = (0, import_moment6.default)().add("1", "day").valueOf().toString();
2985
+ const createTableOptions = {
2986
+ schema,
2987
+ expirationTime
2988
+ };
2989
+ logger.info(`\u{1F423} Creating staging table: ${tableName} on BigQuery`);
2990
+ await this.bqDataset.createTable(
2991
+ tableName,
2992
+ createTableOptions
2993
+ );
2994
+ return;
2995
+ } catch (err) {
2996
+ throw new Error(`StreamId: ${this.streamId} - Issue when creating table in BigQuery
2997
+
2998
+ Error: ${err.message}
2999
+ Stack: ${err.stack}`);
3000
+ }
3001
+ };
3002
+ loadStreamInStagingArea = async (localFilePath) => {
3003
+ try {
3004
+ const file = await uploadFileInBucket(
3005
+ this.streamId,
3006
+ this.config.loading_deck_gcs_bucket_name,
3007
+ localFilePath
3008
+ );
3009
+ const metadata = {
3010
+ sourceFormat: "NEWLINE_DELIMITED_JSON",
3011
+ writeDisposition: "WRITE_TRUNCATE"
3012
+ };
3013
+ await this.loadGCSFileInTable(this.sqlStagingTableId, file, metadata);
3014
+ } catch (err) {
3015
+ logger.error(`StreamId: ${this.streamId} - Error while uploading stream.`);
3016
+ throw err;
3017
+ }
3018
+ };
3019
+ deleteStagingArea = () => {
3020
+ const query = `DROP TABLE IF EXISTS ${this.sqlStagingTableId};`;
3021
+ return this.runQueriesWithRetry([query]);
3022
+ };
3023
+ getTablesInSchema = async () => {
3024
+ const [bqTables] = await this.bqDataset.getTables();
3025
+ const foundTables = bqTables.filter((tbl) => {
3026
+ return !!tbl.id;
3027
+ }).map((bqTable) => {
3028
+ return {
3029
+ tableName: bqTable.id
3030
+ };
3031
+ });
3032
+ return foundTables;
3033
+ };
3034
+ getTableColumnsFromWarehouse = async () => {
3035
+ const [table] = await this.bqTable.getMetadata();
3036
+ return table.schema.fields;
3037
+ };
3038
+ runQueries = async (queries) => {
3039
+ const sqlQuery = `
3040
+ BEGIN
3041
+ ${queries.join(`
3042
+ `)}
3043
+ END;
3044
+ `;
3045
+ await this.bqClient.query(sqlQuery);
3046
+ };
3047
+ // Specific methods
3048
+ /**
3049
+ *
3050
+ * Generate a TableField definition object that can be passed to BigQuery APIs to define a column on a table
3051
+ *
3052
+ * @param colName
3053
+ * @param schemaFieldDefinition
3054
+ * @returns
3055
+ */
3056
+ getBigqueryTableFieldFromInternalSchemaFieldDefinition = (colName, schemaFieldDefinition) => {
3057
+ const name = colName;
3058
+ if (!schemaFieldDefinition) {
3059
+ throw new Error(`StreamId: ${this.streamId} - Schema is unknown for colName=${colName}, so we can't infer the proper BigQuery definition for this column.`);
3060
+ }
3061
+ const type = schemaFieldDefinition.type;
3062
+ let typeArr;
3063
+ if (type instanceof Array) {
3064
+ typeArr = type;
3065
+ } else {
3066
+ typeArr = [type];
3067
+ }
3068
+ if (typeArr.includes("array")) {
3069
+ return {
3070
+ name,
3071
+ mode: "REPEATED",
3072
+ type: this.getWarehouseTypeFromJSONSchema(schemaFieldDefinition)
3073
+ };
3074
+ } else {
3075
+ let nullableMode = "NULLABLE";
3076
+ return {
3077
+ name,
3078
+ mode: nullableMode,
3079
+ type: this.getWarehouseTypeFromJSONSchema(schemaFieldDefinition)
3080
+ };
3081
+ }
3082
+ };
3083
+ generateBigquerySchema = () => {
3084
+ const unsafeToSafeMappingColumnsFromColumnStore = this.renamedColumnStore.getUnsafeToSafeColumnMapping(this.streamId);
3085
+ if (!unsafeToSafeMappingColumnsFromColumnStore) {
3086
+ throw new Error(`StreamId: ${this.streamId} - There is no unsafe->safe column mapping`);
3087
+ }
3088
+ return Object.keys(unsafeToSafeMappingColumnsFromColumnStore).reduce((acc, unsafeKey) => {
3089
+ const renamedColName = this.renamedColumnStore.getColumnTranslation(this.streamId, unsafeKey);
3090
+ const bigqueryTableField = this.getBigqueryTableFieldFromInternalSchemaFieldDefinition(renamedColName, this.flattenedSchema[unsafeKey]);
3091
+ if (bigqueryTableField) {
3092
+ acc.push(bigqueryTableField);
3093
+ }
3094
+ return acc;
3095
+ }, []);
3096
+ };
3097
+ loadGCSFileInTable = async (tableName, file, metadata) => {
3098
+ try {
3099
+ const [job] = await this.bqStagingTable.load(file, metadata);
3100
+ logger.info(`\u{1F69A} Loaded GCS file \`${file.id}\` in BigQuery table: ${tableName} with Job: \`${job.id}\``);
3101
+ logger.debug(`Upload Stats: ${JSON.stringify(job.statistics)}`);
3102
+ const errors2 = job.status?.errors;
3103
+ if (errors2 && errors2.length > 0) {
3104
+ throw errors2;
3105
+ }
3106
+ } catch (err) {
3107
+ logger.error(err);
3108
+ throw new Error(`StreamId: ${this.streamId} - Issue when loading file in BigQuery table | fileName: ${file.name}, tableName: ${tableName}
3109
+
3110
+ Error: ${err.message}
3111
+ Stack: ${err.stack}`);
3112
+ }
3113
+ };
3114
+ };
3115
+
3116
+ // src/targets/bigquery/main.ts
3117
+ var BigQueryTarget = class extends ITarget {
3118
+ constructor(config, resolver) {
3119
+ super(config, resolver);
3120
+ this.renameColumnStore.setSafeColumnNameConverter(this.safeColumnNameConverter);
3121
+ }
3122
+ static requiredConfigKeys = [
3123
+ "schema",
3124
+ "project_id",
3125
+ "loading_deck_gcs_bucket_name"
3126
+ ];
3127
+ newDBSyncInstance = (streamId, database, schema, table) => {
3128
+ return new BigQueryDBSync(
3129
+ this.config,
3130
+ streamId,
3131
+ database,
3132
+ schema,
3133
+ table,
3134
+ this.renameColumnStore
3135
+ );
3136
+ };
3137
+ genTableName = safeTableName;
3138
+ safeColumnNameConverter = safeColumnName;
3139
+ validateDateRange = validateDateRange;
3140
+ convertNumberIntoDecimal = convertNumberIntoDecimal;
3141
+ };
2819
3142
  // Annotate the CommonJS export names for ESM import in node:
2820
3143
  0 && (module.exports = {
2821
3144
  ALL_STREAM_ID_KEYWORD,
2822
3145
  API_CALLS_METRIC_NAME,
2823
3146
  Authenticator,
2824
3147
  BATCH_INTERVAL_MS,
2825
- Catalog,
3148
+ BigQueryTarget,
2826
3149
  CounterMetric,
2827
3150
  DEFAULT_MAX_CONCURRENT_STREAMS,
2828
3151
  EXECUTION_TIME_METRIC_NAME,
2829
3152
  ITarget,
2830
3153
  MissingFieldInSchemaError,
2831
3154
  MissingSchemaError,
2832
- RESTStreamV2,
3155
+ RESTStream,
2833
3156
  ROWS_SYNCED_METRIC_NAME,
2834
3157
  RecordMessage,
2835
3158
  RenameColumnStore,
@@ -2839,13 +3162,12 @@ var ITarget = class _ITarget {
2839
3162
  SchemaValidationError,
2840
3163
  StateMessage,
2841
3164
  StateService,
3165
+ Stream,
2842
3166
  StreamMetadata,
2843
- StreamV2,
2844
3167
  StreamWarehouseSyncService,
2845
3168
  Tap,
2846
3169
  _greaterThan,
2847
3170
  addWhalyFields,
2848
- checkRequiredConfigKeys,
2849
3171
  createTemporaryFileStream,
2850
3172
  extractStateForStream,
2851
3173
  finalizeStateProgressMarkers,
@@ -2863,8 +3185,8 @@ var ITarget = class _ITarget {
2863
3185
  haltAndCatchFire,
2864
3186
  incrementStreamState,
2865
3187
  loadJson,
3188
+ loadResolver,
2866
3189
  loadSchema,
2867
- loadShoreConfig,
2868
3190
  logger,
2869
3191
  postFormDataApiCall,
2870
3192
  postJSONApiCall,
@@ -2872,7 +3194,6 @@ var ITarget = class _ITarget {
2872
3194
  printMemoryFootprint,
2873
3195
  removeParasiteProperties,
2874
3196
  safePath,
2875
- writeCatalogFile,
2876
3197
  writeStateFile
2877
3198
  });
2878
3199
  //# sourceMappingURL=index.js.map