hatchkit 0.1.23 → 0.1.25
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/dist/adopt.js +39 -0
- package/dist/adopt.js.map +1 -1
- package/dist/config.d.ts +18 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +92 -20
- package/dist/config.js.map +1 -1
- package/dist/doctor.d.ts.map +1 -1
- package/dist/doctor.js +97 -3
- package/dist/doctor.js.map +1 -1
- package/dist/index.js +109 -0
- package/dist/index.js.map +1 -1
- package/dist/provision/s3-buckets.d.ts +62 -0
- package/dist/provision/s3-buckets.d.ts.map +1 -0
- package/dist/provision/s3-buckets.js +428 -0
- package/dist/provision/s3-buckets.js.map +1 -0
- package/dist/scaffold/manifest.d.ts +24 -0
- package/dist/scaffold/manifest.d.ts.map +1 -1
- package/dist/scaffold/manifest.js.map +1 -1
- package/dist/utils/cloudflare-api.d.ts +96 -0
- package/dist/utils/cloudflare-api.d.ts.map +1 -1
- package/dist/utils/cloudflare-api.js +176 -0
- package/dist/utils/cloudflare-api.js.map +1 -1
- package/dist/utils/secrets.d.ts +30 -0
- package/dist/utils/secrets.d.ts.map +1 -1
- package/dist/utils/secrets.js +30 -0
- package/dist/utils/secrets.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,428 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* S3/R2 bucket provisioning for adopted projects.
|
|
3
|
+
*
|
|
4
|
+
* Closes the gap between `hatchkit config add s3 r2` (which only stores
|
|
5
|
+
* credentials in the global config + keychain) and a project that
|
|
6
|
+
* actually needs working buckets + env wiring at runtime. Splits the
|
|
7
|
+
* provisioning into two clear roles:
|
|
8
|
+
*
|
|
9
|
+
* · "assets" — public, hot path. Fronts large pre-built media
|
|
10
|
+
* (AVIF/WebP/originals). Public URL goes into a
|
|
11
|
+
* NEXT_PUBLIC_ASSETS_BASE_URL-style env var so the
|
|
12
|
+
* client can fetch directly.
|
|
13
|
+
* · "state" — private, cold. Used for small server-side files
|
|
14
|
+
* (cron state, audit logs). Never publicly reachable.
|
|
15
|
+
*
|
|
16
|
+
* Public URL strategy for the assets bucket, in order:
|
|
17
|
+
* 1. Custom domain on a Cloudflare zone the user owns
|
|
18
|
+
* (`assets.<project-domain>` or a caller-provided override) —
|
|
19
|
+
* preferred long-term, no `r2.dev` rate limits.
|
|
20
|
+
* 2. Managed `pub-<hash>.r2.dev` domain — fallback when no zone
|
|
21
|
+
* matches the project's domain.
|
|
22
|
+
*
|
|
23
|
+
* Env var names are project-specific. Some projects standardised on
|
|
24
|
+
* R2_*; others on the generic S3_* / AWS_* set the starter ships. We
|
|
25
|
+
* sniff the project's `.env.example` for whichever prefix the runtime
|
|
26
|
+
* already reads, so the seeded values match. Without this the env
|
|
27
|
+
* lands under names the app's `process.env.X` calls won't pick up.
|
|
28
|
+
*
|
|
29
|
+
* Idempotent on every step: existing buckets are reused (409 →
|
|
30
|
+
* success), existing managed/custom domains are re-fetched, and env
|
|
31
|
+
* vars overwrite in place (so re-runs after a failure don't duplicate
|
|
32
|
+
* lines or leave the file half-written).
|
|
33
|
+
*/
|
|
34
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
35
|
+
import { join } from "node:path";
|
|
36
|
+
import { set as dotenvxSet } from "@dotenvx/dotenvx";
|
|
37
|
+
import chalk from "chalk";
|
|
38
|
+
import ora from "ora";
|
|
39
|
+
import { getDnsConfig } from "../config.js";
|
|
40
|
+
import { MANIFEST_FILENAME, readManifest, writeManifest, } from "../scaffold/manifest.js";
|
|
41
|
+
import { CloudflareApi } from "../utils/cloudflare-api.js";
|
|
42
|
+
import { SECRET_KEYS, getSecret, setSecret } from "../utils/secrets.js";
|
|
43
|
+
/** Account ID = the subdomain in the S3 endpoint
|
|
44
|
+
* `https://<accountId>.r2.cloudflarestorage.com`. */
|
|
45
|
+
export function accountIdFromR2Endpoint(endpoint) {
|
|
46
|
+
const m = endpoint.match(/https?:\/\/([0-9a-f]{32})\.r2\.cloudflarestorage\.com/i);
|
|
47
|
+
if (!m)
|
|
48
|
+
throw new Error(`Endpoint ${endpoint} doesn't look like an R2 S3 endpoint.`);
|
|
49
|
+
return m[1];
|
|
50
|
+
}
|
|
51
|
+
/** Sniff the project's `.env.example` (and falling back to source files)
|
|
52
|
+
* to pick the env-var prefix the runtime already reads. Some projects
|
|
53
|
+
* use R2_*, others S3_*, others AWS_*. Picking the wrong prefix here
|
|
54
|
+
* is the difference between "deploys" and "deploys but every request
|
|
55
|
+
* throws Missing required env var". */
|
|
56
|
+
export function detectEnvPrefix(projectDir) {
|
|
57
|
+
const candidates = [
|
|
58
|
+
join(projectDir, ".env.example"),
|
|
59
|
+
join(projectDir, ".env.development"),
|
|
60
|
+
join(projectDir, ".env.production"),
|
|
61
|
+
];
|
|
62
|
+
let r2 = 0;
|
|
63
|
+
let s3 = 0;
|
|
64
|
+
let aws = 0;
|
|
65
|
+
for (const p of candidates) {
|
|
66
|
+
if (!existsSync(p))
|
|
67
|
+
continue;
|
|
68
|
+
const text = readFileSync(p, "utf-8");
|
|
69
|
+
r2 += (text.match(/(^|\s)R2_[A-Z_]+\s*=/gm) ?? []).length;
|
|
70
|
+
s3 += (text.match(/(^|\s)S3_[A-Z_]+\s*=/gm) ?? []).length;
|
|
71
|
+
aws += (text.match(/(^|\s)AWS_(REGION|ACCESS_KEY_ID|SECRET_ACCESS_KEY)\s*=/gm) ?? []).length;
|
|
72
|
+
}
|
|
73
|
+
// Highest wins; ties prefer R2 (most explicit) > S3 > AWS.
|
|
74
|
+
const pairs = [
|
|
75
|
+
["R2", r2],
|
|
76
|
+
["S3", s3],
|
|
77
|
+
["AWS", aws],
|
|
78
|
+
];
|
|
79
|
+
pairs.sort((a, b) => b[1] - a[1]);
|
|
80
|
+
if (pairs[0][1] === 0)
|
|
81
|
+
return "S3"; // nothing detected — match starter default
|
|
82
|
+
return pairs[0][0];
|
|
83
|
+
}
|
|
84
|
+
/** Map the detected prefix to the full set of env var names. R2 and S3
|
|
85
|
+
* use distinct endpoint/bucket names but share the access-key shape;
|
|
86
|
+
* AWS uses the AWS_* triple instead of S3_*. */
|
|
87
|
+
export function envKeysForPrefix(prefix) {
|
|
88
|
+
if (prefix === "R2") {
|
|
89
|
+
return {
|
|
90
|
+
endpoint: "R2_ENDPOINT",
|
|
91
|
+
accessKey: "R2_ACCESS_KEY_ID",
|
|
92
|
+
secretKey: "R2_SECRET_ACCESS_KEY",
|
|
93
|
+
region: "R2_REGION",
|
|
94
|
+
bucket: "R2_STATE_BUCKET",
|
|
95
|
+
publicUrl: "NEXT_PUBLIC_ASSETS_BASE_URL",
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
if (prefix === "AWS") {
|
|
99
|
+
return {
|
|
100
|
+
endpoint: "S3_ENDPOINT",
|
|
101
|
+
accessKey: "AWS_ACCESS_KEY_ID",
|
|
102
|
+
secretKey: "AWS_SECRET_ACCESS_KEY",
|
|
103
|
+
region: "AWS_REGION",
|
|
104
|
+
bucket: "S3_BUCKET_NAME",
|
|
105
|
+
publicUrl: "S3_PUBLIC_URL",
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
return {
|
|
109
|
+
endpoint: "S3_ENDPOINT",
|
|
110
|
+
accessKey: "S3_ACCESS_KEY_ID",
|
|
111
|
+
secretKey: "S3_SECRET_ACCESS_KEY",
|
|
112
|
+
region: "S3_REGION",
|
|
113
|
+
bucket: "S3_BUCKET_NAME",
|
|
114
|
+
publicUrl: "S3_PUBLIC_URL",
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
/** Read existing keys in `.env.production` so re-runs don't clobber a
|
|
118
|
+
* value the user has since edited. Returns the set of plain or
|
|
119
|
+
* encrypted KEYs present (we don't try to decrypt — encrypted values
|
|
120
|
+
* always have a `KEY="encrypted:..."` shape). */
|
|
121
|
+
function existingEnvKeys(envPath) {
|
|
122
|
+
if (!existsSync(envPath))
|
|
123
|
+
return new Set();
|
|
124
|
+
const text = readFileSync(envPath, "utf-8");
|
|
125
|
+
const keys = new Set();
|
|
126
|
+
for (const line of text.split("\n")) {
|
|
127
|
+
const m = line.match(/^([A-Z][A-Z0-9_]*)=/);
|
|
128
|
+
if (m)
|
|
129
|
+
keys.add(m[1]);
|
|
130
|
+
}
|
|
131
|
+
return keys;
|
|
132
|
+
}
|
|
133
|
+
/** Build the rclone config snippet the user can paste into
|
|
134
|
+
* `~/.config/rclone/rclone.conf`. Keeps this OUT of the file system
|
|
135
|
+
* (the user's existing rclone config has other remotes — we don't
|
|
136
|
+
* want to mangle them). */
|
|
137
|
+
function buildRcloneSnippet(opts) {
|
|
138
|
+
return [
|
|
139
|
+
`[${opts.remoteName}]`,
|
|
140
|
+
`type = s3`,
|
|
141
|
+
`provider = Cloudflare`,
|
|
142
|
+
`access_key_id = ${opts.accessKey}`,
|
|
143
|
+
`secret_access_key = ${opts.secretKey}`,
|
|
144
|
+
`endpoint = ${opts.endpoint}`,
|
|
145
|
+
`acl = private`,
|
|
146
|
+
`no_check_bucket = true`,
|
|
147
|
+
"",
|
|
148
|
+
].join("\n");
|
|
149
|
+
}
|
|
150
|
+
/** Provision the public+private bucket pair for an adopted project,
|
|
151
|
+
* wire the resulting credentials/URLs into its `.env.production`, and
|
|
152
|
+
* record the bucket names in `.hatchkit.json`. Idempotent on re-run. */
|
|
153
|
+
export async function provisionS3ForProject(opts) {
|
|
154
|
+
const provider = opts.provider ?? "r2";
|
|
155
|
+
const manifest = readManifest(opts.projectDir);
|
|
156
|
+
if (!manifest) {
|
|
157
|
+
throw new Error(`No ${MANIFEST_FILENAME} in ${opts.projectDir}. Run \`hatchkit adopt\` first.`);
|
|
158
|
+
}
|
|
159
|
+
// Provider metadata (endpoint + region). Read from the Conf JSON
|
|
160
|
+
// store directly so we don't require the legacy account-wide
|
|
161
|
+
// access/secret pair to exist — the new model issues per-project
|
|
162
|
+
// creds at provision-time, the global pair is no longer the source
|
|
163
|
+
// of truth for runtime S3 ops.
|
|
164
|
+
if (provider !== "r2") {
|
|
165
|
+
throw new Error(`Bucket auto-provisioning is only implemented for R2 today (got ${provider}). PRs welcome.`);
|
|
166
|
+
}
|
|
167
|
+
const { getStore } = await import("../config.js");
|
|
168
|
+
const meta = getStore().get(`providers.s3.${provider}`);
|
|
169
|
+
if (!meta || meta.status !== "configured" || !meta.endpoint) {
|
|
170
|
+
throw new Error(`S3 provider "${provider}" is not configured. Run \`hatchkit config add s3\` and pick ${provider}.`);
|
|
171
|
+
}
|
|
172
|
+
const accountId = accountIdFromR2Endpoint(meta.endpoint);
|
|
173
|
+
// DNS config — needed only when we're about to attempt a custom
|
|
174
|
+
// domain. Absence is fine; we fall back to the managed r2.dev URL.
|
|
175
|
+
const dns = await getDnsConfig();
|
|
176
|
+
// R2 admin token. Kept separate from the DNS token because the DNS
|
|
177
|
+
// token is typically scoped narrowly (Zone:DNS:Edit + Zone:Zone:Read)
|
|
178
|
+
// and the R2 admin endpoints need account-level perms. Caller
|
|
179
|
+
// (handleProvisionS3) is responsible for prompting + storing this
|
|
180
|
+
// when missing — this function fails fast so non-interactive callers
|
|
181
|
+
// (adopt's auto-step) get a clear hint instead of an opaque 10000.
|
|
182
|
+
const adminToken = await getSecret(SECRET_KEYS.r2AdminToken);
|
|
183
|
+
if (!adminToken) {
|
|
184
|
+
throw new Error("R2 admin token not configured. Run `hatchkit provision s3` interactively, " +
|
|
185
|
+
"or pre-set with: hatchkit config add s3 (TODO) — needs Account > Workers R2 Storage > Edit.");
|
|
186
|
+
}
|
|
187
|
+
// For the zone lookup (custom-domain attach) we need the DNS token's
|
|
188
|
+
// Zone:Zone:Read; the admin token may or may not have it. Use whichever
|
|
189
|
+
// we have available, preferring the DNS token because that's the one
|
|
190
|
+
// that's been verified for zone reads in `hatchkit doctor`.
|
|
191
|
+
const zoneToken = dns?.provider === "cloudflare" ? (dns.apiToken ?? adminToken) : adminToken;
|
|
192
|
+
const cf = new CloudflareApi({ token: adminToken });
|
|
193
|
+
const cfZone = new CloudflareApi({ token: zoneToken });
|
|
194
|
+
const projectName = manifest.name;
|
|
195
|
+
const domain = manifest.domain;
|
|
196
|
+
const assetsBucketName = opts.assetsBucketName ?? `${projectName}-assets`;
|
|
197
|
+
const stateBucketName = opts.stateBucketName ?? `${projectName}-state`;
|
|
198
|
+
const locationHint = opts.locationHint ?? "weur";
|
|
199
|
+
// 1. Create the two buckets (idempotent).
|
|
200
|
+
const spinner = ora(`Creating R2 buckets (${assetsBucketName}, ${stateBucketName})`).start();
|
|
201
|
+
let assetsBucket;
|
|
202
|
+
let stateBucket;
|
|
203
|
+
try {
|
|
204
|
+
assetsBucket = await cf.createR2Bucket(accountId, assetsBucketName, { locationHint });
|
|
205
|
+
stateBucket = await cf.createR2Bucket(accountId, stateBucketName, { locationHint });
|
|
206
|
+
spinner.succeed(`R2 buckets ready — ${assetsBucketName} (${assetsBucket.existed ? "exists" : "created"}), ${stateBucketName} (${stateBucket.existed ? "exists" : "created"})`);
|
|
207
|
+
}
|
|
208
|
+
catch (err) {
|
|
209
|
+
spinner.fail("R2 bucket creation failed");
|
|
210
|
+
const msg = err.message;
|
|
211
|
+
if (/403|10001|permission/i.test(msg)) {
|
|
212
|
+
throw new Error(`${msg}\n\n → Cloudflare token is missing the "Workers R2 Storage: Edit" permission.\n → Edit it at https://dash.cloudflare.com/profile/api-tokens, then re-run.`);
|
|
213
|
+
}
|
|
214
|
+
throw err;
|
|
215
|
+
}
|
|
216
|
+
// 2. Public URL for the assets bucket. Prefer a custom domain on a
|
|
217
|
+
// Cloudflare zone we own; fall back to the managed r2.dev URL.
|
|
218
|
+
let publicUrl;
|
|
219
|
+
let publicUrlSource;
|
|
220
|
+
// Pick the hostname. Default `assets.<domain>`; allow caller override.
|
|
221
|
+
const customHostname = opts.publicHostname ?? `assets.${domain}`;
|
|
222
|
+
// Find the closest matching zone (the registrable name — last
|
|
223
|
+
// two labels of the host, or the host itself if the user passed a
|
|
224
|
+
// bare apex).
|
|
225
|
+
const zoneName = pickClosestZoneName(customHostname);
|
|
226
|
+
try {
|
|
227
|
+
const zone = await cfZone.getZoneByName(zoneName);
|
|
228
|
+
if (zone) {
|
|
229
|
+
const customSpinner = ora(`Attaching custom domain ${customHostname}`).start();
|
|
230
|
+
try {
|
|
231
|
+
const cd = await cf.addR2CustomDomain(accountId, assetsBucketName, {
|
|
232
|
+
domain: customHostname,
|
|
233
|
+
zoneId: zone.id,
|
|
234
|
+
minTLS: "1.2",
|
|
235
|
+
});
|
|
236
|
+
publicUrl = `https://${cd.domain}`;
|
|
237
|
+
publicUrlSource = "custom-domain";
|
|
238
|
+
customSpinner.succeed(`Custom domain ${cd.existed ? "already attached" : "attached"} — ${publicUrl}`);
|
|
239
|
+
}
|
|
240
|
+
catch (err) {
|
|
241
|
+
customSpinner.warn(`Custom domain failed (${err.message.split("\n")[0]}) — falling back to r2.dev managed URL`);
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
catch (err) {
|
|
246
|
+
// Zone lookup is best-effort. Don't fail the whole flow on it.
|
|
247
|
+
console.log(chalk.dim(` · Zone lookup for ${zoneName} failed: ${err.message.split("\n")[0]}`));
|
|
248
|
+
}
|
|
249
|
+
if (!publicUrl) {
|
|
250
|
+
const managedSpinner = ora(`Enabling managed r2.dev URL on ${assetsBucketName}`).start();
|
|
251
|
+
try {
|
|
252
|
+
const md = await cf.enableR2ManagedDomain(accountId, assetsBucketName, true);
|
|
253
|
+
publicUrl = `https://${md.domain}`;
|
|
254
|
+
publicUrlSource = "managed-r2dev";
|
|
255
|
+
managedSpinner.succeed(`Managed r2.dev URL enabled — ${publicUrl}`);
|
|
256
|
+
}
|
|
257
|
+
catch (err) {
|
|
258
|
+
managedSpinner.fail("Could not enable a public URL on the assets bucket");
|
|
259
|
+
throw err;
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
// 3. Mint a per-project R2 API token scoped to just these two
|
|
263
|
+
// buckets. Returns the S3-style access/secret pair (access =
|
|
264
|
+
// token id, secret = sha256(token value)). Re-mint on every
|
|
265
|
+
// re-run — keychain holds the canonical copy and idempotency
|
|
266
|
+
// on the CF side is good enough that the worst case is a few
|
|
267
|
+
// orphaned old tokens (cleaned up by `hatchkit destroy`).
|
|
268
|
+
//
|
|
269
|
+
// If a token already exists in keychain for this project, REUSE
|
|
270
|
+
// it instead of re-minting. This keeps `hatchkit provision s3`
|
|
271
|
+
// idempotent w/r/t the user's CF account (no token churn) and
|
|
272
|
+
// means rotating credentials is an explicit `--rotate` step
|
|
273
|
+
// rather than a side effect.
|
|
274
|
+
const existingProjectAccess = await getSecret(SECRET_KEYS.s3ProjectAccessKey(provider, projectName));
|
|
275
|
+
const existingProjectSecret = await getSecret(SECRET_KEYS.s3ProjectSecretKey(provider, projectName));
|
|
276
|
+
let projectAccessKey;
|
|
277
|
+
let projectSecretKey;
|
|
278
|
+
let projectTokenId;
|
|
279
|
+
if (existingProjectAccess && existingProjectSecret) {
|
|
280
|
+
projectAccessKey = existingProjectAccess;
|
|
281
|
+
projectSecretKey = existingProjectSecret;
|
|
282
|
+
projectTokenId =
|
|
283
|
+
(await getSecret(SECRET_KEYS.s3ProjectTokenId(provider, projectName))) ?? undefined;
|
|
284
|
+
console.log(chalk.dim(` · Reusing existing per-project R2 credentials (keychain ${SECRET_KEYS.s3ProjectAccessKey(provider, projectName)})`));
|
|
285
|
+
}
|
|
286
|
+
else {
|
|
287
|
+
const tokenSpinner = ora(`Minting per-project R2 API token (scoped to those 2 buckets)`).start();
|
|
288
|
+
try {
|
|
289
|
+
const minted = await cf.createR2ApiToken({
|
|
290
|
+
accountId,
|
|
291
|
+
name: `hatchkit-${projectName}`,
|
|
292
|
+
bucketNames: [assetsBucketName, stateBucketName],
|
|
293
|
+
permissions: "read-write",
|
|
294
|
+
});
|
|
295
|
+
projectAccessKey = minted.accessKeyId;
|
|
296
|
+
projectSecretKey = minted.secretAccessKey;
|
|
297
|
+
projectTokenId = minted.tokenId;
|
|
298
|
+
await setSecret(SECRET_KEYS.s3ProjectAccessKey(provider, projectName), minted.accessKeyId);
|
|
299
|
+
await setSecret(SECRET_KEYS.s3ProjectSecretKey(provider, projectName), minted.secretAccessKey);
|
|
300
|
+
await setSecret(SECRET_KEYS.s3ProjectTokenId(provider, projectName), minted.tokenId);
|
|
301
|
+
tokenSpinner.succeed(`Minted scoped R2 API token (id ${minted.tokenId.slice(0, 8)}…, stored in keychain)`);
|
|
302
|
+
}
|
|
303
|
+
catch (err) {
|
|
304
|
+
tokenSpinner.fail("Failed to mint per-project R2 API token");
|
|
305
|
+
const msg = err.message;
|
|
306
|
+
if (/9109|10000|403|invalid api token/i.test(msg)) {
|
|
307
|
+
throw new Error(`${msg}\n\n → Your admin token (s3:r2:admin-token) needs BOTH:\n · Account > Workers R2 Storage > Edit\n · User > API Tokens > Edit (this is what's missing)\n → Edit at https://dash.cloudflare.com/profile/api-tokens, save, re-run.`);
|
|
308
|
+
}
|
|
309
|
+
throw err;
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
// 4. Seed `.env.production` with the credentials + URLs. Names are
|
|
313
|
+
// chosen by the prefix the project's runtime actually reads —
|
|
314
|
+
// detected from `.env.example` etc.
|
|
315
|
+
const envPrefix = opts.envPrefix ?? detectEnvPrefix(opts.projectDir);
|
|
316
|
+
const keys = envKeysForPrefix(envPrefix);
|
|
317
|
+
const envPath = join(opts.projectDir, ".env.production");
|
|
318
|
+
const existingKeys = existingEnvKeys(envPath);
|
|
319
|
+
const toWrite = [];
|
|
320
|
+
const skip = (key) => existingKeys.has(key);
|
|
321
|
+
// ENDPOINT, ACCESS_KEY, SECRET_KEY, REGION are credentials that
|
|
322
|
+
// the runtime always needs. Re-write on every run (cheap, and the
|
|
323
|
+
// user might've rotated keys). REGION is "auto" for R2 — the SDK
|
|
324
|
+
// ignores it anyway when an explicit endpoint is given, but
|
|
325
|
+
// setting it suppresses an `AWS_REGION` warning at runtime.
|
|
326
|
+
toWrite.push({ key: keys.endpoint, value: meta.endpoint });
|
|
327
|
+
toWrite.push({ key: keys.accessKey, value: projectAccessKey });
|
|
328
|
+
toWrite.push({ key: keys.secretKey, value: projectSecretKey });
|
|
329
|
+
toWrite.push({ key: keys.region, value: meta.region ?? "auto" });
|
|
330
|
+
// BUCKET name — keys.bucket is "<PREFIX>_STATE_BUCKET" for R2 (the
|
|
331
|
+
// private bucket is the only one a server lib reads through env;
|
|
332
|
+
// assets are URL-driven). For S3/AWS prefixes the canonical key is
|
|
333
|
+
// <PREFIX>_BUCKET_NAME pointing at the assets bucket. Match the
|
|
334
|
+
// semantics of each prefix.
|
|
335
|
+
if (envPrefix === "R2") {
|
|
336
|
+
toWrite.push({ key: keys.bucket, value: stateBucketName });
|
|
337
|
+
}
|
|
338
|
+
else {
|
|
339
|
+
toWrite.push({ key: keys.bucket, value: assetsBucketName });
|
|
340
|
+
}
|
|
341
|
+
// Public URL — only seed if the project's runtime reads the
|
|
342
|
+
// matching key. Detected via `.env.example` keys for both the
|
|
343
|
+
// primary (`NEXT_PUBLIC_ASSETS_BASE_URL`) and the prefixed fallback.
|
|
344
|
+
// Always write it under NEXT_PUBLIC_ASSETS_BASE_URL when present in
|
|
345
|
+
// .env.example since that's the next.js convention; under
|
|
346
|
+
// <PREFIX>_PUBLIC_URL for non-Next projects.
|
|
347
|
+
const examplePath = join(opts.projectDir, ".env.example");
|
|
348
|
+
const exampleText = existsSync(examplePath) ? readFileSync(examplePath, "utf-8") : "";
|
|
349
|
+
const usesNextPublicAssets = /NEXT_PUBLIC_ASSETS_BASE_URL/.test(exampleText);
|
|
350
|
+
if (usesNextPublicAssets) {
|
|
351
|
+
toWrite.push({ key: "NEXT_PUBLIC_ASSETS_BASE_URL", value: publicUrl });
|
|
352
|
+
}
|
|
353
|
+
else if (envPrefix === "S3" || envPrefix === "AWS") {
|
|
354
|
+
toWrite.push({ key: keys.publicUrl, value: publicUrl });
|
|
355
|
+
}
|
|
356
|
+
// CRON_SECRET — the project's .env.example documents one if it has
|
|
357
|
+
// a cron route. Generate fresh, encrypt. Skip if already set.
|
|
358
|
+
if (opts.generateCronSecret !== false &&
|
|
359
|
+
/CRON_SECRET/.test(exampleText) &&
|
|
360
|
+
!skip("CRON_SECRET")) {
|
|
361
|
+
const { randomBytes } = await import("node:crypto");
|
|
362
|
+
toWrite.push({ key: "CRON_SECRET", value: randomBytes(32).toString("hex") });
|
|
363
|
+
}
|
|
364
|
+
const envWritten = [];
|
|
365
|
+
const envKept = [];
|
|
366
|
+
const envSpinner = ora(`Writing ${toWrite.length} entries to .env.production`).start();
|
|
367
|
+
try {
|
|
368
|
+
for (const { key, value } of toWrite) {
|
|
369
|
+
// Idempotency: re-write everything except CRON_SECRET (treated
|
|
370
|
+
// above) on every run. dotenvx.set overwrites in place, so
|
|
371
|
+
// values stay singletons in the file.
|
|
372
|
+
if (key === "CRON_SECRET" && skip(key)) {
|
|
373
|
+
envKept.push(key);
|
|
374
|
+
continue;
|
|
375
|
+
}
|
|
376
|
+
dotenvxSet(key, value, { path: envPath, encrypt: true });
|
|
377
|
+
envWritten.push(key);
|
|
378
|
+
}
|
|
379
|
+
envSpinner.succeed(`Wrote ${envWritten.length} encrypted entries to .env.production`);
|
|
380
|
+
}
|
|
381
|
+
catch (err) {
|
|
382
|
+
envSpinner.fail("Could not write .env.production");
|
|
383
|
+
throw err;
|
|
384
|
+
}
|
|
385
|
+
// 4. Record bucket names + public URL in the manifest so re-runs
|
|
386
|
+
// don't have to re-derive them and a future `hatchkit destroy`
|
|
387
|
+
// knows what to clean up.
|
|
388
|
+
const updated = {
|
|
389
|
+
...manifest,
|
|
390
|
+
s3Buckets: {
|
|
391
|
+
assets: { name: assetsBucketName, publicUrl },
|
|
392
|
+
state: { name: stateBucketName, publicUrl: null },
|
|
393
|
+
},
|
|
394
|
+
};
|
|
395
|
+
writeManifest(opts.projectDir, updated);
|
|
396
|
+
console.log(chalk.dim(` · Recorded bucket names in ${MANIFEST_FILENAME} (${publicUrlSource}).`));
|
|
397
|
+
// 5. rclone snippet (printed by caller, returned here so callers
|
|
398
|
+
// can capture it programmatically too). Uses the per-project
|
|
399
|
+
// scoped credentials we just minted — anyone running rclone
|
|
400
|
+
// against this remote can only touch this project's two buckets.
|
|
401
|
+
// Don't write the snippet to disk; the user's existing rclone
|
|
402
|
+
// config has unrelated remotes and we don't want to mangle them.
|
|
403
|
+
const rcloneSnippet = buildRcloneSnippet({
|
|
404
|
+
remoteName: `r2-${projectName}`,
|
|
405
|
+
endpoint: meta.endpoint,
|
|
406
|
+
accessKey: projectAccessKey,
|
|
407
|
+
secretKey: projectSecretKey,
|
|
408
|
+
});
|
|
409
|
+
return {
|
|
410
|
+
assets: { name: assetsBucketName, publicUrl, created: !assetsBucket.existed },
|
|
411
|
+
state: { name: stateBucketName, created: !stateBucket.existed },
|
|
412
|
+
envWritten,
|
|
413
|
+
envKept,
|
|
414
|
+
rcloneSnippet,
|
|
415
|
+
};
|
|
416
|
+
}
|
|
417
|
+
/** Pick the registrable zone name for a hostname. Cloudflare keeps
|
|
418
|
+
* zones at the registrable level (example.com), so to attach
|
|
419
|
+
* `assets.foo.example.com` we look up `example.com`. Two-label
|
|
420
|
+
* apex stays as-is. This is the same shape the existing DNS code
|
|
421
|
+
* uses; see `cli/src/deploy/coolify-app.ts` for parallels. */
|
|
422
|
+
function pickClosestZoneName(hostname) {
|
|
423
|
+
const parts = hostname.split(".");
|
|
424
|
+
if (parts.length <= 2)
|
|
425
|
+
return hostname;
|
|
426
|
+
return parts.slice(-2).join(".");
|
|
427
|
+
}
|
|
428
|
+
//# sourceMappingURL=s3-buckets.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"s3-buckets.js","sourceRoot":"","sources":["../../src/provision/s3-buckets.ts"],"names":[],"mappings":"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"}
|
|
@@ -45,6 +45,30 @@ export interface ProjectManifest {
|
|
|
45
45
|
* Optional for back-compat with manifests written before this
|
|
46
46
|
* field existed; readers should fall back to detection. */
|
|
47
47
|
surfaces?: "server-only" | "client-only" | "both";
|
|
48
|
+
/** S3 buckets provisioned by `hatchkit provision s3`. Names go in
|
|
49
|
+
* the manifest (so re-runs are idempotent and `hatchkit destroy`
|
|
50
|
+
* knows what to undo); credentials never do — those live in the
|
|
51
|
+
* global config / OS keychain.
|
|
52
|
+
*
|
|
53
|
+
* `assets` is the public bucket fronting NEXT_PUBLIC_ASSETS_BASE_URL
|
|
54
|
+
* or equivalent. Reachable over HTTPS via either an r2.dev
|
|
55
|
+
* managed domain or a custom domain on a zone the user owns.
|
|
56
|
+
* `state` is the private bucket — used for state files, logs, cron
|
|
57
|
+
* inputs. Never publicly readable.
|
|
58
|
+
*
|
|
59
|
+
* `publicUrl` is the canonical no-trailing-slash URL the runtime
|
|
60
|
+
* should serve assets from. Always present on `assets`; null on
|
|
61
|
+
* `state` (private buckets aren't publicly reachable). */
|
|
62
|
+
s3Buckets?: {
|
|
63
|
+
assets?: {
|
|
64
|
+
name: string;
|
|
65
|
+
publicUrl: string;
|
|
66
|
+
};
|
|
67
|
+
state?: {
|
|
68
|
+
name: string;
|
|
69
|
+
publicUrl: null;
|
|
70
|
+
};
|
|
71
|
+
};
|
|
48
72
|
}
|
|
49
73
|
/** Build a manifest from the internal ProjectConfig, explicitly
|
|
50
74
|
* whitelisting only the safe fields. Any new field on ProjectConfig
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"manifest.d.ts","sourceRoot":"","sources":["../../src/scaffold/manifest.ts"],"names":[],"mappings":"AAgCA,OAAO,KAAK,EAAE,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAChG,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEtD,eAAO,MAAM,iBAAiB,mBAAmB,CAAC;AAClD,eAAO,MAAM,gBAAgB,IAAI,CAAC;AAElC,MAAM,WAAW,eAAe;IAC9B,qEAAqE;IACrE,OAAO,EAAE,OAAO,gBAAgB,CAAC;IACjC,iEAAiE;IACjE,UAAU,EAAE,MAAM,CAAC;IACnB,qCAAqC;IACrC,YAAY,EAAE,MAAM,CAAC;IACrB,mEAAmE;IACnE,IAAI,EAAE,MAAM,CAAC;IACb,gEAAgE;IAChE,MAAM,EAAE,MAAM,CAAC;IACf,0CAA0C;IAC1C,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,0CAA0C;IAC1C,UAAU,EAAE,SAAS,EAAE,CAAC;IACxB;6DACyD;IACzD,UAAU,EAAE,UAAU,CAAC;IACvB;qDACiD;IACjD,YAAY,EAAE,UAAU,GAAG,KAAK,CAAC;IACjC;;mDAE+C;IAC/C,YAAY,CAAC,EAAE,WAAW,EAAE,CAAC;IAC7B,oEAAoE;IACpE,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,2DAA2D;IAC3D,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB;oEACgE;IAChE,KAAK,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC9D;;;;;gEAK4D;IAC5D,QAAQ,CAAC,EAAE,aAAa,GAAG,aAAa,GAAG,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"manifest.d.ts","sourceRoot":"","sources":["../../src/scaffold/manifest.ts"],"names":[],"mappings":"AAgCA,OAAO,KAAK,EAAE,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAChG,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEtD,eAAO,MAAM,iBAAiB,mBAAmB,CAAC;AAClD,eAAO,MAAM,gBAAgB,IAAI,CAAC;AAElC,MAAM,WAAW,eAAe;IAC9B,qEAAqE;IACrE,OAAO,EAAE,OAAO,gBAAgB,CAAC;IACjC,iEAAiE;IACjE,UAAU,EAAE,MAAM,CAAC;IACnB,qCAAqC;IACrC,YAAY,EAAE,MAAM,CAAC;IACrB,mEAAmE;IACnE,IAAI,EAAE,MAAM,CAAC;IACb,gEAAgE;IAChE,MAAM,EAAE,MAAM,CAAC;IACf,0CAA0C;IAC1C,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,0CAA0C;IAC1C,UAAU,EAAE,SAAS,EAAE,CAAC;IACxB;6DACyD;IACzD,UAAU,EAAE,UAAU,CAAC;IACvB;qDACiD;IACjD,YAAY,EAAE,UAAU,GAAG,KAAK,CAAC;IACjC;;mDAE+C;IAC/C,YAAY,CAAC,EAAE,WAAW,EAAE,CAAC;IAC7B,oEAAoE;IACpE,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,2DAA2D;IAC3D,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB;oEACgE;IAChE,KAAK,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC9D;;;;;gEAK4D;IAC5D,QAAQ,CAAC,EAAE,aAAa,GAAG,aAAa,GAAG,MAAM,CAAC;IAClD;;;;;;;;;;;;;+DAa2D;IAC3D,SAAS,CAAC,EAAE;QACV,MAAM,CAAC,EAAE;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,SAAS,EAAE,MAAM,CAAA;SAAE,CAAC;QAC7C,KAAK,CAAC,EAAE;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,SAAS,EAAE,IAAI,CAAA;SAAE,CAAC;KAC3C,CAAC;CACH;AAED;;oEAEoE;AACpE,wBAAgB,UAAU,CACxB,MAAM,EAAE,aAAa,EACrB,KAAK,EAAE,YAAY,EACnB,UAAU,EAAE,MAAM,GACjB,eAAe,CAoBjB;AAED,wBAAgB,aAAa,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,eAAe,GAAG,IAAI,CAGhF;AAED;;;gCAGgC;AAChC,wBAAgB,YAAY,CAAC,UAAU,EAAE,MAAM,GAAG,eAAe,GAAG,IAAI,CAiBvE"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"manifest.js","sourceRoot":"","sources":["../../src/scaffold/manifest.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAEH,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAClE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAIjC,MAAM,CAAC,MAAM,iBAAiB,GAAG,gBAAgB,CAAC;AAClD,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"manifest.js","sourceRoot":"","sources":["../../src/scaffold/manifest.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAEH,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAClE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAIjC,MAAM,CAAC,MAAM,iBAAiB,GAAG,gBAAgB,CAAC;AAClD,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,CAAC;AA6DlC;;oEAEoE;AACpE,MAAM,UAAU,UAAU,CACxB,MAAqB,EACrB,KAAmB,EACnB,UAAkB;IAElB,OAAO;QACL,OAAO,EAAE,gBAAgB;QACzB,UAAU;QACV,YAAY,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;QACtC,IAAI,EAAE,MAAM,CAAC,IAAI;QACjB,MAAM,EAAE,MAAM,CAAC,MAAM;QACrB,QAAQ,EAAE,CAAC,GAAG,MAAM,CAAC,QAAQ,CAAC;QAC9B,UAAU,EAAE,CAAC,GAAG,MAAM,CAAC,UAAU,CAAC;QAClC,UAAU,EAAE,MAAM,CAAC,UAAU;QAC7B,YAAY,EAAE,MAAM,CAAC,YAAY;QACjC,YAAY,EAAE,MAAM,CAAC,YAAY;QACjC,eAAe,EAAE,MAAM,CAAC,eAAe;QACvC,eAAe,EAAE,MAAM,CAAC,eAAe;QACvC,KAAK,EAAE;YACL,MAAM,EAAE,KAAK,CAAC,MAAM;YACpB,MAAM,EAAE,KAAK,CAAC,MAAM;YACpB,SAAS,EAAE,KAAK,CAAC,SAAS;SAC3B;KACF,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,SAAiB,EAAE,QAAyB;IACxE,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,EAAE,iBAAiB,CAAC,CAAC;IAChD,aAAa,CAAC,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,EAAE,OAAO,CAAC,CAAC;AACzE,CAAC;AAED;;;gCAGgC;AAChC,MAAM,UAAU,YAAY,CAAC,UAAkB;IAC7C,MAAM,IAAI,GAAG,IAAI,CAAC,UAAU,EAAE,iBAAiB,CAAC,CAAC;IACjD,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IACnC,IAAI,MAAe,CAAC;IACpB,IAAI,CAAC;QACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC;IACnD,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CAAC,eAAe,IAAI,uBAAwB,GAAa,CAAC,OAAO,EAAE,CAAC,CAAC;IACtF,CAAC;IACD,IACE,CAAC,MAAM;QACP,OAAO,MAAM,KAAK,QAAQ;QACzB,MAAgC,CAAC,OAAO,KAAK,gBAAgB,EAC9D,CAAC;QACD,MAAM,IAAI,KAAK,CAAC,eAAe,IAAI,kCAAkC,gBAAgB,GAAG,CAAC,CAAC;IAC5F,CAAC;IACD,OAAO,MAAyB,CAAC;AACnC,CAAC"}
|
|
@@ -80,6 +80,102 @@ export declare class CloudflareApi {
|
|
|
80
80
|
* mixed-content warnings that bite static-export apps.
|
|
81
81
|
*
|
|
82
82
|
* Returns a per-setting summary for the caller to log. */
|
|
83
|
+
/** Create a bucket. Returns the metadata. If the bucket already
|
|
84
|
+
* exists (409), returns `{ existed: true }` plus a fresh GET. */
|
|
85
|
+
createR2Bucket(accountId: string, name: string, opts?: {
|
|
86
|
+
locationHint?: string;
|
|
87
|
+
storageClass?: "Standard" | "InfrequentAccess";
|
|
88
|
+
}): Promise<{
|
|
89
|
+
name: string;
|
|
90
|
+
location?: string;
|
|
91
|
+
creation_date?: string;
|
|
92
|
+
storage_class?: string;
|
|
93
|
+
existed: boolean;
|
|
94
|
+
}>;
|
|
95
|
+
/** Get bucket metadata. Returns null on 404. */
|
|
96
|
+
getR2Bucket(accountId: string, name: string): Promise<{
|
|
97
|
+
name: string;
|
|
98
|
+
location?: string;
|
|
99
|
+
creation_date?: string;
|
|
100
|
+
storage_class?: string;
|
|
101
|
+
} | null>;
|
|
102
|
+
/** Enable (or disable) the managed `pub-<hash>.r2.dev` public URL on
|
|
103
|
+
* a bucket. Returns the assigned `pub-<hash>.r2.dev` hostname. */
|
|
104
|
+
enableR2ManagedDomain(accountId: string, bucket: string, enabled?: boolean): Promise<{
|
|
105
|
+
bucketId: string;
|
|
106
|
+
domain: string;
|
|
107
|
+
enabled: boolean;
|
|
108
|
+
}>;
|
|
109
|
+
/** List custom domains attached to a bucket — used to short-circuit
|
|
110
|
+
* re-runs that already added the domain. */
|
|
111
|
+
listR2CustomDomains(accountId: string, bucket: string): Promise<Array<{
|
|
112
|
+
domain: string;
|
|
113
|
+
enabled: boolean;
|
|
114
|
+
status?: {
|
|
115
|
+
ownership?: string;
|
|
116
|
+
ssl?: string;
|
|
117
|
+
};
|
|
118
|
+
}>>;
|
|
119
|
+
/** Mint a per-bucket-scoped R2 API token. Returns the token's S3
|
|
120
|
+
* access/secret derivation alongside the raw token id+value (the
|
|
121
|
+
* caller can store the access/secret pair as the project's S3
|
|
122
|
+
* credentials, or hold the token value to use as a Bearer for R2
|
|
123
|
+
* admin calls scoped to those buckets).
|
|
124
|
+
*
|
|
125
|
+
* The token resource scope follows Cloudflare's R2 format:
|
|
126
|
+
* `com.cloudflare.edge.r2.bucket.<accountId>_<jurisdiction>_<bucketName>`
|
|
127
|
+
* with jurisdiction = "default" for buckets created without an
|
|
128
|
+
* explicit jurisdiction (which is what `createR2Bucket` does today).
|
|
129
|
+
*
|
|
130
|
+
* Permission groups are looked up dynamically by name — Cloudflare
|
|
131
|
+
* doesn't publish stable IDs, only stable names. We cache the result
|
|
132
|
+
* on the instance so subsequent calls in the same process re-use it.
|
|
133
|
+
*
|
|
134
|
+
* Note on the calling token: this hits `POST /user/tokens` which
|
|
135
|
+
* requires the calling token to have `User > API Tokens > Edit`.
|
|
136
|
+
* An R2-only admin token will 403 here. The caller should surface
|
|
137
|
+
* that as a "add API Tokens:Edit to your admin token" hint. */
|
|
138
|
+
createR2ApiToken(params: {
|
|
139
|
+
accountId: string;
|
|
140
|
+
/** Display name for the token in the CF dashboard. Project name is
|
|
141
|
+
* the natural choice. */
|
|
142
|
+
name: string;
|
|
143
|
+
/** Bucket names to scope the token to. Token can only access these. */
|
|
144
|
+
bucketNames: string[];
|
|
145
|
+
/** Bucket jurisdiction. Defaults to "default" — matches how
|
|
146
|
+
* `createR2Bucket` creates buckets without explicit jurisdiction. */
|
|
147
|
+
jurisdiction?: "default" | "eu" | "fedramp";
|
|
148
|
+
/** Permissions scope for the resulting S3 keys. Default: read+write. */
|
|
149
|
+
permissions?: "read" | "read-write";
|
|
150
|
+
}): Promise<{
|
|
151
|
+
/** API token id — the same thing as the S3 Access Key ID. */
|
|
152
|
+
tokenId: string;
|
|
153
|
+
/** API token value (raw bearer). Sensitive. */
|
|
154
|
+
tokenValue: string;
|
|
155
|
+
/** S3 Access Key ID, derived per Cloudflare's docs (same as tokenId). */
|
|
156
|
+
accessKeyId: string;
|
|
157
|
+
/** S3 Secret Access Key — sha256(tokenValue), hex. */
|
|
158
|
+
secretAccessKey: string;
|
|
159
|
+
}>;
|
|
160
|
+
/** Cached lookup of /user/tokens/permission_groups filtered to R2
|
|
161
|
+
* groups. Returns at minimum the entries hatchkit looks up by name
|
|
162
|
+
* in `createR2ApiToken`. */
|
|
163
|
+
private permissionGroupsCache?;
|
|
164
|
+
private getR2PermissionGroups;
|
|
165
|
+
/** Delete a Cloudflare API token by id. Idempotent: 404 → "not-found". */
|
|
166
|
+
deleteApiToken(tokenId: string): Promise<"deleted" | "not-found">;
|
|
167
|
+
/** Attach a custom domain (a hostname on a Cloudflare zone you own)
|
|
168
|
+
* to an R2 bucket. Idempotent — duplicates short-circuit via list. */
|
|
169
|
+
addR2CustomDomain(accountId: string, bucket: string, params: {
|
|
170
|
+
domain: string;
|
|
171
|
+
zoneId: string;
|
|
172
|
+
minTLS?: "1.0" | "1.1" | "1.2" | "1.3";
|
|
173
|
+
}): Promise<{
|
|
174
|
+
domain: string;
|
|
175
|
+
enabled: boolean;
|
|
176
|
+
zoneId: string;
|
|
177
|
+
existed: boolean;
|
|
178
|
+
}>;
|
|
83
179
|
enableEdgeHardening(zoneId: string): Promise<{
|
|
84
180
|
changed: Array<{
|
|
85
181
|
id: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cloudflare-api.d.ts","sourceRoot":"","sources":["../../src/utils/cloudflare-api.ts"],"names":[],"mappings":"AAcA,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,MAAM,CAAC;IACd,2EAA2E;IAC3E,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAiBD,kCAAkC;AAClC,qBAAa,aAAa;IACxB,OAAO,CAAC,KAAK,CAAS;IACtB,OAAO,CAAC,SAAS,CAAC,CAAS;gBAEf,OAAO,EAAE,oBAAoB;YAK3B,OAAO;IAoBrB,iDAAiD;IAC3C,WAAW,IAAI,OAAO,CAAC,MAAM,CAAC;IAKpC;;;;;OAKG;IACG,SAAS,IAAI,OAAO,CAAC,cAAc,EAAE,CAAC;IA2B5C,gEAAgE;IAC1D,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC;IAOjE,6DAA6D;IACvD,UAAU,CACd,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,GAAG,GAAG,MAAM,GAAG,OAAO,GAC3B,OAAO,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,OAAO,CAAA;KAAE,GAAG,IAAI,CAAC;IAQhG;;;qEAGiE;IAC3D,YAAY,CAChB,MAAM,EAAE,MAAM,EACd,MAAM,EAAE;QACN,IAAI,EAAE,GAAG,GAAG,MAAM,GAAG,OAAO,CAAC;QAC7B,IAAI,EAAE,MAAM,CAAC;QACb,OAAO,EAAE,MAAM,CAAC;QAChB,OAAO,CAAC,EAAE,OAAO,CAAC;QAClB,GAAG,CAAC,EAAE,MAAM,CAAC;KACd,GACA,OAAO,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,OAAO,CAAC;QAAC,OAAO,EAAE,OAAO,CAAA;KAAE,CAAC;IA8B9D;4EACwE;IAClE,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,GAAG,WAAW,CAAC;IA0BtF;;;gEAG4D;IACtD,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAQzE,0DAA0D;IACpD,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;IASzF;;;;;;;;;;;;;;;;;;;;+DAoB2D;
|
|
1
|
+
{"version":3,"file":"cloudflare-api.d.ts","sourceRoot":"","sources":["../../src/utils/cloudflare-api.ts"],"names":[],"mappings":"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"}
|