@shivaedev/github 0.9.0 → 0.11.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.
Files changed (152) hide show
  1. package/CHANGELOG.md +36 -0
  2. package/README.md +115 -7
  3. package/dist/GitHub.d.ts +279 -19
  4. package/dist/GitHub.d.ts.map +1 -1
  5. package/dist/GitHub.js +22 -10
  6. package/dist/GitHub.js.map +1 -1
  7. package/dist/adapters/manualRedirects.d.ts +4 -0
  8. package/dist/adapters/manualRedirects.d.ts.map +1 -0
  9. package/dist/adapters/manualRedirects.js +6 -0
  10. package/dist/adapters/manualRedirects.js.map +1 -0
  11. package/dist/adapters/mergeResponseHeaders.d.ts +3 -0
  12. package/dist/adapters/mergeResponseHeaders.d.ts.map +1 -0
  13. package/dist/adapters/mergeResponseHeaders.js +5 -0
  14. package/dist/adapters/mergeResponseHeaders.js.map +1 -0
  15. package/dist/adapters/resolveApiUrl.d.ts +2 -0
  16. package/dist/adapters/resolveApiUrl.d.ts.map +1 -0
  17. package/dist/adapters/resolveApiUrl.js +6 -0
  18. package/dist/adapters/resolveApiUrl.js.map +1 -0
  19. package/dist/adapters/signAppJwt.d.ts +5 -0
  20. package/dist/adapters/signAppJwt.d.ts.map +1 -0
  21. package/dist/adapters/signAppJwt.js +15 -0
  22. package/dist/adapters/signAppJwt.js.map +1 -0
  23. package/dist/adapters/verifySignature.d.ts +4 -0
  24. package/dist/adapters/verifySignature.d.ts.map +1 -0
  25. package/dist/adapters/verifySignature.js +13 -0
  26. package/dist/adapters/verifySignature.js.map +1 -0
  27. package/dist/adapters/zipEntries.d.ts +17 -0
  28. package/dist/adapters/zipEntries.d.ts.map +1 -0
  29. package/dist/adapters/zipEntries.js +57 -0
  30. package/dist/adapters/zipEntries.js.map +1 -0
  31. package/dist/appJwt.d.ts +2 -3
  32. package/dist/appJwt.d.ts.map +1 -1
  33. package/dist/appJwt.js +3 -12
  34. package/dist/appJwt.js.map +1 -1
  35. package/dist/appTokens.d.ts.map +1 -1
  36. package/dist/appTokens.js +2 -1
  37. package/dist/appTokens.js.map +1 -1
  38. package/dist/artifactErrors.d.ts +34 -0
  39. package/dist/artifactErrors.d.ts.map +1 -0
  40. package/dist/artifactErrors.js +27 -0
  41. package/dist/artifactErrors.js.map +1 -0
  42. package/dist/artifactExtraction.d.ts +12 -0
  43. package/dist/artifactExtraction.d.ts.map +1 -0
  44. package/dist/artifactExtraction.js +40 -0
  45. package/dist/artifactExtraction.js.map +1 -0
  46. package/dist/artifactPaths.d.ts +4 -0
  47. package/dist/artifactPaths.d.ts.map +1 -0
  48. package/dist/artifactPaths.js +35 -0
  49. package/dist/artifactPaths.js.map +1 -0
  50. package/dist/artifacts.d.ts +13 -8
  51. package/dist/artifacts.d.ts.map +1 -1
  52. package/dist/artifacts.js +18 -10
  53. package/dist/artifacts.js.map +1 -1
  54. package/dist/authenticatedRequest.d.ts +5 -5
  55. package/dist/authenticatedRequest.d.ts.map +1 -1
  56. package/dist/authenticatedRequest.js +6 -5
  57. package/dist/authenticatedRequest.js.map +1 -1
  58. package/dist/cache.d.ts.map +1 -1
  59. package/dist/cache.js +2 -1
  60. package/dist/cache.js.map +1 -1
  61. package/dist/checkRuns.d.ts +4 -4
  62. package/dist/checkRuns.d.ts.map +1 -1
  63. package/dist/checkRuns.js +5 -3
  64. package/dist/checkRuns.js.map +1 -1
  65. package/dist/errors.d.ts +8 -0
  66. package/dist/errors.d.ts.map +1 -1
  67. package/dist/errors.js +6 -0
  68. package/dist/errors.js.map +1 -1
  69. package/dist/gitSchemas.d.ts +195 -0
  70. package/dist/gitSchemas.d.ts.map +1 -0
  71. package/dist/gitSchemas.js +45 -0
  72. package/dist/gitSchemas.js.map +1 -0
  73. package/dist/installationClients.d.ts +291 -15
  74. package/dist/installationClients.d.ts.map +1 -1
  75. package/dist/installationClients.js +14 -5
  76. package/dist/installationClients.js.map +1 -1
  77. package/dist/markdown.d.ts +1 -0
  78. package/dist/markdown.d.ts.map +1 -1
  79. package/dist/markdown.js +3 -0
  80. package/dist/markdown.js.map +1 -1
  81. package/dist/markdownRows.d.ts +8 -1
  82. package/dist/markdownRows.d.ts.map +1 -1
  83. package/dist/markdownRows.js +39 -8
  84. package/dist/markdownRows.js.map +1 -1
  85. package/dist/pagedLists.d.ts +15 -0
  86. package/dist/pagedLists.d.ts.map +1 -0
  87. package/dist/pagedLists.js +16 -0
  88. package/dist/pagedLists.js.map +1 -0
  89. package/dist/repositoryAddress.d.ts +11 -0
  90. package/dist/repositoryAddress.d.ts.map +1 -0
  91. package/dist/repositoryAddress.js +23 -0
  92. package/dist/repositoryAddress.js.map +1 -0
  93. package/dist/repositoryReads.d.ts +262 -0
  94. package/dist/repositoryReads.d.ts.map +1 -0
  95. package/dist/repositoryReads.js +30 -0
  96. package/dist/repositoryReads.js.map +1 -0
  97. package/dist/repositorySchemas.d.ts +73 -0
  98. package/dist/repositorySchemas.d.ts.map +1 -0
  99. package/dist/repositorySchemas.js +38 -0
  100. package/dist/repositorySchemas.js.map +1 -0
  101. package/dist/representations.d.ts +5 -5
  102. package/dist/representations.d.ts.map +1 -1
  103. package/dist/representations.js +3 -2
  104. package/dist/representations.js.map +1 -1
  105. package/dist/requests.d.ts +10 -6
  106. package/dist/requests.d.ts.map +1 -1
  107. package/dist/requests.js +11 -6
  108. package/dist/requests.js.map +1 -1
  109. package/dist/status.d.ts +2 -2
  110. package/dist/status.d.ts.map +1 -1
  111. package/dist/status.js +2 -3
  112. package/dist/status.js.map +1 -1
  113. package/dist/stickyComments.d.ts +1 -1
  114. package/dist/verifyWebhook.d.ts +2 -2
  115. package/dist/verifyWebhook.d.ts.map +1 -1
  116. package/dist/verifyWebhook.js +3 -10
  117. package/dist/verifyWebhook.js.map +1 -1
  118. package/dist/viewerRepositoryAccess.d.ts +46 -0
  119. package/dist/viewerRepositoryAccess.d.ts.map +1 -0
  120. package/dist/viewerRepositoryAccess.js +54 -0
  121. package/dist/viewerRepositoryAccess.js.map +1 -0
  122. package/package.json +13 -6
  123. package/src/GitHub.ts +34 -15
  124. package/src/adapters/manualRedirects.ts +6 -0
  125. package/src/adapters/mergeResponseHeaders.ts +8 -0
  126. package/src/adapters/resolveApiUrl.ts +5 -0
  127. package/src/adapters/signAppJwt.ts +16 -0
  128. package/src/adapters/verifySignature.ts +13 -0
  129. package/src/adapters/zipEntries.ts +69 -0
  130. package/src/appJwt.ts +3 -12
  131. package/src/appTokens.ts +2 -1
  132. package/src/artifactErrors.ts +26 -0
  133. package/src/artifactExtraction.ts +62 -0
  134. package/src/artifactPaths.ts +36 -0
  135. package/src/artifacts.ts +35 -40
  136. package/src/authenticatedRequest.ts +8 -9
  137. package/src/cache.ts +2 -1
  138. package/src/checkRuns.ts +5 -5
  139. package/src/errors.ts +6 -0
  140. package/src/gitSchemas.ts +52 -0
  141. package/src/installationClients.ts +18 -12
  142. package/src/markdown.ts +4 -0
  143. package/src/markdownRows.ts +54 -9
  144. package/src/pagedLists.ts +40 -0
  145. package/src/repositoryAddress.ts +32 -0
  146. package/src/repositoryReads.ts +62 -0
  147. package/src/repositorySchemas.ts +43 -0
  148. package/src/representations.ts +6 -5
  149. package/src/requests.ts +12 -14
  150. package/src/status.ts +3 -3
  151. package/src/verifyWebhook.ts +4 -10
  152. package/src/viewerRepositoryAccess.ts +66 -0
