alchemy 0.40.1 → 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.
- package/lib/build-date.d.ts +1 -1
- package/lib/build-date.js +1 -1
- package/lib/cloudflare/bindings.d.ts +2 -1
- package/lib/cloudflare/bindings.d.ts.map +1 -1
- package/lib/cloudflare/bindings.js.map +1 -1
- package/lib/cloudflare/bound.d.ts +2 -1
- package/lib/cloudflare/bound.d.ts.map +1 -1
- package/lib/cloudflare/bundle/bundle-worker-dev.d.ts.map +1 -1
- package/lib/cloudflare/bundle/bundle-worker-dev.js +2 -1
- package/lib/cloudflare/bundle/bundle-worker-dev.js.map +1 -1
- package/lib/cloudflare/bundle/bundle-worker.d.ts.map +1 -1
- package/lib/cloudflare/bundle/bundle-worker.js +2 -1
- package/lib/cloudflare/bundle/bundle-worker.js.map +1 -1
- package/lib/cloudflare/container.d.ts +509 -0
- package/lib/cloudflare/container.d.ts.map +1 -0
- package/lib/cloudflare/container.js +274 -0
- package/lib/cloudflare/container.js.map +1 -0
- 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/worker/miniflare-worker-options.d.ts.map +1 -1
- package/lib/cloudflare/worker/miniflare-worker-options.js +28 -0
- package/lib/cloudflare/worker/miniflare-worker-options.js.map +1 -1
- package/lib/cloudflare/worker-metadata.d.ts +3 -0
- package/lib/cloudflare/worker-metadata.d.ts.map +1 -1
- package/lib/cloudflare/worker-metadata.js +22 -3
- package/lib/cloudflare/worker-metadata.js.map +1 -1
- package/lib/cloudflare/worker.d.ts +2 -1
- package/lib/cloudflare/worker.d.ts.map +1 -1
- package/lib/cloudflare/worker.js +39 -3
- package/lib/cloudflare/worker.js.map +1 -1
- package/lib/cloudflare/wrangler.json.js +11 -0
- package/lib/cloudflare/wrangler.json.js.map +1 -1
- package/lib/docker/api.d.ts +15 -0
- package/lib/docker/api.d.ts.map +1 -1
- package/lib/docker/api.js +59 -0
- package/lib/docker/api.js.map +1 -1
- package/lib/docker/image.d.ts +22 -4
- package/lib/docker/image.d.ts.map +1 -1
- package/lib/docker/image.js +68 -24
- package/lib/docker/image.js.map +1 -1
- package/lib/github/index.d.ts +1 -0
- package/lib/github/index.d.ts.map +1 -1
- package/lib/github/index.js +1 -0
- package/lib/github/index.js.map +1 -1
- package/lib/github/repository-webhook.d.ts +123 -0
- package/lib/github/repository-webhook.d.ts.map +1 -0
- package/lib/github/repository-webhook.js +146 -0
- package/lib/github/repository-webhook.js.map +1 -0
- package/lib/scope.d.ts +2 -0
- package/lib/scope.d.ts.map +1 -1
- package/lib/scope.js +4 -0
- package/lib/scope.js.map +1 -1
- package/package.json +3 -2
- package/src/build-date.ts +1 -1
- package/src/cloudflare/bindings.ts +2 -0
- package/src/cloudflare/bound.ts +9 -1
- package/src/cloudflare/bundle/bundle-worker-dev.ts +2 -1
- package/src/cloudflare/bundle/bundle-worker.ts +2 -1
- package/src/cloudflare/container.ts +843 -0
- package/src/cloudflare/index.ts +1 -0
- package/src/cloudflare/worker/miniflare-worker-options.ts +28 -0
- package/src/cloudflare/worker-metadata.ts +28 -6
- package/src/cloudflare/worker.ts +67 -16
- package/src/cloudflare/wrangler.json.ts +12 -0
- package/src/docker/api.ts +74 -0
- package/src/docker/image.ts +99 -29
- package/src/github/index.ts +1 -0
- package/src/github/repository-webhook.ts +269 -0
- 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
|
}
|