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.
- package/bin/alchemy.js +3883 -3906
- package/bin/alchemy.ts +2 -0
- package/bin/commands/telemetry.ts +33 -0
- package/bin/services/execute-alchemy.ts +7 -0
- package/bin/trpc.ts +4 -9
- package/lib/alchemy.d.ts +7 -3
- package/lib/alchemy.d.ts.map +1 -1
- package/lib/alchemy.js +3 -15
- package/lib/alchemy.js.map +1 -1
- package/lib/apply.js +24 -9
- package/lib/apply.js.map +1 -1
- package/lib/aws/utils.d.ts +2 -1
- package/lib/aws/utils.d.ts.map +1 -1
- package/lib/aws/utils.js.map +1 -1
- package/lib/clickhouse/api/client.gen.d.ts +13 -0
- package/lib/clickhouse/api/client.gen.d.ts.map +1 -0
- package/lib/clickhouse/api/client.gen.js +7 -0
- package/lib/clickhouse/api/client.gen.js.map +1 -0
- package/lib/clickhouse/api/sdk.gen.d.ts +322 -0
- package/lib/clickhouse/api/sdk.gen.d.ts.map +1 -0
- package/lib/clickhouse/api/sdk.gen.js +683 -0
- package/lib/clickhouse/api/sdk.gen.js.map +1 -0
- package/lib/clickhouse/api/types.gen.d.ts +5030 -0
- package/lib/clickhouse/api/types.gen.d.ts.map +1 -0
- package/lib/clickhouse/api/types.gen.js +2 -0
- package/lib/clickhouse/api/types.gen.js.map +1 -0
- package/lib/clickhouse/api-key.d.ts +29 -0
- package/lib/clickhouse/api-key.d.ts.map +1 -0
- package/lib/clickhouse/api-key.js +83 -0
- package/lib/clickhouse/api-key.js.map +1 -0
- package/lib/clickhouse/api.d.ts +36 -0
- package/lib/clickhouse/api.d.ts.map +1 -0
- package/lib/clickhouse/api.js +48 -0
- package/lib/clickhouse/api.js.map +1 -0
- package/lib/clickhouse/index.d.ts +4 -0
- package/lib/clickhouse/index.d.ts.map +1 -0
- package/lib/clickhouse/index.js +4 -0
- package/lib/clickhouse/index.js.map +1 -0
- package/lib/clickhouse/organization.d.ts +16 -0
- package/lib/clickhouse/organization.d.ts.map +1 -0
- package/lib/clickhouse/organization.js +21 -0
- package/lib/clickhouse/organization.js.map +1 -0
- package/lib/clickhouse/service.d.ts +275 -0
- package/lib/clickhouse/service.d.ts.map +1 -0
- package/lib/clickhouse/service.js +274 -0
- package/lib/clickhouse/service.js.map +1 -0
- package/lib/cloudflare/account-api-token.d.ts.map +1 -1
- package/lib/cloudflare/account-api-token.js +1 -1
- package/lib/cloudflare/account-api-token.js.map +1 -1
- package/lib/cloudflare/api.d.ts.map +1 -1
- package/lib/cloudflare/api.js +2 -0
- package/lib/cloudflare/api.js.map +1 -1
- package/lib/cloudflare/bun-spa/bun-spa.d.ts +13 -0
- package/lib/cloudflare/bun-spa/bun-spa.d.ts.map +1 -0
- package/lib/cloudflare/bun-spa/bun-spa.js +95 -0
- package/lib/cloudflare/bun-spa/bun-spa.js.map +1 -0
- package/lib/cloudflare/compatibility-date.gen.d.ts +1 -1
- package/lib/cloudflare/compatibility-date.gen.js +1 -1
- package/lib/cloudflare/container.d.ts +11 -1
- package/lib/cloudflare/container.d.ts.map +1 -1
- package/lib/cloudflare/container.js.map +1 -1
- package/lib/cloudflare/index.d.ts +1 -0
- package/lib/cloudflare/index.d.ts.map +1 -1
- package/lib/cloudflare/index.js +1 -0
- package/lib/cloudflare/index.js.map +1 -1
- package/lib/cloudflare/miniflare/build-worker-options.d.ts.map +1 -1
- package/lib/cloudflare/miniflare/build-worker-options.js +33 -6
- package/lib/cloudflare/miniflare/build-worker-options.js.map +1 -1
- package/lib/cloudflare/miniflare/miniflare-controller.d.ts.map +1 -1
- package/lib/cloudflare/miniflare/miniflare-controller.js +2 -0
- package/lib/cloudflare/miniflare/miniflare-controller.js.map +1 -1
- package/lib/cloudflare/miniflare/miniflare-worker-proxy.d.ts +1 -1
- package/lib/cloudflare/miniflare/miniflare-worker-proxy.d.ts.map +1 -1
- package/lib/cloudflare/miniflare/miniflare-worker-proxy.js +36 -49
- package/lib/cloudflare/miniflare/miniflare-worker-proxy.js.map +1 -1
- package/lib/cloudflare/permission-groups.d.ts +2 -3
- package/lib/cloudflare/permission-groups.d.ts.map +1 -1
- package/lib/cloudflare/permission-groups.js +10 -15
- package/lib/cloudflare/permission-groups.js.map +1 -1
- package/lib/cloudflare/redwood/redwood.d.ts +1 -1
- package/lib/cloudflare/redwood/redwood.js +1 -1
- package/lib/cloudflare/util/filter-env-bindings.d.ts +62 -0
- package/lib/cloudflare/util/filter-env-bindings.d.ts.map +1 -0
- package/lib/cloudflare/util/filter-env-bindings.js +81 -0
- package/lib/cloudflare/util/filter-env-bindings.js.map +1 -0
- package/lib/cloudflare/website.d.ts +2 -2
- package/lib/cloudflare/website.d.ts.map +1 -1
- package/lib/cloudflare/website.js +6 -18
- package/lib/cloudflare/website.js.map +1 -1
- package/lib/cloudflare/worker-metadata.d.ts +1 -0
- package/lib/cloudflare/worker-metadata.d.ts.map +1 -1
- package/lib/cloudflare/worker-metadata.js +1 -0
- package/lib/cloudflare/worker-metadata.js.map +1 -1
- package/lib/cloudflare/worker.d.ts +11 -1
- package/lib/cloudflare/worker.d.ts.map +1 -1
- package/lib/cloudflare/worker.js.map +1 -1
- package/lib/cloudflare/wrangler.json.d.ts +8 -0
- package/lib/cloudflare/wrangler.json.d.ts.map +1 -1
- package/lib/cloudflare/wrangler.json.js +3 -4
- package/lib/cloudflare/wrangler.json.js.map +1 -1
- package/lib/coinbase/client.d.ts +54 -0
- package/lib/coinbase/client.d.ts.map +1 -0
- package/lib/coinbase/client.js +89 -0
- package/lib/coinbase/client.js.map +1 -0
- package/lib/coinbase/evm-account.d.ts +118 -0
- package/lib/coinbase/evm-account.d.ts.map +1 -0
- package/lib/coinbase/evm-account.js +198 -0
- package/lib/coinbase/evm-account.js.map +1 -0
- package/lib/coinbase/evm-smart-account.d.ts +122 -0
- package/lib/coinbase/evm-smart-account.d.ts.map +1 -0
- package/lib/coinbase/evm-smart-account.js +213 -0
- package/lib/coinbase/evm-smart-account.js.map +1 -0
- package/lib/coinbase/faucet.d.ts +11 -0
- package/lib/coinbase/faucet.d.ts.map +1 -0
- package/lib/coinbase/faucet.js +146 -0
- package/lib/coinbase/faucet.js.map +1 -0
- package/lib/coinbase/index.d.ts +4 -0
- package/lib/coinbase/index.d.ts.map +1 -0
- package/lib/coinbase/index.js +4 -0
- package/lib/coinbase/index.js.map +1 -0
- package/lib/coinbase/types.d.ts +28 -0
- package/lib/coinbase/types.d.ts.map +1 -0
- package/lib/coinbase/types.js +4 -0
- package/lib/{util/telemetry → coinbase}/types.js.map +1 -1
- package/lib/coinbase/utils.d.ts +13 -0
- package/lib/coinbase/utils.d.ts.map +1 -0
- package/lib/coinbase/utils.js +17 -0
- package/lib/coinbase/utils.js.map +1 -0
- package/lib/neon/api/types.gen.d.ts +7 -2
- package/lib/neon/api/types.gen.d.ts.map +1 -1
- package/lib/planetscale/api/types.gen.d.ts +20 -4
- package/lib/planetscale/api/types.gen.d.ts.map +1 -1
- package/lib/planetscale/api.d.ts.map +1 -1
- package/lib/planetscale/api.js +1 -0
- package/lib/planetscale/api.js.map +1 -1
- package/lib/planetscale/password.d.ts.map +1 -1
- package/lib/planetscale/password.js +1 -13
- package/lib/planetscale/password.js.map +1 -1
- package/lib/resource.d.ts.map +1 -1
- package/lib/resource.js +7 -3
- package/lib/resource.js.map +1 -1
- package/lib/scope.d.ts +9 -9
- package/lib/scope.d.ts.map +1 -1
- package/lib/scope.js +18 -37
- package/lib/scope.js.map +1 -1
- package/lib/state/instrumented-state-store.d.ts +1 -3
- package/lib/state/instrumented-state-store.d.ts.map +1 -1
- package/lib/state/instrumented-state-store.js +19 -21
- package/lib/state/instrumented-state-store.js.map +1 -1
- package/lib/test/bun.d.ts.map +1 -1
- package/lib/test/bun.js +1 -2
- package/lib/test/bun.js.map +1 -1
- package/lib/test/vitest.d.ts.map +1 -1
- package/lib/test/vitest.js +1 -2
- package/lib/test/vitest.js.map +1 -1
- package/lib/util/diff.d.ts +5 -0
- package/lib/util/diff.d.ts.map +1 -0
- package/lib/util/diff.js +14 -0
- package/lib/util/diff.js.map +1 -0
- package/lib/util/idempotent-spawn.js +1 -1
- package/lib/util/idempotent-spawn.js.map +1 -1
- package/lib/util/telemetry.d.ts +53 -0
- package/lib/util/telemetry.d.ts.map +1 -0
- package/lib/util/telemetry.js +215 -0
- package/lib/util/telemetry.js.map +1 -0
- package/package.json +19 -1
- package/src/alchemy.ts +10 -20
- package/src/apply.ts +29 -12
- package/src/aws/utils.ts +2 -1
- package/src/clickhouse/api/client.gen.ts +28 -0
- package/src/clickhouse/api/sdk.gen.ts +1286 -0
- package/src/clickhouse/api/types.gen.ts +5898 -0
- package/src/clickhouse/api-key.ts +136 -0
- package/src/clickhouse/api.ts +84 -0
- package/src/clickhouse/index.ts +3 -0
- package/src/clickhouse/organization.ts +31 -0
- package/src/clickhouse/service.ts +668 -0
- package/src/cloudflare/account-api-token.ts +1 -4
- package/src/cloudflare/api.ts +2 -0
- package/src/cloudflare/bun-spa/bun-spa.ts +136 -0
- package/src/cloudflare/compatibility-date.gen.ts +1 -1
- package/src/cloudflare/container.ts +20 -1
- package/src/cloudflare/index.ts +1 -0
- package/src/cloudflare/miniflare/build-worker-options.ts +38 -8
- package/src/cloudflare/miniflare/miniflare-controller.ts +2 -0
- package/src/cloudflare/miniflare/miniflare-worker-proxy.ts +41 -58
- package/src/cloudflare/permission-groups.ts +21 -49
- package/src/cloudflare/redwood/redwood.ts +1 -1
- package/src/cloudflare/util/filter-env-bindings.ts +96 -0
- package/src/cloudflare/website.ts +11 -24
- package/src/cloudflare/worker-metadata.ts +2 -0
- package/src/cloudflare/worker.ts +12 -1
- package/src/cloudflare/wrangler.json.ts +12 -8
- package/src/coinbase/client.ts +146 -0
- package/src/coinbase/evm-account.ts +317 -0
- package/src/coinbase/evm-smart-account.ts +339 -0
- package/src/coinbase/faucet.ts +173 -0
- package/src/coinbase/index.ts +3 -0
- package/src/coinbase/types.ts +33 -0
- package/src/coinbase/utils.ts +19 -0
- package/src/neon/api/types.gen.ts +13 -1
- package/src/planetscale/api/types.gen.ts +22 -2
- package/src/planetscale/api.ts +1 -0
- package/src/planetscale/password.ts +1 -14
- package/src/resource.ts +11 -4
- package/src/scope.ts +29 -45
- package/src/state/instrumented-state-store.ts +27 -26
- package/src/test/bun.ts +1 -2
- package/src/test/vitest.ts +1 -2
- package/src/util/diff.ts +14 -0
- package/src/util/idempotent-spawn.ts +1 -1
- package/src/util/telemetry.ts +328 -0
- package/templates/tanstack-start/package.json +2 -2
- package/workers/tunnel-proxy.js +1 -1
- package/lib/util/telemetry/client.d.ts +0 -31
- package/lib/util/telemetry/client.d.ts.map +0 -1
- package/lib/util/telemetry/client.js +0 -121
- package/lib/util/telemetry/client.js.map +0 -1
- package/lib/util/telemetry/constants.d.ts +0 -5
- package/lib/util/telemetry/constants.d.ts.map +0 -1
- package/lib/util/telemetry/constants.js +0 -8
- package/lib/util/telemetry/constants.js.map +0 -1
- package/lib/util/telemetry/context.d.ts +0 -15
- package/lib/util/telemetry/context.d.ts.map +0 -1
- package/lib/util/telemetry/context.js +0 -128
- package/lib/util/telemetry/context.js.map +0 -1
- package/lib/util/telemetry/index.d.ts +0 -3
- package/lib/util/telemetry/index.d.ts.map +0 -1
- package/lib/util/telemetry/index.js +0 -3
- package/lib/util/telemetry/index.js.map +0 -1
- package/lib/util/telemetry/types.d.ts +0 -68
- package/lib/util/telemetry/types.d.ts.map +0 -1
- package/lib/util/telemetry/types.js +0 -1
- package/src/util/telemetry/client.ts +0 -156
- package/src/util/telemetry/constants.ts +0 -13
- package/src/util/telemetry/context.ts +0 -154
- package/src/util/telemetry/index.ts +0 -2
- 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
|
-
|
|
182
|
-
|
|
183
|
-
|
|
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
|
|
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
|
-
*
|
|
79
|
+
* Whether to disable telemetry for the scope.
|
|
80
80
|
*
|
|
81
|
+
* @default false
|
|
81
82
|
*/
|
|
82
|
-
|
|
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
|
|
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.
|
|
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
|
-
|
|
536
|
-
event: "
|
|
537
|
-
|
|
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
|
-
|
|
587
|
-
event: "
|
|
588
|
-
|
|
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
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
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
|
|
3
|
-
|
|
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
|
|
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:
|
|
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
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
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
|
-
"
|
|
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
|
-
"
|
|
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
|
-
"
|
|
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
|
-
"
|
|
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
|
-
"
|
|
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
|
-
"
|
|
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
|
-
"
|
|
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
|
-
"
|
|
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
|
-
"
|
|
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
|
-
|
|
105
|
+
noTrack: true,
|
|
107
106
|
local: defaultOptions.local,
|
|
108
107
|
});
|
|
109
108
|
|
package/src/test/vitest.ts
CHANGED
|
@@ -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
|
-
|
|
134
|
+
noTrack: true,
|
|
136
135
|
quiet: defaultOptions.quiet,
|
|
137
136
|
password: process.env.ALCHEMY_PASSWORD,
|
|
138
137
|
local: defaultOptions.local,
|
package/src/util/diff.ts
ADDED
|
@@ -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: ["
|
|
115
|
+
stdio: ["inherit", out.fd, out.fd], // stdout/stderr -> files (OS-level)
|
|
116
116
|
env,
|
|
117
117
|
detached: false,
|
|
118
118
|
});
|