package/dist/requests.js CHANGED
@@ -2,11 +2,16 @@ import { Effect } from "effect";
2
2
  import { HttpClient, HttpClientRequest } from "effect/http";
3
3
  import { readBoundedBody } from "@shivaedev/http/body.ts";
4
4
  import { ResponseBodyTooLarge } from "@shivaedev/http/errors.ts";
5
- import { authenticatedRequest } from "./authenticatedRequest.js";
6
- import { responseCache, revalidatedResponse } from "./cache.js";
7
- import { GitHubTransportError } from "./errors.js";
8
- import { isUnchanged } from "./status.js";
9
- export function requests(client, token, rates, refresh = undefined) {
5
+ import { authenticatedRequest } from "#authenticatedRequest.ts";
6
+ import { responseCache, revalidatedResponse } from "#cache.ts";
7
+ import { GitHubTransportError } from "#errors.ts";
8
+ import { GitHubToken } from "#GitHubToken.ts";
9
+ import { isUnchanged } from "#status.ts";
10
+ import { TokenRefresh } from "#TokenRefresh.ts";
11
+ export const requests = Effect.fnUntraced(function* (rates) {
12
+ const client = yield* HttpClient.HttpClient;
13
+ const token = yield* GitHubToken;
14
+ const refresh = yield* TokenRefresh;
10
15
  const cache = responseCache();
11
16
  const send = authenticatedRequest(HttpClient.withScope(client), token, rates, refresh);
12
17
  return Effect.fn("GitHub.request")(function* (input, limit) {
@@ -32,5 +37,5 @@ export function requests(client, token, rates, refresh = undefined) {
32
37
  }
33
38
  return entry;
34
39
  }, Effect.scoped);
35
- }
40
+ });
36
41
  //# sourceMappingURL=requests.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"requests.js","sourceRoot":"","sources":["../src/requests.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"requests.js","sourceRoot":"","sources":["../src/requests.ts"],"names":[],"mappings":"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"}
package/dist/status.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { Effect } from "effect";
2
- import { type HttpClientResponse } from "effect/http";
2
+ import type { HttpClientResponse } from "effect/http";
3
3
  import { GitHubConversationLocked, GitHubPermissionDenied, GitHubRateLimited } from "#errors.ts";
4
4
  export declare function isUnauthorized(response: HttpClientResponse.HttpClientResponse): boolean;
5
5
  export declare function isUnchanged(response: HttpClientResponse.HttpClientResponse): boolean;
6
- export declare const checkStatus: (response: HttpClientResponse.HttpClientResponse, resource: string, failures?: any) => Effect.Effect<HttpClientResponse.HttpClientResponse, GitHubConversationLocked | GitHubPermissionDenied | GitHubRateLimited | import("effect/http/HttpClientError").HttpClientError | import("@shivaedev/http/errors.ts").InvalidBodyLimit | import("@shivaedev/http/errors.ts").ResponseBodyTooLarge | import("@shivaedev/http/errors.ts").RemoteStatusError, never>;
6
+ export declare const checkStatus: (response: HttpClientResponse.HttpClientResponse, resource: string, failures?: any) => Effect.Effect<HttpClientResponse.HttpClientResponse, GitHubConversationLocked | GitHubPermissionDenied | GitHubRateLimited | import("effect/http/HttpClientError").HttpClientError | import("@shivaedev/http/errors.ts").InvalidBodyLimit | import("@shivaedev/http/errors.ts").RemoteGone | import("@shivaedev/http/errors.ts").RemoteHttpError | import("@shivaedev/http/errors.ts").RemoteNotFound | import("@shivaedev/http/errors.ts").RemoteRateLimited | import("@shivaedev/http/errors.ts").RemoteUnauthorized | import("@shivaedev/http/errors.ts").ResponseBodyTooLarge, never>;
7
7
  //# sourceMappingURL=status.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../src/status.ts"],"names":[],"mappings":"AAAA,OAAO,EAAY,MAAM,EAAkB,MAAM,QAAQ,CAAC;AAC1D,OAAO,EAAc,KAAK,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAKlE,OAAO,EAAE,wBAAwB,EAAE,sBAAsB,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAEjG,wBAAgB,cAAc,CAAC,QAAQ,EAAE,kBAAkB,CAAC,kBAAkB,WAE7E;AAED,wBAAgB,WAAW,CAAC,QAAQ,EAAE,kBAAkB,CAAC,kBAAkB,WAE1E;AAED,eAAO,MAAM,WAAW,6bAgBtB,CAAC"}
