repo-sdk 0.2.0 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/github.d.ts +31 -1
- package/dist/github.js +72 -30
- package/package.json +1 -1
package/dist/github.d.ts
CHANGED
|
@@ -57,6 +57,18 @@ interface ListUserInstallationsParams {
|
|
|
57
57
|
cursor?: string;
|
|
58
58
|
signal?: AbortSignal;
|
|
59
59
|
}
|
|
60
|
+
interface ListInstallationRequestsParams {
|
|
61
|
+
/** The GitHub App id the installation requests belong to. */
|
|
62
|
+
appId: string | number;
|
|
63
|
+
/** PEM-encoded private key of the app, used to sign the app JWT. */
|
|
64
|
+
privateKey: string;
|
|
65
|
+
/** GHES API root (`/api/v3`); defaults to `https://api.github.com`. */
|
|
66
|
+
baseUrl?: string;
|
|
67
|
+
fetch?: typeof fetch;
|
|
68
|
+
limit?: number;
|
|
69
|
+
cursor?: string;
|
|
70
|
+
signal?: AbortSignal;
|
|
71
|
+
}
|
|
60
72
|
interface GitHubInstallationAccount {
|
|
61
73
|
id: string;
|
|
62
74
|
login: string;
|
|
@@ -69,6 +81,16 @@ interface GitHubUserInstallation {
|
|
|
69
81
|
account?: GitHubInstallationAccount;
|
|
70
82
|
raw: unknown;
|
|
71
83
|
}
|
|
84
|
+
interface GitHubInstallationRequest {
|
|
85
|
+
id: string;
|
|
86
|
+
/** Account (organization or user) the installation was requested for. */
|
|
87
|
+
account?: GitHubInstallationAccount;
|
|
88
|
+
/** ISO 8601 timestamp of when the request was created. */
|
|
89
|
+
createdAt: string;
|
|
90
|
+
/** User who requested the installation. */
|
|
91
|
+
requester?: GitHubInstallationAccount;
|
|
92
|
+
raw: unknown;
|
|
93
|
+
}
|
|
72
94
|
/**
|
|
73
95
|
* Lists the GitHub App installations the given user can access
|
|
74
96
|
* (`GET /user/installations`). Standalone by design: the endpoint requires a
|
|
@@ -76,9 +98,17 @@ interface GitHubUserInstallation {
|
|
|
76
98
|
* `github` provider authenticates its requests with.
|
|
77
99
|
*/
|
|
78
100
|
declare function listUserInstallations(params: ListUserInstallationsParams): Promise<Page<GitHubUserInstallation>>;
|
|
101
|
+
/**
|
|
102
|
+
* Lists the pending installation requests of a GitHub App
|
|
103
|
+
* (`GET /app/installation-requests`) — installations an organization owner has
|
|
104
|
+
* yet to approve. Standalone by design: the endpoint is authenticated with an
|
|
105
|
+
* app JWT, a different credential from the installation token the `github`
|
|
106
|
+
* provider authenticates its requests with.
|
|
107
|
+
*/
|
|
108
|
+
declare function listInstallationRequests(params: ListInstallationRequestsParams): Promise<Page<GitHubInstallationRequest>>;
|
|
79
109
|
//#endregion
|
|
80
110
|
//#region src/providers/github/webhooks.d.ts
|
|
81
111
|
declare function verifyWebhook(params: VerifyWebhookParams): Promise<boolean>;
|
|
82
112
|
declare function parseWebhookEvent(input: Request | IncomingWebhookRequest): Promise<ParsedWebhookEvent>;
|
|
83
113
|
//#endregion
|
|
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 };
|
|
114
|
+
export { type GitHubAppAuth, type GitHubAuth, type GitHubInstallationAccount, type GitHubInstallationRequest, type GitHubInstallationToken, type GitHubProviderOptions, type GitHubRepoProvider, type GitHubTokenAuth, type GitHubUserInstallation, type ListInstallationRequestsParams, type ListUserInstallationsParams, type VerifyWebhookParams, commitWebUrl, github, listInstallationRequests, listUserInstallations, parseWebhookEvent, verifyWebhook };
|
package/dist/github.js
CHANGED
|
@@ -77,7 +77,23 @@ const encoder = new TextEncoder();
|
|
|
77
77
|
function base64UrlJson(value) {
|
|
78
78
|
return bytesToBase64Url(encoder.encode(JSON.stringify(value)));
|
|
79
79
|
}
|
|
80
|
-
|
|
80
|
+
/**
|
|
81
|
+
* Mints a short-lived RS256 JWT signed with the app private key — the
|
|
82
|
+
* credential for app-level endpoints (`/app/…`), which installation and user
|
|
83
|
+
* tokens cannot access. Internal to the package: not exported from the
|
|
84
|
+
* `repo-sdk/github` barrel.
|
|
85
|
+
*/
|
|
86
|
+
async function createAppJwt(options) {
|
|
87
|
+
let key;
|
|
88
|
+
try {
|
|
89
|
+
key = await importPrivateKey(options.privateKey);
|
|
90
|
+
} catch (error) {
|
|
91
|
+
throw new RepoError("GitHub App private key is not a valid PEM-encoded RSA private key", {
|
|
92
|
+
provider: "github",
|
|
93
|
+
code: "validation",
|
|
94
|
+
cause: error
|
|
95
|
+
});
|
|
96
|
+
}
|
|
81
97
|
const now = Math.floor(Date.now() / 1e3);
|
|
82
98
|
const signingInput = `${base64UrlJson({
|
|
83
99
|
alg: "RS256",
|
|
@@ -85,7 +101,7 @@ async function createJwt(key, appId) {
|
|
|
85
101
|
})}.${base64UrlJson({
|
|
86
102
|
iat: now - 60,
|
|
87
103
|
exp: now + 540,
|
|
88
|
-
iss: appId
|
|
104
|
+
iss: String(options.appId)
|
|
89
105
|
})}`;
|
|
90
106
|
const signature = await crypto.subtle.sign("RSASSA-PKCS1-v1_5", key, encoder.encode(signingInput));
|
|
91
107
|
return `${signingInput}.${bytesToBase64Url(new Uint8Array(signature))}`;
|
|
@@ -94,8 +110,9 @@ async function createJwt(key, appId) {
|
|
|
94
110
|
* Mints and caches GitHub App installation access tokens. A short-lived RS256
|
|
95
111
|
* JWT (signed with the app private key) authenticates the app-level calls that
|
|
96
112
|
* resolve the installation and mint installation tokens; the installation token
|
|
97
|
-
* is cached and refreshed once it nears expiry. A fresh
|
|
98
|
-
* refresh (cheap, and refreshes are rare given the ~1h token
|
|
113
|
+
* is cached and refreshed once it nears expiry. A fresh key import and JWT go
|
|
114
|
+
* into every token refresh (cheap, and refreshes are rare given the ~1h token
|
|
115
|
+
* TTL).
|
|
99
116
|
*/
|
|
100
117
|
var AppTokenSource = class {
|
|
101
118
|
kind = "app";
|
|
@@ -107,7 +124,6 @@ var AppTokenSource = class {
|
|
|
107
124
|
userAgent;
|
|
108
125
|
installationId;
|
|
109
126
|
owner;
|
|
110
|
-
keyPromise;
|
|
111
127
|
cached;
|
|
112
128
|
refresh;
|
|
113
129
|
constructor(options) {
|
|
@@ -153,7 +169,10 @@ var AppTokenSource = class {
|
|
|
153
169
|
return this.refresh;
|
|
154
170
|
}
|
|
155
171
|
async mintInstallationToken() {
|
|
156
|
-
const jwt = await
|
|
172
|
+
const jwt = await createAppJwt({
|
|
173
|
+
appId: this.appId,
|
|
174
|
+
privateKey: this.privateKey
|
|
175
|
+
});
|
|
157
176
|
const installationId = await this.resolveInstallationId(jwt);
|
|
158
177
|
const data = await this.appRequest(`/app/installations/${installationId}/access_tokens`, "POST", jwt);
|
|
159
178
|
const token = {
|
|
@@ -199,10 +218,6 @@ var AppTokenSource = class {
|
|
|
199
218
|
});
|
|
200
219
|
return String(installations[0].id);
|
|
201
220
|
}
|
|
202
|
-
createAppJwt() {
|
|
203
|
-
if (!this.keyPromise) this.keyPromise = importPrivateKey(this.privateKey);
|
|
204
|
-
return this.keyPromise.then((key) => createJwt(key, this.appId));
|
|
205
|
-
}
|
|
206
221
|
async appRequest(path, method, jwt) {
|
|
207
222
|
const url = joinUrl(this.baseUrl, path);
|
|
208
223
|
const { fetchImpl } = this;
|
|
@@ -864,42 +879,47 @@ function github(options) {
|
|
|
864
879
|
}
|
|
865
880
|
//#endregion
|
|
866
881
|
//#region src/providers/github/installations.ts
|
|
882
|
+
function toAccount(payload) {
|
|
883
|
+
if (payload?.login === void 0) return void 0;
|
|
884
|
+
return {
|
|
885
|
+
id: String(payload.id),
|
|
886
|
+
login: payload.login,
|
|
887
|
+
kind: payload.type === "Organization" ? "organization" : "user",
|
|
888
|
+
avatarUrl: payload.avatar_url
|
|
889
|
+
};
|
|
890
|
+
}
|
|
867
891
|
function toInstallation(payload) {
|
|
868
|
-
const account = payload.account;
|
|
869
892
|
return {
|
|
870
893
|
id: String(payload.id),
|
|
871
|
-
account: account
|
|
872
|
-
id: String(account.id),
|
|
873
|
-
login: account.login,
|
|
874
|
-
kind: account.type === "Organization" ? "organization" : "user",
|
|
875
|
-
avatarUrl: account.avatar_url
|
|
876
|
-
},
|
|
894
|
+
account: toAccount(payload.account),
|
|
877
895
|
raw: payload
|
|
878
896
|
};
|
|
879
897
|
}
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
898
|
+
function toInstallationRequest(payload) {
|
|
899
|
+
return {
|
|
900
|
+
id: String(payload.id),
|
|
901
|
+
account: toAccount(payload.account),
|
|
902
|
+
createdAt: payload.created_at,
|
|
903
|
+
requester: toAccount(payload.requester),
|
|
904
|
+
raw: payload
|
|
905
|
+
};
|
|
906
|
+
}
|
|
907
|
+
async function listPage(bearer, defaultPath, params, toItems) {
|
|
888
908
|
const baseUrl = params.baseUrl ?? "https://api.github.com";
|
|
889
909
|
const http = new HttpClient({
|
|
890
910
|
provider: "github",
|
|
891
911
|
baseUrl,
|
|
892
912
|
fetchImpl: params.fetch,
|
|
893
913
|
authHeaders: () => ({
|
|
894
|
-
Authorization: `Bearer ${
|
|
914
|
+
Authorization: `Bearer ${bearer}`,
|
|
895
915
|
Accept: "application/vnd.github+json",
|
|
896
916
|
"X-GitHub-Api-Version": API_VERSION,
|
|
897
917
|
"User-Agent": USER_AGENT
|
|
898
918
|
}),
|
|
899
919
|
mapError,
|
|
900
|
-
secrets: () => [
|
|
920
|
+
secrets: () => [bearer]
|
|
901
921
|
});
|
|
902
|
-
let path =
|
|
922
|
+
let path = defaultPath;
|
|
903
923
|
let query;
|
|
904
924
|
if (params.cursor) {
|
|
905
925
|
const { url } = decodeCursor("github", params.cursor);
|
|
@@ -910,10 +930,32 @@ async function listUserInstallations(params) {
|
|
|
910
930
|
signal: params.signal
|
|
911
931
|
});
|
|
912
932
|
return {
|
|
913
|
-
data: (data
|
|
933
|
+
data: toItems(data),
|
|
914
934
|
cursor: nextCursor(response)
|
|
915
935
|
};
|
|
916
936
|
}
|
|
937
|
+
/**
|
|
938
|
+
* Lists the GitHub App installations the given user can access
|
|
939
|
+
* (`GET /user/installations`). Standalone by design: the endpoint requires a
|
|
940
|
+
* user access token, a different credential from the installation token the
|
|
941
|
+
* `github` provider authenticates its requests with.
|
|
942
|
+
*/
|
|
943
|
+
async function listUserInstallations(params) {
|
|
944
|
+
return listPage(params.token, "/user/installations", params, (payload) => (payload.installations ?? []).map(toInstallation));
|
|
945
|
+
}
|
|
946
|
+
/**
|
|
947
|
+
* Lists the pending installation requests of a GitHub App
|
|
948
|
+
* (`GET /app/installation-requests`) — installations an organization owner has
|
|
949
|
+
* yet to approve. Standalone by design: the endpoint is authenticated with an
|
|
950
|
+
* app JWT, a different credential from the installation token the `github`
|
|
951
|
+
* provider authenticates its requests with.
|
|
952
|
+
*/
|
|
953
|
+
async function listInstallationRequests(params) {
|
|
954
|
+
return listPage(await createAppJwt({
|
|
955
|
+
appId: params.appId,
|
|
956
|
+
privateKey: params.privateKey
|
|
957
|
+
}), "/app/installation-requests", params, (payload) => payload.map(toInstallationRequest));
|
|
958
|
+
}
|
|
917
959
|
//#endregion
|
|
918
960
|
//#region src/providers/github/webhooks.ts
|
|
919
961
|
function verifyWebhook(params) {
|
|
@@ -949,4 +991,4 @@ async function parseWebhookEvent(input) {
|
|
|
949
991
|
};
|
|
950
992
|
}
|
|
951
993
|
//#endregion
|
|
952
|
-
export { commitWebUrl, github, listUserInstallations, parseWebhookEvent, verifyWebhook };
|
|
994
|
+
export { commitWebUrl, github, listInstallationRequests, listUserInstallations, parseWebhookEvent, verifyWebhook };
|
package/package.json
CHANGED