@tangle-network/agent-integrations 0.53.28 → 0.53.29

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.
@@ -181,10 +181,12 @@ __export(adapters_exports, {
181
181
  copperConnector: () => copperConnector,
182
182
  copyAiConnector: () => copyAiConnector,
183
183
  couchbaseConnector: () => couchbaseConnector,
184
+ createSftpConnector: () => createSftpConnector,
184
185
  createTangleIdentityClient: () => createTangleIdentityClient,
185
186
  crispConnector: () => crispConnector,
186
187
  crustdataConnector: () => crustdataConnector,
187
188
  cryptolensConnector: () => cryptolensConnector,
189
+ csvFilesConnector: () => csvFilesConnector,
188
190
  customerIoConnector: () => customerIoConnector,
189
191
  customgptConnector: () => customgptConnector,
190
192
  dappierConnector: () => dappierConnector,
@@ -230,6 +232,7 @@ __export(adapters_exports, {
230
232
  etsyConnector: () => etsyConnector,
231
233
  everhourConnector: () => everhourConnector,
232
234
  exaConnector: () => exaConnector,
235
+ excelFilesConnector: () => excelFilesConnector,
233
236
  facebookLeadsConnector: () => facebookLeadsConnector,
234
237
  facebookPagesConnector: () => facebookPagesConnector,
235
238
  factorsAiConnector: () => factorsAiConnector,
@@ -466,6 +469,7 @@ __export(adapters_exports, {
466
469
  pagerdutyConnector: () => pagerdutyConnector,
467
470
  pandadoc: () => pandadoc,
468
471
  paperformConnector: () => paperformConnector,
472
+ parquetFilesConnector: () => parquetFilesConnector,
469
473
  parseurConnector: () => parseurConnector,
470
474
  pastefyConnector: () => pastefyConnector,
471
475
  paychexConnector: () => paychexConnector,
@@ -542,6 +546,7 @@ __export(adapters_exports, {
542
546
  serperConnector: () => serperConnector,
543
547
  serpstatConnector: () => serpstatConnector,
544
548
  serviceNowConnector: () => serviceNowConnector,
549
+ sftpConnector: () => sftpConnector,
545
550
  sharepoint: () => sharepoint,
546
551
  shippoConnector: () => shippoConnector,
547
552
  shopifyConnector: () => shopifyConnector,
@@ -4446,6 +4451,233 @@ var cartloomConnector = declarativeRestConnector({
4446
4451
  ]
4447
4452
  });
4448
4453
 
4454
+ // src/connectors/adapters/csv-files.ts
4455
+ import { parse } from "csv-parse/sync";
4456
+ import { stringify } from "csv-stringify/sync";
4457
+
4458
+ // src/connectors/adapters/file-payload.ts
4459
+ var MAX_FILE_BYTES = 10 * 1024 * 1024;
4460
+ var MAX_RECORDS = 1e4;
4461
+ function readBase64File(value, label = "fileBase64") {
4462
+ if (typeof value !== "string" || value.length === 0) {
4463
+ throw new Error(`${label} is required`);
4464
+ }
4465
+ if (value.length % 4 !== 0 || !/^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/.test(value)) {
4466
+ throw new Error(`${label} must be canonical base64`);
4467
+ }
4468
+ const file = Buffer.from(value, "base64");
4469
+ if (file.byteLength > MAX_FILE_BYTES) {
4470
+ throw new Error(`${label} exceeds the ${MAX_FILE_BYTES}-byte limit`);
4471
+ }
4472
+ return file;
4473
+ }
4474
+ function encodeFile(file) {
4475
+ if (file.byteLength > MAX_FILE_BYTES) {
4476
+ throw new Error(`generated file exceeds the ${MAX_FILE_BYTES}-byte limit`);
4477
+ }
4478
+ return {
4479
+ fileBase64: Buffer.from(file).toString("base64"),
4480
+ byteLength: file.byteLength
4481
+ };
4482
+ }
4483
+ function readRecords(value) {
4484
+ if (!Array.isArray(value) || value.length === 0) {
4485
+ throw new Error("records must be a non-empty array of objects");
4486
+ }
4487
+ if (value.length > MAX_RECORDS) {
4488
+ throw new Error(`records exceeds the ${MAX_RECORDS}-record limit`);
4489
+ }
4490
+ assertStructuredInputSize(value, "records");
4491
+ return value.map((entry, index) => {
4492
+ if (!isPlainRecord(entry)) {
4493
+ throw new Error(`records[${index}] must be an object`);
4494
+ }
4495
+ return entry;
4496
+ });
4497
+ }
4498
+ function readRows(value) {
4499
+ if (!Array.isArray(value) || value.length === 0) {
4500
+ throw new Error("rows must be a non-empty array of arrays");
4501
+ }
4502
+ if (value.length > MAX_RECORDS) {
4503
+ throw new Error(`rows exceeds the ${MAX_RECORDS}-row limit`);
4504
+ }
4505
+ assertStructuredInputSize(value, "rows");
4506
+ return value.map((entry, index) => {
4507
+ if (!Array.isArray(entry)) throw new Error(`rows[${index}] must be an array`);
4508
+ return entry;
4509
+ });
4510
+ }
4511
+ function readOptionalString(value, label) {
4512
+ if (value === void 0 || value === null) return void 0;
4513
+ if (typeof value !== "string" || value.length === 0) throw new Error(`${label} must be a non-empty string`);
4514
+ return value;
4515
+ }
4516
+ function readBoolean(value, fallback, label) {
4517
+ if (value === void 0 || value === null) return fallback;
4518
+ if (typeof value !== "boolean") throw new Error(`${label} must be a boolean`);
4519
+ return value;
4520
+ }
4521
+ function readBoundedInteger(value, fallback, minimum, maximum, label) {
4522
+ if (value === void 0 || value === null) return fallback;
4523
+ if (!Number.isInteger(value) || value < minimum || value > maximum) {
4524
+ throw new Error(`${label} must be an integer from ${minimum} through ${maximum}`);
4525
+ }
4526
+ return value;
4527
+ }
4528
+ function jsonSafe(value) {
4529
+ if (typeof value === "bigint") return value.toString();
4530
+ if (value instanceof Date) return value.toISOString();
4531
+ if (value instanceof Uint8Array) return Buffer.from(value).toString("base64");
4532
+ if (Array.isArray(value)) return value.map(jsonSafe);
4533
+ if (isPlainRecord(value)) {
4534
+ return Object.fromEntries(Object.entries(value).map(([key, entry]) => [key, jsonSafe(entry)]));
4535
+ }
4536
+ return value;
4537
+ }
4538
+ function isPlainRecord(value) {
4539
+ return Boolean(value) && typeof value === "object" && !Array.isArray(value) && Object.getPrototypeOf(value) === Object.prototype;
4540
+ }
4541
+ function assertStructuredInputSize(value, label) {
4542
+ let serialized;
4543
+ try {
4544
+ serialized = JSON.stringify(value, (_key, entry) => typeof entry === "bigint" ? entry.toString() : entry);
4545
+ } catch {
4546
+ throw new Error(`${label} must be JSON-serializable`);
4547
+ }
4548
+ if (Buffer.byteLength(serialized, "utf8") > MAX_FILE_BYTES) {
4549
+ throw new Error(`${label} exceeds the ${MAX_FILE_BYTES}-byte input limit`);
4550
+ }
4551
+ }
4552
+
4553
+ // src/connectors/adapters/csv-files.ts
4554
+ var MAX_COLUMNS = 256;
4555
+ var MAX_RECORD_SIZE = 1024 * 1024;
4556
+ var csvFilesConnector = {
4557
+ manifest: {
4558
+ kind: "csv-files",
4559
+ displayName: "CSV Files",
4560
+ description: "Parse bounded CSV files into records and create CSV files from structured records.",
4561
+ auth: { kind: "none" },
4562
+ defaultConsistencyModel: "advisory",
4563
+ category: "database",
4564
+ capabilities: [
4565
+ {
4566
+ name: "csv.parse",
4567
+ class: "read",
4568
+ description: "Parse a base64-encoded CSV file into object records or row arrays.",
4569
+ parameters: {
4570
+ type: "object",
4571
+ properties: {
4572
+ fileBase64: { type: "string", description: "CSV file content encoded as canonical base64." },
4573
+ delimiter: { type: "string", minLength: 1, maxLength: 1, default: "," },
4574
+ header: { type: "boolean", default: true }
4575
+ },
4576
+ required: ["fileBase64"],
4577
+ additionalProperties: false
4578
+ }
4579
+ },
4580
+ {
4581
+ name: "csv.create",
4582
+ class: "mutation",
4583
+ description: "Create a base64-encoded CSV file from object records.",
4584
+ parameters: {
4585
+ type: "object",
4586
+ properties: {
4587
+ records: { type: "array", minItems: 1, maxItems: MAX_RECORDS, items: { type: "object" } },
4588
+ columns: { type: "array", maxItems: MAX_COLUMNS, items: { type: "string", minLength: 1 } },
4589
+ delimiter: { type: "string", minLength: 1, maxLength: 1, default: "," },
4590
+ header: { type: "boolean", default: true }
4591
+ },
4592
+ required: ["records"],
4593
+ additionalProperties: false
4594
+ },
4595
+ cas: "none",
4596
+ externalEffect: true
4597
+ }
4598
+ ]
4599
+ },
4600
+ async executeRead({ capabilityName, args }) {
4601
+ if (capabilityName !== "csv.parse") throw new Error(`Unknown CSV capability: ${capabilityName}`);
4602
+ const file = readBase64File(args.fileBase64);
4603
+ const delimiter = readDelimiter(args.delimiter);
4604
+ const header2 = readBoolean(args.header, true, "header");
4605
+ let recordCount = 0;
4606
+ const records = parse(file, {
4607
+ bom: true,
4608
+ columns: header2,
4609
+ delimiter,
4610
+ max_record_size: MAX_RECORD_SIZE,
4611
+ skip_empty_lines: true,
4612
+ on_record(record) {
4613
+ recordCount += 1;
4614
+ if (recordCount > MAX_RECORDS) throw new Error(`CSV exceeds the ${MAX_RECORDS}-record limit`);
4615
+ return record;
4616
+ }
4617
+ });
4618
+ if (records.some(
4619
+ (record) => header2 ? Object.keys(record).length > MAX_COLUMNS : Array.isArray(record) && record.length > MAX_COLUMNS
4620
+ )) {
4621
+ throw new Error(`CSV exceeds the ${MAX_COLUMNS}-column limit`);
4622
+ }
4623
+ return {
4624
+ data: { records, recordCount: records.length, header: header2 },
4625
+ fetchedAt: Date.now()
4626
+ };
4627
+ },
4628
+ async executeMutation({ capabilityName, args }) {
4629
+ if (capabilityName !== "csv.create") throw new Error(`Unknown CSV capability: ${capabilityName}`);
4630
+ const records = readRecords(args.records);
4631
+ const columns = readColumns(args.columns, records);
4632
+ const delimiter = readDelimiter(args.delimiter);
4633
+ const header2 = readBoolean(args.header, true, "header");
4634
+ const csv = stringify(
4635
+ records.map((record) => Object.fromEntries(columns.map((column) => [column, csvValue(record[column])]))),
4636
+ { columns, delimiter, header: header2 }
4637
+ );
4638
+ return {
4639
+ status: "committed",
4640
+ data: { ...encodeFile(Buffer.from(csv, "utf8")), text: csv, columns, recordCount: records.length },
4641
+ committedAt: Date.now(),
4642
+ idempotentReplay: false
4643
+ };
4644
+ },
4645
+ async test() {
4646
+ return { ok: true };
4647
+ }
4648
+ };
4649
+ function readDelimiter(value) {
4650
+ const delimiter = readOptionalString(value, "delimiter") ?? ",";
4651
+ if ([...delimiter].length !== 1 || delimiter === "\r" || delimiter === "\n" || delimiter === '"') {
4652
+ throw new Error("delimiter must be one non-newline character other than a double quote");
4653
+ }
4654
+ return delimiter;
4655
+ }
4656
+ function readColumns(value, records) {
4657
+ const columns = value === void 0 ? [...new Set(records.flatMap((record) => Object.keys(record)))] : value;
4658
+ if (!Array.isArray(columns) || columns.length === 0 || columns.length > MAX_COLUMNS) {
4659
+ throw new Error(`columns must contain 1 through ${MAX_COLUMNS} names`);
4660
+ }
4661
+ const parsed = columns.map((column, index) => {
4662
+ if (typeof column !== "string" || column.length === 0) throw new Error(`columns[${index}] must be a non-empty string`);
4663
+ return column;
4664
+ });
4665
+ if (new Set(parsed).size !== parsed.length) throw new Error("columns must not contain duplicates");
4666
+ return parsed;
4667
+ }
4668
+ function csvValue(value) {
4669
+ if (value === null || value === void 0) return null;
4670
+ if (typeof value === "string") return value;
4671
+ if (typeof value === "boolean") return value ? "true" : "false";
4672
+ if (typeof value === "number") {
4673
+ if (!Number.isFinite(value)) throw new Error("CSV numeric values must be finite");
4674
+ return value;
4675
+ }
4676
+ if (typeof value === "bigint") return value.toString();
4677
+ if (value instanceof Date) return value.toISOString();
4678
+ return JSON.stringify(value);
4679
+ }
4680
+
4449
4681
  // src/connectors/adapters/chain-aware.ts
4450
4682
  var chainAwareConnector = declarativeRestConnector({
4451
4683
  kind: "chain-aware",
@@ -6679,6 +6911,175 @@ var elevenlabsConnector = declarativeRestConnector({
6679
6911
  ]
6680
6912
  });
6681
6913
 
6914
+ // src/connectors/adapters/excel-files.ts
6915
+ import readXlsxFile from "read-excel-file/node";
6916
+ import writeXlsxFile from "write-excel-file/node";
6917
+ var MAX_COLUMNS2 = 256;
6918
+ var MAX_SHEETS = 50;
6919
+ var MAX_UNCOMPRESSED_WORKBOOK_BYTES = 50 * 1024 * 1024;
6920
+ var MAX_ZIP_ENTRIES = 1e3;
6921
+ var excelFilesConnector = {
6922
+ manifest: {
6923
+ kind: "excel-files",
6924
+ displayName: "Excel Files",
6925
+ description: "Read bounded XLSX workbooks and create XLSX files from structured rows.",
6926
+ auth: { kind: "none" },
6927
+ defaultConsistencyModel: "advisory",
6928
+ category: "spreadsheet",
6929
+ capabilities: [
6930
+ {
6931
+ name: "excel.read",
6932
+ class: "read",
6933
+ description: "Read every sheet, or one named sheet, from a base64-encoded XLSX workbook.",
6934
+ parameters: {
6935
+ type: "object",
6936
+ properties: {
6937
+ fileBase64: { type: "string", description: "XLSX workbook content encoded as canonical base64." },
6938
+ sheet: {
6939
+ description: "Optional sheet name or one-based sheet number.",
6940
+ oneOf: [{ type: "string", minLength: 1 }, { type: "integer", minimum: 1 }]
6941
+ }
6942
+ },
6943
+ required: ["fileBase64"],
6944
+ additionalProperties: false
6945
+ }
6946
+ },
6947
+ {
6948
+ name: "excel.create",
6949
+ class: "mutation",
6950
+ description: "Create a single-sheet base64-encoded XLSX workbook from row arrays.",
6951
+ parameters: {
6952
+ type: "object",
6953
+ properties: {
6954
+ rows: {
6955
+ type: "array",
6956
+ minItems: 1,
6957
+ maxItems: MAX_RECORDS,
6958
+ items: { type: "array", maxItems: MAX_COLUMNS2 }
6959
+ },
6960
+ sheetName: { type: "string", minLength: 1, maxLength: 31, default: "Sheet1" }
6961
+ },
6962
+ required: ["rows"],
6963
+ additionalProperties: false
6964
+ },
6965
+ cas: "none",
6966
+ externalEffect: true
6967
+ }
6968
+ ]
6969
+ },
6970
+ async executeRead({ capabilityName, args }) {
6971
+ if (capabilityName !== "excel.read") throw new Error(`Unknown Excel capability: ${capabilityName}`);
6972
+ const file = readBase64File(args.fileBase64);
6973
+ assertBoundedXlsxArchive(file);
6974
+ const requestedSheet = readSheetSelector(args.sheet);
6975
+ const workbook = await readXlsxFile(file);
6976
+ if (workbook.length > MAX_SHEETS) throw new Error(`workbook exceeds the ${MAX_SHEETS}-sheet limit`);
6977
+ const selected = requestedSheet === void 0 ? workbook : workbook.filter(
6978
+ (sheet, index) => typeof requestedSheet === "number" ? index + 1 === requestedSheet : sheet.sheet === requestedSheet
6979
+ );
6980
+ if (requestedSheet !== void 0 && selected.length === 0) {
6981
+ throw new Error(`sheet not found: ${requestedSheet}`);
6982
+ }
6983
+ let totalRows = 0;
6984
+ const sheets = selected.map((sheet) => {
6985
+ totalRows += sheet.data.length;
6986
+ if (totalRows > MAX_RECORDS) throw new Error(`workbook exceeds the ${MAX_RECORDS}-row limit`);
6987
+ for (const [rowIndex, row] of sheet.data.entries()) {
6988
+ if (row.length > MAX_COLUMNS2) {
6989
+ throw new Error(`sheet ${sheet.sheet} row ${rowIndex + 1} exceeds the ${MAX_COLUMNS2}-column limit`);
6990
+ }
6991
+ }
6992
+ return { name: sheet.sheet, rows: jsonSafe(sheet.data) };
6993
+ });
6994
+ return {
6995
+ data: { sheets, sheetCount: sheets.length, rowCount: totalRows },
6996
+ fetchedAt: Date.now()
6997
+ };
6998
+ },
6999
+ async executeMutation({ capabilityName, args }) {
7000
+ if (capabilityName !== "excel.create") throw new Error(`Unknown Excel capability: ${capabilityName}`);
7001
+ const rows = readRows(args.rows);
7002
+ for (const [index, row] of rows.entries()) {
7003
+ if (row.length > MAX_COLUMNS2) throw new Error(`rows[${index}] exceeds the ${MAX_COLUMNS2}-column limit`);
7004
+ }
7005
+ const sheetName = readOptionalString(args.sheetName, "sheetName") ?? "Sheet1";
7006
+ validateSheetName(sheetName);
7007
+ const sheetData = rows.map((row) => row.map(excelCell));
7008
+ const file = await writeXlsxFile(sheetData, { sheet: sheetName }).toBuffer();
7009
+ return {
7010
+ status: "committed",
7011
+ data: { ...encodeFile(file), sheetName, rowCount: rows.length },
7012
+ committedAt: Date.now(),
7013
+ idempotentReplay: false
7014
+ };
7015
+ },
7016
+ async test() {
7017
+ return { ok: true };
7018
+ }
7019
+ };
7020
+ function readSheetSelector(value) {
7021
+ if (value === void 0 || value === null) return void 0;
7022
+ if (typeof value === "string" && value.length > 0) return value;
7023
+ if (Number.isInteger(value) && value >= 1) return value;
7024
+ throw new Error("sheet must be a non-empty name or a one-based integer");
7025
+ }
7026
+ function validateSheetName(value) {
7027
+ if (value.length > 31 || /[\\/*?:[\]]/.test(value)) {
7028
+ throw new Error("sheetName must be at most 31 characters and contain no \\ / * ? : [ ] characters");
7029
+ }
7030
+ }
7031
+ function excelCell(value) {
7032
+ if (value === null || value === void 0) return null;
7033
+ if (typeof value === "string" || typeof value === "boolean" || value instanceof Date) return value;
7034
+ if (typeof value === "number") {
7035
+ if (!Number.isFinite(value)) throw new Error("Excel numeric values must be finite");
7036
+ return value;
7037
+ }
7038
+ if (typeof value === "bigint") return value.toString();
7039
+ return JSON.stringify(value);
7040
+ }
7041
+ function assertBoundedXlsxArchive(file) {
7042
+ const eocdSignature = 101010256;
7043
+ const centralEntrySignature = 33639248;
7044
+ if (file.byteLength < 22) throw new Error("XLSX file is missing its ZIP directory");
7045
+ const searchStart = Math.max(0, file.byteLength - 65557);
7046
+ let eocdOffset = -1;
7047
+ for (let offset2 = file.byteLength - 22; offset2 >= searchStart; offset2 -= 1) {
7048
+ if (file.readUInt32LE(offset2) === eocdSignature) {
7049
+ eocdOffset = offset2;
7050
+ break;
7051
+ }
7052
+ }
7053
+ if (eocdOffset < 0) throw new Error("XLSX file is missing its ZIP directory");
7054
+ const entryCount = file.readUInt16LE(eocdOffset + 10);
7055
+ const centralSize = file.readUInt32LE(eocdOffset + 12);
7056
+ const centralOffset = file.readUInt32LE(eocdOffset + 16);
7057
+ if (entryCount === 65535 || centralSize === 4294967295 || centralOffset === 4294967295) {
7058
+ throw new Error("ZIP64 XLSX workbooks are not supported");
7059
+ }
7060
+ if (entryCount === 0 || entryCount > MAX_ZIP_ENTRIES || centralOffset + centralSize > file.byteLength) {
7061
+ throw new Error("XLSX ZIP directory is invalid or too large");
7062
+ }
7063
+ let offset = centralOffset;
7064
+ let totalUncompressed = 0;
7065
+ for (let index = 0; index < entryCount; index += 1) {
7066
+ if (offset + 46 > file.byteLength || file.readUInt32LE(offset) !== centralEntrySignature) {
7067
+ throw new Error("XLSX ZIP directory entry is invalid");
7068
+ }
7069
+ const compressedSize = file.readUInt32LE(offset + 20);
7070
+ const uncompressedSize = file.readUInt32LE(offset + 24);
7071
+ const fileNameLength = file.readUInt16LE(offset + 28);
7072
+ const extraLength = file.readUInt16LE(offset + 30);
7073
+ const commentLength = file.readUInt16LE(offset + 32);
7074
+ totalUncompressed += uncompressedSize;
7075
+ if (totalUncompressed > MAX_UNCOMPRESSED_WORKBOOK_BYTES || uncompressedSize > 0 && compressedSize === 0) {
7076
+ throw new Error("XLSX workbook expands beyond the safe processing limit");
7077
+ }
7078
+ offset += 46 + fileNameLength + extraLength + commentLength;
7079
+ }
7080
+ if (offset > centralOffset + centralSize) throw new Error("XLSX ZIP directory length is invalid");
7081
+ }
7082
+
6682
7083
  // src/connectors/adapters/everhour.ts
6683
7084
  var everhourConnector = declarativeRestConnector({
6684
7085
  kind: "everhour",
@@ -30336,7 +30737,7 @@ var httpConnector = {
30336
30737
  });
30337
30738
  const data4 = await parseResponse(res, method);
30338
30739
  if (!res.ok) {
30339
- throw new Error(`http ${method} ${url.toString()} failed: ${res.status} ${truncate(stringify(data4), 200)}`);
30740
+ throw new Error(`http ${method} ${url.toString()} failed: ${res.status} ${truncate(stringify2(data4), 200)}`);
30340
30741
  }
30341
30742
  return {
30342
30743
  data: data4,
@@ -30371,7 +30772,7 @@ var httpConnector = {
30371
30772
  };
30372
30773
  }
30373
30774
  if (!res.ok) {
30374
- throw new Error(`http ${method} ${url.toString()} failed: ${res.status} ${truncate(stringify(data4), 200)}`);
30775
+ throw new Error(`http ${method} ${url.toString()} failed: ${res.status} ${truncate(stringify2(data4), 200)}`);
30375
30776
  }
30376
30777
  return {
30377
30778
  status: "committed",
@@ -30501,7 +30902,7 @@ function parseRetryAfterMs(header2) {
30501
30902
  if (!Number.isFinite(date)) return 1e3;
30502
30903
  return Math.max(0, date - Date.now());
30503
30904
  }
30504
- function stringify(value) {
30905
+ function stringify2(value) {
30505
30906
  if (typeof value === "string") return value;
30506
30907
  try {
30507
30908
  return JSON.stringify(value);
@@ -42934,6 +43335,130 @@ var pipedriveConnector = declarativeRestConnector({
42934
43335
  ]
42935
43336
  });
42936
43337
 
43338
+ // src/connectors/adapters/parquet-files.ts
43339
+ import { parquetReadObjects } from "hyparquet";
43340
+ import { parquetWriteBuffer } from "hyparquet-writer";
43341
+ var MAX_COLUMNS3 = 256;
43342
+ var parquetFilesConnector = {
43343
+ manifest: {
43344
+ kind: "parquet-files",
43345
+ displayName: "Parquet Files",
43346
+ description: "Read bounded Apache Parquet files and create Parquet files from structured records.",
43347
+ auth: { kind: "none" },
43348
+ defaultConsistencyModel: "advisory",
43349
+ category: "database",
43350
+ capabilities: [
43351
+ {
43352
+ name: "parquet.read",
43353
+ class: "read",
43354
+ description: "Read selected columns and a bounded row range from a base64-encoded Parquet file.",
43355
+ parameters: {
43356
+ type: "object",
43357
+ properties: {
43358
+ fileBase64: { type: "string", description: "Parquet file content encoded as canonical base64." },
43359
+ columns: { type: "array", maxItems: MAX_COLUMNS3, items: { type: "string", minLength: 1 } },
43360
+ rowStart: { type: "integer", minimum: 0, default: 0 },
43361
+ rowLimit: { type: "integer", minimum: 1, maximum: MAX_RECORDS, default: MAX_RECORDS }
43362
+ },
43363
+ required: ["fileBase64"],
43364
+ additionalProperties: false
43365
+ }
43366
+ },
43367
+ {
43368
+ name: "parquet.create",
43369
+ class: "mutation",
43370
+ description: "Create a base64-encoded Parquet file from object records with inferred column types.",
43371
+ parameters: {
43372
+ type: "object",
43373
+ properties: {
43374
+ records: { type: "array", minItems: 1, maxItems: MAX_RECORDS, items: { type: "object" } }
43375
+ },
43376
+ required: ["records"],
43377
+ additionalProperties: false
43378
+ },
43379
+ cas: "none",
43380
+ externalEffect: true
43381
+ }
43382
+ ]
43383
+ },
43384
+ async executeRead({ capabilityName, args }) {
43385
+ if (capabilityName !== "parquet.read") throw new Error(`Unknown Parquet capability: ${capabilityName}`);
43386
+ const file = readBase64File(args.fileBase64);
43387
+ const columns = readColumns2(args.columns);
43388
+ const rowStart = readBoundedInteger(args.rowStart, 0, 0, Number.MAX_SAFE_INTEGER, "rowStart");
43389
+ const rowLimit = readBoundedInteger(args.rowLimit, MAX_RECORDS, 1, MAX_RECORDS, "rowLimit");
43390
+ const records = await parquetReadObjects({
43391
+ file: asyncBuffer(file),
43392
+ columns,
43393
+ rowStart,
43394
+ rowEnd: rowStart + rowLimit
43395
+ });
43396
+ return {
43397
+ data: { records: jsonSafe(records), recordCount: records.length, rowStart },
43398
+ fetchedAt: Date.now()
43399
+ };
43400
+ },
43401
+ async executeMutation({ capabilityName, args }) {
43402
+ if (capabilityName !== "parquet.create") throw new Error(`Unknown Parquet capability: ${capabilityName}`);
43403
+ const records = readRecords(args.records);
43404
+ const columnNames = [...new Set(records.flatMap((record) => Object.keys(record)))];
43405
+ if (columnNames.length === 0 || columnNames.length > MAX_COLUMNS3) {
43406
+ throw new Error(`records must contain 1 through ${MAX_COLUMNS3} columns`);
43407
+ }
43408
+ if (columnNames.some((name) => name.length === 0)) throw new Error("column names must not be empty");
43409
+ const columnData = columnNames.map((name) => {
43410
+ const data4 = records.map((record) => parquetValue(record[name]));
43411
+ return { name, data: data4, type: inferParquetType(data4) };
43412
+ });
43413
+ const file = parquetWriteBuffer({ columnData });
43414
+ return {
43415
+ status: "committed",
43416
+ data: { ...encodeFile(new Uint8Array(file)), columns: columnNames, recordCount: records.length },
43417
+ committedAt: Date.now(),
43418
+ idempotentReplay: false
43419
+ };
43420
+ },
43421
+ async test() {
43422
+ return { ok: true };
43423
+ }
43424
+ };
43425
+ function asyncBuffer(file) {
43426
+ return {
43427
+ byteLength: file.byteLength,
43428
+ slice(start, end) {
43429
+ const boundedEnd = end === void 0 ? file.byteLength : Math.min(end, file.byteLength);
43430
+ return Uint8Array.from(file.subarray(start, boundedEnd)).buffer;
43431
+ }
43432
+ };
43433
+ }
43434
+ function readColumns2(value) {
43435
+ if (value === void 0 || value === null) return void 0;
43436
+ if (!Array.isArray(value) || value.length === 0 || value.length > MAX_COLUMNS3) {
43437
+ throw new Error(`columns must contain 1 through ${MAX_COLUMNS3} names`);
43438
+ }
43439
+ const columns = value.map((entry, index) => {
43440
+ if (typeof entry !== "string" || entry.length === 0) throw new Error(`columns[${index}] must be a non-empty string`);
43441
+ return entry;
43442
+ });
43443
+ if (new Set(columns).size !== columns.length) throw new Error("columns must not contain duplicates");
43444
+ return columns;
43445
+ }
43446
+ function parquetValue(value) {
43447
+ if (value === void 0) return null;
43448
+ if (typeof value === "number" && !Number.isFinite(value)) throw new Error("Parquet numeric values must be finite");
43449
+ return value;
43450
+ }
43451
+ function inferParquetType(values) {
43452
+ const present = values.filter((value) => value !== null && value !== void 0);
43453
+ if (present.length === 0) return "JSON";
43454
+ if (present.every((value) => typeof value === "boolean")) return "BOOLEAN";
43455
+ if (present.every((value) => typeof value === "string")) return "STRING";
43456
+ if (present.every((value) => typeof value === "number")) return "DOUBLE";
43457
+ if (present.every((value) => typeof value === "bigint")) return "INT64";
43458
+ if (present.every((value) => value instanceof Date)) return "TIMESTAMP";
43459
+ return "JSON";
43460
+ }
43461
+
42937
43462
  // src/connectors/adapters/quickbooks.ts
42938
43463
  var quickbooksConnector = declarativeRestConnector({
42939
43464
  kind: "quickbooks",
@@ -44194,6 +44719,372 @@ var salesforceConnector = declarativeRestConnector({
44194
44719
  ]
44195
44720
  });
44196
44721
 
44722
+ // src/connectors/adapters/sftp.ts
44723
+ import { lookup } from "dns/promises";
44724
+ import { timingSafeEqual as timingSafeEqual4 } from "crypto";
44725
+ import { posix } from "path";
44726
+ import ipaddr from "ipaddr.js";
44727
+ import SftpClient from "ssh2-sftp-client";
44728
+ var MAX_LIST_ENTRIES = 1e3;
44729
+ var MAX_PATH_LENGTH = 1024;
44730
+ function createSftpConnector(options = {}) {
44731
+ const createClient = options.createClient ?? (() => new SftpClient());
44732
+ const lookupHost = options.lookupHost ?? resolvePublicAddresses;
44733
+ return {
44734
+ manifest: {
44735
+ kind: "sftp",
44736
+ displayName: "SFTP",
44737
+ description: "List, inspect, download, upload, move, and delete files over host-key-verified SFTP.",
44738
+ auth: {
44739
+ kind: "api-key",
44740
+ hint: "JSON with host, username, SHA-256 hostFingerprint, and password or privateKey; optional port, passphrase, and rootPath."
44741
+ },
44742
+ defaultConsistencyModel: "advisory",
44743
+ category: "storage",
44744
+ rateLimit: { requests: 120, windowMs: 6e4, scope: "data-source" },
44745
+ capabilities: [
44746
+ {
44747
+ name: "sftp.list",
44748
+ class: "read",
44749
+ description: "List a directory within the connection root.",
44750
+ parameters: {
44751
+ type: "object",
44752
+ properties: {
44753
+ path: { type: "string", default: "/" },
44754
+ limit: { type: "integer", minimum: 1, maximum: MAX_LIST_ENTRIES, default: MAX_LIST_ENTRIES }
44755
+ },
44756
+ additionalProperties: false
44757
+ }
44758
+ },
44759
+ {
44760
+ name: "sftp.stat",
44761
+ class: "read",
44762
+ description: "Read file or directory metadata within the connection root.",
44763
+ parameters: pathSchema()
44764
+ },
44765
+ {
44766
+ name: "sftp.download",
44767
+ class: "read",
44768
+ description: `Download a file no larger than ${MAX_FILE_BYTES} bytes as base64.`,
44769
+ parameters: pathSchema()
44770
+ },
44771
+ {
44772
+ name: "sftp.upload",
44773
+ class: "mutation",
44774
+ description: `Upload a base64 file no larger than ${MAX_FILE_BYTES} bytes within the connection root.`,
44775
+ parameters: {
44776
+ type: "object",
44777
+ properties: {
44778
+ path: { type: "string", minLength: 1 },
44779
+ fileBase64: { type: "string" },
44780
+ overwrite: { type: "boolean", default: false }
44781
+ },
44782
+ required: ["path", "fileBase64"],
44783
+ additionalProperties: false
44784
+ },
44785
+ cas: "none",
44786
+ externalEffect: true
44787
+ },
44788
+ {
44789
+ name: "sftp.mkdir",
44790
+ class: "mutation",
44791
+ description: "Create a directory within the connection root.",
44792
+ parameters: {
44793
+ type: "object",
44794
+ properties: {
44795
+ path: { type: "string", minLength: 1 },
44796
+ recursive: { type: "boolean", default: true }
44797
+ },
44798
+ required: ["path"],
44799
+ additionalProperties: false
44800
+ },
44801
+ cas: "none",
44802
+ externalEffect: true
44803
+ },
44804
+ {
44805
+ name: "sftp.rename",
44806
+ class: "mutation",
44807
+ description: "Move or rename a file without overwriting the destination.",
44808
+ parameters: {
44809
+ type: "object",
44810
+ properties: {
44811
+ sourcePath: { type: "string", minLength: 1 },
44812
+ destinationPath: { type: "string", minLength: 1 }
44813
+ },
44814
+ required: ["sourcePath", "destinationPath"],
44815
+ additionalProperties: false
44816
+ },
44817
+ cas: "none",
44818
+ externalEffect: true
44819
+ },
44820
+ {
44821
+ name: "sftp.delete",
44822
+ class: "mutation",
44823
+ description: "Delete a file within the connection root. Repeated deletion is safe.",
44824
+ parameters: pathSchema(),
44825
+ cas: "none",
44826
+ externalEffect: true
44827
+ }
44828
+ ]
44829
+ },
44830
+ async executeRead({ source, capabilityName, args }) {
44831
+ const credentials = readCredentials(source);
44832
+ if (capabilityName === "sftp.list") {
44833
+ const path = resolveRemotePath(credentials.rootPath, args.path ?? "/");
44834
+ const limit = readBoundedInteger(args.limit, MAX_LIST_ENTRIES, 1, MAX_LIST_ENTRIES, "limit");
44835
+ return withSftp(credentials, createClient, lookupHost, async (client) => {
44836
+ const safePath = await canonicalizeExistingPath(client, credentials.rootPath, path);
44837
+ const allEntries = await client.list(safePath);
44838
+ const entries = allEntries.slice(0, limit);
44839
+ return { data: { path: safePath, entries, truncated: allEntries.length > limit }, fetchedAt: Date.now() };
44840
+ });
44841
+ }
44842
+ if (capabilityName === "sftp.stat") {
44843
+ const path = resolveRemotePath(credentials.rootPath, args.path);
44844
+ return withSftp(credentials, createClient, lookupHost, async (client) => {
44845
+ const safePath = await canonicalizeExistingPath(client, credentials.rootPath, path);
44846
+ return { data: { path: safePath, stat: await client.stat(safePath) }, fetchedAt: Date.now() };
44847
+ });
44848
+ }
44849
+ if (capabilityName === "sftp.download") {
44850
+ const path = resolveRemotePath(credentials.rootPath, args.path);
44851
+ return withSftp(credentials, createClient, lookupHost, async (client) => {
44852
+ const safePath = await canonicalizeExistingPath(client, credentials.rootPath, path);
44853
+ const stat = await client.stat(safePath);
44854
+ if (!stat.isFile) throw new Error("sftp.download path is not a file");
44855
+ if (stat.size > MAX_FILE_BYTES) throw new Error(`sftp.download file exceeds the ${MAX_FILE_BYTES}-byte limit`);
44856
+ const file = await client.get(safePath);
44857
+ if (!Buffer.isBuffer(file)) throw new Error("SFTP client returned a non-buffer download");
44858
+ return { data: { path: safePath, ...encodeFile(file), modifyTime: stat.modifyTime }, fetchedAt: Date.now() };
44859
+ });
44860
+ }
44861
+ throw new Error(`Unknown SFTP read capability: ${capabilityName}`);
44862
+ },
44863
+ async executeMutation({ source, capabilityName, args }) {
44864
+ const credentials = readCredentials(source);
44865
+ const prepared = prepareMutation(capabilityName, args, credentials.rootPath);
44866
+ return withSftp(credentials, createClient, lookupHost, async (client) => {
44867
+ let data4;
44868
+ if (prepared.kind === "upload") {
44869
+ const path = await canonicalizeDestinationPath(client, credentials.rootPath, prepared.path);
44870
+ if (!prepared.overwrite && await client.exists(path)) throw new Error("sftp.upload destination already exists");
44871
+ await client.put(prepared.file, path);
44872
+ data4 = { path, byteLength: prepared.file.byteLength };
44873
+ } else if (prepared.kind === "mkdir") {
44874
+ const path = await canonicalizeDestinationPath(client, credentials.rootPath, prepared.path);
44875
+ await client.mkdir(path, prepared.recursive);
44876
+ data4 = { path };
44877
+ } else if (prepared.kind === "rename") {
44878
+ const sourcePath = await canonicalizeExistingPath(client, credentials.rootPath, prepared.sourcePath);
44879
+ const destinationPath = await canonicalizeDestinationPath(client, credentials.rootPath, prepared.destinationPath);
44880
+ if (await client.exists(destinationPath)) throw new Error("sftp.rename destination already exists");
44881
+ await client.rename(sourcePath, destinationPath);
44882
+ data4 = { sourcePath, destinationPath };
44883
+ } else {
44884
+ const path = await canonicalizeDestinationPath(client, credentials.rootPath, prepared.path);
44885
+ await client.delete(path, true);
44886
+ data4 = { path };
44887
+ }
44888
+ return {
44889
+ status: "committed",
44890
+ data: data4,
44891
+ committedAt: Date.now(),
44892
+ idempotentReplay: false
44893
+ };
44894
+ });
44895
+ },
44896
+ async test(source) {
44897
+ try {
44898
+ const credentials = readCredentials(source);
44899
+ await withSftp(credentials, createClient, lookupHost, (client) => client.cwd());
44900
+ return { ok: true };
44901
+ } catch (error) {
44902
+ return { ok: false, reason: error instanceof Error ? error.message : "SFTP connection test failed" };
44903
+ }
44904
+ }
44905
+ };
44906
+ }
44907
+ function prepareMutation(capabilityName, args, rootPath) {
44908
+ if (capabilityName === "sftp.upload") {
44909
+ return {
44910
+ kind: "upload",
44911
+ path: mutablePath(rootPath, args.path),
44912
+ file: readBase64File(args.fileBase64),
44913
+ overwrite: readBoolean(args.overwrite, false, "overwrite")
44914
+ };
44915
+ }
44916
+ if (capabilityName === "sftp.mkdir") {
44917
+ return {
44918
+ kind: "mkdir",
44919
+ path: mutablePath(rootPath, args.path),
44920
+ recursive: readBoolean(args.recursive, true, "recursive")
44921
+ };
44922
+ }
44923
+ if (capabilityName === "sftp.rename") {
44924
+ return {
44925
+ kind: "rename",
44926
+ sourcePath: mutablePath(rootPath, args.sourcePath),
44927
+ destinationPath: mutablePath(rootPath, args.destinationPath)
44928
+ };
44929
+ }
44930
+ if (capabilityName === "sftp.delete") {
44931
+ return { kind: "delete", path: mutablePath(rootPath, args.path) };
44932
+ }
44933
+ throw new Error(`Unknown SFTP mutation capability: ${capabilityName}`);
44934
+ }
44935
+ var sftpConnector = createSftpConnector();
44936
+ function pathSchema() {
44937
+ return {
44938
+ type: "object",
44939
+ properties: { path: { type: "string", minLength: 1 } },
44940
+ required: ["path"],
44941
+ additionalProperties: false
44942
+ };
44943
+ }
44944
+ async function withSftp(credentials, createClient, lookupHost, run) {
44945
+ const addresses = await lookupHost(credentials.host);
44946
+ if (addresses.length === 0) throw new Error("SFTP host did not resolve");
44947
+ const client = createClient();
44948
+ try {
44949
+ await client.connect({
44950
+ host: addresses[0],
44951
+ port: credentials.port,
44952
+ username: credentials.username,
44953
+ password: credentials.password,
44954
+ privateKey: credentials.privateKey,
44955
+ passphrase: credentials.passphrase,
44956
+ readyTimeout: 1e4,
44957
+ retries: 1,
44958
+ hostHash: "sha256",
44959
+ hostVerifier: (hashedKey) => fingerprintMatches(credentials.hostFingerprint, hashedKey)
44960
+ });
44961
+ return await run(client);
44962
+ } finally {
44963
+ await client.end().catch(() => false);
44964
+ }
44965
+ }
44966
+ function readCredentials(source) {
44967
+ let raw;
44968
+ if (source.credentials.kind === "custom") raw = source.credentials.values;
44969
+ else if (source.credentials.kind === "api-key") {
44970
+ try {
44971
+ raw = JSON.parse(source.credentials.apiKey);
44972
+ } catch {
44973
+ throw new Error("SFTP credential must be valid JSON");
44974
+ }
44975
+ } else {
44976
+ throw new Error("SFTP requires a structured credential bundle");
44977
+ }
44978
+ if (!isPlainRecord(raw)) throw new Error("SFTP credential must be a JSON object");
44979
+ const host = requiredCredentialString2(raw.host, "host");
44980
+ validateHostname(host);
44981
+ const username = requiredCredentialString2(raw.username, "username");
44982
+ const password = readOptionalString(raw.password, "password");
44983
+ const privateKey = readOptionalString(raw.privateKey, "privateKey");
44984
+ if (!password && !privateKey) throw new Error("SFTP credential requires password or privateKey");
44985
+ const rootPath = normalizeRootPath(readOptionalString(raw.rootPath, "rootPath") ?? "/");
44986
+ return {
44987
+ host,
44988
+ port: readBoundedInteger(raw.port, 22, 1, 65535, "port"),
44989
+ username,
44990
+ password,
44991
+ privateKey,
44992
+ passphrase: readOptionalString(raw.passphrase, "passphrase"),
44993
+ hostFingerprint: parseFingerprint(requiredCredentialString2(raw.hostFingerprint, "hostFingerprint")),
44994
+ rootPath
44995
+ };
44996
+ }
44997
+ function requiredCredentialString2(value, label) {
44998
+ const parsed = readOptionalString(value, label);
44999
+ if (!parsed) throw new Error(`SFTP credential ${label} is required`);
45000
+ return parsed;
45001
+ }
45002
+ function validateHostname(host) {
45003
+ if (host.length > 253 || host.includes("://") || /[\s/@]/.test(host) || host === "localhost" || host.endsWith(".localhost") || host.endsWith(".local")) {
45004
+ throw new Error("SFTP host must be a public hostname or IP address without a scheme");
45005
+ }
45006
+ }
45007
+ async function resolvePublicAddresses(host) {
45008
+ const addresses = ipaddr.isValid(host) ? [host] : (await lookup(host, { all: true, verbatim: true })).map((entry) => entry.address);
45009
+ if (addresses.length === 0 || addresses.some((address) => !isPublicAddress(address))) {
45010
+ throw new Error("SFTP host is not a public network target");
45011
+ }
45012
+ return addresses;
45013
+ }
45014
+ function isPublicAddress(value) {
45015
+ if (!ipaddr.isValid(value)) return false;
45016
+ let address = ipaddr.parse(value);
45017
+ if (address.kind() === "ipv6" && address.isIPv4MappedAddress()) {
45018
+ address = address.toIPv4Address();
45019
+ }
45020
+ return address.range() === "unicast";
45021
+ }
45022
+ function parseFingerprint(value) {
45023
+ if (/^[a-fA-F0-9]{64}$/.test(value)) return Buffer.from(value, "hex");
45024
+ const match = /^SHA256:([A-Za-z0-9+/]{43}=?)$/.exec(value);
45025
+ if (!match) throw new Error("hostFingerprint must be 64 hex characters or an SHA256: base64 fingerprint");
45026
+ const parsed = Buffer.from(match[1], "base64");
45027
+ if (parsed.byteLength !== 32) throw new Error("hostFingerprint must contain a 32-byte SHA-256 digest");
45028
+ return parsed;
45029
+ }
45030
+ function fingerprintMatches(expected, actual) {
45031
+ const parsed = Buffer.isBuffer(actual) ? actual : /^[a-fA-F0-9]{64}$/.test(actual) ? Buffer.from(actual, "hex") : Buffer.from(actual.replace(/^SHA256:/, ""), "base64");
45032
+ return parsed.byteLength === expected.byteLength && timingSafeEqual4(parsed, expected);
45033
+ }
45034
+ function normalizeRootPath(value) {
45035
+ if (!value.startsWith("/") || value.includes("\0") || value.length > MAX_PATH_LENGTH) {
45036
+ throw new Error("rootPath must be an absolute SFTP path");
45037
+ }
45038
+ return posix.normalize(value);
45039
+ }
45040
+ function resolveRemotePath(rootPath, value) {
45041
+ const requested = readOptionalString(value, "path");
45042
+ if (!requested || requested.includes("\0") || requested.length > MAX_PATH_LENGTH) {
45043
+ throw new Error("path must be a non-empty SFTP path");
45044
+ }
45045
+ const resolved = posix.resolve(rootPath, requested.replace(/^\/+/, ""));
45046
+ if (rootPath !== "/" && resolved !== rootPath && !resolved.startsWith(`${rootPath}/`)) {
45047
+ throw new Error("path escapes the configured SFTP root");
45048
+ }
45049
+ return resolved;
45050
+ }
45051
+ function mutablePath(rootPath, value) {
45052
+ const path = resolveRemotePath(rootPath, value);
45053
+ if (path === rootPath) throw new Error("mutation path cannot target the configured SFTP root");
45054
+ return path;
45055
+ }
45056
+ async function canonicalizeExistingPath(client, configuredRoot, path) {
45057
+ const root = posix.normalize(await client.realPath(configuredRoot));
45058
+ const target = posix.normalize(await client.realPath(path));
45059
+ assertWithinCanonicalRoot(root, target);
45060
+ return target;
45061
+ }
45062
+ async function canonicalizeDestinationPath(client, configuredRoot, path) {
45063
+ const root = posix.normalize(await client.realPath(configuredRoot));
45064
+ if (await client.exists(path)) {
45065
+ const existing = posix.normalize(await client.realPath(path));
45066
+ assertWithinCanonicalRoot(root, existing);
45067
+ return existing;
45068
+ }
45069
+ let ancestor = posix.dirname(path);
45070
+ const missingSegments = [posix.basename(path)];
45071
+ while (!await client.exists(ancestor)) {
45072
+ if (ancestor === configuredRoot || ancestor === "/") break;
45073
+ missingSegments.unshift(posix.basename(ancestor));
45074
+ ancestor = posix.dirname(ancestor);
45075
+ }
45076
+ const canonicalAncestor = posix.normalize(await client.realPath(ancestor));
45077
+ assertWithinCanonicalRoot(root, canonicalAncestor);
45078
+ const destination = posix.join(canonicalAncestor, ...missingSegments);
45079
+ assertWithinCanonicalRoot(root, destination);
45080
+ return destination;
45081
+ }
45082
+ function assertWithinCanonicalRoot(root, target) {
45083
+ if (root !== "/" && target !== root && !target.startsWith(`${root}/`)) {
45084
+ throw new Error("SFTP path resolves outside the configured root");
45085
+ }
45086
+ }
45087
+
44197
45088
  // src/connectors/adapters/saleor.ts
44198
45089
  var saleorConnector = declarativeRestConnector({
44199
45090
  kind: "saleor",
@@ -62864,6 +63755,10 @@ var CONNECTOR_ADAPTER_FACTORIES = [
62864
63755
  defineFactoryAdapter(() => amazonSqsConnector, {}),
62865
63756
  defineFactoryAdapter(() => httpConnector, {}),
62866
63757
  defineFactoryAdapter(() => rssConnector, {}),
63758
+ defineFactoryAdapter(() => csvFilesConnector, {}),
63759
+ defineFactoryAdapter(() => excelFilesConnector, {}),
63760
+ defineFactoryAdapter(() => parquetFilesConnector, {}),
63761
+ defineFactoryAdapter(() => sftpConnector, {}),
62867
63762
  defineFactoryAdapter(() => chessComConnector, {}),
62868
63763
  defineFactoryAdapter(() => zapierConnector, {}),
62869
63764
  defineFactoryAdapter(() => makeConnector, {}),
@@ -142735,6 +143630,7 @@ export {
142735
143630
  buttondownConnector,
142736
143631
  cambAiConnector,
142737
143632
  cartloomConnector,
143633
+ csvFilesConnector,
142738
143634
  chainAwareConnector,
142739
143635
  chaindeskConnector,
142740
143636
  chatAidConnector,
@@ -142754,6 +143650,7 @@ export {
142754
143650
  dripConnector,
142755
143651
  echowinConnector,
142756
143652
  elevenlabsConnector,
143653
+ excelFilesConnector,
142757
143654
  everhourConnector,
142758
143655
  featheryConnector,
142759
143656
  fellowConnector,
@@ -142892,12 +143789,15 @@ export {
142892
143789
  plaidConnector,
142893
143790
  pipedreamConnector,
142894
143791
  pipedriveConnector,
143792
+ parquetFilesConnector,
142895
143793
  quickbooksConnector,
142896
143794
  recallAiConnector,
142897
143795
  rampConnector,
142898
143796
  ringcentralConnector,
142899
143797
  rssConnector,
142900
143798
  salesforceConnector,
143799
+ createSftpConnector,
143800
+ sftpConnector,
142901
143801
  saleorConnector,
142902
143802
  savvycalConnector,
142903
143803
  sharepoint,
@@ -143349,4 +144249,4 @@ export {
143349
144249
  demandbaseConnector,
143350
144250
  adapters_exports
143351
144251
  };
143352
- //# sourceMappingURL=chunk-UC7J6GZF.js.map
144252
+ //# sourceMappingURL=chunk-ARONCYSG.js.map