alchemy 0.40.0 → 0.41.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.
Files changed (71) hide show
  1. package/lib/build-date.d.ts +1 -1
  2. package/lib/build-date.js +1 -1
  3. package/lib/cloudflare/bindings.d.ts +2 -1
  4. package/lib/cloudflare/bindings.d.ts.map +1 -1
  5. package/lib/cloudflare/bindings.js.map +1 -1
  6. package/lib/cloudflare/bound.d.ts +2 -1
  7. package/lib/cloudflare/bound.d.ts.map +1 -1
  8. package/lib/cloudflare/bundle/bundle-worker-dev.d.ts.map +1 -1
  9. package/lib/cloudflare/bundle/bundle-worker-dev.js +2 -1
  10. package/lib/cloudflare/bundle/bundle-worker-dev.js.map +1 -1
  11. package/lib/cloudflare/bundle/bundle-worker.d.ts.map +1 -1
  12. package/lib/cloudflare/bundle/bundle-worker.js +2 -1
  13. package/lib/cloudflare/bundle/bundle-worker.js.map +1 -1
  14. package/lib/cloudflare/container.d.ts +509 -0
  15. package/lib/cloudflare/container.d.ts.map +1 -0
  16. package/lib/cloudflare/container.js +274 -0
  17. package/lib/cloudflare/container.js.map +1 -0
  18. package/lib/cloudflare/index.d.ts +1 -0
  19. package/lib/cloudflare/index.d.ts.map +1 -1
  20. package/lib/cloudflare/index.js +1 -0
  21. package/lib/cloudflare/index.js.map +1 -1
  22. package/lib/cloudflare/worker/miniflare-worker-options.d.ts.map +1 -1
  23. package/lib/cloudflare/worker/miniflare-worker-options.js +28 -0
  24. package/lib/cloudflare/worker/miniflare-worker-options.js.map +1 -1
  25. package/lib/cloudflare/worker-metadata.d.ts +3 -0
  26. package/lib/cloudflare/worker-metadata.d.ts.map +1 -1
  27. package/lib/cloudflare/worker-metadata.js +22 -3
  28. package/lib/cloudflare/worker-metadata.js.map +1 -1
  29. package/lib/cloudflare/worker.d.ts +2 -1
  30. package/lib/cloudflare/worker.d.ts.map +1 -1
  31. package/lib/cloudflare/worker.js +39 -3
  32. package/lib/cloudflare/worker.js.map +1 -1
  33. package/lib/cloudflare/wrangler.json.js +11 -0
  34. package/lib/cloudflare/wrangler.json.js.map +1 -1
  35. package/lib/docker/api.d.ts +15 -0
  36. package/lib/docker/api.d.ts.map +1 -1
  37. package/lib/docker/api.js +59 -0
  38. package/lib/docker/api.js.map +1 -1
  39. package/lib/docker/image.d.ts +22 -4
  40. package/lib/docker/image.d.ts.map +1 -1
  41. package/lib/docker/image.js +68 -24
  42. package/lib/docker/image.js.map +1 -1
  43. package/lib/github/index.d.ts +1 -0
  44. package/lib/github/index.d.ts.map +1 -1
  45. package/lib/github/index.js +1 -0
  46. package/lib/github/index.js.map +1 -1
  47. package/lib/github/repository-webhook.d.ts +123 -0
  48. package/lib/github/repository-webhook.d.ts.map +1 -0
  49. package/lib/github/repository-webhook.js +146 -0
  50. package/lib/github/repository-webhook.js.map +1 -0
  51. package/lib/scope.d.ts +2 -0
  52. package/lib/scope.d.ts.map +1 -1
  53. package/lib/scope.js +4 -0
  54. package/lib/scope.js.map +1 -1
  55. package/package.json +3 -2
  56. package/src/build-date.ts +1 -1
  57. package/src/cloudflare/bindings.ts +2 -0
  58. package/src/cloudflare/bound.ts +9 -1
  59. package/src/cloudflare/bundle/bundle-worker-dev.ts +2 -1
  60. package/src/cloudflare/bundle/bundle-worker.ts +2 -1
  61. package/src/cloudflare/container.ts +843 -0
  62. package/src/cloudflare/index.ts +1 -0
  63. package/src/cloudflare/worker/miniflare-worker-options.ts +28 -0
  64. package/src/cloudflare/worker-metadata.ts +28 -6
  65. package/src/cloudflare/worker.ts +67 -16
  66. package/src/cloudflare/wrangler.json.ts +12 -0
  67. package/src/docker/api.ts +74 -0
  68. package/src/docker/image.ts +99 -29
  69. package/src/github/index.ts +1 -0
  70. package/src/github/repository-webhook.ts +269 -0
  71. package/src/scope.ts +5 -0
