@oomol-lab/open-connector 1.6.2 → 1.6.3
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/README.md +27 -0
- package/assets/open-connector/catalog/apps/assured_platform.json +218 -0
- package/assets/open-connector/catalog/apps/baixiao.json +1080 -0
- package/assets/open-connector/catalog/apps/benchmarkone.json +956 -0
- package/assets/open-connector/catalog/apps/bing_webmaster.json +3097 -0
- package/assets/open-connector/catalog/apps/buzzsprout.json +1979 -0
- package/assets/open-connector/catalog/apps/feishu.json +13 -19
- package/assets/open-connector/catalog/apps/feishu_app_bot.json +10 -17
- package/assets/open-connector/catalog/apps/linkfox.json +836 -0
- package/assets/open-connector/catalog/apps/metatraderapi.json +1077 -0
- package/assets/open-connector/catalog/apps/mktindex.json +2411 -0
- package/assets/open-connector/catalog/apps/mojo_helpdesk.json +660 -0
- package/assets/open-connector/catalog/apps/mumble.json +446 -0
- package/assets/open-connector/catalog/apps/notion.json +112 -3
- package/assets/open-connector/catalog/apps/omise.json +438 -0
- package/assets/open-connector/catalog/apps/panjiva.json +2858 -0
- package/assets/open-connector/catalog/apps/papertrail.json +449 -0
- package/assets/open-connector/catalog/apps/peec.json +747 -0
- package/assets/open-connector/catalog/apps/polygon_io.json +5156 -584
- package/assets/open-connector/catalog/apps/quant_data.json +1928 -0
- package/assets/open-connector/catalog/apps/riddle_quiz_maker.json +621 -0
- package/assets/open-connector/catalog/apps/slack.json +327 -4
- package/assets/open-connector/catalog/apps/slackbot.json +280 -3
- package/assets/open-connector/catalog/apps/templatedocs.json +438 -0
- package/assets/open-connector/catalog/apps/terminus_app.json +510 -0
- package/assets/open-connector/catalog/apps/ticket_tailor.json +584 -0
- package/assets/open-connector/catalog/apps/tongdaxin.json +2612 -79
- package/assets/open-connector/catalog/apps/veremark.json +514 -0
- package/assets/open-connector/catalog/apps/walletap.json +549 -0
- package/assets/open-connector/catalog/apps/xiaohongshu_store.json +955 -39
- package/assets/open-connector/catalog/apps-index.json +1 -1
- package/package.json +5 -1
- package/src/connection-service.d.ts +2 -0
- package/src/connection-service.js +8 -1
- package/src/core/provider-id.d.ts +5 -0
- package/src/core/provider-id.js +12 -0
- package/src/oauth/oauth-credential-refresh-service.js +2 -0
- package/src/oauth/oauth-flow-service.js +2 -0
- package/src/providers/action-contracts.generated.d.ts +27 -7
- package/src/providers/assured_platform/executors.d.ts +4 -0
- package/src/providers/assured_platform/executors.js +18 -0
- package/src/providers/assured_platform/runtime.d.ts +7 -0
- package/src/providers/assured_platform/runtime.js +108 -0
- package/src/providers/baixiao/actions.d.ts +2 -0
- package/src/providers/baixiao/actions.js +377 -0
- package/src/providers/baixiao/executors.d.ts +4 -0
- package/src/providers/baixiao/executors.js +106 -0
- package/src/providers/benchmarkone/executors.d.ts +4 -0
- package/src/providers/benchmarkone/executors.js +26 -0
- package/src/providers/benchmarkone/runtime.d.ts +12 -0
- package/src/providers/benchmarkone/runtime.js +113 -0
- package/src/providers/bing_webmaster/actions.d.ts +2 -0
- package/src/providers/bing_webmaster/actions.js +113 -0
- package/src/providers/bing_webmaster/executors.d.ts +4 -0
- package/src/providers/bing_webmaster/executors.js +104 -0
- package/src/providers/bing_webmaster/management-actions.d.ts +2 -0
- package/src/providers/bing_webmaster/management-actions.js +241 -0
- package/src/providers/bing_webmaster/reporting-actions.d.ts +2 -0
- package/src/providers/bing_webmaster/reporting-actions.js +300 -0
- package/src/providers/bing_webmaster/schemas.d.ts +33 -0
- package/src/providers/bing_webmaster/schemas.js +313 -0
- package/src/providers/buzzsprout/executors.d.ts +4 -0
- package/src/providers/buzzsprout/executors.js +21 -0
- package/src/providers/buzzsprout/runtime.d.ts +12 -0
- package/src/providers/buzzsprout/runtime.js +237 -0
- package/src/providers/feishu/shared/drive-actions.d.ts +1 -0
- package/src/providers/feishu/shared/drive-actions.js +13 -9
- package/src/providers/feishu/shared/drive-runtime.js +15 -3
- package/src/providers/feishu/shared/wiki-actions.js +4 -2
- package/src/providers/hithink_finance/runtime.js +39 -60
- package/src/providers/linkfox/actions.js +2 -0
- package/src/providers/linkfox/runtime.js +70 -1
- package/src/providers/linkfox/sif-actions.d.ts +10 -0
- package/src/providers/linkfox/sif-actions.js +193 -0
- package/src/providers/metatraderapi/executors.d.ts +4 -0
- package/src/providers/metatraderapi/executors.js +18 -0
- package/src/providers/metatraderapi/runtime.d.ts +7 -0
- package/src/providers/metatraderapi/runtime.js +216 -0
- package/src/providers/mktindex/actions-mmi.d.ts +2 -0
- package/src/providers/mktindex/actions-mmi.js +510 -0
- package/src/providers/mktindex/actions.d.ts +2 -0
- package/src/providers/mktindex/actions.js +2 -0
- package/src/providers/mktindex/executors.d.ts +4 -0
- package/src/providers/mktindex/executors.js +27 -0
- package/src/providers/mktindex/request.d.ts +17 -0
- package/src/providers/mktindex/request.js +48 -0
- package/src/providers/mktindex/runtime.d.ts +9 -0
- package/src/providers/mktindex/runtime.js +492 -0
- package/src/providers/mojo_helpdesk/executors.d.ts +4 -0
- package/src/providers/mojo_helpdesk/executors.js +18 -0
- package/src/providers/mojo_helpdesk/runtime.d.ts +7 -0
- package/src/providers/mojo_helpdesk/runtime.js +173 -0
- package/src/providers/mumble/executors.d.ts +4 -0
- package/src/providers/mumble/executors.js +99 -0
- package/src/providers/notion/executors.d.ts +9 -0
- package/src/providers/notion/executors.js +161 -6
- package/src/providers/omise/executors.d.ts +4 -0
- package/src/providers/omise/executors.js +120 -0
- package/src/providers/panjiva/actions.d.ts +14 -0
- package/src/providers/panjiva/actions.js +389 -0
- package/src/providers/panjiva/executors.d.ts +4 -0
- package/src/providers/panjiva/executors.js +136 -0
- package/src/providers/papertrail/executors.d.ts +4 -0
- package/src/providers/papertrail/executors.js +15 -0
- package/src/providers/papertrail/runtime.d.ts +7 -0
- package/src/providers/papertrail/runtime.js +167 -0
- package/src/providers/peec/executors.d.ts +4 -0
- package/src/providers/peec/executors.js +15 -0
- package/src/providers/peec/runtime.d.ts +7 -0
- package/src/providers/peec/runtime.js +128 -0
- package/src/providers/polygon_io/actions.d.ts +2 -0
- package/src/providers/polygon_io/actions.js +282 -0
- package/src/providers/polygon_io/expanded-actions.d.ts +2 -0
- package/src/providers/polygon_io/expanded-actions.js +375 -0
- package/src/providers/polygon_io/expanded-runtime.d.ts +16 -0
- package/src/providers/polygon_io/expanded-runtime.js +277 -0
- package/src/providers/polygon_io/runtime.js +21 -2
- package/src/providers/quant_data/executors.d.ts +4 -0
- package/src/providers/quant_data/executors.js +15 -0
- package/src/providers/quant_data/runtime.d.ts +7 -0
- package/src/providers/quant_data/runtime.js +118 -0
- package/src/providers/registry.generated.js +20 -0
- package/src/providers/riddle_quiz_maker/executors.d.ts +4 -0
- package/src/providers/riddle_quiz_maker/executors.js +15 -0
- package/src/providers/riddle_quiz_maker/runtime.d.ts +7 -0
- package/src/providers/riddle_quiz_maker/runtime.js +145 -0
- package/src/providers/slack/actions.js +106 -3
- package/src/providers/slack/runtime.js +260 -36
- package/src/providers/slackbot/actions.js +1 -1
- package/src/providers/templatedocs/executors.d.ts +4 -0
- package/src/providers/templatedocs/executors.js +18 -0
- package/src/providers/templatedocs/runtime.d.ts +13 -0
- package/src/providers/templatedocs/runtime.js +151 -0
- package/src/providers/terminus_app/executors.d.ts +4 -0
- package/src/providers/terminus_app/executors.js +15 -0
- package/src/providers/terminus_app/runtime.d.ts +7 -0
- package/src/providers/terminus_app/runtime.js +172 -0
- package/src/providers/ticket_tailor/executors.d.ts +4 -0
- package/src/providers/ticket_tailor/executors.js +15 -0
- package/src/providers/ticket_tailor/runtime.d.ts +7 -0
- package/src/providers/ticket_tailor/runtime.js +152 -0
- package/src/providers/tongdaxin/actions.d.ts +1 -0
- package/src/providers/tongdaxin/actions.js +6 -3
- package/src/providers/tongdaxin/executors.js +51 -10
- package/src/providers/tongdaxin/named-action-output.d.ts +1 -0
- package/src/providers/tongdaxin/named-action-output.js +149 -0
- package/src/providers/tongdaxin/named-action-routing.d.ts +9 -0
- package/src/providers/tongdaxin/named-action-routing.js +417 -0
- package/src/providers/tongdaxin/named-actions.d.ts +2 -0
- package/src/providers/tongdaxin/named-actions.js +378 -0
- package/src/providers/veremark/executors.d.ts +4 -0
- package/src/providers/veremark/executors.js +129 -0
- package/src/providers/walletap/executors.d.ts +4 -0
- package/src/providers/walletap/executors.js +15 -0
- package/src/providers/walletap/runtime.d.ts +7 -0
- package/src/providers/walletap/runtime.js +147 -0
- package/src/providers/weixin_official_account/access-token.js +31 -7
- package/src/providers/weixin_store/access-token.js +33 -7
- package/src/providers/xiaohongshu_store/executors.js +152 -3
- package/src/server/api/openapi.js +3 -0
- package/src/server/connector-assets.d.ts +4 -0
- package/src/server/connector-assets.js +12 -0
- package/src/server/connector-build.d.ts +33 -0
- package/src/server/connector-build.js +73 -0
- package/src/server/connector-runtime.d.ts +1 -2
- package/src/server/connector-runtime.js +2 -8
- package/src/server/server-assets.d.ts +0 -28
- package/src/server/server-assets.js +0 -50
|
@@ -0,0 +1,389 @@
|
|
|
1
|
+
import { jsonSchema as s } from "../../core/json-schema.js";
|
|
2
|
+
import { defineProviderAction } from "../../core/provider-definition.js";
|
|
3
|
+
const service = "panjiva";
|
|
4
|
+
const dataSource = s.nonEmptyString("Data source, such as global or us-imports. Use list_data_sources to discover available sources; global covers the last five years.");
|
|
5
|
+
const query = s.object("Free-text search criteria.", {
|
|
6
|
+
text: s.string("Search text. Supports + (AND), | (OR), - (exclude), quoted phrases, trailing *, and parentheses."),
|
|
7
|
+
group: s.string("Named search group, such as goods_described, consignee_name, shipper_name, or main. Discover groups with get_data_source_metadata."),
|
|
8
|
+
custom_group: s.array("Explicit fields to search instead of a named group.", s.string("Searchable field name.")),
|
|
9
|
+
operator: s.stringEnum("Boolean operator between search terms; the upstream default is OR.", ["AND", "OR"]),
|
|
10
|
+
match: s.stringEnum("Match word stems or exact terms; the upstream default is stem.", ["stem", "exact"]),
|
|
11
|
+
}, { required: ["text"] });
|
|
12
|
+
const selection = {
|
|
13
|
+
query,
|
|
14
|
+
queries: s.array("Multiple search criteria; every query must match.", query, { maxItems: 500 }),
|
|
15
|
+
filters: s.looseObject("Native Panjiva filters, including AND, OR, NOT, ranges, dates and geographic constraints. For example: {record_date:{gte:'2025-01-01'},destination_countries:'United States'}. Discover fields with get_data_source_metadata; syntax: https://panjiva.com/api-guide/data-selection/filters.", {}),
|
|
16
|
+
};
|
|
17
|
+
const metricOperation = s.stringEnum("Statistical aggregation operation.", ["sum", "max", "avg", "min"]);
|
|
18
|
+
const metrics = s.array("Aggregate statistics across matching shipments.", s.object("Metric and aggregation operation.", {
|
|
19
|
+
metric: s.string("Numeric field to aggregate, such as value_usd, weight_kg or volume_teu. Available fields depend on the data source."),
|
|
20
|
+
op: metricOperation,
|
|
21
|
+
}));
|
|
22
|
+
const groupSort = s.object("Sort an aggregation; metric keys must also be declared in metrics.", {
|
|
23
|
+
key: s.string("Sort by count, field, or an available metric."),
|
|
24
|
+
order: s.stringEnum("Ascending or descending order.", ["asc", "desc"]),
|
|
25
|
+
op: metricOperation,
|
|
26
|
+
}, { required: ["key"] });
|
|
27
|
+
const shipmentSort = s.array("Shipment sort fields in priority order.", s.object("One shipment sort rule.", {
|
|
28
|
+
field: s.string("Sortable shipment field; discover fields with get_data_source_metadata."),
|
|
29
|
+
order: s.stringEnum("Ascending or descending order.", ["asc", "desc"]),
|
|
30
|
+
}));
|
|
31
|
+
const timeSeriesFields = {
|
|
32
|
+
interval: s.stringEnum("Time-series bucket interval.", ["week", "month", "quarter", "year"]),
|
|
33
|
+
min_date: s.string("First date included in the time series.", { format: "date" }),
|
|
34
|
+
max_date: s.string("Last date included in the time series.", { format: "date" }),
|
|
35
|
+
};
|
|
36
|
+
const dimensionFields = {
|
|
37
|
+
field: s.string("Field to group by; discover available dimensions with get_data_source_metadata."),
|
|
38
|
+
include_missing: s.boolean("Include missing values as NO_VALUE buckets."),
|
|
39
|
+
sort: groupSort,
|
|
40
|
+
};
|
|
41
|
+
const dimensions = s.array("One to three successive grouping dimensions. Only the first dimension supports offset; size plus offset cannot exceed 1000.", s.object("One grouping dimension.", {
|
|
42
|
+
...dimensionFields,
|
|
43
|
+
size: s.integer("Maximum buckets in this dimension; upstream default is 10.", {
|
|
44
|
+
minimum: 0,
|
|
45
|
+
maximum: 100,
|
|
46
|
+
}),
|
|
47
|
+
offset: s.integer("First-dimension bucket offset; upstream default is 0.", {
|
|
48
|
+
minimum: 0,
|
|
49
|
+
maximum: 999,
|
|
50
|
+
}),
|
|
51
|
+
}, { required: ["field", "sort"] }), { minItems: 1, maxItems: 3 });
|
|
52
|
+
const bulkDimensions = s.array("One grouping dimension for a bulk rollup without synchronous pagination limits.", s.object("One bulk grouping dimension.", dimensionFields, { required: ["field", "sort"] }), { minItems: 1, maxItems: 1 });
|
|
53
|
+
const companyType = s.stringEnum("Company identifier representation; upstream default is country_company_name.", [
|
|
54
|
+
"ccn",
|
|
55
|
+
"country_company_name",
|
|
56
|
+
"pid",
|
|
57
|
+
"capiq",
|
|
58
|
+
"ultimate_parent_capiq",
|
|
59
|
+
]);
|
|
60
|
+
const companyFields = {
|
|
61
|
+
...selection,
|
|
62
|
+
company_type: companyType,
|
|
63
|
+
direction: s.stringEnum("Trade role to search; upstream default is bidirectional.", [
|
|
64
|
+
"bidirectional",
|
|
65
|
+
"consignee",
|
|
66
|
+
"shipper",
|
|
67
|
+
]),
|
|
68
|
+
metrics,
|
|
69
|
+
};
|
|
70
|
+
const companySearchFields = {
|
|
71
|
+
...companyFields,
|
|
72
|
+
size: s.integer("Maximum company results per trade direction.", { minimum: 0, maximum: 5000 }),
|
|
73
|
+
sort: groupSort,
|
|
74
|
+
};
|
|
75
|
+
const exportFields = {
|
|
76
|
+
output_format: s.stringEnum("Download file format; upstream default is jsonl.", ["jsonl", "csv"]),
|
|
77
|
+
notify_email: s.string("Optional email address for job completion notification. Omit to retrieve the download URL by polling.", { format: "email" }),
|
|
78
|
+
};
|
|
79
|
+
const recordCount = s.object("Matching and returned record counts.", {
|
|
80
|
+
total: s.integer("Total matching records."),
|
|
81
|
+
returned: s.integer("Records returned in this response."),
|
|
82
|
+
}, { additionalProperties: true, required: [] });
|
|
83
|
+
const analytics = s.looseObject("Panjiva metrics, refinements, time_series or rollup results, keyed by requested fields.", {});
|
|
84
|
+
const record = s.looseObject("Native record with all data-source-specific fields preserved.", {});
|
|
85
|
+
const company = s.looseObject("Native company entity, trade statistics and requested aggregations.", {});
|
|
86
|
+
const companiesOutput = s.object("Company results separated by trade role.", {
|
|
87
|
+
consignees: s.array("Matching buyers or consignees.", company),
|
|
88
|
+
shippers: s.array("Matching suppliers or shippers.", company),
|
|
89
|
+
}, { additionalProperties: true, required: [] });
|
|
90
|
+
const analyticsOutput = s.object("Matching record counts and requested analytics.", { record_count: recordCount, analytics }, { additionalProperties: true, required: [] });
|
|
91
|
+
const jobId = s.string("Job ID returned by the corresponding submission action.", {
|
|
92
|
+
format: "uuid",
|
|
93
|
+
});
|
|
94
|
+
const jobOutput = s.looseObject("Submitted asynchronous job.", {
|
|
95
|
+
job_id: jobId,
|
|
96
|
+
status: s.string("Upstream job status, initially submitted."),
|
|
97
|
+
});
|
|
98
|
+
const statusOutput = s.object("Asynchronous job status and download location.", {
|
|
99
|
+
id: jobId,
|
|
100
|
+
status: s.string("Upstream state: submitted, in_process, fetched, uploaded, notification_sent, or error."),
|
|
101
|
+
download_url: s.string("Download URL when ready; pass this URL to a file consumer."),
|
|
102
|
+
last_changed: s.string("Time of the latest state change.", { format: "date-time" }),
|
|
103
|
+
parameters: s.looseObject("Original job parameters.", {}),
|
|
104
|
+
}, { additionalProperties: true, required: ["status"] });
|
|
105
|
+
const partialHs = s.string("Optional two- or four-digit HS code prefix that restricts classification results.", {
|
|
106
|
+
pattern: "^(?:[0-9]{2}|[0-9]{4})$",
|
|
107
|
+
});
|
|
108
|
+
const commodityDescription = s.string("Product description to classify into HS codes.");
|
|
109
|
+
const hsCodeList = s.array("HS codes returned by this classification method.", s.string("HS code."));
|
|
110
|
+
const lifecycle = (startAction, statusAction) => ({
|
|
111
|
+
startActionId: `panjiva.${startAction}`,
|
|
112
|
+
statusActionId: `panjiva.${statusAction}`,
|
|
113
|
+
});
|
|
114
|
+
export const panjivaActionSpecs = [
|
|
115
|
+
{
|
|
116
|
+
name: "search_shipments",
|
|
117
|
+
path: "/shipments/search",
|
|
118
|
+
method: "POST",
|
|
119
|
+
description: "Search Panjiva import and export shipment records with filtering, sorting, pagination and optional metrics. Use bulk_search_shipments for larger result sets.",
|
|
120
|
+
inputSchema: s.object("Shipment search criteria.", {
|
|
121
|
+
data_source: dataSource,
|
|
122
|
+
...selection,
|
|
123
|
+
offset: s.integer("Record offset.", { minimum: 0, maximum: 4500 }),
|
|
124
|
+
size: s.integer("Maximum records to return.", { minimum: 0, maximum: 500 }),
|
|
125
|
+
metrics,
|
|
126
|
+
sort: shipmentSort,
|
|
127
|
+
}, { required: ["data_source"] }),
|
|
128
|
+
outputSchema: s.object("Shipment search results.", {
|
|
129
|
+
record_count: recordCount,
|
|
130
|
+
records: s.array("Matching shipment records.", record),
|
|
131
|
+
analytics,
|
|
132
|
+
}, { additionalProperties: true, required: [] }),
|
|
133
|
+
},
|
|
134
|
+
{
|
|
135
|
+
name: "get_shipment_refinements",
|
|
136
|
+
path: "/shipments/refinements",
|
|
137
|
+
method: "POST",
|
|
138
|
+
description: "List the most common values of selected shipment attributes for matching Panjiva records.",
|
|
139
|
+
inputSchema: s.object("Shipment refinement criteria.", {
|
|
140
|
+
data_source: dataSource,
|
|
141
|
+
...selection,
|
|
142
|
+
fields: s.array("Attributes whose top values should be returned; discover available refinements with get_data_source_metadata.", s.string("Shipment attribute name.")),
|
|
143
|
+
}, { required: ["data_source", "fields"] }),
|
|
144
|
+
outputSchema: analyticsOutput,
|
|
145
|
+
},
|
|
146
|
+
{
|
|
147
|
+
name: "get_shipment_time_series",
|
|
148
|
+
path: "/shipments/time-series",
|
|
149
|
+
method: "POST",
|
|
150
|
+
description: "Calculate shipment metrics aggregated by week, month, quarter or year.",
|
|
151
|
+
inputSchema: s.object("Shipment time-series criteria.", { data_source: dataSource, ...selection, metrics, ...timeSeriesFields }, { required: ["data_source", "metrics", "interval"] }),
|
|
152
|
+
outputSchema: analyticsOutput,
|
|
153
|
+
},
|
|
154
|
+
{
|
|
155
|
+
name: "rollup_shipments",
|
|
156
|
+
path: "/shipments/rollup",
|
|
157
|
+
method: "POST",
|
|
158
|
+
description: "Group matching shipments into up to three dimensions with metrics and optional time-series aggregation.",
|
|
159
|
+
inputSchema: s.object("Shipment rollup criteria.", {
|
|
160
|
+
data_source: dataSource,
|
|
161
|
+
...selection,
|
|
162
|
+
metrics,
|
|
163
|
+
dimensions,
|
|
164
|
+
time_series: s.object("Time-series aggregation within the rollup.", timeSeriesFields, {
|
|
165
|
+
required: ["interval"],
|
|
166
|
+
}),
|
|
167
|
+
}, { required: ["data_source", "dimensions"] }),
|
|
168
|
+
outputSchema: analyticsOutput,
|
|
169
|
+
},
|
|
170
|
+
{
|
|
171
|
+
name: "search_companies",
|
|
172
|
+
path: "/companies/search",
|
|
173
|
+
method: "POST",
|
|
174
|
+
description: "Find buyers and suppliers through matching Panjiva trade records, with company identity types and trade-role filtering.",
|
|
175
|
+
inputSchema: s.object("Company search criteria.", companySearchFields, { required: [] }),
|
|
176
|
+
outputSchema: companiesOutput,
|
|
177
|
+
},
|
|
178
|
+
{
|
|
179
|
+
name: "lookup_companies",
|
|
180
|
+
path: "/companies/lookup",
|
|
181
|
+
method: "POST",
|
|
182
|
+
description: "Retrieve Panjiva company entities by company IDs and identifier representation.",
|
|
183
|
+
inputSchema: s.object("Company lookup identifiers.", {
|
|
184
|
+
company_ids: s.array("Company IDs to retrieve.", s.integer("Company ID."), { minItems: 1 }),
|
|
185
|
+
company_type: companyType,
|
|
186
|
+
}, { required: ["company_ids"] }),
|
|
187
|
+
outputSchema: s.object("Company lookup results.", { companies: s.array("Requested company entities.", company) }, { additionalProperties: true, required: [] }),
|
|
188
|
+
},
|
|
189
|
+
{
|
|
190
|
+
name: "rollup_companies",
|
|
191
|
+
path: "/companies/rollup",
|
|
192
|
+
method: "POST",
|
|
193
|
+
description: "Aggregate trade records for selected companies into up to three grouping dimensions.",
|
|
194
|
+
inputSchema: s.object("Company rollup criteria.", {
|
|
195
|
+
...companyFields,
|
|
196
|
+
company_ids: s.array("Company IDs to analyze.", s.integer("Company ID.")),
|
|
197
|
+
dimensions,
|
|
198
|
+
}, { required: ["dimensions"] }),
|
|
199
|
+
outputSchema: companiesOutput,
|
|
200
|
+
},
|
|
201
|
+
{
|
|
202
|
+
name: "get_company_network",
|
|
203
|
+
path: "/companies/network",
|
|
204
|
+
method: "POST",
|
|
205
|
+
description: "Retrieve a company's top buyers, suppliers and trade statistics from Panjiva.",
|
|
206
|
+
inputSchema: s.object("Company network criteria.", {
|
|
207
|
+
...companySearchFields,
|
|
208
|
+
company_id: s.integer("Company ID whose trade network should be retrieved."),
|
|
209
|
+
}, { required: ["company_id"] }),
|
|
210
|
+
outputSchema: s.object("Company trade network.", {
|
|
211
|
+
network: s.record("Trade network keyed by company ID.", s.looseObject("Company network with top_consignees, top_shippers and stats.", {})),
|
|
212
|
+
}),
|
|
213
|
+
},
|
|
214
|
+
{
|
|
215
|
+
name: "search_hs_codes",
|
|
216
|
+
path: "/hs-codes/search",
|
|
217
|
+
method: "POST",
|
|
218
|
+
description: "Search Harmonized System codes and US Harmonized Tariff Schedule descriptions.",
|
|
219
|
+
inputSchema: s.object("HS code search criteria.", {
|
|
220
|
+
query: s.object("HS code text query.", {
|
|
221
|
+
text: s.string("Text to search in HS code descriptions."),
|
|
222
|
+
}),
|
|
223
|
+
queries: s.array("Additional HS code text queries.", s.object("HS code text query.", {
|
|
224
|
+
text: s.string("Text to search in HS code descriptions."),
|
|
225
|
+
})),
|
|
226
|
+
filters: s.looseObject("HS code level and section constraints, supporting AND, OR and NOT. Levels are 2, 4, 6, 8 or 10.", {}),
|
|
227
|
+
offset: s.integer("Record offset.", { minimum: 0, maximum: 4500 }),
|
|
228
|
+
size: s.integer("Maximum records to return.", { minimum: 0, maximum: 500 }),
|
|
229
|
+
}, { required: ["query"] }),
|
|
230
|
+
outputSchema: s.object("HS code search results.", {
|
|
231
|
+
record_count: recordCount,
|
|
232
|
+
results: s.array("Matching HS codes.", s.looseObject("HS code and its hierarchy.", {
|
|
233
|
+
commodity: s.string("HS code."),
|
|
234
|
+
description: s.string("Commodity description."),
|
|
235
|
+
level: s.string("HS code digit level."),
|
|
236
|
+
parent: s.string("Parent HS code."),
|
|
237
|
+
section: s.string("HS system section."),
|
|
238
|
+
})),
|
|
239
|
+
analytics,
|
|
240
|
+
}, { additionalProperties: true, required: [] }),
|
|
241
|
+
},
|
|
242
|
+
{
|
|
243
|
+
name: "parse_hs_codes",
|
|
244
|
+
path: "/hs-codes/parse",
|
|
245
|
+
method: "POST",
|
|
246
|
+
description: "Identify HS codes from a product description using the Panjiva commodity coder. Optionally restrict the HS prefix and enable parser, manual rules or classifier methods; the first matching method supplies the results.",
|
|
247
|
+
inputSchema: s.object("Commodity coding request.", {
|
|
248
|
+
description: commodityDescription,
|
|
249
|
+
partial_hs: partialHs,
|
|
250
|
+
use_parser: s.boolean("Whether to extract HS codes already present in the description."),
|
|
251
|
+
use_manual_logic: s.boolean("Whether to match predefined classification rules."),
|
|
252
|
+
use_classifier: s.boolean("Whether to use the machine-learning HS classifier."),
|
|
253
|
+
}, { required: ["description"] }),
|
|
254
|
+
outputSchema: s.looseObject("Commodity coding results.", {
|
|
255
|
+
result_count: s.number("Number of classification results reported by Panjiva."),
|
|
256
|
+
results: s.array("HS code classification candidates.", s.looseObject("One HS code prediction.", {
|
|
257
|
+
predCode: s.string("Predicted HS code."),
|
|
258
|
+
description: s.string("Description associated with the predicted code."),
|
|
259
|
+
confidence: s.number("Confidence value reported by Panjiva."),
|
|
260
|
+
source: s.string("Classification method that produced the prediction."),
|
|
261
|
+
})),
|
|
262
|
+
}),
|
|
263
|
+
},
|
|
264
|
+
{
|
|
265
|
+
name: "parse_many_hs_codes",
|
|
266
|
+
path: "/hs-codes/parse-many",
|
|
267
|
+
method: "POST",
|
|
268
|
+
description: "Call Panjiva's Parse Many commodity coder and return per-item HS codes and classifier metadata. The published request schema defines items as an object with description, optional marks and partial_hs; pass that documented object shape.",
|
|
269
|
+
inputSchema: s.object("Parse Many commodity coding request.", {
|
|
270
|
+
items: s.object("Commodity item object as defined by the official Parse Many request schema.", {
|
|
271
|
+
description: commodityDescription,
|
|
272
|
+
marks: s.string("Shipment marks text accompanying the product description."),
|
|
273
|
+
partial_hs: partialHs,
|
|
274
|
+
}, { required: ["description"] }),
|
|
275
|
+
}),
|
|
276
|
+
outputSchema: s.looseObject("Parse Many classification results and model metadata.", {
|
|
277
|
+
classifier_training_date: s.string("Classifier training date reported by Panjiva."),
|
|
278
|
+
classifier_version: s.string("Classifier model version."),
|
|
279
|
+
items: s.array("Per-item commodity classification results.", s.looseObject("Classification results for one commodity item.", {
|
|
280
|
+
parsed_hs_codes: hsCodeList,
|
|
281
|
+
piers_override: hsCodeList,
|
|
282
|
+
panjiva_override: hsCodeList,
|
|
283
|
+
classifier_codes: s.array("HS codes predicted by the classifier.", s.looseObject("One classifier prediction.", {
|
|
284
|
+
hs_code: s.string("Predicted HS code."),
|
|
285
|
+
confidence: s.number("Confidence value reported by Panjiva."),
|
|
286
|
+
})),
|
|
287
|
+
})),
|
|
288
|
+
}),
|
|
289
|
+
},
|
|
290
|
+
{
|
|
291
|
+
name: "list_data_sources",
|
|
292
|
+
path: "/metadata/data-sources",
|
|
293
|
+
method: "GET",
|
|
294
|
+
description: "List the Panjiva data sources available to the connected organization.",
|
|
295
|
+
inputSchema: s.object("No input is required.", {}),
|
|
296
|
+
outputSchema: s.object("Available data sources.", {
|
|
297
|
+
data_sources: s.array("Available data-source identifiers.", s.string("Data-source identifier.")),
|
|
298
|
+
}, { additionalProperties: true, required: [] }),
|
|
299
|
+
},
|
|
300
|
+
{
|
|
301
|
+
name: "get_data_source_metadata",
|
|
302
|
+
path: "/metadata/data-source/{data_source}",
|
|
303
|
+
method: "GET",
|
|
304
|
+
description: "Discover searchable fields, filters, sort keys, metrics, dimensions and refinements for a Panjiva data source.",
|
|
305
|
+
inputSchema: s.object("Data source to inspect.", { data_source: dataSource }),
|
|
306
|
+
outputSchema: s.object("Data-source query capabilities.", {
|
|
307
|
+
query: s.looseObject("Query groups and defaults.", {}),
|
|
308
|
+
filters: s.array("Filter fields and their types.", record),
|
|
309
|
+
sort: s.looseObject("Valid sort keys and defaults.", {}),
|
|
310
|
+
metrics: s.array("Available metrics and supported operations.", record),
|
|
311
|
+
dimensions: s.array("Available dimension fields.", s.string("Dimension field.")),
|
|
312
|
+
refinements: s.array("Available refinement fields.", s.string("Refinement field.")),
|
|
313
|
+
}, { additionalProperties: true, required: [] }),
|
|
314
|
+
},
|
|
315
|
+
{
|
|
316
|
+
name: "get_data_source_schema",
|
|
317
|
+
path: "/metadata/data-source/{data_source}/schema",
|
|
318
|
+
method: "GET",
|
|
319
|
+
description: "Retrieve native shipment record schemas for a Panjiva data source.",
|
|
320
|
+
inputSchema: s.object("Data source to inspect.", { data_source: dataSource }),
|
|
321
|
+
outputSchema: s.object("Data-source shipment schemas.", {
|
|
322
|
+
schemas: s.record("Schemas keyed by country and trade direction.", record),
|
|
323
|
+
}),
|
|
324
|
+
},
|
|
325
|
+
{
|
|
326
|
+
name: "bulk_search_shipments",
|
|
327
|
+
path: "/bulk/shipments/search",
|
|
328
|
+
method: "POST",
|
|
329
|
+
description: "Submit a large shipment search for JSONL or CSV download. Poll get_bulk_job_status with the returned job ID.",
|
|
330
|
+
inputSchema: s.object("Bulk shipment search criteria.", { ...exportFields, data_source: dataSource, ...selection, sort: shipmentSort }, { required: ["data_source"] }),
|
|
331
|
+
outputSchema: jobOutput,
|
|
332
|
+
asyncLifecycle: lifecycle("bulk_search_shipments", "get_bulk_job_status"),
|
|
333
|
+
},
|
|
334
|
+
{
|
|
335
|
+
name: "bulk_rollup_shipments",
|
|
336
|
+
path: "/bulk/shipments/rollup",
|
|
337
|
+
method: "POST",
|
|
338
|
+
description: "Submit a bulk shipment aggregation for JSONL or CSV download. Poll get_bulk_job_status with the returned job ID.",
|
|
339
|
+
inputSchema: s.object("Bulk shipment rollup criteria.", {
|
|
340
|
+
...exportFields,
|
|
341
|
+
data_source: dataSource,
|
|
342
|
+
...selection,
|
|
343
|
+
metrics,
|
|
344
|
+
dimensions: bulkDimensions,
|
|
345
|
+
}, { required: ["data_source", "dimensions"] }),
|
|
346
|
+
outputSchema: jobOutput,
|
|
347
|
+
asyncLifecycle: lifecycle("bulk_rollup_shipments", "get_bulk_job_status"),
|
|
348
|
+
},
|
|
349
|
+
{
|
|
350
|
+
name: "batch_search_companies",
|
|
351
|
+
path: "/batch/companies/search",
|
|
352
|
+
method: "POST",
|
|
353
|
+
description: "Submit multiple company searches as one downloadable batch. Poll get_batch_job_status with the returned job ID.",
|
|
354
|
+
inputSchema: s.object("Batch company searches.", {
|
|
355
|
+
...exportFields,
|
|
356
|
+
requests: s.array("Individual company search requests.", s.object("Company search criteria.", companySearchFields, { required: [] }), { minItems: 1, maxItems: 50000 }),
|
|
357
|
+
}, { required: ["requests"] }),
|
|
358
|
+
outputSchema: jobOutput,
|
|
359
|
+
asyncLifecycle: lifecycle("batch_search_companies", "get_batch_job_status"),
|
|
360
|
+
},
|
|
361
|
+
{
|
|
362
|
+
name: "get_bulk_job_status",
|
|
363
|
+
path: "/bulk/status/{job_id}",
|
|
364
|
+
method: "GET",
|
|
365
|
+
description: "Check a bulk shipment job and retrieve its download URL when ready.",
|
|
366
|
+
inputSchema: s.object("Bulk job to inspect.", { job_id: jobId }),
|
|
367
|
+
outputSchema: statusOutput,
|
|
368
|
+
asyncLifecycle: lifecycle("bulk_search_shipments", "get_bulk_job_status"),
|
|
369
|
+
},
|
|
370
|
+
{
|
|
371
|
+
name: "get_batch_job_status",
|
|
372
|
+
path: "/batch/status/{job_id}",
|
|
373
|
+
method: "GET",
|
|
374
|
+
description: "Check a batch company search job and retrieve its download URL when ready.",
|
|
375
|
+
inputSchema: s.object("Batch job to inspect.", { job_id: jobId }),
|
|
376
|
+
outputSchema: statusOutput,
|
|
377
|
+
asyncLifecycle: lifecycle("batch_search_companies", "get_batch_job_status"),
|
|
378
|
+
},
|
|
379
|
+
];
|
|
380
|
+
export const panjivaActions = panjivaActionSpecs.map((spec) => defineProviderAction(service, {
|
|
381
|
+
name: spec.name,
|
|
382
|
+
description: spec.description,
|
|
383
|
+
operationType: ["bulk_search_shipments", "bulk_rollup_shipments", "batch_search_companies"].includes(spec.name)
|
|
384
|
+
? "write"
|
|
385
|
+
: "read",
|
|
386
|
+
inputSchema: spec.inputSchema,
|
|
387
|
+
outputSchema: spec.outputSchema,
|
|
388
|
+
asyncLifecycle: spec.asyncLifecycle,
|
|
389
|
+
}));
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { CredentialValidators, ProviderExecutors, ProviderProxyExecutor } from "../../core/types.ts";
|
|
2
|
+
export declare const executors: ProviderExecutors;
|
|
3
|
+
export declare const proxy: ProviderProxyExecutor;
|
|
4
|
+
export declare const credentialValidators: CredentialValidators;
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { optionalNumber, optionalRecord, optionalString, requiredRecord, requiredString } from "../../core/cast.js";
|
|
3
|
+
import { defineProviderExecutors, defineProviderProxy, mapProviderActionHandlers, providerInputError, providerResponseError, ProviderRequestError, readProviderJsonBody, requireCustomCredential, } from "../provider-runtime.js";
|
|
4
|
+
import { panjivaActionSpecs } from "./actions.js";
|
|
5
|
+
const service = "panjiva", baseUrl = "https://api.panjiva.com/latest";
|
|
6
|
+
const cache = new Map();
|
|
7
|
+
const handlers = mapProviderActionHandlers(service, panjivaActionSpecs, (spec) => {
|
|
8
|
+
return async (input, context) => {
|
|
9
|
+
validateDimensions(input.dimensions);
|
|
10
|
+
let path = spec.path;
|
|
11
|
+
if (path.includes("{data_source}"))
|
|
12
|
+
path = path.replace("{data_source}", segment(input.data_source, "data_source"));
|
|
13
|
+
if (path.includes("{job_id}"))
|
|
14
|
+
path = path.replace("{job_id}", segment(input.job_id, "job_id"));
|
|
15
|
+
const payload = await request(path, spec.method, spec.method === "POST" ? input : undefined, await token(context), context);
|
|
16
|
+
if (spec.name === "get_company_network")
|
|
17
|
+
return { network: payload };
|
|
18
|
+
if (spec.name === "get_data_source_schema")
|
|
19
|
+
return { schemas: payload };
|
|
20
|
+
return payload;
|
|
21
|
+
};
|
|
22
|
+
});
|
|
23
|
+
export const executors = defineProviderExecutors({
|
|
24
|
+
service,
|
|
25
|
+
handlers,
|
|
26
|
+
skipDnsValidation: true,
|
|
27
|
+
async createContext(context, fetcher) {
|
|
28
|
+
const credential = await requireCustomCredential(context, service);
|
|
29
|
+
return {
|
|
30
|
+
clientId: requiredString(credential.values.clientId, "clientId"),
|
|
31
|
+
clientSecret: requiredString(credential.values.clientSecret, "clientSecret"),
|
|
32
|
+
fetcher,
|
|
33
|
+
signal: context.signal,
|
|
34
|
+
};
|
|
35
|
+
},
|
|
36
|
+
});
|
|
37
|
+
export const proxy = defineProviderProxy({
|
|
38
|
+
service,
|
|
39
|
+
baseUrl,
|
|
40
|
+
skipDnsValidation: true,
|
|
41
|
+
auth: {
|
|
42
|
+
type: "bearer_resolver",
|
|
43
|
+
async resolve({ context, fetcher, signal }) {
|
|
44
|
+
const credential = await requireCustomCredential(context, service);
|
|
45
|
+
return {
|
|
46
|
+
accessToken: await token({
|
|
47
|
+
clientId: requiredString(credential.values.clientId, "clientId"),
|
|
48
|
+
clientSecret: requiredString(credential.values.clientSecret, "clientSecret"),
|
|
49
|
+
fetcher,
|
|
50
|
+
signal,
|
|
51
|
+
}),
|
|
52
|
+
tokenType: "Bearer",
|
|
53
|
+
};
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
customizeRequest({ headers }) {
|
|
57
|
+
if (!headers.has("accept"))
|
|
58
|
+
headers.set("accept", "application/json");
|
|
59
|
+
},
|
|
60
|
+
});
|
|
61
|
+
export const credentialValidators = {
|
|
62
|
+
async customCredential(input, { fetcher, signal }) {
|
|
63
|
+
const context = {
|
|
64
|
+
clientId: requiredString(input.values.clientId, "clientId"),
|
|
65
|
+
clientSecret: requiredString(input.values.clientSecret, "clientSecret"),
|
|
66
|
+
fetcher,
|
|
67
|
+
signal,
|
|
68
|
+
};
|
|
69
|
+
await token(context);
|
|
70
|
+
const hash = createHash("sha256").update(context.clientId).digest("hex");
|
|
71
|
+
return {
|
|
72
|
+
profile: { accountId: `panjiva:${hash}`, displayName: "Panjiva Account" },
|
|
73
|
+
grantedScopes: [],
|
|
74
|
+
metadata: {},
|
|
75
|
+
};
|
|
76
|
+
},
|
|
77
|
+
};
|
|
78
|
+
async function token(context) {
|
|
79
|
+
const key = createHash("sha256").update(`${context.clientId}\0${context.clientSecret}`).digest("hex");
|
|
80
|
+
const hit = cache.get(key);
|
|
81
|
+
if (hit && hit.expiresAt - Date.now() > 60_000)
|
|
82
|
+
return hit.token;
|
|
83
|
+
const payload = requiredRecord(await request("/auth/token", "POST", { grant_type: "client_credentials", client_id: context.clientId, client_secret: context.clientSecret }, undefined, context), "Panjiva token response");
|
|
84
|
+
const value = requiredString(payload.token, "Panjiva token");
|
|
85
|
+
const expiresAt = Date.parse(requiredString(payload.expires_at, "Panjiva expires_at"));
|
|
86
|
+
if (!Number.isFinite(expiresAt) || expiresAt <= Date.now())
|
|
87
|
+
throw providerResponseError("Panjiva returned an invalid token expiration");
|
|
88
|
+
cache.set(key, { token: value, expiresAt });
|
|
89
|
+
return value;
|
|
90
|
+
}
|
|
91
|
+
async function request(path, method, body, accessToken, context) {
|
|
92
|
+
const headers = new Headers({ accept: "application/json" });
|
|
93
|
+
if (accessToken)
|
|
94
|
+
headers.set("authorization", `Bearer ${accessToken}`);
|
|
95
|
+
if (body)
|
|
96
|
+
headers.set("content-type", "application/json");
|
|
97
|
+
const response = await context.fetcher(`${baseUrl}${path}`, {
|
|
98
|
+
method,
|
|
99
|
+
headers,
|
|
100
|
+
body: body ? JSON.stringify(body) : undefined,
|
|
101
|
+
signal: context.signal,
|
|
102
|
+
});
|
|
103
|
+
let payload;
|
|
104
|
+
try {
|
|
105
|
+
payload = await readProviderJsonBody(response, {
|
|
106
|
+
emptyBody: undefined,
|
|
107
|
+
invalidJsonMessage: "Panjiva returned invalid JSON",
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
catch {
|
|
111
|
+
payload = undefined;
|
|
112
|
+
}
|
|
113
|
+
if (!response.ok) {
|
|
114
|
+
const record = optionalRecord(payload);
|
|
115
|
+
throw new ProviderRequestError(response.status, optionalString(record?.error) ??
|
|
116
|
+
optionalString(record?.message) ??
|
|
117
|
+
`Panjiva request failed with status ${response.status}`, payload);
|
|
118
|
+
}
|
|
119
|
+
return requiredRecord(payload, "Panjiva response");
|
|
120
|
+
}
|
|
121
|
+
function segment(value, field) {
|
|
122
|
+
const text = requiredString(value, field);
|
|
123
|
+
if (text === "." || text === ".." || text.includes("/") || text.includes("\\"))
|
|
124
|
+
throw providerInputError(`Invalid Panjiva ${field}`);
|
|
125
|
+
return encodeURIComponent(text);
|
|
126
|
+
}
|
|
127
|
+
function validateDimensions(value) {
|
|
128
|
+
if (!Array.isArray(value))
|
|
129
|
+
return;
|
|
130
|
+
for (const [index, item] of value.entries()) {
|
|
131
|
+
const d = optionalRecord(item);
|
|
132
|
+
const offset = optionalNumber(d?.offset) ?? 0, size = optionalNumber(d?.size) ?? 10;
|
|
133
|
+
if ((index > 0 && offset > 0) || offset + size > 1000)
|
|
134
|
+
throw providerInputError("Panjiva only permits offset on the first dimension, and offset plus size must not exceed 1000");
|
|
135
|
+
}
|
|
136
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { CredentialValidators, ProviderExecutors, ProviderProxyExecutor } from "../../core/types.ts";
|
|
2
|
+
export declare const executors: ProviderExecutors;
|
|
3
|
+
export declare const proxy: ProviderProxyExecutor;
|
|
4
|
+
export declare const credentialValidators: CredentialValidators;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { defineApiKeyProviderExecutors, defineProviderProxy } from "../provider-runtime.js";
|
|
2
|
+
import { papertrailActionHandlers, validatePapertrailCredential } from "./runtime.js";
|
|
3
|
+
const service = "papertrail";
|
|
4
|
+
export const executors = defineApiKeyProviderExecutors(service, papertrailActionHandlers);
|
|
5
|
+
export const proxy = defineProviderProxy({
|
|
6
|
+
service,
|
|
7
|
+
baseUrl: "https://papertrailapp.com/api/v1/",
|
|
8
|
+
auth: { type: "api_key_header", name: "x-papertrail-token" },
|
|
9
|
+
skipDnsValidation: true,
|
|
10
|
+
});
|
|
11
|
+
export const credentialValidators = {
|
|
12
|
+
apiKey(input, { fetcher, signal }) {
|
|
13
|
+
return validatePapertrailCredential(input.apiKey, fetcher, signal);
|
|
14
|
+
},
|
|
15
|
+
};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { CredentialValidationResult } from "../../core/types.ts";
|
|
2
|
+
import type { ApiKeyProviderContext, ProviderActionHandlers, ProviderFetch } from "../provider-runtime.ts";
|
|
3
|
+
export declare const papertrailApiBaseUrl = "https://papertrailapp.com/api/v1/";
|
|
4
|
+
type PapertrailHandler = (input: Record<string, unknown>, context: ApiKeyProviderContext) => Promise<unknown>;
|
|
5
|
+
export declare const papertrailActionHandlers: ProviderActionHandlers<"papertrail", PapertrailHandler>;
|
|
6
|
+
export declare function validatePapertrailCredential(apiKey: string, fetcher: ProviderFetch, signal?: AbortSignal): Promise<CredentialValidationResult>;
|
|
7
|
+
export {};
|