@effected/github 0.7.0 → 0.8.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.
@@ -5,6 +5,47 @@ import { Context, Effect, Layer, Schema } from "effect";
5
5
 
6
6
  //#region src/GitHubRepository.ts
7
7
  /**
8
+ * A {@link RepositoryPatch} from a draft, dropping every explicitly-`undefined`
9
+ * field.
10
+ *
11
+ * @remarks
12
+ * The supported spelling for "apply only what was configured" — the natural
13
+ * shape for a sync action, and the one the checker cannot follow on its own.
14
+ * Without it a consumer under the recommended tsconfig is quietly pushed toward
15
+ * `as`, which is a real cost in a package whose stated design property is that
16
+ * the route is the key and there are no casts.
17
+ *
18
+ * Dropping the key rather than sending `undefined` is what the wire needs:
19
+ * `PATCH` treats an absent field as "leave it alone", while an explicit `null`
20
+ * or `undefined` is a value.
21
+ *
22
+ * A key-by-key loop still defeats TypeScript's correlation between two indexed
23
+ * accesses (`draft[key] = source[key]` over a union `key`), which no helper can
24
+ * fix — build the draft as a literal where you can.
25
+ *
26
+ * @example
27
+ * ```ts
28
+ * import { repositoryPatch } from "@effected/github";
29
+ *
30
+ * // `config.has_issues` is `boolean | undefined`; absent fields drop out.
31
+ * const patch = repositoryPatch({
32
+ * has_issues: config.has_issues,
33
+ * has_wiki: config.has_wiki,
34
+ * description: config.description,
35
+ * });
36
+ * ```
37
+ *
38
+ * @param draft - The fields to apply, any of which may be `undefined`.
39
+ * @returns A patch carrying only the fields that were actually set.
40
+ *
41
+ * @public
42
+ */
43
+ const repositoryPatch = (draft) => {
44
+ const out = {};
45
+ for (const [key, value] of Object.entries(draft)) if (value !== void 0) out[key] = value;
46
+ return out;
47
+ };
48
+ /**
8
49
  * Fields in the user-facing `security_and_analysis` block that GitHub accepts
9
50
  * as `{ status: "enabled" | "disabled" }`.
10
51
  *
@@ -234,4 +275,4 @@ const make = (client) => {
234
275
  };
235
276
 
236
277
  //#endregion
237
- export { GRAPHQL_ONLY_SETTINGS, GitHubRepository, SECURITY_ANALYSIS_STATUS_FIELDS, transformSecurityAndAnalysis };
278
+ export { GRAPHQL_ONLY_SETTINGS, GitHubRepository, SECURITY_ANALYSIS_STATUS_FIELDS, repositoryPatch, transformSecurityAndAnalysis };
package/README.md CHANGED
@@ -189,6 +189,19 @@ const program = Effect.gen(function* () {
189
189
  // GitHub would reject, which is what a person reading a dry run is checking for.
190
190
  ```
191
191
 
192
+ `updateSettings` takes octokit's own generated params, and those spell an optional field as `has_issues?: boolean` rather than `has_issues?: boolean | undefined` — so under `exactOptionalPropertyTypes` a `Partial<T>` built from your own settings schema does not assign to it at all. `repositoryPatch` is the supported way out, and it exists so the answer is never a cast:
193
+
194
+ ```ts
195
+ import { repositoryPatch } from "@effected/github";
196
+
197
+ declare const config: { has_issues?: boolean | undefined; description?: string | undefined };
198
+
199
+ const patch = repositoryPatch({ has_issues: config.has_issues, description: config.description });
200
+ // a RepositoryPatch carrying only the fields that were actually set
201
+ ```
202
+
203
+ Dropping the key is what the wire needs: `PATCH` reads an absent field as "leave it alone", while an explicit `null` is a value. `RepositoryPatchDraft` is the input type — the same fields, each allowed to be an explicit `undefined`. Build the draft as an object literal where you can: a key-by-key loop defeats TypeScript's correlation between two indexed accesses, which no helper can repair.
204
+
192
205
  `security_and_analysis` accepts both the bare `"enabled"` a human writes in a config file and the `{ status: "enabled" }` GitHub's own parameter type declares. A map touching neither GraphQL-only setting never reads the node id, so the common case stays one request. `ownerType` answers `"User"` or `"Organization"` for the repository in `Repo`, which is how a shared settings template drops the fields GitHub accepts only on an organization-owned repository before applying itself to a personal one.
193
206
 
194
207
  ## GitHub App authentication
@@ -268,6 +281,7 @@ const TestClient = GitHubClient.layerFixture(fixtures);
268
281
  - `GitHubClient` — the typed transport: `request`, `requestDecoded` (a mandatory-schema escape hatch for routes outside the generated map), `paginate` / `paginateStream`, `graphql`, and `rateLimit` (observation only — nothing here throttles on your behalf).
269
282
  - `Repo` / `RepoRef` — the `{ owner, repo }` coordinate, resolved per call through `R`, with `Repo.provide` for multi-repository programs.
270
283
  - `GitHubRepository` — the repository's settings as GitHub's own generated type, plus `defaultBranch`, `nodeId`, `ownerType` for gating organization-only fields, and `applySettings` reporting the keys it actually sent.
284
+ - `repositoryPatch` / `RepositoryPatchDraft` — build an `updateSettings` patch from fields that may be `undefined`, under `exactOptionalPropertyTypes`, without a cast.
271
285
  - `GitHubError` / `GitHubGraphQLError` — one error per transport, `kind`-routed with `hasKind` for `Effect.catchIf`.
272
286
  - `RetryPolicy` — the client's one retry policy: full-jitter backoff, server-advised delays honored up to a ceiling.
273
287
  - `GitHubApp` — App JWT signing, installation token minting/revocation, app and installation identity, and `clientLayer` for an App-authenticated `GitHubClient`.
package/index.d.ts CHANGED
@@ -2277,6 +2277,59 @@ type RepositorySettings = Data<"GET /repos/{owner}/{repo}">;
2277
2277
  * @public
2278
2278
  */