@@ -0,0 +1,269 @@
1
+ import type { Context } from "../context.ts";
2
+ import { Resource } from "../resource.ts";
3
+ import { logger } from "../util/logger.ts";
4
+ import { createGitHubClient, verifyGitHubAuth } from "./client.ts";
5
+
6
+ /**
7
+ * Properties for creating or updating a GitHub Repository Webhook
8
+ */
9
+ export interface RepositoryWebhookProps {
10
+ /**
11
+ * Repository owner (user or organization)
12
+ */
13
+ owner: string;
14
+
15
+ /**
16
+ * Repository name
17
+ */
18
+ repository: string;
19
+
20
+ /**
21
+ * The URL to which the payloads will be delivered
22
+ */
23
+ url: string;
24
+
25
+ /**
26
+ * Webhook secret for payload validation
27
+ * @default undefined
28
+ */
29
+ secret?: string;
30
+
31
+ /**
32
+ * The media type used to serialize the payloads
33
+ * @default "application/json"
34
+ */
35
+ contentType?: "application/json" | "application/x-www-form-urlencoded";
36
+
37
+ /**
38
+ * Determines whether the SSL certificate of the host for url will be verified
39
+ * @default false
40
+ */
41
+ insecureSsl?: boolean;
42
+
43
+ /**
44
+ * Determines if notifications are sent when the webhook is triggered
45
+ * @default true
46
+ */
47
+ active?: boolean;
48
+
49
+ /**
50
+ * Determines what events the hook is triggered for
51
+ * @default ["push"]
52
+ */
53
+ events?: string[];
54
+
55
+ /**
56
+ * Optional GitHub API token (overrides environment variable)
57
+ * If not provided, will use GITHUB_TOKEN environment variable
58
+ * @default process.env.GITHUB_TOKEN
59
+ */
60
+ token?: string;
61
+ }
62
+
63
+ /**
64
+ * Output returned after Repository Webhook creation/update
65
+ */
66
+ export interface RepositoryWebhook
67
+ extends Resource<"github::RepositoryWebhook">,
68
+ RepositoryWebhookProps {
69
+ /**
70
+ * The ID of the resource
71
+ */
72
+ id: string;
73
+
74
+ /**
75
+ * The numeric ID of the webhook in GitHub
76
+ */
77
+ webhookId: number;
78
+
79
+ /**
80
+ * The webhook URL that was configured
81
+ */
82
+ url: string;
83
+
84
+ /**
85
+ * Time at which the object was created
86
+ */
87
+ createdAt: string;
88
+
89
+ /**
90
+ * Time at which the object was last updated
91
+ */
92
+ updatedAt: string;
93
+
94
+ /**
95
+ * The ping URL for the webhook
96
+ */
97
+ pingUrl: string;
98
+
99
+ /**
100
+ * The test URL for the webhook
101
+ */
102
+ testUrl: string;
103
+ }
104
+
105
+ /**
106
+ * Resource for managing GitHub repository webhooks
107
+ *
108
+ * Webhooks allow external services to be notified when certain events happen in a repository.
109
+ * This resource manages the full lifecycle of repository webhooks including creation, updates, and deletion.
110
+ *
111
+ * @example
112
+ * // Create a basic webhook for push events
113
+ * const pushWebhook = await RepositoryWebhook("push-webhook", {
114
+ * owner: "my-org",
115
+ * repository: "my-repo",
116
+ * url: "https://my-service.com/github-webhook",
117
+ * events: ["push"]
118
+ * });
119
+ *
120
+ * @example
121
+ * // Create a webhook with secret validation for multiple events
122
+ * const ciWebhook = await RepositoryWebhook("ci-webhook", {
123
+ * owner: "my-org",
124
+ * repository: "my-repo",
125
+ * url: "https://ci.example.com/webhook",
126
+ * secret: "my-webhook-secret",
127
+ * events: ["push", "pull_request", "release"],
128
+ * contentType: "application/json"
129
+ * });
130
+ *
131
+ * @example
132
+ * // Create a webhook for all events with custom SSL settings
133
+ * const monitoringWebhook = await RepositoryWebhook("monitoring-webhook", {
134
+ * owner: "my-org",
135
+ * repository: "my-repo",
136
+ * url: "https://monitoring.internal.com/github",
137
+ * secret: "super-secret-key",
138
+ * events: ["*"], // All events
139
+ * insecureSsl: true, // For internal services with self-signed certs
140
+ * contentType: "application/x-www-form-urlencoded"
141
+ * });
142
+ */
143
+ export const RepositoryWebhook = Resource(
144
+ "github::RepositoryWebhook",
145
+ async function (
146
+ this: Context<RepositoryWebhook>,
147
+ _id: string,
148
+ props: RepositoryWebhookProps,
149
+ ): Promise<RepositoryWebhook> {
150
+ // Create authenticated Octokit client
151
+ const octokit = await createGitHubClient({
152
+ token: props.token,
153
+ });
154
+
155
+ // Verify authentication and permissions
156
+ if (!this.quiet) {
157
+ await verifyGitHubAuth(octokit, props.owner, props.repository);
158
+ }
159
+
160
+ if (this.phase === "delete") {
161
+ if (this.output?.webhookId) {
162
+ try {
163
+ // Delete the webhook
164
+ await octokit.rest.repos.deleteWebhook({
165
+ owner: props.owner,
166
+ repo: props.repository,
167
+ hook_id: this.output.webhookId,
168
+ });
169
+ } catch (error: any) {
170
+ // Ignore 404 errors (webhook already deleted)
171
+ if (error.status === 404) {
172
+ logger.log("Webhook doesn't exist, ignoring");
173
+ } else {
174
+ throw error;
175
+ }
176
+ }
177
+ }
178
+
179
+ // Return void (a deleted resource has no content)
180
+ return this.destroy();
181
+ }
182
+
183
+ try {
184
+ const webhookConfig = {
185
+ url: props.url,
186
+ content_type: props.contentType || "application/json",
187
+ insecure_ssl: props.insecureSsl ? "1" : "0",
188
+ ...(props.secret && { secret: props.secret }),
189
+ };
190
+
191
+ const events = props.events || ["push"];
192
+ const active = props.active !== false; // Default to true
193
+
194
+ let webhookData;
195
+ let webhookId: number;
196
+
197
+ if (this.phase === "update" && this.output?.webhookId) {
198
+ // Update existing webhook
199
+ const { data: updatedWebhook } = await octokit.rest.repos.updateWebhook(
200
+ {
201
+ owner: props.owner,
202
+ repo: props.repository,
203
+ hook_id: this.output.webhookId,
204
+ config: webhookConfig,
205
+ events,
206
+ active,
207
+ },
208
+ );
209
+
210
+ webhookData = updatedWebhook;
211
+ webhookId = this.output.webhookId;
212
+ } else {
213
+ // Create new webhook
214
+ const { data: createdWebhook } = await octokit.rest.repos.createWebhook(
215
+ {
216
+ owner: props.owner,
217
+ repo: props.repository,
218
+ name: "web", // GitHub webhook type
219
+ config: webhookConfig,
220
+ events,
221
+ active,
222
+ },
223
+ );
224
+
225
+ webhookData = createdWebhook;
226
+ webhookId = createdWebhook.id;
227
+ }
228
+
229
+ // Return webhook details
230
+ return this({
231
+ id: `${props.owner}/${props.repository}/webhook/${webhookId}`,
232
+ webhookId,
233
+ owner: props.owner,
234
+ repository: props.repository,
235
+ url: props.url,
236
+ secret: props.secret,
237
+ contentType: props.contentType || "application/json",
238
+ insecureSsl: props.insecureSsl,
239
+ active: props.active,
240
+ events: props.events || ["push"],
241
+ token: props.token,
242
+ createdAt: webhookData.created_at,
243
+ updatedAt: webhookData.updated_at,
244
+ pingUrl: webhookData.ping_url,
245
+ testUrl: webhookData.test_url,
246
+ });
247
+ } catch (error: any) {
248
+ if (
249
+ error.status === 403 &&
250
+ error.message?.includes("Must have admin rights")
251
+ ) {
252
+ logger.error(
253
+ "\n⚠️ Error creating/updating GitHub webhook: You must have admin rights to the repository.",
254
+ );
255
+ logger.error(
256
+ "Make sure your GitHub token has the required permissions (repo scope for private repos).\n",
257
+ );
258
+ } else if (error.status === 422) {
259
+ logger.error(
260
+ "\n⚠️ Error creating/updating GitHub webhook: Invalid webhook configuration.",
261
+ );
262
+ logger.error("Check your webhook URL and event configuration.\n");
263
+ } else {
264
+ logger.error("Error creating/updating GitHub webhook:", error.message);
265
+ }
266
+ throw error;
267
+ }
268
+ },
269
+ );
package/src/scope.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import { AsyncLocalStorage } from "node:async_hooks";
2
+ import util from "node:util";
2
3
  import type { Phase } from "./alchemy.ts";
3
4
  import { destroy, destroyAll } from "./destroy.ts";
4
5
  import { FileSystemStateStore } from "./fs/file-system-state-store.ts";
@@ -288,6 +289,10 @@ export class Scope {
288
289
  return Scope.storage.run(this, () => fn(this));
289
290
  }
290
291
 
292
+ [util.inspect.custom]() {
293
+ return `Scope(${this.chain.join("/")})`;
294
+ }
295
+
291
296
  [Symbol.asyncDispose]() {
292
297
  return this.finalize();
293
298
  }