@usine/github 0.0.1 → 0.1.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/README.md +117 -2
- package/dist/access.d.ts +48 -0
- package/dist/access.d.ts.map +1 -0
- package/dist/access.js +53 -0
- package/dist/access.js.map +1 -0
- package/dist/credentials.d.ts +28 -0
- package/dist/credentials.d.ts.map +1 -0
- package/dist/credentials.js +22 -0
- package/dist/credentials.js.map +1 -0
- package/dist/error.d.ts +36 -0
- package/dist/error.d.ts.map +1 -0
- package/dist/error.js +48 -0
- package/dist/error.js.map +1 -0
- package/dist/github-app.d.ts +30 -0
- package/dist/github-app.d.ts.map +1 -0
- package/dist/github-app.js +184 -0
- package/dist/github-app.js.map +1 -0
- package/dist/http.d.ts +18 -0
- package/dist/http.d.ts.map +1 -0
- package/dist/http.js +68 -0
- package/dist/http.js.map +1 -0
- package/dist/installation.d.ts +48 -0
- package/dist/installation.d.ts.map +1 -0
- package/dist/installation.js +40 -0
- package/dist/installation.js.map +1 -0
- package/dist/item-writer.d.ts +23 -0
- package/dist/item-writer.d.ts.map +1 -0
- package/dist/item-writer.js +67 -0
- package/dist/item-writer.js.map +1 -0
- package/dist/jwt.d.ts +11 -0
- package/dist/jwt.d.ts.map +1 -0
- package/dist/jwt.js +72 -0
- package/dist/jwt.js.map +1 -0
- package/dist/label-writer.d.ts +23 -0
- package/dist/label-writer.d.ts.map +1 -0
- package/dist/label-writer.js +54 -0
- package/dist/label-writer.js.map +1 -0
- package/dist/local-secrets.d.ts +28 -0
- package/dist/local-secrets.d.ts.map +1 -0
- package/dist/local-secrets.js +56 -0
- package/dist/local-secrets.js.map +1 -0
- package/dist/polling/content.d.ts +3 -0
- package/dist/polling/content.d.ts.map +1 -0
- package/dist/polling/content.js +24 -0
- package/dist/polling/content.js.map +1 -0
- package/dist/polling/detection.d.ts +55 -0
- package/dist/polling/detection.d.ts.map +1 -0
- package/dist/polling/detection.js +49 -0
- package/dist/polling/detection.js.map +1 -0
- package/dist/polling/labels.d.ts +31 -0
- package/dist/polling/labels.d.ts.map +1 -0
- package/dist/polling/labels.js +29 -0
- package/dist/polling/labels.js.map +1 -0
- package/dist/polling/payload.d.ts +565 -0
- package/dist/polling/payload.d.ts.map +1 -0
- package/dist/polling/payload.js +128 -0
- package/dist/polling/payload.js.map +1 -0
- package/dist/polling/polling.d.ts +24 -0
- package/dist/polling/polling.d.ts.map +1 -0
- package/dist/polling/polling.js +325 -0
- package/dist/polling/polling.js.map +1 -0
- package/dist/polling/queries.d.ts +3 -0
- package/dist/polling/queries.d.ts.map +1 -0
- package/dist/polling/queries.js +125 -0
- package/dist/polling/queries.js.map +1 -0
- package/package.json +32 -6
- package/dist/index.d.ts +0 -8
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js +0 -8
- package/dist/index.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"github-app.js","sourceRoot":"","sources":["../src/github-app.ts"],"names":[],"mappings":"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"}
|
package/dist/http.d.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { Option, Redacted } from "effect";
|
|
2
|
+
import { HttpClientRequest, type HttpClientResponse } from "effect/unstable/http";
|
|
3
|
+
import type { HttpClientError } from "effect/unstable/http/HttpClientError";
|
|
4
|
+
import { GitHubApiError, GitHubRateLimitError, InvalidGitHubResponseError, type GitHubOperation } from "./error.ts";
|
|
5
|
+
export declare const API_ROOT = "https://api.github.com";
|
|
6
|
+
export declare const authorized: (credential: Redacted.Redacted<string>) => (self: HttpClientRequest.HttpClientRequest) => HttpClientRequest.HttpClientRequest;
|
|
7
|
+
export declare const transportError: (operation: GitHubOperation, error: HttpClientError) => GitHubApiError;
|
|
8
|
+
export declare const invalidResponse: (operation: GitHubOperation, detail: string) => InvalidGitHubResponseError;
|
|
9
|
+
type Headers = HttpClientResponse.HttpClientResponse["headers"];
|
|
10
|
+
export declare const retryAfterMillis: (value: string | undefined, now: number) => Option.Option<number>;
|
|
11
|
+
export declare const rateLimitResetMillis: (headers: Headers, threshold: number) => Option.Option<number>;
|
|
12
|
+
export declare const pollIntervalMillis: (headers: Headers, now: number) => Option.Option<number>;
|
|
13
|
+
/** The epoch when GitHub allows the next request, from `retry-after` and an exhausted primary rate-limit budget. */
|
|
14
|
+
export declare const rateLimitRetryEpoch: (headers: Headers, now: number) => Option.Option<number>;
|
|
15
|
+
/** Turns a non-2xx GitHub response into a typed error. A rate-limit status with a known retry time becomes a wait, not a failure. */
|
|
16
|
+
export declare const statusError: (operation: GitHubOperation, response: HttpClientResponse.HttpClientResponse, now: number) => GitHubApiError | GitHubRateLimitError;
|
|
17
|
+
export {};
|
|
18
|
+
//# sourceMappingURL=http.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../src/http.ts"],"names":[],"mappings":"AAAA,OAAO,EAAY,MAAM,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AACpD,OAAO,EAAE,iBAAiB,EAAE,KAAK,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAClF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sCAAsC,CAAC;AAC5E,OAAO,EACL,cAAc,EACd,oBAAoB,EACpB,0BAA0B,EAC1B,KAAK,eAAe,EACrB,MAAM,YAAY,CAAC;AAEpB,eAAO,MAAM,QAAQ,2BAA2B,CAAC;AAGjD,eAAO,MAAM,UAAU,eAAgB,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,uFAM5D,CAAC;AAEL,eAAO,MAAM,cAAc,cAAe,eAAe,SAAS,eAAe,mBAQ7E,CAAC;AAEL,eAAO,MAAM,eAAe,cAAe,eAAe,UAAU,MAAM,+BAKtE,CAAC;AAEL,KAAK,OAAO,GAAG,kBAAkB,CAAC,kBAAkB,CAAC,SAAS,CAAC,CAAC;AAQhE,eAAO,MAAM,gBAAgB,UAAW,MAAM,GAAG,SAAS,OAAO,MAAM,KAAG,MAAM,CAAC,MAAM,CAAC,MAAM,CAM7F,CAAC;AAEF,eAAO,MAAM,oBAAoB,YACtB,OAAO,aACL,MAAM,KAChB,MAAM,CAAC,MAAM,CAAC,MAAM,CAMtB,CAAC;AAEF,eAAO,MAAM,kBAAkB,YAAa,OAAO,OAAO,MAAM,KAAG,MAAM,CAAC,MAAM,CAAC,MAAM,CACG,CAAC;AAS3F,oHAAoH;AACpH,eAAO,MAAM,mBAAmB,YAAa,OAAO,OAAO,MAAM,KAAG,MAAM,CAAC,MAAM,CAAC,MAAM,CACQ,CAAC;AAEjG,qIAAqI;AACrI,eAAO,MAAM,WAAW,cACX,eAAe,YAChB,kBAAkB,CAAC,kBAAkB,OAC1C,MAAM,KACV,cAAc,GAAG,oBAanB,CAAC"}
|
package/dist/http.js
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { DateTime, Option, Redacted } from "effect";
|
|
2
|
+
import { HttpClientRequest } from "effect/unstable/http";
|
|
3
|
+
import { GitHubApiError, GitHubRateLimitError, InvalidGitHubResponseError, } from "./error.js";
|
|
4
|
+
export const API_ROOT = "https://api.github.com";
|
|
5
|
+
const API_VERSION = "2026-03-10";
|
|
6
|
+
export const authorized = (credential) => HttpClientRequest.setHeaders({
|
|
7
|
+
accept: "application/vnd.github+json",
|
|
8
|
+
authorization: `Bearer ${Redacted.value(credential)}`,
|
|
9
|
+
"user-agent": "usine",
|
|
10
|
+
"x-github-api-version": API_VERSION,
|
|
11
|
+
});
|
|
12
|
+
export const transportError = (operation, error) => new GitHubApiError({
|
|
13
|
+
operation,
|
|
14
|
+
status: error.response === undefined ? Option.none() : Option.some(error.response.status),
|
|
15
|
+
message: error.response === undefined
|
|
16
|
+
? "The request to GitHub could not be sent"
|
|
17
|
+
: `GitHub rejected the request with status ${error.response.status}`,
|
|
18
|
+
});
|
|
19
|
+
export const invalidResponse = (operation, detail) => new InvalidGitHubResponseError({
|
|
20
|
+
operation,
|
|
21
|
+
message: "GitHub returned a response that does not match its API contract",
|
|
22
|
+
detail,
|
|
23
|
+
});
|
|
24
|
+
const parseInteger = (value) => {
|
|
25
|
+
if (value === undefined || !/^\d+$/u.test(value))
|
|
26
|
+
return Option.none();
|
|
27
|
+
const parsed = Number(value);
|
|
28
|
+
return Number.isSafeInteger(parsed) ? Option.some(parsed) : Option.none();
|
|
29
|
+
};
|
|
30
|
+
export const retryAfterMillis = (value, now) => {
|
|
31
|
+
const seconds = parseInteger(value);
|
|
32
|
+
if (Option.isSome(seconds))
|
|
33
|
+
return Option.some(now + seconds.value * 1_000);
|
|
34
|
+
if (value === undefined)
|
|
35
|
+
return Option.none();
|
|
36
|
+
const parsed = Date.parse(value);
|
|
37
|
+
return Number.isFinite(parsed) ? Option.some(parsed) : Option.none();
|
|
38
|
+
};
|
|
39
|
+
export const rateLimitResetMillis = (headers, threshold) => {
|
|
40
|
+
const remaining = parseInteger(headers["x-ratelimit-remaining"]);
|
|
41
|
+
const reset = parseInteger(headers["x-ratelimit-reset"]);
|
|
42
|
+
return Option.isSome(remaining) && remaining.value <= threshold && Option.isSome(reset)
|
|
43
|
+
? Option.some(reset.value * 1_000)
|
|
44
|
+
: Option.none();
|
|
45
|
+
};
|
|
46
|
+
export const pollIntervalMillis = (headers, now) => Option.map(parseInteger(headers["x-poll-interval"]), (seconds) => now + seconds * 1_000);
|
|
47
|
+
const latestEpoch = (candidates) => {
|
|
48
|
+
const epochs = candidates.flatMap((candidate) => Option.match(candidate, { onNone: () => [], onSome: (value) => [value] }));
|
|
49
|
+
return epochs.length === 0 ? Option.none() : Option.some(Math.max(...epochs));
|
|
50
|
+
};
|
|
51
|
+
/** The epoch when GitHub allows the next request, from `retry-after` and an exhausted primary rate-limit budget. */
|
|
52
|
+
export const rateLimitRetryEpoch = (headers, now) => latestEpoch([retryAfterMillis(headers["retry-after"], now), rateLimitResetMillis(headers, 0)]);
|
|
53
|
+
/** Turns a non-2xx GitHub response into a typed error. A rate-limit status with a known retry time becomes a wait, not a failure. */
|
|
54
|
+
export const statusError = (operation, response, now) => {
|
|
55
|
+
const retryAt = Option.flatMap(rateLimitRetryEpoch(response.headers, now), DateTime.make);
|
|
56
|
+
return (response.status === 403 || response.status === 429) && Option.isSome(retryAt)
|
|
57
|
+
? new GitHubRateLimitError({
|
|
58
|
+
operation,
|
|
59
|
+
retryAt: retryAt.value,
|
|
60
|
+
message: "GitHub asked the poller to wait before retrying",
|
|
61
|
+
})
|
|
62
|
+
: new GitHubApiError({
|
|
63
|
+
operation,
|
|
64
|
+
status: Option.some(response.status),
|
|
65
|
+
message: `GitHub rejected the request with status ${response.status}`,
|
|
66
|
+
});
|
|
67
|
+
};
|
|
68
|
+
//# sourceMappingURL=http.js.map
|
package/dist/http.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http.js","sourceRoot":"","sources":["../src/http.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { Schema } from "effect";
|
|
2
|
+
/** The numeric identity of an installation of the factory's GitHub App. */
|
|
3
|
+
export declare const InstallationId: Schema.brand<Schema.Int, "GitHubInstallationId">;
|
|
4
|
+
export type InstallationId = typeof InstallationId.Type;
|
|
5
|
+
/** GitHub's numeric repository identity, used to restrict installation tokens. */
|
|
6
|
+
export declare const RepositoryId: Schema.brand<Schema.Int, "GitHubRepositoryId">;
|
|
7
|
+
export type RepositoryId = typeof RepositoryId.Type;
|
|
8
|
+
declare const Installation_base: Schema.Class<Installation, Schema.Struct<{
|
|
9
|
+
readonly id: Schema.brand<Schema.Int, "GitHubInstallationId">;
|
|
10
|
+
readonly accountLogin: Schema.NonEmptyString;
|
|
11
|
+
}>, {}>;
|
|
12
|
+
/** The discovered App installation and the account that owns it. */
|
|
13
|
+
export declare class Installation extends Installation_base {
|
|
14
|
+
}
|
|
15
|
+
declare const InstallationWide_base: Schema.Class<InstallationWide, Schema.TaggedStruct<"InstallationWide", {}>, {}>;
|
|
16
|
+
/** Token access to every repository covered by the installation. */
|
|
17
|
+
export declare class InstallationWide extends InstallationWide_base {
|
|
18
|
+
}
|
|
19
|
+
declare const SingleRepository_base: Schema.Class<SingleRepository, Schema.TaggedStruct<"SingleRepository", {
|
|
20
|
+
readonly repository: Schema.brand<Schema.String, "RepositoryName">;
|
|
21
|
+
readonly repositoryId: Schema.brand<Schema.Int, "GitHubRepositoryId">;
|
|
22
|
+
}>, {}>;
|
|
23
|
+
/** Token access restricted to the repository assigned to one Attempt. */
|
|
24
|
+
export declare class SingleRepository extends SingleRepository_base {
|
|
25
|
+
}
|
|
26
|
+
/** The repository coverage requested when minting an installation token. */
|
|
27
|
+
export declare const TokenScope: Schema.Union<readonly [typeof InstallationWide, typeof SingleRepository]>;
|
|
28
|
+
export type TokenScope = typeof TokenScope.Type;
|
|
29
|
+
declare const InstallationToken_base: Schema.Class<InstallationToken, Schema.Struct<{
|
|
30
|
+
readonly value: Schema.Redacted<Schema.NonEmptyString>;
|
|
31
|
+
readonly expiresAt: Schema.DateTimeUtc;
|
|
32
|
+
readonly scope: Schema.Union<readonly [typeof InstallationWide, typeof SingleRepository]>;
|
|
33
|
+
}>, {}>;
|
|
34
|
+
/** A redacted installation credential with its expiry and permitted repository scope. */
|
|
35
|
+
export declare class InstallationToken extends InstallationToken_base {
|
|
36
|
+
}
|
|
37
|
+
/** Why App installation discovery could not select one usable installation. */
|
|
38
|
+
export declare const InstallationDiscoveryReason: Schema.Literals<readonly ["missing", "multiple", "suspended"]>;
|
|
39
|
+
export type InstallationDiscoveryReason = typeof InstallationDiscoveryReason.Type;
|
|
40
|
+
declare const InstallationDiscoveryError_base: Schema.Class<InstallationDiscoveryError, Schema.TaggedStruct<"InstallationDiscoveryError", {
|
|
41
|
+
readonly reason: Schema.Literals<readonly ["missing", "multiple", "suspended"]>;
|
|
42
|
+
readonly message: Schema.NonEmptyString;
|
|
43
|
+
}>, import("effect/Cause").YieldableError>;
|
|
44
|
+
/** The App has no unambiguous active installation to use for repository access. */
|
|
45
|
+
export declare class InstallationDiscoveryError extends InstallationDiscoveryError_base {
|
|
46
|
+
}
|
|
47
|
+
export {};
|
|
48
|
+
//# sourceMappingURL=installation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"installation.d.ts","sourceRoot":"","sources":["../src/installation.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAIhC,2EAA2E;AAC3E,eAAO,MAAM,cAAc,kDAAyD,CAAC;AACrF,MAAM,MAAM,cAAc,GAAG,OAAO,cAAc,CAAC,IAAI,CAAC;AAExD,kFAAkF;AAClF,eAAO,MAAM,YAAY,gDAAuD,CAAC;AACjF,MAAM,MAAM,YAAY,GAAG,OAAO,YAAY,CAAC,IAAI,CAAC;;;;;AAEpD,oEAAoE;AACpE,qBAAa,YAAa,SAAQ,iBAGhC;CAAG;;AAEL,oEAAoE;AACpE,qBAAa,gBAAiB,SAAQ,qBAEb;CAAG;;;;;AAE5B,yEAAyE;AACzE,qBAAa,gBAAiB,SAAQ,qBAKpC;CAAG;AAEL,4EAA4E;AAC5E,eAAO,MAAM,UAAU,2EAAqD,CAAC;AAC7E,MAAM,MAAM,UAAU,GAAG,OAAO,UAAU,CAAC,IAAI,CAAC;;;;;;AAEhD,yFAAyF;AACzF,qBAAa,iBAAkB,SAAQ,sBAMrC;CAAG;AAEL,+EAA+E;AAC/E,eAAO,MAAM,2BAA2B,gEAAwD,CAAC;AACjG,MAAM,MAAM,2BAA2B,GAAG,OAAO,2BAA2B,CAAC,IAAI,CAAC;;;;;AAElF,mFAAmF;AACnF,qBAAa,0BAA2B,SAAQ,+BAK9C;CAAG"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { RepositoryName } from "@usine/core/repository";
|
|
2
|
+
import { Schema } from "effect";
|
|
3
|
+
const PositiveInt = Schema.Int.check(Schema.isGreaterThanOrEqualTo(1));
|
|
4
|
+
/** The numeric identity of an installation of the factory's GitHub App. */
|
|
5
|
+
export const InstallationId = PositiveInt.pipe(Schema.brand("GitHubInstallationId"));
|
|
6
|
+
/** GitHub's numeric repository identity, used to restrict installation tokens. */
|
|
7
|
+
export const RepositoryId = PositiveInt.pipe(Schema.brand("GitHubRepositoryId"));
|
|
8
|
+
/** The discovered App installation and the account that owns it. */
|
|
9
|
+
export class Installation extends Schema.Class("@usine/github/Installation")({
|
|
10
|
+
id: InstallationId,
|
|
11
|
+
accountLogin: Schema.NonEmptyString,
|
|
12
|
+
}) {
|
|
13
|
+
}
|
|
14
|
+
/** Token access to every repository covered by the installation. */
|
|
15
|
+
export class InstallationWide extends Schema.TaggedClass("@usine/github/TokenScope/InstallationWide")("InstallationWide", {}) {
|
|
16
|
+
}
|
|
17
|
+
/** Token access restricted to the repository assigned to one Attempt. */
|
|
18
|
+
export class SingleRepository extends Schema.TaggedClass("@usine/github/TokenScope/SingleRepository")("SingleRepository", {
|
|
19
|
+
repository: RepositoryName,
|
|
20
|
+
repositoryId: RepositoryId,
|
|
21
|
+
}) {
|
|
22
|
+
}
|
|
23
|
+
/** The repository coverage requested when minting an installation token. */
|
|
24
|
+
export const TokenScope = Schema.Union([InstallationWide, SingleRepository]);
|
|
25
|
+
/** A redacted installation credential with its expiry and permitted repository scope. */
|
|
26
|
+
export class InstallationToken extends Schema.Class("@usine/github/InstallationToken")({
|
|
27
|
+
value: Schema.Redacted(Schema.NonEmptyString, { disallowJsonEncode: true }),
|
|
28
|
+
expiresAt: Schema.DateTimeUtc,
|
|
29
|
+
scope: TokenScope,
|
|
30
|
+
}) {
|
|
31
|
+
}
|
|
32
|
+
/** Why App installation discovery could not select one usable installation. */
|
|
33
|
+
export const InstallationDiscoveryReason = Schema.Literals(["missing", "multiple", "suspended"]);
|
|
34
|
+
/** The App has no unambiguous active installation to use for repository access. */
|
|
35
|
+
export class InstallationDiscoveryError extends Schema.TaggedError("@usine/github/InstallationDiscoveryError")("InstallationDiscoveryError", {
|
|
36
|
+
reason: InstallationDiscoveryReason,
|
|
37
|
+
message: Schema.NonEmptyString,
|
|
38
|
+
}) {
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=installation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"installation.js","sourceRoot":"","sources":["../src/installation.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AACxD,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAEhC,MAAM,WAAW,GAAG,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,sBAAsB,CAAC,CAAC,CAAC,CAAC,CAAC;AAEvE,2EAA2E;AAC3E,MAAM,CAAC,MAAM,cAAc,GAAG,WAAW,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,sBAAsB,CAAC,CAAC,CAAC;AAGrF,kFAAkF;AAClF,MAAM,CAAC,MAAM,YAAY,GAAG,WAAW,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,oBAAoB,CAAC,CAAC,CAAC;AAGjF,oEAAoE;AACpE,MAAM,OAAO,YAAa,SAAQ,MAAM,CAAC,KAAK,CAAe,4BAA4B,CAAC,CAAC;IACzF,EAAE,EAAE,cAAc;IAClB,YAAY,EAAE,MAAM,CAAC,cAAc;CACpC,CAAC;CAAG;AAEL,oEAAoE;AACpE,MAAM,OAAO,gBAAiB,SAAQ,MAAM,CAAC,WAAW,CACtD,2CAA2C,CAC5C,CAAC,kBAAkB,EAAE,EAAE,CAAC;CAAG;AAE5B,yEAAyE;AACzE,MAAM,OAAO,gBAAiB,SAAQ,MAAM,CAAC,WAAW,CACtD,2CAA2C,CAC5C,CAAC,kBAAkB,EAAE;IACpB,UAAU,EAAE,cAAc;IAC1B,YAAY,EAAE,YAAY;CAC3B,CAAC;CAAG;AAEL,4EAA4E;AAC5E,MAAM,CAAC,MAAM,UAAU,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,gBAAgB,EAAE,gBAAgB,CAAC,CAAC,CAAC;AAG7E,yFAAyF;AACzF,MAAM,OAAO,iBAAkB,SAAQ,MAAM,CAAC,KAAK,CACjD,iCAAiC,CAClC,CAAC;IACA,KAAK,EAAE,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,cAAc,EAAE,EAAE,kBAAkB,EAAE,IAAI,EAAE,CAAC;IAC3E,SAAS,EAAE,MAAM,CAAC,WAAW;IAC7B,KAAK,EAAE,UAAU;CAClB,CAAC;CAAG;AAEL,+EAA+E;AAC/E,MAAM,CAAC,MAAM,2BAA2B,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC,SAAS,EAAE,UAAU,EAAE,WAAW,CAAC,CAAC,CAAC;AAGjG,mFAAmF;AACnF,MAAM,OAAO,0BAA2B,SAAQ,MAAM,CAAC,WAAW,CAChE,0CAA0C,CAC3C,CAAC,4BAA4B,EAAE;IAC9B,MAAM,EAAE,2BAA2B;IACnC,OAAO,EAAE,MAAM,CAAC,cAAc;CAC/B,CAAC;CAAG"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { RepositoryName } from "@usine/core/repository";
|
|
2
|
+
import { ItemNumber } from "@usine/core/item";
|
|
3
|
+
import { Context, Effect, Layer, Schema } from "effect";
|
|
4
|
+
import { HttpClient } from "effect/unstable/http";
|
|
5
|
+
import { GitHubApp } from "./github-app.ts";
|
|
6
|
+
import type { GitHubAppError } from "./error.ts";
|
|
7
|
+
declare const ItemLabelMutation_base: Schema.Class<ItemLabelMutation, Schema.Struct<{
|
|
8
|
+
readonly add: Schema.$Array<Schema.NonEmptyString>;
|
|
9
|
+
readonly remove: Schema.$Array<Schema.NonEmptyString>;
|
|
10
|
+
}>, {}>;
|
|
11
|
+
/** Labels to add and remove on one Item. Labels outside these two sets are left alone. */
|
|
12
|
+
export declare class ItemLabelMutation extends ItemLabelMutation_base {
|
|
13
|
+
}
|
|
14
|
+
declare const GitHubItemWriter_base: Context.ServiceClass<GitHubItemWriter, "@usine/github/GitHubItemWriter", {
|
|
15
|
+
/** Adds and removes only the named labels and keeps every other applied label. */
|
|
16
|
+
readonly updateLabels: (repository: RepositoryName, item: ItemNumber, mutation: ItemLabelMutation) => Effect.Effect<ReadonlyArray<string>, GitHubAppError>;
|
|
17
|
+
}>;
|
|
18
|
+
/** Label writes on GitHub Items, used when the Board moves a card between lanes. */
|
|
19
|
+
export declare class GitHubItemWriter extends GitHubItemWriter_base {
|
|
20
|
+
static readonly layer: Layer.Layer<GitHubItemWriter, never, GitHubApp | HttpClient.HttpClient>;
|
|
21
|
+
}
|
|
22
|
+
export {};
|
|
23
|
+
//# sourceMappingURL=item-writer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"item-writer.d.ts","sourceRoot":"","sources":["../src/item-writer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAuB,MAAM,wBAAwB,CAAC;AAC7E,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAS,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC/D,OAAO,EAAE,UAAU,EAAyC,MAAM,sBAAsB,CAAC;AACzF,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAE5C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;;;;;AAKjD,0FAA0F;AAC1F,qBAAa,iBAAkB,SAAQ,sBAKrC;CAAG;;IAcD,kFAAkF;2BAC3D,CACrB,UAAU,EAAE,cAAc,EAC1B,IAAI,EAAE,UAAU,EAChB,QAAQ,EAAE,iBAAiB,KACxB,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,MAAM,CAAC,EAAE,cAAc,CAAC;;AAT7D,oFAAoF;AACpF,qBAAa,gBAAiB,SAAQ,qBAUD;IACnC,MAAM,CAAC,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,gBAAgB,EAAE,KAAK,EAAE,SAAS,GAAG,UAAU,CAAC,UAAU,CAAC,CA4E1F;CACL"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { RepositoryName, splitRepositoryName } from "@usine/core/repository";
|
|
2
|
+
import { ItemNumber } from "@usine/core/item";
|
|
3
|
+
import { Clock, Context, Effect, Layer, Schema } from "effect";
|
|
4
|
+
import { HttpClient, HttpClientRequest, HttpClientResponse } from "effect/unstable/http";
|
|
5
|
+
import { GitHubApp } from "./github-app.js";
|
|
6
|
+
import { API_ROOT, authorized, invalidResponse, statusError, transportError } from "./http.js";
|
|
7
|
+
const LabelResponse = Schema.Array(Schema.Struct({ name: Schema.NonEmptyString }));
|
|
8
|
+
const LabelNames = Schema.Array(Schema.NonEmptyString).check(Schema.isUnique());
|
|
9
|
+
/** Labels to add and remove on one Item. Labels outside these two sets are left alone. */
|
|
10
|
+
export class ItemLabelMutation extends Schema.Class("@usine/github/ItemLabelMutation")({
|
|
11
|
+
add: LabelNames.check(Schema.isNonEmpty()),
|
|
12
|
+
remove: LabelNames,
|
|
13
|
+
}) {
|
|
14
|
+
}
|
|
15
|
+
const labelsUrl = (repository, item) => {
|
|
16
|
+
const { name, owner } = splitRepositoryName(repository);
|
|
17
|
+
return `${API_ROOT}/repos/${encodeURIComponent(owner)}/${encodeURIComponent(name)}/issues/${item}/labels`;
|
|
18
|
+
};
|
|
19
|
+
const labelUrl = (repository, item, label) => `${labelsUrl(repository, item)}/${encodeURIComponent(label)}`;
|
|
20
|
+
/** Label writes on GitHub Items, used when the Board moves a card between lanes. */
|
|
21
|
+
export class GitHubItemWriter extends Context.Service()("@usine/github/GitHubItemWriter") {
|
|
22
|
+
static layer = Layer.effect(GitHubItemWriter, Effect.gen(function* () {
|
|
23
|
+
const app = yield* GitHubApp;
|
|
24
|
+
const http = yield* HttpClient.HttpClient;
|
|
25
|
+
const send = Effect.fn("GitHubItemWriter.sendLabelUpdate")(function* (request) {
|
|
26
|
+
return yield* http
|
|
27
|
+
.execute(request)
|
|
28
|
+
.pipe(Effect.mapError((error) => transportError("update-item-labels", error)));
|
|
29
|
+
});
|
|
30
|
+
const decode = (response) => HttpClientResponse.schemaBodyJson(LabelResponse)(response).pipe(Effect.mapError((error) => invalidResponse("update-item-labels", error.message)));
|
|
31
|
+
return {
|
|
32
|
+
updateLabels: Effect.fn("GitHubItemWriter.updateLabels")(function* (repository, item, mutation) {
|
|
33
|
+
yield* Effect.annotateCurrentSpan({ repository, item });
|
|
34
|
+
const token = yield* app.installationToken();
|
|
35
|
+
const addResponse = yield* send(HttpClientRequest.post(labelsUrl(repository, item)).pipe(HttpClientRequest.bodyJsonUnsafe({ labels: mutation.add }), authorized(token.value)));
|
|
36
|
+
if (addResponse.status < 200 || addResponse.status >= 300) {
|
|
37
|
+
return yield* statusError("update-item-labels", addResponse, yield* Clock.currentTimeMillis);
|
|
38
|
+
}
|
|
39
|
+
let applied = yield* decode(addResponse);
|
|
40
|
+
for (const label of mutation.remove) {
|
|
41
|
+
const removeResponse = yield* send(HttpClientRequest.delete(labelUrl(repository, item, label)).pipe(authorized(token.value)));
|
|
42
|
+
if (removeResponse.status === 404) {
|
|
43
|
+
yield* Effect.logDebug("Lane label was already absent during Board move", {
|
|
44
|
+
repository,
|
|
45
|
+
item,
|
|
46
|
+
label,
|
|
47
|
+
});
|
|
48
|
+
continue;
|
|
49
|
+
}
|
|
50
|
+
if (removeResponse.status < 200 || removeResponse.status >= 300) {
|
|
51
|
+
return yield* statusError("update-item-labels", removeResponse, yield* Clock.currentTimeMillis);
|
|
52
|
+
}
|
|
53
|
+
applied = yield* decode(removeResponse);
|
|
54
|
+
}
|
|
55
|
+
yield* Effect.logInfo("GitHub Item lane labels updated from a Board move", {
|
|
56
|
+
repository,
|
|
57
|
+
item,
|
|
58
|
+
addedLabels: mutation.add.join(", "),
|
|
59
|
+
removedLabels: mutation.remove.join(", "),
|
|
60
|
+
labels: applied.map(({ name }) => name).join(", "),
|
|
61
|
+
});
|
|
62
|
+
return applied.map(({ name }) => name);
|
|
63
|
+
}),
|
|
64
|
+
};
|
|
65
|
+
}));
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=item-writer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"item-writer.js","sourceRoot":"","sources":["../src/item-writer.ts"],"names":[],"mappings":"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"}
|
package/dist/jwt.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { Effect, Redacted } from "effect";
|
|
2
|
+
import { AppAuthenticationError, type AppCredentials } from "./credentials.ts";
|
|
3
|
+
/** Signs an App JWT with `iat` backdated a minute for clock skew and `exp` under GitHub's ten-minute cap. */
|
|
4
|
+
type AppJwtSigner = () => Effect.Effect<Redacted.Redacted<string>>;
|
|
5
|
+
/**
|
|
6
|
+
* Imports the App private key once with WebCrypto RS256. A key that cannot be
|
|
7
|
+
* imported fails here, when the layer is built, not on the first request.
|
|
8
|
+
*/
|
|
9
|
+
export declare const appJwtSigner: (credentials: AppCredentials) => Effect.Effect<AppJwtSigner, AppAuthenticationError, never>;
|
|
10
|
+
export {};
|
|
11
|
+
//# sourceMappingURL=jwt.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jwt.d.ts","sourceRoot":"","sources":["../src/jwt.ts"],"names":[],"mappings":"AAAA,OAAO,EAAS,MAAM,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AACjD,OAAO,EAAE,sBAAsB,EAAE,KAAK,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAoE/E,6GAA6G;AAC7G,KAAK,YAAY,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC;AAEnE;;;GAGG;AACH,eAAO,MAAM,YAAY,6FA6BvB,CAAC"}
|
package/dist/jwt.js
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { Clock, Effect, Redacted } from "effect";
|
|
2
|
+
import { AppAuthenticationError } from "./credentials.js";
|
|
3
|
+
const encoder = new TextEncoder();
|
|
4
|
+
const RSA_ALGORITHM_IDENTIFIER = new Uint8Array([
|
|
5
|
+
0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00,
|
|
6
|
+
]);
|
|
7
|
+
const concat = (...values) => {
|
|
8
|
+
const output = new Uint8Array(values.reduce((size, value) => size + value.length, 0));
|
|
9
|
+
let offset = 0;
|
|
10
|
+
for (const value of values) {
|
|
11
|
+
output.set(value, offset);
|
|
12
|
+
offset += value.length;
|
|
13
|
+
}
|
|
14
|
+
return output;
|
|
15
|
+
};
|
|
16
|
+
const derLength = (length) => {
|
|
17
|
+
if (length < 0x80)
|
|
18
|
+
return new Uint8Array([length]);
|
|
19
|
+
const bytes = [];
|
|
20
|
+
for (let remaining = length; remaining > 0; remaining >>>= 8)
|
|
21
|
+
bytes.unshift(remaining & 0xff);
|
|
22
|
+
return new Uint8Array([0x80 | bytes.length, ...bytes]);
|
|
23
|
+
};
|
|
24
|
+
const der = (tag, value) => concat(new Uint8Array([tag]), derLength(value.length), value);
|
|
25
|
+
/** WebCrypto imports PKCS#8 keys only, and GitHub downloads PKCS#1, so wrap the key. */
|
|
26
|
+
const wrapPkcs1AsPkcs8 = (pkcs1) => der(0x30, concat(new Uint8Array([0x02, 0x01, 0x00]), RSA_ALGORITHM_IDENTIFIER, der(0x04, pkcs1)));
|
|
27
|
+
const decodePem = (pem) => {
|
|
28
|
+
const pkcs1 = pem.includes("-----BEGIN RSA PRIVATE KEY-----");
|
|
29
|
+
const base64 = pem
|
|
30
|
+
.replace(/-----BEGIN (?:RSA )?PRIVATE KEY-----/gu, "")
|
|
31
|
+
.replace(/-----END (?:RSA )?PRIVATE KEY-----/gu, "")
|
|
32
|
+
.replace(/\s/gu, "");
|
|
33
|
+
const binary = atob(base64);
|
|
34
|
+
const bytes = Uint8Array.from(binary, (character) => character.charCodeAt(0));
|
|
35
|
+
return pkcs1 ? wrapPkcs1AsPkcs8(bytes) : bytes;
|
|
36
|
+
};
|
|
37
|
+
const base64Url = (value) => {
|
|
38
|
+
let binary = "";
|
|
39
|
+
for (const byte of value)
|
|
40
|
+
binary += String.fromCharCode(byte);
|
|
41
|
+
return btoa(binary).replace(/=/gu, "").replace(/\+/gu, "-").replace(/\//gu, "_");
|
|
42
|
+
};
|
|
43
|
+
const encodeJson = (value) => base64Url(encoder.encode(JSON.stringify(value)));
|
|
44
|
+
const toArrayBuffer = (value) => {
|
|
45
|
+
const buffer = new ArrayBuffer(value.byteLength);
|
|
46
|
+
new Uint8Array(buffer).set(value);
|
|
47
|
+
return buffer;
|
|
48
|
+
};
|
|
49
|
+
/**
|
|
50
|
+
* Imports the App private key once with WebCrypto RS256. A key that cannot be
|
|
51
|
+
* imported fails here, when the layer is built, not on the first request.
|
|
52
|
+
*/
|
|
53
|
+
export const appJwtSigner = Effect.fn("AppJwt.import")(function* (credentials) {
|
|
54
|
+
const key = yield* Effect.tryPromise({
|
|
55
|
+
try: async () => crypto.subtle.importKey("pkcs8", toArrayBuffer(decodePem(Redacted.value(credentials.privateKey))), { name: "RSASSA-PKCS1-v1_5", hash: "SHA-256" }, false, ["sign"]),
|
|
56
|
+
catch: () => new AppAuthenticationError({
|
|
57
|
+
message: "The GitHub App private key is not an RSA private key WebCrypto can import",
|
|
58
|
+
}),
|
|
59
|
+
});
|
|
60
|
+
const sign = Effect.fn("AppJwt.sign")(function* () {
|
|
61
|
+
const now = Math.floor((yield* Clock.currentTimeMillis) / 1_000);
|
|
62
|
+
const unsigned = `${encodeJson({ alg: "RS256", typ: "JWT" })}.${encodeJson({
|
|
63
|
+
iat: now - 60,
|
|
64
|
+
exp: now + 9 * 60,
|
|
65
|
+
iss: credentials.appId,
|
|
66
|
+
})}`;
|
|
67
|
+
const signature = yield* Effect.promise(() => crypto.subtle.sign("RSASSA-PKCS1-v1_5", key, toArrayBuffer(encoder.encode(unsigned))));
|
|
68
|
+
return Redacted.make(`${unsigned}.${base64Url(new Uint8Array(signature))}`);
|
|
69
|
+
});
|
|
70
|
+
return sign;
|
|
71
|
+
});
|
|
72
|
+
//# sourceMappingURL=jwt.js.map
|
package/dist/jwt.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jwt.js","sourceRoot":"","sources":["../src/jwt.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { RepositoryName } from "@usine/core/repository";
|
|
2
|
+
import { Context, Effect, Layer, Schema } from "effect";
|
|
3
|
+
import { HttpClient } from "effect/unstable/http";
|
|
4
|
+
import { GitHubApp } from "./github-app.ts";
|
|
5
|
+
import type { GitHubAppError } from "./error.ts";
|
|
6
|
+
import { RepositoryLabel } from "./polling/labels.ts";
|
|
7
|
+
declare const NewRepositoryLabel_base: Schema.Class<NewRepositoryLabel, Schema.Struct<{
|
|
8
|
+
readonly name: Schema.brand<Schema.NonEmptyString, "GitHubRepositoryLabelName">;
|
|
9
|
+
readonly color: Schema.Option<Schema.brand<Schema.String, "GitHubRepositoryLabelColor">>;
|
|
10
|
+
readonly description: Schema.Option<Schema.String>;
|
|
11
|
+
}>, {}>;
|
|
12
|
+
/** One label definition as GitHub's create-label endpoint accepts it. */
|
|
13
|
+
export declare class NewRepositoryLabel extends NewRepositoryLabel_base {
|
|
14
|
+
}
|
|
15
|
+
declare const GitHubLabelWriter_base: Context.ServiceClass<GitHubLabelWriter, "@usine/github/GitHubLabelWriter", {
|
|
16
|
+
readonly create: (repository: RepositoryName, label: NewRepositoryLabel) => Effect.Effect<RepositoryLabel, GitHubAppError>;
|
|
17
|
+
}>;
|
|
18
|
+
/** Creates repository labels under the App installation token. */
|
|
19
|
+
export declare class GitHubLabelWriter extends GitHubLabelWriter_base {
|
|
20
|
+
static readonly layer: Layer.Layer<GitHubLabelWriter, never, GitHubApp | HttpClient.HttpClient>;
|
|
21
|
+
}
|
|
22
|
+
export {};
|
|
23
|
+
//# sourceMappingURL=label-writer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"label-writer.d.ts","sourceRoot":"","sources":["../src/label-writer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAuB,MAAM,wBAAwB,CAAC;AAC7E,OAAO,EAAS,OAAO,EAAE,MAAM,EAAE,KAAK,EAAU,MAAM,EAAE,MAAM,QAAQ,CAAC;AACvE,OAAO,EAAE,UAAU,EAAyC,MAAM,sBAAsB,CAAC;AACzF,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAE5C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AACjD,OAAO,EAAE,eAAe,EAA6C,MAAM,qBAAqB,CAAC;;;;;;AAEjG,yEAAyE;AACzE,qBAAa,kBAAmB,SAAQ,uBAMtC;CAAG;;qBAuBgB,CACf,UAAU,EAAE,cAAc,EAC1B,KAAK,EAAE,kBAAkB,KACtB,MAAM,CAAC,MAAM,CAAC,eAAe,EAAE,cAAc,CAAC;;AAPvD,kEAAkE;AAClE,qBAAa,iBAAkB,SAAQ,sBAQD;IACpC,MAAM,CAAC,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,iBAAiB,EAAE,KAAK,EAAE,SAAS,GAAG,UAAU,CAAC,UAAU,CAAC,CA4C3F;CACL"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { RepositoryName, splitRepositoryName } from "@usine/core/repository";
|
|
2
|
+
import { Clock, Context, Effect, Layer, Option, Schema } from "effect";
|
|
3
|
+
import { HttpClient, HttpClientRequest, HttpClientResponse } from "effect/unstable/http";
|
|
4
|
+
import { GitHubApp } from "./github-app.js";
|
|
5
|
+
import { API_ROOT, authorized, invalidResponse, statusError, transportError } from "./http.js";
|
|
6
|
+
import { RepositoryLabel, RepositoryLabelColor, RepositoryLabelName } from "./polling/labels.js";
|
|
7
|
+
/** One label definition as GitHub's create-label endpoint accepts it. */
|
|
8
|
+
export class NewRepositoryLabel extends Schema.Class("@usine/github/NewRepositoryLabel")({
|
|
9
|
+
name: RepositoryLabelName,
|
|
10
|
+
color: Schema.Option(RepositoryLabelColor),
|
|
11
|
+
description: Schema.Option(Schema.String),
|
|
12
|
+
}) {
|
|
13
|
+
}
|
|
14
|
+
const CreateLabelResponse = Schema.Struct({
|
|
15
|
+
name: RepositoryLabelName,
|
|
16
|
+
color: RepositoryLabelColor,
|
|
17
|
+
description: Schema.NullOr(Schema.String),
|
|
18
|
+
});
|
|
19
|
+
const labelsUrl = (repository) => {
|
|
20
|
+
const { name, owner } = splitRepositoryName(repository);
|
|
21
|
+
return `${API_ROOT}/repos/${encodeURIComponent(owner)}/${encodeURIComponent(name)}/labels`;
|
|
22
|
+
};
|
|
23
|
+
/** Creates repository labels under the App installation token. */
|
|
24
|
+
export class GitHubLabelWriter extends Context.Service()("@usine/github/GitHubLabelWriter") {
|
|
25
|
+
static layer = Layer.effect(GitHubLabelWriter, Effect.gen(function* () {
|
|
26
|
+
const app = yield* GitHubApp;
|
|
27
|
+
const http = yield* HttpClient.HttpClient;
|
|
28
|
+
return {
|
|
29
|
+
create: Effect.fn("GitHubLabelWriter.create")(function* (repository, label) {
|
|
30
|
+
yield* Effect.annotateCurrentSpan({ repository, label: label.name });
|
|
31
|
+
const token = yield* app.installationToken();
|
|
32
|
+
const body = { name: label.name };
|
|
33
|
+
if (Option.isSome(label.color))
|
|
34
|
+
body.color = label.color.value;
|
|
35
|
+
if (Option.isSome(label.description))
|
|
36
|
+
body.description = label.description.value;
|
|
37
|
+
const request = HttpClientRequest.post(labelsUrl(repository)).pipe(HttpClientRequest.bodyJsonUnsafe(body), authorized(token.value));
|
|
38
|
+
const response = yield* http
|
|
39
|
+
.execute(request)
|
|
40
|
+
.pipe(Effect.mapError((error) => transportError("create-repository-label", error)));
|
|
41
|
+
if (response.status < 200 || response.status >= 300) {
|
|
42
|
+
return yield* statusError("create-repository-label", response, yield* Clock.currentTimeMillis);
|
|
43
|
+
}
|
|
44
|
+
const created = yield* HttpClientResponse.schemaBodyJson(CreateLabelResponse)(response).pipe(Effect.mapError((error) => invalidResponse("create-repository-label", error.message)));
|
|
45
|
+
return new RepositoryLabel({
|
|
46
|
+
name: created.name,
|
|
47
|
+
color: created.color,
|
|
48
|
+
description: Option.fromNullishOr(created.description),
|
|
49
|
+
});
|
|
50
|
+
}),
|
|
51
|
+
};
|
|
52
|
+
}));
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=label-writer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"label-writer.js","sourceRoot":"","sources":["../src/label-writer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { InstanceDirectory } from "@usine/core/instance";
|
|
2
|
+
import { Effect, FileSystem, Layer, Path, Schema } from "effect";
|
|
3
|
+
import { AppCredentials, GitHubCredentials } from "./credentials.ts";
|
|
4
|
+
export declare const GITHUB_APP_SECRETS_PATH = ".usine/github-app.json";
|
|
5
|
+
declare const EnvironmentCredentialsError_base: Schema.Class<EnvironmentCredentialsError, Schema.TaggedStruct<"EnvironmentCredentialsError", {
|
|
6
|
+
readonly message: Schema.NonEmptyString;
|
|
7
|
+
}>, import("effect/Cause").YieldableError>;
|
|
8
|
+
export declare class EnvironmentCredentialsError extends EnvironmentCredentialsError_base {
|
|
9
|
+
}
|
|
10
|
+
export declare const SecretsFileReason: Schema.Literals<readonly ["read", "permissions", "parse"]>;
|
|
11
|
+
export type SecretsFileReason = typeof SecretsFileReason.Type;
|
|
12
|
+
declare const SecretsFileError_base: Schema.Class<SecretsFileError, Schema.TaggedStruct<"SecretsFileError", {
|
|
13
|
+
readonly path: Schema.NonEmptyString;
|
|
14
|
+
readonly reason: Schema.Literals<readonly ["read", "permissions", "parse"]>;
|
|
15
|
+
readonly message: Schema.NonEmptyString;
|
|
16
|
+
}>, import("effect/Cause").YieldableError>;
|
|
17
|
+
export declare class SecretsFileError extends SecretsFileError_base {
|
|
18
|
+
}
|
|
19
|
+
export declare const LocalSecretsError: Schema.Union<readonly [typeof EnvironmentCredentialsError, typeof SecretsFileError]>;
|
|
20
|
+
export type LocalSecretsError = typeof LocalSecretsError.Type;
|
|
21
|
+
/**
|
|
22
|
+
* Loads the orchestrator's App credentials. An environment variable wins over
|
|
23
|
+
* its file field, and the file is not read when both variables are set.
|
|
24
|
+
*/
|
|
25
|
+
export declare const loadLocalCredentials: (root: string & import("effect/Brand").Brand<"InstanceDirectory">) => Effect.Effect<AppCredentials, EnvironmentCredentialsError | SecretsFileError, FileSystem.FileSystem | Path.Path>;
|
|
26
|
+
export declare const localSecretsLayer: (root: InstanceDirectory) => Layer.Layer<GitHubCredentials, LocalSecretsError, FileSystem.FileSystem | Path.Path>;
|
|
27
|
+
export {};
|
|
28
|
+
//# sourceMappingURL=local-secrets.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"local-secrets.d.ts","sourceRoot":"","sources":["../src/local-secrets.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AACzD,OAAO,EAAU,MAAM,EAAE,UAAU,EAAE,KAAK,EAAU,IAAI,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AACjF,OAAO,EAAE,cAAc,EAAS,iBAAiB,EAAsB,MAAM,kBAAkB,CAAC;AAEhG,eAAO,MAAM,uBAAuB,2BAA2B,CAAC;;;;AAEhE,qBAAa,2BAA4B,SAAQ,gCAI/C;CAAG;AAEL,eAAO,MAAM,iBAAiB,4DAAoD,CAAC;AACnF,MAAM,MAAM,iBAAiB,GAAG,OAAO,iBAAiB,CAAC,IAAI,CAAC;;;;;;AAE9D,qBAAa,gBAAiB,SAAQ,qBAMpC;CAAG;AAEL,eAAO,MAAM,iBAAiB,sFAAgE,CAAC;AAC/F,MAAM,MAAM,iBAAiB,GAAG,OAAO,iBAAiB,CAAC,IAAI,CAAC;AAwC9D;;;GAGG;AACH,eAAO,MAAM,oBAAoB,wLAoB/B,CAAC;AAEH,eAAO,MAAM,iBAAiB,SACtB,iBAAiB,KACtB,KAAK,CAAC,KAAK,CAAC,iBAAiB,EAAE,iBAAiB,EAAE,UAAU,CAAC,UAAU,GAAG,IAAI,CAAC,IAAI,CACzB,CAAC"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { InstanceDirectory } from "@usine/core/instance";
|
|
2
|
+
import { Config, Effect, FileSystem, Layer, Option, Path, Schema } from "effect";
|
|
3
|
+
import { AppCredentials, AppId, GitHubCredentials, RedactedPrivateKey } from "./credentials.js";
|
|
4
|
+
export const GITHUB_APP_SECRETS_PATH = ".usine/github-app.json";
|
|
5
|
+
export class EnvironmentCredentialsError extends Schema.TaggedError("@usine/github/EnvironmentCredentialsError")("EnvironmentCredentialsError", {
|
|
6
|
+
message: Schema.NonEmptyString,
|
|
7
|
+
}) {
|
|
8
|
+
}
|
|
9
|
+
export const SecretsFileReason = Schema.Literals(["read", "permissions", "parse"]);
|
|
10
|
+
export class SecretsFileError extends Schema.TaggedError("@usine/github/SecretsFileError")("SecretsFileError", {
|
|
11
|
+
path: Schema.NonEmptyString,
|
|
12
|
+
reason: SecretsFileReason,
|
|
13
|
+
message: Schema.NonEmptyString,
|
|
14
|
+
}) {
|
|
15
|
+
}
|
|
16
|
+
export const LocalSecretsError = Schema.Union([EnvironmentCredentialsError, SecretsFileError]);
|
|
17
|
+
const AppIdFromString = Schema.FiniteFromString.pipe(Schema.decodeTo(AppId));
|
|
18
|
+
/** Each variable may be absent on its own. A present but invalid one is an error, not a fallback to the file. */
|
|
19
|
+
const environment = Config.all({
|
|
20
|
+
appId: Config.option(Config.schema(AppIdFromString, "USINE_GITHUB_APP_ID")),
|
|
21
|
+
privateKey: Config.option(Config.schema(RedactedPrivateKey, "USINE_GITHUB_PRIVATE_KEY")),
|
|
22
|
+
});
|
|
23
|
+
const AppCredentialsFile = Schema.fromJsonString(Schema.Struct({ appId: AppId, privateKey: RedactedPrivateKey }).pipe(Schema.encodeKeys({ appId: "app_id", privateKey: "private_key" })));
|
|
24
|
+
const decodeCredentialsFile = Schema.decodeUnknownEffect(AppCredentialsFile);
|
|
25
|
+
const readSecretsFile = Effect.fn("GitHubCredentials.readSecretsFile")(function* (root) {
|
|
26
|
+
const fileSystem = yield* FileSystem.FileSystem;
|
|
27
|
+
const path = yield* Path.Path;
|
|
28
|
+
const secretsPath = path.join(root, GITHUB_APP_SECRETS_PATH);
|
|
29
|
+
const fail = (reason, message) => new SecretsFileError({ path: secretsPath, reason, message });
|
|
30
|
+
const unreadable = () => fail("read", `Could not read GitHub App secrets at ${secretsPath}`);
|
|
31
|
+
const info = yield* fileSystem.stat(secretsPath).pipe(Effect.mapError(unreadable));
|
|
32
|
+
if (info.type !== "File" || (info.mode & 0o777) !== 0o600) {
|
|
33
|
+
return yield* fail("permissions", `GitHub App secrets must be a regular 0600 file: ${secretsPath}`);
|
|
34
|
+
}
|
|
35
|
+
const source = yield* fileSystem.readFileString(secretsPath).pipe(Effect.mapError(unreadable));
|
|
36
|
+
return yield* decodeCredentialsFile(source, { onExcessProperty: "error" }).pipe(Effect.mapError(() => fail("parse", `GitHub App secrets are invalid at ${secretsPath}`)));
|
|
37
|
+
});
|
|
38
|
+
/**
|
|
39
|
+
* Loads the orchestrator's App credentials. An environment variable wins over
|
|
40
|
+
* its file field, and the file is not read when both variables are set.
|
|
41
|
+
*/
|
|
42
|
+
export const loadLocalCredentials = Effect.fn("GitHubCredentials.loadLocal")(function* (root) {
|
|
43
|
+
const env = yield* environment.pipe(Effect.mapError(() => new EnvironmentCredentialsError({
|
|
44
|
+
message: "USINE_GITHUB_APP_ID and USINE_GITHUB_PRIVATE_KEY must contain valid GitHub App credentials",
|
|
45
|
+
})));
|
|
46
|
+
if (Option.isSome(env.appId) && Option.isSome(env.privateKey)) {
|
|
47
|
+
return new AppCredentials({ appId: env.appId.value, privateKey: env.privateKey.value });
|
|
48
|
+
}
|
|
49
|
+
const file = yield* readSecretsFile(root);
|
|
50
|
+
return new AppCredentials({
|
|
51
|
+
appId: Option.getOrElse(env.appId, () => file.appId),
|
|
52
|
+
privateKey: Option.getOrElse(env.privateKey, () => file.privateKey),
|
|
53
|
+
});
|
|
54
|
+
});
|
|
55
|
+
export const localSecretsLayer = (root) => Layer.effect(GitHubCredentials, loadLocalCredentials(root));
|
|
56
|
+
//# sourceMappingURL=local-secrets.js.map
|