alchemy 0.69.0 → 0.70.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.
- package/bin/alchemy.js +3810 -3889
- package/bin/commands/init.ts +41 -55
- package/bin/trpc.ts +4 -9
- package/lib/alchemy.d.ts +3 -3
- package/lib/alchemy.d.ts.map +1 -1
- package/lib/alchemy.js +2 -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/bucket-object.d.ts +5 -0
- package/lib/cloudflare/bucket-object.d.ts.map +1 -1
- package/lib/cloudflare/bucket-object.js +1 -1
- package/lib/cloudflare/bucket-object.js.map +1 -1
- package/lib/cloudflare/bucket.d.ts +6 -3
- package/lib/cloudflare/bucket.d.ts.map +1 -1
- package/lib/cloudflare/bucket.js +60 -8
- package/lib/cloudflare/bucket.js.map +1 -1
- package/lib/cloudflare/bun-spa/bun-spa.d.ts +15 -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 +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 +3 -3
- 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 +33 -14
- 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/tanstack-start/plugin.d.ts +2 -15
- package/lib/cloudflare/tanstack-start/plugin.d.ts.map +1 -1
- package/lib/cloudflare/tanstack-start/plugin.js +5 -25
- package/lib/cloudflare/tanstack-start/plugin.js.map +1 -1
- package/lib/cloudflare/tanstack-start/tanstack-start.d.ts.map +1 -1
- package/lib/cloudflare/tanstack-start/tanstack-start.js +15 -4
- package/lib/cloudflare/tanstack-start/tanstack-start.js.map +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 +7 -18
- package/lib/cloudflare/website.js.map +1 -1
- package/lib/cloudflare/worker-metadata.d.ts +5 -1
- package/lib/cloudflare/worker-metadata.d.ts.map +1 -1
- package/lib/cloudflare/worker-metadata.js +3 -0
- package/lib/cloudflare/worker-metadata.js.map +1 -1
- package/lib/cloudflare/worker.d.ts +17 -1
- package/lib/cloudflare/worker.d.ts.map +1 -1
- package/lib/cloudflare/worker.js +1 -0
- package/lib/cloudflare/worker.js.map +1 -1
- package/lib/cloudflare/wrangler.json.d.ts +15 -1
- package/lib/cloudflare/wrangler.json.d.ts.map +1 -1
- package/lib/cloudflare/wrangler.json.js +12 -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/docker/api.d.ts +22 -1
- package/lib/docker/api.d.ts.map +1 -1
- package/lib/docker/api.js +64 -2
- package/lib/docker/api.js.map +1 -1
- package/lib/docker/container.d.ts +88 -0
- package/lib/docker/container.d.ts.map +1 -1
- package/lib/docker/container.js +36 -0
- package/lib/docker/container.js.map +1 -1
- 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 +4 -9
- package/lib/scope.d.ts.map +1 -1
- package/lib/scope.js +16 -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/telemetry.d.ts +52 -0
- package/lib/util/telemetry.d.ts.map +1 -0
- package/lib/util/telemetry.js +191 -0
- package/lib/util/telemetry.js.map +1 -0
- package/package.json +19 -1
- package/src/alchemy.ts +5 -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/bucket-object.ts +11 -1
- package/src/cloudflare/bucket.ts +72 -6
- package/src/cloudflare/bun-spa/bun-spa.ts +139 -0
- package/src/cloudflare/compatibility-date.gen.ts +1 -1
- package/src/cloudflare/container.ts +22 -3
- package/src/cloudflare/index.ts +1 -0
- package/src/cloudflare/miniflare/build-worker-options.ts +6 -4
- package/src/cloudflare/miniflare/miniflare-controller.ts +2 -0
- package/src/cloudflare/miniflare/miniflare-worker-proxy.ts +42 -15
- package/src/cloudflare/permission-groups.ts +21 -49
- package/src/cloudflare/redwood/redwood.ts +1 -1
- package/src/cloudflare/tanstack-start/plugin.ts +7 -28
- package/src/cloudflare/tanstack-start/tanstack-start.ts +15 -4
- package/src/cloudflare/util/filter-env-bindings.ts +96 -0
- package/src/cloudflare/website.ts +12 -24
- package/src/cloudflare/worker-metadata.ts +8 -1
- package/src/cloudflare/worker.ts +19 -1
- package/src/cloudflare/wrangler.json.ts +27 -9
- 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/docker/api.ts +86 -2
- package/src/docker/container.ts +97 -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 +22 -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/telemetry.ts +297 -0
- package/templates/tanstack-start/.cta.json +13 -0
- package/templates/tanstack-start/README.md +267 -49
- package/templates/tanstack-start/_gitignore +9 -18
- package/templates/tanstack-start/alchemy.run.ts +2 -2
- package/templates/tanstack-start/package.json +24 -19
- package/templates/tanstack-start/public/favicon.ico +0 -0
- package/templates/tanstack-start/public/logo192.png +0 -0
- package/templates/tanstack-start/public/logo512.png +0 -0
- package/templates/tanstack-start/public/manifest.json +25 -0
- package/templates/tanstack-start/public/robots.txt +3 -0
- package/templates/tanstack-start/src/components/Header.tsx +21 -0
- package/templates/tanstack-start/src/logo.svg +12 -0
- package/templates/tanstack-start/src/router.tsx +7 -16
- package/templates/tanstack-start/src/routes/__root.tsx +13 -114
- package/templates/tanstack-start/src/routes/api.demo-names.ts +15 -0
- package/templates/tanstack-start/src/routes/demo.start.api-request.tsx +44 -0
- package/templates/tanstack-start/src/routes/demo.start.server-funcs.tsx +97 -0
- package/templates/tanstack-start/src/routes/index.tsx +31 -4
- package/templates/tanstack-start/src/styles.css +15 -0
- package/templates/tanstack-start/tsconfig.json +19 -22
- package/templates/tanstack-start/types/env.d.ts +2 -2
- package/templates/tanstack-start/vite.config.ts +16 -25
- 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
- package/templates/tanstack-start/_prettierignore +0 -4
- package/templates/tanstack-start/public/android-chrome-192x192.png +0 -0
- package/templates/tanstack-start/public/android-chrome-512x512.png +0 -0
- package/templates/tanstack-start/public/apple-touch-icon.png +0 -0
- package/templates/tanstack-start/public/favicon-16x16.png +0 -0
- package/templates/tanstack-start/public/favicon-32x32.png +0 -0
- package/templates/tanstack-start/public/favicon.png +0 -0
- package/templates/tanstack-start/public/site.webmanifest +0 -19
- package/templates/tanstack-start/src/components/DefaultCatchBoundary.tsx +0 -53
- package/templates/tanstack-start/src/components/NotFound.tsx +0 -25
- package/templates/tanstack-start/src/components/PostError.tsx +0 -5
- package/templates/tanstack-start/src/components/UserError.tsx +0 -5
- package/templates/tanstack-start/src/routes/_pathlessLayout/_nested-layout/route-a.tsx +0 -10
- package/templates/tanstack-start/src/routes/_pathlessLayout/_nested-layout/route-b.tsx +0 -10
- package/templates/tanstack-start/src/routes/_pathlessLayout/_nested-layout.tsx +0 -34
- package/templates/tanstack-start/src/routes/_pathlessLayout.tsx +0 -16
- package/templates/tanstack-start/src/routes/api/users.$userId.ts +0 -28
- package/templates/tanstack-start/src/routes/api/users.ts +0 -59
- package/templates/tanstack-start/src/routes/customScript[.]js.ts +0 -10
- package/templates/tanstack-start/src/routes/deferred.tsx +0 -62
- package/templates/tanstack-start/src/routes/posts.$postId.tsx +0 -34
- package/templates/tanstack-start/src/routes/posts.index.tsx +0 -8
- package/templates/tanstack-start/src/routes/posts.tsx +0 -38
- package/templates/tanstack-start/src/routes/posts_.$postId.deep.tsx +0 -29
- package/templates/tanstack-start/src/routes/redirect.tsx +0 -9
- package/templates/tanstack-start/src/routes/users.$userId.tsx +0 -44
- package/templates/tanstack-start/src/routes/users.index.tsx +0 -18
- package/templates/tanstack-start/src/routes/users.tsx +0 -49
- package/templates/tanstack-start/src/styles/app.css +0 -12
- package/templates/tanstack-start/src/utils/loggingMiddleware.tsx +0 -41
- package/templates/tanstack-start/src/utils/posts.tsx +0 -40
- package/templates/tanstack-start/src/utils/seo.ts +0 -33
- package/templates/tanstack-start/src/utils/users.tsx +0 -5
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
/**
|
|
3
|
+
* Request testnet tokens from Coinbase faucet for accounts with faucet metadata
|
|
4
|
+
*
|
|
5
|
+
* Usage:
|
|
6
|
+
* bun node_modules/alchemy/src/coinbase/faucet.ts # Fund all accounts with faucet config
|
|
7
|
+
* bun node_modules/alchemy/src/coinbase/faucet.ts dev # Fund only accounts in dev scope
|
|
8
|
+
* bun node_modules/alchemy/src/coinbase/faucet.ts backend/dev # Fund specific scope
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { readFile, access } from "node:fs/promises";
|
|
12
|
+
import { join } from "node:path";
|
|
13
|
+
import { glob } from "glob";
|
|
14
|
+
import { createCdpClient } from "./client.ts";
|
|
15
|
+
import type { EvmAccount } from "./evm-account.ts";
|
|
16
|
+
import type { EvmSmartAccount } from "./evm-smart-account.ts";
|
|
17
|
+
import type { FaucetNetwork, FaucetToken } from "./types.ts";
|
|
18
|
+
|
|
19
|
+
// Track funded combinations to avoid duplicates within this run
|
|
20
|
+
const funded = new Set<string>();
|
|
21
|
+
|
|
22
|
+
// Get optional scope argument
|
|
23
|
+
const scope = process.argv[2];
|
|
24
|
+
|
|
25
|
+
// Initialize CDP client (uses CDP_* env vars automatically)
|
|
26
|
+
const cdp = await createCdpClient();
|
|
27
|
+
|
|
28
|
+
let stateFiles: string[];
|
|
29
|
+
|
|
30
|
+
if (scope) {
|
|
31
|
+
// If scope provided, find matching directories
|
|
32
|
+
const scopePath = join(".alchemy", scope);
|
|
33
|
+
|
|
34
|
+
let scopeExists = false;
|
|
35
|
+
try {
|
|
36
|
+
await access(scopePath);
|
|
37
|
+
scopeExists = true;
|
|
38
|
+
} catch {
|
|
39
|
+
scopeExists = false;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
if (scopeExists) {
|
|
43
|
+
// Exact match found
|
|
44
|
+
console.log(`Using scope: ${scope}`);
|
|
45
|
+
stateFiles = await glob("*.json", {
|
|
46
|
+
cwd: scopePath,
|
|
47
|
+
absolute: true,
|
|
48
|
+
});
|
|
49
|
+
} else {
|
|
50
|
+
// Try to find directories that end with the provided scope
|
|
51
|
+
// We need to find directories, so we'll look for JSON files and extract the directory paths
|
|
52
|
+
const allFiles = await glob(`**/${scope}/*.json`, {
|
|
53
|
+
cwd: ".alchemy",
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
// Extract unique directory paths
|
|
57
|
+
const possibleScopes = [
|
|
58
|
+
...new Set(allFiles.map((f) => f.replace(/\/[^/]+\.json$/, ""))),
|
|
59
|
+
];
|
|
60
|
+
|
|
61
|
+
if (possibleScopes.length === 0) {
|
|
62
|
+
console.error(`No scope found matching: ${scope}`);
|
|
63
|
+
process.exit(1);
|
|
64
|
+
} else if (possibleScopes.length === 1) {
|
|
65
|
+
// Found exactly one match
|
|
66
|
+
const foundScope = possibleScopes[0];
|
|
67
|
+
console.log(`Using scope: ${foundScope}`);
|
|
68
|
+
stateFiles = await glob("*.json", {
|
|
69
|
+
cwd: join(".alchemy", foundScope),
|
|
70
|
+
absolute: true,
|
|
71
|
+
});
|
|
72
|
+
} else {
|
|
73
|
+
// Multiple matches found - use all of them
|
|
74
|
+
console.log(`Found ${possibleScopes.length} scopes matching '${scope}':`);
|
|
75
|
+
for (const s of possibleScopes) {
|
|
76
|
+
console.log(` - ${s}`);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// Collect state files from all matching scopes
|
|
80
|
+
stateFiles = [];
|
|
81
|
+
for (const foundScope of possibleScopes) {
|
|
82
|
+
const files = await glob("*.json", {
|
|
83
|
+
cwd: join(".alchemy", foundScope),
|
|
84
|
+
absolute: true,
|
|
85
|
+
});
|
|
86
|
+
stateFiles.push(...files);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
} else {
|
|
91
|
+
// No scope provided, search all .alchemy subdirectories
|
|
92
|
+
console.log("Searching all scopes for accounts with faucet configuration...");
|
|
93
|
+
stateFiles = await glob("**/*.json", {
|
|
94
|
+
cwd: ".alchemy",
|
|
95
|
+
absolute: true,
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
const allStates = (
|
|
100
|
+
await Promise.all(
|
|
101
|
+
stateFiles.map(async (file) => {
|
|
102
|
+
try {
|
|
103
|
+
const content = await readFile(file, "utf-8");
|
|
104
|
+
return JSON.parse(content);
|
|
105
|
+
} catch {
|
|
106
|
+
return null;
|
|
107
|
+
}
|
|
108
|
+
}),
|
|
109
|
+
)
|
|
110
|
+
).filter(Boolean);
|
|
111
|
+
|
|
112
|
+
const accounts = allStates
|
|
113
|
+
.filter(
|
|
114
|
+
(state) =>
|
|
115
|
+
state?.kind?.startsWith("coinbase::evm") &&
|
|
116
|
+
state.output &&
|
|
117
|
+
(state.output as EvmAccount | EvmSmartAccount).faucet,
|
|
118
|
+
)
|
|
119
|
+
.map((state) => {
|
|
120
|
+
const output = state.output as EvmAccount | EvmSmartAccount;
|
|
121
|
+
return {
|
|
122
|
+
address: output.address,
|
|
123
|
+
name: output.name,
|
|
124
|
+
faucet: output.faucet!,
|
|
125
|
+
};
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
if (accounts.length === 0) {
|
|
129
|
+
console.log("No accounts with faucet configuration found");
|
|
130
|
+
process.exit(0);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
console.log(`Found ${accounts.length} accounts with faucet configuration\n`);
|
|
134
|
+
|
|
135
|
+
for (const account of accounts) {
|
|
136
|
+
console.log(`Account: ${account.name} (${account.address})`);
|
|
137
|
+
|
|
138
|
+
for (const [network, tokens] of Object.entries(account.faucet)) {
|
|
139
|
+
for (const token of tokens) {
|
|
140
|
+
const key = `${account.address}-${network}-${token}`;
|
|
141
|
+
|
|
142
|
+
// Skip if already processed in this run
|
|
143
|
+
if (funded.has(key)) {
|
|
144
|
+
console.log(` ⏭️ Skipping ${token} on ${network} (already requested)`);
|
|
145
|
+
continue;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// Request tokens from faucet
|
|
149
|
+
try {
|
|
150
|
+
console.log(` 💧 Requesting ${token} on ${network}...`);
|
|
151
|
+
|
|
152
|
+
const response = await cdp.evm.requestFaucet({
|
|
153
|
+
address: account.address,
|
|
154
|
+
network: network as FaucetNetwork,
|
|
155
|
+
token: token as FaucetToken,
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
console.log(` ✅ Funded: ${response.transactionHash}`);
|
|
159
|
+
funded.add(key);
|
|
160
|
+
|
|
161
|
+
// Small delay to avoid rate limits
|
|
162
|
+
await new Promise((resolve) => setTimeout(resolve, 1000));
|
|
163
|
+
} catch (error: any) {
|
|
164
|
+
console.log(
|
|
165
|
+
` ❌ Error funding ${token} on ${network}: ${error.message}`,
|
|
166
|
+
);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
console.log();
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
console.log("✨ Funding complete!");
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Common types for Coinbase CDP resources
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Ethereum address format (20 bytes, 40 hex chars)
|
|
7
|
+
*/
|
|
8
|
+
export type Address = `0x${string}`;
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Private key format (32 bytes, 64 hex chars)
|
|
12
|
+
*/
|
|
13
|
+
export type PrivateKey = `0x${string}`;
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Transaction hash format (32 bytes, 64 hex chars)
|
|
17
|
+
*/
|
|
18
|
+
export type TransactionHash = `0x${string}`;
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Supported testnet networks for faucet requests
|
|
22
|
+
*/
|
|
23
|
+
export type FaucetNetwork = "base-sepolia" | "ethereum-sepolia";
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Supported tokens for faucet requests
|
|
27
|
+
*/
|
|
28
|
+
export type FaucetToken = "eth" | "usdc" | "eurc" | "cbbtc";
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Faucet configuration for requesting testnet tokens
|
|
32
|
+
*/
|
|
33
|
+
export type FaucetConfig = Partial<Record<FaucetNetwork, FaucetToken[]>>;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Utility functions for Coinbase CDP resources
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Validates that a CDP account name follows the required format.
|
|
7
|
+
* CDP only allows letters, numbers, and hyphens in account names.
|
|
8
|
+
* Names cannot start or end with a hyphen.
|
|
9
|
+
*
|
|
10
|
+
* @param name - The account name to validate
|
|
11
|
+
* @throws Error if the name contains invalid characters or starts/ends with hyphen
|
|
12
|
+
*/
|
|
13
|
+
export function validateAccountName(name: string): void {
|
|
14
|
+
if (!/^[a-zA-Z0-9]([a-zA-Z0-9-]*[a-zA-Z0-9])?$/.test(name)) {
|
|
15
|
+
throw new Error(
|
|
16
|
+
`Invalid account name '${name}'. CDP only allows letters, numbers, and hyphens. Names cannot start or end with a hyphen.`,
|
|
17
|
+
);
|
|
18
|
+
}
|
|
19
|
+
}
|
package/src/docker/api.ts
CHANGED
|
@@ -3,6 +3,41 @@ import { Buffer } from "node:buffer";
|
|
|
3
3
|
import { spawn } from "node:child_process";
|
|
4
4
|
import fs from "node:fs/promises";
|
|
5
5
|
import path from "node:path";
|
|
6
|
+
import type { Duration, HealthcheckConfig } from "./container.ts";
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Normalize a duration value to Docker CLI format
|
|
10
|
+
* Accepts either a number (seconds) or a string with unit suffix (ms|s|m|h)
|
|
11
|
+
* Returns a string in Docker CLI format
|
|
12
|
+
*
|
|
13
|
+
* The Duration type provides compile-time type safety, ensuring only valid
|
|
14
|
+
* formats are accepted: number or string matching the pattern `${number}${unit}`
|
|
15
|
+
*
|
|
16
|
+
* @param duration Duration value (number in seconds or string with unit)
|
|
17
|
+
* @returns Normalized duration string for Docker CLI
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* normalizeDuration(30) // "30s"
|
|
21
|
+
* normalizeDuration("30s") // "30s"
|
|
22
|
+
* normalizeDuration("1m") // "1m"
|
|
23
|
+
* normalizeDuration("500ms") // "500ms"
|
|
24
|
+
* normalizeDuration("1.5s") // "1.5s"
|
|
25
|
+
*/
|
|
26
|
+
export function normalizeDuration(duration: Duration): string {
|
|
27
|
+
if (typeof duration === "number") {
|
|
28
|
+
return `${duration}s`;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// Validate string format: must be a number followed by unit (ms|s|m|h)
|
|
32
|
+
const match = duration.match(/^(\d+(?:\.\d+)?)(ms|s|m|h)$/);
|
|
33
|
+
if (!match) {
|
|
34
|
+
throw new Error(
|
|
35
|
+
`Invalid duration format: "${duration}". Expected format: number followed by unit (ms|s|m|h), e.g., "30s", "1m", "500ms"`,
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
return duration;
|
|
40
|
+
}
|
|
6
41
|
|
|
7
42
|
/**
|
|
8
43
|
* Options for Docker API requests
|
|
@@ -59,7 +94,10 @@ export class DockerApi {
|
|
|
59
94
|
* @param args Command arguments to pass to Docker CLI
|
|
60
95
|
* @returns Result of the command
|
|
61
96
|
*/
|
|
62
|
-
async exec(
|
|
97
|
+
async exec(
|
|
98
|
+
args: string[],
|
|
99
|
+
remainingAttempts = 3,
|
|
100
|
+
): Promise<{ stdout: string; stderr: string }> {
|
|
63
101
|
// If a custom config directory is provided, ensure all commands use it by
|
|
64
102
|
// setting the DOCKER_CONFIG env variable for the spawned process.
|
|
65
103
|
const env = this.configDir
|
|
@@ -94,8 +132,16 @@ export class DockerApi {
|
|
|
94
132
|
try {
|
|
95
133
|
await subprocess;
|
|
96
134
|
} catch (error: any) {
|
|
135
|
+
const message = stderr || error.message || "Command failed";
|
|
136
|
+
if (
|
|
137
|
+
message.includes("unexpected status from HEAD request") &&
|
|
138
|
+
remainingAttempts > 0
|
|
139
|
+
) {
|
|
140
|
+
await new Promise((resolve) => setTimeout(resolve, 1000));
|
|
141
|
+
return this.exec(args, remainingAttempts - 1);
|
|
142
|
+
}
|
|
97
143
|
// Process failed, but we still have the output
|
|
98
|
-
throw new Error(
|
|
144
|
+
throw new Error(message);
|
|
99
145
|
}
|
|
100
146
|
|
|
101
147
|
return { stdout, stderr };
|
|
@@ -177,6 +223,7 @@ export class DockerApi {
|
|
|
177
223
|
env?: Record<string, string>;
|
|
178
224
|
volumes?: Record<string, string>;
|
|
179
225
|
cmd?: string[];
|
|
226
|
+
healthcheck?: HealthcheckConfig;
|
|
180
227
|
} = {},
|
|
181
228
|
): Promise<string> {
|
|
182
229
|
const args = ["create", "--name", name];
|
|
@@ -202,6 +249,43 @@ export class DockerApi {
|
|
|
202
249
|
}
|
|
203
250
|
}
|
|
204
251
|
|
|
252
|
+
// Add healthcheck configuration
|
|
253
|
+
if (options.healthcheck) {
|
|
254
|
+
const hc = options.healthcheck;
|
|
255
|
+
|
|
256
|
+
// Format the cmd
|
|
257
|
+
const cmdStr = Array.isArray(hc.cmd) ? hc.cmd.join(" ") : hc.cmd;
|
|
258
|
+
args.push("--health-cmd", cmdStr);
|
|
259
|
+
|
|
260
|
+
// Add interval
|
|
261
|
+
if (hc.interval !== undefined) {
|
|
262
|
+
args.push("--health-interval", normalizeDuration(hc.interval));
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
// Add timeout
|
|
266
|
+
if (hc.timeout !== undefined) {
|
|
267
|
+
args.push("--health-timeout", normalizeDuration(hc.timeout));
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
// Add retries
|
|
271
|
+
if (hc.retries !== undefined) {
|
|
272
|
+
args.push("--health-retries", String(hc.retries));
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
// Add start period
|
|
276
|
+
if (hc.startPeriod !== undefined) {
|
|
277
|
+
args.push("--health-start-period", normalizeDuration(hc.startPeriod));
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
// Add start interval (API 1.44+)
|
|
281
|
+
if (hc.startInterval !== undefined) {
|
|
282
|
+
args.push(
|
|
283
|
+
"--health-start-interval",
|
|
284
|
+
normalizeDuration(hc.startInterval),
|
|
285
|
+
);
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
|
|
205
289
|
args.push(image);
|
|
206
290
|
|
|
207
291
|
// Add command if specified
|
package/src/docker/container.ts
CHANGED
|
@@ -59,6 +59,62 @@ export interface NetworkMapping {
|
|
|
59
59
|
aliases?: string[];
|
|
60
60
|
}
|
|
61
61
|
|
|
62
|
+
/**
|
|
63
|
+
* Duration value supporting both number (seconds) and string format (value + unit)
|
|
64
|
+
* Units: ms (milliseconds), s (seconds), m (minutes), h (hours)
|
|
65
|
+
* Examples: 30, "30s", "1m", "500ms", "2h"
|
|
66
|
+
*/
|
|
67
|
+
export type Duration = number | `${number}${"ms" | "s" | "m" | "h"}`;
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Healthcheck configuration
|
|
71
|
+
*/
|
|
72
|
+
export interface HealthcheckConfig {
|
|
73
|
+
/**
|
|
74
|
+
* Command to run to check health.
|
|
75
|
+
* Can be an array of command arguments or a shell command string.
|
|
76
|
+
* Examples:
|
|
77
|
+
* - ["curl", "-f", "http://localhost/"]
|
|
78
|
+
* - "curl -f http://localhost/ || exit 1"
|
|
79
|
+
*/
|
|
80
|
+
cmd: string[] | string;
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Time between running the check
|
|
84
|
+
* Can be a number (in seconds) or string with unit (e.g., "30s", "1m")
|
|
85
|
+
* @default 0
|
|
86
|
+
*/
|
|
87
|
+
interval?: Duration;
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Maximum time to allow one check to run
|
|
91
|
+
* Can be a number (in seconds) or string with unit (e.g., "10s", "500ms")
|
|
92
|
+
* @default 0
|
|
93
|
+
*/
|
|
94
|
+
timeout?: Duration;
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Consecutive failures needed to report unhealthy
|
|
98
|
+
*/
|
|
99
|
+
retries?: number;
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Start period for the container to initialize before starting
|
|
103
|
+
* health-retries countdown
|
|
104
|
+
* Can be a number (in seconds) or string with unit (e.g., "40s", "1m")
|
|
105
|
+
* @default 0
|
|
106
|
+
*/
|
|
107
|
+
startPeriod?: Duration;
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Time between running the check during the start period
|
|
111
|
+
* Can be a number (in seconds) or string with unit (e.g., "5s", "500ms")
|
|
112
|
+
* Requires Docker API 1.44+
|
|
113
|
+
* @default 0
|
|
114
|
+
*/
|
|
115
|
+
startInterval?: Duration;
|
|
116
|
+
}
|
|
117
|
+
|
|
62
118
|
/**
|
|
63
119
|
* Properties for creating a Docker container
|
|
64
120
|
*/
|
|
@@ -115,6 +171,11 @@ export interface ContainerProps {
|
|
|
115
171
|
* Start the container after creation
|
|
116
172
|
*/
|
|
117
173
|
start?: boolean;
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* Healthcheck configuration
|
|
177
|
+
*/
|
|
178
|
+
healthcheck?: HealthcheckConfig;
|
|
118
179
|
}
|
|
119
180
|
|
|
120
181
|
/**
|
|
@@ -172,6 +233,41 @@ export interface Container extends ContainerProps {
|
|
|
172
233
|
* restart: "always",
|
|
173
234
|
* start: true
|
|
174
235
|
* });
|
|
236
|
+
*
|
|
237
|
+
* @example
|
|
238
|
+
* // Create a container with healthcheck using numeric values (seconds)
|
|
239
|
+
* const healthyContainer = await Container("api", {
|
|
240
|
+
* image: "my-api:latest",
|
|
241
|
+
* ports: [
|
|
242
|
+
* { external: 3000, internal: 3000 }
|
|
243
|
+
* ],
|
|
244
|
+
* healthcheck: {
|
|
245
|
+
* cmd: ["curl", "-f", "http://localhost:3000/health"],
|
|
246
|
+
* interval: 30,
|
|
247
|
+
* timeout: 10,
|
|
248
|
+
* retries: 3,
|
|
249
|
+
* startPeriod: 40
|
|
250
|
+
* },
|
|
251
|
+
* start: true
|
|
252
|
+
* });
|
|
253
|
+
*
|
|
254
|
+
* @example
|
|
255
|
+
* // Create a container with healthcheck using string duration format
|
|
256
|
+
* const healthyContainer2 = await Container("api2", {
|
|
257
|
+
* image: "my-api:latest",
|
|
258
|
+
* ports: [
|
|
259
|
+
* { external: 3001, internal: 3000 }
|
|
260
|
+
* ],
|
|
261
|
+
* healthcheck: {
|
|
262
|
+
* cmd: ["curl", "-f", "http://localhost:3000/health"],
|
|
263
|
+
* interval: "30s",
|
|
264
|
+
* timeout: "10s",
|
|
265
|
+
* retries: 3,
|
|
266
|
+
* startPeriod: "1m",
|
|
267
|
+
* startInterval: "500ms"
|
|
268
|
+
* },
|
|
269
|
+
* start: true
|
|
270
|
+
* });
|
|
175
271
|
*/
|
|
176
272
|
export const Container = Resource(
|
|
177
273
|
"docker::Container",
|
|
@@ -245,6 +341,7 @@ export const Container = Resource(
|
|
|
245
341
|
env: props.environment,
|
|
246
342
|
volumes: volumeMappings,
|
|
247
343
|
cmd: props.command,
|
|
344
|
+
healthcheck: props.healthcheck,
|
|
248
345
|
});
|
|
249
346
|
|
|
250
347
|
// Connect to networks if specified
|
|
@@ -1899,6 +1899,7 @@ export type BillingAccountState =
|
|
|
1899
1899
|
export type BillingSubscriptionType =
|
|
1900
1900
|
| "UNKNOWN"
|
|
1901
1901
|
| "direct_sales"
|
|
1902
|
+
| "direct_sales_v3"
|
|
1902
1903
|
| "aws_marketplace"
|
|
1903
1904
|
| "free_v2"
|
|
1904
1905
|
| "free_v3"
|
|
@@ -2527,6 +2528,11 @@ export type NeonAuthCreateIntegrationRequest = {
|
|
|
2527
2528
|
role_name?: string;
|
|
2528
2529
|
};
|
|
2529
2530
|
|
|
2531
|
+
export type EnableNeonAuthIntegrationRequest = {
|
|
2532
|
+
auth_provider: NeonAuthSupportedAuthProvider;
|
|
2533
|
+
database_name?: string;
|
|
2534
|
+
};
|
|
2535
|
+
|
|
2530
2536
|
export type NeonAuthCreateIntegrationResponse = {
|
|
2531
2537
|
auth_provider: NeonAuthSupportedAuthProvider;
|
|
2532
2538
|
auth_provider_project_id: string;
|
|
@@ -2677,7 +2683,12 @@ export type RoleOperations = RoleResponse & OperationsResponse;
|
|
|
2677
2683
|
|
|
2678
2684
|
export type JwksCreationOperation = JwksResponse & OperationsResponse;
|
|
2679
2685
|
|
|
2680
|
-
export type SupportTicketSeverity =
|
|
2686
|
+
export type SupportTicketSeverity =
|
|
2687
|
+
| "low"
|
|
2688
|
+
| "normal"
|
|
2689
|
+
| "high"
|
|
2690
|
+
| "critical"
|
|
2691
|
+
| "urgent";
|
|
2681
2692
|
|
|
2682
2693
|
export type AnnotationData = {
|
|
2683
2694
|
object: AnnotationObjectData;
|
|
@@ -2758,6 +2769,7 @@ export type Snapshot = {
|
|
|
2758
2769
|
source_branch_id?: string;
|
|
2759
2770
|
created_at: string;
|
|
2760
2771
|
expires_at?: string;
|
|
2772
|
+
manual?: boolean;
|
|
2761
2773
|
};
|
|
2762
2774
|
|
|
2763
2775
|
export type SnapshotUpdateRequest = {
|
|
@@ -514,6 +514,10 @@ export type PaginatedPostgresClusterResizeRequest = {
|
|
|
514
514
|
* The SKU representing the branch cluster for display
|
|
515
515
|
*/
|
|
516
516
|
cluster_display_name: string;
|
|
517
|
+
/**
|
|
518
|
+
* Whether or not this is a metal database
|
|
519
|
+
*/
|
|
520
|
+
cluster_metal: boolean;
|
|
517
521
|
/**
|
|
518
522
|
* The total number of replicas
|
|
519
523
|
*/
|
|
@@ -532,6 +536,10 @@ export type PaginatedPostgresClusterResizeRequest = {
|
|
|
532
536
|
* The previous SKU representing the branch cluster for display
|
|
533
537
|
*/
|
|
534
538
|
previous_cluster_display_name: string;
|
|
539
|
+
/**
|
|
540
|
+
* Whether or not the previous SKU was a metal database
|
|
541
|
+
*/
|
|
542
|
+
previous_cluster_metal: boolean;
|
|
535
543
|
/**
|
|
536
544
|
* The previous total number of replicas
|
|
537
545
|
*/
|
|
@@ -652,6 +660,10 @@ export type PostgresClusterResizeRequest = {
|
|
|
652
660
|
* The SKU representing the branch cluster for display
|
|
653
661
|
*/
|
|
654
662
|
cluster_display_name: string;
|
|
663
|
+
/**
|
|
664
|
+
* Whether or not this is a metal database
|
|
665
|
+
*/
|
|
666
|
+
cluster_metal: boolean;
|
|
655
667
|
/**
|
|
656
668
|
* The total number of replicas
|
|
657
669
|
*/
|
|
@@ -670,6 +682,10 @@ export type PostgresClusterResizeRequest = {
|
|
|
670
682
|
* The previous SKU representing the branch cluster for display
|
|
671
683
|
*/
|
|
672
684
|
previous_cluster_display_name: string;
|
|
685
|
+
/**
|
|
686
|
+
* Whether or not the previous SKU was a metal database
|
|
687
|
+
*/
|
|
688
|
+
previous_cluster_metal: boolean;
|
|
673
689
|
/**
|
|
674
690
|
* The previous total number of replicas
|
|
675
691
|
*/
|
|
@@ -1301,7 +1317,8 @@ export type PostgresClusterExtension = {
|
|
|
1301
1317
|
| "milliseconds"
|
|
1302
1318
|
| "seconds"
|
|
1303
1319
|
| "select"
|
|
1304
|
-
| "string"
|
|
1320
|
+
| "string"
|
|
1321
|
+
| "time";
|
|
1305
1322
|
/**
|
|
1306
1323
|
* The default value of the parameter
|
|
1307
1324
|
*/
|
|
@@ -1408,7 +1425,8 @@ export type PostgresClusterParameter = {
|
|
|
1408
1425
|
| "milliseconds"
|
|
1409
1426
|
| "seconds"
|
|
1410
1427
|
| "select"
|
|
1411
|
-
| "string"
|
|
1428
|
+
| "string"
|
|
1429
|
+
| "time";
|
|
1412
1430
|
/**
|
|
1413
1431
|
* The default value of the parameter
|
|
1414
1432
|
*/
|
|
@@ -6943,6 +6961,7 @@ export type PaginatedDatabaseWebhook = {
|
|
|
6943
6961
|
| "branch.anomaly"
|
|
6944
6962
|
| "branch.schema_recommendation"
|
|
6945
6963
|
| "branch.sleeping"
|
|
6964
|
+
| "branch.start_maintenance"
|
|
6946
6965
|
| "cluster.storage"
|
|
6947
6966
|
| "database.access_request"
|
|
6948
6967
|
| "deploy_request.closed"
|
|
@@ -7004,6 +7023,7 @@ export type DatabaseWebhook = {
|
|
|
7004
7023
|
| "branch.anomaly"
|
|
7005
7024
|
| "branch.schema_recommendation"
|
|
7006
7025
|
| "branch.sleeping"
|
|
7026
|
+
| "branch.start_maintenance"
|
|
7007
7027
|
| "cluster.storage"
|
|
7008
7028
|
| "database.access_request"
|
|
7009
7029
|
| "deploy_request.closed"
|
package/src/planetscale/api.ts
CHANGED
|
@@ -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
|
}
|