@effected/github 0.25.1 → 0.27.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ActionsOidc.js +7 -4
- package/DeploymentEnvironment.js +7 -2
- package/GitHubApp.js +81 -69
- package/GitHubClient.js +68 -19
- package/GitHubError.js +13 -2
- package/GitHubRelease.js +23 -6
- package/GitHubRepository.js +74 -22
- package/GraphQL.js +7 -1
- package/README.md +3 -3
- package/index.d.ts +262 -36
- package/internal/confinement.js +62 -0
- package/internal/octokit.js +95 -5
- package/internal/requestOptions.js +84 -0
- package/internal/scrub.js +113 -0
- package/internal/uploads.js +70 -0
- package/package.json +7 -6
- package/tsdoc-metadata.json +1 -1
package/index.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { BareLineReference, CLOSING_KEYWORDS, ClosingKeyword, IssueReference, harvestIssueReferences, parseBareLineReference } from "@effected/github-references";
|
|
2
2
|
import { JwksResolver, JwtError } from "@effected/jwt";
|
|
3
3
|
import { Cause, Config, Context, Duration, Effect, Layer, Option, Redacted, Result, Schedule, Schema, Scope, Stream } from "effect";
|
|
4
|
+
import { Signature } from "effect/crypto";
|
|
4
5
|
import { PaginatingEndpoints } from "@octokit/plugin-paginate-rest";
|
|
5
6
|
import { Endpoints, RequestHeaders } from "@octokit/types";
|
|
6
7
|
import { SemVer } from "@effected/semver";
|
|
@@ -126,7 +127,8 @@ interface ActionsOidcVerifyOptions {
|
|
|
126
127
|
* @remarks
|
|
127
128
|
* {@link ActionsOidc.verify} is `@effected/oidc`'s `Oidc.verify` pinned to the
|
|
128
129
|
* Actions issuer: it checks the signature against GitHub's published JWKS
|
|
129
|
-
* (through `@effected/jwt`'s `JwksResolver`, which caches it
|
|
130
|
+
* (through `@effected/jwt`'s `JwksResolver`, which caches it; the signature
|
|
131
|
+
* itself runs on core `effect/jose` and needs core's `Signature` service), then `iss`,
|
|
130
132
|
* `aud`, `exp`, `nbf` and `iat`, then decodes the payload into
|
|
131
133
|
* {@link ActionsOidcClaims}. Every failure is a `JwtError`; route on its
|
|
132
134
|
* `reason` (`wrongAudience`, `expired`, `claims`, ...), never on its message.
|
|
@@ -151,7 +153,8 @@ interface ActionsOidcVerifyOptions {
|
|
|
151
153
|
* ```ts
|
|
152
154
|
* import { JwksResolver } from "@effected/jwt";
|
|
153
155
|
* import { ActionsOidc } from "@effected/github";
|
|
154
|
-
* import { Data, Effect } from "effect";
|
|
156
|
+
* import { Data, Effect, Layer } from "effect";
|
|
157
|
+
* import { SecureRandom, Signature } from "effect/crypto";
|
|
155
158
|
*
|
|
156
159
|
* class Forbidden extends Data.TaggedError("Forbidden")<{ readonly repositoryId: number }> {}
|
|
157
160
|
*
|
|
@@ -169,7 +172,8 @@ interface ActionsOidcVerifyOptions {
|
|
|
169
172
|
* });
|
|
170
173
|
*
|
|
171
174
|
* // JwksResolver.layer needs an HttpClient and a JwksStore, provided once at the edge.
|
|
172
|
-
*
|
|
175
|
+
* const CryptoLive = Signature.layerWebCrypto.pipe(Layer.provide(SecureRandom.layerWebCrypto));
|
|
176
|
+
* export const program = authorize("eyJ...").pipe(Effect.provide(Layer.merge(JwksResolver.layer, CryptoLive)));
|
|
173
177
|
* ```
|
|
174
178
|
*
|
|
175
179
|
* @public
|
|
@@ -178,8 +182,8 @@ export declare class ActionsOidc {
|
|
|
178
182
|
private constructor();
|
|
179
183
|
/** The Actions OIDC issuer, `https://token.actions.githubusercontent.com`. */
|
|
180
184
|
static readonly issuer: "https://token.actions.githubusercontent.com";
|
|
181
|
-
/** Verify a runner-issued OIDC token: signature against GitHub's JWKS, iss, aud, exp/nbf, then typed claims
|
|
182
|
-
static readonly verify: (token: string, options: ActionsOidcVerifyOptions) => Effect.Effect<ActionsOidcClaims, JwtError, JwksResolver>;
|
|
185
|
+
/** Verify a runner-issued OIDC token: signature against GitHub's JWKS, iss, aud, exp/nbf, then typed claims; requires `JwksResolver` and core `Signature`. */
|
|
186
|
+
static readonly verify: (token: string, options: ActionsOidcVerifyOptions) => Effect.Effect<ActionsOidcClaims, JwtError, JwksResolver | Signature.Signature>;
|
|
183
187
|
/**
|
|
184
188
|
* A valid claims payload for tests, overridable field by field.
|
|
185
189
|
*
|
|
@@ -272,7 +276,7 @@ declare const GitHubError_base: Schema.Class<GitHubError, Schema.TaggedStruct<"G
|
|
|
272
276
|
* 422s ("Update is not a fast forward") are prose only.
|
|
273
277
|
*/
|
|
274
278
|
readonly validation: Schema.optionalKey<Schema.$Array<typeof GitHubValidationEntry>>;
|
|
275
|
-
/** The underlying throwable, when one exists. */
|
|
279
|
+
/** The underlying throwable, when one exists; an octokit throwable is kept as a credential-free copy. */
|
|
276
280
|
readonly cause: Schema.optionalKey<Schema.Defect>;
|
|
277
281
|
}>, import("effect/Cause").YieldableError>;
|
|
278
282
|
/**
|
|
@@ -318,6 +322,16 @@ export declare class GitHubError extends GitHubError_base {
|
|
|
318
322
|
* epoch second, and turning it into a delay needs a "now" the caller controls.
|
|
319
323
|
* The client supplies `Clock.currentTimeMillis`, which is the `TestClock`
|
|
320
324
|
* under test.
|
|
325
|
+
*
|
|
326
|
+
* The kept `cause` is a credential-free copy of the throwable, not the
|
|
327
|
+
* throwable itself. octokit redacts only the `authorization` credential and
|
|
328
|
+
* two query values; the copy also drops the request body (a webhook secret,
|
|
329
|
+
* GraphQL variables), the per-request options and the response body beyond
|
|
330
|
+
* its top-level `message` and `documentation_url`, drops `set-cookie`, and
|
|
331
|
+
* reads `REDACTED` for every other credential-bearing header. It keeps the
|
|
332
|
+
* prototype (so `instanceof` still answers), `name`, `message`, `status`,
|
|
333
|
+
* the method, the redacted url and the remaining headers. A throwable with
|
|
334
|
+
* no `request`, `response` or `headers` field is kept as it is.
|
|
321
335
|
*/
|
|
322
336
|
static fromOctokit(operation: string, error: unknown, nowMillis: number): GitHubError;
|
|
323
337
|
/**
|
|
@@ -437,6 +451,11 @@ export declare class GitHubGraphQLError extends GitHubGraphQLError_base {
|
|
|
437
451
|
* failure with a `status`. Both arrive as throwables and both are read
|
|
438
452
|
* structurally, for the same reason the REST classifier does it — the error
|
|
439
453
|
* classes live in packages this one does not declare.
|
|
454
|
+
*
|
|
455
|
+
* The kept `cause` is the same credential-free copy
|
|
456
|
+
* {@link GitHubError.fromOctokit} keeps: the GraphQL document, its variables
|
|
457
|
+
* and any partial `data` are dropped with the rest of the request and response
|
|
458
|
+
* bodies.
|
|
440
459
|
*/
|
|
441
460
|
static fromThrowable(operation: string, error: unknown, nowMillis: number): GitHubGraphQLError;
|
|
442
461
|
}
|
|
@@ -649,17 +668,22 @@ export declare class RetryPolicy extends RetryPolicy_base {
|
|
|
649
668
|
*/
|
|
650
669
|
type Route = keyof Endpoints;
|
|
651
670
|
/**
|
|
652
|
-
* Transport knobs octokit accepts on any route, narrowed to the
|
|
671
|
+
* Transport knobs octokit accepts on any route, narrowed to the two this
|
|
653
672
|
* package allows.
|
|
654
673
|
*
|
|
655
674
|
* @remarks
|
|
656
675
|
* octokit's own `RequestParameters` carries an `[parameter: string]: unknown`
|
|
657
676
|
* index signature, so intersecting it would silently accept every misspelled
|
|
658
|
-
* parameter. These
|
|
659
|
-
*
|
|
660
|
-
*
|
|
661
|
-
*
|
|
662
|
-
*
|
|
677
|
+
* parameter. These two are the ones callers need: `headers` for a release
|
|
678
|
+
* asset's `content-type` and the attestations API version pin, and
|
|
679
|
+
* `mediaType.format` for raw content reads. Everything else a caller might
|
|
680
|
+
* reach for is a real endpoint parameter and is already typed.
|
|
681
|
+
*
|
|
682
|
+
* There is no knob that moves a request: **a client's token only ever goes to
|
|
683
|
+
* the host it was configured with.** octokit reads `baseUrl` and `url` off the
|
|
684
|
+
* flat parameters as the request's host, so the raw surface refuses either
|
|
685
|
+
* name, and an absolute-URL route, with a `rejected` `GitHubError` and nothing
|
|
686
|
+
* sent. A request to another GitHub host is a second client configured for it.
|
|
663
687
|
*
|
|
664
688
|
* @public
|
|
665
689
|
*/
|
|
@@ -670,16 +694,21 @@ interface RequestExtras {
|
|
|
670
694
|
readonly mediaType?: {
|
|
671
695
|
readonly format?: string;
|
|
672
696
|
};
|
|
673
|
-
/** Overrides the API host for this one request. */
|
|
674
|
-
readonly baseUrl?: string;
|
|
675
697
|
}
|
|
676
698
|
/**
|
|
677
699
|
* The parameters `Route` accepts — path, query and body parameters from
|
|
678
700
|
* GitHub's OpenAPI description, plus the extras below.
|
|
679
701
|
*
|
|
702
|
+
* @remarks
|
|
703
|
+
* `baseUrl` is typed `never`, so passing one is a compile error: the request
|
|
704
|
+
* goes to the client's configured host and nowhere else. One that arrives
|
|
705
|
+
* through a cast is refused at runtime.
|
|
706
|
+
*
|
|
680
707
|
* @public
|
|
681
708
|
*/
|
|
682
|
-
type Params<R extends Route> = Endpoints[R]["parameters"] & RequestExtras
|
|
709
|
+
type Params<R extends Route> = Endpoints[R]["parameters"] & RequestExtras & {
|
|
710
|
+
readonly baseUrl?: never;
|
|
711
|
+
};
|
|
683
712
|
/**
|
|
684
713
|
* The full response `Route` returns, including `status`, `headers` and `data`.
|
|
685
714
|
*
|
|
@@ -770,6 +799,12 @@ interface GitHubClientShape {
|
|
|
770
799
|
/**
|
|
771
800
|
* One request. The route types both the parameters and the returned `data`.
|
|
772
801
|
*
|
|
802
|
+
* @remarks
|
|
803
|
+
* The request carries this client's token to the configured base URL and
|
|
804
|
+
* nowhere else. A `baseUrl` or `url` parameter (through a cast), or a
|
|
805
|
+
* route that resolves to another origin, fails `kind: "rejected"` with no
|
|
806
|
+
* status and nothing sent.
|
|
807
|
+
*
|
|
773
808
|
* @example
|
|
774
809
|
* ```ts
|
|
775
810
|
* import { GitHubClient } from "@effected/github";
|
|
@@ -794,13 +829,29 @@ interface GitHubClientShape {
|
|
|
794
829
|
* checked. The attestations read uses it, because pinning
|
|
795
830
|
* `X-GitHub-Api-Version` puts the response on a contract the generated types
|
|
796
831
|
* do not describe.
|
|
832
|
+
*
|
|
833
|
+
* The token goes to the configured base URL and nowhere else. An
|
|
834
|
+
* absolute-URL route (`"POST https://host/path"`, which octokit would send
|
|
835
|
+
* as written) on another origin, a `baseUrl`, `url`, `request` or `method`
|
|
836
|
+
* parameter, or a template that expands to another host fails
|
|
837
|
+
* `kind: "rejected"` with no status and nothing sent. A body field octokit
|
|
838
|
+
* would otherwise read as an option, such as a webhook configuration's
|
|
839
|
+
* `url`, goes inside `data`, which is sent as the whole body.
|
|
797
840
|
*/
|
|
798
|
-
readonly requestDecoded: <A, I>(route: string, params: Record<string, unknown> & RequestExtras
|
|
841
|
+
readonly requestDecoded: <A, I>(route: string, params: Record<string, unknown> & RequestExtras & {
|
|
842
|
+
readonly baseUrl?: never;
|
|
843
|
+
}, schema: Schema.Codec<A, I>) => Effect.Effect<A, GitHubError>;
|
|
799
844
|
/**
|
|
800
845
|
* Collect every page of a paginating route, honoring {@link PageOptions}.
|
|
801
846
|
*
|
|
802
847
|
* @remarks
|
|
803
848
|
* Handing this a non-paginating route is a compile error.
|
|
849
|
+
*
|
|
850
|
+
* Every page goes to the configured host. A route or parameter that
|
|
851
|
+
* resolves elsewhere is refused before the first request, and a `Link`
|
|
852
|
+
* header whose next page names another origin fails the walk
|
|
853
|
+
* `kind: "rejected"` before that page is requested, rather than sending the
|
|
854
|
+
* token there or ending the walk early as if the collection were complete.
|
|
804
855
|
*/
|
|
805
856
|
readonly paginate: <R extends PaginatingRoute>(route: R, params: Params<R>, options?: PageOptions) => Effect.Effect<ReadonlyArray<Item<R>>, GitHubError>;
|
|
806
857
|
/**
|
|
@@ -808,7 +859,8 @@ interface GitHubClientShape {
|
|
|
808
859
|
*
|
|
809
860
|
* @remarks
|
|
810
861
|
* Lazy in requests: a downstream `Stream.take` stops the walk rather than
|
|
811
|
-
* filtering pages that were already fetched.
|
|
862
|
+
* filtering pages that were already fetched. Confined to the configured
|
|
863
|
+
* host exactly as {@link GitHubClientShape.paginate} is.
|
|
812
864
|
*/
|
|
813
865
|
readonly paginateStream: <R extends PaginatingRoute>(route: R, params: Params<R>, options?: PageOptions) => Stream.Stream<Item<R>, GitHubError>;
|
|
814
866
|
/** Run an owned GraphQL document and decode its answer. */
|
|
@@ -1116,6 +1168,12 @@ export declare class GitHubClient extends GitHubClient_base {
|
|
|
1116
1168
|
* `rateLimit` answers `Option.none()` and `apiVersion` the live default,
|
|
1117
1169
|
* because a real client legitimately answers both without a request.
|
|
1118
1170
|
*
|
|
1171
|
+
* It refuses what the live client refuses, before any override runs: a
|
|
1172
|
+
* `baseUrl`, `url`, `request` or `method` parameter (a body field called
|
|
1173
|
+
* `url` goes inside `data`), or a route that resolves off github.com's REST
|
|
1174
|
+
* root, fails `kind: "rejected"` with no status. A double has no
|
|
1175
|
+
* configured base, so an absolute-URL route must name `api.github.com`.
|
|
1176
|
+
*
|
|
1119
1177
|
* For recorded responses that page for real, use
|
|
1120
1178
|
* {@link GitHubClient.layerFixture}.
|
|
1121
1179
|
*/
|
|
@@ -1140,6 +1198,11 @@ export declare class GitHubClient extends GitHubClient_base {
|
|
|
1140
1198
|
* one fixture both records the calls and classifies a raw failure the way
|
|
1141
1199
|
* the live client would; there is no need to classify by hand inside a
|
|
1142
1200
|
* {@link GitHubClient.layerTest} handler.
|
|
1201
|
+
*
|
|
1202
|
+
* It refuses what the live client refuses, exactly as
|
|
1203
|
+
* {@link GitHubClient.makeTest} does. A refused call fails
|
|
1204
|
+
* `kind: "rejected"` and is **not** recorded in `requested`: it is never
|
|
1205
|
+
* served, as a refused live call never reaches the wire.
|
|
1143
1206
|
*/
|
|
1144
1207
|
static readonly layerFixture: (fixtures: GitHubFixtures) => Layer.Layer<GitHubClient>;
|
|
1145
1208
|
}
|
|
@@ -2090,6 +2153,14 @@ interface DeploymentEnvironmentShape {
|
|
|
2090
2153
|
* `config` stays an open record because the protection-rule body is a moving
|
|
2091
2154
|
* target: wait timers, reviewers, deployment-branch policies and whatever
|
|
2092
2155
|
* GitHub adds next.
|
|
2156
|
+
*
|
|
2157
|
+
* It is sent as the request BODY and nothing else. octokit reads `baseUrl`,
|
|
2158
|
+
* `url`, `method`, `headers`, `request` and `mediaType` off a call's flat
|
|
2159
|
+
* parameters as the request itself, and a `data` key as the whole body, so a
|
|
2160
|
+
* config spread beside the coordinates could send the authenticated `PUT` to
|
|
2161
|
+
* another host with the token attached. A config naming one of those, the
|
|
2162
|
+
* route's own `owner`, `repo` or `environment_name`, or `__proto__`, dies
|
|
2163
|
+
* with a `RangeError` before any request is made.
|
|
2093
2164
|
*/
|
|
2094
2165
|
readonly upsert: (name: string, config?: Record<string, unknown>) => Effect.Effect<void, GitHubError, Repo>;
|
|
2095
2166
|
/** The repository's deployment environments. */
|
|
@@ -2781,7 +2852,7 @@ declare const GitHubApp_base: Context.ServiceClass<GitHubApp, "@effected/github/
|
|
|
2781
2852
|
*/
|
|
2782
2853
|
export declare class GitHubApp extends GitHubApp_base {
|
|
2783
2854
|
/** The default transport. Bind it once; layers are memoized by reference. */
|
|
2784
|
-
static readonly layer: Layer.Layer<GitHubApp>;
|
|
2855
|
+
static readonly layer: Layer.Layer<GitHubApp, never, Signature.Signature>;
|
|
2785
2856
|
/**
|
|
2786
2857
|
* A transport with custom settings.
|
|
2787
2858
|
*
|
|
@@ -2790,7 +2861,7 @@ export declare class GitHubApp extends GitHubApp_base {
|
|
|
2790
2861
|
* this at two provide sites builds two instances, because layers are
|
|
2791
2862
|
* memoized by reference.
|
|
2792
2863
|
*/
|
|
2793
|
-
static readonly layerWith: (options: GitHubAppOptions) => Layer.Layer<GitHubApp>;
|
|
2864
|
+
static readonly layerWith: (options: GitHubAppOptions) => Layer.Layer<GitHubApp, never, Signature.Signature>;
|
|
2794
2865
|
/**
|
|
2795
2866
|
* A {@link GitHubClient} authenticated as an app installation.
|
|
2796
2867
|
*
|
|
@@ -2809,7 +2880,7 @@ export declare class GitHubApp extends GitHubApp_base {
|
|
|
2809
2880
|
* authorization failure, and widening every method's error channel to say so
|
|
2810
2881
|
* would tax every caller for a case only this layer can produce.
|
|
2811
2882
|
*/
|
|
2812
|
-
static readonly clientLayer: (request: TokenRequest, options?: GitHubAppOptions) => Layer.Layer<GitHubClient, GitHubAppError>;
|
|
2883
|
+
static readonly clientLayer: (request: TokenRequest, options?: GitHubAppOptions) => Layer.Layer<GitHubClient, GitHubAppError, Signature.Signature>;
|
|
2813
2884
|
/**
|
|
2814
2885
|
* A {@link GitHubClient} authenticated as the app itself, with an App JWT.
|
|
2815
2886
|
*
|
|
@@ -2862,7 +2933,7 @@ export declare class GitHubApp extends GitHubApp_base {
|
|
|
2862
2933
|
* Effect.runPromise(Effect.provide(sweep, layer));
|
|
2863
2934
|
* ```
|
|
2864
2935
|
*/
|
|
2865
|
-
static readonly appClientLayer: (credentials: AppCredentials, options?: GitHubAppOptions) => Layer.Layer<GitHubClient, GitHubAppError>;
|
|
2936
|
+
static readonly appClientLayer: (credentials: AppCredentials, options?: GitHubAppOptions) => Layer.Layer<GitHubClient, GitHubAppError, Signature.Signature>;
|
|
2866
2937
|
/**
|
|
2867
2938
|
* An installation token, reused from an {@link InstallationTokenStore}
|
|
2868
2939
|
* while it has `margin` (five minutes by default) left to live.
|
|
@@ -3470,7 +3541,15 @@ declare const ReleaseInfo_base: Schema.Class<ReleaseInfo, Schema.Struct<{
|
|
|
3470
3541
|
readonly prerelease: Schema.Boolean;
|
|
3471
3542
|
/** The web URL. */
|
|
3472
3543
|
readonly url: Schema.String;
|
|
3473
|
-
/**
|
|
3544
|
+
/**
|
|
3545
|
+
* The templated upload endpoint GitHub hands back for assets.
|
|
3546
|
+
*
|
|
3547
|
+
* @remarks
|
|
3548
|
+
* {@link GitHubReleaseShape.uploadAsset} never routes by this value: it is
|
|
3549
|
+
* response data. It only cross-checks that its origin is the upload host
|
|
3550
|
+
* derived from the client's configured base URL, and refuses the upload
|
|
3551
|
+
* when it is not.
|
|
3552
|
+
*/
|
|
3474
3553
|
readonly uploadUrl: Schema.String;
|
|
3475
3554
|
}>, {}>;
|
|
3476
3555
|
/**
|
|
@@ -3528,9 +3607,9 @@ interface GitHubReleaseShape {
|
|
|
3528
3607
|
*
|
|
3529
3608
|
* @remarks
|
|
3530
3609
|
* The one route in this package that is **not** in GitHub's generated
|
|
3531
|
-
* endpoint map: asset upload goes to
|
|
3532
|
-
* body, and the map omits it. So it
|
|
3533
|
-
*
|
|
3610
|
+
* endpoint map: asset upload goes to a separate upload host with a raw
|
|
3611
|
+
* binary body, and the map omits it. So it is decoded against an owned
|
|
3612
|
+
* schema — the escape hatch is from the route table, never from typing.
|
|
3534
3613
|
*
|
|
3535
3614
|
* Being outside the map cuts the other way too: octokit has no schema
|
|
3536
3615
|
* saying `name` is a **query** parameter, so the route template must carry
|
|
@@ -3538,6 +3617,29 @@ interface GitHubReleaseShape {
|
|
|
3538
3617
|
* `Invalid name for request` — a hand-written route owns its query
|
|
3539
3618
|
* parameters in the template, always. `label` is the endpoint's optional
|
|
3540
3619
|
* display label, shown in place of the file name on the release page.
|
|
3620
|
+
*
|
|
3621
|
+
* The upload host is derived from the base URL the client was **configured**
|
|
3622
|
+
* with, so the token only goes where the caller pointed it: github.com
|
|
3623
|
+
* (`https://api.github.com`, or no `baseUrl`) uploads to
|
|
3624
|
+
* `https://uploads.github.com`, GitHub Enterprise Server
|
|
3625
|
+
* (`https://<host>/api/v3`) to `https://<host>/api/uploads`, and any other
|
|
3626
|
+
* base to itself. The release's own `uploadUrl` is response data, so it is
|
|
3627
|
+
* never the route; its origin must equal the derived host's, or the call
|
|
3628
|
+
* fails `kind: "rejected"` with no status and nothing is sent.
|
|
3629
|
+
*
|
|
3630
|
+
* The client's public `requestDecoded` cannot reach the upload host: it
|
|
3631
|
+
* refuses every host but the configured API host. A client this package
|
|
3632
|
+
* built uploads through a private channel it carries off its public type,
|
|
3633
|
+
* which takes no host from anyone. A shape spread from a built client
|
|
3634
|
+
* (`{ ...client, requestDecoded }`) keeps that channel, so its upload does
|
|
3635
|
+
* **not** go through an overridden `requestDecoded`.
|
|
3636
|
+
*
|
|
3637
|
+
* A client shape this package did not build (`GitHubClient.makeTest`,
|
|
3638
|
+
* `layerFixture`, a hand-written double) has no channel: it is read as
|
|
3639
|
+
* github.com for the `uploadUrl` check, and the upload is handed to its own
|
|
3640
|
+
* `requestDecoded`, so a double records and answers it as usual. Before
|
|
3641
|
+
* these checks, a GitHub Enterprise Server client's upload sent its token to
|
|
3642
|
+
* `uploads.github.com`.
|
|
3541
3643
|
*/
|
|
3542
3644
|
readonly uploadAsset: (release: ReleaseInfo, asset: {
|
|
3543
3645
|
readonly name: string;
|
|
@@ -3593,11 +3695,20 @@ export declare class GitHubRelease extends GitHubRelease_base {
|
|
|
3593
3695
|
*/
|
|
3594
3696
|
type RepositorySettings = Data<"GET /repos/{owner}/{repo}">;
|
|
3595
3697
|
/**
|
|
3596
|
-
* The fields `PATCH /repos/{owner}/{repo}` accepts, minus the coordinate
|
|
3698
|
+
* The fields `PATCH /repos/{owner}/{repo}` accepts, minus the coordinate and
|
|
3699
|
+
* the per-request transport options.
|
|
3700
|
+
*
|
|
3701
|
+
* @remarks
|
|
3702
|
+
* A patch is the request **body** and nothing else. `GitHubRepository`
|
|
3703
|
+
* sends it as octokit's `data` option, so no key in it is ever read as a
|
|
3704
|
+
* request option (`baseUrl`, `url`, `headers`, `request`, `mediaType`) or as
|
|
3705
|
+
* the route's `owner` / `repo`. The transport knobs of `Rest.RequestExtras`
|
|
3706
|
+
* are therefore left out of the type: carried in a patch they would be body
|
|
3707
|
+
* fields, not the options they are named after.
|
|
3597
3708
|
*
|
|
3598
3709
|
* @public
|
|
3599
3710
|
*/
|
|
3600
|
-
type RepositoryPatch = Omit<Params<"PATCH /repos/{owner}/{repo}">, "owner" | "repo">;
|
|
3711
|
+
type RepositoryPatch = Omit<Params<"PATCH /repos/{owner}/{repo}">, "owner" | "repo" | keyof RequestExtras>;
|
|
3601
3712
|
/**
|
|
3602
3713
|
* A {@link RepositoryPatch} under construction, where an absent field may be
|
|
3603
3714
|
* spelled as an explicit `undefined`.
|
|
@@ -3613,9 +3724,66 @@ type RepositoryPatch = Omit<Params<"PATCH /repos/{owner}/{repo}">, "owner" | "re
|
|
|
3613
3724
|
* @public
|
|
3614
3725
|
*/
|
|
3615
3726
|
type RepositoryPatchDraft = { readonly [K in keyof RepositoryPatch]?: RepositoryPatch[K] | undefined; };
|
|
3727
|
+
/**
|
|
3728
|
+
* Repository settings the generated {@link RepositoryPatch} type does not know
|
|
3729
|
+
* yet, for {@link RepositoryPatchOptions.extra}.
|
|
3730
|
+
*
|
|
3731
|
+
* @remarks
|
|
3732
|
+
* An open map minus every key `RepositoryPatch` declares: a known key written
|
|
3733
|
+
* here is a compile error, so it has to go in the draft, where its value is
|
|
3734
|
+
* checked against octokit's type. Only what octokit has not caught up with
|
|
3735
|
+
* travels unchecked. The guard holds for a literal; a value already typed
|
|
3736
|
+
* `Record<string, unknown>` assigns anyway (an index signature does not meet an
|
|
3737
|
+
* optional property), which is why {@link repositoryPatch} checks again at
|
|
3738
|
+
* runtime.
|
|
3739
|
+
*
|
|
3740
|
+
* @public
|
|
3741
|
+
*/
|
|
3742
|
+
type RepositoryPatchExtra = {
|
|
3743
|
+
readonly [key: string]: unknown;
|
|
3744
|
+
} & { readonly [K in keyof RepositoryPatch]?: never; } & { readonly [K in RepositoryPatchReservedKey]?: never; };
|
|
3745
|
+
/**
|
|
3746
|
+
* Names {@link repositoryPatch} refuses in a draft or an extra.
|
|
3747
|
+
*
|
|
3748
|
+
* @remarks
|
|
3749
|
+
* octokit takes a route's path parameters, body fields and transport options
|
|
3750
|
+
* in one flat object, and `@octokit/endpoint` reads these names as the request
|
|
3751
|
+
* itself: `baseUrl` and `url` pick the host the authenticated request goes to,
|
|
3752
|
+
* `headers` its headers, `request` the fetch implementation, `data` the whole
|
|
3753
|
+
* body, `method` the verb, and `owner` / `repo` the path of
|
|
3754
|
+
* `PATCH /repos/{owner}/{repo}`. `__proto__` would set the patch's prototype
|
|
3755
|
+
* instead of a field. None of them is a repository setting.
|
|
3756
|
+
*
|
|
3757
|
+
* @public
|
|
3758
|
+
*/
|
|
3759
|
+
type RepositoryPatchReservedKey = "method" | "baseUrl" | "url" | "headers" | "request" | "mediaType" | "data" | "owner" | "repo" | "__proto__";
|
|
3760
|
+
/**
|
|
3761
|
+
* Options for {@link repositoryPatch}.
|
|
3762
|
+
*
|
|
3763
|
+
* @public
|
|
3764
|
+
*/
|
|
3765
|
+
interface RepositoryPatchOptions {
|
|
3766
|
+
/**
|
|
3767
|
+
* Settings GitHub accepts that octokit's generated types do not declare
|
|
3768
|
+
* yet, sent verbatim.
|
|
3769
|
+
*
|
|
3770
|
+
* @remarks
|
|
3771
|
+
* **GitHub may ignore them silently.** The REST `PATCH` answers 200 for a
|
|
3772
|
+
* field it does not recognise, so a misspelled extra reads as applied while
|
|
3773
|
+
* nothing changed: read the setting back when it matters. An `undefined`
|
|
3774
|
+
* value is dropped, as in the draft. A key the PATCH body already declares,
|
|
3775
|
+
* or a GraphQL-only setting (`has_sponsorships`, `has_pull_requests`,
|
|
3776
|
+
* `has_discussions`, which this patch cannot set; use
|
|
3777
|
+
* `GitHubRepository.applySettings`), throws a `RangeError` naming it, as
|
|
3778
|
+
* does a {@link RepositoryPatchReservedKey}: an octokit request option
|
|
3779
|
+
* (`baseUrl`, `url`, `headers`, `request`, `data`, and so on), the route's
|
|
3780
|
+
* own `owner` / `repo`, or `__proto__`.
|
|
3781
|
+
*/
|
|
3782
|
+
readonly extra?: RepositoryPatchExtra | undefined;
|
|
3783
|
+
}
|
|
3616
3784
|
/**
|
|
3617
3785
|
* A {@link RepositoryPatch} from a draft, dropping every explicitly-`undefined`
|
|
3618
|
-
* field.
|
|
3786
|
+
* field, plus any settings octokit's types do not know yet.
|
|
3619
3787
|
*
|
|
3620
3788
|
* @remarks
|
|
3621
3789
|
* The supported spelling for "apply only what was configured" — the natural
|
|
@@ -3625,6 +3793,13 @@ type RepositoryPatchDraft = { readonly [K in keyof RepositoryPatch]?: Repository
|
|
|
3625
3793
|
* `PATCH` treats an absent field as "leave it alone", while an explicit `null`
|
|
3626
3794
|
* or `undefined` is a value.
|
|
3627
3795
|
*
|
|
3796
|
+
* `options.extra` is the typed escape hatch for a setting GitHub accepts
|
|
3797
|
+
* before octokit's generated types declare it: the draft stays checked, and
|
|
3798
|
+
* only the extras ride unchecked. The result is still typed `RepositoryPatch`,
|
|
3799
|
+
* and `GitHubRepository.updateSettings` sends every key it carries. A known key
|
|
3800
|
+
* passed through `extra` throws a `RangeError` rather than skipping the draft's
|
|
3801
|
+
* type check (see {@link RepositoryPatchOptions.extra}).
|
|
3802
|
+
*
|
|
3628
3803
|
* A key-by-key loop still defeats TypeScript's correlation between two indexed
|
|
3629
3804
|
* accesses (`draft[key] = source[key]` over a union `key`), which no helper can
|
|
3630
3805
|
* fix — build the draft as a literal where you can.
|
|
@@ -3634,19 +3809,24 @@ type RepositoryPatchDraft = { readonly [K in keyof RepositoryPatch]?: Repository
|
|
|
3634
3809
|
* import { repositoryPatch } from "@effected/github";
|
|
3635
3810
|
*
|
|
3636
3811
|
* // `config.has_issues` is `boolean | undefined`; absent fields drop out.
|
|
3637
|
-
* const patch = repositoryPatch(
|
|
3638
|
-
*
|
|
3639
|
-
*
|
|
3640
|
-
*
|
|
3641
|
-
*
|
|
3812
|
+
* const patch = repositoryPatch(
|
|
3813
|
+
* {
|
|
3814
|
+
* has_issues: config.has_issues,
|
|
3815
|
+
* has_wiki: config.has_wiki,
|
|
3816
|
+
* description: config.description,
|
|
3817
|
+
* },
|
|
3818
|
+
* // A setting GitHub accepts before octokit's types declare it.
|
|
3819
|
+
* { extra: { has_new_feature: true } },
|
|
3820
|
+
* );
|
|
3642
3821
|
* ```
|
|
3643
3822
|
*
|
|
3644
3823
|
* @param draft - The fields to apply, any of which may be `undefined`.
|
|
3824
|
+
* @param options - `extra`: settings the generated type does not declare.
|
|
3645
3825
|
* @returns A patch carrying only the fields that were actually set.
|
|
3646
3826
|
*
|
|
3647
3827
|
* @public
|
|
3648
3828
|
*/
|
|
3649
|
-
export declare const repositoryPatch: (draft: RepositoryPatchDraft) => RepositoryPatch;
|
|
3829
|
+
export declare const repositoryPatch: (draft: RepositoryPatchDraft, options?: RepositoryPatchOptions) => RepositoryPatch;
|
|
3650
3830
|
/**
|
|
3651
3831
|
* Whether an account is a user or an organization.
|
|
3652
3832
|
*
|
|
@@ -3741,8 +3921,50 @@ interface AppliedSettings {
|
|
|
3741
3921
|
* REST `PATCH` ignores unknown fields and answers 200, so the key would be
|
|
3742
3922
|
* reported applied while the repository never changed. A caller that wants
|
|
3743
3923
|
* an unknown key to fail the run checks this list.
|
|
3924
|
+
*
|
|
3925
|
+
* Under `unknownKeys: "send"` an undescribed key is sent instead and named
|
|
3926
|
+
* in {@link AppliedSettings.unverified}; a key the api-version removed is
|
|
3927
|
+
* still ignored, because the description says GitHub drops it.
|
|
3928
|
+
*
|
|
3929
|
+
* Under either mode, a name octokit reads as a request option rather than
|
|
3930
|
+
* a body field (`baseUrl`, `url`, `headers`, `request`, `mediaType`,
|
|
3931
|
+
* `method`, `data`), the route's own `owner` / `repo`, and `__proto__` are
|
|
3932
|
+
* never sent and land here.
|
|
3744
3933
|
*/
|
|
3745
3934
|
readonly ignored: ReadonlyArray<string>;
|
|
3935
|
+
/**
|
|
3936
|
+
* Keys sent on the REST patch that GitHub's description does not declare,
|
|
3937
|
+
* so nothing confirms GitHub acted on them. Always a subset of
|
|
3938
|
+
* {@link AppliedSettings.rest}, and empty unless the call passed
|
|
3939
|
+
* `unknownKeys: "send"`.
|
|
3940
|
+
*
|
|
3941
|
+
* @remarks
|
|
3942
|
+
* The REST `PATCH` answers 200 whether or not it recognised a field, so a
|
|
3943
|
+
* key here may have changed the repository or done nothing. Read the setting
|
|
3944
|
+
* back when it matters.
|
|
3945
|
+
*/
|
|
3946
|
+
readonly unverified: ReadonlyArray<string>;
|
|
3947
|
+
}
|
|
3948
|
+
/**
|
|
3949
|
+
* Options for {@link GitHubRepositoryShape.applySettings}.
|
|
3950
|
+
*
|
|
3951
|
+
* @public
|
|
3952
|
+
*/
|
|
3953
|
+
interface ApplySettingsOptions {
|
|
3954
|
+
/**
|
|
3955
|
+
* What to do with a key neither API declares. `"ignore"` (the default)
|
|
3956
|
+
* leaves it unsent and reports it in {@link AppliedSettings.ignored};
|
|
3957
|
+
* `"send"` forwards it on the REST patch verbatim and reports it in
|
|
3958
|
+
* {@link AppliedSettings.rest} and {@link AppliedSettings.unverified}.
|
|
3959
|
+
*
|
|
3960
|
+
* @remarks
|
|
3961
|
+
* `"send"` is for a sync tool applying settings a user declared that GitHub
|
|
3962
|
+
* accepts before its OpenAPI description, and octokit's types, catch up.
|
|
3963
|
+
* The cost is that a typo is sent too and answered 200, so it is only as
|
|
3964
|
+
* safe as the caller's own validation. GraphQL-only keys still route to
|
|
3965
|
+
* GraphQL, and a key the client's api-version removed is still ignored.
|
|
3966
|
+
*/
|
|
3967
|
+
readonly unknownKeys?: "ignore" | "send" | undefined;
|
|
3746
3968
|
}
|
|
3747
3969
|
/**
|
|
3748
3970
|
* Read and update a repository's settings and topics, and look up its default
|
|
@@ -3809,8 +4031,12 @@ interface GitHubRepositoryShape {
|
|
|
3809
4031
|
* in `ignored`, rather than forwarded to a `PATCH` that would ignore it and
|
|
3810
4032
|
* answer 200. It does not fail the call, so additive GitHub API growth never
|
|
3811
4033
|
* breaks a run; a caller that owns a schema should still validate first.
|
|
4034
|
+
*
|
|
4035
|
+
* A setting GitHub accepts before its description declares it is sent with
|
|
4036
|
+
* `{ unknownKeys: "send" }` ({@link ApplySettingsOptions}), and reported in
|
|
4037
|
+
* `unverified` as well as `rest`, because a 200 does not say GitHub used it.
|
|
3812
4038
|
*/
|
|
3813
|
-
readonly applySettings: (settings: Record<string, unknown
|
|
4039
|
+
readonly applySettings: (settings: Record<string, unknown>, options?: ApplySettingsOptions) => Effect.Effect<AppliedSettings, GitHubError | GitHubGraphQLError, Repo>;
|
|
3814
4040
|
/**
|
|
3815
4041
|
* The repository's topics, as GitHub stores them.
|
|
3816
4042
|
*
|
|
@@ -4959,5 +5185,5 @@ export declare class WorkflowDispatch extends WorkflowDispatch_base {
|
|
|
4959
5185
|
/** {@link WorkflowDispatch.makeTest} behind a `Layer`. */
|
|
4960
5186
|
static readonly layerTest: (overrides?: Partial<WorkflowDispatchShape>) => Layer.Layer<WorkflowDispatch>;
|
|
4961
5187
|
}
|
|
4962
|
-
export { type ActionsOidcVerifyOptions, type AppCredentials, type AppliedSettings, type ArtifactMetadataShape, type AttestationShape, type AuthenticatedAppShape, type BareLineReference, type BotUserRequest, type BranchOutcome, CLOSING_KEYWORDS, type CachedToken, type CachedTokenRequest, type CheckRunShape, type ClosingKeyword, type CodeScanningSetup, type CodeScanningShape, type CompleteCheckRunOptions, type ConcludeCheckRun, type CreateCheckRunOptions, type DeliveriesOptions, type DeploymentEnvironmentInfo, type DeploymentEnvironmentShape, type GitBranchShape, type GitCommitShape, type GitHubAppOptions, type GitHubAppShape, type GitHubClientOptions, type GitHubClientShape, type GitHubCommitShape, type GitHubContentShape, type GitHubIssueShape, type GitHubReleaseShape, type GitHubRepositoryShape, type GitTagShape, type InstallationTokenStoreShape, type IssueReference, type LatestSemverOptions, type ListCheckRunsOptions, type OwnerType, type PollOptions, type PullRequestCommentShape, type PullRequestShape, type RecordedCall, type RepositoryPatch, type RepositoryPatchDraft, type RepositorySecretShape, type RepositorySecurityShape, type RepositorySettings, type RepositoryVariableShape, type Data as RestData, type RequestExtras as RestExtras, type Item as RestItem, type PaginatingRoute as RestPaginatingRoute, type Params as RestParams, type Response as RestResponse, type Route as RestRoute, type RetryableFailure, type RulesetInfo, type RulesetPayload, type RulesetShape, type SecretInfo, type SecretScope, type TokenRequest, type UpdateCheckRunOptions, type UpsertedPullRequest, type VariableInfo, type VersionFromTag, type WorkflowDispatchShape, type WorkflowInfo, harvestIssueReferences, parseBareLineReference };
|
|
5188
|
+
export { type ActionsOidcVerifyOptions, type AppCredentials, type AppliedSettings, type ApplySettingsOptions, type ArtifactMetadataShape, type AttestationShape, type AuthenticatedAppShape, type BareLineReference, type BotUserRequest, type BranchOutcome, CLOSING_KEYWORDS, type CachedToken, type CachedTokenRequest, type CheckRunShape, type ClosingKeyword, type CodeScanningSetup, type CodeScanningShape, type CompleteCheckRunOptions, type ConcludeCheckRun, type CreateCheckRunOptions, type DeliveriesOptions, type DeploymentEnvironmentInfo, type DeploymentEnvironmentShape, type GitBranchShape, type GitCommitShape, type GitHubAppOptions, type GitHubAppShape, type GitHubClientOptions, type GitHubClientShape, type GitHubCommitShape, type GitHubContentShape, type GitHubIssueShape, type GitHubReleaseShape, type GitHubRepositoryShape, type GitTagShape, type InstallationTokenStoreShape, type IssueReference, type LatestSemverOptions, type ListCheckRunsOptions, type OwnerType, type PollOptions, type PullRequestCommentShape, type PullRequestShape, type RecordedCall, type RepositoryPatch, type RepositoryPatchDraft, type RepositoryPatchExtra, type RepositoryPatchOptions, type RepositoryPatchReservedKey, type RepositorySecretShape, type RepositorySecurityShape, type RepositorySettings, type RepositoryVariableShape, type Data as RestData, type RequestExtras as RestExtras, type Item as RestItem, type PaginatingRoute as RestPaginatingRoute, type Params as RestParams, type Response as RestResponse, type Route as RestRoute, type RetryableFailure, type RulesetInfo, type RulesetPayload, type RulesetShape, type SecretInfo, type SecretScope, type TokenRequest, type UpdateCheckRunOptions, type UpsertedPullRequest, type VariableInfo, type VersionFromTag, type WorkflowDispatchShape, type WorkflowInfo, harvestIssueReferences, parseBareLineReference };
|
|
4963
5189
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { GitHubError } from "../GitHubError.js";
|
|
2
|
+
import { reservedRawParam } from "./requestOptions.js";
|
|
3
|
+
import { originOf } from "./uploads.js";
|
|
4
|
+
|
|
5
|
+
// src/internal/confinement.ts
|
|
6
|
+
/**
|
|
7
|
+
* Why one of the caller's parameters may not be sent, or `undefined`.
|
|
8
|
+
*
|
|
9
|
+
* @remarks
|
|
10
|
+
* Checked against the CALLER's parameters, before anything the transport adds
|
|
11
|
+
* (`per_page`, a signal, the upload base): `baseUrl` and `url` move the host,
|
|
12
|
+
* `request` swaps the fetch, `method` rewrites the verb.
|
|
13
|
+
*
|
|
14
|
+
* @internal
|
|
15
|
+
*/
|
|
16
|
+
const reservedParamReason = (params) => {
|
|
17
|
+
for (const key of Object.keys(params)) {
|
|
18
|
+
const reason = reservedRawParam(key);
|
|
19
|
+
if (reason !== void 0) return `the parameter "${key}" ${reason}`;
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* Why `route` with `params` may not be sent to the origin `allowed`, or
|
|
24
|
+
* `undefined` when it may.
|
|
25
|
+
*
|
|
26
|
+
* @remarks
|
|
27
|
+
* The URL checked is the one `expand` builds, which is the one octokit itself
|
|
28
|
+
* would send, so no spelling of the route reaches a host this check did not
|
|
29
|
+
* see.
|
|
30
|
+
*
|
|
31
|
+
* @internal
|
|
32
|
+
*/
|
|
33
|
+
const routeReason = (expand, route, params, allowed) => {
|
|
34
|
+
let url;
|
|
35
|
+
try {
|
|
36
|
+
url = expand(route, params).url;
|
|
37
|
+
} catch {
|
|
38
|
+
return "the route does not expand to a URL";
|
|
39
|
+
}
|
|
40
|
+
if (allowed === void 0) return "the configured base URL is not an absolute URL";
|
|
41
|
+
const origin = originOf(url);
|
|
42
|
+
return origin === allowed ? void 0 : `the route resolves to ${origin ?? "a URL that does not parse"}, not the configured host ${allowed}; refusing to send the token there`;
|
|
43
|
+
};
|
|
44
|
+
/**
|
|
45
|
+
* Why a raw-surface call may not be sent to `allowed`, or `undefined`: a
|
|
46
|
+
* reserved parameter first, then the route's resolved origin.
|
|
47
|
+
*
|
|
48
|
+
* @internal
|
|
49
|
+
*/
|
|
50
|
+
const rawRequestRefusal = (expand, route, params, allowed) => reservedParamReason(params) ?? routeReason(expand, route, params, allowed);
|
|
51
|
+
/**
|
|
52
|
+
* The error a refused call fails with: `kind: "rejected"`, no status.
|
|
53
|
+
*
|
|
54
|
+
* @internal
|
|
55
|
+
*/
|
|
56
|
+
const refusedRequest = (operation, reason) => new GitHubError({
|
|
57
|
+
kind: "rejected",
|
|
58
|
+
operation,
|
|
59
|
+
reason
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
export { rawRequestRefusal, refusedRequest, reservedParamReason, routeReason };
|