alchemy 0.69.1 → 0.70.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 (238) hide show
  1. package/bin/alchemy.js +3883 -3906
  2. package/bin/alchemy.ts +2 -0
  3. package/bin/commands/telemetry.ts +33 -0
  4. package/bin/services/execute-alchemy.ts +7 -0
  5. package/bin/trpc.ts +4 -9
  6. package/lib/alchemy.d.ts +7 -3
  7. package/lib/alchemy.d.ts.map +1 -1
  8. package/lib/alchemy.js +3 -15
  9. package/lib/alchemy.js.map +1 -1
  10. package/lib/apply.js +24 -9
  11. package/lib/apply.js.map +1 -1
  12. package/lib/aws/utils.d.ts +2 -1
  13. package/lib/aws/utils.d.ts.map +1 -1
  14. package/lib/aws/utils.js.map +1 -1
  15. package/lib/clickhouse/api/client.gen.d.ts +13 -0
  16. package/lib/clickhouse/api/client.gen.d.ts.map +1 -0
  17. package/lib/clickhouse/api/client.gen.js +7 -0
  18. package/lib/clickhouse/api/client.gen.js.map +1 -0
  19. package/lib/clickhouse/api/sdk.gen.d.ts +322 -0
  20. package/lib/clickhouse/api/sdk.gen.d.ts.map +1 -0
  21. package/lib/clickhouse/api/sdk.gen.js +683 -0
  22. package/lib/clickhouse/api/sdk.gen.js.map +1 -0
  23. package/lib/clickhouse/api/types.gen.d.ts +5030 -0
  24. package/lib/clickhouse/api/types.gen.d.ts.map +1 -0
  25. package/lib/clickhouse/api/types.gen.js +2 -0
  26. package/lib/clickhouse/api/types.gen.js.map +1 -0
  27. package/lib/clickhouse/api-key.d.ts +29 -0
  28. package/lib/clickhouse/api-key.d.ts.map +1 -0
  29. package/lib/clickhouse/api-key.js +83 -0
  30. package/lib/clickhouse/api-key.js.map +1 -0
  31. package/lib/clickhouse/api.d.ts +36 -0
  32. package/lib/clickhouse/api.d.ts.map +1 -0
  33. package/lib/clickhouse/api.js +48 -0
  34. package/lib/clickhouse/api.js.map +1 -0
  35. package/lib/clickhouse/index.d.ts +4 -0
  36. package/lib/clickhouse/index.d.ts.map +1 -0
  37. package/lib/clickhouse/index.js +4 -0
  38. package/lib/clickhouse/index.js.map +1 -0
  39. package/lib/clickhouse/organization.d.ts +16 -0
  40. package/lib/clickhouse/organization.d.ts.map +1 -0
  41. package/lib/clickhouse/organization.js +21 -0
  42. package/lib/clickhouse/organization.js.map +1 -0
  43. package/lib/clickhouse/service.d.ts +275 -0
  44. package/lib/clickhouse/service.d.ts.map +1 -0
  45. package/lib/clickhouse/service.js +274 -0
  46. package/lib/clickhouse/service.js.map +1 -0
  47. package/lib/cloudflare/account-api-token.d.ts.map +1 -1
  48. package/lib/cloudflare/account-api-token.js +1 -1
  49. package/lib/cloudflare/account-api-token.js.map +1 -1
  50. package/lib/cloudflare/api.d.ts.map +1 -1
  51. package/lib/cloudflare/api.js +2 -0
  52. package/lib/cloudflare/api.js.map +1 -1
  53. package/lib/cloudflare/bun-spa/bun-spa.d.ts +13 -0
  54. package/lib/cloudflare/bun-spa/bun-spa.d.ts.map +1 -0
  55. package/lib/cloudflare/bun-spa/bun-spa.js +95 -0
  56. package/lib/cloudflare/bun-spa/bun-spa.js.map +1 -0
  57. package/lib/cloudflare/compatibility-date.gen.d.ts +1 -1
  58. package/lib/cloudflare/compatibility-date.gen.js +1 -1
  59. package/lib/cloudflare/container.d.ts +11 -1
  60. package/lib/cloudflare/container.d.ts.map +1 -1
  61. package/lib/cloudflare/container.js.map +1 -1
  62. package/lib/cloudflare/index.d.ts +1 -0
  63. package/lib/cloudflare/index.d.ts.map +1 -1
  64. package/lib/cloudflare/index.js +1 -0
  65. package/lib/cloudflare/index.js.map +1 -1
  66. package/lib/cloudflare/miniflare/build-worker-options.d.ts.map +1 -1
  67. package/lib/cloudflare/miniflare/build-worker-options.js +33 -6
  68. package/lib/cloudflare/miniflare/build-worker-options.js.map +1 -1
  69. package/lib/cloudflare/miniflare/miniflare-controller.d.ts.map +1 -1
  70. package/lib/cloudflare/miniflare/miniflare-controller.js +2 -0
  71. package/lib/cloudflare/miniflare/miniflare-controller.js.map +1 -1
  72. package/lib/cloudflare/miniflare/miniflare-worker-proxy.d.ts +1 -1
  73. package/lib/cloudflare/miniflare/miniflare-worker-proxy.d.ts.map +1 -1
  74. package/lib/cloudflare/miniflare/miniflare-worker-proxy.js +36 -49
  75. package/lib/cloudflare/miniflare/miniflare-worker-proxy.js.map +1 -1
  76. package/lib/cloudflare/permission-groups.d.ts +2 -3
  77. package/lib/cloudflare/permission-groups.d.ts.map +1 -1
  78. package/lib/cloudflare/permission-groups.js +10 -15
  79. package/lib/cloudflare/permission-groups.js.map +1 -1
  80. package/lib/cloudflare/redwood/redwood.d.ts +1 -1
  81. package/lib/cloudflare/redwood/redwood.js +1 -1
  82. package/lib/cloudflare/util/filter-env-bindings.d.ts +62 -0
  83. package/lib/cloudflare/util/filter-env-bindings.d.ts.map +1 -0
  84. package/lib/cloudflare/util/filter-env-bindings.js +81 -0
  85. package/lib/cloudflare/util/filter-env-bindings.js.map +1 -0
  86. package/lib/cloudflare/website.d.ts +2 -2
  87. package/lib/cloudflare/website.d.ts.map +1 -1
  88. package/lib/cloudflare/website.js +6 -18
  89. package/lib/cloudflare/website.js.map +1 -1
  90. package/lib/cloudflare/worker-metadata.d.ts +1 -0
  91. package/lib/cloudflare/worker-metadata.d.ts.map +1 -1
  92. package/lib/cloudflare/worker-metadata.js +1 -0
  93. package/lib/cloudflare/worker-metadata.js.map +1 -1
  94. package/lib/cloudflare/worker.d.ts +11 -1
  95. package/lib/cloudflare/worker.d.ts.map +1 -1
  96. package/lib/cloudflare/worker.js.map +1 -1
  97. package/lib/cloudflare/wrangler.json.d.ts +8 -0
  98. package/lib/cloudflare/wrangler.json.d.ts.map +1 -1
  99. package/lib/cloudflare/wrangler.json.js +3 -4
  100. package/lib/cloudflare/wrangler.json.js.map +1 -1
  101. package/lib/coinbase/client.d.ts +54 -0
  102. package/lib/coinbase/client.d.ts.map +1 -0
  103. package/lib/coinbase/client.js +89 -0
  104. package/lib/coinbase/client.js.map +1 -0
  105. package/lib/coinbase/evm-account.d.ts +118 -0
  106. package/lib/coinbase/evm-account.d.ts.map +1 -0
  107. package/lib/coinbase/evm-account.js +198 -0
  108. package/lib/coinbase/evm-account.js.map +1 -0
  109. package/lib/coinbase/evm-smart-account.d.ts +122 -0
  110. package/lib/coinbase/evm-smart-account.d.ts.map +1 -0
  111. package/lib/coinbase/evm-smart-account.js +213 -0
  112. package/lib/coinbase/evm-smart-account.js.map +1 -0
  113. package/lib/coinbase/faucet.d.ts +11 -0
  114. package/lib/coinbase/faucet.d.ts.map +1 -0
  115. package/lib/coinbase/faucet.js +146 -0
  116. package/lib/coinbase/faucet.js.map +1 -0
  117. package/lib/coinbase/index.d.ts +4 -0
  118. package/lib/coinbase/index.d.ts.map +1 -0
  119. package/lib/coinbase/index.js +4 -0
  120. package/lib/coinbase/index.js.map +1 -0
  121. package/lib/coinbase/types.d.ts +28 -0
  122. package/lib/coinbase/types.d.ts.map +1 -0
  123. package/lib/coinbase/types.js +4 -0
  124. package/lib/{util/telemetry → coinbase}/types.js.map +1 -1
  125. package/lib/coinbase/utils.d.ts +13 -0
  126. package/lib/coinbase/utils.d.ts.map +1 -0
  127. package/lib/coinbase/utils.js +17 -0
  128. package/lib/coinbase/utils.js.map +1 -0
  129. package/lib/neon/api/types.gen.d.ts +7 -2
  130. package/lib/neon/api/types.gen.d.ts.map +1 -1
  131. package/lib/planetscale/api/types.gen.d.ts +20 -4
  132. package/lib/planetscale/api/types.gen.d.ts.map +1 -1
  133. package/lib/planetscale/api.d.ts.map +1 -1
  134. package/lib/planetscale/api.js +1 -0
  135. package/lib/planetscale/api.js.map +1 -1
  136. package/lib/planetscale/password.d.ts.map +1 -1
  137. package/lib/planetscale/password.js +1 -13
  138. package/lib/planetscale/password.js.map +1 -1
  139. package/lib/resource.d.ts.map +1 -1
  140. package/lib/resource.js +7 -3
  141. package/lib/resource.js.map +1 -1
  142. package/lib/scope.d.ts +9 -9
  143. package/lib/scope.d.ts.map +1 -1
  144. package/lib/scope.js +18 -37
  145. package/lib/scope.js.map +1 -1
  146. package/lib/state/instrumented-state-store.d.ts +1 -3
  147. package/lib/state/instrumented-state-store.d.ts.map +1 -1
  148. package/lib/state/instrumented-state-store.js +19 -21
  149. package/lib/state/instrumented-state-store.js.map +1 -1
  150. package/lib/test/bun.d.ts.map +1 -1
  151. package/lib/test/bun.js +1 -2
  152. package/lib/test/bun.js.map +1 -1
  153. package/lib/test/vitest.d.ts.map +1 -1
  154. package/lib/test/vitest.js +1 -2
  155. package/lib/test/vitest.js.map +1 -1
  156. package/lib/util/diff.d.ts +5 -0
  157. package/lib/util/diff.d.ts.map +1 -0
  158. package/lib/util/diff.js +14 -0
  159. package/lib/util/diff.js.map +1 -0
  160. package/lib/util/idempotent-spawn.js +1 -1
  161. package/lib/util/idempotent-spawn.js.map +1 -1
  162. package/lib/util/telemetry.d.ts +53 -0
  163. package/lib/util/telemetry.d.ts.map +1 -0
  164. package/lib/util/telemetry.js +215 -0
  165. package/lib/util/telemetry.js.map +1 -0
  166. package/package.json +19 -1
  167. package/src/alchemy.ts +10 -20
  168. package/src/apply.ts +29 -12
  169. package/src/aws/utils.ts +2 -1
  170. package/src/clickhouse/api/client.gen.ts +28 -0
  171. package/src/clickhouse/api/sdk.gen.ts +1286 -0
  172. package/src/clickhouse/api/types.gen.ts +5898 -0
  173. package/src/clickhouse/api-key.ts +136 -0
  174. package/src/clickhouse/api.ts +84 -0
  175. package/src/clickhouse/index.ts +3 -0
  176. package/src/clickhouse/organization.ts +31 -0
  177. package/src/clickhouse/service.ts +668 -0
  178. package/src/cloudflare/account-api-token.ts +1 -4
  179. package/src/cloudflare/api.ts +2 -0
  180. package/src/cloudflare/bun-spa/bun-spa.ts +136 -0
  181. package/src/cloudflare/compatibility-date.gen.ts +1 -1
  182. package/src/cloudflare/container.ts +20 -1
  183. package/src/cloudflare/index.ts +1 -0
  184. package/src/cloudflare/miniflare/build-worker-options.ts +38 -8
  185. package/src/cloudflare/miniflare/miniflare-controller.ts +2 -0
  186. package/src/cloudflare/miniflare/miniflare-worker-proxy.ts +41 -58
  187. package/src/cloudflare/permission-groups.ts +21 -49
  188. package/src/cloudflare/redwood/redwood.ts +1 -1
  189. package/src/cloudflare/util/filter-env-bindings.ts +96 -0
  190. package/src/cloudflare/website.ts +11 -24
  191. package/src/cloudflare/worker-metadata.ts +2 -0
  192. package/src/cloudflare/worker.ts +12 -1
  193. package/src/cloudflare/wrangler.json.ts +12 -8
  194. package/src/coinbase/client.ts +146 -0
  195. package/src/coinbase/evm-account.ts +317 -0
  196. package/src/coinbase/evm-smart-account.ts +339 -0
  197. package/src/coinbase/faucet.ts +173 -0
  198. package/src/coinbase/index.ts +3 -0
  199. package/src/coinbase/types.ts +33 -0
  200. package/src/coinbase/utils.ts +19 -0
  201. package/src/neon/api/types.gen.ts +13 -1
  202. package/src/planetscale/api/types.gen.ts +22 -2
  203. package/src/planetscale/api.ts +1 -0
  204. package/src/planetscale/password.ts +1 -14
  205. package/src/resource.ts +11 -4
  206. package/src/scope.ts +29 -45
  207. package/src/state/instrumented-state-store.ts +27 -26
  208. package/src/test/bun.ts +1 -2
  209. package/src/test/vitest.ts +1 -2
  210. package/src/util/diff.ts +14 -0
  211. package/src/util/idempotent-spawn.ts +1 -1
  212. package/src/util/telemetry.ts +328 -0
  213. package/templates/tanstack-start/package.json +2 -2
  214. package/workers/tunnel-proxy.js +1 -1
  215. package/lib/util/telemetry/client.d.ts +0 -31
  216. package/lib/util/telemetry/client.d.ts.map +0 -1
  217. package/lib/util/telemetry/client.js +0 -121
  218. package/lib/util/telemetry/client.js.map +0 -1
  219. package/lib/util/telemetry/constants.d.ts +0 -5
  220. package/lib/util/telemetry/constants.d.ts.map +0 -1
  221. package/lib/util/telemetry/constants.js +0 -8
  222. package/lib/util/telemetry/constants.js.map +0 -1
  223. package/lib/util/telemetry/context.d.ts +0 -15
  224. package/lib/util/telemetry/context.d.ts.map +0 -1
  225. package/lib/util/telemetry/context.js +0 -128
  226. package/lib/util/telemetry/context.js.map +0 -1
  227. package/lib/util/telemetry/index.d.ts +0 -3
  228. package/lib/util/telemetry/index.d.ts.map +0 -1
  229. package/lib/util/telemetry/index.js +0 -3
  230. package/lib/util/telemetry/index.js.map +0 -1
  231. package/lib/util/telemetry/types.d.ts +0 -68
  232. package/lib/util/telemetry/types.d.ts.map +0 -1
  233. package/lib/util/telemetry/types.js +0 -1
  234. package/src/util/telemetry/client.ts +0 -156
  235. package/src/util/telemetry/constants.ts +0 -13
  236. package/src/util/telemetry/context.ts +0 -154
  237. package/src/util/telemetry/index.ts +0 -2
  238. package/src/util/telemetry/types.ts +0 -105