1
+ {"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../src/status.ts"],"names":[],"mappings":"AAAA,OAAO,EAAY,MAAM,EAAkB,MAAM,QAAQ,CAAC;AAC1D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAKtD,OAAO,EAAE,wBAAwB,EAAE,sBAAsB,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAEjG,wBAAgB,cAAc,CAAC,QAAQ,EAAE,kBAAkB,CAAC,kBAAkB,WAE7E;AAED,wBAAgB,WAAW,CAAC,QAAQ,EAAE,kBAAkB,CAAC,kBAAkB,WAE1E;AAED,eAAO,MAAM,WAAW,kpBAgBtB,CAAC"}
package/dist/status.js CHANGED
@@ -1,8 +1,7 @@
1
1
  import { DateTime, Effect, Option, Schema } from "effect";
2
- import { HttpClient } from "effect/http";
3
2
  import * as HttpStatus from "effect/http/HttpStatus";
4
3
  import { readBoundedText } from "@shivaedev/http/body.ts";
5
- import { filterStatus } from "@shivaedev/http/filterStatus.ts";
4
+ import { checkStatus as checkResponseStatus } from "@shivaedev/http/checkStatus.ts";
6
5
  import { parseRetryAfter } from "@shivaedev/http/parseRetryAfter.ts";
7
6
  import { GitHubConversationLocked, GitHubPermissionDenied, GitHubRateLimited } from "#errors.ts";
8
7
  export function isUnauthorized(response) {
@@ -25,7 +24,7 @@ export const checkStatus = Effect.fnUntraced(function* (response, resource, fail
25
24
  return yield* refusal;
26
25
  }
27
26
  }
28
- return yield* filterStatus(HttpClient.makeWith(() => Effect.succeed(response), Effect.succeed)).execute(response.request);
27
+ return yield* checkResponseStatus(response);
29
28
  });
30
29
  const Message = Schema.fromJsonString(Schema.Struct({ message: Schema.String }));
31
30
  const responseMessage = Effect.fnUntraced(function* (response) {
@@ -1 +1 @@
1
- {"version":3,"file":"status.js","sourceRoot":"","sources":["../src/status.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC1D,OAAO,EAAE,UAAU,EAA2B,MAAM,aAAa,CAAC;AAClE,OAAO,KAAK,UAAU,MAAM,wBAAwB,CAAC;AACrD,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC1D,OAAO,EAAE,YAAY,EAAE,MAAM,iCAAiC,CAAC;AAC/D,OAAO,EAAE,eAAe,EAAE,MAAM,oCAAoC,CAAC;AACrE,OAAO,EAAE,wBAAwB,EAAE,sBAAsB,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAEjG,MAAM,UAAU,cAAc,CAAC,QAA+C;IAC7E,OAAO,QAAQ,CAAC,MAAM,KAAK,UAAU,CAAC,WAAW,CAAC,cAAc,CAAC,CAAC;AACnE,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,QAA+C;IAC1E,OAAO,QAAQ,CAAC,MAAM,KAAK,UAAU,CAAC,WAAW,CAAC,aAAa,CAAC,CAAC;AAClE,CAAC;AAED,MAAM,CAAC,MAAM,WAAW,GAAG,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,QAA+C,EAAE,QAAgB,EAAE,QAAQ,GAAG,CAAC;IACtI,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,QAAQ,CAAC;IACrC,IAAI,MAAM,KAAK,UAAU,CAAC,WAAW,CAAC,WAAW,CAAC,IAAI,MAAM,KAAK,UAAU,CAAC,WAAW,CAAC,iBAAiB,CAAC,EAAE,CAAC;QAC5G,MAAM,gBAAgB,GACrB,MAAM,KAAK,UAAU,CAAC,WAAW,CAAC,iBAAiB,CAAC,IAAI,OAAO,CAAC,uBAAuB,CAAC,KAAK,GAAG,IAAI,OAAO,CAAC,aAAa,CAAC,KAAK,SAAS,CAAC;QAC1I,MAAM,OAAO,GAAG,CAAC,gBAAgB,IAAI,MAAM,KAAK,UAAU,CAAC,WAAW,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,eAAe,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QACnI,MAAM,gBAAgB,GAAG,OAAO,KAAK,SAAS,IAAI,cAAc,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAC/E,IAAI,gBAAgB,IAAI,gBAAgB,EAAE,CAAC;YAC1C,OAAO,KAAK,CAAC,CAAC,eAAe,CAAC,QAAQ,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAC;QAC7D,CAAC;QACD,MAAM,OAAO,GAAG,aAAa,CAAC,OAAO,EAAE,IAAI,GAAG,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAC;QAC/E,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;YAC3B,OAAO,KAAK,CAAC,CAAC,OAAO,CAAC;QACvB,CAAC;IACF,CAAC;IACD,OAAO,KAAK,CAAC,CAAC,YAAY,CAAC,UAAU,CAAC,QAAQ,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;AAC3H,CAAC,CAAC,CAAC;AAEH,MAAM,OAAO,GAAG,MAAM,CAAC,cAAc,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;AAEjF,MAAM,eAAe,GAAG,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,QAA+C;IACnG,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,eAAe,CAAC,QAAQ,EAAE,EAAE,GAAG,IAAI,CAAC,CAAC;IACzD,MAAM,IAAI,GAAG,MAAM,CAAC,mBAAmB,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC;IACvD,OAAO,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC;AAC7D,CAAC,CAAC,CAAC;AAEH,SAAS,aAAa,CAAC,OAA2B,EAAE,IAAY;IAC/D,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;QAC3B,OAAO,SAAS,CAAC;IAClB,CAAC;IACD,IAAI,4CAA4C,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;QAChE,OAAO,IAAI,sBAAsB,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC;IAC7C,CAAC;IACD,IAAI,2CAA2C,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;QAC/D,OAAO,IAAI,wBAAwB,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC;IAC/C,CAAC;IACD,OAAO,SAAS,CAAC;AAClB,CAAC;AAED,MAAM,eAAe,GAAG,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,QAA+C,EAAE,QAAgB,EAAE,QAAgB;IACvI,MAAM,EAAE,OAAO,EAAE,GAAG,QAAQ,CAAC;IAC7B,MAAM,GAAG,GAAG,KAAK,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC;IAChC,MAAM,KAAK,GAAG,MAAM,CAAC,OAAO,CAAC,mBAAmB,CAAC,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC;IAC/D,MAAM,QAAQ,GACb,OAAO,CAAC,uBAAuB,CAAC,KAAK,GAAG,IAAI,KAAK,GAAG,QAAQ,CAAC,aAAa,CAAC,GAAG,CAAC;QAC9E,CAAC,CAAC,KAAK;QACP,CAAC,CAAC,QAAQ,CAAC,aAAa,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,GAAG,MAAM,EAAE,MAAM,GAAG,CAAC,IAAI,QAAQ,CAAC,CAAC;IAChF,MAAM,OAAO,GAAG,eAAe,CAAC,OAAO,CAAC,aAAa,CAAC,EAAE,GAAG,CAAC,IAAI,QAAQ,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;IAC9F,OAAO,KAAK,CAAC,CAAC,IAAI,iBAAiB,CAAC,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAC;AAC5D,CAAC,CAAC,CAAC"}
1
+ {"version":3,"file":"status.js","sourceRoot":"","sources":["../src/status.ts"],"names":[],"mappings":"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"}
@@ -41,6 +41,6 @@ export declare function stickyComments(client: Representations): {
41
41
  readonly login: string;
42
42
  readonly type?: string | undefined;
43
43
  } | null;
44
- }, import("./errors.ts").GitHubAppError | import("./errors.ts").GitHubConversationLocked | import("./errors.ts").GitHubPermissionDenied | import("./errors.ts").GitHubRateLimited | import("./errors.ts").GitHubTransportError | import("effect/http/HttpBody").HttpBodyError | import("@shivaedev/http/errors.ts").InvalidBodyLimit | import("effect/Cause").NoSuchElementError | import("@shivaedev/http/errors.ts").PaginationLinkError | import("@shivaedev/http/errors.ts").ResponseBodyTooLarge | Schema.SchemaError | import("@shivaedev/errors/taxonomy.ts").ServiceUnavailable | import("@shivaedev/http/errors.ts").RemoteStatusError, never>;
44
+ }, import("./errors.ts").GitHubAppError | import("./errors.ts").GitHubConversationLocked | import("./errors.ts").GitHubPermissionDenied | import("./errors.ts").GitHubRateLimited | import("./errors.ts").GitHubTransportError | import("effect/http/HttpBody").HttpBodyError | import("@shivaedev/http/errors.ts").InvalidBodyLimit | import("effect/Cause").NoSuchElementError | import("@shivaedev/http/errors.ts").PaginationLinkError | import("@shivaedev/http/errors.ts").RemoteGone | import("@shivaedev/http/errors.ts").RemoteHttpError | import("@shivaedev/http/errors.ts").RemoteNotFound | import("@shivaedev/http/errors.ts").RemoteRateLimited | import("@shivaedev/http/errors.ts").RemoteUnauthorized | import("@shivaedev/http/errors.ts").ResponseBodyTooLarge | Schema.SchemaError | import("@shivaedev/errors/taxonomy.ts").ServiceUnavailable, never>;
45
45
  };
