@squadbase/vite-server 0.1.9-dev.f236b23 → 0.1.10-dev.9dac57b

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.
@@ -42,6 +42,39 @@ var ParameterDefinition = class {
42
42
  }
43
43
  };
44
44
 
45
+ // ../connectors/src/connectors/google-ads/constants.ts
46
+ var VERSION_FALLBACK_ORDER = ["v22", "v23", "v24"];
47
+ var cachedWorkingVersion = VERSION_FALLBACK_ORDER[0];
48
+ var looksSunset = (contentType) => {
49
+ return contentType != null && contentType.toLowerCase().includes("text/html");
50
+ };
51
+ async function fetchGoogleAdsWithVersionFallback(attempt) {
52
+ const order = [
53
+ cachedWorkingVersion,
54
+ ...VERSION_FALLBACK_ORDER.filter((v) => v !== cachedWorkingVersion)
55
+ ];
56
+ let lastResponse = null;
57
+ for (let i = 0; i < order.length; i++) {
58
+ const version = order[i];
59
+ const baseUrl = `https://googleads.googleapis.com/${version}/`;
60
+ const response = await attempt(baseUrl);
61
+ const contentType = response.headers.get("content-type");
62
+ if (looksSunset(contentType) && i < order.length - 1) {
63
+ console.warn(
64
+ `[google-ads] version ${version} returned a sunset/HTML response (status ${response.status}); retrying with newer version`
65
+ );
66
+ lastResponse = response;
67
+ continue;
68
+ }
69
+ cachedWorkingVersion = version;
70
+ return response;
71
+ }
72
+ return lastResponse ?? new Response(null, {
73
+ status: 502,
74
+ statusText: "All Google Ads API versions returned sunset responses"
75
+ });
76
+ }
77
+
45
78
  // ../connectors/src/connectors/google-ads/parameters.ts
