alchemy 0.70.2 → 0.71.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.
Files changed (131) hide show
  1. package/README.md +1 -1
  2. package/bin/alchemy.js +131 -58
  3. package/bin/commands/init.ts +0 -10
  4. package/bin/services/execute-alchemy.ts +12 -3
  5. package/bin/trpc.ts +12 -12
  6. package/lib/alchemy.d.ts.map +1 -1
  7. package/lib/alchemy.js +21 -6
  8. package/lib/alchemy.js.map +1 -1
  9. package/lib/apply.d.ts.map +1 -1
  10. package/lib/apply.js +3 -1
  11. package/lib/apply.js.map +1 -1
  12. package/lib/cloudflare/bindings.d.ts +12 -2
  13. package/lib/cloudflare/bindings.d.ts.map +1 -1
  14. package/lib/cloudflare/bindings.js.map +1 -1
  15. package/lib/cloudflare/bound.d.ts +3 -2
  16. package/lib/cloudflare/bound.d.ts.map +1 -1
  17. package/lib/cloudflare/bucket.d.ts +6 -0
  18. package/lib/cloudflare/bucket.d.ts.map +1 -1
  19. package/lib/cloudflare/bucket.js +5 -3
  20. package/lib/cloudflare/bucket.js.map +1 -1
  21. package/lib/cloudflare/bun-spa/bun-spa.d.ts +6 -1
  22. package/lib/cloudflare/bun-spa/bun-spa.d.ts.map +1 -1
  23. package/lib/cloudflare/bun-spa/bun-spa.js +29 -9
  24. package/lib/cloudflare/bun-spa/bun-spa.js.map +1 -1
  25. package/lib/cloudflare/compatibility-date.gen.d.ts +1 -1
  26. package/lib/cloudflare/compatibility-date.gen.js +1 -1
  27. package/lib/cloudflare/d1-database.d.ts +1 -1
  28. package/lib/cloudflare/d1-database.d.ts.map +1 -1
  29. package/lib/cloudflare/d1-database.js +1 -1
  30. package/lib/cloudflare/d1-database.js.map +1 -1
  31. package/lib/cloudflare/health-check.d.ts +261 -0
  32. package/lib/cloudflare/health-check.d.ts.map +1 -0
  33. package/lib/cloudflare/health-check.js +277 -0
  34. package/lib/cloudflare/health-check.js.map +1 -0
  35. package/lib/cloudflare/index.d.ts +3 -0
  36. package/lib/cloudflare/index.d.ts.map +1 -1
  37. package/lib/cloudflare/index.js +3 -0
  38. package/lib/cloudflare/index.js.map +1 -1
  39. package/lib/cloudflare/logpush-job.d.ts +349 -0
  40. package/lib/cloudflare/logpush-job.d.ts.map +1 -0
  41. package/lib/cloudflare/logpush-job.js +277 -0
  42. package/lib/cloudflare/logpush-job.js.map +1 -0
  43. package/lib/cloudflare/miniflare/build-worker-options.d.ts +1 -0
  44. package/lib/cloudflare/miniflare/build-worker-options.d.ts.map +1 -1
  45. package/lib/cloudflare/miniflare/build-worker-options.js +16 -6
  46. package/lib/cloudflare/miniflare/build-worker-options.js.map +1 -1
  47. package/lib/cloudflare/miniflare/remote-binding-proxy.d.ts.map +1 -1
  48. package/lib/cloudflare/miniflare/remote-binding-proxy.js +2 -0
  49. package/lib/cloudflare/miniflare/remote-binding-proxy.js.map +1 -1
  50. package/lib/cloudflare/queue-consumer.js +2 -2
  51. package/lib/cloudflare/queue-consumer.js.map +1 -1
  52. package/lib/cloudflare/worker-loader.d.ts +9 -0
  53. package/lib/cloudflare/worker-loader.d.ts.map +1 -0
  54. package/lib/cloudflare/worker-loader.js +6 -0
  55. package/lib/cloudflare/worker-loader.js.map +1 -0
  56. package/lib/cloudflare/worker-metadata.d.ts.map +1 -1
  57. package/lib/cloudflare/worker-metadata.js +6 -0
  58. package/lib/cloudflare/worker-metadata.js.map +1 -1
  59. package/lib/cloudflare/worker-subdomain.js +1 -1
  60. package/lib/cloudflare/worker.d.ts.map +1 -1
  61. package/lib/cloudflare/worker.js +7 -0
  62. package/lib/cloudflare/worker.js.map +1 -1
  63. package/lib/cloudflare/wrangler.json.d.ts +11 -8
  64. package/lib/cloudflare/wrangler.json.d.ts.map +1 -1
  65. package/lib/cloudflare/wrangler.json.js +18 -11
  66. package/lib/cloudflare/wrangler.json.js.map +1 -1
  67. package/lib/cloudflare/zone.js +1 -1
  68. package/lib/destroy.d.ts.map +1 -1
  69. package/lib/destroy.js +27 -0
  70. package/lib/destroy.js.map +1 -1
  71. package/lib/docker/image.js +1 -1
  72. package/lib/docker/image.js.map +1 -1
  73. package/lib/github/comment.d.ts.map +1 -1
  74. package/lib/github/comment.js +14 -7
  75. package/lib/github/comment.js.map +1 -1
  76. package/lib/resource.js +1 -1
  77. package/lib/resource.js.map +1 -1
  78. package/lib/scope.d.ts +6 -1
  79. package/lib/scope.d.ts.map +1 -1
  80. package/lib/scope.js +22 -22
  81. package/lib/scope.js.map +1 -1
  82. package/lib/state/instrumented-state-store.js +1 -1
  83. package/lib/state/instrumented-state-store.js.map +1 -1
  84. package/lib/util/cli-args.d.ts +3 -0
  85. package/lib/util/cli-args.d.ts.map +1 -0
  86. package/lib/util/cli-args.js +6 -0
  87. package/lib/util/cli-args.js.map +1 -0
  88. package/lib/util/retry.d.ts +1 -1
  89. package/lib/util/retry.d.ts.map +1 -1
  90. package/lib/util/retry.js +2 -2
  91. package/lib/util/retry.js.map +1 -1
  92. package/lib/util/telemetry.d.ts +1 -0
  93. package/lib/util/telemetry.d.ts.map +1 -1
  94. package/lib/util/telemetry.js +47 -2
  95. package/lib/util/telemetry.js.map +1 -1
  96. package/lib/util/validate-resource-id.d.ts +2 -0
  97. package/lib/util/validate-resource-id.d.ts.map +1 -0
  98. package/lib/util/validate-resource-id.js +11 -0
  99. package/lib/util/validate-resource-id.js.map +1 -0
  100. package/package.json +11 -9
  101. package/src/alchemy.ts +25 -11
  102. package/src/apply.ts +3 -1
  103. package/src/cloudflare/bindings.ts +13 -0
  104. package/src/cloudflare/bound.ts +36 -32
  105. package/src/cloudflare/bucket.ts +13 -4
  106. package/src/cloudflare/bun-spa/bun-spa.ts +42 -10
  107. package/src/cloudflare/compatibility-date.gen.ts +1 -1
  108. package/src/cloudflare/d1-database.ts +2 -2
  109. package/src/cloudflare/health-check.ts +617 -0
  110. package/src/cloudflare/index.ts +3 -0
  111. package/src/cloudflare/logpush-job.ts +768 -0
  112. package/src/cloudflare/miniflare/build-worker-options.ts +18 -6
  113. package/src/cloudflare/miniflare/remote-binding-proxy.ts +2 -0
  114. package/src/cloudflare/queue-consumer.ts +2 -2
  115. package/src/cloudflare/worker-loader.ts +12 -0
  116. package/src/cloudflare/worker-metadata.ts +5 -0
  117. package/src/cloudflare/worker-subdomain.ts +1 -1
  118. package/src/cloudflare/worker.ts +8 -0
  119. package/src/cloudflare/wrangler.json.ts +36 -23
  120. package/src/cloudflare/zone.ts +1 -1
  121. package/src/destroy.ts +32 -0
  122. package/src/docker/image.ts +1 -1
  123. package/src/github/comment.ts +17 -8
  124. package/src/resource.ts +1 -1
  125. package/src/scope.ts +32 -25
  126. package/src/state/instrumented-state-store.ts +1 -1
  127. package/src/util/cli-args.ts +11 -0
  128. package/src/util/retry.ts +2 -1
  129. package/src/util/telemetry.ts +68 -2
  130. package/src/util/validate-resource-id.ts +10 -0
  131. package/workers/tunnel-proxy.js +1 -1