@@ -1,8 +1,8 @@
1
- import { isDeepStrictEqual } from "node:util";
2
1
  import { alchemy } from "../alchemy.ts";
3
2
  import type { Context } from "../context.ts";
4
3
  import { Resource } from "../resource.ts";
5
4
  import type { Secret } from "../secret.ts";
5
+ import { diff } from "../util/diff.ts";
6
6
  import { lowercaseId } from "../util/nanoid.ts";
7
7
  import { createPlanetScaleClient, type PlanetScaleProps } from "./api.ts";
8
8
  import type { Branch } from "./branch.ts";
@@ -357,16 +357,3 @@ export const Password = Resource(
357
357
  };
358
358
  },
359
359
  );
360
-
361
- /**
362
- * Returns an array of keys in `b` that are different from `a`.
363
- */
364
- const diff = <T>(a: T, b: NoInfer<T>) => {
365
- const keys: (keyof T)[] = [];
366
- for (const key in a) {
367
- if (!isDeepStrictEqual(a[key], b[key])) {
368
- keys.push(key);
369
- }
370
- }
371
- return keys;
372
- };
package/src/resource.ts CHANGED
@@ -2,6 +2,7 @@ import { apply } from "./apply.ts";
2
2
  import type { Context } from "./context.ts";
3
3
  import { DestroyStrategy } from "./destroy.ts";
