@tangle-network/agent-integrations 0.53.27 → 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.
- package/dist/catalog.js +4 -4
- package/dist/{chunk-4H5F6E7W.js → chunk-ARONCYSG.js} +939 -75
- package/dist/{chunk-4H5F6E7W.js.map → chunk-ARONCYSG.js.map} +1 -1
- package/dist/{chunk-RUHXNRQU.js → chunk-U4OI4QU3.js} +29 -2
- package/dist/chunk-U4OI4QU3.js.map +1 -0
- package/dist/{chunk-J7CBKM7C.js → chunk-XGVHAXTB.js} +2 -2
- package/dist/{chunk-TMYH36VV.js → chunk-XVXTWH3O.js} +3 -3
- package/dist/connectors/adapters/index.d.ts +52 -1
- package/dist/connectors/adapters/index.js +11 -1
- package/dist/connectors/index.d.ts +2 -1
- package/dist/connectors/index.js +12 -2
- package/dist/index.d.ts +2 -1
- package/dist/index.js +14 -4
- package/dist/mcp.js +4 -4
- package/dist/registry.js +4 -4
- package/dist/runtime.js +4 -4
- package/dist/specs.js +3 -3
- package/docs/integration-execution-audit.md +12 -8
- package/docs/integration-execution-matrix.json +125 -60
- package/package.json +11 -2
- package/dist/chunk-RUHXNRQU.js.map +0 -1
- /package/dist/{chunk-J7CBKM7C.js.map → chunk-XGVHAXTB.js.map} +0 -0
- /package/dist/{chunk-TMYH36VV.js.map → chunk-XVXTWH3O.js.map} +0 -0
|
@@ -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(
|
|
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(
|
|
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
|
|
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, {}),
|
|
@@ -68846,11 +69741,15 @@ var figmaConnector = declarativeRestConnector({
|
|
|
68846
69741
|
authorizationUrl: "https://www.figma.com/oauth",
|
|
68847
69742
|
tokenUrl: "https://api.figma.com/v1/oauth/token",
|
|
68848
69743
|
scopes: [
|
|
68849
|
-
"
|
|
68850
|
-
"
|
|
69744
|
+
"current_user:read",
|
|
69745
|
+
"file_comments:read",
|
|
68851
69746
|
"file_comments:write",
|
|
69747
|
+
"file_content:read",
|
|
68852
69748
|
"file_dev_resources:read",
|
|
68853
|
-
"
|
|
69749
|
+
"file_versions:read",
|
|
69750
|
+
"library_content:read",
|
|
69751
|
+
"projects:read",
|
|
69752
|
+
"team_library_content:read",
|
|
68854
69753
|
"webhooks:write"
|
|
68855
69754
|
],
|
|
68856
69755
|
clientIdEnv: "FIGMA_OAUTH_CLIENT_ID",
|
|
@@ -68867,7 +69766,7 @@ var figmaConnector = declarativeRestConnector({
|
|
|
68867
69766
|
description: "Return the authenticated Figma user.",
|
|
68868
69767
|
parameters: { type: "object", properties: {}, required: [] },
|
|
68869
69768
|
request: { method: "GET", path: "/v1/me" },
|
|
68870
|
-
requiredScopes: ["
|
|
69769
|
+
requiredScopes: ["current_user:read"]
|
|
68871
69770
|
},
|
|
68872
69771
|
{
|
|
68873
69772
|
name: "files.get",
|
|
@@ -68898,7 +69797,7 @@ var figmaConnector = declarativeRestConnector({
|
|
|
68898
69797
|
branch_data: "{branch_data}"
|
|
68899
69798
|
}
|
|
68900
69799
|
},
|
|
68901
|
-
requiredScopes: ["
|
|
69800
|
+
requiredScopes: ["file_content:read"]
|
|
68902
69801
|
},
|
|
68903
69802
|
{
|
|
68904
69803
|
name: "files.nodes",
|
|
@@ -68920,7 +69819,7 @@ var figmaConnector = declarativeRestConnector({
|
|
|
68920
69819
|
path: "/v1/files/{file_key}/nodes",
|
|
68921
69820
|
query: { ids: "{ids}", version: "{version}", depth: "{depth}", geometry: "{geometry}" }
|
|
68922
69821
|
},
|
|
68923
|
-
requiredScopes: ["
|
|
69822
|
+
requiredScopes: ["file_content:read"]
|
|
68924
69823
|
},
|
|
68925
69824
|
{
|
|
68926
69825
|
name: "files.images",
|
|
@@ -68955,7 +69854,7 @@ var figmaConnector = declarativeRestConnector({
|
|
|
68955
69854
|
version: "{version}"
|
|
68956
69855
|
}
|
|
68957
69856
|
},
|
|
68958
|
-
requiredScopes: ["
|
|
69857
|
+
requiredScopes: ["file_content:read"]
|
|
68959
69858
|
},
|
|
68960
69859
|
{
|
|
68961
69860
|
name: "files.image_fills",
|
|
@@ -68967,7 +69866,7 @@ var figmaConnector = declarativeRestConnector({
|
|
|
68967
69866
|
required: ["file_key"]
|
|
68968
69867
|
},
|
|
68969
69868
|
request: { method: "GET", path: "/v1/files/{file_key}/images" },
|
|
68970
|
-
requiredScopes: ["
|
|
69869
|
+
requiredScopes: ["file_content:read"]
|
|
68971
69870
|
},
|
|
68972
69871
|
{
|
|
68973
69872
|
name: "files.versions.list",
|
|
@@ -68988,7 +69887,7 @@ var figmaConnector = declarativeRestConnector({
|
|
|
68988
69887
|
path: "/v1/files/{file_key}/versions",
|
|
68989
69888
|
query: { page_size: "{page_size}", before: "{before}", after: "{after}" }
|
|
68990
69889
|
},
|
|
68991
|
-
requiredScopes: ["
|
|
69890
|
+
requiredScopes: ["file_versions:read"]
|
|
68992
69891
|
},
|
|
68993
69892
|
{
|
|
68994
69893
|
name: "files.components.list",
|
|
@@ -69000,7 +69899,7 @@ var figmaConnector = declarativeRestConnector({
|
|
|
69000
69899
|
required: ["file_key"]
|
|
69001
69900
|
},
|
|
69002
69901
|
request: { method: "GET", path: "/v1/files/{file_key}/components" },
|
|
69003
|
-
requiredScopes: ["
|
|
69902
|
+
requiredScopes: ["library_content:read"]
|
|
69004
69903
|
},
|
|
69005
69904
|
{
|
|
69006
69905
|
name: "files.component_sets.list",
|
|
@@ -69012,7 +69911,7 @@ var figmaConnector = declarativeRestConnector({
|
|
|
69012
69911
|
required: ["file_key"]
|
|
69013
69912
|
},
|
|
69014
69913
|
request: { method: "GET", path: "/v1/files/{file_key}/component_sets" },
|
|
69015
|
-
requiredScopes: ["
|
|
69914
|
+
requiredScopes: ["library_content:read"]
|
|
69016
69915
|
},
|
|
69017
69916
|
{
|
|
69018
69917
|
name: "files.styles.list",
|
|
@@ -69024,31 +69923,7 @@ var figmaConnector = declarativeRestConnector({
|
|
|
69024
69923
|
required: ["file_key"]
|
|
69025
69924
|
},
|
|
69026
69925
|
request: { method: "GET", path: "/v1/files/{file_key}/styles" },
|
|
69027
|
-
requiredScopes: ["
|
|
69028
|
-
},
|
|
69029
|
-
{
|
|
69030
|
-
name: "files.variables.local",
|
|
69031
|
-
class: "read",
|
|
69032
|
-
description: "List locally defined variables and variable collections in a file (Enterprise-only).",
|
|
69033
|
-
parameters: {
|
|
69034
|
-
type: "object",
|
|
69035
|
-
properties: { file_key: { type: "string" } },
|
|
69036
|
-
required: ["file_key"]
|
|
69037
|
-
},
|
|
69038
|
-
request: { method: "GET", path: "/v1/files/{file_key}/variables/local" },
|
|
69039
|
-
requiredScopes: ["file_variables:read"]
|
|
69040
|
-
},
|
|
69041
|
-
{
|
|
69042
|
-
name: "files.variables.published",
|
|
69043
|
-
class: "read",
|
|
69044
|
-
description: "List variables published from a Figma library file (Enterprise-only).",
|
|
69045
|
-
parameters: {
|
|
69046
|
-
type: "object",
|
|
69047
|
-
properties: { file_key: { type: "string" } },
|
|
69048
|
-
required: ["file_key"]
|
|
69049
|
-
},
|
|
69050
|
-
request: { method: "GET", path: "/v1/files/{file_key}/variables/published" },
|
|
69051
|
-
requiredScopes: ["file_variables:read"]
|
|
69926
|
+
requiredScopes: ["library_content:read"]
|
|
69052
69927
|
},
|
|
69053
69928
|
{
|
|
69054
69929
|
name: "files.dev_resources.list",
|
|
@@ -69086,7 +69961,7 @@ var figmaConnector = declarativeRestConnector({
|
|
|
69086
69961
|
path: "/v1/files/{file_key}/comments",
|
|
69087
69962
|
query: { as_md: "{as_md}" }
|
|
69088
69963
|
},
|
|
69089
|
-
requiredScopes: ["
|
|
69964
|
+
requiredScopes: ["file_comments:read"]
|
|
69090
69965
|
},
|
|
69091
69966
|
{
|
|
69092
69967
|
name: "teams.projects.list",
|
|
@@ -69098,7 +69973,7 @@ var figmaConnector = declarativeRestConnector({
|
|
|
69098
69973
|
required: ["team_id"]
|
|
69099
69974
|
},
|
|
69100
69975
|
request: { method: "GET", path: "/v1/teams/{team_id}/projects" },
|
|
69101
|
-
requiredScopes: ["
|
|
69976
|
+
requiredScopes: ["projects:read"]
|
|
69102
69977
|
},
|
|
69103
69978
|
{
|
|
69104
69979
|
name: "projects.files.list",
|
|
@@ -69117,7 +69992,7 @@ var figmaConnector = declarativeRestConnector({
|
|
|
69117
69992
|
path: "/v1/projects/{project_id}/files",
|
|
69118
69993
|
query: { branch_data: "{branch_data}" }
|
|
69119
69994
|
},
|
|
69120
|
-
requiredScopes: ["
|
|
69995
|
+
requiredScopes: ["projects:read"]
|
|
69121
69996
|
},
|
|
69122
69997
|
{
|
|
69123
69998
|
name: "teams.components.list",
|
|
@@ -69138,7 +70013,7 @@ var figmaConnector = declarativeRestConnector({
|
|
|
69138
70013
|
path: "/v1/teams/{team_id}/components",
|
|
69139
70014
|
query: { page_size: "{page_size}", after: "{after}", before: "{before}" }
|
|
69140
70015
|
},
|
|
69141
|
-
requiredScopes: ["
|
|
70016
|
+
requiredScopes: ["team_library_content:read"]
|
|
69142
70017
|
},
|
|
69143
70018
|
{
|
|
69144
70019
|
name: "teams.styles.list",
|
|
@@ -69159,27 +70034,7 @@ var figmaConnector = declarativeRestConnector({
|
|
|
69159
70034
|
path: "/v1/teams/{team_id}/styles",
|
|
69160
70035
|
query: { page_size: "{page_size}", after: "{after}", before: "{before}" }
|
|
69161
70036
|
},
|
|
69162
|
-
requiredScopes: ["
|
|
69163
|
-
},
|
|
69164
|
-
{
|
|
69165
|
-
name: "analytics.library.component_usages",
|
|
69166
|
-
class: "read",
|
|
69167
|
-
description: "Read library analytics: component usage rollup for a library file.",
|
|
69168
|
-
parameters: {
|
|
69169
|
-
type: "object",
|
|
69170
|
-
properties: {
|
|
69171
|
-
file_key: { type: "string" },
|
|
69172
|
-
group_by: { type: "string", enum: ["component", "file"] },
|
|
69173
|
-
cursor: { type: "string" }
|
|
69174
|
-
},
|
|
69175
|
-
required: ["file_key", "group_by"]
|
|
69176
|
-
},
|
|
69177
|
-
request: {
|
|
69178
|
-
method: "GET",
|
|
69179
|
-
path: "/v1/analytics/libraries/{file_key}/component/usages",
|
|
69180
|
-
query: { group_by: "{group_by}", cursor: "{cursor}" }
|
|
69181
|
-
},
|
|
69182
|
-
requiredScopes: ["library_analytics:read"]
|
|
70037
|
+
requiredScopes: ["team_library_content:read"]
|
|
69183
70038
|
},
|
|
69184
70039
|
{
|
|
69185
70040
|
name: "files.comments.create",
|
|
@@ -69310,8 +70165,12 @@ var figjamConnector = declarativeRestConnector({
|
|
|
69310
70165
|
authorizationUrl: "https://www.figma.com/oauth",
|
|
69311
70166
|
tokenUrl: "https://api.figma.com/v1/oauth/token",
|
|
69312
70167
|
scopes: [
|
|
69313
|
-
"
|
|
70168
|
+
"current_user:read",
|
|
70169
|
+
"file_comments:read",
|
|
69314
70170
|
"file_comments:write",
|
|
70171
|
+
"file_content:read",
|
|
70172
|
+
"file_versions:read",
|
|
70173
|
+
"projects:read",
|
|
69315
70174
|
"webhooks:write"
|
|
69316
70175
|
],
|
|
69317
70176
|
clientIdEnv: "FIGMA_OAUTH_CLIENT_ID",
|
|
@@ -69328,7 +70187,7 @@ var figjamConnector = declarativeRestConnector({
|
|
|
69328
70187
|
description: "Return the authenticated Figma/FigJam user.",
|
|
69329
70188
|
parameters: { type: "object", properties: {}, required: [] },
|
|
69330
70189
|
request: { method: "GET", path: "/v1/me" },
|
|
69331
|
-
requiredScopes: ["
|
|
70190
|
+
requiredScopes: ["current_user:read"]
|
|
69332
70191
|
},
|
|
69333
70192
|
{
|
|
69334
70193
|
name: "files.get",
|
|
@@ -69357,7 +70216,7 @@ var figjamConnector = declarativeRestConnector({
|
|
|
69357
70216
|
plugin_data: "{plugin_data}"
|
|
69358
70217
|
}
|
|
69359
70218
|
},
|
|
69360
|
-
requiredScopes: ["
|
|
70219
|
+
requiredScopes: ["file_content:read"]
|
|
69361
70220
|
},
|
|
69362
70221
|
{
|
|
69363
70222
|
name: "files.nodes",
|
|
@@ -69379,7 +70238,7 @@ var figjamConnector = declarativeRestConnector({
|
|
|
69379
70238
|
path: "/v1/files/{file_key}/nodes",
|
|
69380
70239
|
query: { ids: "{ids}", version: "{version}", depth: "{depth}", geometry: "{geometry}" }
|
|
69381
70240
|
},
|
|
69382
|
-
requiredScopes: ["
|
|
70241
|
+
requiredScopes: ["file_content:read"]
|
|
69383
70242
|
},
|
|
69384
70243
|
{
|
|
69385
70244
|
name: "files.images",
|
|
@@ -69414,7 +70273,7 @@ var figjamConnector = declarativeRestConnector({
|
|
|
69414
70273
|
version: "{version}"
|
|
69415
70274
|
}
|
|
69416
70275
|
},
|
|
69417
|
-
requiredScopes: ["
|
|
70276
|
+
requiredScopes: ["file_content:read"]
|
|
69418
70277
|
},
|
|
69419
70278
|
{
|
|
69420
70279
|
name: "files.image_fills",
|
|
@@ -69426,7 +70285,7 @@ var figjamConnector = declarativeRestConnector({
|
|
|
69426
70285
|
required: ["file_key"]
|
|
69427
70286
|
},
|
|
69428
70287
|
request: { method: "GET", path: "/v1/files/{file_key}/images" },
|
|
69429
|
-
requiredScopes: ["
|
|
70288
|
+
requiredScopes: ["file_content:read"]
|
|
69430
70289
|
},
|
|
69431
70290
|
{
|
|
69432
70291
|
name: "files.versions.list",
|
|
@@ -69447,7 +70306,7 @@ var figjamConnector = declarativeRestConnector({
|
|
|
69447
70306
|
path: "/v1/files/{file_key}/versions",
|
|
69448
70307
|
query: { page_size: "{page_size}", before: "{before}", after: "{after}" }
|
|
69449
70308
|
},
|
|
69450
|
-
requiredScopes: ["
|
|
70309
|
+
requiredScopes: ["file_versions:read"]
|
|
69451
70310
|
},
|
|
69452
70311
|
{
|
|
69453
70312
|
name: "files.comments.list",
|
|
@@ -69466,7 +70325,7 @@ var figjamConnector = declarativeRestConnector({
|
|
|
69466
70325
|
path: "/v1/files/{file_key}/comments",
|
|
69467
70326
|
query: { as_md: "{as_md}" }
|
|
69468
70327
|
},
|
|
69469
|
-
requiredScopes: ["
|
|
70328
|
+
requiredScopes: ["file_comments:read"]
|
|
69470
70329
|
},
|
|
69471
70330
|
{
|
|
69472
70331
|
name: "teams.projects.list",
|
|
@@ -69478,7 +70337,7 @@ var figjamConnector = declarativeRestConnector({
|
|
|
69478
70337
|
required: ["team_id"]
|
|
69479
70338
|
},
|
|
69480
70339
|
request: { method: "GET", path: "/v1/teams/{team_id}/projects" },
|
|
69481
|
-
requiredScopes: ["
|
|
70340
|
+
requiredScopes: ["projects:read"]
|
|
69482
70341
|
},
|
|
69483
70342
|
{
|
|
69484
70343
|
name: "projects.files.list",
|
|
@@ -69495,7 +70354,7 @@ var figjamConnector = declarativeRestConnector({
|
|
|
69495
70354
|
method: "GET",
|
|
69496
70355
|
path: "/v1/projects/{project_id}/files"
|
|
69497
70356
|
},
|
|
69498
|
-
requiredScopes: ["
|
|
70357
|
+
requiredScopes: ["projects:read"]
|
|
69499
70358
|
},
|
|
69500
70359
|
{
|
|
69501
70360
|
name: "files.comments.create",
|
|
@@ -142771,6 +143630,7 @@ export {
|
|
|
142771
143630
|
buttondownConnector,
|
|
142772
143631
|
cambAiConnector,
|
|
142773
143632
|
cartloomConnector,
|
|
143633
|
+
csvFilesConnector,
|
|
142774
143634
|
chainAwareConnector,
|
|
142775
143635
|
chaindeskConnector,
|
|
142776
143636
|
chatAidConnector,
|
|
@@ -142790,6 +143650,7 @@ export {
|
|
|
142790
143650
|
dripConnector,
|
|
142791
143651
|
echowinConnector,
|
|
142792
143652
|
elevenlabsConnector,
|
|
143653
|
+
excelFilesConnector,
|
|
142793
143654
|
everhourConnector,
|
|
142794
143655
|
featheryConnector,
|
|
142795
143656
|
fellowConnector,
|
|
@@ -142928,12 +143789,15 @@ export {
|
|
|
142928
143789
|
plaidConnector,
|
|
142929
143790
|
pipedreamConnector,
|
|
142930
143791
|
pipedriveConnector,
|
|
143792
|
+
parquetFilesConnector,
|
|
142931
143793
|
quickbooksConnector,
|
|
142932
143794
|
recallAiConnector,
|
|
142933
143795
|
rampConnector,
|
|
142934
143796
|
ringcentralConnector,
|
|
142935
143797
|
rssConnector,
|
|
142936
143798
|
salesforceConnector,
|
|
143799
|
+
createSftpConnector,
|
|
143800
|
+
sftpConnector,
|
|
142937
143801
|
saleorConnector,
|
|
142938
143802
|
savvycalConnector,
|
|
142939
143803
|
sharepoint,
|
|
@@ -143385,4 +144249,4 @@ export {
|
|
|
143385
144249
|
demandbaseConnector,
|
|
143386
144250
|
adapters_exports
|
|
143387
144251
|
};
|
|
143388
|
-
//# sourceMappingURL=chunk-
|
|
144252
|
+
//# sourceMappingURL=chunk-ARONCYSG.js.map
|