@@ -0,0 +1,11 @@
1
+ export const cliArgs = process.argv.slice(2);
2
+
3
+ export function parseOption<D extends string | undefined>(
4
+ option: string,
5
+ defaultValue?: D,
6
+ ): D {
7
+ const i = cliArgs.indexOf(option);
8
+ return (
9
+ i !== -1 && i + 1 < cliArgs.length ? cliArgs[i + 1] : defaultValue
10
+ ) as D;
11
+ }
package/src/util/retry.ts CHANGED
@@ -14,6 +14,7 @@ export async function withExponentialBackoff<T>(
14
14
  isRetryable: (error: any) => any,
15
15
  maxAttempts = 5,
16
16
  initialDelayMs = 100,
17
+ maxDelayMs = 10000,
17
18
  ): Promise<T> {
18
19
  let attempt = 0;
19
20
  let delay = initialDelayMs;
@@ -31,7 +32,7 @@ export async function withExponentialBackoff<T>(
31
32
  const jitter = Math.random() * 0.1 * delay;
32
33
  await new Promise((resolve) => setTimeout(resolve, delay + jitter));
33
34
  delay *= 2; // Double the delay for next attempt
34
- delay = Math.min(delay, 10000); // Cap at 10 seconds
35
+ delay = Math.min(delay, maxDelayMs); // Cap at 10 seconds
35
36
  }
36
37
  }
37
38
  }
@@ -1,11 +1,15 @@
1
1
  import envPaths from "env-paths";