4
4
  import { Scope as _Scope, type Scope } from "./scope.ts";
5
+ import { createAndSendEvent } from "./util/telemetry.ts";
5
6
 
6
7
  declare global {
7
8
  var ALCHEMY_PROVIDERS: Map<ResourceKind, Provider<string, any>>;
@@ -178,11 +179,17 @@ export function Resource<
178
179
  const error = new Error(
179
180
  `Resource ${resourceID} already exists in the stack and is of a different type: '${otherResource?.[ResourceKind]}' !== '${type}'`,
180
181
  );
181
- scope.telemetryClient.record({
182
- event: "resource.error",
183
- resource: type,
182
+ createAndSendEvent(
183
+ {
184
+ event: "resource.error",
185
+ resource: type,
186
+ phase: scope.phase,
187
+ status: "unknown",
188
+ duration: 0,
189
+ replaced: false,
190
+ },
184
191
  error,
185
- });
192
+ );
186
193
  throw error;
187
194
  }
188
195
  }
package/src/scope.ts CHANGED
@@ -29,7 +29,7 @@ import {
29
29
  import { logger } from "./util/logger.ts";
30
30
  import { AsyncMutex } from "./util/mutex.ts";
31
31
  import { ALCHEMY_ROOT } from "./util/root-dir.ts";
32
- import type { ITelemetryClient } from "./util/telemetry/client.ts";
32
+ import { createAndSendEvent } from "./util/telemetry.ts";
33
33
 
34
34
  export class RootScopeStateAttemptError extends Error {
35
35
  constructor() {
@@ -76,10 +76,11 @@ export interface ScopeOptions extends ProviderCredentials {
76
76
  */
77
77
  destroyStrategy?: DestroyStrategy;
78
78
  /**
79
- * The telemetry client to use for the scope.
79
+ * Whether to disable telemetry for the scope.
80
80
  *
81
+ * @default false
81
82
  */
82
- telemetryClient?: ITelemetryClient;
83
+ noTrack?: boolean;
83
84
  /**
84
85
  * The logger to use for the scope.
85
86
  */
@@ -102,6 +103,10 @@ export interface ScopeOptions extends ProviderCredentials {
102
103
  * @default process.cwd()
103
104
  */
104
105
  rootDir?: string;
106
+ /**
107
+ * The Alchemy profile to use for authoriziing requests.
108
+ */
109
+ profile?: string;
105
110
  /**
106
111
  * Whether this is the application that was selected with `--app`
107
112
  *
@@ -197,11 +202,12 @@ export class Scope {
197
202
  public readonly adopt: boolean;
198
203
  public readonly destroyStrategy: DestroyStrategy;
199
204
  public readonly logger: LoggerApi;
200
- public readonly telemetryClient: ITelemetryClient;
205
+ public readonly noTrack: boolean;
201
206
  public readonly dataMutex: AsyncMutex;
202
207
  public readonly rootDir: string;
203
208
  public readonly dotAlchemy: string;
204
209
  public readonly isSelected: boolean | undefined;
210
+ public readonly profile: string | undefined;
205
211
 
206
212
  // Provider credentials for scope-level credential overrides
207
213
  public readonly providerCredentials: ProviderCredentials;
@@ -235,12 +241,13 @@ export class Scope {
235
241
  tunnel,
236
242
  force,
237
243
  destroyStrategy,
238
- telemetryClient,
239
244
  logger,
240
245
  adopt,
241
246
  dotAlchemy,
242
247
  rootDir,
243
248
  isSelected,
249
+ noTrack,
250
+ profile,
244
251
  ...providerCredentials
245
252
  } = options;
246
253
 
@@ -267,12 +274,14 @@ export class Scope {
267
274
  }
268
275
 
269
276
  this.stage = stage ?? this.parent?.stage ?? DEFAULT_STAGE;
277
+ this.profile = profile ?? this.parent?.profile;
270
278
  this.parent?.children.set(this.scopeName!, this);
271
279
  this.quiet = quiet ?? this.parent?.quiet ?? false;
272
280
  if (this.parent && !this.scopeName) {
273
281
  throw new Error("Scope name is required when creating a child scope");
274
282
  }
275
283
  this.password = password ?? this.parent?.password;
284
+ this.noTrack = noTrack ?? this.parent?.noTrack ?? false;
276
285
  const resolvedPhase = phase ?? this.parent?.phase;
277
286
  if (resolvedPhase === undefined) {
278
287
  throw new Error("Phase is required");
@@ -307,14 +316,7 @@ export class Scope {
307
316
  stateStore ??
308
317
  this.parent?.stateStore ??
309
318
  ((scope) => new FileSystemStateStore(scope));
310
- this.telemetryClient = telemetryClient ?? this.parent?.telemetryClient!;
311
- this.state = new InstrumentedStateStore(
312
- this.stateStore(this),
313
- this.telemetryClient,
314
- );
315
- if (!telemetryClient && !this.parent?.telemetryClient) {
316
- throw new Error("Telemetry client is required");
317
- }
319
+ this.state = new InstrumentedStateStore(this.stateStore(this));
318
320
  this.dataMutex = new AsyncMutex();
319
321
  }
320
322
 
@@ -413,12 +415,7 @@ export class Scope {
413
415
  }
414
416
 
415
417
  public async init() {
416
- await Promise.all([
417
- this.state.init?.(),
418
- this.telemetryClient.ready.catch((error) => {
419
- this.logger.warn("Telemetry initialization failed:", error);
420
- }),
421
- ]);
418
+ await Promise.all([this.state.init?.()]);
422
419
  }
423
420
 
424
421
  public async deinit() {
@@ -515,26 +512,15 @@ export class Scope {
515
512
  return this.finalize();
516
513
  }
517
514
 
518
- /**
519
- * The telemetry client for the root scope.
520
- * This is used so that app-level hooks are only called once.
521
- */
522
- private get rootTelemetryClient(): ITelemetryClient | null {
523
- if (!this.parent) {
524
- return this.telemetryClient;
525
- }
526
- return null;
527
- }
528
-
529
515
  public async finalize(options?: { force?: boolean; noop?: boolean }) {
530
516
  const shouldForce =
531
517
  options?.force ||
532
518
  this.parent === undefined ||
533
519
  this?.parent?.scopeName === this.root.scopeName;
534
520
  if (this.phase === "read") {
535
- this.rootTelemetryClient?.record({
536
- event: "app.success",
537
- elapsed: performance.now() - this.startedAt,
521
+ createAndSendEvent({
522
+ event: "alchemy.success",
523
+ duration: performance.now() - this.startedAt,
538
524
  });
539
525
  return;
540
526
  }
@@ -583,23 +569,21 @@ export class Scope {
583
569
  force: shouldForce,
584
570
  noop: options?.noop,
585
571
  });
586
- this.rootTelemetryClient?.record({
587
- event: "app.success",
588
- elapsed: performance.now() - this.startedAt,
572
+ createAndSendEvent({
573
+ event: "alchemy.success",
574
+ duration: performance.now() - this.startedAt,
589
575
  });
590
576
  } else if (this.isErrored) {
591
577
  this.logger.warn("Scope is in error, skipping finalize");
592
- this.rootTelemetryClient?.record({
593
- event: "app.error",
594
- error: new Error("Scope failed"),
595
- elapsed: performance.now() - this.startedAt,
596
- });
578
+ createAndSendEvent(
579
+ {
580
+ event: "alchemy.error",
581
+ duration: performance.now() - this.startedAt,
582
+ },
583
+ new Error("Scope failed"),
584
+ );
597
585
  }
598
586
 
599
- await this.rootTelemetryClient?.finalize()?.catch((error) => {
600
- this.logger.warn("Telemetry finalization failed:", error);
601
- });
602
-
603
587
  if (!this.parent && process.env.ALCHEMY_TEST_KILL_ON_FINALIZE) {
604
588
  await this.cleanup();
605
589
  process.exit(0);
@@ -1,6 +1,8 @@
1
1
  import type { State, StateStore } from "../state.ts";
2
- import type { ITelemetryClient } from "../util/telemetry/client.ts";
3
- import type { Telemetry } from "../util/telemetry/types.ts";
2
+ import {
3
+ createAndSendEvent,
4
+ type StateStoreTelemetryData,
5
+ } from "../util/telemetry.ts";
4
6
 
5
7
  //todo(michael): we should also handle serde here
6
8
  export class InstrumentedStateStore<T extends StateStore>
@@ -9,17 +11,15 @@ export class InstrumentedStateStore<T extends StateStore>
9
11
  /** @internal */
10
12
  __phantom?: T;
11
13
  private readonly stateStore: StateStore;
12
- private readonly telemetryClient: ITelemetryClient;
13
14
  private readonly stateStoreClass: string;
14
15
 
15
- constructor(stateStore: StateStore, telemetryClient: ITelemetryClient) {
16
+ constructor(stateStore: StateStore) {
16
17
  this.stateStore = stateStore;
17
- this.telemetryClient = telemetryClient;
18
18
  this.stateStoreClass = stateStore.constructor.name;
19
19
  }
20
20
 
21
21
  private async callWithTelemetry<T>(
22
- event: Telemetry.StateStoreEvent["event"],
22
+ event: StateStoreTelemetryData["event"],
23
23
  fn: () => Promise<T>,
24
24
  ): Promise<T> {
25
25
  const start = performance.now();
@@ -30,17 +30,18 @@ export class InstrumentedStateStore<T extends StateStore>
30
30
  error = err;
31
31
  throw err;
32
32
  } finally {
33
- this.telemetryClient.record({
34
- event,
35
- stateStoreClass: this.stateStoreClass,
36
- elapsed: performance.now() - start,
37
- error:
38
- error instanceof Error
39
- ? error
40
- : error
41
- ? new Error(String(error))
42
- : undefined,
43
- });
33
+ createAndSendEvent(
34
+ {
35
+ event,
36
+ stateStore: this.stateStoreClass,
37
+ duration: performance.now() - start,
38
+ },
39
+ error instanceof Error
40
+ ? error
41
+ : error
42
+ ? new Error(String(error))
43
+ : undefined,
44
+ );
44
45
  }
45
46
  }
46
47
 
@@ -49,7 +50,7 @@ export class InstrumentedStateStore<T extends StateStore>
49
50
  return;
50
51
  }
51
52
  await this.callWithTelemetry(
52
- "stateStore.init",
53
+ "statestore.init",
53
54
  this.stateStore.init.bind(this.stateStore),
54
55
  );
55
56
  }
@@ -58,49 +59,49 @@ export class InstrumentedStateStore<T extends StateStore>
58
59
  return;
59
60
  }
60
61
  await this.callWithTelemetry(
61
- "stateStore.deinit",
62
+ "statestore.deinit",
62
63
  this.stateStore.deinit.bind(this.stateStore),
63
64
  );
64
65
  }
65
66
  async list() {
66
67
  return await this.callWithTelemetry(
67
- "stateStore.list",
68
+ "statestore.list",
68
69
  this.stateStore.list.bind(this.stateStore),
69
70
  );
70
71
  }
71
72
  async count() {
72
73
  return await this.callWithTelemetry(
73
- "stateStore.count",
74
+ "statestore.count",
74
75
  this.stateStore.count.bind(this.stateStore),
75
76
  );
76
77
  }
77
78
  async get(key: string) {
78
79
  return await this.callWithTelemetry(
79
- "stateStore.get",
80
+ "statestore.get",
80
81
  this.stateStore.get.bind(this.stateStore, key),
81
82
  );
82
83
  }
83
84
  async getBatch(ids: string[]) {
84
85
  return await this.callWithTelemetry(
85
- "stateStore.getBatch",
86
+ "statestore.getBatch",
86
87
  this.stateStore.getBatch.bind(this.stateStore, ids),
87
88
  );
88
89
  }
89
90
  async all() {
90
91
  return await this.callWithTelemetry(
91
- "stateStore.all",
92
+ "statestore.all",
92
93
  this.stateStore.all.bind(this.stateStore),
93
94
  );
94
95
  }
95
96
  async set(key: string, value: State) {
96
97
  await this.callWithTelemetry(
97
- "stateStore.set",
98
+ "statestore.set",
98
99
  this.stateStore.set.bind(this.stateStore, key, value),
99
100
  );
100
101
  }
101
102
  async delete(key: string) {
102
103
  await this.callWithTelemetry(
103
- "stateStore.delete",
104
+ "statestore.delete",
104
105
  this.stateStore.delete.bind(this.stateStore, key),
105
106
  );
106
107
  }
package/src/test/bun.ts CHANGED
@@ -4,7 +4,6 @@ import { afterAll, beforeAll, it } from "bun:test";
4
4
  import path from "node:path";
5
5
  import { alchemy } from "../alchemy.ts";
6
6
  import { Scope } from "../scope.ts";
7
- import { NoopTelemetryClient } from "../util/telemetry/index.ts";
8
7
  import type { TestOptions } from "./options.ts";
9
8
 
10
9
  /**
@@ -103,7 +102,7 @@ export function test(meta: ImportMeta, defaultOptions?: TestOptions): test {
103
102
  // parent: globalTestScope,
104
103
  stateStore: defaultOptions?.stateStore,
105
104
  phase: "up",
106
- telemetryClient: new NoopTelemetryClient(),
105
+ noTrack: true,
107
106
  local: defaultOptions.local,
108
107
  });
109
108
 
@@ -8,7 +8,6 @@ import {
8
8
  FileSystemStateStore,
9
9
  SQLiteStateStore,
10
10
  } from "../state/index.ts";
11
- import { NoopTelemetryClient } from "../util/telemetry/client.ts";
12
11
  import type { TestOptions } from "./options.ts";
13
12
 
14
13
  /**
@@ -132,7 +131,7 @@ export function test(
132
131
  scopeName: `${defaultOptions.prefix ? `${defaultOptions.prefix}-` : ""}${path.basename(meta.filename)}`,
133
132
  stateStore: defaultOptions?.stateStore,
134
133
  phase: "up",
135
- telemetryClient: new NoopTelemetryClient(),
134
+ noTrack: true,
136
135
  quiet: defaultOptions.quiet,
137
136
  password: process.env.ALCHEMY_PASSWORD,
138
137
  local: defaultOptions.local,
@@ -0,0 +1,14 @@
1
+ import { isDeepStrictEqual } from "node:util";
2
+
3
+ /**
4
+ * Returns an array of keys in `b` that are different from `a`.
5
+ */
6
+ export const diff = <T>(a: T, b: NoInfer<T>) => {
7
+ const keys: (keyof T)[] = [];
8
+ for (const key in a) {
9
+ if (!isDeepStrictEqual(a[key], b[key])) {
10
+ keys.push(key);
11
+ }
12
+ }
13
+ return keys;
14
+ };
@@ -112,7 +112,7 @@ export async function idempotentSpawn({
112
112
  const child = spawn(cmd, {
113
113
  shell: true,
114
114
  cwd,
115
- stdio: ["ignore", out.fd, out.fd], // stdout/stderr -> files (OS-level)
115
+ stdio: ["inherit", out.fd, out.fd], // stdout/stderr -> files (OS-level)
116
116
  env,
117
117
  detached: false,
118
118
  });