46
79
  var parameters = {
47
80
  customerId: new ParameterDefinition({
@@ -52,29 +85,13 @@ var parameters = {
52
85
  type: "text",
53
86
  secret: false,
54
87
  required: false
55
- }),
56
- developerToken: new ParameterDefinition({
57
- slug: "developer-token",
58
- name: "Google Ads Developer Token",
59
- description: "The developer token for accessing the Google Ads API. Required for all API requests.",
60
- envVarBaseKey: "GOOGLE_ADS_DEVELOPER_TOKEN",
61
- type: "text",
62
- secret: true,
63
- required: true
64
88
  })
65
89
  };
66
90
 
67
91
  // ../connectors/src/connectors/google-ads/sdk/index.ts
68
- var BASE_URL = "https://googleads.googleapis.com/v18/";
69
92
  function createClient(params, fetchFn = fetch) {
70
93
  const rawCustomerId = params[parameters.customerId.slug];
71
94
  const defaultCustomerId = rawCustomerId?.replace(/-/g, "") ?? "";
72
- const developerToken = params[parameters.developerToken.slug];
73
- if (!developerToken) {
74
- throw new Error(
75
- `google-ads: missing required parameter: ${parameters.developerToken.slug}`
76
- );
77
- }
78
95
  function resolveCustomerId(override) {
79
96
  const id = override?.replace(/-/g, "") ?? defaultCustomerId;
80
97
  if (!id) {
@@ -86,26 +103,26 @@ function createClient(params, fetchFn = fetch) {
86
103
  }
87
104
  function request(path2, init) {
88
105
  const resolvedPath = defaultCustomerId ? path2.replace(/\{customerId\}/g, defaultCustomerId) : path2;
89
- const url = `${BASE_URL}${resolvedPath}`;
90
106
  const headers = new Headers(init?.headers);
91
- headers.set("developer-token", developerToken);
92
107
  if (defaultCustomerId) {
93
108
  headers.set("login-customer-id", defaultCustomerId);
94
109
  }
95
- return fetchFn(url, { ...init, headers });
110
+ return fetchGoogleAdsWithVersionFallback(
111
+ (baseUrl) => fetchFn(`${baseUrl}${resolvedPath}`, { ...init, headers })
112
+ );
96
113
  }
97
114
  async function search(query, customerId) {
98
115
  const cid = resolveCustomerId(customerId);
99
- const url = `${BASE_URL}customers/${cid}/googleAds:searchStream`;
100
116
  const headers = new Headers();
101
117
  headers.set("Content-Type", "application/json");
102
- headers.set("developer-token", developerToken);
103
118
  headers.set("login-customer-id", cid);
104
- const response = await fetchFn(url, {
105
- method: "POST",
106
- headers,
107
- body: JSON.stringify({ query })
108
- });
119
+ const response = await fetchGoogleAdsWithVersionFallback(
120
+ (baseUrl) => fetchFn(`${baseUrl}customers/${cid}/googleAds:searchStream`, {
121
+ method: "POST",
122
+ headers,
123
+ body: JSON.stringify({ query })
124
+ })
125
+ );
109
126
  if (!response.ok) {
110
127
  const body = await response.text();
111
128
  throw new Error(
@@ -116,10 +133,9 @@ function createClient(params, fetchFn = fetch) {
116
133
  return data.flatMap((chunk) => chunk.results ?? []);
117
134
  }
118
135
  async function listAccessibleCustomers() {
119
- const url = `${BASE_URL}customers:listAccessibleCustomers`;
120
- const headers = new Headers();
121
- headers.set("developer-token", developerToken);
122
- const response = await fetchFn(url, { method: "GET", headers });
136
+ const response = await fetchGoogleAdsWithVersionFallback(
137
+ (baseUrl) => fetchFn(`${baseUrl}customers:listAccessibleCustomers`, { method: "GET" })
138
+ );
123
139
  if (!response.ok) {
124
140
  const body = await response.text();
125
141
  throw new Error(
@@ -289,7 +305,6 @@ var AUTH_TYPES = {
289
305
 
290
306
  // ../connectors/src/connectors/google-ads/tools/list-customers.ts
291
307
  import { z } from "zod";
292
- var BASE_URL2 = "https://googleads.googleapis.com/v18/";
293
308
  var REQUEST_TIMEOUT_MS = 6e4;
294
309
  var cachedToken = null;
295
310
  async function getProxyToken(config) {
@@ -360,27 +375,25 @@ var listCustomersTool = new ConnectorTool({
360
375
  `[connector-request] google-ads/${connection2.name}: listCustomers`
361
376
  );
362
377
  try {
363
- const developerToken = parameters.developerToken.getValue(connection2);
364
378
  const token = await getProxyToken(config.oauthProxy);
365
379
  const proxyUrl = `https://${config.oauthProxy.sandboxId}.${config.oauthProxy.previewBaseDomain}/_sqcore/connections/${connectionId}/request`;
366
380
  const controller = new AbortController();
367
381
  const timeout = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS);
368
382
  try {
369
- const response = await fetch(proxyUrl, {
370
- method: "POST",
371
- headers: {
372
- "Content-Type": "application/json",
373
- Authorization: `Bearer ${token}`
374
- },
375
- body: JSON.stringify({
376
- url: `${BASE_URL2}customers:listAccessibleCustomers`,
377
- method: "GET",
383
+ const response = await fetchGoogleAdsWithVersionFallback(
384
+ (baseUrl) => fetch(proxyUrl, {
385
+ method: "POST",
378
386
  headers: {
379
- "developer-token": developerToken
380
- }
381
- }),
382
- signal: controller.signal
383
- });
387
+ "Content-Type": "application/json",
388
+ Authorization: `Bearer ${token}`
389
+ },
390
+ body: JSON.stringify({
391
+ url: `${baseUrl}customers:listAccessibleCustomers`,
392
+ method: "GET"
393
+ }),
394
+ signal: controller.signal
395
+ })
396
+ );
384
397
  const data = await response.json();
385
398
  if (!response.ok) {
386
399
  const errorMessage = typeof data?.error === "string" ? data.error : typeof data?.message === "string" ? data.message : `HTTP ${response.status} ${response.statusText}`;
@@ -392,26 +405,27 @@ var listCustomersTool = new ConnectorTool({
392
405
  const customers = [];
393
406
  for (const cid of customerIds) {
394
407
  try {
395
- const detailResponse = await fetch(proxyUrl, {
396
- method: "POST",
397
- headers: {
398
- "Content-Type": "application/json",
399
- Authorization: `Bearer ${token}`
400
- },
401
- body: JSON.stringify({
402
- url: `${BASE_URL2}customers/${cid}/googleAds:searchStream`,
408
+ const detailResponse = await fetchGoogleAdsWithVersionFallback(
409
+ (baseUrl) => fetch(proxyUrl, {
403
410
  method: "POST",
404
411
  headers: {
405
412
  "Content-Type": "application/json",
406
- "developer-token": developerToken,
407
- "login-customer-id": cid
413
+ Authorization: `Bearer ${token}`
408
414
  },
409
415
  body: JSON.stringify({
410
- query: "SELECT customer.id, customer.descriptive_name FROM customer LIMIT 1"
411
- })
412
- }),
413
- signal: controller.signal
414
- });
416
+ url: `${baseUrl}customers/${cid}/googleAds:searchStream`,
417
+ method: "POST",
418
+ headers: {
419
+ "Content-Type": "application/json",
420
+ "login-customer-id": cid
421
+ },
422
+ body: JSON.stringify({
423
+ query: "SELECT customer.id, customer.descriptive_name FROM customer LIMIT 1"
424
+ })
425
+ }),
426
+ signal: controller.signal
427
+ })
428
+ );
415
429
  if (detailResponse.ok) {
416
430
  const detailData = await detailResponse.json();
417
431
  const customer = detailData?.[0]?.results?.[0]?.customer;
@@ -449,30 +463,24 @@ var googleAdsOnboarding = new ConnectorOnboarding({
449
463
  connectionSetupInstructions: {
450
464
  ja: `\u4EE5\u4E0B\u306E\u624B\u9806\u3067Google Ads (OAuth) \u30B3\u30CD\u30AF\u30B7\u30E7\u30F3\u306E\u30BB\u30C3\u30C8\u30A2\u30C3\u30D7\u3092\u884C\u3063\u3066\u304F\u3060\u3055\u3044\u3002
451
465
 
452
- 1. \u30E6\u30FC\u30B6\u30FC\u306B\u300CGoogle Ads API \u306E Developer Token \u3092\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044\uFF08Google Ads \u7BA1\u7406\u753B\u9762 > \u30C4\u30FC\u30EB\u3068\u8A2D\u5B9A > API \u30BB\u30F3\u30BF\u30FC\u3067\u53D6\u5F97\u3067\u304D\u307E\u3059\uFF09\u300D\u3068\u4F1D\u3048\u308B
466
+ 1. \`${listCustomersToolName}\` \u3092\u547C\u3073\u51FA\u3057\u3066\u3001OAuth\u3067\u30A2\u30AF\u30BB\u30B9\u53EF\u80FD\u306AGoogle Ads\u30AB\u30B9\u30BF\u30DE\u30FC\u30A2\u30AB\u30A6\u30F3\u30C8\u4E00\u89A7\u3092\u53D6\u5F97\u3059\u308B
453
467
  2. \`updateConnectionParameters\` \u3092\u547C\u3073\u51FA\u3059:
454
- - \`parameterSlug\`: \`"developer-token"\`
455
- - \`value\`: \u30E6\u30FC\u30B6\u30FC\u304C\u63D0\u4F9B\u3057\u305F Developer Token
456
- 3. \`${listCustomersToolName}\` \u3092\u547C\u3073\u51FA\u3057\u3066\u3001OAuth\u3067\u30A2\u30AF\u30BB\u30B9\u53EF\u80FD\u306AGoogle Ads\u30AB\u30B9\u30BF\u30DE\u30FC\u30A2\u30AB\u30A6\u30F3\u30C8\u4E00\u89A7\u3092\u53D6\u5F97\u3059\u308B
457
- 4. \`updateConnectionParameters\` \u3092\u547C\u3073\u51FA\u3059:
458
468
  - \`parameterSlug\`: \`"customer-id"\`
459
469
  - \`options\`: \u30AB\u30B9\u30BF\u30DE\u30FC\u4E00\u89A7\u3002\u5404 option \u306E \`label\` \u306F \`\u30A2\u30AB\u30A6\u30F3\u30C8\u540D (id: \u30AB\u30B9\u30BF\u30DE\u30FCID)\` \u306E\u5F62\u5F0F\u3001\`value\` \u306F\u30AB\u30B9\u30BF\u30DE\u30FCID
460
- 5. \u30E6\u30FC\u30B6\u30FC\u304C\u9078\u629E\u3057\u305F\u30AB\u30B9\u30BF\u30DE\u30FC\u306E \`label\` \u304C\u30E1\u30C3\u30BB\u30FC\u30B8\u3068\u3057\u3066\u5C4A\u304F\u306E\u3067\u3001\u6B21\u306E\u30B9\u30C6\u30C3\u30D7\u306B\u9032\u3080
470
+ - \u30AB\u30B9\u30BF\u30DE\u30FC\u304C **0\u4EF6** \u306E\u5834\u5408\u306F\u30BB\u30C3\u30C8\u30A2\u30C3\u30D7\u3092\u4E2D\u65AD\u3057\u3001\u30E6\u30FC\u30B6\u30FC\u306B\u30A2\u30AF\u30BB\u30B9\u53EF\u80FD\u306A\u30A2\u30AB\u30A6\u30F3\u30C8\u304C\u306A\u3044\u65E8\u3092\u4F1D\u3048\u308B
471
+ 3. \u30E6\u30FC\u30B6\u30FC\u304C\u9078\u629E\u3057\u305F\u30AB\u30B9\u30BF\u30DE\u30FC\u306E \`label\` \u304C\u30E1\u30C3\u30BB\u30FC\u30B8\u3068\u3057\u3066\u5C4A\u304F\u306E\u3067\u3001\u6B21\u306E\u30B9\u30C6\u30C3\u30D7\u306B\u9032\u3080
461
472
 
462
473
  #### \u5236\u7D04
463
474
  - **\u30BB\u30C3\u30C8\u30A2\u30C3\u30D7\u4E2D\u306B\u30EC\u30DD\u30FC\u30C8\u30C7\u30FC\u30BF\u3092\u53D6\u5F97\u3057\u306A\u3044\u3053\u3068**\u3002\u5B9F\u884C\u3057\u3066\u3088\u3044\u306E\u306F\u4E0A\u8A18\u624B\u9806\u3067\u6307\u5B9A\u3055\u308C\u305F\u30E1\u30BF\u30C7\u30FC\u30BF\u53D6\u5F97\u306E\u307F
464
475
  - \u30C4\u30FC\u30EB\u9593\u306F1\u6587\u3060\u3051\u66F8\u3044\u3066\u5373\u6B21\u306E\u30C4\u30FC\u30EB\u547C\u3073\u51FA\u3057\u3002\u4E0D\u8981\u306A\u8AAC\u660E\u306F\u7701\u7565\u3057\u3001\u52B9\u7387\u7684\u306B\u9032\u3081\u308B`,
465
476
  en: `Follow these steps to set up the Google Ads (OAuth) connection.
466
477
 
467
- 1. Ask the user to provide their Google Ads API Developer Token (available in Google Ads UI > Tools & Settings > API Center)
478
+ 1. Call \`${listCustomersToolName}\` to get the list of Google Ads customer accounts accessible with the OAuth credentials
468
479
  2. Call \`updateConnectionParameters\`:
469
- - \`parameterSlug\`: \`"developer-token"\`
470
- - \`value\`: The Developer Token provided by the user
471
- 3. Call \`${listCustomersToolName}\` to get the list of Google Ads customer accounts accessible with the OAuth credentials
472
- 4. Call \`updateConnectionParameters\`:
473
480
  - \`parameterSlug\`: \`"customer-id"\`
474
481
  - \`options\`: The customer list. Each option's \`label\` should be \`Account Name (id: customerId)\`, \`value\` should be the customer ID
475
- 5. The \`label\` of the user's selected customer will arrive as a message. Proceed to the next step
482
+ - If **0 customers** are returned, abort setup and inform the user that no accessible accounts are available
483
+ 3. The \`label\` of the user's selected customer will arrive as a message. Proceed to the next step
476
484
 
477
485
  #### Constraints
478
486
  - **Do NOT fetch report data during setup**. Only the metadata requests specified in the steps above are allowed
@@ -488,7 +496,6 @@ var googleAdsOnboarding = new ConnectorOnboarding({
488
496
 
489
497
  // ../connectors/src/connectors/google-ads/tools/request.ts
490
498
  import { z as z2 } from "zod";
491
- var BASE_URL3 = "https://googleads.googleapis.com/v18/";
492
499
  var REQUEST_TIMEOUT_MS2 = 6e4;
493
500
  var cachedToken2 = null;
494
501
  async function getProxyToken2(config) {
@@ -528,7 +535,7 @@ var inputSchema2 = z2.object({
528
535
  connectionId: z2.string().describe("ID of the Google Ads OAuth connection to use"),
529
536
  method: z2.enum(["GET", "POST"]).describe("HTTP method"),
530
537
  path: z2.string().describe(
531
- "API path appended to https://googleads.googleapis.com/v18/ (e.g., 'customers/{customerId}/googleAds:searchStream'). {customerId} is automatically replaced."
538
+ "API path appended to https://googleads.googleapis.com/<version>/ (e.g., 'customers/{customerId}/googleAds:searchStream'). The API version is auto-managed and {customerId} is automatically replaced."
532
539
  ),
533
540
  body: z2.record(z2.string(), z2.unknown()).optional().describe("POST request body (JSON)")
534
541
  });
@@ -545,7 +552,7 @@ var outputSchema2 = z2.discriminatedUnion("success", [
545
552
  ]);
546
553
  var requestTool = new ConnectorTool({
547
554
  name: "request",
548
- description: `Send authenticated requests to the Google Ads API v18.
555
+ description: `Send authenticated requests to the Google Ads API.
549
556
  Authentication is handled automatically via OAuth proxy.
550
557
  {customerId} in the path is automatically replaced with the connection's customer ID (hyphens removed).`,
551
558
  inputSchema: inputSchema2,
@@ -565,31 +572,30 @@ Authentication is handled automatically via OAuth proxy.
565
572
  const rawCustomerId = parameters.customerId.tryGetValue(connection2);
566
573
  const customerId = rawCustomerId?.replace(/-/g, "") ?? "";
567
574
  const resolvedPath = customerId ? path2.replace(/\{customerId\}/g, customerId) : path2;
568
- const url = `${BASE_URL3}${resolvedPath}`;
569
575
  const token = await getProxyToken2(config.oauthProxy);
570
576
  const proxyUrl = `https://${config.oauthProxy.sandboxId}.${config.oauthProxy.previewBaseDomain}/_sqcore/connections/${connectionId}/request`;
571
577
  const controller = new AbortController();
572
578
  const timeout = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS2);
573
579
  try {
574
- const developerToken = parameters.developerToken.getValue(connection2);
575
- const response = await fetch(proxyUrl, {
576
- method: "POST",
577
- headers: {
578
- "Content-Type": "application/json",
579
- Authorization: `Bearer ${token}`
580
- },
581
- body: JSON.stringify({
582
- url,
583
- method,
580
+ const response = await fetchGoogleAdsWithVersionFallback(
581
+ (baseUrl) => fetch(proxyUrl, {
582
+ method: "POST",
584
583
  headers: {
585
584
  "Content-Type": "application/json",
586
- "developer-token": developerToken,
587
- ...customerId ? { "login-customer-id": customerId } : {}
585
+ Authorization: `Bearer ${token}`
588
586
  },
589
- ...method === "POST" && body ? { body: JSON.stringify(body) } : {}
590
- }),
591
- signal: controller.signal
592
- });
587
+ body: JSON.stringify({
588
+ url: `${baseUrl}${resolvedPath}`,
589
+ method,
590
+ headers: {
591
+ "Content-Type": "application/json",
592
+ ...customerId ? { "login-customer-id": customerId } : {}
593
+ },
594
+ ...method === "POST" && body ? { body: JSON.stringify(body) } : {}
595
+ }),
596
+ signal: controller.signal
597
+ })
598
+ );
593
599
  const data = await response.json();
594
600
  if (!response.ok) {
595
601
  const dataObj = data;
@@ -764,26 +770,22 @@ const customerIds = await ads.listAccessibleCustomers();
764
770
  if (!customerId) {
765
771
  return { success: true };
766
772
  }
767
- const developerToken = params[parameters.developerToken.slug];
768
- if (!developerToken) {
769
- return {
770
- success: false,
771
- error: "Developer token is required"
772
- };
773
- }
774
- const url = `https://googleads.googleapis.com/v18/customers/${customerId}/googleAds:searchStream`;
775
773
  try {
776
- const res = await proxyFetch(url, {
777
- method: "POST",
778
- headers: {
779
- "Content-Type": "application/json",
780
- "developer-token": developerToken,
781
- "login-customer-id": customerId
782
- },
783
- body: JSON.stringify({
784
- query: "SELECT customer.id FROM customer LIMIT 1"
785
- })
786
- });
774
+ const res = await fetchGoogleAdsWithVersionFallback(
775
+ (baseUrl) => proxyFetch(
776
+ `${baseUrl}customers/${customerId}/googleAds:searchStream`,
777
+ {
778
+ method: "POST",
779
+ headers: {
780
+ "Content-Type": "application/json",
781
+ "login-customer-id": customerId
782
+ },
783
+ body: JSON.stringify({
784
+ query: "SELECT customer.id FROM customer LIMIT 1"
785
+ })
786
+ }
787
+ )
788
+ );
787
789
  if (!res.ok) {
788
790
  const errorText = await res.text().catch(() => res.statusText);
789
791
  return {