@ponharu/pkgflare 1.0.0 → 1.1.1
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/README.md +45 -2
- package/dist/cli.js +174 -9
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +16 -2
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/worker.js +1207 -61
- package/dist/worker.js.map +1 -1
- package/docs/architecture.md +6 -1
- package/docs/operations.md +71 -4
- package/docs/specification.md +17 -3
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -9,7 +9,7 @@ Deploy a scoped private npm registry to your own Cloudflare account.
|
|
|
9
9
|
- Standard scoped package publish and install endpoints
|
|
10
10
|
- Immutable tarballs in R2
|
|
11
11
|
- Package metadata and mutable dist-tags in D1
|
|
12
|
-
-
|
|
12
|
+
- Cloudflare Secret tokens and short-lived GitHub Actions OIDC authentication
|
|
13
13
|
- Repeatable deployment through one `pkgflare deploy` command
|
|
14
14
|
- npm-compatible metadata and tarball responses tested with npm, pnpm, Yarn Classic, and Bun
|
|
15
15
|
|
|
@@ -144,7 +144,47 @@ The `.npmrc` contains an environment variable reference and can be committed; th
|
|
|
144
144
|
|
|
145
145
|
Yarn Berry and other clients are outside the tested compatibility baseline. pkgflare does not implement `npm login`, `npm adduser`, `npm unpublish`, `npm deprecate`, search, or the npm audit API. It is a scoped private registry, not a complete replacement for the public npm service.
|
|
146
146
|
|
|
147
|
-
A read token can read every package in the registry. A publish token can also publish packages and change dist-tags across all configured scopes.
|
|
147
|
+
A Secret read token can read every package in the registry. A Secret publish token can also publish packages and change dist-tags across all configured scopes. Secret-token permissions are not restricted per package or scope; use GitHub OIDC package grants or separate registry deployments when publishers need narrower trust boundaries.
|
|
148
|
+
|
|
149
|
+
GitHub Actions jobs can instead use short-lived OIDC tokens with per-package grants and no stored registry token. Configure the trusted repository IDs, owner ID, ref, workflow, permissions, and package names under `auth.githubOidc`, then request the configured audience in the job:
|
|
150
|
+
|
|
151
|
+
```ts
|
|
152
|
+
auth: {
|
|
153
|
+
provider: "secrets",
|
|
154
|
+
tokens: [
|
|
155
|
+
{ binding: "PKGFLARE_READ_TOKEN", permissions: ["read"] },
|
|
156
|
+
{ binding: "PKGFLARE_PUBLISH_TOKEN", permissions: ["publish"] },
|
|
157
|
+
],
|
|
158
|
+
githubOidc: {
|
|
159
|
+
audience: "pkgflare://packages.example.com",
|
|
160
|
+
subjects: [{
|
|
161
|
+
repositoryId: "123456789",
|
|
162
|
+
repositoryOwnerId: "987654321",
|
|
163
|
+
ref: "refs/heads/main",
|
|
164
|
+
workflowRef: "acme/example/.github/workflows/publish.yml@refs/heads/main",
|
|
165
|
+
permissions: ["publish"],
|
|
166
|
+
packages: ["@acme/example"],
|
|
167
|
+
}],
|
|
168
|
+
},
|
|
169
|
+
}
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
```yaml
|
|
173
|
+
permissions:
|
|
174
|
+
contents: read
|
|
175
|
+
id-token: write
|
|
176
|
+
|
|
177
|
+
steps:
|
|
178
|
+
- uses: actions/checkout@v4
|
|
179
|
+
- uses: actions/setup-node@v4
|
|
180
|
+
with:
|
|
181
|
+
node-version: 22
|
|
182
|
+
- run: npm ci
|
|
183
|
+
- name: Publish
|
|
184
|
+
run: NPM_TOKEN="$(npx pkgflare auth github --audience 'pkgflare://packages.example.com')" npm publish
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
The package repository's `.npmrc` still points its scope to pkgflare and references `${NPM_TOKEN}`. Use the same command with `npm ci` or another supported client for OIDC-authenticated reads. See [GitHub Actions OIDC](./docs/operations.md#github-actions-oidc) for reusable workflows, wildcard rules, and the security model.
|
|
148
188
|
|
|
149
189
|
Versions are immutable. To promote or roll back an existing version, use the publish token with `npm dist-tag`:
|
|
150
190
|
|
|
@@ -159,12 +199,15 @@ The first command assumes `1.1.0` has already been published. Moving a tag affec
|
|
|
159
199
|
|
|
160
200
|
```text
|
|
161
201
|
pkgflare deploy [--config <path>] [--secrets-file <path>] [--adopt-existing]
|
|
202
|
+
pkgflare auth github --audience <audience>
|
|
162
203
|
pkgflare init
|
|
163
204
|
pkgflare token generate
|
|
164
205
|
```
|
|
165
206
|
|
|
166
207
|
`token generate` creates a cryptographically random token locally and prints it once. pkgflare does not store, distribute, list, or revoke tokens.
|
|
167
208
|
|
|
209
|
+
`auth github` requests a short-lived GitHub Actions OIDC JWT and writes only that JWT to standard output. It is intended for command substitution and fails outside the GitHub Actions OIDC environment.
|
|
210
|
+
|
|
168
211
|
## Publish consistency
|
|
169
212
|
|
|
170
213
|
A package version is immutable, while dist-tags remain mutable for promotion and rollback. pkgflare incrementally parses the standard npm publish document, decodes its Base64 attachment into fixed-size R2 multipart chunks, and calculates SHA-1 and SHA-512 without holding the complete tarball in Worker memory. A unique attempt object is published in D1 only after R2 completes; D1's package-and-version constraint chooses the sole winner of concurrent publishes.
|
package/dist/cli.js
CHANGED
|
@@ -23,9 +23,89 @@ var scopePattern = /^@[a-z0-9](?:[a-z0-9._-]*[a-z0-9])?$/;
|
|
|
23
23
|
var bindingPattern = /^[A-Z][A-Z0-9_]*$/;
|
|
24
24
|
var hostnamePattern = /^(?=.{1,253}$)(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z](?:[a-z0-9-]{0,61}[a-z0-9])?$/;
|
|
25
25
|
var reservedBindings = /* @__PURE__ */ new Set(["PKGFLARE_DB", "PKGFLARE_BUCKET", "PKGFLARE_CONFIG"]);
|
|
26
|
+
var githubIdPattern = /^[1-9][0-9]{0,19}$/;
|
|
27
|
+
var audiencePattern = /^[\x21-\x7e]{1,256}$/;
|
|
28
|
+
var refPattern = /^refs\/(?:heads|tags)\/[A-Za-z0-9._/-]+\*?$/;
|
|
29
|
+
var workflowRefPattern = /^[A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+\/\.github\/workflows\/[A-Za-z0-9_.-]+\.ya?ml@refs\/(?:heads|tags)\/[A-Za-z0-9._/-]+\*?$/;
|
|
30
|
+
var jobWorkflowRefPattern = /^[A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+\/\.github\/workflows\/[A-Za-z0-9_.-]+\.ya?ml@(?:refs\/(?:heads|tags)\/[A-Za-z0-9._/-]+\*?|[0-9a-f]{40})$/;
|
|
31
|
+
var packageSegmentPattern = /^(?!\.)(?:[a-z0-9._-]+)$/;
|
|
32
|
+
var maximumGithubSubjects = 128;
|
|
33
|
+
var maximumPackagesPerSubject = 128;
|
|
34
|
+
var maximumRuntimeConfigBytes = 5 * 1024;
|
|
26
35
|
function isObject(value) {
|
|
27
36
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
28
37
|
}
|
|
38
|
+
function normalizePermissions(value, label) {
|
|
39
|
+
if (!Array.isArray(value) || value.length === 0 || value.some((permission) => permission !== "read" && permission !== "publish")) {
|
|
40
|
+
throw new Error(`invalid permissions for ${label}`);
|
|
41
|
+
}
|
|
42
|
+
return [...new Set(value)];
|
|
43
|
+
}
|
|
44
|
+
function isSafePattern(value, pattern) {
|
|
45
|
+
if (!pattern.test(value)) return false;
|
|
46
|
+
const wildcard = value.indexOf("*");
|
|
47
|
+
return wildcard === -1 || wildcard === value.length - 1;
|
|
48
|
+
}
|
|
49
|
+
function normalizeGithubOidc(value, configuredScopes) {
|
|
50
|
+
if (!isObject(value) || typeof value.audience !== "string") {
|
|
51
|
+
throw new Error("githubOidc must define an audience and trusted subjects");
|
|
52
|
+
}
|
|
53
|
+
if (!audiencePattern.test(value.audience)) {
|
|
54
|
+
throw new Error("githubOidc audience must be 1-256 printable ASCII characters");
|
|
55
|
+
}
|
|
56
|
+
if (!Array.isArray(value.subjects) || value.subjects.length === 0 || value.subjects.length > maximumGithubSubjects) {
|
|
57
|
+
throw new Error(`githubOidc must define 1-${String(maximumGithubSubjects)} subjects`);
|
|
58
|
+
}
|
|
59
|
+
const subjects = value.subjects.map((subjectValue, index) => {
|
|
60
|
+
const label = `githubOidc subject ${String(index + 1)}`;
|
|
61
|
+
if (!isObject(subjectValue)) throw new Error(`${label} must be an object`);
|
|
62
|
+
const { repositoryId, repositoryOwnerId, ref, workflowRef, jobWorkflowRef } = subjectValue;
|
|
63
|
+
if (typeof repositoryId !== "string" || !githubIdPattern.test(repositoryId)) {
|
|
64
|
+
throw new Error(`${label} repositoryId must be a decimal GitHub repository ID`);
|
|
65
|
+
}
|
|
66
|
+
if (typeof repositoryOwnerId !== "string" || !githubIdPattern.test(repositoryOwnerId)) {
|
|
67
|
+
throw new Error(`${label} repositoryOwnerId must be a decimal GitHub owner ID`);
|
|
68
|
+
}
|
|
69
|
+
if (typeof ref !== "string" || !isSafePattern(ref, refPattern)) {
|
|
70
|
+
throw new Error(`${label} ref must be an exact branch/tag ref or trailing-wildcard pattern`);
|
|
71
|
+
}
|
|
72
|
+
if (typeof workflowRef !== "string" || !isSafePattern(workflowRef, workflowRefPattern)) {
|
|
73
|
+
throw new Error(
|
|
74
|
+
`${label} workflowRef must identify a workflow file at an exact or trailing-wildcard ref`
|
|
75
|
+
);
|
|
76
|
+
}
|
|
77
|
+
if (jobWorkflowRef !== void 0 && (typeof jobWorkflowRef !== "string" || !isSafePattern(jobWorkflowRef, jobWorkflowRefPattern))) {
|
|
78
|
+
throw new Error(
|
|
79
|
+
`${label} jobWorkflowRef must identify a reusable workflow at a full commit SHA or an exact/trailing-wildcard branch or tag ref`
|
|
80
|
+
);
|
|
81
|
+
}
|
|
82
|
+
const permissions = normalizePermissions(subjectValue.permissions, label);
|
|
83
|
+
if (!Array.isArray(subjectValue.packages) || subjectValue.packages.length === 0 || subjectValue.packages.length > maximumPackagesPerSubject || subjectValue.packages.some((packageName) => typeof packageName !== "string")) {
|
|
84
|
+
throw new Error(
|
|
85
|
+
`${label} must define 1-${String(maximumPackagesPerSubject)} package patterns`
|
|
86
|
+
);
|
|
87
|
+
}
|
|
88
|
+
const packages = [...new Set(subjectValue.packages)];
|
|
89
|
+
for (const packagePattern of packages) {
|
|
90
|
+
const slash = packagePattern.indexOf("/");
|
|
91
|
+
const scope = packagePattern.slice(0, slash);
|
|
92
|
+
const packageSegment = packagePattern.slice(slash + 1);
|
|
93
|
+
if (slash === -1 || packagePattern.length > 214 || !configuredScopes.includes(scope) || packageSegment !== "*" && !packageSegmentPattern.test(packageSegment)) {
|
|
94
|
+
throw new Error(`${label} contains an invalid or unconfigured package pattern`);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
return {
|
|
98
|
+
repositoryId,
|
|
99
|
+
repositoryOwnerId,
|
|
100
|
+
ref,
|
|
101
|
+
workflowRef,
|
|
102
|
+
...jobWorkflowRef === void 0 ? {} : { jobWorkflowRef },
|
|
103
|
+
permissions,
|
|
104
|
+
packages
|
|
105
|
+
};
|
|
106
|
+
});
|
|
107
|
+
return { audience: value.audience, subjects };
|
|
108
|
+
}
|
|
29
109
|
function normalizeConfig(value) {
|
|
30
110
|
if (!isObject(value)) throw new Error("configuration must be an object");
|
|
31
111
|
const { name, scopes: scopeValues, accountId, hostname, auth } = value;
|
|
@@ -50,11 +130,12 @@ function normalizeConfig(value) {
|
|
|
50
130
|
if (!isObject(auth) || auth.provider !== "secrets") {
|
|
51
131
|
throw new Error("unsupported authentication provider");
|
|
52
132
|
}
|
|
53
|
-
|
|
54
|
-
|
|
133
|
+
const tokenValues = auth.tokens ?? [];
|
|
134
|
+
if (!Array.isArray(tokenValues)) {
|
|
135
|
+
throw new Error("authentication token bindings must be an array");
|
|
55
136
|
}
|
|
56
137
|
const seenBindings = /* @__PURE__ */ new Set();
|
|
57
|
-
const tokens =
|
|
138
|
+
const tokens = tokenValues.map((tokenValue) => {
|
|
58
139
|
if (!isObject(tokenValue) || typeof tokenValue.binding !== "string") {
|
|
59
140
|
throw new Error("authentication token binding must be an object with a binding name");
|
|
60
141
|
}
|
|
@@ -69,19 +150,28 @@ function normalizeConfig(value) {
|
|
|
69
150
|
throw new Error(`duplicate secret binding: ${binding}`);
|
|
70
151
|
}
|
|
71
152
|
seenBindings.add(binding);
|
|
72
|
-
|
|
73
|
-
throw new Error(`invalid permissions for ${binding}`);
|
|
74
|
-
}
|
|
75
|
-
const permissions = [...new Set(permissionValues)];
|
|
153
|
+
const permissions = normalizePermissions(permissionValues, binding);
|
|
76
154
|
return { binding, permissions };
|
|
77
155
|
});
|
|
78
|
-
|
|
156
|
+
const githubOidc = auth.githubOidc === void 0 ? void 0 : normalizeGithubOidc(auth.githubOidc, scopes);
|
|
157
|
+
if (tokens.length === 0 && githubOidc === void 0) {
|
|
158
|
+
throw new Error("at least one authentication method is required");
|
|
159
|
+
}
|
|
160
|
+
const normalized = {
|
|
79
161
|
name,
|
|
80
162
|
scopes,
|
|
81
163
|
...accountId === void 0 ? {} : { accountId },
|
|
82
164
|
...hostname === void 0 ? {} : { hostname },
|
|
83
|
-
auth: {
|
|
165
|
+
auth: {
|
|
166
|
+
provider: "secrets",
|
|
167
|
+
tokens,
|
|
168
|
+
...githubOidc === void 0 ? {} : { githubOidc }
|
|
169
|
+
}
|
|
84
170
|
};
|
|
171
|
+
if (new TextEncoder().encode(JSON.stringify(normalized)).byteLength > maximumRuntimeConfigBytes) {
|
|
172
|
+
throw new Error("normalized configuration exceeds the 5 KiB Worker variable limit");
|
|
173
|
+
}
|
|
174
|
+
return normalized;
|
|
85
175
|
}
|
|
86
176
|
|
|
87
177
|
// src/cli/config-loader.ts
|
|
@@ -419,6 +509,74 @@ async function deploy(options) {
|
|
|
419
509
|
};
|
|
420
510
|
}
|
|
421
511
|
|
|
512
|
+
// src/cli/github-oidc.ts
|
|
513
|
+
async function readGithubTokenResponse(response) {
|
|
514
|
+
const maximumBytes = 32 * 1024;
|
|
515
|
+
if (response.body === null) throw new Error("GitHub OIDC token response is empty");
|
|
516
|
+
const reader = response.body.getReader();
|
|
517
|
+
const decoder = new TextDecoder("utf-8", { fatal: true });
|
|
518
|
+
let size = 0;
|
|
519
|
+
let contents = "";
|
|
520
|
+
try {
|
|
521
|
+
while (true) {
|
|
522
|
+
const { done, value: value2 } = await reader.read();
|
|
523
|
+
if (done) break;
|
|
524
|
+
size += value2.byteLength;
|
|
525
|
+
if (size > maximumBytes) {
|
|
526
|
+
await reader.cancel();
|
|
527
|
+
throw new Error("GitHub OIDC token response is too large");
|
|
528
|
+
}
|
|
529
|
+
contents += decoder.decode(value2, { stream: true });
|
|
530
|
+
}
|
|
531
|
+
contents += decoder.decode();
|
|
532
|
+
} finally {
|
|
533
|
+
reader.releaseLock();
|
|
534
|
+
}
|
|
535
|
+
let value;
|
|
536
|
+
try {
|
|
537
|
+
value = JSON.parse(contents);
|
|
538
|
+
} catch {
|
|
539
|
+
throw new Error("GitHub OIDC token response is invalid");
|
|
540
|
+
}
|
|
541
|
+
if (typeof value !== "object" || value === null || !("value" in value) || typeof value.value !== "string" || value.value.length > 16 * 1024 || !/^[^.]+\.[^.]+\.[^.]+$/.test(value.value)) {
|
|
542
|
+
throw new Error("GitHub OIDC token response is invalid");
|
|
543
|
+
}
|
|
544
|
+
return value.value;
|
|
545
|
+
}
|
|
546
|
+
async function requestGithubOidcToken(audience, environment = process.env) {
|
|
547
|
+
if (audience === void 0) throw new Error("--audience is required");
|
|
548
|
+
if (!/^[\x21-\x7e]{1,256}$/.test(audience)) {
|
|
549
|
+
throw new Error("--audience must be 1-256 printable ASCII characters");
|
|
550
|
+
}
|
|
551
|
+
const requestUrlValue = environment.ACTIONS_ID_TOKEN_REQUEST_URL;
|
|
552
|
+
const requestToken = environment.ACTIONS_ID_TOKEN_REQUEST_TOKEN;
|
|
553
|
+
if (requestUrlValue === void 0 || requestToken === void 0 || requestToken.length === 0) {
|
|
554
|
+
throw new Error("GitHub Actions OIDC environment is unavailable");
|
|
555
|
+
}
|
|
556
|
+
let requestUrl;
|
|
557
|
+
try {
|
|
558
|
+
requestUrl = new URL(requestUrlValue);
|
|
559
|
+
} catch {
|
|
560
|
+
throw new Error("GitHub Actions OIDC request URL is invalid");
|
|
561
|
+
}
|
|
562
|
+
if (requestUrl.protocol !== "https:" || requestUrl.hostname !== "token.actions.githubusercontent.com" && !requestUrl.hostname.endsWith(".actions.githubusercontent.com") || requestUrl.username !== "" || requestUrl.password !== "") {
|
|
563
|
+
throw new Error("GitHub Actions OIDC request URL is not trusted");
|
|
564
|
+
}
|
|
565
|
+
requestUrl.searchParams.set("audience", audience);
|
|
566
|
+
let response;
|
|
567
|
+
try {
|
|
568
|
+
response = await fetch(requestUrl, {
|
|
569
|
+
headers: { authorization: `bearer ${requestToken}` },
|
|
570
|
+
redirect: "error",
|
|
571
|
+
signal: AbortSignal.timeout(5e3)
|
|
572
|
+
});
|
|
573
|
+
} catch {
|
|
574
|
+
throw new Error("GitHub Actions OIDC token request failed");
|
|
575
|
+
}
|
|
576
|
+
if (!response.ok) throw new Error("GitHub Actions OIDC token request failed");
|
|
577
|
+
return readGithubTokenResponse(response);
|
|
578
|
+
}
|
|
579
|
+
|
|
422
580
|
// src/cli.ts
|
|
423
581
|
function valueAfter(arguments_, flag) {
|
|
424
582
|
const index = arguments_.indexOf(flag);
|
|
@@ -433,6 +591,7 @@ function help() {
|
|
|
433
591
|
|
|
434
592
|
Usage:
|
|
435
593
|
pkgflare deploy [--config <path>] [--secrets-file <path>] [--adopt-existing]
|
|
594
|
+
pkgflare auth github --audience <audience>
|
|
436
595
|
pkgflare init
|
|
437
596
|
pkgflare token generate
|
|
438
597
|
`
|
|
@@ -509,6 +668,12 @@ Deployment state: ${statePath}
|
|
|
509
668
|
await init(process.cwd());
|
|
510
669
|
return;
|
|
511
670
|
}
|
|
671
|
+
if (command === "auth" && subcommand === "github") {
|
|
672
|
+
const token = await requestGithubOidcToken(valueAfter(arguments_, "--audience"));
|
|
673
|
+
process.stdout.write(`${token}
|
|
674
|
+
`);
|
|
675
|
+
return;
|
|
676
|
+
}
|
|
512
677
|
if (command === "token" && subcommand === "generate") {
|
|
513
678
|
let binary = "";
|
|
514
679
|
for (const byte of randomBytes(32)) binary += String.fromCharCode(byte);
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/cli.ts","../src/cli/deploy.ts","../src/cli/config-loader.ts","../src/config.ts","../src/cli/runner.ts"],"sourcesContent":["import { randomBytes } from \"node:crypto\";\nimport { open } from \"node:fs/promises\";\nimport { relative, resolve } from \"node:path\";\nimport { deploy } from \"./cli/deploy.js\";\n\nfunction valueAfter(arguments_: readonly string[], flag: string): string | undefined {\n const index = arguments_.indexOf(flag);\n if (index === -1) return undefined;\n const value = arguments_[index + 1];\n if (value === undefined || value.startsWith(\"--\")) throw new Error(`${flag} requires a value`);\n return value;\n}\n\nfunction help(): void {\n process.stdout.write(\n `pkgflare\\n\\nUsage:\\n pkgflare deploy [--config <path>] [--secrets-file <path>] [--adopt-existing]\\n pkgflare init\\n pkgflare token generate\\n`,\n );\n}\n\nasync function init(cwd: string): Promise<void> {\n const path = resolve(cwd, \"pkgflare.config.ts\");\n const file = await open(path, \"wx\").catch((error: unknown) => {\n if ((error as NodeJS.ErrnoException).code === \"EEXIST\")\n throw new Error(\"pkgflare.config.ts already exists\");\n throw error;\n });\n await file.writeFile(\n `import { defineConfig } from \"@ponharu/pkgflare\";\\n\\nexport default defineConfig({\\n name: \"acme-registry\",\\n scopes: [\"@acme\"],\\n auth: {\\n provider: \"secrets\",\\n tokens: [\\n { binding: \"PKGFLARE_READ_TOKEN\", permissions: [\"read\"] },\\n { binding: \"PKGFLARE_PUBLISH_TOKEN\", permissions: [\"publish\"] },\\n ],\\n },\\n});\\n`,\n );\n await file.close();\n process.stdout.write(\"Created pkgflare.config.ts\\n\");\n}\n\nasync function main(arguments_: string[]): Promise<void> {\n const [command, subcommand] = arguments_;\n if (command === undefined || command === \"--help\" || command === \"-h\") {\n help();\n return;\n }\n if (command === \"deploy\") {\n const configFile = valueAfter(arguments_, \"--config\");\n const secretsFile = valueAfter(arguments_, \"--secrets-file\");\n const adoptExisting = arguments_.includes(\"--adopt-existing\");\n const result = await deploy({\n cwd: process.cwd(),\n ...(configFile === undefined ? {} : { configFile }),\n ...(secretsFile === undefined ? {} : { secretsFile }),\n adoptExisting,\n });\n const statePath = relative(process.cwd(), result.stateFile);\n process.stdout.write(`\\nDeployment state: ${statePath}\\n`);\n if (result.registryUrl !== null) {\n process.stdout.write(`Registry: ${result.registryUrl}\\n`);\n }\n process.stdout.write(\"\\nRegister each token secret if it was not supplied during deploy:\\n\");\n for (const binding of result.secretBindings) {\n process.stdout.write(` npx wrangler secret put ${binding} --config ${statePath}\\n`);\n }\n if (result.registryUrl !== null) {\n const host = new URL(result.registryUrl).host;\n process.stdout.write(\"\\n.npmrc:\\n\");\n for (const scope of result.scopes) {\n process.stdout.write(` ${scope}:registry=${result.registryUrl}\\n`);\n }\n process.stdout.write(` //${host}/:_authToken=\\${NPM_TOKEN}\\n`);\n }\n return;\n }\n if (command === \"init\") {\n await init(process.cwd());\n return;\n }\n if (command === \"token\" && subcommand === \"generate\") {\n let binary = \"\";\n for (const byte of randomBytes(32)) binary += String.fromCharCode(byte);\n const token = btoa(binary).replace(/\\+/g, \"-\").replace(/\\//g, \"_\").replace(/=+$/, \"\");\n process.stdout.write(`${token}\\n`);\n return;\n }\n throw new Error(`unknown command: ${arguments_.join(\" \")}`);\n}\n\nmain(process.argv.slice(2)).catch((error: unknown) => {\n const message = error instanceof Error ? error.message : String(error);\n process.stderr.write(`pkgflare: ${message}\\n`);\n process.exitCode = 1;\n});\n","import { copyFile, mkdir, readFile, readdir, writeFile } from \"node:fs/promises\";\nimport { dirname, join, relative, resolve } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport type { NormalizedConfig } from \"../config.js\";\nimport { loadConfig } from \"./config-loader.js\";\nimport { createWranglerRunner, type WranglerRunner } from \"./runner.js\";\n\nconst stateDirectoryName = \".pkgflare\";\nconst stateFileName = \"wrangler.json\";\nconst ownershipFileName = \"ownership.json\";\nconst d1Binding = \"PKGFLARE_DB\";\nconst r2Binding = \"PKGFLARE_BUCKET\";\n\ninterface D1Binding {\n binding: string;\n database_name: string;\n database_id: string;\n migrations_dir?: string;\n}\n\ninterface R2Binding {\n binding: string;\n bucket_name: string;\n}\n\ninterface WranglerState {\n $schema: string;\n account_id?: string;\n name: string;\n main: string;\n compatibility_date: string;\n workers_dev: boolean;\n routes?: Array<{ pattern: string; custom_domain: true }>;\n vars: { PKGFLARE_CONFIG: string };\n d1_databases: D1Binding[];\n r2_buckets: R2Binding[];\n}\n\ninterface D1ListEntry {\n name?: unknown;\n uuid?: unknown;\n}\n\ninterface WhoamiResult {\n loggedIn?: unknown;\n accounts?: unknown;\n}\n\ninterface AccountEntry {\n id: string;\n name?: string;\n}\n\ninterface OwnershipState {\n account_id: string;\n worker_name: string;\n}\n\nexport interface DeployOptions {\n cwd: string;\n configFile?: string;\n secretsFile?: string;\n adoptExisting?: boolean;\n runner?: WranglerRunner;\n assetsDirectory?: string;\n}\n\nexport interface DeployResult {\n registryUrl: string | null;\n stateFile: string;\n secretBindings: string[];\n scopes: string[];\n}\n\nfunction packageRoot(): string {\n return dirname(fileURLToPath(import.meta.url));\n}\n\nfunction stateFor(\n config: NormalizedConfig,\n accountId: string,\n previous?: WranglerState,\n): WranglerState {\n if (previous?.account_id !== undefined && previous.account_id !== accountId) {\n throw new Error(\"authenticated Cloudflare account does not match the deployment state\");\n }\n const state: WranglerState = {\n $schema:\n \"https://raw.githubusercontent.com/cloudflare/workers-sdk/main/packages/wrangler/config-schema.json\",\n account_id: accountId,\n name: config.name,\n main: \"runtime/worker.js\",\n compatibility_date: \"2026-08-01\",\n workers_dev: config.hostname === undefined,\n vars: { PKGFLARE_CONFIG: JSON.stringify(config) },\n d1_databases: previous?.d1_databases ?? [],\n r2_buckets: previous?.r2_buckets ?? [],\n };\n if (config.hostname !== undefined) {\n state.routes = [{ pattern: config.hostname, custom_domain: true }];\n }\n return state;\n}\n\nasync function readState(\n path: string,\n config: NormalizedConfig,\n): Promise<WranglerState | undefined> {\n let contents: string;\n try {\n contents = await readFile(path, \"utf8\");\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === \"ENOENT\") return undefined;\n throw error;\n }\n const state = JSON.parse(contents) as WranglerState;\n if (state.name !== config.name) {\n throw new Error(\n `existing deployment state belongs to ${state.name}; remove ${stateDirectoryName} only after verifying the remote resources`,\n );\n }\n return state;\n}\n\nasync function writeState(path: string, state: WranglerState): Promise<void> {\n await writeFile(path, `${JSON.stringify(state, null, 2)}\\n`, \"utf8\");\n}\n\nasync function readWorkerOwnership(\n path: string,\n workerName: string,\n accountId: string,\n): Promise<boolean> {\n let contents: string;\n try {\n contents = await readFile(path, \"utf8\");\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === \"ENOENT\") return false;\n throw error;\n }\n const ownership = JSON.parse(contents) as Partial<OwnershipState>;\n if (ownership.worker_name !== workerName || ownership.account_id !== accountId) {\n throw new Error(\"deployment ownership state does not match the configured Worker and account\");\n }\n return true;\n}\n\nasync function writeWorkerOwnership(\n path: string,\n workerName: string,\n accountId: string,\n): Promise<void> {\n const ownership: OwnershipState = { account_id: accountId, worker_name: workerName };\n await writeFile(path, `${JSON.stringify(ownership, null, 2)}\\n`, \"utf8\");\n}\n\nasync function copyRuntimeFiles(stateDirectory: string, root: string): Promise<void> {\n const runtimeDirectory = join(stateDirectory, \"runtime\");\n const migrationsDirectory = join(stateDirectory, \"migrations\");\n await Promise.all([\n mkdir(runtimeDirectory, { recursive: true }),\n mkdir(migrationsDirectory, { recursive: true }),\n ]);\n const sourceMigrations = resolve(root, \"..\", \"migrations\");\n const migrationFiles = (await readdir(sourceMigrations, { withFileTypes: true }))\n .filter((entry) => entry.isFile() && entry.name.endsWith(\".sql\"))\n .map((entry) => entry.name);\n // oxlint-disable-next-line unicorn/no-array-sort -- this array has just been created locally\n migrationFiles.sort();\n if (migrationFiles.length === 0) throw new Error(\"pkgflare package contains no D1 migrations\");\n await Promise.all([\n copyFile(join(root, \"worker.js\"), join(runtimeDirectory, \"worker.js\")),\n copyFile(join(root, \"worker.js.map\"), join(runtimeDirectory, \"worker.js.map\")),\n ...migrationFiles.map((file) =>\n copyFile(join(sourceMigrations, file), join(migrationsDirectory, file)),\n ),\n ]);\n await writeFile(join(stateDirectory, \".gitignore\"), \"runtime/\\nmigrations/\\n\", {\n flag: \"wx\",\n }).catch((error: unknown) => {\n if ((error as NodeJS.ErrnoException).code !== \"EEXIST\") throw error;\n });\n}\n\nfunction configArguments(stateFile: string, cwd: string): string[] {\n return [\"--config\", relative(cwd, stateFile)];\n}\n\nasync function recoverD1(\n runner: WranglerRunner,\n databaseName: string,\n configArgs: readonly string[],\n): Promise<D1Binding | null> {\n const result = await runner([\"d1\", \"list\", \"--json\", ...configArgs], { silent: true });\n const entries = JSON.parse(result.stdout) as D1ListEntry[];\n const matches = entries.filter(\n (entry) => entry.name === databaseName && typeof entry.uuid === \"string\",\n );\n if (matches.length > 1) throw new Error(`multiple D1 databases are named ${databaseName}`);\n const match = matches[0];\n return match === undefined\n ? null\n : {\n binding: d1Binding,\n database_name: databaseName,\n database_id: match.uuid as string,\n migrations_dir: \"migrations\",\n };\n}\n\nasync function recoverR2(\n runner: WranglerRunner,\n bucketName: string,\n configArgs: readonly string[],\n): Promise<R2Binding | null> {\n const result = await runner([\"r2\", \"bucket\", \"info\", bucketName, \"--json\", ...configArgs], {\n silent: true,\n allowFailure: true,\n });\n if (result.exitCode === 0) return { binding: r2Binding, bucket_name: bucketName };\n if (/not found|does not exist|10006/i.test(result.stderr)) return null;\n throw new Error(`unable to inspect the ${bucketName} R2 bucket with the current credentials`);\n}\n\nfunction accountsFromWhoami(value: unknown): AccountEntry[] {\n if (typeof value !== \"object\" || value === null)\n throw new Error(\"Wrangler returned invalid account information\");\n const accounts = (value as WhoamiResult).accounts;\n if (!Array.isArray(accounts)) throw new Error(\"Wrangler returned invalid account information\");\n return accounts.flatMap((account) => {\n if (\n typeof account !== \"object\" ||\n account === null ||\n !(\"id\" in account) ||\n typeof account.id !== \"string\"\n ) {\n return [];\n }\n return [\n {\n id: account.id,\n ...(typeof (account as { name?: unknown }).name === \"string\"\n ? { name: (account as { name: string }).name }\n : {}),\n },\n ];\n });\n}\n\nasync function resolveAccountId(\n runner: WranglerRunner,\n configuredAccountId: string | undefined,\n): Promise<string> {\n if (configuredAccountId !== undefined) return configuredAccountId;\n const result = await runner([\"whoami\", \"--json\"], { silent: true });\n const accounts = accountsFromWhoami(JSON.parse(result.stdout) as unknown);\n if (accounts.length !== 1) {\n throw new Error(\"accountId is required when Wrangler credentials can access multiple accounts\");\n }\n const account = accounts[0];\n if (account === undefined)\n throw new Error(\"Wrangler credentials do not provide a Cloudflare account\");\n return account.id;\n}\n\nasync function workerExists(\n runner: WranglerRunner,\n workerName: string,\n configArgs: readonly string[],\n): Promise<boolean> {\n const result = await runner([\"versions\", \"list\", \"--name\", workerName, \"--json\", ...configArgs], {\n silent: true,\n allowFailure: true,\n });\n if (result.exitCode === 0) return true;\n if (/not found|does not exist|10007/i.test(result.stderr)) return false;\n throw new Error(`unable to inspect the ${workerName} Worker with the current credentials`);\n}\n\nasync function verifyWorkerOwnership(\n workerName: string,\n configArgs: readonly string[],\n runner: WranglerRunner,\n adoptExisting: boolean,\n): Promise<boolean> {\n const exists = await workerExists(runner, workerName, configArgs);\n if (exists && !adoptExisting) {\n throw new Error(\n `the ${workerName} Worker already exists; verify it, then rerun with --adopt-existing`,\n );\n }\n return exists;\n}\n\nasync function ensureResources(\n state: WranglerState,\n stateFile: string,\n cwd: string,\n runner: WranglerRunner,\n adoptExisting: boolean,\n): Promise<WranglerState> {\n const d1Name = `${state.name}-metadata`;\n const r2Name = `${state.name}-packages`;\n const configArgs = configArguments(stateFile, cwd);\n const configuredD1 = state.d1_databases.filter((database) => database.binding === d1Binding);\n const configuredR2 = state.r2_buckets.filter((bucket) => bucket.binding === r2Binding);\n const selectedD1 = configuredD1[0];\n const selectedR2 = configuredR2[0];\n if (\n configuredD1.length > 1 ||\n (selectedD1 !== undefined && selectedD1.database_name !== d1Name)\n ) {\n throw new Error(`${d1Binding} must reference the ${d1Name} D1 database`);\n }\n if (configuredR2.length > 1 || (selectedR2 !== undefined && selectedR2.bucket_name !== r2Name)) {\n throw new Error(`${r2Binding} must reference the ${r2Name} R2 bucket`);\n }\n\n if (configuredD1.length === 0) {\n const recovered = await recoverD1(runner, d1Name, configArgs);\n if (recovered !== null) {\n if (!adoptExisting) {\n throw new Error(\n `the ${d1Name} D1 database already exists; verify it, then rerun with --adopt-existing`,\n );\n }\n state.d1_databases.push(recovered);\n await writeState(stateFile, state);\n } else {\n await runner([\n \"d1\",\n \"create\",\n d1Name,\n \"--binding\",\n d1Binding,\n \"--update-config\",\n ...configArgs,\n ]);\n state = JSON.parse(await readFile(stateFile, \"utf8\")) as WranglerState;\n }\n }\n\n if (configuredR2.length === 0) {\n const recovered = await recoverR2(runner, r2Name, configArgs);\n if (recovered !== null) {\n if (!adoptExisting) {\n throw new Error(\n `the ${r2Name} R2 bucket already exists; verify it, then rerun with --adopt-existing`,\n );\n }\n state.r2_buckets.push(recovered);\n await writeState(stateFile, state);\n } else {\n await runner([\n \"r2\",\n \"bucket\",\n \"create\",\n r2Name,\n \"--binding\",\n r2Binding,\n \"--update-config\",\n ...configArgs,\n ]);\n state = JSON.parse(await readFile(stateFile, \"utf8\")) as WranglerState;\n }\n }\n\n state.d1_databases = state.d1_databases.map((database) =>\n database.binding === d1Binding ? { ...database, migrations_dir: \"migrations\" } : database,\n );\n await writeState(stateFile, state);\n return state;\n}\n\nfunction deploymentUrl(output: string, config: NormalizedConfig): string | null {\n if (config.hostname !== undefined) return `https://${config.hostname}`;\n return output.match(/https:\\/\\/[^\\s]+\\.workers\\.dev\\b/)?.[0] ?? null;\n}\n\nexport async function deploy(options: DeployOptions): Promise<DeployResult> {\n const cwd = resolve(options.cwd);\n const config = await loadConfig(cwd, options.configFile);\n const stateDirectory = join(cwd, stateDirectoryName);\n const stateFile = join(stateDirectory, stateFileName);\n const ownershipFile = join(stateDirectory, ownershipFileName);\n await mkdir(stateDirectory, { recursive: true });\n\n const previous = await readState(stateFile, config);\n const runner = options.runner ?? createWranglerRunner(cwd);\n const environmentAccountId = process.env.CLOUDFLARE_ACCOUNT_ID;\n const configuredAccountId = config.accountId ?? previous?.account_id;\n if (\n environmentAccountId !== undefined &&\n configuredAccountId !== undefined &&\n environmentAccountId !== configuredAccountId\n ) {\n throw new Error(\"CLOUDFLARE_ACCOUNT_ID does not match the configured deployment account\");\n }\n const accountId = await resolveAccountId(runner, configuredAccountId ?? environmentAccountId);\n const ownsWorker = await readWorkerOwnership(ownershipFile, config.name, accountId);\n let state = stateFor(config, accountId, previous);\n await writeState(stateFile, state);\n await copyRuntimeFiles(stateDirectory, options.assetsDirectory ?? packageRoot());\n\n state = await ensureResources(state, stateFile, cwd, runner, options.adoptExisting ?? false);\n const configArgs = configArguments(stateFile, cwd);\n await runner([\"d1\", \"migrations\", \"apply\", d1Binding, \"--remote\", ...configArgs]);\n\n const adoptedWorker = ownsWorker\n ? false\n : await verifyWorkerOwnership(state.name, configArgs, runner, options.adoptExisting ?? false);\n if (adoptedWorker) await writeWorkerOwnership(ownershipFile, state.name, accountId);\n\n const deployArguments = [\"deploy\", \"--no-bundle\", ...configArgs];\n if (options.secretsFile !== undefined) {\n deployArguments.push(\"--secrets-file\", options.secretsFile);\n }\n const deployed = await runner(deployArguments);\n if (!ownsWorker && !adoptedWorker)\n await writeWorkerOwnership(ownershipFile, state.name, accountId);\n return {\n registryUrl: deploymentUrl(deployed.stdout, config),\n stateFile,\n secretBindings: config.auth.tokens.map((token) => token.binding),\n scopes: config.scopes,\n };\n}\n","import { access } from \"node:fs/promises\";\nimport { resolve } from \"node:path\";\nimport { pathToFileURL } from \"node:url\";\nimport { createJiti } from \"jiti\";\nimport { normalizeConfig, type NormalizedConfig } from \"../config.js\";\n\nexport const defaultConfigFile = \"pkgflare.config.ts\";\n\nexport async function loadConfig(\n cwd: string,\n configFile = defaultConfigFile,\n): Promise<NormalizedConfig> {\n const path = resolve(cwd, configFile);\n try {\n await access(path);\n } catch {\n throw new Error(`configuration file not found: ${configFile}`);\n }\n\n const jiti = createJiti(pathToFileURL(import.meta.url).href, {\n interopDefault: true,\n moduleCache: false,\n });\n const imported = await jiti.import(path, { default: true });\n return normalizeConfig(imported);\n}\n","export type Permission = \"read\" | \"publish\";\n\nexport interface SecretTokenConfig {\n binding: string;\n permissions: readonly Permission[];\n}\n\nexport interface SecretsAuthConfig {\n provider: \"secrets\";\n tokens: readonly SecretTokenConfig[];\n}\n\nexport interface PkgflareConfig {\n name: string;\n scopes: readonly string[];\n accountId?: string;\n hostname?: string;\n auth: SecretsAuthConfig;\n}\n\nexport interface NormalizedConfig {\n name: string;\n scopes: string[];\n accountId?: string;\n hostname?: string;\n auth: {\n provider: \"secrets\";\n tokens: Array<{\n binding: string;\n permissions: Permission[];\n }>;\n };\n}\n\nconst workerNamePattern = /^[a-z](?:[a-z0-9-]{0,52}[a-z0-9])?$/;\nconst accountIdPattern = /^[a-f0-9]{32}$/;\nconst scopePattern = /^@[a-z0-9](?:[a-z0-9._-]*[a-z0-9])?$/;\nconst bindingPattern = /^[A-Z][A-Z0-9_]*$/;\nconst hostnamePattern =\n /^(?=.{1,253}$)(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\\.)+[a-z](?:[a-z0-9-]{0,61}[a-z0-9])?$/;\nconst reservedBindings = new Set([\"PKGFLARE_DB\", \"PKGFLARE_BUCKET\", \"PKGFLARE_CONFIG\"]);\n\nexport function defineConfig(config: PkgflareConfig): PkgflareConfig {\n return config;\n}\n\nfunction isObject(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nexport function normalizeConfig(value: unknown): NormalizedConfig {\n if (!isObject(value)) throw new Error(\"configuration must be an object\");\n const { name, scopes: scopeValues, accountId, hostname, auth } = value;\n if (typeof name !== \"string\" || !workerNamePattern.test(name)) {\n throw new Error(\"name must be a lowercase Cloudflare resource name of at most 54 characters\");\n }\n\n if (\n accountId !== undefined &&\n (typeof accountId !== \"string\" || !accountIdPattern.test(accountId))\n ) {\n throw new Error(\"accountId must be a 32-character lowercase hexadecimal Cloudflare account ID\");\n }\n\n if (\n !Array.isArray(scopeValues) ||\n scopeValues.length === 0 ||\n scopeValues.some((scope) => typeof scope !== \"string\")\n ) {\n throw new Error(\"at least one package scope is required\");\n }\n\n const scopes = [...new Set(scopeValues as string[])];\n for (const scope of scopes) {\n if (!scopePattern.test(scope)) {\n throw new Error(`invalid package scope: ${scope}`);\n }\n }\n\n if (hostname !== undefined && (typeof hostname !== \"string\" || !hostnamePattern.test(hostname))) {\n throw new Error(\"hostname must be a valid DNS hostname without a scheme or path\");\n }\n\n if (!isObject(auth) || auth.provider !== \"secrets\") {\n throw new Error(\"unsupported authentication provider\");\n }\n\n if (!Array.isArray(auth.tokens) || auth.tokens.length === 0) {\n throw new Error(\"at least one authentication token binding is required\");\n }\n\n const seenBindings = new Set<string>();\n const tokens = auth.tokens.map((tokenValue) => {\n if (!isObject(tokenValue) || typeof tokenValue.binding !== \"string\") {\n throw new Error(\"authentication token binding must be an object with a binding name\");\n }\n const { binding, permissions: permissionValues } = tokenValue;\n if (!bindingPattern.test(binding)) {\n throw new Error(`invalid secret binding: ${binding}`);\n }\n if (reservedBindings.has(binding)) {\n throw new Error(`secret binding is reserved by pkgflare: ${binding}`);\n }\n if (seenBindings.has(binding)) {\n throw new Error(`duplicate secret binding: ${binding}`);\n }\n seenBindings.add(binding);\n\n if (\n !Array.isArray(permissionValues) ||\n permissionValues.length === 0 ||\n permissionValues.some((permission) => permission !== \"read\" && permission !== \"publish\")\n ) {\n throw new Error(`invalid permissions for ${binding}`);\n }\n const permissions = [...new Set(permissionValues)] as Permission[];\n\n return { binding, permissions };\n });\n\n return {\n name,\n scopes,\n ...(accountId === undefined ? {} : { accountId }),\n ...(hostname === undefined ? {} : { hostname }),\n auth: { provider: \"secrets\", tokens },\n };\n}\n","import { spawn } from \"node:child_process\";\nimport { createRequire } from \"node:module\";\nimport { dirname, join } from \"node:path\";\n\nexport interface CommandResult {\n exitCode: number;\n stdout: string;\n stderr: string;\n}\n\nexport type WranglerRunner = (\n arguments_: readonly string[],\n options?: { allowFailure?: boolean; silent?: boolean },\n) => Promise<CommandResult>;\n\nfunction wranglerEntry(): string {\n const require = createRequire(import.meta.url);\n return join(dirname(require.resolve(\"wrangler/package.json\")), \"bin\", \"wrangler.js\");\n}\n\nexport function createWranglerRunner(cwd: string): WranglerRunner {\n return async (arguments_, options = {}) => {\n const result = await new Promise<CommandResult>((resolve, reject) => {\n const child = spawn(process.execPath, [wranglerEntry(), ...arguments_], {\n cwd,\n env: process.env,\n shell: false,\n stdio: [\"inherit\", \"pipe\", \"pipe\"],\n });\n let stdout = \"\";\n let stderr = \"\";\n child.stdout.setEncoding(\"utf8\");\n child.stderr.setEncoding(\"utf8\");\n child.stdout.on(\"data\", (chunk: string) => {\n stdout += chunk;\n if (!options.silent) process.stdout.write(chunk);\n });\n child.stderr.on(\"data\", (chunk: string) => {\n stderr += chunk;\n if (!options.silent) process.stderr.write(chunk);\n });\n child.once(\"error\", reject);\n child.once(\"close\", (code) => resolve({ exitCode: code ?? 1, stdout, stderr }));\n });\n\n if (result.exitCode !== 0 && !options.allowFailure) {\n const operation = arguments_.slice(0, 3).join(\" \");\n throw new Error(\n `Wrangler command ${JSON.stringify(operation)} exited with status ${String(result.exitCode)}`,\n );\n }\n return result;\n };\n}\n"],"mappings":"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","names":["relative","resolve","dirname","join","resolve","require","resolve","dirname","join","resolve","resolve","relative"]}
|
|
1
|
+
{"version":3,"sources":["../src/cli.ts","../src/cli/deploy.ts","../src/cli/config-loader.ts","../src/config.ts","../src/cli/runner.ts","../src/cli/github-oidc.ts"],"sourcesContent":["import { randomBytes } from \"node:crypto\";\nimport { open } from \"node:fs/promises\";\nimport { relative, resolve } from \"node:path\";\nimport { deploy } from \"./cli/deploy.js\";\nimport { requestGithubOidcToken } from \"./cli/github-oidc.js\";\n\nfunction valueAfter(arguments_: readonly string[], flag: string): string | undefined {\n const index = arguments_.indexOf(flag);\n if (index === -1) return undefined;\n const value = arguments_[index + 1];\n if (value === undefined || value.startsWith(\"--\")) throw new Error(`${flag} requires a value`);\n return value;\n}\n\nfunction help(): void {\n process.stdout.write(\n `pkgflare\\n\\nUsage:\\n pkgflare deploy [--config <path>] [--secrets-file <path>] [--adopt-existing]\\n pkgflare auth github --audience <audience>\\n pkgflare init\\n pkgflare token generate\\n`,\n );\n}\n\nasync function init(cwd: string): Promise<void> {\n const path = resolve(cwd, \"pkgflare.config.ts\");\n const file = await open(path, \"wx\").catch((error: unknown) => {\n if ((error as NodeJS.ErrnoException).code === \"EEXIST\")\n throw new Error(\"pkgflare.config.ts already exists\");\n throw error;\n });\n await file.writeFile(\n `import { defineConfig } from \"@ponharu/pkgflare\";\\n\\nexport default defineConfig({\\n name: \"acme-registry\",\\n scopes: [\"@acme\"],\\n auth: {\\n provider: \"secrets\",\\n tokens: [\\n { binding: \"PKGFLARE_READ_TOKEN\", permissions: [\"read\"] },\\n { binding: \"PKGFLARE_PUBLISH_TOKEN\", permissions: [\"publish\"] },\\n ],\\n },\\n});\\n`,\n );\n await file.close();\n process.stdout.write(\"Created pkgflare.config.ts\\n\");\n}\n\nasync function main(arguments_: string[]): Promise<void> {\n const [command, subcommand] = arguments_;\n if (command === undefined || command === \"--help\" || command === \"-h\") {\n help();\n return;\n }\n if (command === \"deploy\") {\n const configFile = valueAfter(arguments_, \"--config\");\n const secretsFile = valueAfter(arguments_, \"--secrets-file\");\n const adoptExisting = arguments_.includes(\"--adopt-existing\");\n const result = await deploy({\n cwd: process.cwd(),\n ...(configFile === undefined ? {} : { configFile }),\n ...(secretsFile === undefined ? {} : { secretsFile }),\n adoptExisting,\n });\n const statePath = relative(process.cwd(), result.stateFile);\n process.stdout.write(`\\nDeployment state: ${statePath}\\n`);\n if (result.registryUrl !== null) {\n process.stdout.write(`Registry: ${result.registryUrl}\\n`);\n }\n process.stdout.write(\"\\nRegister each token secret if it was not supplied during deploy:\\n\");\n for (const binding of result.secretBindings) {\n process.stdout.write(` npx wrangler secret put ${binding} --config ${statePath}\\n`);\n }\n if (result.registryUrl !== null) {\n const host = new URL(result.registryUrl).host;\n process.stdout.write(\"\\n.npmrc:\\n\");\n for (const scope of result.scopes) {\n process.stdout.write(` ${scope}:registry=${result.registryUrl}\\n`);\n }\n process.stdout.write(` //${host}/:_authToken=\\${NPM_TOKEN}\\n`);\n }\n return;\n }\n if (command === \"init\") {\n await init(process.cwd());\n return;\n }\n if (command === \"auth\" && subcommand === \"github\") {\n const token = await requestGithubOidcToken(valueAfter(arguments_, \"--audience\"));\n process.stdout.write(`${token}\\n`);\n return;\n }\n if (command === \"token\" && subcommand === \"generate\") {\n let binary = \"\";\n for (const byte of randomBytes(32)) binary += String.fromCharCode(byte);\n const token = btoa(binary).replace(/\\+/g, \"-\").replace(/\\//g, \"_\").replace(/=+$/, \"\");\n process.stdout.write(`${token}\\n`);\n return;\n }\n throw new Error(`unknown command: ${arguments_.join(\" \")}`);\n}\n\nmain(process.argv.slice(2)).catch((error: unknown) => {\n const message = error instanceof Error ? error.message : String(error);\n process.stderr.write(`pkgflare: ${message}\\n`);\n process.exitCode = 1;\n});\n","import { copyFile, mkdir, readFile, readdir, writeFile } from \"node:fs/promises\";\nimport { dirname, join, relative, resolve } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport type { NormalizedConfig } from \"../config.js\";\nimport { loadConfig } from \"./config-loader.js\";\nimport { createWranglerRunner, type WranglerRunner } from \"./runner.js\";\n\nconst stateDirectoryName = \".pkgflare\";\nconst stateFileName = \"wrangler.json\";\nconst ownershipFileName = \"ownership.json\";\nconst d1Binding = \"PKGFLARE_DB\";\nconst r2Binding = \"PKGFLARE_BUCKET\";\n\ninterface D1Binding {\n binding: string;\n database_name: string;\n database_id: string;\n migrations_dir?: string;\n}\n\ninterface R2Binding {\n binding: string;\n bucket_name: string;\n}\n\ninterface WranglerState {\n $schema: string;\n account_id?: string;\n name: string;\n main: string;\n compatibility_date: string;\n workers_dev: boolean;\n routes?: Array<{ pattern: string; custom_domain: true }>;\n vars: { PKGFLARE_CONFIG: string };\n d1_databases: D1Binding[];\n r2_buckets: R2Binding[];\n}\n\ninterface D1ListEntry {\n name?: unknown;\n uuid?: unknown;\n}\n\ninterface WhoamiResult {\n loggedIn?: unknown;\n accounts?: unknown;\n}\n\ninterface AccountEntry {\n id: string;\n name?: string;\n}\n\ninterface OwnershipState {\n account_id: string;\n worker_name: string;\n}\n\nexport interface DeployOptions {\n cwd: string;\n configFile?: string;\n secretsFile?: string;\n adoptExisting?: boolean;\n runner?: WranglerRunner;\n assetsDirectory?: string;\n}\n\nexport interface DeployResult {\n registryUrl: string | null;\n stateFile: string;\n secretBindings: string[];\n scopes: string[];\n}\n\nfunction packageRoot(): string {\n return dirname(fileURLToPath(import.meta.url));\n}\n\nfunction stateFor(\n config: NormalizedConfig,\n accountId: string,\n previous?: WranglerState,\n): WranglerState {\n if (previous?.account_id !== undefined && previous.account_id !== accountId) {\n throw new Error(\"authenticated Cloudflare account does not match the deployment state\");\n }\n const state: WranglerState = {\n $schema:\n \"https://raw.githubusercontent.com/cloudflare/workers-sdk/main/packages/wrangler/config-schema.json\",\n account_id: accountId,\n name: config.name,\n main: \"runtime/worker.js\",\n compatibility_date: \"2026-08-01\",\n workers_dev: config.hostname === undefined,\n vars: { PKGFLARE_CONFIG: JSON.stringify(config) },\n d1_databases: previous?.d1_databases ?? [],\n r2_buckets: previous?.r2_buckets ?? [],\n };\n if (config.hostname !== undefined) {\n state.routes = [{ pattern: config.hostname, custom_domain: true }];\n }\n return state;\n}\n\nasync function readState(\n path: string,\n config: NormalizedConfig,\n): Promise<WranglerState | undefined> {\n let contents: string;\n try {\n contents = await readFile(path, \"utf8\");\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === \"ENOENT\") return undefined;\n throw error;\n }\n const state = JSON.parse(contents) as WranglerState;\n if (state.name !== config.name) {\n throw new Error(\n `existing deployment state belongs to ${state.name}; remove ${stateDirectoryName} only after verifying the remote resources`,\n );\n }\n return state;\n}\n\nasync function writeState(path: string, state: WranglerState): Promise<void> {\n await writeFile(path, `${JSON.stringify(state, null, 2)}\\n`, \"utf8\");\n}\n\nasync function readWorkerOwnership(\n path: string,\n workerName: string,\n accountId: string,\n): Promise<boolean> {\n let contents: string;\n try {\n contents = await readFile(path, \"utf8\");\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === \"ENOENT\") return false;\n throw error;\n }\n const ownership = JSON.parse(contents) as Partial<OwnershipState>;\n if (ownership.worker_name !== workerName || ownership.account_id !== accountId) {\n throw new Error(\"deployment ownership state does not match the configured Worker and account\");\n }\n return true;\n}\n\nasync function writeWorkerOwnership(\n path: string,\n workerName: string,\n accountId: string,\n): Promise<void> {\n const ownership: OwnershipState = { account_id: accountId, worker_name: workerName };\n await writeFile(path, `${JSON.stringify(ownership, null, 2)}\\n`, \"utf8\");\n}\n\nasync function copyRuntimeFiles(stateDirectory: string, root: string): Promise<void> {\n const runtimeDirectory = join(stateDirectory, \"runtime\");\n const migrationsDirectory = join(stateDirectory, \"migrations\");\n await Promise.all([\n mkdir(runtimeDirectory, { recursive: true }),\n mkdir(migrationsDirectory, { recursive: true }),\n ]);\n const sourceMigrations = resolve(root, \"..\", \"migrations\");\n const migrationFiles = (await readdir(sourceMigrations, { withFileTypes: true }))\n .filter((entry) => entry.isFile() && entry.name.endsWith(\".sql\"))\n .map((entry) => entry.name);\n // oxlint-disable-next-line unicorn/no-array-sort -- this array has just been created locally\n migrationFiles.sort();\n if (migrationFiles.length === 0) throw new Error(\"pkgflare package contains no D1 migrations\");\n await Promise.all([\n copyFile(join(root, \"worker.js\"), join(runtimeDirectory, \"worker.js\")),\n copyFile(join(root, \"worker.js.map\"), join(runtimeDirectory, \"worker.js.map\")),\n ...migrationFiles.map((file) =>\n copyFile(join(sourceMigrations, file), join(migrationsDirectory, file)),\n ),\n ]);\n await writeFile(join(stateDirectory, \".gitignore\"), \"runtime/\\nmigrations/\\n\", {\n flag: \"wx\",\n }).catch((error: unknown) => {\n if ((error as NodeJS.ErrnoException).code !== \"EEXIST\") throw error;\n });\n}\n\nfunction configArguments(stateFile: string, cwd: string): string[] {\n return [\"--config\", relative(cwd, stateFile)];\n}\n\nasync function recoverD1(\n runner: WranglerRunner,\n databaseName: string,\n configArgs: readonly string[],\n): Promise<D1Binding | null> {\n const result = await runner([\"d1\", \"list\", \"--json\", ...configArgs], { silent: true });\n const entries = JSON.parse(result.stdout) as D1ListEntry[];\n const matches = entries.filter(\n (entry) => entry.name === databaseName && typeof entry.uuid === \"string\",\n );\n if (matches.length > 1) throw new Error(`multiple D1 databases are named ${databaseName}`);\n const match = matches[0];\n return match === undefined\n ? null\n : {\n binding: d1Binding,\n database_name: databaseName,\n database_id: match.uuid as string,\n migrations_dir: \"migrations\",\n };\n}\n\nasync function recoverR2(\n runner: WranglerRunner,\n bucketName: string,\n configArgs: readonly string[],\n): Promise<R2Binding | null> {\n const result = await runner([\"r2\", \"bucket\", \"info\", bucketName, \"--json\", ...configArgs], {\n silent: true,\n allowFailure: true,\n });\n if (result.exitCode === 0) return { binding: r2Binding, bucket_name: bucketName };\n if (/not found|does not exist|10006/i.test(result.stderr)) return null;\n throw new Error(`unable to inspect the ${bucketName} R2 bucket with the current credentials`);\n}\n\nfunction accountsFromWhoami(value: unknown): AccountEntry[] {\n if (typeof value !== \"object\" || value === null)\n throw new Error(\"Wrangler returned invalid account information\");\n const accounts = (value as WhoamiResult).accounts;\n if (!Array.isArray(accounts)) throw new Error(\"Wrangler returned invalid account information\");\n return accounts.flatMap((account) => {\n if (\n typeof account !== \"object\" ||\n account === null ||\n !(\"id\" in account) ||\n typeof account.id !== \"string\"\n ) {\n return [];\n }\n return [\n {\n id: account.id,\n ...(typeof (account as { name?: unknown }).name === \"string\"\n ? { name: (account as { name: string }).name }\n : {}),\n },\n ];\n });\n}\n\nasync function resolveAccountId(\n runner: WranglerRunner,\n configuredAccountId: string | undefined,\n): Promise<string> {\n if (configuredAccountId !== undefined) return configuredAccountId;\n const result = await runner([\"whoami\", \"--json\"], { silent: true });\n const accounts = accountsFromWhoami(JSON.parse(result.stdout) as unknown);\n if (accounts.length !== 1) {\n throw new Error(\"accountId is required when Wrangler credentials can access multiple accounts\");\n }\n const account = accounts[0];\n if (account === undefined)\n throw new Error(\"Wrangler credentials do not provide a Cloudflare account\");\n return account.id;\n}\n\nasync function workerExists(\n runner: WranglerRunner,\n workerName: string,\n configArgs: readonly string[],\n): Promise<boolean> {\n const result = await runner([\"versions\", \"list\", \"--name\", workerName, \"--json\", ...configArgs], {\n silent: true,\n allowFailure: true,\n });\n if (result.exitCode === 0) return true;\n if (/not found|does not exist|10007/i.test(result.stderr)) return false;\n throw new Error(`unable to inspect the ${workerName} Worker with the current credentials`);\n}\n\nasync function verifyWorkerOwnership(\n workerName: string,\n configArgs: readonly string[],\n runner: WranglerRunner,\n adoptExisting: boolean,\n): Promise<boolean> {\n const exists = await workerExists(runner, workerName, configArgs);\n if (exists && !adoptExisting) {\n throw new Error(\n `the ${workerName} Worker already exists; verify it, then rerun with --adopt-existing`,\n );\n }\n return exists;\n}\n\nasync function ensureResources(\n state: WranglerState,\n stateFile: string,\n cwd: string,\n runner: WranglerRunner,\n adoptExisting: boolean,\n): Promise<WranglerState> {\n const d1Name = `${state.name}-metadata`;\n const r2Name = `${state.name}-packages`;\n const configArgs = configArguments(stateFile, cwd);\n const configuredD1 = state.d1_databases.filter((database) => database.binding === d1Binding);\n const configuredR2 = state.r2_buckets.filter((bucket) => bucket.binding === r2Binding);\n const selectedD1 = configuredD1[0];\n const selectedR2 = configuredR2[0];\n if (\n configuredD1.length > 1 ||\n (selectedD1 !== undefined && selectedD1.database_name !== d1Name)\n ) {\n throw new Error(`${d1Binding} must reference the ${d1Name} D1 database`);\n }\n if (configuredR2.length > 1 || (selectedR2 !== undefined && selectedR2.bucket_name !== r2Name)) {\n throw new Error(`${r2Binding} must reference the ${r2Name} R2 bucket`);\n }\n\n if (configuredD1.length === 0) {\n const recovered = await recoverD1(runner, d1Name, configArgs);\n if (recovered !== null) {\n if (!adoptExisting) {\n throw new Error(\n `the ${d1Name} D1 database already exists; verify it, then rerun with --adopt-existing`,\n );\n }\n state.d1_databases.push(recovered);\n await writeState(stateFile, state);\n } else {\n await runner([\n \"d1\",\n \"create\",\n d1Name,\n \"--binding\",\n d1Binding,\n \"--update-config\",\n ...configArgs,\n ]);\n state = JSON.parse(await readFile(stateFile, \"utf8\")) as WranglerState;\n }\n }\n\n if (configuredR2.length === 0) {\n const recovered = await recoverR2(runner, r2Name, configArgs);\n if (recovered !== null) {\n if (!adoptExisting) {\n throw new Error(\n `the ${r2Name} R2 bucket already exists; verify it, then rerun with --adopt-existing`,\n );\n }\n state.r2_buckets.push(recovered);\n await writeState(stateFile, state);\n } else {\n await runner([\n \"r2\",\n \"bucket\",\n \"create\",\n r2Name,\n \"--binding\",\n r2Binding,\n \"--update-config\",\n ...configArgs,\n ]);\n state = JSON.parse(await readFile(stateFile, \"utf8\")) as WranglerState;\n }\n }\n\n state.d1_databases = state.d1_databases.map((database) =>\n database.binding === d1Binding ? { ...database, migrations_dir: \"migrations\" } : database,\n );\n await writeState(stateFile, state);\n return state;\n}\n\nfunction deploymentUrl(output: string, config: NormalizedConfig): string | null {\n if (config.hostname !== undefined) return `https://${config.hostname}`;\n return output.match(/https:\\/\\/[^\\s]+\\.workers\\.dev\\b/)?.[0] ?? null;\n}\n\nexport async function deploy(options: DeployOptions): Promise<DeployResult> {\n const cwd = resolve(options.cwd);\n const config = await loadConfig(cwd, options.configFile);\n const stateDirectory = join(cwd, stateDirectoryName);\n const stateFile = join(stateDirectory, stateFileName);\n const ownershipFile = join(stateDirectory, ownershipFileName);\n await mkdir(stateDirectory, { recursive: true });\n\n const previous = await readState(stateFile, config);\n const runner = options.runner ?? createWranglerRunner(cwd);\n const environmentAccountId = process.env.CLOUDFLARE_ACCOUNT_ID;\n const configuredAccountId = config.accountId ?? previous?.account_id;\n if (\n environmentAccountId !== undefined &&\n configuredAccountId !== undefined &&\n environmentAccountId !== configuredAccountId\n ) {\n throw new Error(\"CLOUDFLARE_ACCOUNT_ID does not match the configured deployment account\");\n }\n const accountId = await resolveAccountId(runner, configuredAccountId ?? environmentAccountId);\n const ownsWorker = await readWorkerOwnership(ownershipFile, config.name, accountId);\n let state = stateFor(config, accountId, previous);\n await writeState(stateFile, state);\n await copyRuntimeFiles(stateDirectory, options.assetsDirectory ?? packageRoot());\n\n state = await ensureResources(state, stateFile, cwd, runner, options.adoptExisting ?? false);\n const configArgs = configArguments(stateFile, cwd);\n await runner([\"d1\", \"migrations\", \"apply\", d1Binding, \"--remote\", ...configArgs]);\n\n const adoptedWorker = ownsWorker\n ? false\n : await verifyWorkerOwnership(state.name, configArgs, runner, options.adoptExisting ?? false);\n if (adoptedWorker) await writeWorkerOwnership(ownershipFile, state.name, accountId);\n\n const deployArguments = [\"deploy\", \"--no-bundle\", ...configArgs];\n if (options.secretsFile !== undefined) {\n deployArguments.push(\"--secrets-file\", options.secretsFile);\n }\n const deployed = await runner(deployArguments);\n if (!ownsWorker && !adoptedWorker)\n await writeWorkerOwnership(ownershipFile, state.name, accountId);\n return {\n registryUrl: deploymentUrl(deployed.stdout, config),\n stateFile,\n secretBindings: config.auth.tokens.map((token) => token.binding),\n scopes: config.scopes,\n };\n}\n","import { access } from \"node:fs/promises\";\nimport { resolve } from \"node:path\";\nimport { pathToFileURL } from \"node:url\";\nimport { createJiti } from \"jiti\";\nimport { normalizeConfig, type NormalizedConfig } from \"../config.js\";\n\nexport const defaultConfigFile = \"pkgflare.config.ts\";\n\nexport async function loadConfig(\n cwd: string,\n configFile = defaultConfigFile,\n): Promise<NormalizedConfig> {\n const path = resolve(cwd, configFile);\n try {\n await access(path);\n } catch {\n throw new Error(`configuration file not found: ${configFile}`);\n }\n\n const jiti = createJiti(pathToFileURL(import.meta.url).href, {\n interopDefault: true,\n moduleCache: false,\n });\n const imported = await jiti.import(path, { default: true });\n return normalizeConfig(imported);\n}\n","export type Permission = \"read\" | \"publish\";\n\nexport interface SecretTokenConfig {\n binding: string;\n permissions: readonly Permission[];\n}\n\nexport interface GitHubOidcSubjectConfig {\n repositoryId: string;\n repositoryOwnerId: string;\n ref: string;\n workflowRef: string;\n jobWorkflowRef?: string;\n permissions: readonly Permission[];\n packages: readonly string[];\n}\n\nexport interface GitHubOidcConfig {\n audience: string;\n subjects: readonly GitHubOidcSubjectConfig[];\n}\n\nexport interface SecretsAuthConfig {\n provider: \"secrets\";\n tokens?: readonly SecretTokenConfig[];\n githubOidc?: GitHubOidcConfig;\n}\n\nexport interface PkgflareConfig {\n name: string;\n scopes: readonly string[];\n accountId?: string;\n hostname?: string;\n auth: SecretsAuthConfig;\n}\n\nexport interface NormalizedConfig {\n name: string;\n scopes: string[];\n accountId?: string;\n hostname?: string;\n auth: {\n provider: \"secrets\";\n tokens: Array<{\n binding: string;\n permissions: Permission[];\n }>;\n githubOidc?: {\n audience: string;\n subjects: Array<{\n repositoryId: string;\n repositoryOwnerId: string;\n ref: string;\n workflowRef: string;\n jobWorkflowRef?: string;\n permissions: Permission[];\n packages: string[];\n }>;\n };\n };\n}\n\nconst workerNamePattern = /^[a-z](?:[a-z0-9-]{0,52}[a-z0-9])?$/;\nconst accountIdPattern = /^[a-f0-9]{32}$/;\nconst scopePattern = /^@[a-z0-9](?:[a-z0-9._-]*[a-z0-9])?$/;\nconst bindingPattern = /^[A-Z][A-Z0-9_]*$/;\nconst hostnamePattern =\n /^(?=.{1,253}$)(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\\.)+[a-z](?:[a-z0-9-]{0,61}[a-z0-9])?$/;\nconst reservedBindings = new Set([\"PKGFLARE_DB\", \"PKGFLARE_BUCKET\", \"PKGFLARE_CONFIG\"]);\nconst githubIdPattern = /^[1-9][0-9]{0,19}$/;\nconst audiencePattern = /^[\\x21-\\x7e]{1,256}$/;\nconst refPattern = /^refs\\/(?:heads|tags)\\/[A-Za-z0-9._/-]+\\*?$/;\nconst workflowRefPattern =\n /^[A-Za-z0-9_.-]+\\/[A-Za-z0-9_.-]+\\/\\.github\\/workflows\\/[A-Za-z0-9_.-]+\\.ya?ml@refs\\/(?:heads|tags)\\/[A-Za-z0-9._/-]+\\*?$/;\nconst jobWorkflowRefPattern =\n /^[A-Za-z0-9_.-]+\\/[A-Za-z0-9_.-]+\\/\\.github\\/workflows\\/[A-Za-z0-9_.-]+\\.ya?ml@(?:refs\\/(?:heads|tags)\\/[A-Za-z0-9._/-]+\\*?|[0-9a-f]{40})$/;\nconst packageSegmentPattern = /^(?!\\.)(?:[a-z0-9._-]+)$/;\nconst maximumGithubSubjects = 128;\nconst maximumPackagesPerSubject = 128;\nconst maximumRuntimeConfigBytes = 5 * 1024;\n\nexport function defineConfig(config: PkgflareConfig): PkgflareConfig {\n return config;\n}\n\nfunction isObject(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction normalizePermissions(value: unknown, label: string): Permission[] {\n if (\n !Array.isArray(value) ||\n value.length === 0 ||\n value.some((permission) => permission !== \"read\" && permission !== \"publish\")\n ) {\n throw new Error(`invalid permissions for ${label}`);\n }\n return [...new Set(value)] as Permission[];\n}\n\nfunction isSafePattern(value: string, pattern: RegExp): boolean {\n if (!pattern.test(value)) return false;\n const wildcard = value.indexOf(\"*\");\n return wildcard === -1 || wildcard === value.length - 1;\n}\n\nfunction normalizeGithubOidc(\n value: unknown,\n configuredScopes: readonly string[],\n): NormalizedConfig[\"auth\"][\"githubOidc\"] {\n if (!isObject(value) || typeof value.audience !== \"string\") {\n throw new Error(\"githubOidc must define an audience and trusted subjects\");\n }\n if (!audiencePattern.test(value.audience)) {\n throw new Error(\"githubOidc audience must be 1-256 printable ASCII characters\");\n }\n if (\n !Array.isArray(value.subjects) ||\n value.subjects.length === 0 ||\n value.subjects.length > maximumGithubSubjects\n ) {\n throw new Error(`githubOidc must define 1-${String(maximumGithubSubjects)} subjects`);\n }\n\n const subjects = value.subjects.map((subjectValue, index) => {\n const label = `githubOidc subject ${String(index + 1)}`;\n if (!isObject(subjectValue)) throw new Error(`${label} must be an object`);\n const { repositoryId, repositoryOwnerId, ref, workflowRef, jobWorkflowRef } = subjectValue;\n if (typeof repositoryId !== \"string\" || !githubIdPattern.test(repositoryId)) {\n throw new Error(`${label} repositoryId must be a decimal GitHub repository ID`);\n }\n if (typeof repositoryOwnerId !== \"string\" || !githubIdPattern.test(repositoryOwnerId)) {\n throw new Error(`${label} repositoryOwnerId must be a decimal GitHub owner ID`);\n }\n if (typeof ref !== \"string\" || !isSafePattern(ref, refPattern)) {\n throw new Error(`${label} ref must be an exact branch/tag ref or trailing-wildcard pattern`);\n }\n if (typeof workflowRef !== \"string\" || !isSafePattern(workflowRef, workflowRefPattern)) {\n throw new Error(\n `${label} workflowRef must identify a workflow file at an exact or trailing-wildcard ref`,\n );\n }\n if (\n jobWorkflowRef !== undefined &&\n (typeof jobWorkflowRef !== \"string\" || !isSafePattern(jobWorkflowRef, jobWorkflowRefPattern))\n ) {\n throw new Error(\n `${label} jobWorkflowRef must identify a reusable workflow at a full commit SHA or an exact/trailing-wildcard branch or tag ref`,\n );\n }\n const permissions = normalizePermissions(subjectValue.permissions, label);\n if (\n !Array.isArray(subjectValue.packages) ||\n subjectValue.packages.length === 0 ||\n subjectValue.packages.length > maximumPackagesPerSubject ||\n subjectValue.packages.some((packageName) => typeof packageName !== \"string\")\n ) {\n throw new Error(\n `${label} must define 1-${String(maximumPackagesPerSubject)} package patterns`,\n );\n }\n const packages = [...new Set(subjectValue.packages as string[])];\n for (const packagePattern of packages) {\n const slash = packagePattern.indexOf(\"/\");\n const scope = packagePattern.slice(0, slash);\n const packageSegment = packagePattern.slice(slash + 1);\n if (\n slash === -1 ||\n packagePattern.length > 214 ||\n !configuredScopes.includes(scope) ||\n (packageSegment !== \"*\" && !packageSegmentPattern.test(packageSegment))\n ) {\n throw new Error(`${label} contains an invalid or unconfigured package pattern`);\n }\n }\n return {\n repositoryId,\n repositoryOwnerId,\n ref,\n workflowRef,\n ...(jobWorkflowRef === undefined ? {} : { jobWorkflowRef }),\n permissions,\n packages,\n };\n });\n return { audience: value.audience, subjects };\n}\n\nexport function normalizeConfig(value: unknown): NormalizedConfig {\n if (!isObject(value)) throw new Error(\"configuration must be an object\");\n const { name, scopes: scopeValues, accountId, hostname, auth } = value;\n if (typeof name !== \"string\" || !workerNamePattern.test(name)) {\n throw new Error(\"name must be a lowercase Cloudflare resource name of at most 54 characters\");\n }\n\n if (\n accountId !== undefined &&\n (typeof accountId !== \"string\" || !accountIdPattern.test(accountId))\n ) {\n throw new Error(\"accountId must be a 32-character lowercase hexadecimal Cloudflare account ID\");\n }\n\n if (\n !Array.isArray(scopeValues) ||\n scopeValues.length === 0 ||\n scopeValues.some((scope) => typeof scope !== \"string\")\n ) {\n throw new Error(\"at least one package scope is required\");\n }\n\n const scopes = [...new Set(scopeValues as string[])];\n for (const scope of scopes) {\n if (!scopePattern.test(scope)) {\n throw new Error(`invalid package scope: ${scope}`);\n }\n }\n\n if (hostname !== undefined && (typeof hostname !== \"string\" || !hostnamePattern.test(hostname))) {\n throw new Error(\"hostname must be a valid DNS hostname without a scheme or path\");\n }\n\n if (!isObject(auth) || auth.provider !== \"secrets\") {\n throw new Error(\"unsupported authentication provider\");\n }\n\n const tokenValues = auth.tokens ?? [];\n if (!Array.isArray(tokenValues)) {\n throw new Error(\"authentication token bindings must be an array\");\n }\n\n const seenBindings = new Set<string>();\n const tokens = tokenValues.map((tokenValue) => {\n if (!isObject(tokenValue) || typeof tokenValue.binding !== \"string\") {\n throw new Error(\"authentication token binding must be an object with a binding name\");\n }\n const { binding, permissions: permissionValues } = tokenValue;\n if (!bindingPattern.test(binding)) {\n throw new Error(`invalid secret binding: ${binding}`);\n }\n if (reservedBindings.has(binding)) {\n throw new Error(`secret binding is reserved by pkgflare: ${binding}`);\n }\n if (seenBindings.has(binding)) {\n throw new Error(`duplicate secret binding: ${binding}`);\n }\n seenBindings.add(binding);\n\n const permissions = normalizePermissions(permissionValues, binding);\n\n return { binding, permissions };\n });\n\n const githubOidc =\n auth.githubOidc === undefined ? undefined : normalizeGithubOidc(auth.githubOidc, scopes);\n if (tokens.length === 0 && githubOidc === undefined) {\n throw new Error(\"at least one authentication method is required\");\n }\n\n const normalized: NormalizedConfig = {\n name,\n scopes,\n ...(accountId === undefined ? {} : { accountId }),\n ...(hostname === undefined ? {} : { hostname }),\n auth: {\n provider: \"secrets\",\n tokens,\n ...(githubOidc === undefined ? {} : { githubOidc }),\n },\n };\n if (new TextEncoder().encode(JSON.stringify(normalized)).byteLength > maximumRuntimeConfigBytes) {\n throw new Error(\"normalized configuration exceeds the 5 KiB Worker variable limit\");\n }\n return normalized;\n}\n","import { spawn } from \"node:child_process\";\nimport { createRequire } from \"node:module\";\nimport { dirname, join } from \"node:path\";\n\nexport interface CommandResult {\n exitCode: number;\n stdout: string;\n stderr: string;\n}\n\nexport type WranglerRunner = (\n arguments_: readonly string[],\n options?: { allowFailure?: boolean; silent?: boolean },\n) => Promise<CommandResult>;\n\nfunction wranglerEntry(): string {\n const require = createRequire(import.meta.url);\n return join(dirname(require.resolve(\"wrangler/package.json\")), \"bin\", \"wrangler.js\");\n}\n\nexport function createWranglerRunner(cwd: string): WranglerRunner {\n return async (arguments_, options = {}) => {\n const result = await new Promise<CommandResult>((resolve, reject) => {\n const child = spawn(process.execPath, [wranglerEntry(), ...arguments_], {\n cwd,\n env: process.env,\n shell: false,\n stdio: [\"inherit\", \"pipe\", \"pipe\"],\n });\n let stdout = \"\";\n let stderr = \"\";\n child.stdout.setEncoding(\"utf8\");\n child.stderr.setEncoding(\"utf8\");\n child.stdout.on(\"data\", (chunk: string) => {\n stdout += chunk;\n if (!options.silent) process.stdout.write(chunk);\n });\n child.stderr.on(\"data\", (chunk: string) => {\n stderr += chunk;\n if (!options.silent) process.stderr.write(chunk);\n });\n child.once(\"error\", reject);\n child.once(\"close\", (code) => resolve({ exitCode: code ?? 1, stdout, stderr }));\n });\n\n if (result.exitCode !== 0 && !options.allowFailure) {\n const operation = arguments_.slice(0, 3).join(\" \");\n throw new Error(\n `Wrangler command ${JSON.stringify(operation)} exited with status ${String(result.exitCode)}`,\n );\n }\n return result;\n };\n}\n","async function readGithubTokenResponse(response: Response): Promise<string> {\n const maximumBytes = 32 * 1024;\n if (response.body === null) throw new Error(\"GitHub OIDC token response is empty\");\n const reader = response.body.getReader();\n const decoder = new TextDecoder(\"utf-8\", { fatal: true });\n let size = 0;\n let contents = \"\";\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n size += value.byteLength;\n if (size > maximumBytes) {\n await reader.cancel();\n throw new Error(\"GitHub OIDC token response is too large\");\n }\n contents += decoder.decode(value, { stream: true });\n }\n contents += decoder.decode();\n } finally {\n reader.releaseLock();\n }\n\n let value: unknown;\n try {\n value = JSON.parse(contents) as unknown;\n } catch {\n throw new Error(\"GitHub OIDC token response is invalid\");\n }\n if (\n typeof value !== \"object\" ||\n value === null ||\n !(\"value\" in value) ||\n typeof value.value !== \"string\" ||\n value.value.length > 16 * 1024 ||\n !/^[^.]+\\.[^.]+\\.[^.]+$/.test(value.value)\n ) {\n throw new Error(\"GitHub OIDC token response is invalid\");\n }\n return value.value;\n}\n\nexport async function requestGithubOidcToken(\n audience: string | undefined,\n environment: NodeJS.ProcessEnv = process.env,\n): Promise<string> {\n if (audience === undefined) throw new Error(\"--audience is required\");\n if (!/^[\\x21-\\x7e]{1,256}$/.test(audience)) {\n throw new Error(\"--audience must be 1-256 printable ASCII characters\");\n }\n const requestUrlValue = environment.ACTIONS_ID_TOKEN_REQUEST_URL;\n const requestToken = environment.ACTIONS_ID_TOKEN_REQUEST_TOKEN;\n if (requestUrlValue === undefined || requestToken === undefined || requestToken.length === 0) {\n throw new Error(\"GitHub Actions OIDC environment is unavailable\");\n }\n\n let requestUrl: URL;\n try {\n requestUrl = new URL(requestUrlValue);\n } catch {\n throw new Error(\"GitHub Actions OIDC request URL is invalid\");\n }\n if (\n requestUrl.protocol !== \"https:\" ||\n (requestUrl.hostname !== \"token.actions.githubusercontent.com\" &&\n !requestUrl.hostname.endsWith(\".actions.githubusercontent.com\")) ||\n requestUrl.username !== \"\" ||\n requestUrl.password !== \"\"\n ) {\n throw new Error(\"GitHub Actions OIDC request URL is not trusted\");\n }\n requestUrl.searchParams.set(\"audience\", audience);\n\n let response: Response;\n try {\n response = await fetch(requestUrl, {\n headers: { authorization: `bearer ${requestToken}` },\n redirect: \"error\",\n signal: AbortSignal.timeout(5000),\n });\n } catch {\n throw new Error(\"GitHub Actions OIDC token request failed\");\n }\n if (!response.ok) throw new Error(\"GitHub Actions OIDC token request failed\");\n return readGithubTokenResponse(response);\n}\n"],"mappings":"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","names":["relative","resolve","dirname","join","resolve","require","resolve","dirname","join","resolve","value","resolve","relative"]}
|
package/dist/index.d.ts
CHANGED
|
@@ -3,9 +3,23 @@ interface SecretTokenConfig {
|
|
|
3
3
|
binding: string;
|
|
4
4
|
permissions: readonly Permission[];
|
|
5
5
|
}
|
|
6
|
+
interface GitHubOidcSubjectConfig {
|
|
7
|
+
repositoryId: string;
|
|
8
|
+
repositoryOwnerId: string;
|
|
9
|
+
ref: string;
|
|
10
|
+
workflowRef: string;
|
|
11
|
+
jobWorkflowRef?: string;
|
|
12
|
+
permissions: readonly Permission[];
|
|
13
|
+
packages: readonly string[];
|
|
14
|
+
}
|
|
15
|
+
interface GitHubOidcConfig {
|
|
16
|
+
audience: string;
|
|
17
|
+
subjects: readonly GitHubOidcSubjectConfig[];
|
|
18
|
+
}
|
|
6
19
|
interface SecretsAuthConfig {
|
|
7
20
|
provider: "secrets";
|
|
8
|
-
tokens
|
|
21
|
+
tokens?: readonly SecretTokenConfig[];
|
|
22
|
+
githubOidc?: GitHubOidcConfig;
|
|
9
23
|
}
|
|
10
24
|
interface PkgflareConfig {
|
|
11
25
|
name: string;
|
|
@@ -16,4 +30,4 @@ interface PkgflareConfig {
|
|
|
16
30
|
}
|
|
17
31
|
declare function defineConfig(config: PkgflareConfig): PkgflareConfig;
|
|
18
32
|
|
|
19
|
-
export { type Permission, type PkgflareConfig, type SecretTokenConfig, type SecretsAuthConfig, defineConfig };
|
|
33
|
+
export { type GitHubOidcConfig, type GitHubOidcSubjectConfig, type Permission, type PkgflareConfig, type SecretTokenConfig, type SecretsAuthConfig, defineConfig };
|
package/dist/index.js
CHANGED
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/config.ts"],"sourcesContent":["export type Permission = \"read\" | \"publish\";\n\nexport interface SecretTokenConfig {\n binding: string;\n permissions: readonly Permission[];\n}\n\nexport interface SecretsAuthConfig {\n provider: \"secrets\";\n tokens: readonly SecretTokenConfig[];\n}\n\nexport interface PkgflareConfig {\n name: string;\n scopes: readonly string[];\n accountId?: string;\n hostname?: string;\n auth: SecretsAuthConfig;\n}\n\nexport interface NormalizedConfig {\n name: string;\n scopes: string[];\n accountId?: string;\n hostname?: string;\n auth: {\n provider: \"secrets\";\n tokens: Array<{\n binding: string;\n permissions: Permission[];\n }>;\n };\n}\n\nconst workerNamePattern = /^[a-z](?:[a-z0-9-]{0,52}[a-z0-9])?$/;\nconst accountIdPattern = /^[a-f0-9]{32}$/;\nconst scopePattern = /^@[a-z0-9](?:[a-z0-9._-]*[a-z0-9])?$/;\nconst bindingPattern = /^[A-Z][A-Z0-9_]*$/;\nconst hostnamePattern =\n /^(?=.{1,253}$)(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\\.)+[a-z](?:[a-z0-9-]{0,61}[a-z0-9])?$/;\nconst reservedBindings = new Set([\"PKGFLARE_DB\", \"PKGFLARE_BUCKET\", \"PKGFLARE_CONFIG\"]);\n\nexport function defineConfig(config: PkgflareConfig): PkgflareConfig {\n return config;\n}\n\nfunction isObject(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nexport function normalizeConfig(value: unknown): NormalizedConfig {\n if (!isObject(value)) throw new Error(\"configuration must be an object\");\n const { name, scopes: scopeValues, accountId, hostname, auth } = value;\n if (typeof name !== \"string\" || !workerNamePattern.test(name)) {\n throw new Error(\"name must be a lowercase Cloudflare resource name of at most 54 characters\");\n }\n\n if (\n accountId !== undefined &&\n (typeof accountId !== \"string\" || !accountIdPattern.test(accountId))\n ) {\n throw new Error(\"accountId must be a 32-character lowercase hexadecimal Cloudflare account ID\");\n }\n\n if (\n !Array.isArray(scopeValues) ||\n scopeValues.length === 0 ||\n scopeValues.some((scope) => typeof scope !== \"string\")\n ) {\n throw new Error(\"at least one package scope is required\");\n }\n\n const scopes = [...new Set(scopeValues as string[])];\n for (const scope of scopes) {\n if (!scopePattern.test(scope)) {\n throw new Error(`invalid package scope: ${scope}`);\n }\n }\n\n if (hostname !== undefined && (typeof hostname !== \"string\" || !hostnamePattern.test(hostname))) {\n throw new Error(\"hostname must be a valid DNS hostname without a scheme or path\");\n }\n\n if (!isObject(auth) || auth.provider !== \"secrets\") {\n throw new Error(\"unsupported authentication provider\");\n }\n\n if (!Array.isArray(auth.tokens) || auth.tokens.length === 0) {\n throw new Error(\"at least one authentication token binding is required\");\n }\n\n const seenBindings = new Set<string>();\n const tokens = auth.tokens.map((tokenValue) => {\n if (!isObject(tokenValue) || typeof tokenValue.binding !== \"string\") {\n throw new Error(\"authentication token binding must be an object with a binding name\");\n }\n const { binding, permissions: permissionValues } = tokenValue;\n if (!bindingPattern.test(binding)) {\n throw new Error(`invalid secret binding: ${binding}`);\n }\n if (reservedBindings.has(binding)) {\n throw new Error(`secret binding is reserved by pkgflare: ${binding}`);\n }\n if (seenBindings.has(binding)) {\n throw new Error(`duplicate secret binding: ${binding}`);\n }\n seenBindings.add(binding);\n\n if (\n !Array.isArray(permissionValues) ||\n permissionValues.length === 0 ||\n permissionValues.some((permission) => permission !== \"read\" && permission !== \"publish\")\n ) {\n throw new Error(`invalid permissions for ${binding}`);\n }\n const permissions = [...new Set(permissionValues)] as Permission[];\n\n return { binding, permissions };\n });\n\n return {\n name,\n scopes,\n ...(accountId === undefined ? {} : { accountId }),\n ...(hostname === undefined ? {} : { hostname }),\n auth: { provider: \"secrets\", tokens },\n };\n}\n"],"mappings":";AA0CO,SAAS,aAAa,QAAwC;AACnE,SAAO;AACT;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/config.ts"],"sourcesContent":["export type Permission = \"read\" | \"publish\";\n\nexport interface SecretTokenConfig {\n binding: string;\n permissions: readonly Permission[];\n}\n\nexport interface GitHubOidcSubjectConfig {\n repositoryId: string;\n repositoryOwnerId: string;\n ref: string;\n workflowRef: string;\n jobWorkflowRef?: string;\n permissions: readonly Permission[];\n packages: readonly string[];\n}\n\nexport interface GitHubOidcConfig {\n audience: string;\n subjects: readonly GitHubOidcSubjectConfig[];\n}\n\nexport interface SecretsAuthConfig {\n provider: \"secrets\";\n tokens?: readonly SecretTokenConfig[];\n githubOidc?: GitHubOidcConfig;\n}\n\nexport interface PkgflareConfig {\n name: string;\n scopes: readonly string[];\n accountId?: string;\n hostname?: string;\n auth: SecretsAuthConfig;\n}\n\nexport interface NormalizedConfig {\n name: string;\n scopes: string[];\n accountId?: string;\n hostname?: string;\n auth: {\n provider: \"secrets\";\n tokens: Array<{\n binding: string;\n permissions: Permission[];\n }>;\n githubOidc?: {\n audience: string;\n subjects: Array<{\n repositoryId: string;\n repositoryOwnerId: string;\n ref: string;\n workflowRef: string;\n jobWorkflowRef?: string;\n permissions: Permission[];\n packages: string[];\n }>;\n };\n };\n}\n\nconst workerNamePattern = /^[a-z](?:[a-z0-9-]{0,52}[a-z0-9])?$/;\nconst accountIdPattern = /^[a-f0-9]{32}$/;\nconst scopePattern = /^@[a-z0-9](?:[a-z0-9._-]*[a-z0-9])?$/;\nconst bindingPattern = /^[A-Z][A-Z0-9_]*$/;\nconst hostnamePattern =\n /^(?=.{1,253}$)(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\\.)+[a-z](?:[a-z0-9-]{0,61}[a-z0-9])?$/;\nconst reservedBindings = new Set([\"PKGFLARE_DB\", \"PKGFLARE_BUCKET\", \"PKGFLARE_CONFIG\"]);\nconst githubIdPattern = /^[1-9][0-9]{0,19}$/;\nconst audiencePattern = /^[\\x21-\\x7e]{1,256}$/;\nconst refPattern = /^refs\\/(?:heads|tags)\\/[A-Za-z0-9._/-]+\\*?$/;\nconst workflowRefPattern =\n /^[A-Za-z0-9_.-]+\\/[A-Za-z0-9_.-]+\\/\\.github\\/workflows\\/[A-Za-z0-9_.-]+\\.ya?ml@refs\\/(?:heads|tags)\\/[A-Za-z0-9._/-]+\\*?$/;\nconst jobWorkflowRefPattern =\n /^[A-Za-z0-9_.-]+\\/[A-Za-z0-9_.-]+\\/\\.github\\/workflows\\/[A-Za-z0-9_.-]+\\.ya?ml@(?:refs\\/(?:heads|tags)\\/[A-Za-z0-9._/-]+\\*?|[0-9a-f]{40})$/;\nconst packageSegmentPattern = /^(?!\\.)(?:[a-z0-9._-]+)$/;\nconst maximumGithubSubjects = 128;\nconst maximumPackagesPerSubject = 128;\nconst maximumRuntimeConfigBytes = 5 * 1024;\n\nexport function defineConfig(config: PkgflareConfig): PkgflareConfig {\n return config;\n}\n\nfunction isObject(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction normalizePermissions(value: unknown, label: string): Permission[] {\n if (\n !Array.isArray(value) ||\n value.length === 0 ||\n value.some((permission) => permission !== \"read\" && permission !== \"publish\")\n ) {\n throw new Error(`invalid permissions for ${label}`);\n }\n return [...new Set(value)] as Permission[];\n}\n\nfunction isSafePattern(value: string, pattern: RegExp): boolean {\n if (!pattern.test(value)) return false;\n const wildcard = value.indexOf(\"*\");\n return wildcard === -1 || wildcard === value.length - 1;\n}\n\nfunction normalizeGithubOidc(\n value: unknown,\n configuredScopes: readonly string[],\n): NormalizedConfig[\"auth\"][\"githubOidc\"] {\n if (!isObject(value) || typeof value.audience !== \"string\") {\n throw new Error(\"githubOidc must define an audience and trusted subjects\");\n }\n if (!audiencePattern.test(value.audience)) {\n throw new Error(\"githubOidc audience must be 1-256 printable ASCII characters\");\n }\n if (\n !Array.isArray(value.subjects) ||\n value.subjects.length === 0 ||\n value.subjects.length > maximumGithubSubjects\n ) {\n throw new Error(`githubOidc must define 1-${String(maximumGithubSubjects)} subjects`);\n }\n\n const subjects = value.subjects.map((subjectValue, index) => {\n const label = `githubOidc subject ${String(index + 1)}`;\n if (!isObject(subjectValue)) throw new Error(`${label} must be an object`);\n const { repositoryId, repositoryOwnerId, ref, workflowRef, jobWorkflowRef } = subjectValue;\n if (typeof repositoryId !== \"string\" || !githubIdPattern.test(repositoryId)) {\n throw new Error(`${label} repositoryId must be a decimal GitHub repository ID`);\n }\n if (typeof repositoryOwnerId !== \"string\" || !githubIdPattern.test(repositoryOwnerId)) {\n throw new Error(`${label} repositoryOwnerId must be a decimal GitHub owner ID`);\n }\n if (typeof ref !== \"string\" || !isSafePattern(ref, refPattern)) {\n throw new Error(`${label} ref must be an exact branch/tag ref or trailing-wildcard pattern`);\n }\n if (typeof workflowRef !== \"string\" || !isSafePattern(workflowRef, workflowRefPattern)) {\n throw new Error(\n `${label} workflowRef must identify a workflow file at an exact or trailing-wildcard ref`,\n );\n }\n if (\n jobWorkflowRef !== undefined &&\n (typeof jobWorkflowRef !== \"string\" || !isSafePattern(jobWorkflowRef, jobWorkflowRefPattern))\n ) {\n throw new Error(\n `${label} jobWorkflowRef must identify a reusable workflow at a full commit SHA or an exact/trailing-wildcard branch or tag ref`,\n );\n }\n const permissions = normalizePermissions(subjectValue.permissions, label);\n if (\n !Array.isArray(subjectValue.packages) ||\n subjectValue.packages.length === 0 ||\n subjectValue.packages.length > maximumPackagesPerSubject ||\n subjectValue.packages.some((packageName) => typeof packageName !== \"string\")\n ) {\n throw new Error(\n `${label} must define 1-${String(maximumPackagesPerSubject)} package patterns`,\n );\n }\n const packages = [...new Set(subjectValue.packages as string[])];\n for (const packagePattern of packages) {\n const slash = packagePattern.indexOf(\"/\");\n const scope = packagePattern.slice(0, slash);\n const packageSegment = packagePattern.slice(slash + 1);\n if (\n slash === -1 ||\n packagePattern.length > 214 ||\n !configuredScopes.includes(scope) ||\n (packageSegment !== \"*\" && !packageSegmentPattern.test(packageSegment))\n ) {\n throw new Error(`${label} contains an invalid or unconfigured package pattern`);\n }\n }\n return {\n repositoryId,\n repositoryOwnerId,\n ref,\n workflowRef,\n ...(jobWorkflowRef === undefined ? {} : { jobWorkflowRef }),\n permissions,\n packages,\n };\n });\n return { audience: value.audience, subjects };\n}\n\nexport function normalizeConfig(value: unknown): NormalizedConfig {\n if (!isObject(value)) throw new Error(\"configuration must be an object\");\n const { name, scopes: scopeValues, accountId, hostname, auth } = value;\n if (typeof name !== \"string\" || !workerNamePattern.test(name)) {\n throw new Error(\"name must be a lowercase Cloudflare resource name of at most 54 characters\");\n }\n\n if (\n accountId !== undefined &&\n (typeof accountId !== \"string\" || !accountIdPattern.test(accountId))\n ) {\n throw new Error(\"accountId must be a 32-character lowercase hexadecimal Cloudflare account ID\");\n }\n\n if (\n !Array.isArray(scopeValues) ||\n scopeValues.length === 0 ||\n scopeValues.some((scope) => typeof scope !== \"string\")\n ) {\n throw new Error(\"at least one package scope is required\");\n }\n\n const scopes = [...new Set(scopeValues as string[])];\n for (const scope of scopes) {\n if (!scopePattern.test(scope)) {\n throw new Error(`invalid package scope: ${scope}`);\n }\n }\n\n if (hostname !== undefined && (typeof hostname !== \"string\" || !hostnamePattern.test(hostname))) {\n throw new Error(\"hostname must be a valid DNS hostname without a scheme or path\");\n }\n\n if (!isObject(auth) || auth.provider !== \"secrets\") {\n throw new Error(\"unsupported authentication provider\");\n }\n\n const tokenValues = auth.tokens ?? [];\n if (!Array.isArray(tokenValues)) {\n throw new Error(\"authentication token bindings must be an array\");\n }\n\n const seenBindings = new Set<string>();\n const tokens = tokenValues.map((tokenValue) => {\n if (!isObject(tokenValue) || typeof tokenValue.binding !== \"string\") {\n throw new Error(\"authentication token binding must be an object with a binding name\");\n }\n const { binding, permissions: permissionValues } = tokenValue;\n if (!bindingPattern.test(binding)) {\n throw new Error(`invalid secret binding: ${binding}`);\n }\n if (reservedBindings.has(binding)) {\n throw new Error(`secret binding is reserved by pkgflare: ${binding}`);\n }\n if (seenBindings.has(binding)) {\n throw new Error(`duplicate secret binding: ${binding}`);\n }\n seenBindings.add(binding);\n\n const permissions = normalizePermissions(permissionValues, binding);\n\n return { binding, permissions };\n });\n\n const githubOidc =\n auth.githubOidc === undefined ? undefined : normalizeGithubOidc(auth.githubOidc, scopes);\n if (tokens.length === 0 && githubOidc === undefined) {\n throw new Error(\"at least one authentication method is required\");\n }\n\n const normalized: NormalizedConfig = {\n name,\n scopes,\n ...(accountId === undefined ? {} : { accountId }),\n ...(hostname === undefined ? {} : { hostname }),\n auth: {\n provider: \"secrets\",\n tokens,\n ...(githubOidc === undefined ? {} : { githubOidc }),\n },\n };\n if (new TextEncoder().encode(JSON.stringify(normalized)).byteLength > maximumRuntimeConfigBytes) {\n throw new Error(\"normalized configuration exceeds the 5 KiB Worker variable limit\");\n }\n return normalized;\n}\n"],"mappings":";AA+EA,IAAM,4BAA4B,IAAI;AAE/B,SAAS,aAAa,QAAwC;AACnE,SAAO;AACT;","names":[]}
|