2279
2279
  type RepositoryPatch = Omit<Params<"PATCH /repos/{owner}/{repo}">, "owner" | "repo">;
2280
+ /**
2281
+ * A {@link RepositoryPatch} under construction, where an absent field may be
2282
+ * spelled as an explicit `undefined`.
2283
+ *
2284
+ * @remarks
2285
+ * The shape you actually have when you are applying only what a user
2286
+ * configured. Octokit's generated params spell an optional field as
2287
+ * `has_issues?: boolean`, **not** `has_issues?: boolean | undefined`, so under
2288
+ * `exactOptionalPropertyTypes` — on in this repo and in the silk tsconfig base
2289
+ * — a `Partial<T>` built from your own settings schema does not assign to
2290
+ * `RepositoryPatch` at all. This type does, and {@link repositoryPatch} turns
2291
+ * it into one.
2292
+ *
2293
+ * @public
2294
+ */
2295
+ type RepositoryPatchDraft = { readonly [K in keyof RepositoryPatch]?: RepositoryPatch[K] | undefined; };
2296
+ /**
2297
+ * A {@link RepositoryPatch} from a draft, dropping every explicitly-`undefined`
2298
+ * field.
2299
+ *
2300
+ * @remarks
2301
+ * The supported spelling for "apply only what was configured" — the natural
2302
+ * shape for a sync action, and the one the checker cannot follow on its own.
2303
+ * Without it a consumer under the recommended tsconfig is quietly pushed toward
2304
+ * `as`, which is a real cost in a package whose stated design property is that
2305
+ * the route is the key and there are no casts.
2306
+ *
2307
+ * Dropping the key rather than sending `undefined` is what the wire needs:
2308
+ * `PATCH` treats an absent field as "leave it alone", while an explicit `null`
2309
+ * or `undefined` is a value.
2310
+ *
2311
+ * A key-by-key loop still defeats TypeScript's correlation between two indexed
2312
+ * accesses (`draft[key] = source[key]` over a union `key`), which no helper can
2313
+ * fix — build the draft as a literal where you can.
2314
+ *
2315
+ * @example
2316
+ * ```ts
2317
+ * import { repositoryPatch } from "@effected/github";
2318
+ *
2319
+ * // `config.has_issues` is `boolean | undefined`; absent fields drop out.
2320
+ * const patch = repositoryPatch({
2321
+ * has_issues: config.has_issues,
2322
+ * has_wiki: config.has_wiki,
2323
+ * description: config.description,
2324
+ * });
2325
+ * ```
2326
+ *
2327
+ * @param draft - The fields to apply, any of which may be `undefined`.
2328
+ * @returns A patch carrying only the fields that were actually set.
2329
+ *
2330
+ * @public
2331
+ */
2332
+ declare const repositoryPatch: (draft: RepositoryPatchDraft) => RepositoryPatch;
2280
2333
  /**
2281
2334
  * Whether an account is a user or an organization.
2282
2335
  *
@@ -3279,5 +3332,5 @@ declare class WorkflowDispatch extends WorkflowDispatch_base {
3279
3332
  static readonly layerTest: (overrides?: Partial<WorkflowDispatchShape>) => Layer.Layer<WorkflowDispatch>;
3280
3333
  }
3281
3334
  //#endregion
3282
- export { Annotation, AnnotationLevel, type AppCredentials, AppIdentity, type AppliedSettings, ArtifactMetadata, type ArtifactMetadataShape, Attestation, AttestationListEntry, AttestationRecord, type AttestationShape, type BareLineReference, BotIdentity, type BranchOutcome, CLOSING_KEYWORDS, CheckConclusion, CheckRun, CheckRunOutput, CheckRunRef, type CheckRunShape, type ClosingKeyword, CodeScanning, type CodeScanningSetup, type CodeScanningShape, CommentMarker, CommentOnceResult, CommentRecord, CommitComparison, CommitFile, CommitRef, CommitSummary, type ConcludeCheckRun, DeploymentEnvironment, type DeploymentEnvironmentInfo, type DeploymentEnvironmentShape, ExtraPermission, FileChange, FileContent, FileDeletion, FileMode, FileStatus, GRAPHQL_ONLY_SETTINGS, GitBranch, type GitBranchShape, GitCommit, type GitCommitShape, GitHubApp, GitHubAppError, type GitHubAppOptions, type GitHubAppShape, GitHubClient, type GitHubClientOptions, type GitHubClientShape, GitHubCommit, type GitHubCommitShape, GitHubContent, type GitHubContentShape, GitHubError, GitHubErrorKind, type GitHubFixtures, GitHubGraphQLError, GitHubIssue, type GitHubIssueShape, GitHubRelease, type GitHubReleaseShape, GitHubRepository, type GitHubRepositoryShape, GitTag, type GitTagShape, GraphQLDocument, GraphQLErrorEntry, Installation, InstallationToken, InvalidRepoRefError, IssueInfo, type IssueReference, type LatestSemverOptions, LinkedIssue, MergeMethod, type OwnerType, PageOptions, PermissionGap, PermissionLevel, PermissionResult, type PollOptions, PullRequest, PullRequestComment, type PullRequestCommentShape, PullRequestInfo, type PullRequestShape, RateLimitSnapshot, type RecordedCall, ReleaseAsset, ReleaseInfo, Repo, RepoRef, type RepositoryPatch, RepositorySecret, type RepositorySecretShape, RepositorySecurity, type RepositorySecurityShape, type RepositorySettings, RepositoryVariable, 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, RetryPolicy, type RetryableFailure, Ruleset, type RulesetInfo, type RulesetPayload, type RulesetShape, SECURITY_ANALYSIS_STATUS_FIELDS, type SecretInfo, type SecretScope, SemverTag, StorageRecordInput, TagRef, TokenPermissionError, TokenPermissions, type TokenRequest, type UpsertedPullRequest, type VariableInfo, type VersionFromTag, WorkflowDispatch, type WorkflowDispatchShape, type WorkflowInfo, WorkflowRunStatus, harvestIssueReferences, parseBareLineReference, transformSecurityAndAnalysis, versionFromTag };
3335
+ export { Annotation, AnnotationLevel, type AppCredentials, AppIdentity, type AppliedSettings, ArtifactMetadata, type ArtifactMetadataShape, Attestation, AttestationListEntry, AttestationRecord, type AttestationShape, type BareLineReference, BotIdentity, type BranchOutcome, CLOSING_KEYWORDS, CheckConclusion, CheckRun, CheckRunOutput, CheckRunRef, type CheckRunShape, type ClosingKeyword, CodeScanning, type CodeScanningSetup, type CodeScanningShape, CommentMarker, CommentOnceResult, CommentRecord, CommitComparison, CommitFile, CommitRef, CommitSummary, type ConcludeCheckRun, DeploymentEnvironment, type DeploymentEnvironmentInfo, type DeploymentEnvironmentShape, ExtraPermission, FileChange, FileContent, FileDeletion, FileMode, FileStatus, GRAPHQL_ONLY_SETTINGS, GitBranch, type GitBranchShape, GitCommit, type GitCommitShape, GitHubApp, GitHubAppError, type GitHubAppOptions, type GitHubAppShape, GitHubClient, type GitHubClientOptions, type GitHubClientShape, GitHubCommit, type GitHubCommitShape, GitHubContent, type GitHubContentShape, GitHubError, GitHubErrorKind, type GitHubFixtures, GitHubGraphQLError, GitHubIssue, type GitHubIssueShape, GitHubRelease, type GitHubReleaseShape, GitHubRepository, type GitHubRepositoryShape, GitTag, type GitTagShape, GraphQLDocument, GraphQLErrorEntry, Installation, InstallationToken, InvalidRepoRefError, IssueInfo, type IssueReference, type LatestSemverOptions, LinkedIssue, MergeMethod, type OwnerType, PageOptions, PermissionGap, PermissionLevel, PermissionResult, type PollOptions, PullRequest, PullRequestComment, type PullRequestCommentShape, PullRequestInfo, type PullRequestShape, RateLimitSnapshot, type RecordedCall, ReleaseAsset, ReleaseInfo, Repo, RepoRef, type RepositoryPatch, type RepositoryPatchDraft, RepositorySecret, type RepositorySecretShape, RepositorySecurity, type RepositorySecurityShape, type RepositorySettings, RepositoryVariable, 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, RetryPolicy, type RetryableFailure, Ruleset, type RulesetInfo, type RulesetPayload, type RulesetShape, SECURITY_ANALYSIS_STATUS_FIELDS, type SecretInfo, type SecretScope, SemverTag, StorageRecordInput, TagRef, TokenPermissionError, TokenPermissions, type TokenRequest, type UpsertedPullRequest, type VariableInfo, type VersionFromTag, WorkflowDispatch, type WorkflowDispatchShape, type WorkflowInfo, WorkflowRunStatus, harvestIssueReferences, parseBareLineReference, repositoryPatch, transformSecurityAndAnalysis, versionFromTag };
3283
3336
  //# sourceMappingURL=index.d.ts.map
package/index.js CHANGED
@@ -16,7 +16,7 @@ import { GitHubContent } from "./GitHubContent.js";
16
16
  import { CommentMarker, CommentRecord, PullRequestComment } from "./PullRequestComment.js";
17
17
  import { CommentOnceResult, GitHubIssue, IssueInfo, LinkedIssue } from "./GitHubIssue.js";
18
18
  import { GitHubRelease, ReleaseAsset, ReleaseInfo } from "./GitHubRelease.js";
19
- import { GRAPHQL_ONLY_SETTINGS, GitHubRepository, SECURITY_ANALYSIS_STATUS_FIELDS, transformSecurityAndAnalysis } from "./GitHubRepository.js";
19
+ import { GRAPHQL_ONLY_SETTINGS, GitHubRepository, SECURITY_ANALYSIS_STATUS_FIELDS, repositoryPatch, transformSecurityAndAnalysis } from "./GitHubRepository.js";
20
20
  import { GitTag, SemverTag, TagRef, versionFromTag } from "./GitTag.js";
21
21
  import { PageOptions } from "./Rest.js";
22
22
  import { MergeMethod, PullRequest, PullRequestInfo } from "./PullRequest.js";
@@ -28,4 +28,4 @@ import { ExtraPermission, PermissionGap, PermissionLevel, PermissionResult, Toke
28
28
  import { WorkflowDispatch, WorkflowRunStatus } from "./WorkflowDispatch.js";
29
29
  import { CLOSING_KEYWORDS, harvestIssueReferences, parseBareLineReference } from "@effected/github-references";
30
30
 
31
- export { Annotation, AnnotationLevel, AppIdentity, ArtifactMetadata, Attestation, AttestationListEntry, AttestationRecord, BotIdentity, CLOSING_KEYWORDS, CheckConclusion, CheckRun, CheckRunOutput, CheckRunRef, CodeScanning, CommentMarker, CommentOnceResult, CommentRecord, CommitComparison, CommitFile, CommitRef, CommitSummary, DeploymentEnvironment, ExtraPermission, FileChange, FileContent, FileDeletion, FileMode, FileStatus, GRAPHQL_ONLY_SETTINGS, GitBranch, GitCommit, GitHubApp, GitHubAppError, GitHubClient, GitHubCommit, GitHubContent, GitHubError, GitHubErrorKind, GitHubGraphQLError, GitHubIssue, GitHubRelease, GitHubRepository, GitTag, GraphQLDocument, GraphQLErrorEntry, Installation, InstallationToken, InvalidRepoRefError, IssueInfo, LinkedIssue, MergeMethod, PageOptions, PermissionGap, PermissionLevel, PermissionResult, PullRequest, PullRequestComment, PullRequestInfo, RateLimitSnapshot, ReleaseAsset, ReleaseInfo, Repo, RepoRef, RepositorySecret, RepositorySecurity, RepositoryVariable, RetryPolicy, Ruleset, SECURITY_ANALYSIS_STATUS_FIELDS, SemverTag, StorageRecordInput, TagRef, TokenPermissionError, TokenPermissions, WorkflowDispatch, WorkflowRunStatus, harvestIssueReferences, parseBareLineReference, transformSecurityAndAnalysis, versionFromTag };
31
+ export { Annotation, AnnotationLevel, AppIdentity, ArtifactMetadata, Attestation, AttestationListEntry, AttestationRecord, BotIdentity, CLOSING_KEYWORDS, CheckConclusion, CheckRun, CheckRunOutput, CheckRunRef, CodeScanning, CommentMarker, CommentOnceResult, CommentRecord, CommitComparison, CommitFile, CommitRef, CommitSummary, DeploymentEnvironment, ExtraPermission, FileChange, FileContent, FileDeletion, FileMode, FileStatus, GRAPHQL_ONLY_SETTINGS, GitBranch, GitCommit, GitHubApp, GitHubAppError, GitHubClient, GitHubCommit, GitHubContent, GitHubError, GitHubErrorKind, GitHubGraphQLError, GitHubIssue, GitHubRelease, GitHubRepository, GitTag, GraphQLDocument, GraphQLErrorEntry, Installation, InstallationToken, InvalidRepoRefError, IssueInfo, LinkedIssue, MergeMethod, PageOptions, PermissionGap, PermissionLevel, PermissionResult, PullRequest, PullRequestComment, PullRequestInfo, RateLimitSnapshot, ReleaseAsset, ReleaseInfo, Repo, RepoRef, RepositorySecret, RepositorySecurity, RepositoryVariable, RetryPolicy, Ruleset, SECURITY_ANALYSIS_STATUS_FIELDS, SemverTag, StorageRecordInput, TagRef, TokenPermissionError, TokenPermissions, WorkflowDispatch, WorkflowRunStatus, harvestIssueReferences, parseBareLineReference, repositoryPatch, transformSecurityAndAnalysis, versionFromTag };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@effected/github",
3
- "version": "0.7.0",
3
+ "version": "0.8.0",
4
4
  "private": false,
5
5
  "description": "Typed GitHub REST and GraphQL services over the octokit core request surface, with app auth and resource helpers.",
6
6
  "keywords": [
@@ -5,7 +5,7 @@
5
5
  "toolPackages": [
6
6
  {
7
7
  "packageName": "@microsoft/api-extractor",
8
- "packageVersion": "7.58.12"
8
+ "packageVersion": "7.59.0"
9
9
  }
10
10
  ]
11
11
  }