@squadbase/vite-server 0.1.2 → 0.1.3-dev.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/index.js +13609 -3797
- package/dist/connectors/airtable-oauth.js +12 -4
- package/dist/connectors/amplitude.js +335 -32
- package/dist/connectors/asana.d.ts +5 -0
- package/dist/connectors/asana.js +661 -0
- package/dist/connectors/attio.js +304 -36
- package/dist/connectors/customerio.d.ts +5 -0
- package/dist/connectors/customerio.js +633 -0
- package/dist/connectors/gmail-oauth.d.ts +5 -0
- package/dist/connectors/gmail-oauth.js +639 -0
- package/dist/connectors/google-ads-oauth.js +14 -8
- package/dist/connectors/google-ads.d.ts +5 -0
- package/dist/connectors/google-ads.js +784 -0
- package/dist/connectors/google-analytics-oauth.js +16 -8
- package/dist/connectors/google-sheets-oauth.js +12 -4
- package/dist/connectors/google-sheets.d.ts +5 -0
- package/dist/connectors/google-sheets.js +598 -0
- package/dist/connectors/hubspot-oauth.js +12 -4
- package/dist/connectors/hubspot.d.ts +5 -0
- package/dist/connectors/hubspot.js +550 -0
- package/dist/connectors/intercom-oauth.d.ts +5 -0
- package/dist/connectors/intercom-oauth.js +510 -0
- package/dist/connectors/intercom.d.ts +5 -0
- package/dist/connectors/intercom.js +627 -0
- package/dist/connectors/jira-api-key.d.ts +5 -0
- package/dist/connectors/jira-api-key.js +523 -0
- package/dist/connectors/kintone-api-token.js +16 -20
- package/dist/connectors/linkedin-ads-oauth.d.ts +5 -0
- package/dist/connectors/linkedin-ads-oauth.js +774 -0
- package/dist/connectors/linkedin-ads.d.ts +5 -0
- package/dist/connectors/linkedin-ads.js +782 -0
- package/dist/connectors/mailchimp-oauth.d.ts +5 -0
- package/dist/connectors/mailchimp-oauth.js +539 -0
- package/dist/connectors/mailchimp.d.ts +5 -0
- package/dist/connectors/mailchimp.js +646 -0
- package/dist/connectors/shopify-oauth.js +12 -4
- package/dist/connectors/shopify.js +500 -80
- package/dist/connectors/stripe-oauth.js +12 -4
- package/dist/connectors/zendesk-oauth.d.ts +5 -0
- package/dist/connectors/zendesk-oauth.js +505 -0
- package/dist/connectors/zendesk.d.ts +5 -0
- package/dist/connectors/zendesk.js +631 -0
- package/dist/index.js +13594 -3782
- package/dist/main.js +13596 -3784
- package/dist/vite-plugin.js +13596 -3784
- package/package.json +46 -2
|
@@ -44,43 +44,284 @@ var ParameterDefinition = class {
|
|
|
44
44
|
|
|
45
45
|
// ../connectors/src/connectors/shopify/parameters.ts
|
|
46
46
|
var parameters = {
|
|
47
|
-
accessToken: new ParameterDefinition({
|
|
48
|
-
slug: "access-token",
|
|
49
|
-
name: "Shopify Admin API Access Token",
|
|
50
|
-
description: "The Shopify Admin API access token for authentication (starts with shpat_).",
|
|
51
|
-
envVarBaseKey: "SHOPIFY_ACCESS_TOKEN",
|
|
52
|
-
type: "text",
|
|
53
|
-
secret: true,
|
|
54
|
-
required: true
|
|
55
|
-
}),
|
|
56
47
|
storeDomain: new ParameterDefinition({
|
|
57
48
|
slug: "store-domain",
|
|
58
|
-
name: "
|
|
59
|
-
description:
|
|
49
|
+
name: "Shop Name",
|
|
50
|
+
description: 'Your Shopify store name (the subdomain part of your .myshopify.com URL, e.g., "mystore" for mystore.myshopify.com).',
|
|
60
51
|
envVarBaseKey: "SHOPIFY_STORE_DOMAIN",
|
|
61
52
|
type: "text",
|
|
62
53
|
secret: false,
|
|
63
54
|
required: true
|
|
55
|
+
}),
|
|
56
|
+
clientId: new ParameterDefinition({
|
|
57
|
+
slug: "client-id",
|
|
58
|
+
name: "Client ID",
|
|
59
|
+
description: "The Client ID (API Key) of your Shopify Custom App.",
|
|
60
|
+
envVarBaseKey: "SHOPIFY_CLIENT_ID",
|
|
61
|
+
type: "text",
|
|
62
|
+
secret: false,
|
|
63
|
+
required: true
|
|
64
|
+
}),
|
|
65
|
+
clientSecret: new ParameterDefinition({
|
|
66
|
+
slug: "client-secret",
|
|
67
|
+
name: "Client Secret",
|
|
68
|
+
description: "The Client Secret (API Secret Key) of your Shopify Custom App.",
|
|
69
|
+
envVarBaseKey: "SHOPIFY_CLIENT_SECRET",
|
|
70
|
+
type: "text",
|
|
71
|
+
secret: true,
|
|
72
|
+
required: true
|
|
64
73
|
})
|
|
65
74
|
};
|
|
66
75
|
|
|
67
76
|
// ../connectors/src/connectors/shopify/sdk/index.ts
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
const
|
|
71
|
-
|
|
77
|
+
var API_VERSION = "2024-10";
|
|
78
|
+
async function fetchAccessToken(storeDomain, clientId, clientSecret) {
|
|
79
|
+
const res = await fetch(
|
|
80
|
+
`https://${storeDomain}/admin/oauth/access_token`,
|
|
81
|
+
{
|
|
82
|
+
method: "POST",
|
|
83
|
+
headers: { "Content-Type": "application/json" },
|
|
84
|
+
body: JSON.stringify({
|
|
85
|
+
client_id: clientId,
|
|
86
|
+
client_secret: clientSecret
|
|
87
|
+
})
|
|
88
|
+
}
|
|
89
|
+
);
|
|
90
|
+
if (!res.ok) {
|
|
91
|
+
const body = await res.text().catch(() => "(unreadable body)");
|
|
72
92
|
throw new Error(
|
|
73
|
-
`shopify:
|
|
93
|
+
`shopify: failed to obtain access token: ${res.status} ${res.statusText} \u2014 ${body}`
|
|
74
94
|
);
|
|
75
95
|
}
|
|
96
|
+
const json = await res.json();
|
|
97
|
+
if (!json.access_token) {
|
|
98
|
+
throw new Error("shopify: access_token not found in token response");
|
|
99
|
+
}
|
|
100
|
+
return json.access_token;
|
|
101
|
+
}
|
|
102
|
+
function createClient(params) {
|
|
103
|
+
const storeDomain = params[parameters.storeDomain.slug];
|
|
104
|
+
const clientId = params[parameters.clientId.slug];
|
|
105
|
+
const clientSecret = params[parameters.clientSecret.slug];
|
|
76
106
|
if (!storeDomain) {
|
|
77
107
|
throw new Error(
|
|
78
108
|
`shopify: missing required parameter: ${parameters.storeDomain.slug}`
|
|
79
109
|
);
|
|
80
110
|
}
|
|
81
|
-
|
|
111
|
+
if (!clientId) {
|
|
112
|
+
throw new Error(
|
|
113
|
+
`shopify: missing required parameter: ${parameters.clientId.slug}`
|
|
114
|
+
);
|
|
115
|
+
}
|
|
116
|
+
if (!clientSecret) {
|
|
117
|
+
throw new Error(
|
|
118
|
+
`shopify: missing required parameter: ${parameters.clientSecret.slug}`
|
|
119
|
+
);
|
|
120
|
+
}
|
|
121
|
+
const baseUrl = `https://${storeDomain}`;
|
|
122
|
+
async function getToken() {
|
|
123
|
+
return fetchAccessToken(storeDomain, clientId, clientSecret);
|
|
124
|
+
}
|
|
125
|
+
async function authHeaders(extra) {
|
|
126
|
+
const token = await getToken();
|
|
127
|
+
const headers = new Headers(extra);
|
|
128
|
+
headers.set("X-Shopify-Access-Token", token);
|
|
129
|
+
headers.set("Content-Type", "application/json");
|
|
130
|
+
return headers;
|
|
131
|
+
}
|
|
132
|
+
async function assertOk(res, label) {
|
|
133
|
+
if (!res.ok) {
|
|
134
|
+
const body = await res.text().catch(() => "(unreadable body)");
|
|
135
|
+
throw new Error(
|
|
136
|
+
`shopify ${label}: ${res.status} ${res.statusText} \u2014 ${body}`
|
|
137
|
+
);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
function buildQuery(params2) {
|
|
141
|
+
if (!params2) return "";
|
|
142
|
+
const entries = Object.entries(params2).filter(
|
|
143
|
+
([, v]) => v !== void 0 && v !== ""
|
|
144
|
+
);
|
|
145
|
+
if (entries.length === 0) return "";
|
|
146
|
+
const sp = new URLSearchParams();
|
|
147
|
+
for (const [k, v] of entries) sp.set(k, String(v));
|
|
148
|
+
return `?${sp.toString()}`;
|
|
149
|
+
}
|
|
150
|
+
return {
|
|
151
|
+
async request(path2, init) {
|
|
152
|
+
const url = `${baseUrl}${path2}`;
|
|
153
|
+
const token = await getToken();
|
|
154
|
+
const headers = new Headers(init?.headers);
|
|
155
|
+
headers.set("X-Shopify-Access-Token", token);
|
|
156
|
+
headers.set("Content-Type", "application/json");
|
|
157
|
+
return fetch(url, { ...init, headers });
|
|
158
|
+
},
|
|
159
|
+
async listProducts(options) {
|
|
160
|
+
const qs = buildQuery({
|
|
161
|
+
limit: options?.limit,
|
|
162
|
+
page_info: options?.pageInfo,
|
|
163
|
+
fields: options?.fields,
|
|
164
|
+
status: options?.status,
|
|
165
|
+
created_at_min: options?.createdAtMin,
|
|
166
|
+
created_at_max: options?.createdAtMax,
|
|
167
|
+
updated_at_min: options?.updatedAtMin,
|
|
168
|
+
updated_at_max: options?.updatedAtMax
|
|
169
|
+
});
|
|
170
|
+
const res = await fetch(
|
|
171
|
+
`${baseUrl}/admin/api/${API_VERSION}/products.json${qs}`,
|
|
172
|
+
{ method: "GET", headers: await authHeaders() }
|
|
173
|
+
);
|
|
174
|
+
await assertOk(res, "listProducts");
|
|
175
|
+
const json = await res.json();
|
|
176
|
+
return {
|
|
177
|
+
products: json.products ?? []
|
|
178
|
+
};
|
|
179
|
+
},
|
|
180
|
+
async getProduct(productId) {
|
|
181
|
+
const res = await fetch(
|
|
182
|
+
`${baseUrl}/admin/api/${API_VERSION}/products/${encodeURIComponent(String(productId))}.json`,
|
|
183
|
+
{ method: "GET", headers: await authHeaders() }
|
|
184
|
+
);
|
|
185
|
+
await assertOk(res, "getProduct");
|
|
186
|
+
const json = await res.json();
|
|
187
|
+
return { product: json.product };
|
|
188
|
+
},
|
|
189
|
+
async listOrders(options) {
|
|
190
|
+
const qs = buildQuery({
|
|
191
|
+
limit: options?.limit,
|
|
192
|
+
page_info: options?.pageInfo,
|
|
193
|
+
fields: options?.fields,
|
|
194
|
+
status: options?.status,
|
|
195
|
+
financial_status: options?.financialStatus,
|
|
196
|
+
fulfillment_status: options?.fulfillmentStatus,
|
|
197
|
+
created_at_min: options?.createdAtMin,
|
|
198
|
+
created_at_max: options?.createdAtMax,
|
|
199
|
+
updated_at_min: options?.updatedAtMin,
|
|
200
|
+
updated_at_max: options?.updatedAtMax
|
|
201
|
+
});
|
|
202
|
+
const res = await fetch(
|
|
203
|
+
`${baseUrl}/admin/api/${API_VERSION}/orders.json${qs}`,
|
|
204
|
+
{ method: "GET", headers: await authHeaders() }
|
|
205
|
+
);
|
|
206
|
+
await assertOk(res, "listOrders");
|
|
207
|
+
const json = await res.json();
|
|
208
|
+
return {
|
|
209
|
+
orders: json.orders ?? []
|
|
210
|
+
};
|
|
211
|
+
},
|
|
212
|
+
async getOrder(orderId) {
|
|
213
|
+
const res = await fetch(
|
|
214
|
+
`${baseUrl}/admin/api/${API_VERSION}/orders/${encodeURIComponent(String(orderId))}.json`,
|
|
215
|
+
{ method: "GET", headers: await authHeaders() }
|
|
216
|
+
);
|
|
217
|
+
await assertOk(res, "getOrder");
|
|
218
|
+
const json = await res.json();
|
|
219
|
+
return { order: json.order };
|
|
220
|
+
},
|
|
221
|
+
async listCustomers(options) {
|
|
222
|
+
const qs = buildQuery({
|
|
223
|
+
limit: options?.limit,
|
|
224
|
+
page_info: options?.pageInfo,
|
|
225
|
+
fields: options?.fields,
|
|
226
|
+
created_at_min: options?.createdAtMin,
|
|
227
|
+
created_at_max: options?.createdAtMax,
|
|
228
|
+
updated_at_min: options?.updatedAtMin,
|
|
229
|
+
updated_at_max: options?.updatedAtMax
|
|
230
|
+
});
|
|
231
|
+
const res = await fetch(
|
|
232
|
+
`${baseUrl}/admin/api/${API_VERSION}/customers.json${qs}`,
|
|
233
|
+
{ method: "GET", headers: await authHeaders() }
|
|
234
|
+
);
|
|
235
|
+
await assertOk(res, "listCustomers");
|
|
236
|
+
const json = await res.json();
|
|
237
|
+
return {
|
|
238
|
+
customers: json.customers ?? []
|
|
239
|
+
};
|
|
240
|
+
},
|
|
241
|
+
async getCustomer(customerId) {
|
|
242
|
+
const res = await fetch(
|
|
243
|
+
`${baseUrl}/admin/api/${API_VERSION}/customers/${encodeURIComponent(String(customerId))}.json`,
|
|
244
|
+
{ method: "GET", headers: await authHeaders() }
|
|
245
|
+
);
|
|
246
|
+
await assertOk(res, "getCustomer");
|
|
247
|
+
const json = await res.json();
|
|
248
|
+
return { customer: json.customer };
|
|
249
|
+
},
|
|
250
|
+
async listCustomCollections(options) {
|
|
251
|
+
const qs = buildQuery({
|
|
252
|
+
limit: options?.limit,
|
|
253
|
+
page_info: options?.pageInfo
|
|
254
|
+
});
|
|
255
|
+
const res = await fetch(
|
|
256
|
+
`${baseUrl}/admin/api/${API_VERSION}/custom_collections.json${qs}`,
|
|
257
|
+
{ method: "GET", headers: await authHeaders() }
|
|
258
|
+
);
|
|
259
|
+
await assertOk(res, "listCustomCollections");
|
|
260
|
+
const json = await res.json();
|
|
261
|
+
return {
|
|
262
|
+
custom_collections: json.custom_collections ?? []
|
|
263
|
+
};
|
|
264
|
+
},
|
|
265
|
+
async listSmartCollections(options) {
|
|
266
|
+
const qs = buildQuery({
|
|
267
|
+
limit: options?.limit,
|
|
268
|
+
page_info: options?.pageInfo
|
|
269
|
+
});
|
|
270
|
+
const res = await fetch(
|
|
271
|
+
`${baseUrl}/admin/api/${API_VERSION}/smart_collections.json${qs}`,
|
|
272
|
+
{ method: "GET", headers: await authHeaders() }
|
|
273
|
+
);
|
|
274
|
+
await assertOk(res, "listSmartCollections");
|
|
275
|
+
const json = await res.json();
|
|
276
|
+
return {
|
|
277
|
+
smart_collections: json.smart_collections ?? []
|
|
278
|
+
};
|
|
279
|
+
}
|
|
280
|
+
};
|
|
82
281
|
}
|
|
83
282
|
|
|
283
|
+
// ../connectors/src/connector-onboarding.ts
|
|
284
|
+
var ConnectorOnboarding = class {
|
|
285
|
+
/** Phase 1: Connection setup instructions (optional — some connectors don't need this) */
|
|
286
|
+
connectionSetupInstructions;
|
|
287
|
+
/** Phase 2: Data overview instructions */
|
|
288
|
+
dataOverviewInstructions;
|
|
289
|
+
constructor(config) {
|
|
290
|
+
this.connectionSetupInstructions = config.connectionSetupInstructions;
|
|
291
|
+
this.dataOverviewInstructions = config.dataOverviewInstructions;
|
|
292
|
+
}
|
|
293
|
+
getConnectionSetupPrompt(language) {
|
|
294
|
+
return this.connectionSetupInstructions?.[language] ?? null;
|
|
295
|
+
}
|
|
296
|
+
getDataOverviewInstructions(language) {
|
|
297
|
+
return this.dataOverviewInstructions[language];
|
|
298
|
+
}
|
|
299
|
+
};
|
|
300
|
+
|
|
301
|
+
// ../connectors/src/connector-tool.ts
|
|
302
|
+
var ConnectorTool = class {
|
|
303
|
+
name;
|
|
304
|
+
description;
|
|
305
|
+
inputSchema;
|
|
306
|
+
outputSchema;
|
|
307
|
+
_execute;
|
|
308
|
+
constructor(config) {
|
|
309
|
+
this.name = config.name;
|
|
310
|
+
this.description = config.description;
|
|
311
|
+
this.inputSchema = config.inputSchema;
|
|
312
|
+
this.outputSchema = config.outputSchema;
|
|
313
|
+
this._execute = config.execute;
|
|
314
|
+
}
|
|
315
|
+
createTool(connections, config) {
|
|
316
|
+
return {
|
|
317
|
+
description: this.description,
|
|
318
|
+
inputSchema: this.inputSchema,
|
|
319
|
+
outputSchema: this.outputSchema,
|
|
320
|
+
execute: (input) => this._execute(input, connections, config)
|
|
321
|
+
};
|
|
322
|
+
}
|
|
323
|
+
};
|
|
324
|
+
|
|
84
325
|
// ../connectors/src/connector-plugin.ts
|
|
85
326
|
var ConnectorPlugin = class _ConnectorPlugin {
|
|
86
327
|
slug;
|
|
@@ -139,8 +380,124 @@ var ConnectorPlugin = class _ConnectorPlugin {
|
|
|
139
380
|
}
|
|
140
381
|
};
|
|
141
382
|
|
|
383
|
+
// ../connectors/src/connectors/shopify/setup.ts
|
|
384
|
+
var shopifyOnboarding = new ConnectorOnboarding({
|
|
385
|
+
dataOverviewInstructions: {
|
|
386
|
+
en: `1. Call shopify_request with GET /admin/api/2024-10/products.json?limit=5 to explore products structure
|
|
387
|
+
2. Call shopify_request with GET /admin/api/2024-10/orders.json?limit=5&status=any to explore orders structure
|
|
388
|
+
3. Explore other endpoints (customers, inventory, collections) as needed`,
|
|
389
|
+
ja: `1. shopify_request \u3067 GET /admin/api/2024-10/products.json?limit=5 \u3092\u547C\u3073\u51FA\u3057\u3001\u5546\u54C1\u306E\u69CB\u9020\u3092\u78BA\u8A8D
|
|
390
|
+
2. shopify_request \u3067 GET /admin/api/2024-10/orders.json?limit=5&status=any \u3092\u547C\u3073\u51FA\u3057\u3001\u6CE8\u6587\u306E\u69CB\u9020\u3092\u78BA\u8A8D
|
|
391
|
+
3. \u5FC5\u8981\u306B\u5FDC\u3058\u3066\u4ED6\u306E\u30A8\u30F3\u30C9\u30DD\u30A4\u30F3\u30C8\uFF08\u9867\u5BA2\u3001\u5728\u5EAB\u3001\u30B3\u30EC\u30AF\u30B7\u30E7\u30F3\uFF09\u3092\u63A2\u7D22`
|
|
392
|
+
}
|
|
393
|
+
});
|
|
394
|
+
|
|
395
|
+
// ../connectors/src/connectors/shopify/tools/request.ts
|
|
396
|
+
import { z } from "zod";
|
|
397
|
+
var REQUEST_TIMEOUT_MS = 6e4;
|
|
398
|
+
var inputSchema = z.object({
|
|
399
|
+
toolUseIntent: z.string().optional().describe(
|
|
400
|
+
"Brief description of what you intend to accomplish with this tool call"
|
|
401
|
+
),
|
|
402
|
+
connectionId: z.string().describe("ID of the Shopify connection to use"),
|
|
403
|
+
method: z.enum(["GET", "POST", "PUT", "DELETE"]).describe(
|
|
404
|
+
"HTTP method. GET for reading resources (products, orders, customers), POST for creating, PUT for updating, DELETE for removing."
|
|
405
|
+
),
|
|
406
|
+
path: z.string().describe(
|
|
407
|
+
"API path including version (e.g., '/admin/api/2024-10/products.json', '/admin/api/2024-10/orders.json?limit=50')"
|
|
408
|
+
),
|
|
409
|
+
body: z.record(z.string(), z.unknown()).optional().describe("Request body (JSON) for POST/PUT requests")
|
|
410
|
+
});
|
|
411
|
+
var outputSchema = z.discriminatedUnion("success", [
|
|
412
|
+
z.object({
|
|
413
|
+
success: z.literal(true),
|
|
414
|
+
status: z.number(),
|
|
415
|
+
data: z.record(z.string(), z.unknown())
|
|
416
|
+
}),
|
|
417
|
+
z.object({
|
|
418
|
+
success: z.literal(false),
|
|
419
|
+
error: z.string()
|
|
420
|
+
})
|
|
421
|
+
]);
|
|
422
|
+
var requestTool = new ConnectorTool({
|
|
423
|
+
name: "request",
|
|
424
|
+
description: `Send authenticated requests to the Shopify Admin REST API.
|
|
425
|
+
Authentication is handled automatically using Custom App credentials (Client ID + Client Secret). An access token is obtained on each request.
|
|
426
|
+
The store domain is resolved from the connection \u2014 only provide the path starting with /admin/api/.
|
|
427
|
+
Use this tool for all Shopify API interactions: listing products, orders, customers, inventory, collections, and more.`,
|
|
428
|
+
inputSchema,
|
|
429
|
+
outputSchema,
|
|
430
|
+
async execute({ connectionId, method, path: path2, body }, connections) {
|
|
431
|
+
const connection2 = connections.find((c) => c.id === connectionId);
|
|
432
|
+
if (!connection2) {
|
|
433
|
+
return {
|
|
434
|
+
success: false,
|
|
435
|
+
error: `Connection ${connectionId} not found`
|
|
436
|
+
};
|
|
437
|
+
}
|
|
438
|
+
console.log(
|
|
439
|
+
`[connector-request] shopify/${connection2.name}: ${method} ${path2}`
|
|
440
|
+
);
|
|
441
|
+
try {
|
|
442
|
+
const storeDomain = parameters.storeDomain.getValue(connection2);
|
|
443
|
+
const clientId = parameters.clientId.getValue(connection2);
|
|
444
|
+
const clientSecret = parameters.clientSecret.getValue(connection2);
|
|
445
|
+
const tokenRes = await fetch(
|
|
446
|
+
`https://${storeDomain}/admin/oauth/access_token`,
|
|
447
|
+
{
|
|
448
|
+
method: "POST",
|
|
449
|
+
headers: { "Content-Type": "application/json" },
|
|
450
|
+
body: JSON.stringify({
|
|
451
|
+
client_id: clientId,
|
|
452
|
+
client_secret: clientSecret
|
|
453
|
+
})
|
|
454
|
+
}
|
|
455
|
+
);
|
|
456
|
+
if (!tokenRes.ok) {
|
|
457
|
+
const tokenBody = await tokenRes.text().catch(() => "(unreadable body)");
|
|
458
|
+
return {
|
|
459
|
+
success: false,
|
|
460
|
+
error: `Failed to obtain access token: ${tokenRes.status} ${tokenRes.statusText} \u2014 ${tokenBody}`
|
|
461
|
+
};
|
|
462
|
+
}
|
|
463
|
+
const tokenJson = await tokenRes.json();
|
|
464
|
+
if (!tokenJson.access_token) {
|
|
465
|
+
return {
|
|
466
|
+
success: false,
|
|
467
|
+
error: "access_token not found in token response"
|
|
468
|
+
};
|
|
469
|
+
}
|
|
470
|
+
const url = `https://${storeDomain}${path2}`;
|
|
471
|
+
const controller = new AbortController();
|
|
472
|
+
const timeout = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS);
|
|
473
|
+
try {
|
|
474
|
+
const response = await fetch(url, {
|
|
475
|
+
method,
|
|
476
|
+
headers: {
|
|
477
|
+
"X-Shopify-Access-Token": tokenJson.access_token,
|
|
478
|
+
"Content-Type": "application/json"
|
|
479
|
+
},
|
|
480
|
+
body: body ? JSON.stringify(body) : void 0,
|
|
481
|
+
signal: controller.signal
|
|
482
|
+
});
|
|
483
|
+
const data = await response.json();
|
|
484
|
+
if (!response.ok) {
|
|
485
|
+
const errorMessage = typeof data?.errors === "string" ? data.errors : typeof data?.error === "string" ? data.error : `HTTP ${response.status} ${response.statusText}`;
|
|
486
|
+
return { success: false, error: errorMessage };
|
|
487
|
+
}
|
|
488
|
+
return { success: true, status: response.status, data };
|
|
489
|
+
} finally {
|
|
490
|
+
clearTimeout(timeout);
|
|
491
|
+
}
|
|
492
|
+
} catch (err) {
|
|
493
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
494
|
+
return { success: false, error: msg };
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
});
|
|
498
|
+
|
|
142
499
|
// ../connectors/src/connectors/shopify/index.ts
|
|
143
|
-
var tools = {};
|
|
500
|
+
var tools = { request: requestTool };
|
|
144
501
|
var shopifyConnector = new ConnectorPlugin({
|
|
145
502
|
slug: "shopify",
|
|
146
503
|
authType: null,
|
|
@@ -149,89 +506,152 @@ var shopifyConnector = new ConnectorPlugin({
|
|
|
149
506
|
iconUrl: "https://images.ctfassets.net/9ncizv60xc5y/57KEjZCBskKgSxgKyU4Sm0/117d681a410f48dc36f97cdd9c0593c5/shopify-icon.svg",
|
|
150
507
|
parameters,
|
|
151
508
|
releaseFlag: { dev1: true, dev2: false, prod: false },
|
|
509
|
+
onboarding: shopifyOnboarding,
|
|
152
510
|
systemPrompt: {
|
|
153
|
-
en: `###
|
|
154
|
-
|
|
511
|
+
en: `### Tools
|
|
512
|
+
|
|
513
|
+
- \`shopify_request\`: The only way to call the Shopify Admin REST API. Use it to query products, orders, customers, inventory, collections, and more. Authentication (Custom App Client ID + Client Secret) is configured automatically \u2014 an access token is obtained on each request. Only provide the path starting with \`/admin/api/\`. Shopify uses cursor-based pagination via the \`page_info\` query parameter (obtained from the Link header in the response).
|
|
514
|
+
|
|
515
|
+
### Business Logic
|
|
516
|
+
|
|
517
|
+
The business logic type for this connector is "typescript". Use the connector SDK in your handler. Do NOT read credentials from environment variables.
|
|
518
|
+
|
|
519
|
+
SDK methods (client created via \`connection(connectionId)\`):
|
|
520
|
+
- \`client.request(path, init?)\` \u2014 low-level authenticated fetch
|
|
521
|
+
- \`client.listProducts(options?)\` \u2014 list products with filters (status, date range) and pagination
|
|
522
|
+
- \`client.getProduct(productId)\` \u2014 fetch a single product
|
|
523
|
+
- \`client.listOrders(options?)\` \u2014 list orders with filters (status, financial_status, fulfillment_status, date range)
|
|
524
|
+
- \`client.getOrder(orderId)\` \u2014 fetch a single order
|
|
525
|
+
- \`client.listCustomers(options?)\` \u2014 list customers with filters and pagination
|
|
526
|
+
- \`client.getCustomer(customerId)\` \u2014 fetch a single customer
|
|
527
|
+
- \`client.listCustomCollections(options?)\` \u2014 list custom collections
|
|
528
|
+
- \`client.listSmartCollections(options?)\` \u2014 list smart collections
|
|
155
529
|
|
|
156
530
|
\`\`\`ts
|
|
531
|
+
import type { Context } from "hono";
|
|
157
532
|
import { connection } from "@squadbase/vite-server/connectors/shopify";
|
|
158
533
|
|
|
159
|
-
const
|
|
534
|
+
const shopify = connection("<connectionId>");
|
|
160
535
|
|
|
161
|
-
|
|
162
|
-
const
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
)
|
|
171
|
-
|
|
536
|
+
export default async function handler(c: Context) {
|
|
537
|
+
const { status = "active", limit = 50 } = await c.req.json<{
|
|
538
|
+
status?: "active" | "draft" | "archived";
|
|
539
|
+
limit?: number;
|
|
540
|
+
}>();
|
|
541
|
+
|
|
542
|
+
const { products } = await shopify.listProducts({ status, limit });
|
|
543
|
+
|
|
544
|
+
return c.json({
|
|
545
|
+
products: products.map((p: Record<string, unknown>) => ({
|
|
546
|
+
id: p.id,
|
|
547
|
+
title: p.title,
|
|
548
|
+
status: p.status,
|
|
549
|
+
vendor: p.vendor,
|
|
550
|
+
created_at: p.created_at,
|
|
551
|
+
})),
|
|
552
|
+
});
|
|
553
|
+
}
|
|
172
554
|
\`\`\`
|
|
173
555
|
|
|
174
|
-
###
|
|
175
|
-
|
|
176
|
-
-
|
|
177
|
-
-
|
|
178
|
-
-
|
|
179
|
-
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
- GET \`/
|
|
183
|
-
- GET \`/
|
|
184
|
-
- GET \`/
|
|
185
|
-
- GET \`/
|
|
186
|
-
|
|
187
|
-
|
|
556
|
+
### Shopify Admin REST API Reference
|
|
557
|
+
|
|
558
|
+
- Base URL: \`https://{storeDomain}/admin/api/2024-10\`
|
|
559
|
+
- Authentication: Custom App (Client ID + Client Secret \u2192 access token obtained per request)
|
|
560
|
+
- Pagination: cursor-based via \`page_info\` query parameter (from Link header)
|
|
561
|
+
- Max 250 records per page
|
|
562
|
+
|
|
563
|
+
#### Common Endpoints
|
|
564
|
+
- GET \`/admin/api/2024-10/products.json\` \u2014 List products
|
|
565
|
+
- GET \`/admin/api/2024-10/products/{id}.json\` \u2014 Get a product
|
|
566
|
+
- GET \`/admin/api/2024-10/orders.json\` \u2014 List orders
|
|
567
|
+
- GET \`/admin/api/2024-10/orders/{id}.json\` \u2014 Get an order
|
|
568
|
+
- GET \`/admin/api/2024-10/customers.json\` \u2014 List customers
|
|
569
|
+
- GET \`/admin/api/2024-10/customers/{id}.json\` \u2014 Get a customer
|
|
570
|
+
- GET \`/admin/api/2024-10/inventory_items.json?ids={ids}\` \u2014 List inventory items
|
|
571
|
+
- GET \`/admin/api/2024-10/locations.json\` \u2014 List locations
|
|
572
|
+
- GET \`/admin/api/2024-10/collects.json\` \u2014 List collects
|
|
573
|
+
- GET \`/admin/api/2024-10/custom_collections.json\` \u2014 List custom collections
|
|
574
|
+
- GET \`/admin/api/2024-10/smart_collections.json\` \u2014 List smart collections
|
|
575
|
+
|
|
576
|
+
#### Common Query Parameters
|
|
188
577
|
- \`limit\` \u2014 Max records per page (max 250)
|
|
189
578
|
- \`page_info\` \u2014 Cursor for pagination (from Link header)
|
|
190
579
|
- \`fields\` \u2014 Comma-separated list of fields to return
|
|
191
|
-
- \`created_at_min\`, \`created_at_max\` \u2014 Date filters
|
|
192
|
-
- \`updated_at_min\`, \`updated_at_max\` \u2014 Date filters
|
|
193
|
-
- \`status\` \u2014 Filter by status (e.g., active, draft, archived for products)`,
|
|
194
|
-
ja: `###
|
|
195
|
-
|
|
580
|
+
- \`created_at_min\`, \`created_at_max\` \u2014 Date filters (ISO 8601)
|
|
581
|
+
- \`updated_at_min\`, \`updated_at_max\` \u2014 Date filters (ISO 8601)
|
|
582
|
+
- \`status\` \u2014 Filter by status (e.g., active, draft, archived for products; open, closed, cancelled, any for orders)`,
|
|
583
|
+
ja: `### \u30C4\u30FC\u30EB
|
|
584
|
+
|
|
585
|
+
- \`shopify_request\`: Shopify Admin REST API\u3092\u547C\u3073\u51FA\u3059\u552F\u4E00\u306E\u624B\u6BB5\u3067\u3059\u3002\u5546\u54C1\u3001\u6CE8\u6587\u3001\u9867\u5BA2\u3001\u5728\u5EAB\u3001\u30B3\u30EC\u30AF\u30B7\u30E7\u30F3\u306A\u3069\u306E\u30AF\u30A8\u30EA\u306B\u4F7F\u7528\u3057\u307E\u3059\u3002\u8A8D\u8A3C\uFF08\u30AB\u30B9\u30BF\u30E0\u30A2\u30D7\u30EA\u306E Client ID + Client Secret\uFF09\u306F\u81EA\u52D5\u7684\u306B\u8A2D\u5B9A\u3055\u308C\u3001\u30EA\u30AF\u30A8\u30B9\u30C8\u3054\u3068\u306B\u30A2\u30AF\u30BB\u30B9\u30C8\u30FC\u30AF\u30F3\u3092\u53D6\u5F97\u3057\u307E\u3059\u3002\`/admin/api/\` \u304B\u3089\u59CB\u307E\u308B\u30D1\u30B9\u306E\u307F\u3092\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044\u3002Shopify\u306F\u30EC\u30B9\u30DD\u30F3\u30B9\u306E Link \u30D8\u30C3\u30C0\u30FC\u304B\u3089\u53D6\u5F97\u3059\u308B \`page_info\` \u30AF\u30A8\u30EA\u30D1\u30E9\u30E1\u30FC\u30BF\u306B\u3088\u308B\u30AB\u30FC\u30BD\u30EB\u30D9\u30FC\u30B9\u306E\u30DA\u30FC\u30B8\u30CD\u30FC\u30B7\u30E7\u30F3\u3092\u4F7F\u7528\u3057\u307E\u3059\u3002
|
|
586
|
+
|
|
587
|
+
### Business Logic
|
|
588
|
+
|
|
589
|
+
\u3053\u306E\u30B3\u30CD\u30AF\u30BF\u306E\u30D3\u30B8\u30CD\u30B9\u30ED\u30B8\u30C3\u30AF\u30BF\u30A4\u30D7\u306F "typescript" \u3067\u3059\u3002\u30CF\u30F3\u30C9\u30E9\u5185\u3067\u306F\u30B3\u30CD\u30AF\u30BFSDK\u3092\u4F7F\u7528\u3057\u3066\u304F\u3060\u3055\u3044\u3002\u74B0\u5883\u5909\u6570\u304B\u3089\u8A8D\u8A3C\u60C5\u5831\u3092\u8AAD\u307F\u53D6\u3089\u306A\u3044\u3067\u304F\u3060\u3055\u3044\u3002
|
|
590
|
+
|
|
591
|
+
SDK\u30E1\u30BD\u30C3\u30C9 (\`connection(connectionId)\` \u3067\u4F5C\u6210\u3057\u305F\u30AF\u30E9\u30A4\u30A2\u30F3\u30C8):
|
|
592
|
+
- \`client.request(path, init?)\` \u2014 \u4F4E\u30EC\u30D9\u30EB\u306E\u8A8D\u8A3C\u4ED8\u304Dfetch
|
|
593
|
+
- \`client.listProducts(options?)\` \u2014 \u30D5\u30A3\u30EB\u30BF\uFF08\u30B9\u30C6\u30FC\u30BF\u30B9\u3001\u65E5\u4ED8\u7BC4\u56F2\uFF09\u3068\u30DA\u30FC\u30B8\u30CD\u30FC\u30B7\u30E7\u30F3\u4ED8\u304D\u3067\u5546\u54C1\u3092\u4E00\u89A7\u53D6\u5F97
|
|
594
|
+
- \`client.getProduct(productId)\` \u2014 \u5358\u4E00\u5546\u54C1\u3092\u53D6\u5F97
|
|
595
|
+
- \`client.listOrders(options?)\` \u2014 \u30D5\u30A3\u30EB\u30BF\uFF08\u30B9\u30C6\u30FC\u30BF\u30B9\u3001\u652F\u6255\u3044\u72B6\u6CC1\u3001\u914D\u9001\u72B6\u6CC1\u3001\u65E5\u4ED8\u7BC4\u56F2\uFF09\u4ED8\u304D\u3067\u6CE8\u6587\u3092\u4E00\u89A7\u53D6\u5F97
|
|
596
|
+
- \`client.getOrder(orderId)\` \u2014 \u5358\u4E00\u6CE8\u6587\u3092\u53D6\u5F97
|
|
597
|
+
- \`client.listCustomers(options?)\` \u2014 \u30D5\u30A3\u30EB\u30BF\u3068\u30DA\u30FC\u30B8\u30CD\u30FC\u30B7\u30E7\u30F3\u4ED8\u304D\u3067\u9867\u5BA2\u3092\u4E00\u89A7\u53D6\u5F97
|
|
598
|
+
- \`client.getCustomer(customerId)\` \u2014 \u5358\u4E00\u9867\u5BA2\u3092\u53D6\u5F97
|
|
599
|
+
- \`client.listCustomCollections(options?)\` \u2014 \u30AB\u30B9\u30BF\u30E0\u30B3\u30EC\u30AF\u30B7\u30E7\u30F3\u3092\u4E00\u89A7\u53D6\u5F97
|
|
600
|
+
- \`client.listSmartCollections(options?)\` \u2014 \u30B9\u30DE\u30FC\u30C8\u30B3\u30EC\u30AF\u30B7\u30E7\u30F3\u3092\u4E00\u89A7\u53D6\u5F97
|
|
196
601
|
|
|
197
602
|
\`\`\`ts
|
|
603
|
+
import type { Context } from "hono";
|
|
198
604
|
import { connection } from "@squadbase/vite-server/connectors/shopify";
|
|
199
605
|
|
|
200
|
-
const
|
|
606
|
+
const shopify = connection("<connectionId>");
|
|
201
607
|
|
|
202
|
-
|
|
203
|
-
const
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
)
|
|
212
|
-
|
|
608
|
+
export default async function handler(c: Context) {
|
|
609
|
+
const { status = "active", limit = 50 } = await c.req.json<{
|
|
610
|
+
status?: "active" | "draft" | "archived";
|
|
611
|
+
limit?: number;
|
|
612
|
+
}>();
|
|
613
|
+
|
|
614
|
+
const { products } = await shopify.listProducts({ status, limit });
|
|
615
|
+
|
|
616
|
+
return c.json({
|
|
617
|
+
products: products.map((p: Record<string, unknown>) => ({
|
|
618
|
+
id: p.id,
|
|
619
|
+
title: p.title,
|
|
620
|
+
status: p.status,
|
|
621
|
+
vendor: p.vendor,
|
|
622
|
+
created_at: p.created_at,
|
|
623
|
+
})),
|
|
624
|
+
});
|
|
625
|
+
}
|
|
213
626
|
\`\`\`
|
|
214
627
|
|
|
215
|
-
### \
|
|
216
|
-
|
|
217
|
-
-
|
|
218
|
-
-
|
|
219
|
-
-
|
|
220
|
-
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
- GET \`/
|
|
224
|
-
- GET \`/
|
|
225
|
-
- GET \`/
|
|
226
|
-
- GET \`/
|
|
227
|
-
|
|
228
|
-
|
|
628
|
+
### Shopify Admin REST API \u30EA\u30D5\u30A1\u30EC\u30F3\u30B9
|
|
629
|
+
|
|
630
|
+
- \u30D9\u30FC\u30B9URL: \`https://{storeDomain}/admin/api/2024-10\`
|
|
631
|
+
- \u8A8D\u8A3C: \u30AB\u30B9\u30BF\u30E0\u30A2\u30D7\u30EA\uFF08Client ID + Client Secret \u2192 \u30EA\u30AF\u30A8\u30B9\u30C8\u3054\u3068\u306B\u30A2\u30AF\u30BB\u30B9\u30C8\u30FC\u30AF\u30F3\u53D6\u5F97\uFF09
|
|
632
|
+
- \u30DA\u30FC\u30B8\u30CD\u30FC\u30B7\u30E7\u30F3: Link \u30D8\u30C3\u30C0\u30FC\u304B\u3089\u306E \`page_info\` \u306B\u3088\u308B\u30AB\u30FC\u30BD\u30EB\u30D9\u30FC\u30B9
|
|
633
|
+
- \u30DA\u30FC\u30B8\u3042\u305F\u308A\u6700\u5927250\u30EC\u30B3\u30FC\u30C9
|
|
634
|
+
|
|
635
|
+
#### \u4E3B\u8981\u30A8\u30F3\u30C9\u30DD\u30A4\u30F3\u30C8
|
|
636
|
+
- GET \`/admin/api/2024-10/products.json\` \u2014 \u5546\u54C1\u4E00\u89A7
|
|
637
|
+
- GET \`/admin/api/2024-10/products/{id}.json\` \u2014 \u5546\u54C1\u306E\u53D6\u5F97
|
|
638
|
+
- GET \`/admin/api/2024-10/orders.json\` \u2014 \u6CE8\u6587\u4E00\u89A7
|
|
639
|
+
- GET \`/admin/api/2024-10/orders/{id}.json\` \u2014 \u6CE8\u6587\u306E\u53D6\u5F97
|
|
640
|
+
- GET \`/admin/api/2024-10/customers.json\` \u2014 \u9867\u5BA2\u4E00\u89A7
|
|
641
|
+
- GET \`/admin/api/2024-10/customers/{id}.json\` \u2014 \u9867\u5BA2\u306E\u53D6\u5F97
|
|
642
|
+
- GET \`/admin/api/2024-10/inventory_items.json?ids={ids}\` \u2014 \u5728\u5EAB\u30A2\u30A4\u30C6\u30E0\u4E00\u89A7
|
|
643
|
+
- GET \`/admin/api/2024-10/locations.json\` \u2014 \u30ED\u30B1\u30FC\u30B7\u30E7\u30F3\u4E00\u89A7
|
|
644
|
+
- GET \`/admin/api/2024-10/collects.json\` \u2014 \u30B3\u30EC\u30AF\u30C8\u4E00\u89A7
|
|
645
|
+
- GET \`/admin/api/2024-10/custom_collections.json\` \u2014 \u30AB\u30B9\u30BF\u30E0\u30B3\u30EC\u30AF\u30B7\u30E7\u30F3\u4E00\u89A7
|
|
646
|
+
- GET \`/admin/api/2024-10/smart_collections.json\` \u2014 \u30B9\u30DE\u30FC\u30C8\u30B3\u30EC\u30AF\u30B7\u30E7\u30F3\u4E00\u89A7
|
|
647
|
+
|
|
648
|
+
#### \u4E3B\u8981\u30AF\u30A8\u30EA\u30D1\u30E9\u30E1\u30FC\u30BF
|
|
229
649
|
- \`limit\` \u2014 \u30DA\u30FC\u30B8\u3042\u305F\u308A\u306E\u6700\u5927\u30EC\u30B3\u30FC\u30C9\u6570\uFF08\u6700\u5927250\uFF09
|
|
230
650
|
- \`page_info\` \u2014 \u30DA\u30FC\u30B8\u30CD\u30FC\u30B7\u30E7\u30F3\u7528\u30AB\u30FC\u30BD\u30EB\uFF08Link\u30D8\u30C3\u30C0\u30FC\u304B\u3089\u53D6\u5F97\uFF09
|
|
231
651
|
- \`fields\` \u2014 \u8FD4\u5374\u3059\u308B\u30D5\u30A3\u30FC\u30EB\u30C9\u306E\u30AB\u30F3\u30DE\u533A\u5207\u308A\u30EA\u30B9\u30C8
|
|
232
|
-
- \`created_at_min\`, \`created_at_max\` \u2014 \u4F5C\u6210\u65E5\u30D5\u30A3\u30EB\u30BF\u30FC
|
|
233
|
-
- \`updated_at_min\`, \`updated_at_max\` \u2014 \u66F4\u65B0\u65E5\u30D5\u30A3\u30EB\u30BF\u30FC
|
|
234
|
-
- \`status\` \u2014 \u30B9\u30C6\u30FC\u30BF\u30B9\u3067\u30D5\u30A3\u30EB\u30BF\u30FC\uFF08\u4F8B: \u5546\u54C1\u306E\u5834\u5408 active, draft, archived\uFF09`
|
|
652
|
+
- \`created_at_min\`, \`created_at_max\` \u2014 \u4F5C\u6210\u65E5\u30D5\u30A3\u30EB\u30BF\u30FC\uFF08ISO 8601\uFF09
|
|
653
|
+
- \`updated_at_min\`, \`updated_at_max\` \u2014 \u66F4\u65B0\u65E5\u30D5\u30A3\u30EB\u30BF\u30FC\uFF08ISO 8601\uFF09
|
|
654
|
+
- \`status\` \u2014 \u30B9\u30C6\u30FC\u30BF\u30B9\u3067\u30D5\u30A3\u30EB\u30BF\u30FC\uFF08\u4F8B: \u5546\u54C1\u306E\u5834\u5408 active, draft, archived\u3001\u6CE8\u6587\u306E\u5834\u5408 open, closed, cancelled, any\uFF09`
|
|
235
655
|
},
|
|
236
656
|
tools
|
|
237
657
|
});
|