@squadbase/vite-server 0.1.2 → 0.1.3-dev.0

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.
@@ -365,9 +365,13 @@ var airtableOauthConnector = new ConnectorPlugin({
365
365
  ]
366
366
  },
367
367
  systemPrompt: {
368
- en: `### Airtable API (OAuth)
368
+ en: `### Tools
369
369
 
370
- ### Available Endpoints
370
+ - \`airtable-oauth_request\`: The only way to call the Airtable REST API. Use it to list tables, query/create/update/delete records. Authentication is configured automatically via OAuth. The {baseId} placeholder in paths is automatically replaced with the configured default base ID.
371
+
372
+ ### Airtable API Reference
373
+
374
+ #### Available Endpoints
371
375
  - GET \`/meta/bases/{baseId}/tables\` \u2014 List tables in a base
372
376
  - GET \`/{baseId}/{tableIdOrName}\` \u2014 List records in a table
373
377
  - GET \`/{baseId}/{tableIdOrName}/{recordId}\` \u2014 Get a single record
@@ -409,9 +413,13 @@ const data = await res.json();
409
413
  const records = await airtable.request("/{baseId}/Tasks?maxRecords=100");
410
414
  const recordsData = await records.json();
411
415
  \`\`\``,
412
- ja: `### Airtable API (OAuth)
416
+ ja: `### \u30C4\u30FC\u30EB
417
+
418
+ - \`airtable-oauth_request\`: Airtable REST API\u3092\u547C\u3073\u51FA\u3059\u552F\u4E00\u306E\u624B\u6BB5\u3067\u3059\u3002\u30C6\u30FC\u30D6\u30EB\u4E00\u89A7\u306E\u53D6\u5F97\u3001\u30EC\u30B3\u30FC\u30C9\u306E\u691C\u7D22\u30FB\u4F5C\u6210\u30FB\u66F4\u65B0\u30FB\u524A\u9664\u306B\u4F7F\u7528\u3057\u307E\u3059\u3002OAuth\u7D4C\u7531\u3067\u8A8D\u8A3C\u306F\u81EA\u52D5\u8A2D\u5B9A\u3055\u308C\u307E\u3059\u3002\u30D1\u30B9\u5185\u306E{baseId}\u30D7\u30EC\u30FC\u30B9\u30DB\u30EB\u30C0\u30FC\u306F\u8A2D\u5B9A\u6E08\u307F\u306E\u30C7\u30D5\u30A9\u30EB\u30C8\u30D9\u30FC\u30B9ID\u3067\u81EA\u52D5\u7684\u306B\u7F6E\u63DB\u3055\u308C\u307E\u3059\u3002
419
+
420
+ ### Airtable API \u30EA\u30D5\u30A1\u30EC\u30F3\u30B9
413
421
 
414
- ### \u5229\u7528\u53EF\u80FD\u306A\u30A8\u30F3\u30C9\u30DD\u30A4\u30F3\u30C8
422
+ #### \u5229\u7528\u53EF\u80FD\u306A\u30A8\u30F3\u30C9\u30DD\u30A4\u30F3\u30C8
415
423
  - GET \`/meta/bases/{baseId}/tables\` \u2014 \u30D9\u30FC\u30B9\u5185\u306E\u30C6\u30FC\u30D6\u30EB\u4E00\u89A7\u3092\u53D6\u5F97
416
424
  - GET \`/{baseId}/{tableIdOrName}\` \u2014 \u30C6\u30FC\u30D6\u30EB\u5185\u306E\u30EC\u30B3\u30FC\u30C9\u4E00\u89A7\u3092\u53D6\u5F97
417
425
  - GET \`/{baseId}/{tableIdOrName}/{recordId}\` \u2014 \u5358\u4E00\u30EC\u30B3\u30FC\u30C9\u3092\u53D6\u5F97
@@ -61,6 +61,15 @@ var parameters = {
61
61
  type: "text",
62
62
  secret: true,
63
63
  required: true
64
+ }),
65
+ region: new ParameterDefinition({
66
+ slug: "region",
67
+ name: "Region",
68
+ description: 'Amplitude data region. Set to "eu" if your Amplitude project is hosted in the EU. Leave empty for US (default).',
69
+ envVarBaseKey: "AMPLITUDE_REGION",
70
+ type: "text",
71
+ secret: false,
72
+ required: false
64
73
  })
65
74
  };
66
75
 
@@ -68,6 +77,7 @@ var parameters = {
68
77
  function createClient(params) {
69
78
  const apiKey = params[parameters.apiKey.slug];
70
79
  const secretKey = params[parameters.secretKey.slug];
80
+ const region = params[parameters.region.slug] ?? "us";
71
81
  if (!apiKey) {
72
82
  throw new Error(
73
83
  `amplitude: missing required parameter: ${parameters.apiKey.slug}`
@@ -78,9 +88,117 @@ function createClient(params) {
78
88
  `amplitude: missing required parameter: ${parameters.secretKey.slug}`
79
89
  );
80
90
  }
81
- return { apiKey, secretKey };
91
+ const baseUrl = region === "eu" ? "https://analytics.eu.amplitude.com" : "https://amplitude.com";
92
+ const authToken = btoa(`${apiKey}:${secretKey}`);
93
+ function authHeaders(extra) {
94
+ const headers = new Headers(extra);
95
+ headers.set("Authorization", `Basic ${authToken}`);
96
+ return headers;
97
+ }
98
+ async function assertOk(res, label) {
99
+ if (!res.ok) {
100
+ const body = await res.text().catch(() => "(unreadable body)");
101
+ throw new Error(
102
+ `amplitude ${label}: ${res.status} ${res.statusText} \u2014 ${body}`
103
+ );
104
+ }
105
+ }
106
+ return {
107
+ request(url, init) {
108
+ const headers = new Headers(init?.headers);
109
+ headers.set("Authorization", `Basic ${authToken}`);
110
+ return fetch(url, { ...init, headers });
111
+ },
112
+ async listEventTypes() {
113
+ const res = await fetch(
114
+ `${baseUrl}/api/2/events/list`,
115
+ { method: "GET", headers: authHeaders() }
116
+ );
117
+ await assertOk(res, "listEventTypes");
118
+ return await res.json();
119
+ },
120
+ async eventSegmentation(options) {
121
+ const params2 = new URLSearchParams();
122
+ params2.set("e", JSON.stringify(options.e));
123
+ params2.set("start", options.start);
124
+ params2.set("end", options.end);
125
+ if (options.m) params2.set("m", options.m);
126
+ if (options.i !== void 0) params2.set("i", String(options.i));
127
+ if (options.g) params2.set("g", options.g);
128
+ const res = await fetch(
129
+ `${baseUrl}/api/2/events/segmentation?${params2.toString()}`,
130
+ { method: "GET", headers: authHeaders() }
131
+ );
132
+ await assertOk(res, "eventSegmentation");
133
+ return await res.json();
134
+ },
135
+ async userSearch(query) {
136
+ const params2 = new URLSearchParams({ user: query });
137
+ const res = await fetch(
138
+ `${baseUrl}/api/2/usersearch?${params2.toString()}`,
139
+ { method: "GET", headers: authHeaders() }
140
+ );
141
+ await assertOk(res, "userSearch");
142
+ return await res.json();
143
+ },
144
+ async userActivity(amplitudeId, options) {
145
+ const params2 = new URLSearchParams({ user: amplitudeId });
146
+ if (options?.offset !== void 0)
147
+ params2.set("offset", String(options.offset));
148
+ if (options?.limit !== void 0)
149
+ params2.set("limit", String(options.limit));
150
+ const res = await fetch(
151
+ `${baseUrl}/api/2/useractivity?${params2.toString()}`,
152
+ { method: "GET", headers: authHeaders() }
153
+ );
154
+ await assertOk(res, "userActivity");
155
+ return await res.json();
156
+ }
157
+ };
82
158
  }
83
159
 
160
+ // ../connectors/src/connector-onboarding.ts
161
+ var ConnectorOnboarding = class {
162
+ /** Phase 1: Connection setup instructions (optional — some connectors don't need this) */
163
+ connectionSetupInstructions;
164
+ /** Phase 2: Data overview instructions */
165
+ dataOverviewInstructions;
166
+ constructor(config) {
167
+ this.connectionSetupInstructions = config.connectionSetupInstructions;
168
+ this.dataOverviewInstructions = config.dataOverviewInstructions;
169
+ }
170
+ getConnectionSetupPrompt(language) {
171
+ return this.connectionSetupInstructions?.[language] ?? null;
172
+ }
173
+ getDataOverviewInstructions(language) {
174
+ return this.dataOverviewInstructions[language];
175
+ }
176
+ };
177
+
178
+ // ../connectors/src/connector-tool.ts
179
+ var ConnectorTool = class {
180
+ name;
181
+ description;
182
+ inputSchema;
183
+ outputSchema;
184
+ _execute;
185
+ constructor(config) {
186
+ this.name = config.name;
187
+ this.description = config.description;
188
+ this.inputSchema = config.inputSchema;
189
+ this.outputSchema = config.outputSchema;
190
+ this._execute = config.execute;
191
+ }
192
+ createTool(connections, config) {
193
+ return {
194
+ description: this.description,
195
+ inputSchema: this.inputSchema,
196
+ outputSchema: this.outputSchema,
197
+ execute: (input) => this._execute(input, connections, config)
198
+ };
199
+ }
200
+ };
201
+
84
202
  // ../connectors/src/connector-plugin.ts
85
203
  var ConnectorPlugin = class _ConnectorPlugin {
86
204
  slug;
@@ -139,8 +257,110 @@ var ConnectorPlugin = class _ConnectorPlugin {
139
257
  }
140
258
  };
141
259
 
260
+ // ../connectors/src/connectors/amplitude/setup.ts
261
+ var amplitudeOnboarding = new ConnectorOnboarding({
262
+ dataOverviewInstructions: {
263
+ en: `1. Check the connection's region parameter: use https://analytics.eu.amplitude.com for EU, https://amplitude.com for US (default)
264
+ 2. Call amplitude_request with GET {baseUrl}/api/2/events/list to list available event types
265
+ 3. Call amplitude_request with GET {baseUrl}/api/2/export?start=YYYYMMDDTHH&end=YYYYMMDDTHH to export raw event data for a time range
266
+ 4. Use GET {baseUrl}/api/2/usersearch?user=QUERY and GET {baseUrl}/api/2/useractivity?user=AMPLITUDE_ID to explore user-level data
267
+ NOTE: The Dashboard REST API endpoints (events/segmentation, funnels, retention, etc.) require a paid Growth or Enterprise plan. If you get a 403 Forbidden error, fall back to the Export API (/api/2/export) to retrieve raw events and perform aggregation in code instead.`,
268
+ ja: `1. \u63A5\u7D9A\u306Eregion\u30D1\u30E9\u30E1\u30FC\u30BF\u3092\u78BA\u8A8D\uFF1AEU\u306E\u5834\u5408\u306F https://analytics.eu.amplitude.com\u3001US\uFF08\u30C7\u30D5\u30A9\u30EB\u30C8\uFF09\u306E\u5834\u5408\u306F https://amplitude.com \u3092\u4F7F\u7528
269
+ 2. amplitude_request \u3067 GET {baseUrl}/api/2/events/list \u3092\u547C\u3073\u51FA\u3057\u3001\u5229\u7528\u53EF\u80FD\u306A\u30A4\u30D9\u30F3\u30C8\u30BF\u30A4\u30D7\u4E00\u89A7\u3092\u53D6\u5F97
270
+ 3. amplitude_request \u3067 GET {baseUrl}/api/2/export?start=YYYYMMDDTHH&end=YYYYMMDDTHH \u3092\u547C\u3073\u51FA\u3057\u3001\u6307\u5B9A\u671F\u9593\u306E\u751F\u30A4\u30D9\u30F3\u30C8\u30C7\u30FC\u30BF\u3092\u30A8\u30AF\u30B9\u30DD\u30FC\u30C8
271
+ 4. GET {baseUrl}/api/2/usersearch?user=QUERY \u3084 GET {baseUrl}/api/2/useractivity?user=AMPLITUDE_ID \u3067\u30E6\u30FC\u30B6\u30FC\u30EC\u30D9\u30EB\u306E\u30C7\u30FC\u30BF\u3092\u63A2\u7D22
272
+ \u6CE8\u610F: Dashboard REST API\uFF08events/segmentation\u3001funnels\u3001retention\u7B49\uFF09\u306F\u6709\u6599\u306EGrowth\u307E\u305F\u306FEnterprise\u30D7\u30E9\u30F3\u304C\u5FC5\u8981\u3067\u3059\u3002403 Forbidden\u30A8\u30E9\u30FC\u304C\u8FD4\u3055\u308C\u305F\u5834\u5408\u306F\u3001Export API\uFF08/api/2/export\uFF09\u3067\u751F\u30A4\u30D9\u30F3\u30C8\u3092\u53D6\u5F97\u3057\u3001\u30B3\u30FC\u30C9\u4E0A\u3067\u96C6\u8A08\u3092\u884C\u3063\u3066\u304F\u3060\u3055\u3044\u3002`
273
+ }
274
+ });
275
+
276
+ // ../connectors/src/connectors/amplitude/tools/request.ts
277
+ import { z } from "zod";
278
+ var REQUEST_TIMEOUT_MS = 6e4;
279
+ var inputSchema = z.object({
280
+ toolUseIntent: z.string().optional().describe(
281
+ "Brief description of what you intend to accomplish with this tool call"
282
+ ),
283
+ connectionId: z.string().describe("ID of the Amplitude connection to use"),
284
+ method: z.enum(["GET", "POST"]).describe(
285
+ "HTTP method. GET for most read endpoints (events/list, export, usersearch, useractivity). POST is rarely needed."
286
+ ),
287
+ url: z.string().describe(
288
+ "Full URL including query parameters (e.g., 'https://amplitude.com/api/2/events/list', 'https://amplitude.com/api/2/export?start=20240101T00&end=20240102T00')"
289
+ ),
290
+ body: z.record(z.string(), z.unknown()).optional().describe("Request body (JSON) for POST requests")
291
+ });
292
+ var outputSchema = z.discriminatedUnion("success", [
293
+ z.object({
294
+ success: z.literal(true),
295
+ status: z.number(),
296
+ data: z.record(z.string(), z.unknown())
297
+ }),
298
+ z.object({
299
+ success: z.literal(false),
300
+ error: z.string()
301
+ })
302
+ ]);
303
+ var requestTool = new ConnectorTool({
304
+ name: "request",
305
+ description: `Send authenticated requests to the Amplitude REST API.
306
+ Authentication is handled automatically using Basic auth (API Key + Secret Key).
307
+ Provide the full URL including any query parameters.
308
+ Base URL by region: US \u2192 https://amplitude.com, EU \u2192 https://analytics.eu.amplitude.com. Check the connection's region parameter to determine which base URL to use.
309
+
310
+ Recommended endpoints (available on all plans):
311
+ - GET {baseUrl}/api/2/events/list \u2014 list event types
312
+ - GET {baseUrl}/api/2/export?start=YYYYMMDDTHH&end=YYYYMMDDTHH \u2014 export raw events
313
+ - GET {baseUrl}/api/2/usersearch?user=QUERY \u2014 search users
314
+ - GET {baseUrl}/api/2/useractivity?user=AMPLITUDE_ID \u2014 user activity
315
+
316
+ IMPORTANT: Dashboard REST API endpoints (events/segmentation, funnels, retention, revenue, etc.) require a paid Growth or Enterprise plan and will return 403 Forbidden on free plans. Always try the Export API first and aggregate data in code.`,
317
+ inputSchema,
318
+ outputSchema,
319
+ async execute({ connectionId, method, url, body }, connections) {
320
+ const connection2 = connections.find((c) => c.id === connectionId);
321
+ if (!connection2) {
322
+ return {
323
+ success: false,
324
+ error: `Connection ${connectionId} not found`
325
+ };
326
+ }
327
+ console.log(
328
+ `[connector-request] amplitude/${connection2.name}: ${method} ${url}`
329
+ );
330
+ try {
331
+ const apiKey = parameters.apiKey.getValue(connection2);
332
+ const secretKey = parameters.secretKey.getValue(connection2);
333
+ const authToken = btoa(`${apiKey}:${secretKey}`);
334
+ const controller = new AbortController();
335
+ const timeout = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS);
336
+ try {
337
+ const response = await fetch(url, {
338
+ method,
339
+ headers: {
340
+ Authorization: `Basic ${authToken}`,
341
+ "Content-Type": "application/json"
342
+ },
343
+ body: body ? JSON.stringify(body) : void 0,
344
+ signal: controller.signal
345
+ });
346
+ const data = await response.json();
347
+ if (!response.ok) {
348
+ const errorMessage = typeof data?.error === "string" ? data.error : typeof data?.message === "string" ? data.message : `HTTP ${response.status} ${response.statusText}`;
349
+ return { success: false, error: errorMessage };
350
+ }
351
+ return { success: true, status: response.status, data };
352
+ } finally {
353
+ clearTimeout(timeout);
354
+ }
355
+ } catch (err) {
356
+ const msg = err instanceof Error ? err.message : String(err);
357
+ return { success: false, error: msg };
358
+ }
359
+ }
360
+ });
361
+
142
362
  // ../connectors/src/connectors/amplitude/index.ts
143
- var tools = {};
363
+ var tools = { request: requestTool };
144
364
  var amplitudeConnector = new ConnectorPlugin({
145
365
  slug: "amplitude",
146
366
  authType: null,
@@ -149,53 +369,136 @@ var amplitudeConnector = new ConnectorPlugin({
149
369
  iconUrl: "https://images.ctfassets.net/9ncizv60xc5y/2UBJSdRlFJaLq52WUCTBEB/308b59b374cf6c662ac70989860bffd7/amplitude-icon.svg",
150
370
  parameters,
151
371
  releaseFlag: { dev1: true, dev2: false, prod: false },
372
+ onboarding: amplitudeOnboarding,
152
373
  systemPrompt: {
153
- en: `### Amplitude SDK (TypeScript handler)
154
- Use the Amplitude connector via the SDK in TypeScript handlers:
374
+ en: `### Tools
375
+
376
+ - \`amplitude_request\`: The only way to call the Amplitude REST API. Use it for event segmentation, listing event types, user search, user activity, and data export. Authentication (Basic auth with API Key + Secret Key) is configured automatically. Provide the full URL including query parameters \u2014 the base URL varies by endpoint.
377
+
378
+ ### Business Logic
379
+
380
+ The business logic type for this connector is "typescript". Use the connector SDK in your handler. Do NOT read credentials from environment variables.
381
+
382
+ SDK methods (client created via \`connection(connectionId)\`):
383
+ - \`client.request(url, init?)\` \u2014 low-level authenticated fetch (provide full URL)
384
+ - \`client.listEventTypes()\` \u2014 list all event types
385
+ - \`client.eventSegmentation(options)\` \u2014 run event segmentation query (e, start, end, m?, i?, g?)
386
+ - \`client.userSearch(query)\` \u2014 search users by user or amplitude ID
387
+ - \`client.userActivity(amplitudeId, options?)\` \u2014 get user activity by amplitude ID
155
388
 
156
389
  \`\`\`ts
390
+ import type { Context } from "hono";
157
391
  import { connection } from "@squadbase/vite-server/connectors/amplitude";
158
392
 
159
- const { apiKey, secretKey } = connection("<connectionId>");
393
+ const amp = connection("<connectionId>");
160
394
 
161
- // Use the Amplitude REST API with Basic auth (apiKey:secretKey)
162
- const res = await fetch("https://amplitude.com/api/2/events/segmentation", {
163
- headers: {
164
- Authorization: "Basic " + btoa(apiKey + ":" + secretKey),
165
- },
166
- });
167
- const data = await res.json();
395
+ export default async function handler(c: Context) {
396
+ const { eventType, start, end } = await c.req.json<{
397
+ eventType: string;
398
+ start: string;
399
+ end: string;
400
+ }>();
401
+
402
+ const result = await amp.eventSegmentation({
403
+ e: { event_type: eventType },
404
+ start,
405
+ end,
406
+ });
407
+
408
+ return c.json(result);
409
+ }
168
410
  \`\`\`
169
411
 
170
- ### Common Endpoints
171
- - GET \`https://amplitude.com/api/2/events/segmentation\` \u2014 Event segmentation
412
+ ### Amplitude REST API Reference
413
+
414
+ - Authentication: Basic auth (API Key:Secret Key, handled automatically)
415
+ - All timestamps use YYYYMMDD format for date parameters
416
+
417
+ #### Endpoints Available on All Plans
172
418
  - GET \`https://amplitude.com/api/2/events/list\` \u2014 List event types
173
- - GET \`https://amplitude.com/api/2/usersearch\` \u2014 Search users
174
- - GET \`https://amplitude.com/api/2/useractivity\` \u2014 User activity
175
- - POST \`https://amplitude.com/api/2/export\` \u2014 Export raw events`,
176
- ja: `### Amplitude SDK\uFF08TypeScript\u30CF\u30F3\u30C9\u30E9\u30FC\uFF09
177
- TypeScript\u30CF\u30F3\u30C9\u30E9\u30FC\u3067Amplitude\u30B3\u30CD\u30AF\u30BF\u30FC\u3092SDK\u7D4C\u7531\u3067\u4F7F\u7528\u3057\u307E\u3059\uFF1A
419
+ - GET \`https://amplitude.com/api/2/export?start=YYYYMMDDTHH&end=YYYYMMDDTHH\` \u2014 Export raw events
420
+ - GET \`https://amplitude.com/api/2/usersearch?user=QUERY\` \u2014 Search users
421
+ - GET \`https://amplitude.com/api/2/useractivity?user=AMPLITUDE_ID\` \u2014 User activity
422
+
423
+ #### Endpoints Requiring Growth or Enterprise Plan (will return 403 on free/Starter plans)
424
+ - GET \`https://amplitude.com/api/2/events/segmentation\` \u2014 Event segmentation
425
+ - GET \`https://amplitude.com/api/2/funnels\` \u2014 Funnel analysis
426
+ - GET \`https://amplitude.com/api/2/retention\` \u2014 Retention analysis
427
+ - GET \`https://amplitude.com/api/2/revenue\` \u2014 Revenue analysis
428
+
429
+ IMPORTANT: Always start with the endpoints available on all plans. If you need aggregated analytics, use the Export API to retrieve raw events and aggregate in code. Only attempt the Dashboard REST API endpoints (segmentation, funnels, retention, revenue) if specifically requested, and handle 403 errors gracefully by falling back to the Export API.
430
+
431
+ #### Event Segmentation Query Parameters (Growth/Enterprise only)
432
+ - \`e\` \u2014 JSON-encoded event definition (e.g., \`{"event_type":"Click"}\`)
433
+ - \`start\` \u2014 Start date (YYYYMMDD)
434
+ - \`end\` \u2014 End date (YYYYMMDD)
435
+ - \`m\` \u2014 Metric type (uniques, totals, avg, etc.)
436
+ - \`i\` \u2014 Interval (1=daily, 7=weekly, 30=monthly)
437
+ - \`g\` \u2014 Group by property`,
438
+ ja: `### \u30C4\u30FC\u30EB
439
+
440
+ - \`amplitude_request\`: Amplitude REST API\u3092\u547C\u3073\u51FA\u3059\u552F\u4E00\u306E\u624B\u6BB5\u3067\u3059\u3002\u30A4\u30D9\u30F3\u30C8\u30BB\u30B0\u30E1\u30F3\u30C6\u30FC\u30B7\u30E7\u30F3\u3001\u30A4\u30D9\u30F3\u30C8\u30BF\u30A4\u30D7\u4E00\u89A7\u3001\u30E6\u30FC\u30B6\u30FC\u691C\u7D22\u3001\u30E6\u30FC\u30B6\u30FC\u30A2\u30AF\u30C6\u30A3\u30D3\u30C6\u30A3\u3001\u30C7\u30FC\u30BF\u30A8\u30AF\u30B9\u30DD\u30FC\u30C8\u306B\u4F7F\u7528\u3057\u307E\u3059\u3002\u8A8D\u8A3C\uFF08API Key + Secret Key\u306B\u3088\u308BBasic\u8A8D\u8A3C\uFF09\u306F\u81EA\u52D5\u7684\u306B\u8A2D\u5B9A\u3055\u308C\u307E\u3059\u3002\u30AF\u30A8\u30EA\u30D1\u30E9\u30E1\u30FC\u30BF\u3092\u542B\u3080\u5B8C\u5168\u306AURL\u3092\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044 \u2014 \u30D9\u30FC\u30B9URL\u306F\u30A8\u30F3\u30C9\u30DD\u30A4\u30F3\u30C8\u306B\u3088\u3063\u3066\u7570\u306A\u308A\u307E\u3059\u3002
441
+
442
+ ### Business Logic
443
+
444
+ \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
445
+
446
+ SDK\u30E1\u30BD\u30C3\u30C9 (\`connection(connectionId)\` \u3067\u4F5C\u6210\u3057\u305F\u30AF\u30E9\u30A4\u30A2\u30F3\u30C8):
447
+ - \`client.request(url, init?)\` \u2014 \u4F4E\u30EC\u30D9\u30EB\u306E\u8A8D\u8A3C\u4ED8\u304Dfetch\uFF08\u5B8C\u5168\u306AURL\u3092\u6307\u5B9A\uFF09
448
+ - \`client.listEventTypes()\` \u2014 \u5168\u30A4\u30D9\u30F3\u30C8\u30BF\u30A4\u30D7\u306E\u4E00\u89A7
449
+ - \`client.eventSegmentation(options)\` \u2014 \u30A4\u30D9\u30F3\u30C8\u30BB\u30B0\u30E1\u30F3\u30C6\u30FC\u30B7\u30E7\u30F3\u30AF\u30A8\u30EA\u306E\u5B9F\u884C\uFF08e, start, end, m?, i?, g?\uFF09
450
+ - \`client.userSearch(query)\` \u2014 \u30E6\u30FC\u30B6\u30FC\u307E\u305F\u306Famplitude ID\u3067\u30E6\u30FC\u30B6\u30FC\u3092\u691C\u7D22
451
+ - \`client.userActivity(amplitudeId, options?)\` \u2014 amplitude ID\u3067\u30E6\u30FC\u30B6\u30FC\u30A2\u30AF\u30C6\u30A3\u30D3\u30C6\u30A3\u3092\u53D6\u5F97
178
452
 
179
453
  \`\`\`ts
454
+ import type { Context } from "hono";
180
455
  import { connection } from "@squadbase/vite-server/connectors/amplitude";
181
456
 
182
- const { apiKey, secretKey } = connection("<connectionId>");
457
+ const amp = connection("<connectionId>");
183
458
 
184
- // Amplitude REST API\u3092Basic\u8A8D\u8A3C\uFF08apiKey:secretKey\uFF09\u3067\u4F7F\u7528
185
- const res = await fetch("https://amplitude.com/api/2/events/segmentation", {
186
- headers: {
187
- Authorization: "Basic " + btoa(apiKey + ":" + secretKey),
188
- },
189
- });
190
- const data = await res.json();
459
+ export default async function handler(c: Context) {
460
+ const { eventType, start, end } = await c.req.json<{
461
+ eventType: string;
462
+ start: string;
463
+ end: string;
464
+ }>();
465
+
466
+ const result = await amp.eventSegmentation({
467
+ e: { event_type: eventType },
468
+ start,
469
+ end,
470
+ });
471
+
472
+ return c.json(result);
473
+ }
191
474
  \`\`\`
192
475
 
193
- ### \u4E3B\u8981\u30A8\u30F3\u30C9\u30DD\u30A4\u30F3\u30C8
194
- - GET \`https://amplitude.com/api/2/events/segmentation\` \u2014 \u30A4\u30D9\u30F3\u30C8\u30BB\u30B0\u30E1\u30F3\u30C6\u30FC\u30B7\u30E7\u30F3
476
+ ### Amplitude REST API \u30EA\u30D5\u30A1\u30EC\u30F3\u30B9
477
+
478
+ - \u8A8D\u8A3C: Basic\u8A8D\u8A3C\uFF08API Key:Secret Key\u3001\u81EA\u52D5\u8A2D\u5B9A\uFF09
479
+ - \u65E5\u4ED8\u30D1\u30E9\u30E1\u30FC\u30BF\u306F\u3059\u3079\u3066YYYYMMDD\u5F62\u5F0F\u306E\u30BF\u30A4\u30E0\u30B9\u30BF\u30F3\u30D7\u3092\u4F7F\u7528
480
+
481
+ #### \u5168\u30D7\u30E9\u30F3\u3067\u5229\u7528\u53EF\u80FD\u306A\u30A8\u30F3\u30C9\u30DD\u30A4\u30F3\u30C8
195
482
  - GET \`https://amplitude.com/api/2/events/list\` \u2014 \u30A4\u30D9\u30F3\u30C8\u30BF\u30A4\u30D7\u4E00\u89A7
196
- - GET \`https://amplitude.com/api/2/usersearch\` \u2014 \u30E6\u30FC\u30B6\u30FC\u691C\u7D22
197
- - GET \`https://amplitude.com/api/2/useractivity\` \u2014 \u30E6\u30FC\u30B6\u30FC\u30A2\u30AF\u30C6\u30A3\u30D3\u30C6\u30A3
198
- - POST \`https://amplitude.com/api/2/export\` \u2014 \u751F\u30A4\u30D9\u30F3\u30C8\u306E\u30A8\u30AF\u30B9\u30DD\u30FC\u30C8`
483
+ - GET \`https://amplitude.com/api/2/export?start=YYYYMMDDTHH&end=YYYYMMDDTHH\` \u2014 \u751F\u30A4\u30D9\u30F3\u30C8\u306E\u30A8\u30AF\u30B9\u30DD\u30FC\u30C8
484
+ - GET \`https://amplitude.com/api/2/usersearch?user=QUERY\` \u2014 \u30E6\u30FC\u30B6\u30FC\u691C\u7D22
485
+ - GET \`https://amplitude.com/api/2/useractivity?user=AMPLITUDE_ID\` \u2014 \u30E6\u30FC\u30B6\u30FC\u30A2\u30AF\u30C6\u30A3\u30D3\u30C6\u30A3
486
+
487
+ #### Growth\u307E\u305F\u306FEnterprise\u30D7\u30E9\u30F3\u304C\u5FC5\u8981\u306A\u30A8\u30F3\u30C9\u30DD\u30A4\u30F3\u30C8\uFF08\u7121\u6599/Starter\u30D7\u30E9\u30F3\u3067\u306F403\u30A8\u30E9\u30FC\uFF09
488
+ - GET \`https://amplitude.com/api/2/events/segmentation\` \u2014 \u30A4\u30D9\u30F3\u30C8\u30BB\u30B0\u30E1\u30F3\u30C6\u30FC\u30B7\u30E7\u30F3
489
+ - GET \`https://amplitude.com/api/2/funnels\` \u2014 \u30D5\u30A1\u30CD\u30EB\u5206\u6790
490
+ - GET \`https://amplitude.com/api/2/retention\` \u2014 \u30EA\u30C6\u30F3\u30B7\u30E7\u30F3\u5206\u6790
491
+ - GET \`https://amplitude.com/api/2/revenue\` \u2014 \u53CE\u76CA\u5206\u6790
492
+
493
+ \u91CD\u8981: \u307E\u305A\u5168\u30D7\u30E9\u30F3\u3067\u5229\u7528\u53EF\u80FD\u306A\u30A8\u30F3\u30C9\u30DD\u30A4\u30F3\u30C8\u3092\u4F7F\u7528\u3057\u3066\u304F\u3060\u3055\u3044\u3002\u96C6\u8A08\u5206\u6790\u304C\u5FC5\u8981\u306A\u5834\u5408\u306F\u3001Export API\u3067\u751F\u30A4\u30D9\u30F3\u30C8\u3092\u53D6\u5F97\u3057\u3001\u30B3\u30FC\u30C9\u4E0A\u3067\u96C6\u8A08\u3092\u884C\u3063\u3066\u304F\u3060\u3055\u3044\u3002Dashboard REST API\uFF08segmentation\u3001funnels\u3001retention\u3001revenue\uFF09\u306F\u660E\u793A\u7684\u306B\u8981\u6C42\u3055\u308C\u305F\u5834\u5408\u306E\u307F\u8A66\u884C\u3057\u3001403\u30A8\u30E9\u30FC\u304C\u8FD4\u3055\u308C\u305F\u5834\u5408\u306FExport API\u306B\u30D5\u30A9\u30FC\u30EB\u30D0\u30C3\u30AF\u3057\u3066\u304F\u3060\u3055\u3044\u3002
494
+
495
+ #### \u30A4\u30D9\u30F3\u30C8\u30BB\u30B0\u30E1\u30F3\u30C6\u30FC\u30B7\u30E7\u30F3\u30AF\u30A8\u30EA\u30D1\u30E9\u30E1\u30FC\u30BF\uFF08Growth/Enterprise\u30D7\u30E9\u30F3\u306E\u307F\uFF09
496
+ - \`e\` \u2014 JSON\u30A8\u30F3\u30B3\u30FC\u30C9\u3055\u308C\u305F\u30A4\u30D9\u30F3\u30C8\u5B9A\u7FA9\uFF08\u4F8B: \`{"event_type":"Click"}\`\uFF09
497
+ - \`start\` \u2014 \u958B\u59CB\u65E5\uFF08YYYYMMDD\uFF09
498
+ - \`end\` \u2014 \u7D42\u4E86\u65E5\uFF08YYYYMMDD\uFF09
499
+ - \`m\` \u2014 \u30E1\u30C8\u30EA\u30AF\u30B9\u30BF\u30A4\u30D7\uFF08uniques, totals, avg\u306A\u3069\uFF09
500
+ - \`i\` \u2014 \u30A4\u30F3\u30BF\u30FC\u30D0\u30EB\uFF081=\u65E5\u6B21\u30017=\u9031\u6B21\u300130=\u6708\u6B21\uFF09
501
+ - \`g\` \u2014 \u30B0\u30EB\u30FC\u30D7\u5316\u30D7\u30ED\u30D1\u30C6\u30A3`
199
502
  },
200
503
  tools
201
504
  });