repo-sdk 0.1.1 → 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/azure-devops.d.ts +1 -1
- package/dist/azure-devops.js +1 -1
- package/dist/bitbucket.d.ts +1 -1
- package/dist/bitbucket.js +1 -1
- package/dist/git-http.d.ts +1 -1
- package/dist/git-http.js +1 -1
- package/dist/gitea.d.ts +1 -1
- package/dist/gitea.js +1 -1
- package/dist/github.d.ts +36 -2
- package/dist/github.js +72 -20
- package/dist/gitlab.d.ts +1 -1
- package/dist/gitlab.js +1 -1
- package/dist/{shared-CuiOaaLD.js → http-C3hAQeY0.js} +34 -32
- package/dist/index.d.ts +2 -2
- package/dist/index.js +46 -14
- package/dist/testing.d.ts +1 -1
- package/dist/{types-CTeiAxMy.d.ts → types-DfiRluvJ.d.ts} +8 -3
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -74,7 +74,7 @@ npm install
|
|
|
74
74
|
| `npm run test:live` | Gated live provider tests (env vars documented in CONTRIBUTING) |
|
|
75
75
|
| `npm run typecheck` | Type-check without emitting |
|
|
76
76
|
| `npm run lint` | Lint the codebase |
|
|
77
|
-
| `npm run
|
|
77
|
+
| `npm run fmt` | Format with prettier |
|
|
78
78
|
|
|
79
79
|
Docs site:
|
|
80
80
|
|
package/dist/azure-devops.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { B as TokenProvider, F as RepoProvider, O as ParsedWebhookEvent, v as IncomingWebhookRequest } from "./types-DfiRluvJ.js";
|
|
2
2
|
import { t as VerifyWebhookParams$1 } from "./verify-p6JsExms.js";
|
|
3
3
|
//#region src/providers/azure-devops/auth.d.ts
|
|
4
4
|
/**
|
package/dist/azure-devops.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { t as RepoError } from "./errors-Cxq_CqYv.js";
|
|
2
2
|
import { n as decodeCursor, r as encodeCursor } from "./pagination-CWWHSu8I.js";
|
|
3
|
-
import { a as
|
|
3
|
+
import { a as filenameFromContentDisposition, o as isRecord, r as commitWebUrlBuilder, t as HttpClient } from "./http-C3hAQeY0.js";
|
|
4
4
|
import { a as headShaOrUndefined, n as timingSafeEqual, r as toIncomingWebhook } from "./verify-BBMVxz8q.js";
|
|
5
5
|
//#region src/providers/azure-devops/auth.ts
|
|
6
6
|
/**
|
package/dist/bitbucket.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { B as TokenProvider, F as RepoProvider, O as ParsedWebhookEvent, v as IncomingWebhookRequest } from "./types-DfiRluvJ.js";
|
|
2
2
|
import { t as VerifyWebhookParams } from "./verify-p6JsExms.js";
|
|
3
3
|
//#region src/providers/bitbucket/index.d.ts
|
|
4
4
|
interface BitbucketProviderOptions {
|
package/dist/bitbucket.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { t as RepoError } from "./errors-Cxq_CqYv.js";
|
|
2
2
|
import { n as decodeCursor, r as encodeCursor, t as assertSameOriginUrl } from "./pagination-CWWHSu8I.js";
|
|
3
|
-
import { a as
|
|
3
|
+
import { a as filenameFromContentDisposition, n as clampPerPage, o as isRecord, r as commitWebUrlBuilder, t as HttpClient } from "./http-C3hAQeY0.js";
|
|
4
4
|
import { a as headShaOrUndefined, i as verifyHmacSignature, r as toIncomingWebhook } from "./verify-BBMVxz8q.js";
|
|
5
5
|
//#region src/providers/bitbucket/index.ts
|
|
6
6
|
const BASE_URL = "https://api.bitbucket.org/2.0";
|
package/dist/git-http.d.ts
CHANGED
package/dist/git-http.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { t as RepoError } from "./errors-Cxq_CqYv.js";
|
|
2
2
|
import { a as stringToBase64, n as decodeCursor, r as encodeCursor } from "./pagination-CWWHSu8I.js";
|
|
3
|
-
import {
|
|
3
|
+
import { n as clampPerPage, t as HttpClient } from "./http-C3hAQeY0.js";
|
|
4
4
|
//#region src/providers/git-http/index.ts
|
|
5
5
|
const CAPABILITIES = {
|
|
6
6
|
userProfile: false,
|
package/dist/gitea.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { B as TokenProvider, F as RepoProvider, O as ParsedWebhookEvent, v as IncomingWebhookRequest } from "./types-DfiRluvJ.js";
|
|
2
2
|
import { t as VerifyWebhookParams } from "./verify-p6JsExms.js";
|
|
3
3
|
//#region src/providers/gitea/index.d.ts
|
|
4
4
|
interface GiteaProviderOptions {
|
package/dist/gitea.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { t as RepoError } from "./errors-Cxq_CqYv.js";
|
|
2
2
|
import { n as decodeCursor, r as encodeCursor, t as assertSameOriginUrl } from "./pagination-CWWHSu8I.js";
|
|
3
|
-
import { a as
|
|
3
|
+
import { a as filenameFromContentDisposition, i as encodeRefPath, n as clampPerPage, o as isRecord, r as commitWebUrlBuilder, s as parseLinkNext, t as HttpClient } from "./http-C3hAQeY0.js";
|
|
4
4
|
import { a as headShaOrUndefined, n as timingSafeEqual, r as toIncomingWebhook, t as hmacSha256Hex } from "./verify-BBMVxz8q.js";
|
|
5
5
|
//#region src/providers/gitea/index.ts
|
|
6
6
|
const DEFAULT_BASE_URL = "https://gitea.com/api/v1";
|
package/dist/github.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { B as TokenProvider, D as Page, F as RepoProvider, O as ParsedWebhookEvent, v as IncomingWebhookRequest } from "./types-DfiRluvJ.js";
|
|
2
2
|
import { t as VerifyWebhookParams } from "./verify-p6JsExms.js";
|
|
3
3
|
//#region src/providers/github/app-auth.d.ts
|
|
4
4
|
interface InstallationToken {
|
|
@@ -43,8 +43,42 @@ interface GitHubRepoProvider extends RepoProvider {
|
|
|
43
43
|
declare const commitWebUrl: (repoWebUrl: string, sha: string) => string;
|
|
44
44
|
declare function github(options: GitHubProviderOptions): GitHubRepoProvider;
|
|
45
45
|
//#endregion
|
|
46
|
+
//#region src/providers/github/installations.d.ts
|
|
47
|
+
interface ListUserInstallationsParams {
|
|
48
|
+
/**
|
|
49
|
+
* A user access token — e.g. the OAuth token minted by the GitHub App web
|
|
50
|
+
* login flow. Installation tokens cannot call this endpoint.
|
|
51
|
+
*/
|
|
52
|
+
token: string;
|
|
53
|
+
/** GHES API root (`/api/v3`); defaults to `https://api.github.com`. */
|
|
54
|
+
baseUrl?: string;
|
|
55
|
+
fetch?: typeof fetch;
|
|
56
|
+
limit?: number;
|
|
57
|
+
cursor?: string;
|
|
58
|
+
signal?: AbortSignal;
|
|
59
|
+
}
|
|
60
|
+
interface GitHubInstallationAccount {
|
|
61
|
+
id: string;
|
|
62
|
+
login: string;
|
|
63
|
+
kind: 'user' | 'organization';
|
|
64
|
+
avatarUrl?: string;
|
|
65
|
+
}
|
|
66
|
+
interface GitHubUserInstallation {
|
|
67
|
+
id: string;
|
|
68
|
+
/** Account the app is installed on; absent for enterprise-level installations. */
|
|
69
|
+
account?: GitHubInstallationAccount;
|
|
70
|
+
raw: unknown;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Lists the GitHub App installations the given user can access
|
|
74
|
+
* (`GET /user/installations`). Standalone by design: the endpoint requires a
|
|
75
|
+
* user access token, a different credential from the installation token the
|
|
76
|
+
* `github` provider authenticates its requests with.
|
|
77
|
+
*/
|
|
78
|
+
declare function listUserInstallations(params: ListUserInstallationsParams): Promise<Page<GitHubUserInstallation>>;
|
|
79
|
+
//#endregion
|
|
46
80
|
//#region src/providers/github/webhooks.d.ts
|
|
47
81
|
declare function verifyWebhook(params: VerifyWebhookParams): Promise<boolean>;
|
|
48
82
|
declare function parseWebhookEvent(input: Request | IncomingWebhookRequest): Promise<ParsedWebhookEvent>;
|
|
49
83
|
//#endregion
|
|
50
|
-
export { type GitHubAppAuth, type GitHubAuth, type GitHubInstallationToken, type GitHubProviderOptions, type GitHubRepoProvider, type GitHubTokenAuth, type VerifyWebhookParams, commitWebUrl, github, parseWebhookEvent, verifyWebhook };
|
|
84
|
+
export { type GitHubAppAuth, type GitHubAuth, type GitHubInstallationAccount, type GitHubInstallationToken, type GitHubProviderOptions, type GitHubRepoProvider, type GitHubTokenAuth, type GitHubUserInstallation, type ListUserInstallationsParams, type VerifyWebhookParams, commitWebUrl, github, listUserInstallations, parseWebhookEvent, verifyWebhook };
|
package/dist/github.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { n as codeFromStatus, t as RepoError } from "./errors-Cxq_CqYv.js";
|
|
2
2
|
import { i as bytesToBase64Url, n as decodeCursor, r as encodeCursor, t as assertSameOriginUrl } from "./pagination-CWWHSu8I.js";
|
|
3
|
-
import { a as
|
|
3
|
+
import { a as filenameFromContentDisposition, i as encodeRefPath, n as clampPerPage, o as isRecord, r as commitWebUrlBuilder, s as parseLinkNext, t as HttpClient } from "./http-C3hAQeY0.js";
|
|
4
4
|
import { a as headShaOrUndefined, i as verifyHmacSignature, r as toIncomingWebhook } from "./verify-BBMVxz8q.js";
|
|
5
5
|
//#region src/providers/github/app-auth.ts
|
|
6
6
|
const RSA_ALGORITHM_IDENTIFIER = [
|
|
@@ -205,9 +205,10 @@ var AppTokenSource = class {
|
|
|
205
205
|
}
|
|
206
206
|
async appRequest(path, method, jwt) {
|
|
207
207
|
const url = joinUrl(this.baseUrl, path);
|
|
208
|
+
const { fetchImpl } = this;
|
|
208
209
|
let response;
|
|
209
210
|
try {
|
|
210
|
-
response = await
|
|
211
|
+
response = await fetchImpl(url, {
|
|
211
212
|
method,
|
|
212
213
|
headers: {
|
|
213
214
|
Authorization: `Bearer ${jwt}`,
|
|
@@ -242,11 +243,23 @@ var AppTokenSource = class {
|
|
|
242
243
|
});
|
|
243
244
|
}
|
|
244
245
|
};
|
|
245
|
-
//#endregion
|
|
246
|
-
//#region src/providers/github/index.ts
|
|
247
|
-
const DEFAULT_BASE_URL = "https://api.github.com";
|
|
248
246
|
const API_VERSION = "2022-11-28";
|
|
249
247
|
const USER_AGENT = "repo-sdk";
|
|
248
|
+
function mapError(status, body, response) {
|
|
249
|
+
const message = isRecord(body) && typeof body.message === "string" ? body.message : void 0;
|
|
250
|
+
let code;
|
|
251
|
+
if (status === 429 || status === 403 && response.headers.get("x-ratelimit-remaining") === "0") code = "rate_limited";
|
|
252
|
+
return {
|
|
253
|
+
code,
|
|
254
|
+
message
|
|
255
|
+
};
|
|
256
|
+
}
|
|
257
|
+
function nextCursor(response) {
|
|
258
|
+
const next = parseLinkNext(response.headers.get("link"));
|
|
259
|
+
return next === void 0 ? void 0 : encodeCursor("github", { url: next });
|
|
260
|
+
}
|
|
261
|
+
//#endregion
|
|
262
|
+
//#region src/providers/github/index.ts
|
|
250
263
|
const CAPABILITIES = {
|
|
251
264
|
tagDates: false,
|
|
252
265
|
repoSearch: true,
|
|
@@ -297,10 +310,6 @@ function createTokenSource(auth, baseUrl, fetchImpl) {
|
|
|
297
310
|
userAgent: USER_AGENT
|
|
298
311
|
});
|
|
299
312
|
}
|
|
300
|
-
function nextCursor(response) {
|
|
301
|
-
const next = parseLinkNext(response.headers.get("link"));
|
|
302
|
-
return next === void 0 ? void 0 : encodeCursor("github", { url: next });
|
|
303
|
-
}
|
|
304
313
|
function gitHostFromBaseUrl(baseUrl) {
|
|
305
314
|
const url = new URL(baseUrl);
|
|
306
315
|
return url.hostname === "api.github.com" ? "github.com" : url.host;
|
|
@@ -410,22 +419,13 @@ function toWebhook(hook) {
|
|
|
410
419
|
raw: hook
|
|
411
420
|
};
|
|
412
421
|
}
|
|
413
|
-
function mapError(status, body, response) {
|
|
414
|
-
const message = isRecord(body) && typeof body.message === "string" ? body.message : void 0;
|
|
415
|
-
let code;
|
|
416
|
-
if (status === 429 || status === 403 && response.headers.get("x-ratelimit-remaining") === "0") code = "rate_limited";
|
|
417
|
-
return {
|
|
418
|
-
code,
|
|
419
|
-
message
|
|
420
|
-
};
|
|
421
|
-
}
|
|
422
422
|
/**
|
|
423
423
|
* Builds the human-facing web URL for a commit from the repository's web URL
|
|
424
424
|
* (`Repository.urls.web`) and a commit SHA — no API request needed.
|
|
425
425
|
*/
|
|
426
426
|
const commitWebUrl = commitWebUrlBuilder("commit");
|
|
427
427
|
function github(options) {
|
|
428
|
-
const baseUrl = options.baseUrl ??
|
|
428
|
+
const baseUrl = options.baseUrl ?? "https://api.github.com";
|
|
429
429
|
const fetchImpl = options.fetch ?? fetch;
|
|
430
430
|
const tokenSource = createTokenSource(options.auth, baseUrl, fetchImpl);
|
|
431
431
|
const webBase = `https://${gitHostFromBaseUrl(baseUrl)}`;
|
|
@@ -863,6 +863,58 @@ function github(options) {
|
|
|
863
863
|
};
|
|
864
864
|
}
|
|
865
865
|
//#endregion
|
|
866
|
+
//#region src/providers/github/installations.ts
|
|
867
|
+
function toInstallation(payload) {
|
|
868
|
+
const account = payload.account;
|
|
869
|
+
return {
|
|
870
|
+
id: String(payload.id),
|
|
871
|
+
account: account?.login === void 0 ? void 0 : {
|
|
872
|
+
id: String(account.id),
|
|
873
|
+
login: account.login,
|
|
874
|
+
kind: account.type === "Organization" ? "organization" : "user",
|
|
875
|
+
avatarUrl: account.avatar_url
|
|
876
|
+
},
|
|
877
|
+
raw: payload
|
|
878
|
+
};
|
|
879
|
+
}
|
|
880
|
+
/**
|
|
881
|
+
* Lists the GitHub App installations the given user can access
|
|
882
|
+
* (`GET /user/installations`). Standalone by design: the endpoint requires a
|
|
883
|
+
* user access token, a different credential from the installation token the
|
|
884
|
+
* `github` provider authenticates its requests with.
|
|
885
|
+
*/
|
|
886
|
+
async function listUserInstallations(params) {
|
|
887
|
+
const { token } = params;
|
|
888
|
+
const baseUrl = params.baseUrl ?? "https://api.github.com";
|
|
889
|
+
const http = new HttpClient({
|
|
890
|
+
provider: "github",
|
|
891
|
+
baseUrl,
|
|
892
|
+
fetchImpl: params.fetch,
|
|
893
|
+
authHeaders: () => ({
|
|
894
|
+
Authorization: `Bearer ${token}`,
|
|
895
|
+
Accept: "application/vnd.github+json",
|
|
896
|
+
"X-GitHub-Api-Version": API_VERSION,
|
|
897
|
+
"User-Agent": USER_AGENT
|
|
898
|
+
}),
|
|
899
|
+
mapError,
|
|
900
|
+
secrets: () => [token]
|
|
901
|
+
});
|
|
902
|
+
let path = "/user/installations";
|
|
903
|
+
let query;
|
|
904
|
+
if (params.cursor) {
|
|
905
|
+
const { url } = decodeCursor("github", params.cursor);
|
|
906
|
+
path = assertSameOriginUrl("github", baseUrl, url);
|
|
907
|
+
} else query = { per_page: clampPerPage(params.limit) };
|
|
908
|
+
const { data, response } = await http.json(path, {
|
|
909
|
+
query,
|
|
910
|
+
signal: params.signal
|
|
911
|
+
});
|
|
912
|
+
return {
|
|
913
|
+
data: (data.installations ?? []).map(toInstallation),
|
|
914
|
+
cursor: nextCursor(response)
|
|
915
|
+
};
|
|
916
|
+
}
|
|
917
|
+
//#endregion
|
|
866
918
|
//#region src/providers/github/webhooks.ts
|
|
867
919
|
function verifyWebhook(params) {
|
|
868
920
|
return verifyHmacSignature(params, { header: "x-hub-signature-256" });
|
|
@@ -897,4 +949,4 @@ async function parseWebhookEvent(input) {
|
|
|
897
949
|
};
|
|
898
950
|
}
|
|
899
951
|
//#endregion
|
|
900
|
-
export { commitWebUrl, github, parseWebhookEvent, verifyWebhook };
|
|
952
|
+
export { commitWebUrl, github, listUserInstallations, parseWebhookEvent, verifyWebhook };
|
package/dist/gitlab.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { B as TokenProvider, F as RepoProvider, O as ParsedWebhookEvent, v as IncomingWebhookRequest } from "./types-DfiRluvJ.js";
|
|
2
2
|
import { t as VerifyWebhookParams } from "./verify-p6JsExms.js";
|
|
3
3
|
//#region src/providers/gitlab/index.d.ts
|
|
4
4
|
interface GitLabProviderOptions {
|
package/dist/gitlab.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { t as RepoError } from "./errors-Cxq_CqYv.js";
|
|
2
2
|
import { n as decodeCursor, r as encodeCursor, t as assertSameOriginUrl } from "./pagination-CWWHSu8I.js";
|
|
3
|
-
import { a as
|
|
3
|
+
import { a as filenameFromContentDisposition, n as clampPerPage, o as isRecord, r as commitWebUrlBuilder, s as parseLinkNext, t as HttpClient } from "./http-C3hAQeY0.js";
|
|
4
4
|
import { a as headShaOrUndefined, n as timingSafeEqual, r as toIncomingWebhook } from "./verify-BBMVxz8q.js";
|
|
5
5
|
//#region src/providers/gitlab/index.ts
|
|
6
6
|
const DEFAULT_BASE_URL = "https://gitlab.com/api/v4";
|
|
@@ -1,5 +1,37 @@
|
|
|
1
1
|
import { n as codeFromStatus, r as parseRetryAfter, t as RepoError } from "./errors-Cxq_CqYv.js";
|
|
2
|
+
//#region src/providers/shared.ts
|
|
3
|
+
function isRecord(value) {
|
|
4
|
+
return typeof value === "object" && value !== null;
|
|
5
|
+
}
|
|
6
|
+
function clampPerPage(limit, max = 100) {
|
|
7
|
+
if (limit === void 0) return void 0;
|
|
8
|
+
return Math.min(Math.max(1, Math.trunc(limit)), max);
|
|
9
|
+
}
|
|
10
|
+
function parseLinkNext(header) {
|
|
11
|
+
if (!header) return void 0;
|
|
12
|
+
for (const part of header.split(",")) {
|
|
13
|
+
const match = part.match(/<([^>]+)>\s*;\s*rel="([^"]+)"/);
|
|
14
|
+
if (match && match[2] === "next") return match[1];
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
/** Percent-encodes a ref path while keeping its `/` separators intact. */
|
|
18
|
+
function encodeRefPath(ref) {
|
|
19
|
+
return ref.split("/").map(encodeURIComponent).join("/");
|
|
20
|
+
}
|
|
21
|
+
function commitWebUrlBuilder(pathSegment) {
|
|
22
|
+
return function commitWebUrl(repoWebUrl, sha) {
|
|
23
|
+
return `${repoWebUrl.replace(/\/+$/, "")}/${pathSegment}/${sha}`;
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
function filenameFromContentDisposition(header) {
|
|
27
|
+
if (!header) return void 0;
|
|
28
|
+
const extended = header.match(/filename\*=(?:UTF-8'')?([^;]+)/i);
|
|
29
|
+
if (extended?.[1]) return decodeURIComponent(extended[1].trim().replace(/^"|"$/g, ""));
|
|
30
|
+
return header.match(/filename="?([^";]+)"?/i)?.[1]?.trim();
|
|
31
|
+
}
|
|
32
|
+
//#endregion
|
|
2
33
|
//#region src/http.ts
|
|
34
|
+
const USER_AGENT = "repo-sdk";
|
|
3
35
|
var HttpClient = class {
|
|
4
36
|
options;
|
|
5
37
|
constructor(options) {
|
|
@@ -23,6 +55,7 @@ var HttpClient = class {
|
|
|
23
55
|
...await this.options.authHeaders({ forceRefresh }),
|
|
24
56
|
...options.headers
|
|
25
57
|
};
|
|
58
|
+
headers["User-Agent"] ??= USER_AGENT;
|
|
26
59
|
if (body !== void 0) headers["Content-Type"] ??= "application/json";
|
|
27
60
|
try {
|
|
28
61
|
return await fetchImpl(url, {
|
|
@@ -71,35 +104,4 @@ var HttpClient = class {
|
|
|
71
104
|
}
|
|
72
105
|
};
|
|
73
106
|
//#endregion
|
|
74
|
-
|
|
75
|
-
function isRecord(value) {
|
|
76
|
-
return typeof value === "object" && value !== null;
|
|
77
|
-
}
|
|
78
|
-
function clampPerPage(limit, max = 100) {
|
|
79
|
-
if (limit === void 0) return void 0;
|
|
80
|
-
return Math.min(Math.max(1, Math.trunc(limit)), max);
|
|
81
|
-
}
|
|
82
|
-
function parseLinkNext(header) {
|
|
83
|
-
if (!header) return void 0;
|
|
84
|
-
for (const part of header.split(",")) {
|
|
85
|
-
const match = part.match(/<([^>]+)>\s*;\s*rel="([^"]+)"/);
|
|
86
|
-
if (match && match[2] === "next") return match[1];
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
/** Percent-encodes a ref path while keeping its `/` separators intact. */
|
|
90
|
-
function encodeRefPath(ref) {
|
|
91
|
-
return ref.split("/").map(encodeURIComponent).join("/");
|
|
92
|
-
}
|
|
93
|
-
function commitWebUrlBuilder(pathSegment) {
|
|
94
|
-
return function commitWebUrl(repoWebUrl, sha) {
|
|
95
|
-
return `${repoWebUrl.replace(/\/+$/, "")}/${pathSegment}/${sha}`;
|
|
96
|
-
};
|
|
97
|
-
}
|
|
98
|
-
function filenameFromContentDisposition(header) {
|
|
99
|
-
if (!header) return void 0;
|
|
100
|
-
const extended = header.match(/filename\*=(?:UTF-8'')?([^;]+)/i);
|
|
101
|
-
if (extended?.[1]) return decodeURIComponent(extended[1].trim().replace(/^"|"$/g, ""));
|
|
102
|
-
return header.match(/filename="?([^";]+)"?/i)?.[1]?.trim();
|
|
103
|
-
}
|
|
104
|
-
//#endregion
|
|
105
|
-
export { isRecord as a, filenameFromContentDisposition as i, commitWebUrlBuilder as n, parseLinkNext as o, encodeRefPath as r, HttpClient as s, clampPerPage as t };
|
|
107
|
+
export { filenameFromContentDisposition as a, encodeRefPath as i, clampPerPage as n, isRecord as o, commitWebUrlBuilder as r, parseLinkNext as s, HttpClient as t };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { A as
|
|
1
|
+
import { A as ProviderRefMatch, B as TokenProvider, C as ListTagsParams, D as Page, E as NamespaceKind, F as RepoProvider, G as WebhookVerificationMethod, H as UserRef, I as Repository, L as ResolveRefParams, M as RefMatch, N as RefType, O as ParsedWebhookEvent, P as RepoCapabilities, R as SearchRefsParams, S as ListRepositoriesParams, T as Namespace, U as Webhook, V as UpdateWebhookParams, W as WebhookEventType, _ as GitActor, a as CloneUrl, b as ListCommitsParams, c as DeleteWebhookParams, d as GetBranchParams, f as GetCloneUrlParams, g as GetWebhookParams, h as GetTagParams, i as Branch, j as ProviderSearchRefsParams, k as ProviderName, l as DownloadArchiveParams, m as GetRepositoryParams, n as ArchiveFormat, o as Commit, p as GetCommitParams, r as AuthenticatedUser, s as CreateWebhookParams, t as Archive, u as GetAuthenticatedUserParams, v as IncomingWebhookRequest, w as ListWebhooksParams, x as ListNamespacesParams, y as ListBranchesParams, z as Tag } from "./types-DfiRluvJ.js";
|
|
2
2
|
//#region src/client.d.ts
|
|
3
3
|
interface RetryOptions {
|
|
4
4
|
rateLimit?: boolean;
|
|
@@ -92,4 +92,4 @@ declare class RepoError extends Error {
|
|
|
92
92
|
constructor(message: string, options: RepoErrorOptions);
|
|
93
93
|
}
|
|
94
94
|
//#endregion
|
|
95
|
-
export { type Archive, type ArchiveFormat, type AuthenticatedUser, type Branch, type CloneUrl, type Commit, type CreateClientOptions, type CreateWebhookParams, type DeleteWebhookParams, type DetectWebhookProviderInput, type DownloadArchiveParams, type GetAuthenticatedUserParams, type GetBranchParams, type GetCloneUrlParams, type GetCommitParams, type GetRepositoryParams, type GetTagParams, type GetWebhookParams, type GitActor, type IncomingWebhookRequest, type ListBranchesParams, type ListCommitsParams, type ListNamespacesParams, type ListRepositoriesParams, type ListTagsParams, type ListWebhooksParams, type Namespace, type NamespaceKind, type Page, type ParsedWebhookEvent, type ProviderName, type ProviderSearchRefsParams, type RefMatch, type RefType, type RepoCapabilities, type RepoClient, RepoError, type RepoErrorCode, type RepoErrorOptions, type RepoProvider, type Repository, type ResolveRefParams, type RetryOptions, type SearchRefsParams, type Tag, type TokenProvider, type UpdateWebhookParams, type UserRef, type Webhook, type WebhookEventType, type WebhookVerificationMethod, createClient, detectWebhookProvider };
|
|
95
|
+
export { type Archive, type ArchiveFormat, type AuthenticatedUser, type Branch, type CloneUrl, type Commit, type CreateClientOptions, type CreateWebhookParams, type DeleteWebhookParams, type DetectWebhookProviderInput, type DownloadArchiveParams, type GetAuthenticatedUserParams, type GetBranchParams, type GetCloneUrlParams, type GetCommitParams, type GetRepositoryParams, type GetTagParams, type GetWebhookParams, type GitActor, type IncomingWebhookRequest, type ListBranchesParams, type ListCommitsParams, type ListNamespacesParams, type ListRepositoriesParams, type ListTagsParams, type ListWebhooksParams, type Namespace, type NamespaceKind, type Page, type ParsedWebhookEvent, type ProviderName, type ProviderRefMatch, type ProviderSearchRefsParams, type RefMatch, type RefType, type RepoCapabilities, type RepoClient, RepoError, type RepoErrorCode, type RepoErrorOptions, type RepoProvider, type Repository, type ResolveRefParams, type RetryOptions, type SearchRefsParams, type Tag, type TokenProvider, type UpdateWebhookParams, type UserRef, type Webhook, type WebhookEventType, type WebhookVerificationMethod, createClient, detectWebhookProvider };
|
package/dist/index.js
CHANGED
|
@@ -10,29 +10,39 @@ const ALL_REF_TYPES = [
|
|
|
10
10
|
"commit"
|
|
11
11
|
];
|
|
12
12
|
const COMMIT_SHA_PATTERN = /^[0-9a-f]{4,40}$/i;
|
|
13
|
-
|
|
13
|
+
const FULL_COMMIT_SHA_PATTERN = /^[0-9a-f]{40}$/i;
|
|
14
|
+
const BRANCH_REF_PREFIX = "refs/heads/";
|
|
15
|
+
const TAG_REF_PREFIX = "refs/tags/";
|
|
16
|
+
function qualifyRef(match) {
|
|
17
|
+
const ref = match.type === "branch" ? `${BRANCH_REF_PREFIX}${match.name}` : match.type === "tag" ? `${TAG_REF_PREFIX}${match.name}` : match.sha;
|
|
14
18
|
return {
|
|
19
|
+
...match,
|
|
20
|
+
ref
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
function branchMatch(branch) {
|
|
24
|
+
return qualifyRef({
|
|
15
25
|
type: "branch",
|
|
16
26
|
name: branch.name,
|
|
17
27
|
sha: branch.sha,
|
|
18
28
|
raw: branch.raw
|
|
19
|
-
};
|
|
29
|
+
});
|
|
20
30
|
}
|
|
21
31
|
function tagMatch(tag) {
|
|
22
|
-
return {
|
|
32
|
+
return qualifyRef({
|
|
23
33
|
type: "tag",
|
|
24
34
|
name: tag.name,
|
|
25
35
|
sha: tag.sha,
|
|
26
36
|
raw: tag.raw
|
|
27
|
-
};
|
|
37
|
+
});
|
|
28
38
|
}
|
|
29
39
|
function commitMatch(commit) {
|
|
30
|
-
return {
|
|
40
|
+
return qualifyRef({
|
|
31
41
|
type: "commit",
|
|
32
42
|
name: commit.sha,
|
|
33
43
|
sha: commit.sha,
|
|
34
44
|
raw: commit.raw
|
|
35
|
-
};
|
|
45
|
+
});
|
|
36
46
|
}
|
|
37
47
|
function createClient(options) {
|
|
38
48
|
const { provider } = options;
|
|
@@ -192,7 +202,7 @@ function createClient(options) {
|
|
|
192
202
|
types: refTypes,
|
|
193
203
|
limit,
|
|
194
204
|
signal
|
|
195
|
-
})) : [], types.includes("commit") && COMMIT_SHA_PATTERN.test(query) ? withRetry(() => provider.getCommit({
|
|
205
|
+
})).then((matches) => matches.map(qualifyRef)) : [], types.includes("commit") && COMMIT_SHA_PATTERN.test(query) ? withRetry(() => provider.getCommit({
|
|
196
206
|
repo,
|
|
197
207
|
ref: query,
|
|
198
208
|
signal
|
|
@@ -205,8 +215,16 @@ function createClient(options) {
|
|
|
205
215
|
resolve: async (params) => {
|
|
206
216
|
requireNonEmpty(params.repo, "repo");
|
|
207
217
|
requireNonEmpty(params.ref, "ref");
|
|
208
|
-
const { repo,
|
|
209
|
-
|
|
218
|
+
const { repo, signal } = params;
|
|
219
|
+
let { ref, type } = params;
|
|
220
|
+
const impliedType = ref.startsWith(BRANCH_REF_PREFIX) ? "branch" : ref.startsWith(TAG_REF_PREFIX) ? "tag" : void 0;
|
|
221
|
+
if (impliedType !== void 0) {
|
|
222
|
+
if (type !== void 0 && type !== impliedType) fail("validation", `Fully-qualified ref '${ref}' contradicts type '${type}'`);
|
|
223
|
+
type = impliedType;
|
|
224
|
+
ref = ref.slice(impliedType === "branch" ? 11 : 10);
|
|
225
|
+
requireNonEmpty(ref, "ref");
|
|
226
|
+
}
|
|
227
|
+
if (impliedType === void 0 && ref === "HEAD" && (type === void 0 || type === "branch")) {
|
|
210
228
|
const defaultBranch = (await withRetry(() => provider.getRepository({
|
|
211
229
|
repo,
|
|
212
230
|
signal
|
|
@@ -226,6 +244,17 @@ function createClient(options) {
|
|
|
226
244
|
ref,
|
|
227
245
|
signal
|
|
228
246
|
})));
|
|
247
|
+
let commitProbeError;
|
|
248
|
+
if (type === void 0 && FULL_COMMIT_SHA_PATTERN.test(ref)) try {
|
|
249
|
+
return commitMatch(await withRetry(() => provider.getCommit({
|
|
250
|
+
repo,
|
|
251
|
+
ref,
|
|
252
|
+
signal
|
|
253
|
+
})));
|
|
254
|
+
} catch (error) {
|
|
255
|
+
if (error instanceof RepoError && (error.code === "not_found" || error.code === "validation" || error.code === "unsupported")) commitProbeError = error;
|
|
256
|
+
else throw error;
|
|
257
|
+
}
|
|
229
258
|
const [tagResult, branchResult] = await Promise.allSettled([type === "branch" ? void 0 : withRetry(() => provider.getTag({
|
|
230
259
|
repo,
|
|
231
260
|
name: ref,
|
|
@@ -242,11 +271,14 @@ function createClient(options) {
|
|
|
242
271
|
if (branchResult.status === "fulfilled") {
|
|
243
272
|
if (branchResult.value !== void 0) return branchMatch(branchResult.value);
|
|
244
273
|
} else if (!isMiss(branchResult)) throw branchResult.reason;
|
|
245
|
-
if (type === void 0 && COMMIT_SHA_PATTERN.test(ref))
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
274
|
+
if (type === void 0 && COMMIT_SHA_PATTERN.test(ref)) {
|
|
275
|
+
if (commitProbeError !== void 0) throw commitProbeError;
|
|
276
|
+
return commitMatch(await withRetry(() => provider.getCommit({
|
|
277
|
+
repo,
|
|
278
|
+
ref,
|
|
279
|
+
signal
|
|
280
|
+
})));
|
|
281
|
+
}
|
|
250
282
|
throw new RepoError(`Ref not found: ${ref}`, {
|
|
251
283
|
code: "not_found",
|
|
252
284
|
provider: provider.name
|
package/dist/testing.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { E as NamespaceKind, F as
|
|
1
|
+
import { E as NamespaceKind, F as RepoProvider, I as Repository, P as RepoCapabilities, T as Namespace, U as Webhook, W as WebhookEventType, i as Branch, k as ProviderName, o as Commit, z as Tag } from "./types-DfiRluvJ.js";
|
|
2
2
|
//#region src/providers/testing/index.d.ts
|
|
3
3
|
interface InMemoryNamespaceSeed {
|
|
4
4
|
id: string;
|
|
@@ -93,10 +93,14 @@ type RefType = 'branch' | 'tag' | 'commit';
|
|
|
93
93
|
interface RefMatch {
|
|
94
94
|
type: RefType;
|
|
95
95
|
name: string;
|
|
96
|
+
/** Fully-qualified form — `refs/heads/<name>` for branches, `refs/tags/<name>` for tags, the SHA itself for commits. Any `ref` value round-trips through `refs.resolve`. */
|
|
97
|
+
ref: string;
|
|
96
98
|
/** SHA the ref points to. In `refs.search` results on GitHub and Gitea, annotated tags carry the tag object SHA rather than the commit; `refs.resolve` and `tags.get` always return the peeled commit SHA. */
|
|
97
99
|
sha: string;
|
|
98
100
|
raw: unknown;
|
|
99
101
|
}
|
|
102
|
+
/** `RefMatch` as produced by provider adapters, before the client derives the fully-qualified `ref`. */
|
|
103
|
+
type ProviderRefMatch = Omit<RefMatch, 'ref'>;
|
|
100
104
|
interface Webhook {
|
|
101
105
|
id: string;
|
|
102
106
|
url: string;
|
|
@@ -188,8 +192,9 @@ interface GetTagParams extends BaseParams {
|
|
|
188
192
|
}
|
|
189
193
|
interface ResolveRefParams extends BaseParams {
|
|
190
194
|
repo: string;
|
|
195
|
+
/** A branch or tag name, a fully-qualified ref (`refs/heads/…`, `refs/tags/…`), a 4–40 hex commit SHA, or `HEAD`. */
|
|
191
196
|
ref: string;
|
|
192
|
-
/** Restrict resolution to one ref type; when omitted, branches and tags
|
|
197
|
+
/** Restrict resolution to one ref type; when omitted, a full 40-hex `ref` is tried as a commit first, then branches and tags (tag wins on collision), then abbreviated commit SHAs. A fully-qualified `ref` implies its type; passing a contradicting `type` throws a validation error. */
|
|
193
198
|
type?: RefType;
|
|
194
199
|
}
|
|
195
200
|
interface SearchRefsParams extends BaseParams {
|
|
@@ -269,7 +274,7 @@ interface RepoProvider {
|
|
|
269
274
|
/** Exact-match a tag by name, peeled to the commit SHA for annotated tags; throws `not_found` on a miss. */
|
|
270
275
|
getTag(params: GetTagParams): Promise<Tag>;
|
|
271
276
|
/** Prefix-match refs of the requested types, branches before tags, at most `limit` results. */
|
|
272
|
-
searchRefs(params: ProviderSearchRefsParams): Promise<
|
|
277
|
+
searchRefs(params: ProviderSearchRefsParams): Promise<ProviderRefMatch[]>;
|
|
273
278
|
downloadArchive(params: DownloadArchiveParams): Promise<Archive>;
|
|
274
279
|
getCloneUrl(params: GetCloneUrlParams): Promise<CloneUrl>;
|
|
275
280
|
createWebhook(params: CreateWebhookParams): Promise<Webhook>;
|
|
@@ -279,4 +284,4 @@ interface RepoProvider {
|
|
|
279
284
|
deleteWebhook(params: DeleteWebhookParams): Promise<void>;
|
|
280
285
|
}
|
|
281
286
|
//#endregion
|
|
282
|
-
export {
|
|
287
|
+
export { ProviderRefMatch as A, TokenProvider as B, ListTagsParams as C, Page as D, NamespaceKind as E, RepoProvider as F, WebhookVerificationMethod as G, UserRef as H, Repository as I, ResolveRefParams as L, RefMatch as M, RefType as N, ParsedWebhookEvent as O, RepoCapabilities as P, SearchRefsParams as R, ListRepositoriesParams as S, Namespace as T, Webhook as U, UpdateWebhookParams as V, WebhookEventType as W, GitActor as _, CloneUrl as a, ListCommitsParams as b, DeleteWebhookParams as c, GetBranchParams as d, GetCloneUrlParams as f, GetWebhookParams as g, GetTagParams as h, Branch as i, ProviderSearchRefsParams as j, ProviderName as k, DownloadArchiveParams as l, GetRepositoryParams as m, ArchiveFormat as n, Commit as o, GetCommitParams as p, AuthenticatedUser as r, CreateWebhookParams as s, Archive as t, GetAuthenticatedUserParams as u, IncomingWebhookRequest as v, ListWebhooksParams as w, ListNamespacesParams as x, ListBranchesParams as y, Tag as z };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "repo-sdk",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"description": "Unified TypeScript SDK for git providers — GitHub, GitLab, Bitbucket, Azure DevOps, Gitea",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Robin Genz <mail@robingenz.dev>",
|
|
@@ -76,8 +76,8 @@
|
|
|
76
76
|
"test:watch": "vitest",
|
|
77
77
|
"typecheck": "tsc --noEmit",
|
|
78
78
|
"lint": "eslint .",
|
|
79
|
-
"
|
|
80
|
-
"
|
|
79
|
+
"fmt": "prettier --write .",
|
|
80
|
+
"fmt:check": "prettier --check .",
|
|
81
81
|
"docs:dev": "blume dev",
|
|
82
82
|
"docs:build": "blume build && rm -rf .blume-dist && cp -R dist .blume-dist",
|
|
83
83
|
"docs:preview": "blume preview",
|