46
46
  //# sourceMappingURL=stickyComments.d.ts.map
@@ -1,5 +1,5 @@
1
- import { Effect, Redacted, Schema } from "effect";
2
- import { GitHubWebhookSignatureError } from "#errors.ts";
1
+ import { Effect, type Redacted, Schema } from "effect";
2
+ import type { GitHubWebhookSignatureError } from "#errors.ts";
3
3
  export declare function verifyWebhook(body: Uint8Array, signature: string | undefined, secret: Redacted.Redacted<string>): Effect.Effect<void, GitHubWebhookSignatureError>;
4
4
  export declare function verifyWebhook<TSchema extends Schema.Constraint>(body: Uint8Array, signature: string | undefined, secret: Redacted.Redacted<string>, schema: TSchema): Effect.Effect<TSchema["Type"], GitHubWebhookSignatureError | Schema.SchemaError, TSchema["DecodingServices"]>;
5
5
  //# sourceMappingURL=verifyWebhook.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"verifyWebhook.d.ts","sourceRoot":"","sources":["../src/verifyWebhook.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAClD,OAAO,EAAE,2BAA2B,EAAE,MAAM,YAAY,CAAC;AAqBzD,wBAAgB,aAAa,CAC5B,IAAI,EAAE,UAAU,EAChB,SAAS,EAAE,MAAM,GAAG,SAAS,EAC7B,MAAM,EAAE,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,GAC/B,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,2BAA2B,CAAC,CAAC;AACpD,wBAAgB,aAAa,CAAC,OAAO,SAAS,MAAM,CAAC,UAAU,EAC9D,IAAI,EAAE,UAAU,EAChB,SAAS,EAAE,MAAM,GAAG,SAAS,EAC7B,MAAM,EAAE,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,EACjC,MAAM,EAAE,OAAO,GACb,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,2BAA2B,GAAG,MAAM,CAAC,WAAW,EAAE,OAAO,CAAC,kBAAkB,CAAC,CAAC,CAAC"}