2
2
  import { exec } from "node:child_process";
3
3
  import fs from "node:fs/promises";
4
+ import http from "node:http";
5
+ import https from "node:https";
4
6
  import os from "node:os";
7
+ import { URL } from "node:url";
5
8
  import path from "pathe";
6
9
  import pkg from "../../package.json" with { type: "json" };
7
10
  import type { Phase } from "../alchemy.ts";
8
11
  import { Scope } from "../scope.ts";
12
+ import { parseOption } from "./cli-args.ts";
9
13
  import { logger } from "./logger.ts";
10
14
  import { memoize } from "./memoize.ts";
11
15
 
@@ -170,9 +174,25 @@ export const collectData = memoize(async (): Promise<GenericTelemetryData> => {
170
174
  getRuntime(),
171
175
  getEnvironment(),
172
176
  ]);
177
+
178
+ const sessionId =
179
+ parseOption("--telemetry-session-id") ??
180
+ process.env.ALCHEMY_TELEMETRY_SESSION_ID ??
181
+ //@ts-expect-error
182
+ globalThis.ALCHEMY_TELEMETRY_SESSION_ID ??
183
+ crypto.randomUUID();
184
+
185
+ const referrer =
186
+ parseOption("--telemetry-ref") ??
187
+ process.env.ALCHEMY_TELEMETRY_REF ??
188
+ //@ts-expect-error
189
+ globalThis.ALCHEMY_TELEMETRY_REF ??
190
+ "";
191
+
173
192
  return {
174
193
  userId: userId ?? "",
175
- sessionId: crypto.randomUUID(),
194
+ sessionId,
195
+ referrer,
176
196
  platform: os.platform(),
177
197
  osVersion: os.release(),
178
198
  arch: os.arch(),
@@ -192,6 +212,7 @@ export const collectData = memoize(async (): Promise<GenericTelemetryData> => {
192
212
  export type GenericTelemetryData = {
193
213
  userId: string;
194
214
  sessionId: string;
215
+ referrer: string;
195
216
  platform: string;
196
217
  osVersion: string;
197
218
  arch: string;
@@ -287,7 +308,7 @@ export async function createAndSendEvent(
287
308
  ...(await collectData()),
288
309
  ...serializeError(error),
289
310
  };
290
- await fetch(TELEMETRY_API_URL, {
311
+ await fetchNoResponse(TELEMETRY_API_URL, {
291
312
  method: "POST",
292
313
  headers: {
293
314
  "Content-Type": "application/json",
@@ -326,3 +347,48 @@ function serializeError(error: Error | undefined) {
326
347
  errorStack: "",
327
348
  };
328
349
  }
350
+
351
+ async function fetchNoResponse(
352
+ url: string,
353
+ options: {
354
+ body?: string;
355
+ headers?: Record<string, string>;
356
+ method?: string;
357
+ } = {},
358
+ ) {
359
+ const parsedUrl = new URL(url);
360
+ const isHttps = parsedUrl.protocol === "https:";
361
+ const client = isHttps ? https : http;
362
+
363
+ const body = options.body || "";
364
+ const headers = {
365
+ ...options.headers,
366
+ "Content-Length": Buffer.byteLength(body),
367
+ };
368
+
369
+ const requestOptions = {
370
+ hostname: parsedUrl.hostname,
371
+ port: parsedUrl.port || (isHttps ? 443 : 80),
372
+ path: parsedUrl.pathname + parsedUrl.search,
373
+ method: options.method || "GET",
374
+ headers,
375
+ };
376
+
377
+ await new Promise<void>((resolve, reject) => {
378
+ const req = client.request(requestOptions);
379
+
380
+ req.on("error", (error) => {
381
+ reject(error);
382
+ });
383
+
384
+ if (body) {
385
+ req.write(body);
386
+ }
387
+
388
+ req.once("finish", () => {
389
+ resolve(void 0);
390
+ });
391
+
392
+ req.end();
393
+ });
394
+ }
@@ -0,0 +1,10 @@
1
+ export function validateResourceID(id: string, qualifier = "Resource"): void {
2
+ //todo(sam): during effect rewrite, this should be much more limiting
3
+ //todo: its hard to undo the flexibility we've offered to users now
4
+ if (!id) {
5
+ throw new Error(`${qualifier} ID cannot be an empty string: "${id}"`);
6
+ }
7
+ if (id.includes(":")) {
8
+ throw new Error(`${qualifier} ID cannot include colons: "${id}"`);
9
+ }
10
+ }
@@ -34,7 +34,7 @@ var h={async fetch(e,r){let n=new URL(e.url);n.host=r.TUNNEL_HOST;let l=new Head
34
34
  Alchemy</a>.</p>
35
35
  </div>
36
36
  <div class="bg-slate-200 px-5 py-3 flex flex-col w-full max-w-lg">
37
- <p class="text-sm text-slate-500">Alchemy 0.70.2</p>
37
+ <p class="text-sm text-slate-500">Alchemy 0.71.1</p>
38
38
  </div>
39
39
  </div>
40
40
  </body>