devflare 1.0.0-next.39 → 1.0.0-next.40
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/_chunks/account-BtWcv3X9.js +462 -0
- package/dist/_chunks/account-resources-CsmVowJp.js +159 -0
- package/dist/_chunks/ai-CBEuLdoP.js +322 -0
- package/dist/_chunks/api-TzdliH-6.js +568 -0
- package/dist/_chunks/build-3T6O4uIg.js +24 -0
- package/dist/_chunks/build-artifacts-8TqBSQkG.js +483 -0
- package/dist/_chunks/cli-BTF1X4SG.js +1128 -0
- package/dist/_chunks/cloudflare-BaloqI3H.js +157 -0
- package/dist/_chunks/colors-DiK6wPJ5.js +13 -0
- package/dist/_chunks/command-utils-BsfkmTqh.js +45 -0
- package/dist/_chunks/compiler-uoyAQ8zW.js +424 -0
- package/dist/_chunks/config-D5u-bEkn.js +78 -0
- package/dist/_chunks/config-path-DCPto4XB.js +42 -0
- package/dist/_chunks/context-CX50Y2Kb.js +2250 -0
- package/dist/_chunks/decorators-QmV57ixr.js +19 -0
- package/dist/_chunks/dependencies-C2oxFjU_.js +57 -0
- package/dist/_chunks/deploy-DMTr6JeR.js +915 -0
- package/dist/_chunks/dev-CvRHmRFZ.js +3456 -0
- package/dist/_chunks/doctor-DIG8DoFU.js +219 -0
- package/dist/_chunks/durable-object-DMtH0XYX.js +234 -0
- package/dist/_chunks/env-S0_nMVz1.js +125 -0
- package/dist/_chunks/family-DXC5SdFK.js +143 -0
- package/dist/_chunks/generated-artifacts-dMJY4KAt.js +32 -0
- package/dist/_chunks/glob-CmQOvunB.js +56 -0
- package/dist/_chunks/init-3moXTgpb.js +165 -0
- package/dist/_chunks/loader-DLXO60RO.js +1153 -0
- package/dist/_chunks/local-dev-vars-CTSa-wvF.js +81 -0
- package/dist/_chunks/local-hyperdrive-CJ90j46O.js +119 -0
- package/dist/_chunks/local-media-bindings-DsAW4AMF.js +335 -0
- package/dist/_chunks/local-secrets-DMmEOygL.js +123 -0
- package/dist/_chunks/local-workflow-entrypoints-Wip3o1u8.js +90 -0
- package/dist/_chunks/login-BmnDzDlH.js +51 -0
- package/dist/_chunks/package-metadata-DAuCkyvK.js +39 -0
- package/dist/_chunks/preferences-BKp_7XJx.js +241 -0
- package/dist/_chunks/preview-BhqDmq8I.js +456 -0
- package/dist/_chunks/preview-registry-ClAbLTHH.js +1186 -0
- package/dist/_chunks/preview-resources-DdXj8LMM.js +358 -0
- package/dist/_chunks/previews-Dlr13x5M.js +1134 -0
- package/dist/_chunks/productions-D3AnOHac.js +411 -0
- package/dist/_chunks/ref-CYJNAAe_.js +178 -0
- package/dist/_chunks/remote-CZnP-HLJ.js +79 -0
- package/dist/_chunks/remote-config-D39BY9ji.js +132 -0
- package/dist/_chunks/resolve-package-Y84HB3Nt.js +133 -0
- package/dist/_chunks/rolldown-runtime-CvQ6eiug.js +14 -0
- package/dist/_chunks/routes-C3FqES2W.js +796 -0
- package/dist/_chunks/runtime-FvXvfuZ2.js +550 -0
- package/dist/_chunks/schema-normalization-DWVleVxo.js +477 -0
- package/dist/_chunks/secrets-70eN0Q6C.js +95 -0
- package/dist/_chunks/token-kguIDmej.js +333 -0
- package/dist/_chunks/tokens-iVcgNXi-.js +221 -0
- package/dist/_chunks/types-OrLbzv4I.js +476 -0
- package/dist/_chunks/ui-BUoZApvE.js +103 -0
- package/dist/_chunks/usage-BBTGzjon.js +272 -0
- package/dist/_chunks/vite-CsI0E-uV.js +1235 -0
- package/dist/_chunks/vite-utils-OVLMV605.js +183 -0
- package/dist/_chunks/worker-CS1jgNFE.js +410 -0
- package/dist/_chunks/worker-bundler-dTTnYU3n.js +458 -0
- package/dist/_chunks/worker-entrypoint-CQW77lG8.js +247 -0
- package/dist/_chunks/workerName-CFJsLZA-.js +23 -0
- package/dist/bridge/index.d.ts +6 -6
- package/dist/bridge/miniflare.d.ts +2 -2
- package/dist/bridge/proxy.d.ts +1 -1
- package/dist/bridge/v2/body-streams.d.ts +1 -1
- package/dist/bridge/v2/codec.d.ts +4 -4
- package/dist/bridge/v2/index.d.ts +10 -10
- package/dist/bridge/v2/serialization.d.ts +1 -1
- package/dist/bridge/v2/value-codec.d.ts +1 -1
- package/dist/bridge/v2/value-serialization.d.ts.map +1 -1
- package/dist/bridge/v2/ws-relay.d.ts +3 -3
- package/dist/browser-shim/index.d.ts +2 -2
- package/dist/browser.d.ts +70 -70
- package/dist/browser.js +74 -2462
- package/dist/bundler/do-bundler.d.ts +1 -1
- package/dist/bundler/index.d.ts +3 -3
- package/dist/bundler/rolldown-shared.d.ts +1 -1
- package/dist/bundler/worker-bundler.d.ts +1 -1
- package/dist/cli/build-manifest.d.ts +1 -1
- package/dist/cli/command-utils.d.ts +1 -1
- package/dist/cli/commands/account.d.ts +1 -1
- package/dist/cli/commands/ai.d.ts +1 -1
- package/dist/cli/commands/build-artifacts.d.ts +5 -5
- package/dist/cli/commands/build.d.ts +1 -1
- package/dist/cli/commands/config.d.ts +1 -1
- package/dist/cli/commands/deploy/prepare.d.ts +2 -2
- package/dist/cli/commands/deploy/runtime.d.ts +1 -1
- package/dist/cli/commands/deploy/verification.d.ts +1 -1
- package/dist/cli/commands/deploy.d.ts +1 -1
- package/dist/cli/commands/dev.d.ts +1 -1
- package/dist/cli/commands/doctor.d.ts +1 -1
- package/dist/cli/commands/init.d.ts +1 -1
- package/dist/cli/commands/login.d.ts +1 -1
- package/dist/cli/commands/previews-support/cleanup.d.ts +1 -1
- package/dist/cli/commands/previews-support/family.d.ts +3 -3
- package/dist/cli/commands/previews-support/render.d.ts +3 -3
- package/dist/cli/commands/previews-support/theme.d.ts +2 -2
- package/dist/cli/commands/previews-support/types.d.ts +2 -2
- package/dist/cli/commands/previews.d.ts +1 -1
- package/dist/cli/commands/productions.d.ts +1 -1
- package/dist/cli/commands/remote.d.ts +1 -1
- package/dist/cli/commands/secrets.d.ts +1 -1
- package/dist/cli/commands/token.d.ts +1 -1
- package/dist/cli/commands/type-generation/discovery.d.ts +2 -2
- package/dist/cli/commands/type-generation/generator.d.ts +3 -3
- package/dist/cli/commands/type-generation/models.d.ts +1 -1
- package/dist/cli/commands/types.d.ts +1 -1
- package/dist/cli/commands/worker.d.ts +1 -1
- package/dist/cli/deploy-strategy.d.ts +1 -1
- package/dist/cli/deploy-target.d.ts +1 -1
- package/dist/cli/help-pages/pages/account.d.ts +1 -1
- package/dist/cli/help-pages/pages/core.d.ts +1 -1
- package/dist/cli/help-pages/pages/index.d.ts +1 -1
- package/dist/cli/help-pages/pages/misc.d.ts +1 -1
- package/dist/cli/help-pages/pages/previews.d.ts +1 -1
- package/dist/cli/help-pages/pages/productions.d.ts +1 -1
- package/dist/cli/help-pages/render.d.ts +2 -2
- package/dist/cli/help-pages/shared.d.ts +1 -1
- package/dist/cli/help.d.ts +2 -2
- package/dist/cli/index.js +2 -1383
- package/dist/cli/preview-bindings.d.ts +3 -3
- package/dist/cli/preview.d.ts +1 -1
- package/dist/cli/wrangler-auth.d.ts +1 -1
- package/dist/cloudflare/account-core.d.ts +2 -2
- package/dist/cloudflare/account-resources.d.ts +2 -2
- package/dist/cloudflare/account-status.d.ts +1 -1
- package/dist/cloudflare/account-workers.d.ts +2 -2
- package/dist/cloudflare/account.d.ts +7 -7
- package/dist/cloudflare/auth.d.ts +1 -1
- package/dist/cloudflare/index.d.ts +13 -13
- package/dist/cloudflare/index.js +4 -59
- package/dist/cloudflare/kv-namespace.d.ts +1 -1
- package/dist/cloudflare/preview-registry-cache.d.ts +1 -1
- package/dist/cloudflare/preview-registry-inference.d.ts +2 -2
- package/dist/cloudflare/preview-registry-records.d.ts +3 -3
- package/dist/cloudflare/preview-registry-shape.d.ts +2 -2
- package/dist/cloudflare/preview-registry-store.d.ts +3 -3
- package/dist/cloudflare/preview-registry-transport.d.ts +2 -2
- package/dist/cloudflare/preview-registry-types.d.ts +2 -2
- package/dist/cloudflare/preview-registry.d.ts +5 -5
- package/dist/cloudflare/tokens.d.ts +2 -2
- package/dist/cloudflare/usage.d.ts +2 -2
- package/dist/config/binding-resolution-helpers.d.ts +1 -1
- package/dist/config/compiler/bindings.d.ts +2 -2
- package/dist/config/compiler/core-helpers.d.ts +2 -2
- package/dist/config/compiler/do-workers.d.ts +2 -2
- package/dist/config/compiler/paths.d.ts +1 -1
- package/dist/config/compiler.d.ts +6 -6
- package/dist/config/define.d.ts +2 -2
- package/dist/config/deploy-resources.d.ts +5 -5
- package/dist/config/env-vars.d.ts +1 -1
- package/dist/config/framework-providers.d.ts +1 -1
- package/dist/config/index.d.ts +12 -12
- package/dist/config/loader.d.ts +2 -2
- package/dist/config/local-dev-vars.d.ts +1 -1
- package/dist/config/preview-resources.d.ts +4 -4
- package/dist/config/preview.d.ts +1 -1
- package/dist/config/ref.d.ts +2 -2
- package/dist/config/resolve-phased.d.ts +4 -4
- package/dist/config/resolve.d.ts +1 -1
- package/dist/config/resource-resolution.d.ts +6 -6
- package/dist/config/schema-env.d.ts +20 -20
- package/dist/config/schema-normalization.d.ts +1 -1
- package/dist/config/schema-types-bindings.d.ts +4 -4
- package/dist/config/schema-types-build.d.ts +1 -1
- package/dist/config/schema-types.d.ts +7 -7
- package/dist/config/schema.d.ts +46 -46
- package/dist/config/service-bindings-validation.d.ts +1 -1
- package/dist/config-entry.d.ts +6 -6
- package/dist/config-entry.js +3 -8
- package/dist/decorators/index.d.ts +2 -2
- package/dist/decorators/index.js +2 -9
- package/dist/dev-server/d1-migrations.d.ts +1 -1
- package/dist/dev-server/dev-server-state.d.ts +6 -6
- package/dist/dev-server/gateway-script.d.ts +1 -1
- package/dist/dev-server/index.d.ts +1 -1
- package/dist/dev-server/miniflare-bindings.d.ts +1 -1
- package/dist/dev-server/miniflare-dev-config.d.ts +5 -5
- package/dist/dev-server/miniflare-worker-config.d.ts +3 -3
- package/dist/dev-server/server-startup-helpers.d.ts +6 -6
- package/dist/dev-server/worker-surface-paths.d.ts +2 -2
- package/dist/index.d.ts +8 -8
- package/dist/index.js +9 -22
- package/dist/runtime/context-events.d.ts +1 -1
- package/dist/runtime/context.d.ts +3 -3
- package/dist/runtime/exports.d.ts +2 -2
- package/dist/runtime/index.d.ts +10 -10
- package/dist/runtime/index.js +5 -57
- package/dist/runtime/middleware.d.ts +1 -1
- package/dist/runtime/router/index.d.ts +3 -3
- package/dist/runtime/validation.d.ts +1 -1
- package/dist/secrets/local-secrets.d.ts +1 -1
- package/dist/shims/local-media-bindings.d.ts +1 -1
- package/dist/sveltekit/index.d.ts +1 -1
- package/dist/sveltekit/index.js +327 -9
- package/dist/sveltekit/local-bindings.d.ts +1 -1
- package/dist/sveltekit/platform.d.ts +1 -1
- package/dist/test/binding-hints.d.ts +2 -2
- package/dist/test/cf.d.ts +19 -19
- package/dist/test/index.d.ts +18 -18
- package/dist/test/index.js +4495 -46
- package/dist/test/offline-bindings.d.ts +3 -3
- package/dist/test/resolve-service-bindings.d.ts +1 -1
- package/dist/test/simple-context-bindings.d.ts +1 -1
- package/dist/test/simple-context-durable-objects.d.ts +1 -1
- package/dist/test/simple-context-env.d.ts +2 -2
- package/dist/test/simple-context-handlers.d.ts +2 -2
- package/dist/test/simple-context-lifecycle.d.ts +2 -2
- package/dist/test/simple-context-mfconfig.d.ts +1 -1
- package/dist/test/simple-context-multi-worker.d.ts +2 -2
- package/dist/test/simple-context-runtime.d.ts +1 -1
- package/dist/test/simple-context-startup.d.ts +1 -1
- package/dist/test/simple-context.d.ts +1 -1
- package/dist/test/utilities/env.d.ts +3 -3
- package/dist/test/utilities.d.ts +10 -10
- package/dist/test/worker.d.ts +1 -1
- package/dist/transform/index.d.ts +2 -2
- package/dist/utils/send-email.js +163 -19
- package/dist/vite/config-file.d.ts +2 -2
- package/dist/vite/index.d.ts +3 -3
- package/dist/vite/index.js +2 -31
- package/dist/vite/plugin-config-hook.d.ts +1 -1
- package/dist/vite/plugin-context.d.ts +3 -3
- package/dist/vite/plugin-durable-objects.d.ts +2 -2
- package/dist/vite/plugin-programmatic.d.ts +1 -1
- package/dist/vite/plugin-service-bindings.d.ts +2 -2
- package/dist/vite/plugin.d.ts +3 -3
- package/dist/worker-entry/composed-worker.d.ts +1 -1
- package/dist/worker-entry/routes.d.ts +2 -2
- package/dist/worker-entry/surface-paths.d.ts +1 -1
- package/dist/workflows/local-workflow-entrypoints.d.ts +1 -1
- package/package.json +5 -3
- package/dist/account-4tgh03a8.js +0 -484
- package/dist/ai-r3zqmxan.js +0 -261
- package/dist/api-6z01z734.js +0 -33
- package/dist/build-kw625v84.js +0 -51
- package/dist/config-ghk2bxj3.js +0 -102
- package/dist/deploy-9kee65n9.js +0 -1062
- package/dist/dev-x8zr249a.js +0 -3569
- package/dist/doctor-0ng5qrr1.js +0 -258
- package/dist/durable-object-0ybmg08a.js +0 -13
- package/dist/index-04wh9bxx.js +0 -514
- package/dist/index-0cc05hzv.js +0 -74
- package/dist/index-2yv7w548.js +0 -185
- package/dist/index-37x76zdn.js +0 -4
- package/dist/index-3cpzsr47.js +0 -125
- package/dist/index-3t6rypgc.js +0 -13
- package/dist/index-4mmpccrb.js +0 -309
- package/dist/index-5dkjffqz.js +0 -25
- package/dist/index-5hy7jmv3.js +0 -890
- package/dist/index-627srx16.js +0 -45
- package/dist/index-7m557715.js +0 -283
- package/dist/index-a8pnvg3r.js +0 -52
- package/dist/index-aabgympv.js +0 -39
- package/dist/index-atwc3csp.js +0 -256
- package/dist/index-cv4cvrxe.js +0 -2046
- package/dist/index-h7r11y4a.js +0 -539
- package/dist/index-hvtd936d.js +0 -1229
- package/dist/index-kcp7y951.js +0 -136
- package/dist/index-maw0jjnn.js +0 -147
- package/dist/index-mek9msfv.js +0 -705
- package/dist/index-n4xkaymm.js +0 -236
- package/dist/index-nkk59p3y.js +0 -579
- package/dist/index-phcrvs6d.js +0 -342
- package/dist/index-se4kw8tm.js +0 -460
- package/dist/index-x8s9rwfh.js +0 -2020
- package/dist/index-y7w3x9p1.js +0 -18
- package/dist/index-z9gy8w6b.js +0 -57
- package/dist/index-zdd0d9qa.js +0 -199
- package/dist/init-tb8jqgvr.js +0 -180
- package/dist/login-4h1sfsed.js +0 -75
- package/dist/previews-qr7c5j8h.js +0 -1336
- package/dist/productions-xpmd6bw8.js +0 -505
- package/dist/remote-kqcvhnfx.js +0 -192
- package/dist/secrets-6wbdsdek.js +0 -89
- package/dist/token-yp1qa70y.js +0 -419
- package/dist/types-15yv4cj3.js +0 -701
- package/dist/worker-1yg72jxg.js +0 -510
- package/dist/worker-entrypoint-y8s9kdcx.js +0 -15
|
@@ -0,0 +1,333 @@
|
|
|
1
|
+
import { n as CloudflareAPIError, t as AuthenticationError } from "./api-TzdliH-6.js";
|
|
2
|
+
import { d as getPrimaryAccount, i as getWorkspaceAccountId } from "./preferences-BKp_7XJx.js";
|
|
3
|
+
import { d as green, f as logLine, g as yellow, h as whiteDim, o as dim, p as logTable, r as createCliTheme } from "./ui-BUoZApvE.js";
|
|
4
|
+
import { a as listAccountTokenPermissionGroups, c as selectAllReusablePermissionGroups, i as listAccountOwnedAPITokens, l as selectDevflarePermissionGroups, n as deleteAccountOwnedAPIToken, o as normalizeDevflareTokenName, r as filterDevflareManagedTokens, s as rollAccountOwnedAPITokenValue, t as createAccountOwnedAPIToken, u as stripDevflareTokenNamePrefix } from "./tokens-iVcgNXi-.js";
|
|
5
|
+
//#region src/cli/commands/token.ts
|
|
6
|
+
const CLI_API_OPTIONS = { timeout: 1e4 };
|
|
7
|
+
const TOKENS_USAGE = "devflare tokens <bootstrap-token> (--list | --new [token-name] | --roll [token-name] | --delete [token-name] | --delete-all) [--account <id>] [--all-flags]";
|
|
8
|
+
const TOKEN_OPERATION_SUMMARY_LINES = [
|
|
9
|
+
"--list List Devflare-managed account-owned tokens",
|
|
10
|
+
"--new [name] Create a Devflare-managed account-owned token",
|
|
11
|
+
"--roll [name] Roll a Devflare-managed account-owned token secret",
|
|
12
|
+
"--delete [name] Delete a Devflare-managed account-owned token",
|
|
13
|
+
"--delete-all Delete every Devflare-managed account-owned token",
|
|
14
|
+
"--all-flags With --new, include every reusable account/zone-scoped permission group"
|
|
15
|
+
];
|
|
16
|
+
function getTrimmedStringOption(options, key) {
|
|
17
|
+
const value = options[key];
|
|
18
|
+
if (typeof value !== "string") return;
|
|
19
|
+
return value.trim() || void 0;
|
|
20
|
+
}
|
|
21
|
+
function formatTokenTimestamp(value) {
|
|
22
|
+
if (!value) return "—";
|
|
23
|
+
return value.toISOString().replace(/:\d{2}\.\d{3}Z$/, "Z").replace("T", " ");
|
|
24
|
+
}
|
|
25
|
+
function sortTokens(tokens) {
|
|
26
|
+
return [...tokens].sort((left, right) => {
|
|
27
|
+
const nameComparison = left.name.localeCompare(right.name);
|
|
28
|
+
if (nameComparison !== 0) return nameComparison;
|
|
29
|
+
return (right.modifiedOn?.getTime() ?? 0) - (left.modifiedOn?.getTime() ?? 0);
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
function logUsage(logger, theme) {
|
|
33
|
+
logLine(logger);
|
|
34
|
+
logLine(logger, `${dim("Usage:", theme)} ${TOKENS_USAGE}`);
|
|
35
|
+
logLine(logger, dim("Operations:", theme));
|
|
36
|
+
for (const line of TOKEN_OPERATION_SUMMARY_LINES) logLine(logger, ` ${line}`);
|
|
37
|
+
logLine(logger, dim("Token names are normalized to the devflare- prefix automatically.", theme));
|
|
38
|
+
logLine(logger, dim("The bootstrap token must include Cloudflare API token management permissions.", theme));
|
|
39
|
+
logLine(logger);
|
|
40
|
+
}
|
|
41
|
+
function resolveTokenOperation(parsed) {
|
|
42
|
+
const newOption = parsed.options.new;
|
|
43
|
+
const rollOption = parsed.options.roll;
|
|
44
|
+
const deleteOption = parsed.options.delete;
|
|
45
|
+
const requestedOperations = [
|
|
46
|
+
newOption !== void 0 ? "new" : null,
|
|
47
|
+
rollOption !== void 0 ? "roll" : null,
|
|
48
|
+
deleteOption !== void 0 ? "delete" : null,
|
|
49
|
+
parsed.options.list === true ? "list" : null,
|
|
50
|
+
parsed.options["delete-all"] === true ? "delete-all" : null
|
|
51
|
+
].filter(Boolean);
|
|
52
|
+
if (parsed.options["all-flags"] && !requestedOperations.includes("new")) return "--all-flags can only be used together with --new.";
|
|
53
|
+
if (requestedOperations.length === 0) return "Choose one token operation: --list, --new, --roll, --delete, or --delete-all.";
|
|
54
|
+
if (requestedOperations.length > 1) return "Choose only one token operation at a time.";
|
|
55
|
+
switch (requestedOperations[0]) {
|
|
56
|
+
case "new": return {
|
|
57
|
+
kind: "new",
|
|
58
|
+
requestedName: typeof newOption === "string" ? newOption.trim() || void 0 : void 0
|
|
59
|
+
};
|
|
60
|
+
case "roll": return {
|
|
61
|
+
kind: "roll",
|
|
62
|
+
requestedName: typeof rollOption === "string" ? rollOption.trim() || void 0 : void 0
|
|
63
|
+
};
|
|
64
|
+
case "delete": return {
|
|
65
|
+
kind: "delete",
|
|
66
|
+
requestedName: typeof deleteOption === "string" ? deleteOption.trim() || void 0 : void 0
|
|
67
|
+
};
|
|
68
|
+
case "list": return { kind: "list" };
|
|
69
|
+
case "delete-all": return { kind: "delete-all" };
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
function formatManagedTokenDisplayName(name) {
|
|
73
|
+
return stripDevflareTokenNamePrefix(name);
|
|
74
|
+
}
|
|
75
|
+
async function promptForTokenName(logger, theme, message) {
|
|
76
|
+
while (true) {
|
|
77
|
+
const selected = await logger.prompt(message, {
|
|
78
|
+
type: "text",
|
|
79
|
+
placeholder: "preview",
|
|
80
|
+
cancel: "symbol"
|
|
81
|
+
});
|
|
82
|
+
if (typeof selected === "symbol") {
|
|
83
|
+
logLine(logger, dim("Cancelled", theme));
|
|
84
|
+
return null;
|
|
85
|
+
}
|
|
86
|
+
const trimmedValue = selected.trim();
|
|
87
|
+
if (trimmedValue) return trimmedValue;
|
|
88
|
+
logger.error("Token name is required.");
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
async function resolveTokenName(requestedName, logger, theme, promptMessage) {
|
|
92
|
+
const rawName = requestedName ?? await promptForTokenName(logger, theme, promptMessage);
|
|
93
|
+
if (!rawName) return null;
|
|
94
|
+
return normalizeDevflareTokenName(rawName);
|
|
95
|
+
}
|
|
96
|
+
async function resolveNamedManagedTokens(accountId, accountSource, bootstrapToken, requestedName, logger, theme, options) {
|
|
97
|
+
const tokenName = await resolveTokenName(requestedName, logger, theme, options.promptMessage);
|
|
98
|
+
if (!tokenName) return { exitCode: 0 };
|
|
99
|
+
logLine(logger);
|
|
100
|
+
logLine(logger, `${yellow("tokens", theme)} ${dim(`${options.actionLabel} a Devflare-managed account-owned token…`, theme)}`);
|
|
101
|
+
logLine(logger, `${dim("Account:", theme)} ${green(accountId, theme)} ${whiteDim(`(${accountSource})`, theme)}`);
|
|
102
|
+
logLine(logger, `${dim("Name:", theme)} ${green(tokenName, theme)}`);
|
|
103
|
+
const matchingTokens = filterDevflareManagedTokens(await listAccountOwnedAPITokens(accountId, {
|
|
104
|
+
...CLI_API_OPTIONS,
|
|
105
|
+
token: bootstrapToken
|
|
106
|
+
})).filter((token) => token.name === tokenName);
|
|
107
|
+
if (matchingTokens.length === 0) {
|
|
108
|
+
logger.error(`No Devflare-managed token named ${tokenName} was found.`);
|
|
109
|
+
return { exitCode: 1 };
|
|
110
|
+
}
|
|
111
|
+
if (matchingTokens.length > 1) logLine(logger, dim(`Found ${matchingTokens.length} tokens with that name. ${options.multipleMatchMessage}.`, theme));
|
|
112
|
+
return {
|
|
113
|
+
tokenName,
|
|
114
|
+
matchingTokens
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
async function resolveRequestedAccountId(requestedAccountId, bootstrapToken) {
|
|
118
|
+
if (requestedAccountId) return {
|
|
119
|
+
accountId: requestedAccountId,
|
|
120
|
+
source: "flag"
|
|
121
|
+
};
|
|
122
|
+
const workspaceAccountId = getWorkspaceAccountId();
|
|
123
|
+
if (workspaceAccountId) return {
|
|
124
|
+
accountId: workspaceAccountId,
|
|
125
|
+
source: "workspace"
|
|
126
|
+
};
|
|
127
|
+
const primaryAccount = await getPrimaryAccount({
|
|
128
|
+
...CLI_API_OPTIONS,
|
|
129
|
+
token: bootstrapToken
|
|
130
|
+
});
|
|
131
|
+
if (!primaryAccount) throw new Error("No Cloudflare accounts found for this bootstrap token");
|
|
132
|
+
return {
|
|
133
|
+
accountId: primaryAccount.id,
|
|
134
|
+
source: "primary"
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
async function createManagedToken(accountId, accountSource, bootstrapToken, requestedName, includeAllFlags, logger, theme) {
|
|
138
|
+
const tokenName = await resolveTokenName(requestedName, logger, theme, "Enter a Devflare token name:");
|
|
139
|
+
if (!tokenName) return { exitCode: 0 };
|
|
140
|
+
logLine(logger);
|
|
141
|
+
logLine(logger, `${yellow("tokens", theme)} ${dim("Creating an account-owned Devflare token…", theme)}`);
|
|
142
|
+
logLine(logger, `${dim("Account:", theme)} ${green(accountId, theme)} ${whiteDim(`(${accountSource})`, theme)}`);
|
|
143
|
+
logLine(logger, `${dim("Name:", theme)} ${green(tokenName, theme)}`);
|
|
144
|
+
const permissionGroups = await listAccountTokenPermissionGroups(accountId, {
|
|
145
|
+
...CLI_API_OPTIONS,
|
|
146
|
+
token: bootstrapToken
|
|
147
|
+
});
|
|
148
|
+
if (permissionGroups.length === 0) {
|
|
149
|
+
logger.error("Cloudflare returned zero account token permission groups for this account.");
|
|
150
|
+
return { exitCode: 1 };
|
|
151
|
+
}
|
|
152
|
+
const selectedPermissionGroups = includeAllFlags ? selectAllReusablePermissionGroups(permissionGroups) : selectDevflarePermissionGroups(permissionGroups);
|
|
153
|
+
const createdToken = await createAccountOwnedAPIToken(accountId, {
|
|
154
|
+
name: tokenName,
|
|
155
|
+
permissionGroups: selectedPermissionGroups
|
|
156
|
+
}, {
|
|
157
|
+
...CLI_API_OPTIONS,
|
|
158
|
+
token: bootstrapToken
|
|
159
|
+
});
|
|
160
|
+
if (!createdToken.value) {
|
|
161
|
+
logger.error("Cloudflare created the token but did not return a token value.");
|
|
162
|
+
return { exitCode: 1 };
|
|
163
|
+
}
|
|
164
|
+
logger.success(`Created ${createdToken.name || tokenName}`);
|
|
165
|
+
logLine(logger, `${dim("Permission groups:", theme)} ${selectedPermissionGroups.length} ${includeAllFlags ? "reusable account/zone-scoped" : "Devflare-relevant account/zone-scoped"} selected from ${permissionGroups.length} available`);
|
|
166
|
+
if (includeAllFlags) {
|
|
167
|
+
logLine(logger, dim("Account-owned Devflare tokens include account resources plus all zones in the account; user-scoped groups are skipped automatically.", theme));
|
|
168
|
+
logLine(logger, dim("Account API Tokens permissions are still excluded because Cloudflare does not allow sub-tokens to manage other tokens.", theme));
|
|
169
|
+
}
|
|
170
|
+
logger.warn("Cloudflare only returns the token secret once. Store it safely now.");
|
|
171
|
+
logger.log(createdToken.value);
|
|
172
|
+
return {
|
|
173
|
+
exitCode: 0,
|
|
174
|
+
output: createdToken.value
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
async function listManagedTokens(accountId, accountSource, bootstrapToken, logger, theme) {
|
|
178
|
+
logLine(logger);
|
|
179
|
+
logLine(logger, `${yellow("tokens", theme)} ${dim("Listing Devflare-managed account-owned tokens…", theme)}`);
|
|
180
|
+
logLine(logger, `${dim("Account:", theme)} ${green(accountId, theme)} ${whiteDim(`(${accountSource})`, theme)}`);
|
|
181
|
+
const accountTokens = await listAccountOwnedAPITokens(accountId, {
|
|
182
|
+
...CLI_API_OPTIONS,
|
|
183
|
+
token: bootstrapToken
|
|
184
|
+
});
|
|
185
|
+
const managedTokens = sortTokens(filterDevflareManagedTokens(accountTokens));
|
|
186
|
+
if (managedTokens.length === 0) {
|
|
187
|
+
logLine(logger, dim("No Devflare-managed account-owned tokens found for this account.", theme));
|
|
188
|
+
return {
|
|
189
|
+
exitCode: 0,
|
|
190
|
+
output: ""
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
logTable(logger, {
|
|
194
|
+
title: "Devflare-managed tokens",
|
|
195
|
+
rows: managedTokens,
|
|
196
|
+
columns: [
|
|
197
|
+
{
|
|
198
|
+
label: "Name",
|
|
199
|
+
value: (token) => formatManagedTokenDisplayName(token.name),
|
|
200
|
+
width: 46
|
|
201
|
+
},
|
|
202
|
+
{
|
|
203
|
+
label: "Status",
|
|
204
|
+
value: (token) => token.status ?? "unknown",
|
|
205
|
+
width: 10
|
|
206
|
+
},
|
|
207
|
+
{
|
|
208
|
+
label: "Token ID",
|
|
209
|
+
value: (token) => token.id.slice(0, 12),
|
|
210
|
+
width: 12
|
|
211
|
+
},
|
|
212
|
+
{
|
|
213
|
+
label: "Modified",
|
|
214
|
+
value: (token) => formatTokenTimestamp(token.modifiedOn)
|
|
215
|
+
}
|
|
216
|
+
],
|
|
217
|
+
theme
|
|
218
|
+
});
|
|
219
|
+
const untouchedTokenCount = accountTokens.length - managedTokens.length;
|
|
220
|
+
if (untouchedTokenCount > 0) logLine(logger, dim(`Left ${untouchedTokenCount} non-Devflare token(s) out of this list.`, theme));
|
|
221
|
+
return {
|
|
222
|
+
exitCode: 0,
|
|
223
|
+
output: managedTokens.map((token) => formatManagedTokenDisplayName(token.name)).join("\n")
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
async function rollManagedTokensByName(accountId, accountSource, bootstrapToken, requestedName, logger, theme) {
|
|
227
|
+
const selectedTokens = await resolveNamedManagedTokens(accountId, accountSource, bootstrapToken, requestedName, logger, theme, {
|
|
228
|
+
promptMessage: "Enter the Devflare token name to roll:",
|
|
229
|
+
actionLabel: "Rolling",
|
|
230
|
+
multipleMatchMessage: "Rolling all exact matches"
|
|
231
|
+
});
|
|
232
|
+
if ("exitCode" in selectedTokens) return selectedTokens;
|
|
233
|
+
const { tokenName, matchingTokens } = selectedTokens;
|
|
234
|
+
const rolledValues = [];
|
|
235
|
+
for (const token of matchingTokens) {
|
|
236
|
+
const rolledValue = await rollAccountOwnedAPITokenValue(accountId, token.id, {
|
|
237
|
+
...CLI_API_OPTIONS,
|
|
238
|
+
token: bootstrapToken
|
|
239
|
+
});
|
|
240
|
+
rolledValues.push(rolledValue);
|
|
241
|
+
}
|
|
242
|
+
logger.success(`Rolled ${matchingTokens.length} Devflare-managed token(s) named ${tokenName}`);
|
|
243
|
+
logger.warn("Cloudflare only returns the new token secret once. Store it safely now.");
|
|
244
|
+
if (rolledValues.length === 1) logger.log(rolledValues[0]);
|
|
245
|
+
else for (const [index, value] of rolledValues.entries()) logLine(logger, `${dim(`${matchingTokens[index].id.slice(0, 12)}:`, theme)} ${value}`);
|
|
246
|
+
return {
|
|
247
|
+
exitCode: 0,
|
|
248
|
+
output: rolledValues.join("\n")
|
|
249
|
+
};
|
|
250
|
+
}
|
|
251
|
+
async function deleteManagedTokensByName(accountId, accountSource, bootstrapToken, requestedName, logger, theme) {
|
|
252
|
+
const selectedTokens = await resolveNamedManagedTokens(accountId, accountSource, bootstrapToken, requestedName, logger, theme, {
|
|
253
|
+
promptMessage: "Enter the Devflare token name to delete:",
|
|
254
|
+
actionLabel: "Deleting",
|
|
255
|
+
multipleMatchMessage: "Deleting all exact matches"
|
|
256
|
+
});
|
|
257
|
+
if ("exitCode" in selectedTokens) return selectedTokens;
|
|
258
|
+
const { tokenName, matchingTokens } = selectedTokens;
|
|
259
|
+
for (const token of matchingTokens) await deleteAccountOwnedAPIToken(accountId, token.id, {
|
|
260
|
+
...CLI_API_OPTIONS,
|
|
261
|
+
token: bootstrapToken
|
|
262
|
+
});
|
|
263
|
+
logger.success(`Deleted ${matchingTokens.length} Devflare-managed token(s) named ${tokenName}`);
|
|
264
|
+
return {
|
|
265
|
+
exitCode: 0,
|
|
266
|
+
output: matchingTokens.map((token) => token.id).join("\n")
|
|
267
|
+
};
|
|
268
|
+
}
|
|
269
|
+
async function deleteAllManagedTokens(accountId, accountSource, bootstrapToken, logger, theme) {
|
|
270
|
+
logLine(logger);
|
|
271
|
+
logLine(logger, `${yellow("tokens", theme)} ${dim("Deleting all Devflare-managed account-owned tokens…", theme)}`);
|
|
272
|
+
logLine(logger, `${dim("Account:", theme)} ${green(accountId, theme)} ${whiteDim(`(${accountSource})`, theme)}`);
|
|
273
|
+
const accountTokens = await listAccountOwnedAPITokens(accountId, {
|
|
274
|
+
...CLI_API_OPTIONS,
|
|
275
|
+
token: bootstrapToken
|
|
276
|
+
});
|
|
277
|
+
const managedTokens = filterDevflareManagedTokens(accountTokens);
|
|
278
|
+
if (managedTokens.length === 0) {
|
|
279
|
+
logger.success("No Devflare-managed tokens were found, so nothing was deleted.");
|
|
280
|
+
return { exitCode: 0 };
|
|
281
|
+
}
|
|
282
|
+
for (const token of managedTokens) await deleteAccountOwnedAPIToken(accountId, token.id, {
|
|
283
|
+
...CLI_API_OPTIONS,
|
|
284
|
+
token: bootstrapToken
|
|
285
|
+
});
|
|
286
|
+
logger.success(`Deleted ${managedTokens.length} Devflare-managed token(s)`);
|
|
287
|
+
const untouchedTokenCount = accountTokens.length - managedTokens.length;
|
|
288
|
+
if (untouchedTokenCount > 0) logLine(logger, dim(`Left ${untouchedTokenCount} non-Devflare token(s) untouched.`, theme));
|
|
289
|
+
return {
|
|
290
|
+
exitCode: 0,
|
|
291
|
+
output: managedTokens.map((token) => token.id).join("\n")
|
|
292
|
+
};
|
|
293
|
+
}
|
|
294
|
+
async function runTokenCommand(parsed, logger, _options) {
|
|
295
|
+
const bootstrapToken = parsed.args[0]?.trim();
|
|
296
|
+
const theme = createCliTheme(parsed.options);
|
|
297
|
+
if (!bootstrapToken) {
|
|
298
|
+
logUsage(logger, theme);
|
|
299
|
+
return { exitCode: 1 };
|
|
300
|
+
}
|
|
301
|
+
const tokenOperation = resolveTokenOperation(parsed);
|
|
302
|
+
if (typeof tokenOperation === "string") {
|
|
303
|
+
logUsage(logger, theme);
|
|
304
|
+
return { exitCode: 1 };
|
|
305
|
+
}
|
|
306
|
+
const requestedAccountId = getTrimmedStringOption(parsed.options, "account");
|
|
307
|
+
try {
|
|
308
|
+
const { accountId, source } = await resolveRequestedAccountId(requestedAccountId, bootstrapToken);
|
|
309
|
+
switch (tokenOperation.kind) {
|
|
310
|
+
case "new": return createManagedToken(accountId, source, bootstrapToken, tokenOperation.requestedName, parsed.options["all-flags"] === true, logger, theme);
|
|
311
|
+
case "roll": return rollManagedTokensByName(accountId, source, bootstrapToken, tokenOperation.requestedName, logger, theme);
|
|
312
|
+
case "list": return listManagedTokens(accountId, source, bootstrapToken, logger, theme);
|
|
313
|
+
case "delete": return deleteManagedTokensByName(accountId, source, bootstrapToken, tokenOperation.requestedName, logger, theme);
|
|
314
|
+
case "delete-all": return deleteAllManagedTokens(accountId, source, bootstrapToken, logger, theme);
|
|
315
|
+
}
|
|
316
|
+
} catch (error) {
|
|
317
|
+
if (error instanceof AuthenticationError) {
|
|
318
|
+
logger.error(error.message);
|
|
319
|
+
return { exitCode: 1 };
|
|
320
|
+
}
|
|
321
|
+
if (error instanceof CloudflareAPIError) {
|
|
322
|
+
logger.error(`API Error: ${error.message}`);
|
|
323
|
+
return { exitCode: 1 };
|
|
324
|
+
}
|
|
325
|
+
if (error instanceof Error) {
|
|
326
|
+
logger.error(error.message);
|
|
327
|
+
return { exitCode: 1 };
|
|
328
|
+
}
|
|
329
|
+
throw error;
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
//#endregion
|
|
333
|
+
export { runTokenCommand };
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
import { a as apiGetAll, c as apiPut, r as apiDelete, s as apiPost } from "./api-TzdliH-6.js";
|
|
2
|
+
//#region src/cloudflare/known-permission-group-ids.generated.ts
|
|
3
|
+
const KNOWN_PERMISSION_GROUP_IDS_DATA = {
|
|
4
|
+
WORKERS_SCRIPTS_WRITE: null,
|
|
5
|
+
WORKERS_SCRIPTS_READ: null,
|
|
6
|
+
ACCOUNT_SETTINGS_READ: null,
|
|
7
|
+
WORKERS_KV_STORAGE_WRITE: null,
|
|
8
|
+
WORKERS_KV_STORAGE_READ: null,
|
|
9
|
+
ACCOUNT_API_TOKENS_WRITE: null,
|
|
10
|
+
ACCOUNT_API_TOKENS_READ: null
|
|
11
|
+
};
|
|
12
|
+
//#endregion
|
|
13
|
+
//#region src/cloudflare/tokens.ts
|
|
14
|
+
const MAX_ACCOUNT_OWNED_TOKEN_PERMISSION_GROUPS = 300;
|
|
15
|
+
const DEVFLARE_MANAGED_TOKEN_PREFIX = "devflare-";
|
|
16
|
+
const ACCOUNT_OWNED_TOKEN_SCOPE = "com.cloudflare.api.account";
|
|
17
|
+
const ACCOUNT_ZONE_OWNED_TOKEN_SCOPE = "com.cloudflare.api.account.zone";
|
|
18
|
+
const ACCOUNT_API_TOKENS_PERMISSION_GROUP_NAME_PATTERN = /^Account API Tokens\b/i;
|
|
19
|
+
const DEVFLARE_MANAGED_TOKEN_NAME_PATTERN = /^devflare-/i;
|
|
20
|
+
const DEVFLARE_PERMISSION_GROUP_NAME_PATTERNS = [
|
|
21
|
+
/^Account Analytics /i,
|
|
22
|
+
/^Account Settings /i,
|
|
23
|
+
/^Account Filter Lists /i,
|
|
24
|
+
/^AI /i,
|
|
25
|
+
/^Analytics /i,
|
|
26
|
+
/^Browser Rendering /i,
|
|
27
|
+
/^Cache Purge\b/i,
|
|
28
|
+
/^D1 /i,
|
|
29
|
+
/^DNS /i,
|
|
30
|
+
/^Email /i,
|
|
31
|
+
/^Hyperdrive /i,
|
|
32
|
+
/^Images /i,
|
|
33
|
+
/^Logs /i,
|
|
34
|
+
/^Logpush /i,
|
|
35
|
+
/^Pages /i,
|
|
36
|
+
/^Queues /i,
|
|
37
|
+
/^R2 /i,
|
|
38
|
+
/^SSL and Certificates /i,
|
|
39
|
+
/^Stream /i,
|
|
40
|
+
/^Vectorize /i,
|
|
41
|
+
/^Workers /i,
|
|
42
|
+
/^Zone Settings /i,
|
|
43
|
+
/^Zone /i
|
|
44
|
+
];
|
|
45
|
+
/**
|
|
46
|
+
* Symbolic names for individual Cloudflare permission groups we care about
|
|
47
|
+
* when reasoning about a Devflare token policy. Stable ids (when known)
|
|
48
|
+
* should be preferred over display names, which Cloudflare is free to
|
|
49
|
+
* rename or localize at any time.
|
|
50
|
+
*
|
|
51
|
+
* Entries set to `undefined` have not been confidently verified against
|
|
52
|
+
* Cloudflare's `GET /accounts/:id/tokens/permission_groups` endpoint and
|
|
53
|
+
* fall back to exact display-name matching via
|
|
54
|
+
* {@link KNOWN_PERMISSION_GROUP_DISPLAY_NAMES}.
|
|
55
|
+
*
|
|
56
|
+
* The verified UUIDs (or `null` placeholders) live in
|
|
57
|
+
* `known-permission-group-ids.generated.ts`, which is rewritten by
|
|
58
|
+
* `scripts/refresh-permission-groups.ts` against a maintainer's Cloudflare
|
|
59
|
+
* account so this file does not need hand-edits when Cloudflare publishes
|
|
60
|
+
* or rotates permission-group ids.
|
|
61
|
+
*/
|
|
62
|
+
function deriveKnownPermissionGroupIds(data) {
|
|
63
|
+
const result = {};
|
|
64
|
+
for (const key of Object.keys(data)) {
|
|
65
|
+
const value = data[key];
|
|
66
|
+
result[key] = value === null ? void 0 : value;
|
|
67
|
+
}
|
|
68
|
+
return result;
|
|
69
|
+
}
|
|
70
|
+
deriveKnownPermissionGroupIds(KNOWN_PERMISSION_GROUP_IDS_DATA);
|
|
71
|
+
function dedupePermissionGroups(permissionGroups) {
|
|
72
|
+
const seenIds = /* @__PURE__ */ new Set();
|
|
73
|
+
return permissionGroups.filter((permissionGroup) => {
|
|
74
|
+
if (seenIds.has(permissionGroup.id)) return false;
|
|
75
|
+
seenIds.add(permissionGroup.id);
|
|
76
|
+
return true;
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
function dedupePermissionGroupIds(permissionGroupIds) {
|
|
80
|
+
return Array.from(new Set(permissionGroupIds.map((id) => id.trim()).filter(Boolean)));
|
|
81
|
+
}
|
|
82
|
+
function dedupeScopedPermissionGroups(permissionGroups) {
|
|
83
|
+
const seenIds = /* @__PURE__ */ new Set();
|
|
84
|
+
return permissionGroups.filter((permissionGroup) => {
|
|
85
|
+
const id = permissionGroup.id.trim();
|
|
86
|
+
if (!id || seenIds.has(id)) return false;
|
|
87
|
+
seenIds.add(id);
|
|
88
|
+
return true;
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
function permissionGroupHasScope(permissionGroup, scope) {
|
|
92
|
+
return permissionGroup.scopes.some((value) => value.trim() === scope);
|
|
93
|
+
}
|
|
94
|
+
function buildCreateTokenPoliciesFromPermissionGroups(accountId, permissionGroups) {
|
|
95
|
+
const dedupedPermissionGroups = dedupeScopedPermissionGroups(permissionGroups);
|
|
96
|
+
const accountPermissionGroupIds = dedupePermissionGroupIds(dedupedPermissionGroups.filter((permissionGroup) => permissionGroupHasScope(permissionGroup, ACCOUNT_OWNED_TOKEN_SCOPE)).map((permissionGroup) => permissionGroup.id));
|
|
97
|
+
const zonePermissionGroupIds = dedupePermissionGroupIds(dedupedPermissionGroups.filter((permissionGroup) => permissionGroupHasScope(permissionGroup, ACCOUNT_ZONE_OWNED_TOKEN_SCOPE)).map((permissionGroup) => permissionGroup.id));
|
|
98
|
+
const policies = [];
|
|
99
|
+
if (accountPermissionGroupIds.length > 0) policies.push({
|
|
100
|
+
effect: "allow",
|
|
101
|
+
resources: { [`com.cloudflare.api.account.${accountId}`]: "*" },
|
|
102
|
+
permission_groups: accountPermissionGroupIds.map((id) => ({ id }))
|
|
103
|
+
});
|
|
104
|
+
if (zonePermissionGroupIds.length > 0) policies.push({
|
|
105
|
+
effect: "allow",
|
|
106
|
+
resources: { [`com.cloudflare.api.account.${accountId}`]: { [`${ACCOUNT_ZONE_OWNED_TOKEN_SCOPE}.*`]: "*" } },
|
|
107
|
+
permission_groups: zonePermissionGroupIds.map((id) => ({ id }))
|
|
108
|
+
});
|
|
109
|
+
return policies;
|
|
110
|
+
}
|
|
111
|
+
function buildCreateTokenPoliciesFromPermissionGroupIds(accountId, permissionGroupIds) {
|
|
112
|
+
const dedupedPermissionGroupIds = dedupePermissionGroupIds(permissionGroupIds);
|
|
113
|
+
if (dedupedPermissionGroupIds.length === 0) return [];
|
|
114
|
+
return [{
|
|
115
|
+
effect: "allow",
|
|
116
|
+
resources: { [`com.cloudflare.api.account.${accountId}`]: "*" },
|
|
117
|
+
permission_groups: dedupedPermissionGroupIds.map((id) => ({ id }))
|
|
118
|
+
}];
|
|
119
|
+
}
|
|
120
|
+
function excludeAccountApiTokensPermissionGroups(permissionGroups) {
|
|
121
|
+
return permissionGroups.filter((permissionGroup) => {
|
|
122
|
+
return !ACCOUNT_API_TOKENS_PERMISSION_GROUP_NAME_PATTERN.test(permissionGroup.name);
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
function keepAccountOwnedTokenCompatiblePermissionGroups(permissionGroups) {
|
|
126
|
+
return permissionGroups.filter((permissionGroup) => {
|
|
127
|
+
return permissionGroup.scopes.some((scope) => {
|
|
128
|
+
const normalizedScope = scope.trim();
|
|
129
|
+
return normalizedScope === ACCOUNT_OWNED_TOKEN_SCOPE || normalizedScope === ACCOUNT_ZONE_OWNED_TOKEN_SCOPE;
|
|
130
|
+
});
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
function selectReusableAccountOwnedTokenPermissionGroups(permissionGroups) {
|
|
134
|
+
return dedupePermissionGroups(excludeAccountApiTokensPermissionGroups(keepAccountOwnedTokenCompatiblePermissionGroups(permissionGroups)));
|
|
135
|
+
}
|
|
136
|
+
function parseOptionalDate(value) {
|
|
137
|
+
if (!value) return;
|
|
138
|
+
const parsed = new Date(value);
|
|
139
|
+
return Number.isNaN(parsed.getTime()) ? void 0 : parsed;
|
|
140
|
+
}
|
|
141
|
+
function mapAccountOwnedAPITokenPolicy(policy) {
|
|
142
|
+
return {
|
|
143
|
+
id: policy.id,
|
|
144
|
+
effect: policy.effect,
|
|
145
|
+
permissionGroups: policy.permission_groups?.map((permissionGroup) => ({
|
|
146
|
+
id: permissionGroup.id,
|
|
147
|
+
name: permissionGroup.name
|
|
148
|
+
}))
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
function mapAccountOwnedAPIToken(token) {
|
|
152
|
+
return {
|
|
153
|
+
id: token.id,
|
|
154
|
+
name: token.name ?? token.id,
|
|
155
|
+
status: token.status,
|
|
156
|
+
value: token.value,
|
|
157
|
+
issuedOn: parseOptionalDate(token.issued_on),
|
|
158
|
+
modifiedOn: parseOptionalDate(token.modified_on),
|
|
159
|
+
lastUsedOn: parseOptionalDate(token.last_used_on),
|
|
160
|
+
policies: token.policies?.map(mapAccountOwnedAPITokenPolicy)
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
function isDevflareManagedTokenName(name) {
|
|
164
|
+
return DEVFLARE_MANAGED_TOKEN_NAME_PATTERN.test(name.trim());
|
|
165
|
+
}
|
|
166
|
+
function normalizeDevflareTokenName(name) {
|
|
167
|
+
const trimmedName = name.trim();
|
|
168
|
+
if (!trimmedName) throw new Error("Devflare token name cannot be empty");
|
|
169
|
+
const suffix = isDevflareManagedTokenName(trimmedName) ? trimmedName.replace(DEVFLARE_MANAGED_TOKEN_NAME_PATTERN, "") : trimmedName;
|
|
170
|
+
if (!suffix) throw new Error("Devflare token name cannot be empty");
|
|
171
|
+
return `${DEVFLARE_MANAGED_TOKEN_PREFIX}${suffix}`;
|
|
172
|
+
}
|
|
173
|
+
function stripDevflareTokenNamePrefix(name) {
|
|
174
|
+
const trimmedName = name.trim();
|
|
175
|
+
if (!trimmedName) return trimmedName;
|
|
176
|
+
return trimmedName.replace(DEVFLARE_MANAGED_TOKEN_NAME_PATTERN, "") || trimmedName;
|
|
177
|
+
}
|
|
178
|
+
function filterDevflareManagedTokens(tokens) {
|
|
179
|
+
return tokens.filter((token) => isDevflareManagedTokenName(token.name));
|
|
180
|
+
}
|
|
181
|
+
function selectDevflarePermissionGroups(permissionGroups) {
|
|
182
|
+
const selectedPermissionGroups = dedupePermissionGroups(selectReusableAccountOwnedTokenPermissionGroups(permissionGroups).filter((permissionGroup) => {
|
|
183
|
+
return DEVFLARE_PERMISSION_GROUP_NAME_PATTERNS.some((pattern) => {
|
|
184
|
+
return pattern.test(permissionGroup.name);
|
|
185
|
+
});
|
|
186
|
+
}));
|
|
187
|
+
if (selectedPermissionGroups.length === 0) throw new Error("Could not map the available Cloudflare permission groups to a Devflare token policy.");
|
|
188
|
+
if (selectedPermissionGroups.length > MAX_ACCOUNT_OWNED_TOKEN_PERMISSION_GROUPS) throw new Error(`Devflare selected ${selectedPermissionGroups.length} permission groups, which exceeds Cloudflare's ${MAX_ACCOUNT_OWNED_TOKEN_PERMISSION_GROUPS}-group limit for account-owned tokens.`);
|
|
189
|
+
return selectedPermissionGroups;
|
|
190
|
+
}
|
|
191
|
+
function selectAllReusablePermissionGroups(permissionGroups) {
|
|
192
|
+
const selectedPermissionGroups = selectReusableAccountOwnedTokenPermissionGroups(permissionGroups);
|
|
193
|
+
if (selectedPermissionGroups.length === 0) throw new Error("Could not find any reusable account/zone-scoped Cloudflare permission groups for this Devflare token.");
|
|
194
|
+
if (selectedPermissionGroups.length > MAX_ACCOUNT_OWNED_TOKEN_PERMISSION_GROUPS) throw new Error(`Devflare selected ${selectedPermissionGroups.length} permission groups, which exceeds Cloudflare\'s ${MAX_ACCOUNT_OWNED_TOKEN_PERMISSION_GROUPS}-group limit for account-owned tokens.`);
|
|
195
|
+
return selectedPermissionGroups;
|
|
196
|
+
}
|
|
197
|
+
async function listAccountTokenPermissionGroups(accountId, options) {
|
|
198
|
+
return dedupePermissionGroups(await apiGetAll(`/accounts/${accountId}/tokens/permission_groups`, options));
|
|
199
|
+
}
|
|
200
|
+
async function listAccountOwnedAPITokens(accountId, options) {
|
|
201
|
+
return (await apiGetAll(`/accounts/${accountId}/tokens`, options)).map(mapAccountOwnedAPIToken);
|
|
202
|
+
}
|
|
203
|
+
async function deleteAccountOwnedAPIToken(accountId, tokenId, options) {
|
|
204
|
+
return apiDelete(`/accounts/${accountId}/tokens/${tokenId}`, options);
|
|
205
|
+
}
|
|
206
|
+
async function rollAccountOwnedAPITokenValue(accountId, tokenId, options) {
|
|
207
|
+
return apiPut(`/accounts/${accountId}/tokens/${tokenId}/value`, {}, options);
|
|
208
|
+
}
|
|
209
|
+
async function createAccountOwnedAPIToken(accountId, options, clientOptions) {
|
|
210
|
+
const permissionGroupIds = dedupePermissionGroupIds(options.permissionGroups?.map((permissionGroup) => permissionGroup.id) ?? options.permissionGroupIds ?? []);
|
|
211
|
+
if (permissionGroupIds.length === 0) throw new Error("Cannot create a Devflare token without any permission groups");
|
|
212
|
+
if (permissionGroupIds.length > MAX_ACCOUNT_OWNED_TOKEN_PERMISSION_GROUPS) throw new Error(`Cannot create a Devflare token with more than ${MAX_ACCOUNT_OWNED_TOKEN_PERMISSION_GROUPS} permission groups.`);
|
|
213
|
+
const policies = options.permissionGroups ? buildCreateTokenPoliciesFromPermissionGroups(accountId, options.permissionGroups) : buildCreateTokenPoliciesFromPermissionGroupIds(accountId, permissionGroupIds);
|
|
214
|
+
if (policies.length === 0) throw new Error("Cannot create a Devflare token without any account- or zone-scoped permission groups");
|
|
215
|
+
return mapAccountOwnedAPIToken(await apiPost(`/accounts/${accountId}/tokens`, {
|
|
216
|
+
name: options.name,
|
|
217
|
+
policies
|
|
218
|
+
}, clientOptions));
|
|
219
|
+
}
|
|
220
|
+
//#endregion
|
|
221
|
+
export { listAccountTokenPermissionGroups as a, selectAllReusablePermissionGroups as c, listAccountOwnedAPITokens as i, selectDevflarePermissionGroups as l, deleteAccountOwnedAPIToken as n, normalizeDevflareTokenName as o, filterDevflareManagedTokens as r, rollAccountOwnedAPITokenValue as s, createAccountOwnedAPIToken as t, stripDevflareTokenNamePrefix as u };
|