1
+ {"version":3,"file":"verifyWebhook.d.ts","sourceRoot":"","sources":["../src/verifyWebhook.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,KAAK,QAAQ,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAEvD,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,YAAY,CAAC;AAe9D,wBAAgB,aAAa,CAC5B,IAAI,EAAE,UAAU,EAChB,SAAS,EAAE,MAAM,GAAG,SAAS,EAC7B,MAAM,EAAE,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,GAC/B,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,2BAA2B,CAAC,CAAC;AACpD,wBAAgB,aAAa,CAAC,OAAO,SAAS,MAAM,CAAC,UAAU,EAC9D,IAAI,EAAE,UAAU,EAChB,SAAS,EAAE,MAAM,GAAG,SAAS,EAC7B,MAAM,EAAE,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,EACjC,MAAM,EAAE,OAAO,GACb,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,2BAA2B,GAAG,MAAM,CAAC,WAAW,EAAE,OAAO,CAAC,kBAAkB,CAAC,CAAC,CAAC"}
@@ -1,14 +1,7 @@
1
- import { createHmac, timingSafeEqual } from "node:crypto";
2
- import { Effect, Redacted, Schema } from "effect";
3
- import { GitHubWebhookSignatureError } from "#errors.ts";
1
+ import { Effect, Schema } from "effect";
2
+ import { verifySignature } from "#adapters/verifySignature.ts";
4
3
  const verify = Effect.fnUntraced(function* (body, signature, secret, schema) {
5
- if (signature === undefined || !/^sha256=[0-9a-f]{64}$/u.test(signature)) {
6
- return yield* new GitHubWebhookSignatureError();
7
- }
8
- const expected = createHmac("sha256", Redacted.value(secret)).update(body).digest();
9
- if (!timingSafeEqual(expected, Buffer.from(signature.slice(7), "hex"))) {
10
- return yield* new GitHubWebhookSignatureError();
11
- }
4
+ yield* verifySignature(body, signature, secret);
12
5
  if (schema === undefined) {
13
6
  return;
14
7
  }
@@ -1 +1 @@
1
- {"version":3,"file":"verifyWebhook.js","sourceRoot":"","sources":["../src/verifyWebhook.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC1D,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAClD,OAAO,EAAE,2BAA2B,EAAE,MAAM,YAAY,CAAC;AAEzD,MAAM,MAAM,GAAG,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,EACzC,IAAgB,EAChB,SAA6B,EAC7B,MAAiC,EACjC,MAAgB;IAEhB,IAAI,SAAS,KAAK,SAAS,IAAI,CAAC,wBAAwB,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC;QAC1E,OAAO,KAAK,CAAC,CAAC,IAAI,2BAA2B,EAAE,CAAC;IACjD,CAAC;IACD,MAAM,QAAQ,GAAG,UAAU,CAAC,QAAQ,EAAE,QAAQ,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,CAAC;IACpF,IAAI,CAAC,eAAe,CAAC,QAAQ,EAAE,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,EAAE,CAAC;QACxE,OAAO,KAAK,CAAC,CAAC,IAAI,2BAA2B,EAAE,CAAC;IACjD,CAAC;IACD,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;QAC1B,OAAO;IACR,CAAC;IACD,OAAO,KAAK,CAAC,CAAC,MAAM,CAAC,mBAAmB,CAAC,MAAM,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC;AACzG,CAAC,CAAC,CAAC;AAaH,MAAM,UAAU,aAAa,CAC5B,IAAgB,EAChB,SAA6B,EAC7B,MAAiC,EACjC,MAAgB;IAEhB,OAAO,MAAM,CAAC,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;AAChD,CAAC"}
1
+ {"version":3,"file":"verifyWebhook.js","sourceRoot":"","sources":["../src/verifyWebhook.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAiB,MAAM,EAAE,MAAM,QAAQ,CAAC;AACvD,OAAO,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAG/D,MAAM,MAAM,GAAG,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,EACzC,IAAgB,EAChB,SAA6B,EAC7B,MAAiC,EACjC,MAAgB;IAEhB,KAAK,CAAC,CAAC,eAAe,CAAC,IAAI,EAAE,SAAS,EAAE,MAAM,CAAC,CAAC;IAChD,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;QAC1B,OAAO;IACR,CAAC;IACD,OAAO,KAAK,CAAC,CAAC,MAAM,CAAC,mBAAmB,CAAC,MAAM,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC;AACzG,CAAC,CAAC,CAAC;AAaH,MAAM,UAAU,aAAa,CAC5B,IAAgB,EAChB,SAA6B,EAC7B,MAAiC,EACjC,MAAgB;IAEhB,OAAO,MAAM,CAAC,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;AAChD,CAAC"}
@@ -0,0 +1,46 @@
1
+ import { Cache, Effect, Schema } from "effect";
2
+ import type { Representations } from "#representations.ts";
3
+ export declare const InstalledRepository: Schema.encodeKeys<Schema.Struct<{
4
+ readonly htmlUrl: Schema.String;
5
+ readonly id: Schema.Number;
6
+ readonly name: Schema.String;
7
+ readonly owner: Schema.Struct<{
8
+ readonly login: Schema.String;
9
+ }>;
10
+ readonly private: Schema.Boolean;
11
+ }>, {
12
+ readonly htmlUrl: "html_url";
13
+ }>;
14
+ export interface ViewerRepositoryAccess {
15
+ readonly administrable: readonly (typeof InstalledRepository.Type & {
16
+ readonly installationId: number;
17
+ })[];
18
+ readonly readable: readonly (typeof InstalledRepository.Type & {
19
+ readonly installationId: number;
20
+ })[];
21
+ }
22
+ export declare function viewerRepositoryAccess(app: Representations, installation: (id: number) => Effect.Effect<Representations>): Effect.Effect<Cache.Cache<string, {
23
+ administrable: ({
24
+ readonly htmlUrl: string;
25
+ readonly id: number;
26
+ readonly name: string;
27
+ readonly owner: {
28
+ readonly login: string;
29
+ };
30
+ readonly private: boolean;
31
+ } & {
32
+ readonly installationId: number;
33
+ })[];
34
+ readable: ({
35
+ readonly htmlUrl: string;
36
+ readonly id: number;
37
+ readonly name: string;
38
+ readonly owner: {
39
+ readonly login: string;
40
+ };
41
+ readonly private: boolean;
42
+ } & {
43
+ readonly installationId: number;
44
+ })[];
45
+ }, import("./errors.ts").GitHubAppError | import("./errors.ts").GitHubConversationLocked | import("./errors.ts").GitHubPermissionDenied | import("./errors.ts").GitHubRateLimited | import("./errors.ts").GitHubTransportError | import("@shivaedev/http/errors.ts").InvalidBodyLimit | import("effect/Cause").NoSuchElementError | import("@shivaedev/http/errors.ts").PaginationLinkError | import("@shivaedev/http/errors.ts").RemoteGone | import("@shivaedev/http/errors.ts").RemoteHttpError | import("@shivaedev/http/errors.ts").RemoteNotFound | import("@shivaedev/http/errors.ts").RemoteRateLimited | import("@shivaedev/http/errors.ts").RemoteUnauthorized | import("@shivaedev/http/errors.ts").ResponseBodyTooLarge | Schema.SchemaError | import("@shivaedev/errors/taxonomy.ts").ServiceUnavailable, never>, never, never>;
46
+ //# sourceMappingURL=viewerRepositoryAccess.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"viewerRepositoryAccess.d.ts","sourceRoot":"","sources":["../src/viewerRepositoryAccess.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,EAAQ,MAAM,EAAU,MAAM,QAAQ,CAAC;AAE7D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAE3D,eAAO,MAAM,mBAAmB;;;;;;;;;;EAMmB,CAAC;AAEpD,MAAM,WAAW,sBAAsB;IACtC,QAAQ,CAAC,aAAa,EAAE,SAAS,CAAC,OAAO,mBAAmB,CAAC,IAAI,GAAG;QAAE,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAA;KAAE,CAAC,EAAE,CAAC;IAC3G,QAAQ,CAAC,QAAQ,EAAE,SAAS,CAAC,OAAO,mBAAmB,CAAC,IAAI,GAAG;QAAE,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAA;KAAE,CAAC,EAAE,CAAC;CACtG;AA6BD,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,eAAe,EAAE,YAAY,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,MAAM,CAAC,MAAM,CAAC,eAAe,CAAC;;;;;;;;;;iCA/BzB,MAAM;;;;;;;;;;;iCACX,MAAM;;6yBAmDhG"}
@@ -0,0 +1,54 @@
1
+ import { Cache, Effect, Exit, Schema, Stream } from "effect";
2
+ import { decodedPages } from "#pagedLists.ts";
3
+ export const InstalledRepository = Schema.Struct({
4
+ htmlUrl: Schema.String,
5
+ id: Schema.Number,
6
+ name: Schema.String,
7
+ owner: Schema.Struct({ login: Schema.String }),
8
+ private: Schema.Boolean,
9
+ }).pipe(Schema.encodeKeys({ htmlUrl: "html_url" }));
10
+ const Account = Schema.Struct({ login: Schema.String });
11
+ const Installation = Schema.Struct({ id: Schema.Number });
12
+ const Permission = Schema.Struct({ permission: Schema.String });
13
+ const installationAccess = Effect.fnUntraced(function* (client, installationId, login) {
14
+ const pages = yield* decodedPages(client, "/installation/repositories?per_page=100", InstalledRepository, {
15
+ arrayKey: "repositories",
16
+ }).pipe(Stream.runCollect);
17
+ const readable = [];
18
+ const administrable = [];
19
+ for (const repository of pages.flatMap((page) => page.items)) {
20
+ const permissionPath = `/repos/${encodeURIComponent(repository.owner.login)}/${encodeURIComponent(repository.name)}/collaborators/${encodeURIComponent(login)}/permission`;
21
+ const permission = yield* Effect.flatMap(client.read(permissionPath), (response) => response.decode(Permission)).pipe(Effect.map((grant) => grant.permission), Effect.catchTag("RemoteNotFound", () => Effect.succeed("none")));
22
+ const installed = { ...repository, installationId };
23
+ if (!repository.private || ["read", "triage", "write", "maintain", "admin"].includes(permission)) {
24
+ readable.push(installed);
25
+ }
26
+ if (permission === "admin") {
27
+ administrable.push(installed);
28
+ }
29
+ }
30
+ return { administrable, readable };
31
+ });
32
+ export function viewerRepositoryAccess(app, installation) {
33
+ const lookup = Effect.fnUntraced(function* (account) {
34
+ const path = account.startsWith("id:") ? `/user/${account.slice(3)}` : `/users/${encodeURIComponent(account.slice(6))}`;
35
+ const installations = yield* decodedPages(app, "/app/installations?per_page=100", Installation).pipe(Stream.runCollect);
36
+ const first = installations.flatMap((page) => page.items)[0];
37
+ if (first === undefined) {
38
+ return { administrable: [], readable: [] };
39
+ }
40
+ const resolver = yield* installation(first.id);
41
+ const { login } = yield* Effect.flatMap(resolver.read(path), (response) => response.decode(Account));
42
+ const readable = [];
43
+ const administrable = [];
44
+ for (const { id } of installations.flatMap((page) => page.items)) {
45
+ const client = yield* installation(id);
46
+ const access = yield* installationAccess(client, id, login);
47
+ readable.push(...access.readable);
48
+ administrable.push(...access.administrable);
49
+ }
50
+ return { administrable, readable };
51
+ });
52
+ return Cache.makeWith(lookup, { capacity: 100, timeToLive: (exit) => (Exit.isSuccess(exit) ? "60 seconds" : 0) });
53
+ }
54
+ //# sourceMappingURL=viewerRepositoryAccess.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"viewerRepositoryAccess.js","sourceRoot":"","sources":["../src/viewerRepositoryAccess.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shivaedev/github",
3
- "version": "0.9.0",
3
+ "version": "0.11.0",
4
4
  "description": "Typed GitHub REST requests, conditional reads and resource budgets for Effect applications",
5
5
  "keywords": [
6
6
  "effect"
@@ -43,25 +43,32 @@
43
43
  "README.md"
44
44
  ],
45
45
  "dependencies": {
46
- "@shivaedev/errors": "0.5.0",
47
- "@shivaedev/http": "0.4.0",
46
+ "@shivaedev/errors": "0.6.0",
47
+ "@shivaedev/http": "0.5.0",
48
48
  "@shivaedev/service": "0.6.1"
49
49
  },
50
50
  "devDependencies": {
51
51
  "@effect/platform-node": "4.0.6",
52
52
  "@effect/platform-node-shared": "4.0.6",
53
53
  "@effect/vitest": "4.0.6",
54
- "@shivaedev/quality": "0.55.0",
55
- "@shivaedev/test": "0.12.1",
56
- "@shivaedev/test-story": "0.33.0",
54
+ "@shivaedev/quality": "0.57.0",
55
+ "@shivaedev/test": "0.14.0",
56
+ "@shivaedev/test-story": "0.35.0",
57
57
  "@types/node": "24.19.2",
58
+ "@zip.js/zip.js": "2.24.0",
58
59
  "effect": "4.0.6",
59
60
  "typescript": "7.0.2",
60
61
  "vitest": "5.0.5"
61
62
  },
62
63
  "peerDependencies": {
64
+ "@zip.js/zip.js": "2.24.0",
63
65
  "effect": "4.0.6"
64
66
  },
67
+ "peerDependenciesMeta": {
68
+ "@zip.js/zip.js": {
69
+ "optional": true
70
+ }
71
+ },
65
72
  "engines": {
66
73
  "node": ">=24"
67
74
  },
package/src/GitHub.ts CHANGED
@@ -1,40 +1,46 @@
1
1
  import { Effect, Schema, Stream } from "effect";
2
2
  import { HttpClient } from "effect/http";
3
+ import type { ServiceUnavailable } from "@shivaedev/errors/taxonomy.ts";
3
4
  import { defineService } from "@shivaedev/service/defineService.ts";
5
+ import { genericMethod } from "@shivaedev/service/genericMethod.ts";
4
6
  import { artifacts } from "#artifacts.ts";
5
7
  import { checkRuns } from "#checkRuns.ts";
6
8
  import { GitHubConfig } from "#GitHubConfig.ts";
7
9
  import { GitHubToken } from "#GitHubToken.ts";
10
+ import { decodedPages, type ListOptions } from "#pagedLists.ts";
8
11
  import { rateLimits } from "#rateLimits.ts";
12
+ import { repositoryReads } from "#repositoryReads.ts";
9
13
  import { representations } from "#representations.ts";
10
14
  import { requests } from "#requests.ts";
11
15
  import { stickyComments } from "#stickyComments.ts";
12
- import { TokenRefresh } from "#TokenRefresh.ts";
13
16
 
14
17
  export const GitHub = defineService({
15
18
  id: "@shivaedev/github/GitHub",
16
19
  initialize: Effect.gen(function* () {
17
20
  const config = yield* GitHubConfig;
18
21
  const rates = rateLimits();
19
- const client = yield* HttpClient.HttpClient;
20
- const token = yield* GitHubToken;
21
- const refresh = yield* TokenRefresh;
22
22
  return {
23
23
  apiUrl: config.apiUrl,
24
- archive: artifacts(config.apiUrl, client, token, rates, refresh),
24
+ archive: yield* artifacts(config.apiUrl, rates),
25
25
  rates,
26
- request: requests(client, token, rates, refresh),
26
+ request: yield* requests(rates),
27
27
  responseByteLimit: config.responseByteLimit,
28
28
  };
29
29
  }),
30
30
  methods: ({ apiUrl, archive, rates, request, responseByteLimit }) => {
31
31
  const { get, ...client } = representations(apiUrl, request, rates.resource, responseByteLimit);
32
+ const reads = repositoryReads(client);
32
33
  return {
33
34
  bytes: (path: string, accept: string, limit: number) => Effect.map(request(get(path, accept), limit), (entry) => entry.bytes),
34
35
  ...client,
36
+ list: genericMethod(client.list),
35
37
  ...archive,
36
38
  ...stickyComments(client),
37
39
  ...checkRuns(client),
40
+ ...reads,
41
+ listCommits: genericMethod(reads.listCommits),
42
+ listIssues: genericMethod(reads.listIssues),
43
+ listPullRequestFiles: genericMethod(reads.listPullRequestFiles),
38
44
  observations: () => Effect.sync(() => [...rates.observations.values()]),
39
45
  resource: (path: string) => Effect.sync(() => rates.resource(new URL(path, apiUrl).pathname)),
40
46
  text: (path: string, accept: string, limit: number) =>
@@ -48,19 +54,32 @@ export function read<TSchema extends Schema.Constraint>(path: string, schema: TS
48
54
  return Effect.flatMap(GitHub, (github) => Effect.flatMap(github.read(path, responseByteLimit), (response) => response.decode(schema)));
49
55
  }
50
56
 
51
- export function list<TSchema extends Schema.Constraint>(path: string, schema: TSchema, responseByteLimit?: number) {
52
- return Stream.unwrap(Effect.flatMap(GitHub, (github) => github.list(path, undefined, responseByteLimit))).pipe(
53
- Stream.mapEffect((response) => response.decode(Schema.Array(schema))),
54
- Stream.flatMap(Stream.fromIterable),
55
- );
57
+ export function listPages<TSchema extends Schema.Constraint, E = ServiceUnavailable>(
58
+ path: string,
59
+ schema: TSchema,
60
+ options?: ListOptions<E> | number,
61
+ ) {
62
+ return Stream.unwrap(Effect.map(GitHub, (github) => decodedPages(github, path, schema, options)));
56
63
  }
57
64
 
58
- export function listBounded<TSchema extends Schema.Constraint>(path: string, schema: TSchema, pageCap: number, responseByteLimit?: number) {
59
- return Stream.unwrap(Effect.flatMap(GitHub, (github) => github.list(path, undefined, responseByteLimit))).pipe(
65
+ export function list<TSchema extends Schema.Constraint, E = ServiceUnavailable>(path: string, schema: TSchema, options?: ListOptions<E> | number) {
66
+ return listPages(path, schema, options).pipe(Stream.flatMap((page) => Stream.fromIterable(page.items)));
67
+ }
68
+
69
+ export function listBounded<TSchema extends Schema.Constraint, E = ServiceUnavailable>(
70
+ path: string,
71
+ schema: TSchema,
72
+ pageCap: number,
73
+ options?: ListOptions<E> | number,
74
+ ) {
75
+ return listPages(path, schema, options).pipe(
60
76
  Stream.take(pageCap),
61
- Stream.mapEffect((page) => Effect.map(page.decode(Schema.Array(schema)), (items) => ({ items, truncated: page.hasNext }))),
62
77
  Stream.runCollect,
63
- Effect.map((pages) => ({ items: pages.flatMap((page) => page.items), truncated: pages.at(-1)?.truncated ?? false })),
78
+ Effect.map((pages) => ({
79
+ items: pages.flatMap((page) => page.items),
80
+ skipped: pages.reduce((count, page) => count + page.skipped, 0),
81
+ truncated: pages.at(-1)?.hasNext ?? false,
82
+ })),
64
83
  );
65
84
  }
66
85
 
@@ -0,0 +1,6 @@
1
+ import { Effect } from "effect";
2
+ import { FetchHttpClient } from "effect/http";
3
+
4
+ export function manualRedirects<A, E, R>(request: Effect.Effect<A, E, R>) {
5
+ return request.pipe(Effect.provideService(FetchHttpClient.RequestInit, { credentials: "omit", redirect: "manual" }));
6
+ }
@@ -0,0 +1,8 @@
1
+ import { HttpClientResponse } from "effect/http";
2
+
3
+ export function mergeResponseHeaders(cached: HttpClientResponse.HttpClientResponse, response: HttpClientResponse.HttpClientResponse) {
4
+ return HttpClientResponse.fromWeb(
5
+ response.request,
6
+ new Response(null, { headers: { ...cached.headers, ...response.headers }, status: response.status }),
7
+ );
8
+ }
@@ -0,0 +1,5 @@
1
+ export function resolveApiUrl(apiUrl: string, path: string) {
2
+ const base = new URL(apiUrl);
3
+ base.pathname = `${base.pathname.replace(/\/$/u, "")}/`;
4
+ return new URL(path.replace(/^\/(?!\/)/u, ""), base).href;
5
+ }
@@ -0,0 +1,16 @@
1
+ import { sign } from "node:crypto";
2
+ import { Effect, Redacted } from "effect";
3
+ import type { AppCredentials } from "#appJwt.ts";
4
+ import { GitHubAppError } from "#errors.ts";
5
+
6
+ export function signAppJwt(options: AppCredentials, now: number) {
7
+ return Effect.try({
8
+ catch: (cause) => new GitHubAppError({ reason: "sign" }, { cause }),
9
+ try: () => {
10
+ const header = Buffer.from(JSON.stringify({ alg: "RS256", typ: "JWT" })).toString("base64url");
11
+ const payload = Buffer.from(JSON.stringify({ exp: now + 600, iat: now - 60, iss: options.appId })).toString("base64url");
12
+ const input = `${header}.${payload}`;
13
+ return Redacted.make(`${input}.${sign("RSA-SHA256", Buffer.from(input), Redacted.value(options.privateKey)).toString("base64url")}`);
14
+ },
15
+ });
16
+ }
@@ -0,0 +1,13 @@
1
+ import { createHmac, timingSafeEqual } from "node:crypto";
2
+ import { Effect, Redacted } from "effect";
3
+ import { GitHubWebhookSignatureError } from "#errors.ts";
4
+
5
+ export const verifySignature = Effect.fnUntraced(function* (body: Uint8Array, signature: string | undefined, secret: Redacted.Redacted<string>) {
6
+ if (signature === undefined || !/^sha256=[0-9a-f]{64}$/u.test(signature)) {
7
+ return yield* new GitHubWebhookSignatureError();
8
+ }
9
+ const expected = createHmac("sha256", Redacted.value(secret)).update(body).digest();
10
+ if (!timingSafeEqual(expected, Buffer.from(signature.slice(7), "hex"))) {
11
+ return yield* new GitHubWebhookSignatureError();
12
+ }
13
+ });
@@ -0,0 +1,69 @@
1
+ import type { Entry } from "@zip.js/zip.js";
2
+ import { Effect, Stream } from "effect";
3
+ import { GitHubArtifactCompressionRatio, GitHubArtifactExtractedTooLarge, GitHubArtifactExtractionError } from "#artifactErrors.ts";
4
+
5
+ interface ReadLimits {
6
+ readonly compressionRatioLimit: number;
7
+ readonly remaining: number;
8
+ readonly totalSizeLimit: number;
9
+ }
10
+
11
+ function invalidArchive() {
12
+ return new GitHubArtifactExtractionError({ reason: "invalid-archive" });
13
+ }
14
+
15
+ function readEntry(entry: Entry, limits: ReadLimits) {
16
+ return Effect.tryPromise({
17
+ catch: (error) =>
18
+ error instanceof GitHubArtifactExtractedTooLarge || error instanceof GitHubArtifactCompressionRatio ? error : invalidArchive(),
19
+ try: async (signal) => {
20
+ let size = 0;
21
+ const chunks: Uint8Array[] = [];
22
+ const output = new WritableStream<Uint8Array>({
23
+ write(chunk) {
24
+ size += chunk.byteLength;
25
+ if (size > limits.remaining) {
26
+ throw new GitHubArtifactExtractedTooLarge({ limit: limits.totalSizeLimit });
27
+ }
28
+ if (size > entry.compressedSize * limits.compressionRatioLimit) {
29
+ throw new GitHubArtifactCompressionRatio({ limit: limits.compressionRatioLimit, path: entry.filename });
30
+ }
31
+ chunks.push(chunk);
32
+ },
33
+ });
34
+ if (!entry.directory) {
35
+ await entry.getData(output, { signal });
36
+ }
37
+ const result = new Uint8Array(size);
38
+ let offset = 0;
39
+ for (const chunk of chunks) {
40
+ result.set(chunk, offset);
41
+ offset += chunk.byteLength;
42
+ }
43
+ return result;
44
+ },
45
+ });
46
+ }
47
+
48
+ export const zipEntries = Effect.fn("GitHub.zipEntries")(function* (bytes: Uint8Array) {
49
+ const { ZipReader, Uint8ArrayReader } = yield* Effect.tryPromise({
50
+ catch: () => new GitHubArtifactExtractionError({ reason: "reader-unavailable" }),
51
+ try: () => import("@zip.js/zip.js"),
52
+ });
53
+ const reader = new ZipReader(new Uint8ArrayReader(bytes), {
54
+ checkCrc32: true,
55
+ // Core validates paths so refusals retain their dedicated typed error.
56
+ filenameValidation: "tolerant",
57
+ useWebWorkers: false,
58
+ });
59
+ return Stream.fromAsyncIterable(reader.getEntriesGenerator(), invalidArchive).pipe(
60
+ Stream.map((entry) => ({
61
+ compressedSize: entry.compressedSize,
62
+ directory: entry.directory,
63
+ path: entry.filename,
64
+ read: (limits: ReadLimits) => readEntry(entry, limits),
65
+ symlink: entry.symlink,
66
+ uncompressedSize: entry.uncompressedSize,
67
+ })),
68
+ );
69
+ });
package/src/appJwt.ts CHANGED
@@ -1,6 +1,5 @@
1
- import { sign } from "node:crypto";
2
- import { Clock, Effect, Redacted } from "effect";
3
- import { GitHubAppError } from "#errors.ts";
1
+ import { Clock, Effect, type Redacted } from "effect";
2
+ import { signAppJwt } from "#adapters/signAppJwt.ts";
4
3
 
5
4
  export interface AppCredentials {
6
5
  readonly appId: string;
@@ -9,13 +8,5 @@ export interface AppCredentials {
9
8
 
10
9
  export const appJwt = Effect.fnUntraced(function* (options: AppCredentials) {
11
10
  const now = Math.floor((yield* Clock.currentTimeMillis) / 1000);
12
- return yield* Effect.try({
13
- catch: (cause) => new GitHubAppError({ reason: "sign" }, { cause }),
14
- try: () => {
15
- const header = Buffer.from(JSON.stringify({ alg: "RS256", typ: "JWT" })).toString("base64url");
16
- const payload = Buffer.from(JSON.stringify({ exp: now + 600, iat: now - 60, iss: options.appId })).toString("base64url");
17
- const input = `${header}.${payload}`;
18
- return Redacted.make(`${input}.${sign("RSA-SHA256", Buffer.from(input), Redacted.value(options.privateKey)).toString("base64url")}`);
19
- },
20
- });
11
+ return yield* signAppJwt(options, now);
21
12
  });
package/src/appTokens.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  import { Cache, Clock, Context, Effect, Exit, Layer, Option, type Redacted, Schema } from "effect";
2
2
  import { HttpClient, HttpClientRequest } from "effect/http";
3
3
  import { readBoundedJson } from "@shivaedev/http/body.ts";
4
+ import { resolveApiUrl } from "#adapters/resolveApiUrl.ts";
4
5
  import { appJwt } from "#appJwt.ts";
5
6
  import { authenticatedRequest } from "#authenticatedRequest.ts";
6
7
  import { GitHubAppError } from "#errors.ts";
@@ -65,7 +66,7 @@ function appRequests(client: HttpClient.HttpClient, apiUrl: string) {
65
66
  schema: TSchema,
66
67
  body?: unknown,
67
68
  ) {
68
- let input = HttpClientRequest.make(method)(new URL(path, apiUrl).href, {
69
+ let input = HttpClientRequest.make(method)(resolveApiUrl(apiUrl, path), {
69
70
  headers: { Accept: "application/vnd.github+json" },
70
71
  });
71
72
  if (body !== undefined) {
@@ -0,0 +1,26 @@
1
+ import { Schema } from "effect";
2
+
3
+ export class GitHubArtifactPathTraversal extends Schema.TaggedError<GitHubArtifactPathTraversal>()("GitHubArtifactPathTraversal", {
4
+ path: Schema.String,
5
+ }) {}
6
+
7
+ export class GitHubArtifactSymlink extends Schema.TaggedError<GitHubArtifactSymlink>()("GitHubArtifactSymlink", {
8
+ path: Schema.String,
9
+ }) {}
10
+
11
+ export class GitHubArtifactDuplicateEntry extends Schema.TaggedError<GitHubArtifactDuplicateEntry>()("GitHubArtifactDuplicateEntry", {
12
+ path: Schema.String,
13
+ }) {}
14
+
15
+ export class GitHubArtifactCompressionRatio extends Schema.TaggedError<GitHubArtifactCompressionRatio>()("GitHubArtifactCompressionRatio", {
16
+ limit: Schema.Number,
17
+ path: Schema.String,
18
+ }) {}
19
+
20
+ export class GitHubArtifactExtractedTooLarge extends Schema.TaggedError<GitHubArtifactExtractedTooLarge>()("GitHubArtifactExtractedTooLarge", {
21
+ limit: Schema.Number,
22
+ }) {}
23
+
24
+ export class GitHubArtifactExtractionError extends Schema.TaggedError<GitHubArtifactExtractionError>()("GitHubArtifactExtractionError", {
25
+ reason: Schema.Literals(["reader-unavailable", "invalid-archive", "invalid-limits"]),
26
+ }) {}