git-dlp 0.2.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.
- package/README.md +290 -0
- package/dist/git-dl.js +43 -0
- package/dist/git-dl.js.map +1 -0
- package/dist/package.json +138 -0
- package/dist/src/TaggedErrorVerifyingCause.js +27 -0
- package/dist/src/TaggedErrorVerifyingCause.js.map +1 -0
- package/dist/src/castToReadableStream.js +28 -0
- package/dist/src/castToReadableStream.js.map +1 -0
- package/dist/src/cli.js +8 -0
- package/dist/src/cli.js.map +1 -0
- package/dist/src/commandLineParams.js +172 -0
- package/dist/src/commandLineParams.js.map +1 -0
- package/dist/src/commonErrors.js +60 -0
- package/dist/src/commonErrors.js.map +1 -0
- package/dist/src/configContext.js +12 -0
- package/dist/src/configContext.js.map +1 -0
- package/dist/src/downloadEntityFromRepo.js +21 -0
- package/dist/src/downloadEntityFromRepo.js.map +1 -0
- package/dist/src/errors.js +10 -0
- package/dist/src/errors.js.map +1 -0
- package/dist/src/getPathContents/ParsedMetaInfoAboutPathContentsFromGitHubAPI.js +43 -0
- package/dist/src/getPathContents/ParsedMetaInfoAboutPathContentsFromGitHubAPI.js.map +1 -0
- package/dist/src/getPathContents/PathContentsMetaInfo.js +71 -0
- package/dist/src/getPathContents/PathContentsMetaInfo.js.map +1 -0
- package/dist/src/getPathContents/RawStreamOfRepoPathContentsFromGitHubAPI.js +4 -0
- package/dist/src/getPathContents/RawStreamOfRepoPathContentsFromGitHubAPI.js.map +1 -0
- package/dist/src/getPathContents/RepoPathContentsFromGitHubAPI.js +51 -0
- package/dist/src/getPathContents/RepoPathContentsFromGitHubAPI.js.map +1 -0
- package/dist/src/getPathContents/index.js +5 -0
- package/dist/src/getPathContents/index.js.map +1 -0
- package/dist/src/getPathContents/parseGitLFSObjectEither.js +70 -0
- package/dist/src/getPathContents/parseGitLFSObjectEither.js.map +1 -0
- package/dist/src/getReadableTarGzStreamOfRepoDirectory.js +39 -0
- package/dist/src/getReadableTarGzStreamOfRepoDirectory.js.map +1 -0
- package/dist/src/index.js +8 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/octokit.js +6 -0
- package/dist/src/octokit.js.map +1 -0
- package/dist/src/unpackRepoFolderTarGzStreamToFs.js +31 -0
- package/dist/src/unpackRepoFolderTarGzStreamToFs.js.map +1 -0
- package/dist/src/writeFileStreamToDestinationPath.js +22 -0
- package/dist/src/writeFileStreamToDestinationPath.js.map +1 -0
- package/dist-types/git-dl.d.ts +3 -0
- package/dist-types/git-dl.d.ts.map +1 -0
- package/dist-types/src/TaggedErrorVerifyingCause.d.ts +38 -0
- package/dist-types/src/TaggedErrorVerifyingCause.d.ts.map +1 -0
- package/dist-types/src/castToReadableStream.d.ts +11 -0
- package/dist-types/src/castToReadableStream.d.ts.map +1 -0
- package/dist-types/src/cli.d.ts +8 -0
- package/dist-types/src/cli.d.ts.map +1 -0
- package/dist-types/src/commandLineParams.d.ts +108 -0
- package/dist-types/src/commandLineParams.d.ts.map +1 -0
- package/dist-types/src/commonErrors.d.ts +60 -0
- package/dist-types/src/commonErrors.d.ts.map +1 -0
- package/dist-types/src/configContext.d.ts +44 -0
- package/dist-types/src/configContext.d.ts.map +1 -0
- package/dist-types/src/downloadEntityFromRepo.d.ts +11 -0
- package/dist-types/src/downloadEntityFromRepo.d.ts.map +1 -0
- package/dist-types/src/errors.d.ts +10 -0
- package/dist-types/src/errors.d.ts.map +1 -0
- package/dist-types/src/getPathContents/ParsedMetaInfoAboutPathContentsFromGitHubAPI.d.ts +141 -0
- package/dist-types/src/getPathContents/ParsedMetaInfoAboutPathContentsFromGitHubAPI.d.ts.map +1 -0
- package/dist-types/src/getPathContents/PathContentsMetaInfo.d.ts +66 -0
- package/dist-types/src/getPathContents/PathContentsMetaInfo.d.ts.map +1 -0
- package/dist-types/src/getPathContents/RawStreamOfRepoPathContentsFromGitHubAPI.d.ts +9 -0
- package/dist-types/src/getPathContents/RawStreamOfRepoPathContentsFromGitHubAPI.d.ts.map +1 -0
- package/dist-types/src/getPathContents/RepoPathContentsFromGitHubAPI.d.ts +81 -0
- package/dist-types/src/getPathContents/RepoPathContentsFromGitHubAPI.d.ts.map +1 -0
- package/dist-types/src/getPathContents/index.d.ts +5 -0
- package/dist-types/src/getPathContents/index.d.ts.map +1 -0
- package/dist-types/src/getPathContents/parseGitLFSObjectEither.d.ts +40 -0
- package/dist-types/src/getPathContents/parseGitLFSObjectEither.d.ts.map +1 -0
- package/dist-types/src/getReadableTarGzStreamOfRepoDirectory.d.ts +13 -0
- package/dist-types/src/getReadableTarGzStreamOfRepoDirectory.d.ts.map +1 -0
- package/dist-types/src/index.d.ts +9 -0
- package/dist-types/src/index.d.ts.map +1 -0
- package/dist-types/src/octokit.d.ts +8 -0
- package/dist-types/src/octokit.d.ts.map +1 -0
- package/dist-types/src/unpackRepoFolderTarGzStreamToFs.d.ts +16 -0
- package/dist-types/src/unpackRepoFolderTarGzStreamToFs.d.ts.map +1 -0
- package/dist-types/src/writeFileStreamToDestinationPath.d.ts +16 -0
- package/dist-types/src/writeFileStreamToDestinationPath.d.ts.map +1 -0
- package/package.json +139 -0
- package/src/TaggedErrorVerifyingCause.ts +142 -0
- package/src/castToReadableStream.ts +44 -0
- package/src/cli.ts +14 -0
- package/src/commandLineParams.ts +257 -0
- package/src/commonErrors.ts +139 -0
- package/src/configContext.ts +46 -0
- package/src/downloadEntityFromRepo.ts +86 -0
- package/src/errors.ts +24 -0
- package/src/getPathContents/ParsedMetaInfoAboutPathContentsFromGitHubAPI.ts +76 -0
- package/src/getPathContents/PathContentsMetaInfo.ts +85 -0
- package/src/getPathContents/RawStreamOfRepoPathContentsFromGitHubAPI.ts +6 -0
- package/src/getPathContents/RepoPathContentsFromGitHubAPI.ts +82 -0
- package/src/getPathContents/index.ts +7 -0
- package/src/getPathContents/parseGitLFSObjectEither.ts +143 -0
- package/src/getReadableTarGzStreamOfRepoDirectory.ts +65 -0
- package/src/index.ts +13 -0
- package/src/octokit.ts +15 -0
- package/src/unpackRepoFolderTarGzStreamToFs.ts +61 -0
- package/src/writeFileStreamToDestinationPath.ts +45 -0
- package/template.env +13 -0
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
import { outdent } from 'outdent';
|
|
2
|
+
import * as CLIOptions from '@effect/cli/Options';
|
|
3
|
+
import * as Path from '@effect/platform/Path';
|
|
4
|
+
import * as Config from 'effect/Config';
|
|
5
|
+
import * as Effect from 'effect/Effect';
|
|
6
|
+
import * as EFunction from 'effect/Function';
|
|
7
|
+
import * as ParseResult from 'effect/ParseResult';
|
|
8
|
+
import * as Schema from 'effect/Schema';
|
|
9
|
+
const isGitHubSlug = (s) => !!s.match(/^[a-z0-9.\-_]+$/gi);
|
|
10
|
+
const invalidGitHubSlugMessage = 'GitHub handle should have only ASCII letters, digits, and the characters ".", "-", and "_"';
|
|
11
|
+
// https://developer.mozilla.org/en-US/docs/Glossary/Slug
|
|
12
|
+
const GitHubSlugStringSchema = Schema.NonEmptyString.pipe(Schema.filter(s => isGitHubSlug(s) || invalidGitHubSlugMessage));
|
|
13
|
+
// TODO change approach to default values. Either remove defaults completely or
|
|
14
|
+
// provided an easy way to set for people their own defaults instead of
|
|
15
|
+
// comparing them to the hardcoded default value. Also document the helpers for
|
|
16
|
+
// overriding defaults in TSDoc of exported CLIOptions objects
|
|
17
|
+
const withGitHubSlugConfigValidation = Config.validate({
|
|
18
|
+
message: invalidGitHubSlugMessage,
|
|
19
|
+
validation: isGitHubSlug,
|
|
20
|
+
});
|
|
21
|
+
const pathToEntityInRepoDescription = 'Path to file or directory in repo';
|
|
22
|
+
const repoOwnerDescription = outdent `
|
|
23
|
+
This is a username (login handle) of a person owning repo you
|
|
24
|
+
are trying to download from. For example, if the repository's URL is
|
|
25
|
+
\`https://github.com/apache/superset\`, the owner is \`apache\`
|
|
26
|
+
`;
|
|
27
|
+
const repoNameDescription = outdent `
|
|
28
|
+
This is the name handle of the repository you are trying to download
|
|
29
|
+
from. For example, if the repository's URL is
|
|
30
|
+
\`https://github.com/apache/superset\`, the name is \`superset\`
|
|
31
|
+
`;
|
|
32
|
+
const destinationPathDescription = outdent `
|
|
33
|
+
Local path of the downloaded file or directory. If
|
|
34
|
+
"pathToEntityInRepo" points to a file, then last element of the
|
|
35
|
+
destination path will be new file name. If "pathToEntityInRepo" points
|
|
36
|
+
to a directory then all files and directories inside directory at
|
|
37
|
+
"pathToEntityInRepo" will be put into a directory with name equal last
|
|
38
|
+
element of destination path. If the directory doesn't exist, it will
|
|
39
|
+
be automatically created.
|
|
40
|
+
`;
|
|
41
|
+
const gitRefDescription = outdent `
|
|
42
|
+
This is the commit's SHA hash, branch name, tag name, or any other ref
|
|
43
|
+
you want to download from. If you don't specify it, the default branch
|
|
44
|
+
in the repository will be used.
|
|
45
|
+
`;
|
|
46
|
+
const RepoNameConfig = EFunction.pipe(Config.nonEmptyString('REPO_NAME'), withGitHubSlugConfigValidation, Config.withDescription(repoNameDescription));
|
|
47
|
+
const RepoOwnerConfig = EFunction.pipe(Config.nonEmptyString('REPO_OWNER'), withGitHubSlugConfigValidation, Config.withDescription(repoOwnerDescription));
|
|
48
|
+
const DestinationPathConfig = EFunction.pipe(Config.nonEmptyString('DESTINATION_PATH'), Config.withDefault('./destination'), Config.withDescription(destinationPathDescription));
|
|
49
|
+
const PathToEntityInRepoConfig = EFunction.pipe(Config.nonEmptyString('PATH_TO_ENTITY_IN_REPO'), Config.withDefault('.'), Config.withDescription(pathToEntityInRepoDescription));
|
|
50
|
+
const GitRefConfig = EFunction.pipe(Config.nonEmptyString('GIT_REF'), Config.withDefault('HEAD'), Config.withDescription(gitRefDescription));
|
|
51
|
+
const CleanRepoEntityPathString = Schema.transformOrFail(Schema.NonEmptyString, Schema.NonEmptyString, {
|
|
52
|
+
strict: true,
|
|
53
|
+
decode: (dirtyPathToEntityInRepo, _, ast) => Effect.flatMap(Path.Path, path => {
|
|
54
|
+
// dot can be there only when that's all there is. path.join(...)
|
|
55
|
+
// removes all './', so '.' will never be just left by themself. If it's
|
|
56
|
+
// there, it's very intentional and no other elements in the path exist.
|
|
57
|
+
const cleanPathToEntityInRepo = path
|
|
58
|
+
.join(dirtyPathToEntityInRepo)
|
|
59
|
+
.replaceAll(/\/?$/g, '');
|
|
60
|
+
if (cleanPathToEntityInRepo.startsWith('..'))
|
|
61
|
+
return ParseResult.fail(new ParseResult.Type(ast, dirtyPathToEntityInRepo, "Can't request contents that lie higher than the root of the repo"));
|
|
62
|
+
return ParseResult.succeed(cleanPathToEntityInRepo);
|
|
63
|
+
}),
|
|
64
|
+
encode: ParseResult.succeed,
|
|
65
|
+
});
|
|
66
|
+
/**
|
|
67
|
+
* Text parameter containing path to a directory or a file inside target repo.
|
|
68
|
+
*
|
|
69
|
+
* Can be passed in two ways:
|
|
70
|
+
* 1. As CLI option `gdl --pathToEntityInRepo nestedFolder/Readme.md`
|
|
71
|
+
* 2. As env variable `PATH_TO_ENTITY_IN_REPO="nestedFolder/Readme.md" gdl`
|
|
72
|
+
*
|
|
73
|
+
* Has default: `.`, which means that if not specified, script will download
|
|
74
|
+
* entire repository (download root directory of the repository)
|
|
75
|
+
*
|
|
76
|
+
* Parameter is automatically validated to not point higher than the root of the
|
|
77
|
+
* repository.
|
|
78
|
+
*
|
|
79
|
+
* @since 0.1.7
|
|
80
|
+
* @category CLI options
|
|
81
|
+
* @constant
|
|
82
|
+
*/
|
|
83
|
+
export const pathToEntityInRepoCLIOptionBackedByEnv = EFunction.pipe(CLIOptions.text(`pathToEntityInRepo`), CLIOptions.withDescription(pathToEntityInRepoDescription), CLIOptions.withFallbackConfig(PathToEntityInRepoConfig), CLIOptions.withSchema(CleanRepoEntityPathString));
|
|
84
|
+
/**
|
|
85
|
+
* Text parameter containing URL slug of the user which owns the repo.
|
|
86
|
+
*
|
|
87
|
+
* Examples:
|
|
88
|
+
* 1. `apache`
|
|
89
|
+
* 2. `nikelborm`
|
|
90
|
+
*
|
|
91
|
+
* Can be passed in two ways:
|
|
92
|
+
* 1. As CLI option `gdl --repoOwner apache`
|
|
93
|
+
* 2. As env variable `REPO_OWNER="apache" gdl`
|
|
94
|
+
*
|
|
95
|
+
* Doesn`t have defaults and will fail if not specified.
|
|
96
|
+
*
|
|
97
|
+
* Parameter is automatically validated so it can consist of only ASCII letters,
|
|
98
|
+
* digits, and the characters `.`, `-`, and `_`.
|
|
99
|
+
*
|
|
100
|
+
* @since 0.1.7
|
|
101
|
+
* @category CLI options
|
|
102
|
+
* @constant
|
|
103
|
+
*/
|
|
104
|
+
export const repoOwnerCLIOptionBackedByEnv = EFunction.pipe(CLIOptions.text(`repoOwner`), CLIOptions.withDescription(repoOwnerDescription), CLIOptions.withFallbackConfig(RepoOwnerConfig), CLIOptions.withSchema(GitHubSlugStringSchema));
|
|
105
|
+
/**
|
|
106
|
+
* Text parameter containing URL slug of the repo itself.
|
|
107
|
+
*
|
|
108
|
+
* Examples:
|
|
109
|
+
* 1. `superset`
|
|
110
|
+
* 2. `git-dl`
|
|
111
|
+
*
|
|
112
|
+
* Can be passed in two ways:
|
|
113
|
+
* 1. As CLI option `gdl --repoName superset`
|
|
114
|
+
* 2. As env variable `REPO_NAME="superset" gdl`
|
|
115
|
+
*
|
|
116
|
+
* Doesn`t have defaults and will fail if not specified.
|
|
117
|
+
*
|
|
118
|
+
* Parameter is automatically validated so it can consist of only ASCII letters,
|
|
119
|
+
* digits, and the characters `.`, `-`, and `_`.
|
|
120
|
+
*
|
|
121
|
+
* @since 0.1.7
|
|
122
|
+
* @category CLI options
|
|
123
|
+
* @constant
|
|
124
|
+
*/
|
|
125
|
+
export const repoNameCLIOptionBackedByEnv = EFunction.pipe(CLIOptions.text(`repoName`), CLIOptions.withDescription(repoNameDescription), CLIOptions.withFallbackConfig(RepoNameConfig), CLIOptions.withSchema(GitHubSlugStringSchema));
|
|
126
|
+
/**
|
|
127
|
+
* Text parameter containing path inside your local file system, your new
|
|
128
|
+
* file/directory will be placed at. Last element of the path will be the name
|
|
129
|
+
* of the new file/directory.
|
|
130
|
+
*
|
|
131
|
+
* Examples:
|
|
132
|
+
* 1. `../docker`
|
|
133
|
+
* 2. `/tmp/Readme.md`
|
|
134
|
+
*
|
|
135
|
+
* Can be passed in two ways:
|
|
136
|
+
* 1. As CLI option `gdl --destinationPath docker`
|
|
137
|
+
* 2. As env variable `DESTINATION_PATH="docker" gdl`
|
|
138
|
+
*
|
|
139
|
+
* Has default: `./destination`, which means that if not specified, script will
|
|
140
|
+
* either create a file or a directory named `destination` inside your current PWD
|
|
141
|
+
* depending on the type of remote target.
|
|
142
|
+
*
|
|
143
|
+
* @since 0.1.7
|
|
144
|
+
* @category CLI options
|
|
145
|
+
* @constant
|
|
146
|
+
* @readonly
|
|
147
|
+
*/
|
|
148
|
+
export const destinationPathCLIOptionBackedByEnv = EFunction.pipe(CLIOptions.text(`destinationPath`), CLIOptions.withDescription(destinationPathDescription), CLIOptions.withFallbackConfig(DestinationPathConfig));
|
|
149
|
+
/**
|
|
150
|
+
* Text parameter containing commit SHA hash, branch name, or tag name you want
|
|
151
|
+
* to download from.
|
|
152
|
+
*
|
|
153
|
+
* Examples:
|
|
154
|
+
* 1. `HEAD`
|
|
155
|
+
* 2. `main`
|
|
156
|
+
* 3. `4.1.1`
|
|
157
|
+
* 4. `dca3efb3dd2a2a75aea32e3561c4104a53f02808`
|
|
158
|
+
* 5. `dca3efb`
|
|
159
|
+
*
|
|
160
|
+
* Can be passed in two ways:
|
|
161
|
+
* 1. As CLI option `gdl --gitRef 4.1.1`
|
|
162
|
+
* 2. As env variable `GIT_REF="4.1.1" gdl`
|
|
163
|
+
*
|
|
164
|
+
* Has default: `HEAD`, which means that if not specified, the default branch in
|
|
165
|
+
* the repository will be used.
|
|
166
|
+
*
|
|
167
|
+
* @since 0.1.7
|
|
168
|
+
* @category CLI options
|
|
169
|
+
* @constant
|
|
170
|
+
*/
|
|
171
|
+
export const gitRefCLIOptionBackedByEnv = EFunction.pipe(CLIOptions.text(`gitRef`), CLIOptions.withDescription(gitRefDescription), CLIOptions.withFallbackConfig(GitRefConfig));
|
|
172
|
+
//# sourceMappingURL=commandLineParams.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"commandLineParams.js","sourceRoot":"","sources":["../../src/commandLineParams.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { RequestError } from '@octokit/request-error';
|
|
2
|
+
import { buildTaggedErrorClassVerifyingCause, } from "./TaggedErrorVerifyingCause.js";
|
|
3
|
+
// Extracting to a separate type is required by JSR, so that consumers of the
|
|
4
|
+
// library will have much faster type inference
|
|
5
|
+
const _1 = buildTaggedErrorClassVerifyingCause()('GitHubApiGeneralServerError', 'GitHub API Error: Bad server', RequestError);
|
|
6
|
+
export class GitHubApiGeneralServerError extends _1 {
|
|
7
|
+
}
|
|
8
|
+
// Extracting to a separate type is required by JSR, so that consumers of the
|
|
9
|
+
// library will have much faster type inference
|
|
10
|
+
const _2 = buildTaggedErrorClassVerifyingCause()('GitHubApiGeneralUserError', 'GitHub API Error: Bad user, invalid request', RequestError);
|
|
11
|
+
export class GitHubApiGeneralUserError extends _2 {
|
|
12
|
+
}
|
|
13
|
+
// Extracting to a separate type is required by JSR, so that consumers of the
|
|
14
|
+
// library will have much faster type inference
|
|
15
|
+
const _3 = buildTaggedErrorClassVerifyingCause()('GitHubApiThingNotExistsOrYouDontHaveAccessError', "GitHub API Error: Either repo, owner, path in repo, or specified ref don't exist or you don't have permissions to access it", RequestError);
|
|
16
|
+
export class GitHubApiThingNotExistsOrYouDontHaveAccessError extends _3 {
|
|
17
|
+
}
|
|
18
|
+
// Extracting to a separate type is required by JSR, so that consumers of the
|
|
19
|
+
// library will have much faster type inference
|
|
20
|
+
const _4 = buildTaggedErrorClassVerifyingCause()('GitHubApiRepoIsEmptyError', 'GitHub API Error: This Repo is empty', RequestError);
|
|
21
|
+
export class GitHubApiRepoIsEmptyError extends _4 {
|
|
22
|
+
}
|
|
23
|
+
// Extracting to a separate type is required by JSR, so that consumers of the
|
|
24
|
+
// library will have much faster type inference
|
|
25
|
+
const _5 = buildTaggedErrorClassVerifyingCause()('GitHubApiNoCommitFoundForGitRefError', 'GitHub API Error: No commit found for this git ref', RequestError);
|
|
26
|
+
export class GitHubApiNoCommitFoundForGitRefError extends _5 {
|
|
27
|
+
}
|
|
28
|
+
// Extracting to a separate type is required by JSR, so that consumers of the
|
|
29
|
+
// library will have much faster type inference
|
|
30
|
+
const _6 = buildTaggedErrorClassVerifyingCause()('GitHubApiBadCredentialsError', "GitHub API Error: Token you're using is invalid.", RequestError);
|
|
31
|
+
export class GitHubApiBadCredentialsError extends _6 {
|
|
32
|
+
}
|
|
33
|
+
// Extracting to a separate type is required by JSR, so that consumers of the
|
|
34
|
+
// library will have much faster type inference
|
|
35
|
+
const _7 = buildTaggedErrorClassVerifyingCause()('GitHubApiAuthRatelimitedError', 'GitHub API Error: Too many invalid auth attempts. Chillout pal', RequestError);
|
|
36
|
+
export class GitHubApiAuthRatelimitedError extends _7 {
|
|
37
|
+
}
|
|
38
|
+
// Extracting to a separate type is required by JSR, so that consumers of the
|
|
39
|
+
// library will have much faster type inference
|
|
40
|
+
const _8 = buildTaggedErrorClassVerifyingCause()('GitHubApiRatelimitedError', 'GitHub API Error: Too many requests. Chillout pal', RequestError);
|
|
41
|
+
export class GitHubApiRatelimitedError extends _8 {
|
|
42
|
+
}
|
|
43
|
+
export const parseCommonGitHubApiErrors = (error) => {
|
|
44
|
+
if (error.status === 401)
|
|
45
|
+
return new GitHubApiBadCredentialsError(error);
|
|
46
|
+
// https://docs.github.com/en/rest/authentication/authenticating-to-the-rest-api?apiVersion=2022-11-28#failed-login-limit
|
|
47
|
+
if (error.status === 403)
|
|
48
|
+
return new GitHubApiAuthRatelimitedError(error);
|
|
49
|
+
// docs.github.com/en/rest/using-the-rest-api/rate-limits-for-the-rest-api?apiVersion=2022-11-28
|
|
50
|
+
if (error.status === 429)
|
|
51
|
+
return new GitHubApiRatelimitedError(error);
|
|
52
|
+
if (error.status === 404)
|
|
53
|
+
return new GitHubApiThingNotExistsOrYouDontHaveAccessError(error);
|
|
54
|
+
if (error.status >= 500)
|
|
55
|
+
return new GitHubApiGeneralServerError(error);
|
|
56
|
+
if (error.status >= 400)
|
|
57
|
+
return new GitHubApiGeneralUserError(error, {});
|
|
58
|
+
return error;
|
|
59
|
+
};
|
|
60
|
+
//# sourceMappingURL=commonErrors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"commonErrors.js","sourceRoot":"","sources":["../../src/commonErrors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAA;AAErD,OAAO,EACL,mCAAmC,GAEpC,MAAM,gCAAgC,CAAA;AAEvC,6EAA6E;AAC7E,+CAA+C;AAC/C,MAAM,EAAE,GAGH,mCAAmC,EAAE,CACxC,6BAA6B,EAC7B,8BAA8B,EAC9B,YAAY,CACb,CAAA;AAED,MAAM,OAAO,2BAA4B,SAAQ,EAAE;CAAG;AAEtD,6EAA6E;AAC7E,+CAA+C;AAC/C,MAAM,EAAE,GAIH,mCAAmC,EAA+B,CACrE,2BAA2B,EAC3B,6CAA6C,EAC7C,YAAY,CACb,CAAA;AAED,MAAM,OAAO,yBAA0B,SAAQ,EAAE;CAAG;AAEpD,6EAA6E;AAC7E,+CAA+C;AAC/C,MAAM,EAAE,GAGH,mCAAmC,EAAE,CACxC,iDAAiD,EACjD,6HAA6H,EAC7H,YAAY,CACb,CAAA;AAED,MAAM,OAAO,+CAAgD,SAAQ,EAAE;CAAG;AAE1E,6EAA6E;AAC7E,+CAA+C;AAC/C,MAAM,EAAE,GAGH,mCAAmC,EAAE,CACxC,2BAA2B,EAC3B,sCAAsC,EACtC,YAAY,CACb,CAAA;AAED,MAAM,OAAO,yBAA0B,SAAQ,EAAE;CAAG;AAEpD,6EAA6E;AAC7E,+CAA+C;AAC/C,MAAM,EAAE,GAIH,mCAAmC,EAAsB,CAC5D,sCAAsC,EACtC,oDAAoD,EACpD,YAAY,CACb,CAAA;AAED,MAAM,OAAO,oCAAqC,SAAQ,EAAE;CAAG;AAE/D,6EAA6E;AAC7E,+CAA+C;AAC/C,MAAM,EAAE,GAGH,mCAAmC,EAAE,CACxC,8BAA8B,EAC9B,kDAAkD,EAClD,YAAY,CACb,CAAA;AAED,MAAM,OAAO,4BAA6B,SAAQ,EAAE;CAAG;AAEvD,6EAA6E;AAC7E,+CAA+C;AAC/C,MAAM,EAAE,GAGH,mCAAmC,EAAE,CACxC,+BAA+B,EAC/B,gEAAgE,EAChE,YAAY,CACb,CAAA;AAED,MAAM,OAAO,6BAA8B,SAAQ,EAAE;CAAG;AAExD,6EAA6E;AAC7E,+CAA+C;AAC/C,MAAM,EAAE,GAGH,mCAAmC,EAAE,CACxC,2BAA2B,EAC3B,mDAAmD,EACnD,YAAY,CACb,CAAA;AAED,MAAM,OAAO,yBAA0B,SAAQ,EAAE;CAAG;AAEpD,MAAM,CAAC,MAAM,0BAA0B,GAAG,CAAC,KAAmB,EAAE,EAAE;IAChE,IAAI,KAAK,CAAC,MAAM,KAAK,GAAG;QAAE,OAAO,IAAI,4BAA4B,CAAC,KAAK,CAAC,CAAA;IAExE,yHAAyH;IACzH,IAAI,KAAK,CAAC,MAAM,KAAK,GAAG;QAAE,OAAO,IAAI,6BAA6B,CAAC,KAAK,CAAC,CAAA;IAEzE,gGAAgG;IAChG,IAAI,KAAK,CAAC,MAAM,KAAK,GAAG;QAAE,OAAO,IAAI,yBAAyB,CAAC,KAAK,CAAC,CAAA;IAErE,IAAI,KAAK,CAAC,MAAM,KAAK,GAAG;QACtB,OAAO,IAAI,+CAA+C,CAAC,KAAK,CAAC,CAAA;IAEnE,IAAI,KAAK,CAAC,MAAM,IAAI,GAAG;QAAE,OAAO,IAAI,2BAA2B,CAAC,KAAK,CAAC,CAAA;IAEtE,IAAI,KAAK,CAAC,MAAM,IAAI,GAAG;QAAE,OAAO,IAAI,yBAAyB,CAAC,KAAK,EAAE,EAAE,CAAC,CAAA;IAExE,OAAO,KAAK,CAAA;AACd,CAAC,CAAA"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import * as Context from 'effect/Context';
|
|
2
|
+
import * as Effect from 'effect/Effect';
|
|
3
|
+
import * as Layer from 'effect/Layer';
|
|
4
|
+
export const InputConfigTag = Context.GenericTag('InputConfig');
|
|
5
|
+
export const OutputConfigTag = Context.GenericTag('OutputConfig');
|
|
6
|
+
const InputConfigLive = (inputConfig) => Layer.succeed(InputConfigTag, InputConfigTag.of(inputConfig));
|
|
7
|
+
export const provideInputConfig = (inputConfig) => Effect.provide(InputConfigLive(inputConfig));
|
|
8
|
+
const OutputConfigLive = (outputConfig) => Layer.succeed(OutputConfigTag, OutputConfigTag.of(outputConfig));
|
|
9
|
+
export const provideSingleDownloadTargetConfig = ({ localPathAtWhichEntityFromRepoWillBeAvailable, ...inputConfig }) => Effect.provide(Layer.merge(InputConfigLive(inputConfig), OutputConfigLive({
|
|
10
|
+
localPathAtWhichEntityFromRepoWillBeAvailable,
|
|
11
|
+
})));
|
|
12
|
+
//# sourceMappingURL=configContext.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"configContext.js","sourceRoot":"","sources":["../../src/configContext.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,OAAO,MAAM,gBAAgB,CAAA;AACzC,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AACvC,OAAO,KAAK,KAAK,MAAM,cAAc,CAAA;AAWrC,MAAM,CAAC,MAAM,cAAc,GAAG,OAAO,CAAC,UAAU,CAAc,aAAa,CAAC,CAAA;AAM5E,MAAM,CAAC,MAAM,eAAe,GAAG,OAAO,CAAC,UAAU,CAAe,cAAc,CAAC,CAAA;AAE/E,MAAM,eAAe,GAAG,CAAC,WAAwB,EAAE,EAAE,CACnD,KAAK,CAAC,OAAO,CAAC,cAAc,EAAE,cAAc,CAAC,EAAE,CAAC,WAAW,CAAC,CAAC,CAAA;AAE/D,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,WAAwB,EAAE,EAAE,CAC7D,MAAM,CAAC,OAAO,CAAC,eAAe,CAAC,WAAW,CAAC,CAAC,CAAA;AAE9C,MAAM,gBAAgB,GAAG,CAAC,YAA0B,EAAE,EAAE,CACtD,KAAK,CAAC,OAAO,CAAC,eAAe,EAAE,eAAe,CAAC,EAAE,CAAC,YAAY,CAAC,CAAC,CAAA;AAIlE,MAAM,CAAC,MAAM,iCAAiC,GAAG,CAAC,EAChD,6CAA6C,EAC7C,GAAG,WAAW,EACK,EAE6C,EAAE,CAClE,MAAM,CAAC,OAAO,CACZ,KAAK,CAAC,KAAK,CACT,eAAe,CAAC,WAAW,CAAC,EAC5B,gBAAgB,CAAC;IACf,6CAA6C;CAC9C,CAAC,CACH,CACF,CAAA"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import * as Effect from 'effect/Effect';
|
|
2
|
+
import { provideSingleDownloadTargetConfig, } from "./configContext.js";
|
|
3
|
+
import { PathContentsMetaInfo, RawStreamOfRepoPathContentsFromGitHubAPI, } from "./getPathContents/index.js";
|
|
4
|
+
import { getReadableTarGzStreamOfRepoDirectory } from "./getReadableTarGzStreamOfRepoDirectory.js";
|
|
5
|
+
import { unpackRepoFolderTarGzStreamToFs, } from "./unpackRepoFolderTarGzStreamToFs.js";
|
|
6
|
+
import { writeFileStreamToDestinationPath, } from "./writeFileStreamToDestinationPath.js";
|
|
7
|
+
const downloadEntityFromRepoWithoutContext = Effect.gen(function* () {
|
|
8
|
+
const pathContentsMetaInfo = yield* PathContentsMetaInfo;
|
|
9
|
+
if (pathContentsMetaInfo.type === 'dir')
|
|
10
|
+
return yield* unpackRepoFolderTarGzStreamToFs(getReadableTarGzStreamOfRepoDirectory(pathContentsMetaInfo.treeSha));
|
|
11
|
+
if (pathContentsMetaInfo.meta ===
|
|
12
|
+
'This file is small enough that GitHub API decided to inline it')
|
|
13
|
+
return yield* writeFileStreamToDestinationPath(pathContentsMetaInfo.contentStream);
|
|
14
|
+
if (pathContentsMetaInfo.meta === 'This file can be downloaded as a blob')
|
|
15
|
+
return yield* writeFileStreamToDestinationPath(RawStreamOfRepoPathContentsFromGitHubAPI);
|
|
16
|
+
yield* Effect.dieMessage('LFS files are not yet supported');
|
|
17
|
+
});
|
|
18
|
+
// Extracting to a separate type is required by JSR, so that consumers of the
|
|
19
|
+
// library will have much faster type inference
|
|
20
|
+
export const downloadEntityFromRepo = (target) => downloadEntityFromRepoWithoutContext.pipe(provideSingleDownloadTargetConfig(target));
|
|
21
|
+
//# sourceMappingURL=downloadEntityFromRepo.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"downloadEntityFromRepo.js","sourceRoot":"","sources":["../../src/downloadEntityFromRepo.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AAavC,OAAO,EACL,iCAAiC,GAElC,MAAM,oBAAoB,CAAA;AAC3B,OAAO,EAGL,oBAAoB,EACpB,wCAAwC,GACzC,MAAM,4BAA4B,CAAA;AACnC,OAAO,EAAE,qCAAqC,EAAE,MAAM,4CAA4C,CAAA;AAClG,OAAO,EAEL,+BAA+B,GAChC,MAAM,sCAAsC,CAAA;AAC7C,OAAO,EAEL,gCAAgC,GACjC,MAAM,uCAAuC,CAAA;AAE9C,MAAM,oCAAoC,GAAG,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;IAC/D,MAAM,oBAAoB,GAAG,KAAK,CAAC,CAAC,oBAAoB,CAAA;IAExD,IAAI,oBAAoB,CAAC,IAAI,KAAK,KAAK;QACrC,OAAO,KAAK,CAAC,CAAC,+BAA+B,CAC3C,qCAAqC,CAAC,oBAAoB,CAAC,OAAO,CAAC,CACpE,CAAA;IAEH,IACE,oBAAoB,CAAC,IAAI;QACzB,gEAAgE;QAEhE,OAAO,KAAK,CAAC,CAAC,gCAAgC,CAC5C,oBAAoB,CAAC,aAAa,CACnC,CAAA;IAEH,IAAI,oBAAoB,CAAC,IAAI,KAAK,uCAAuC;QACvE,OAAO,KAAK,CAAC,CAAC,gCAAgC,CAC5C,wCAAwC,CACzC,CAAA;IAEH,KAAK,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC,iCAAiC,CAAC,CAAA;AAC7D,CAAC,CAAC,CAAA;AAEF,6EAA6E;AAC7E,+CAA+C;AAC/C,MAAM,CAAC,MAAM,sBAAsB,GAAG,CACpC,MAA0B,EAmB1B,EAAE,CACF,oCAAoC,CAAC,IAAI,CACvC,iCAAiC,CAAC,MAAM,CAAC,CAC1C,CAAA"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module
|
|
3
|
+
*/
|
|
4
|
+
export { FailedToCastDataToReadableStreamError } from "./castToReadableStream.js";
|
|
5
|
+
export { GitHubApiAuthRatelimitedError, GitHubApiBadCredentialsError, GitHubApiGeneralServerError, GitHubApiGeneralUserError, GitHubApiNoCommitFoundForGitRefError, GitHubApiRatelimitedError, GitHubApiRepoIsEmptyError, GitHubApiThingNotExistsOrYouDontHaveAccessError, } from "./commonErrors.js";
|
|
6
|
+
export { FailedToParseGitLFSInfoError, FailedToParseResponseFromRepoPathContentsMetaInfoAPIError, InconsistentExpectedAndRealContentSizeError, } from "./getPathContents/index.js";
|
|
7
|
+
export * from "./TaggedErrorVerifyingCause.js";
|
|
8
|
+
export { FailedToUnpackRepoFolderTarGzStreamToFsError } from "./unpackRepoFolderTarGzStreamToFs.js";
|
|
9
|
+
export { FailedToWriteFileStreamToDestinationPathError } from "./writeFileStreamToDestinationPath.js";
|
|
10
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/errors.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,qCAAqC,EAAE,MAAM,2BAA2B,CAAA;AACjF,OAAO,EACL,6BAA6B,EAC7B,4BAA4B,EAE5B,2BAA2B,EAC3B,yBAAyB,EACzB,oCAAoC,EACpC,yBAAyB,EACzB,yBAAyB,EACzB,+CAA+C,GAChD,MAAM,mBAAmB,CAAA;AAC1B,OAAO,EACL,4BAA4B,EAC5B,yDAAyD,EACzD,2CAA2C,GAC5C,MAAM,4BAA4B,CAAA;AACnC,cAAc,gCAAgC,CAAA;AAC9C,OAAO,EAAE,4CAA4C,EAAE,MAAM,sCAAsC,CAAA;AACnG,OAAO,EAAE,6CAA6C,EAAE,MAAM,uCAAuC,CAAA"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import * as Effect from 'effect/Effect';
|
|
2
|
+
import * as Either from 'effect/Either';
|
|
3
|
+
import * as ParseResult from 'effect/ParseResult';
|
|
4
|
+
import * as Schema from 'effect/Schema';
|
|
5
|
+
import { buildTaggedErrorClassVerifyingCause, } from "../TaggedErrorVerifyingCause.js";
|
|
6
|
+
import { RepoPathContentsFromGitHubAPI } from "./RepoPathContentsFromGitHubAPI.js";
|
|
7
|
+
export const UnparsedMetaInfoAboutPathContentsFromGitHubAPI = RepoPathContentsFromGitHubAPI('object');
|
|
8
|
+
export const ParsedMetaInfoAboutPathContentsFromGitHubAPI = Effect.gen(function* () {
|
|
9
|
+
const response = yield* UnparsedMetaInfoAboutPathContentsFromGitHubAPI;
|
|
10
|
+
return yield* Either.mapLeft(decodeResponse(response.data), parseError => new FailedToParseResponseFromRepoPathContentsMetaInfoAPIError(parseError, {
|
|
11
|
+
response,
|
|
12
|
+
}));
|
|
13
|
+
});
|
|
14
|
+
const GitSomethingFields = {
|
|
15
|
+
size: Schema.Number,
|
|
16
|
+
name: Schema.String,
|
|
17
|
+
path: Schema.String,
|
|
18
|
+
sha: Schema.String,
|
|
19
|
+
};
|
|
20
|
+
const dirLiteral = Schema.Literal('dir');
|
|
21
|
+
const nonDirLiterals = Schema.Literal('file', 'submodule', 'symlink');
|
|
22
|
+
export const ResponseSchema = Schema.Union(Schema.Struct({
|
|
23
|
+
type: Schema.Literal('dir'),
|
|
24
|
+
entries: Schema.Struct({
|
|
25
|
+
type: Schema.Union(dirLiteral, nonDirLiterals),
|
|
26
|
+
...GitSomethingFields,
|
|
27
|
+
}).pipe(Schema.Array),
|
|
28
|
+
...GitSomethingFields,
|
|
29
|
+
}), Schema.Struct({
|
|
30
|
+
type: Schema.Literal('file'),
|
|
31
|
+
encoding: Schema.Literal('base64', 'none'),
|
|
32
|
+
content: Schema.String,
|
|
33
|
+
...GitSomethingFields,
|
|
34
|
+
}));
|
|
35
|
+
const decodeResponse = Schema.decodeUnknownEither(ResponseSchema, {
|
|
36
|
+
exact: true,
|
|
37
|
+
});
|
|
38
|
+
// Extracting to a separate type is required by JSR, so that consumers of the
|
|
39
|
+
// library will have much faster type inference
|
|
40
|
+
const _1 = buildTaggedErrorClassVerifyingCause()('FailedToParseResponseFromRepoPathContentsMetaInfoAPI', `Failed to parse response from repo path contents meta info API`, ParseResult.ParseError);
|
|
41
|
+
export class FailedToParseResponseFromRepoPathContentsMetaInfoAPIError extends _1 {
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=ParsedMetaInfoAboutPathContentsFromGitHubAPI.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ParsedMetaInfoAboutPathContentsFromGitHubAPI.js","sourceRoot":"","sources":["../../../src/getPathContents/ParsedMetaInfoAboutPathContentsFromGitHubAPI.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AACvC,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AACvC,OAAO,KAAK,WAAW,MAAM,oBAAoB,CAAA;AACjD,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AAEvC,OAAO,EACL,mCAAmC,GAEpC,MAAM,iCAAiC,CAAA;AACxC,OAAO,EAAE,6BAA6B,EAAE,MAAM,oCAAoC,CAAA;AAElF,MAAM,CAAC,MAAM,8CAA8C,GACzD,6BAA6B,CAAC,QAAQ,CAAC,CAAA;AAEzC,MAAM,CAAC,MAAM,4CAA4C,GAAG,MAAM,CAAC,GAAG,CACpE,QAAQ,CAAC;IACP,MAAM,QAAQ,GAAG,KAAK,CAAC,CAAC,8CAA8C,CAAA;IAEtE,OAAO,KAAK,CAAC,CAAC,MAAM,CAAC,OAAO,CAC1B,cAAc,CAAC,QAAQ,CAAC,IAAI,CAAC,EAC7B,UAAU,CAAC,EAAE,CACX,IAAI,yDAAyD,CAC3D,UAAU,EACV;QACE,QAAQ;KACT,CACF,CACJ,CAAA;AACH,CAAC,CACF,CAAA;AAED,MAAM,kBAAkB,GAAG;IACzB,IAAI,EAAE,MAAM,CAAC,MAAM;IACnB,IAAI,EAAE,MAAM,CAAC,MAAM;IACnB,IAAI,EAAE,MAAM,CAAC,MAAM;IACnB,GAAG,EAAE,MAAM,CAAC,MAAM;CACnB,CAAA;AAED,MAAM,UAAU,GAAG,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,CAAA;AACxC,MAAM,cAAc,GAAG,MAAM,CAAC,OAAO,CAAC,MAAM,EAAE,WAAW,EAAE,SAAS,CAAC,CAAA;AAErE,MAAM,CAAC,MAAM,cAAc,GAAG,MAAM,CAAC,KAAK,CACxC,MAAM,CAAC,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC;IAC3B,OAAO,EAAE,MAAM,CAAC,MAAM,CAAC;QACrB,IAAI,EAAE,MAAM,CAAC,KAAK,CAAC,UAAU,EAAE,cAAc,CAAC;QAC9C,GAAG,kBAAkB;KACtB,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC;IACrB,GAAG,kBAAkB;CACtB,CAAC,EACF,MAAM,CAAC,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC;IAC5B,QAAQ,EAAE,MAAM,CAAC,OAAO,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1C,OAAO,EAAE,MAAM,CAAC,MAAM;IACtB,GAAG,kBAAkB;CACtB,CAAC,CACH,CAAA;AAED,MAAM,cAAc,GAAG,MAAM,CAAC,mBAAmB,CAAC,cAAc,EAAE;IAChE,KAAK,EAAE,IAAI;CACZ,CAAC,CAAA;AAEF,6EAA6E;AAC7E,+CAA+C;AAE/C,MAAM,EAAE,GAIH,mCAAmC,EAAyB,CAC/D,sDAAsD,EACtD,gEAAgE,EAChE,WAAW,CAAC,UAAU,CACvB,CAAA;AAED,MAAM,OAAO,yDAA0D,SAAQ,EAAE;CAAG"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import * as Effect from 'effect/Effect';
|
|
2
|
+
import { CastToReadableStream } from "../castToReadableStream.js";
|
|
3
|
+
import { ParsedMetaInfoAboutPathContentsFromGitHubAPI } from "./ParsedMetaInfoAboutPathContentsFromGitHubAPI.js";
|
|
4
|
+
import { parseGitLFSObjectEither } from "./parseGitLFSObjectEither.js";
|
|
5
|
+
export const PathContentsMetaInfo = Effect.gen(function* () {
|
|
6
|
+
const response = yield* ParsedMetaInfoAboutPathContentsFromGitHubAPI;
|
|
7
|
+
const { type, name, path, size } = response;
|
|
8
|
+
if (type === 'dir') {
|
|
9
|
+
const { entries, sha: treeSha } = response;
|
|
10
|
+
if (name && path)
|
|
11
|
+
return {
|
|
12
|
+
type,
|
|
13
|
+
name,
|
|
14
|
+
path,
|
|
15
|
+
treeSha,
|
|
16
|
+
entries,
|
|
17
|
+
meta: 'This nested directory can be downloaded as a git tree',
|
|
18
|
+
};
|
|
19
|
+
return {
|
|
20
|
+
type,
|
|
21
|
+
treeSha,
|
|
22
|
+
entries,
|
|
23
|
+
meta: 'This root directory of the repo can be downloaded as a git tree',
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
// This is quite forgiving implementation. I had the choice to throw
|
|
27
|
+
// errors whenever GitHub's API didn't follow its documentation. I even
|
|
28
|
+
// did that initially, but when I looked at the resulting mess, I changed
|
|
29
|
+
// my mind not to. For example, I could throw errors in the following
|
|
30
|
+
// cases:
|
|
31
|
+
// 1. When the size is between 1 MB and 100 MB per documentation, I
|
|
32
|
+
// should never receive data. Instead, I should receive an empty
|
|
33
|
+
// "content" field and an "encoding" field equal to "none." If this
|
|
34
|
+
// promise was broken, I could have thrown an error. Instead, if I
|
|
35
|
+
// receive a 50 MB file with the correct encoding, I will parse and
|
|
36
|
+
// return it.
|
|
37
|
+
// 2. Per the documentation, all files larger than 100 MB should be put
|
|
38
|
+
// into Git LFS storage. If I receive a 110 MB file inlined, I'll not
|
|
39
|
+
// fail; I'll parse and return it.
|
|
40
|
+
// 3. Per documentation when size less than 1MB it MUST be inlined. If it
|
|
41
|
+
// wasn't inlined I could have thrown an error, but instead, I just
|
|
42
|
+
// returned an object representing the message "It's a blob, download
|
|
43
|
+
// it elsewhere"
|
|
44
|
+
// 4. Per documentation files larger than 100 mb must be in a git LFS
|
|
45
|
+
// storage and it's assumed that git LFS annotation will be provided.
|
|
46
|
+
// But if it's not provided, instead of throwing an error, I returned
|
|
47
|
+
// an object representing the message "It's a blob, download it
|
|
48
|
+
// elsewhere"
|
|
49
|
+
// In the end it leads to much lower complexity with a ton of IFs removed
|
|
50
|
+
const { content, encoding, sha: blobSha, ...restFileObjectFields } = response;
|
|
51
|
+
const base = { ...restFileObjectFields, blobSha };
|
|
52
|
+
if (encoding === 'none')
|
|
53
|
+
return { ...base, meta: 'This file can be downloaded as a blob' };
|
|
54
|
+
const contentAsBuffer = Buffer.from(content, encoding);
|
|
55
|
+
const potentialGitLFSObject = yield* parseGitLFSObjectEither({
|
|
56
|
+
contentAsBuffer,
|
|
57
|
+
expectedContentSize: size,
|
|
58
|
+
});
|
|
59
|
+
if (typeof potentialGitLFSObject === 'object')
|
|
60
|
+
return {
|
|
61
|
+
...base,
|
|
62
|
+
...potentialGitLFSObject,
|
|
63
|
+
meta: 'This file can be downloaded as a git-LFS object',
|
|
64
|
+
};
|
|
65
|
+
return {
|
|
66
|
+
...base,
|
|
67
|
+
contentStream: CastToReadableStream(Effect.succeed(contentAsBuffer)),
|
|
68
|
+
meta: 'This file is small enough that GitHub API decided to inline it',
|
|
69
|
+
};
|
|
70
|
+
});
|
|
71
|
+
//# sourceMappingURL=PathContentsMetaInfo.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PathContentsMetaInfo.js","sourceRoot":"","sources":["../../../src/getPathContents/PathContentsMetaInfo.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AAEvC,OAAO,EAAE,oBAAoB,EAAE,MAAM,4BAA4B,CAAA;AACjE,OAAO,EAAE,4CAA4C,EAAE,MAAM,mDAAmD,CAAA;AAChH,OAAO,EAAE,uBAAuB,EAAE,MAAM,8BAA8B,CAAA;AAEtE,MAAM,CAAC,MAAM,oBAAoB,GAAG,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;IACtD,MAAM,QAAQ,GAAG,KAAK,CAAC,CAAC,4CAA4C,CAAA;IAEpE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,QAAQ,CAAA;IAE3C,IAAI,IAAI,KAAK,KAAK,EAAE,CAAC;QACnB,MAAM,EAAE,OAAO,EAAE,GAAG,EAAE,OAAO,EAAE,GAAG,QAAQ,CAAA;QAE1C,IAAI,IAAI,IAAI,IAAI;YACd,OAAO;gBACL,IAAI;gBACJ,IAAI;gBACJ,IAAI;gBACJ,OAAO;gBACP,OAAO;gBACP,IAAI,EAAE,uDAAuD;aACrD,CAAA;QAEZ,OAAO;YACL,IAAI;YACJ,OAAO;YACP,OAAO;YACP,IAAI,EAAE,iEAAiE;SAC/D,CAAA;IACZ,CAAC;IAED,oEAAoE;IACpE,uEAAuE;IACvE,yEAAyE;IACzE,qEAAqE;IACrE,SAAS;IAET,mEAAmE;IACnE,mEAAmE;IACnE,sEAAsE;IACtE,qEAAqE;IACrE,sEAAsE;IACtE,gBAAgB;IAChB,uEAAuE;IACvE,wEAAwE;IACxE,qCAAqC;IACrC,yEAAyE;IACzE,sEAAsE;IACtE,wEAAwE;IACxE,mBAAmB;IACnB,qEAAqE;IACrE,wEAAwE;IACxE,wEAAwE;IACxE,kEAAkE;IAClE,gBAAgB;IAEhB,yEAAyE;IAEzE,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,GAAG,EAAE,OAAO,EAAE,GAAG,oBAAoB,EAAE,GAAG,QAAQ,CAAA;IAC7E,MAAM,IAAI,GAAG,EAAE,GAAG,oBAAoB,EAAE,OAAO,EAAE,CAAA;IAEjD,IAAI,QAAQ,KAAK,MAAM;QACrB,OAAO,EAAE,GAAG,IAAI,EAAE,IAAI,EAAE,uCAAuC,EAAW,CAAA;IAE5E,MAAM,eAAe,GAAG,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAA;IAEtD,MAAM,qBAAqB,GAAG,KAAK,CAAC,CAAC,uBAAuB,CAAC;QAC3D,eAAe;QACf,mBAAmB,EAAE,IAAI;KAC1B,CAAC,CAAA;IAEF,IAAI,OAAO,qBAAqB,KAAK,QAAQ;QAC3C,OAAO;YACL,GAAG,IAAI;YACP,GAAG,qBAAqB;YACxB,IAAI,EAAE,iDAAiD;SAC/C,CAAA;IAEZ,OAAO;QACL,GAAG,IAAI;QACP,aAAa,EAAE,oBAAoB,CAAC,MAAM,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC;QACpE,IAAI,EAAE,gEAAgE;KAC9D,CAAA;AACZ,CAAC,CAAC,CAAA"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { CastToReadableStream } from "../castToReadableStream.js";
|
|
2
|
+
import { RepoPathContentsFromGitHubAPI } from "./RepoPathContentsFromGitHubAPI.js";
|
|
3
|
+
export const RawStreamOfRepoPathContentsFromGitHubAPI = CastToReadableStream(RepoPathContentsFromGitHubAPI('raw', true));
|
|
4
|
+
//# sourceMappingURL=RawStreamOfRepoPathContentsFromGitHubAPI.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RawStreamOfRepoPathContentsFromGitHubAPI.js","sourceRoot":"","sources":["../../../src/getPathContents/RawStreamOfRepoPathContentsFromGitHubAPI.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,4BAA4B,CAAA;AACjE,OAAO,EAAE,6BAA6B,EAAE,MAAM,oCAAoC,CAAA;AAElF,MAAM,CAAC,MAAM,wCAAwC,GAAG,oBAAoB,CAC1E,6BAA6B,CAAC,KAAK,EAAE,IAAI,CAAC,CAC3C,CAAA"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { RequestError } from '@octokit/request-error';
|
|
2
|
+
import * as Cause from 'effect/Cause';
|
|
3
|
+
import * as Effect from 'effect/Effect';
|
|
4
|
+
import { GitHubApiNoCommitFoundForGitRefError, GitHubApiRepoIsEmptyError, GitHubApiThingNotExistsOrYouDontHaveAccessError, parseCommonGitHubApiErrors, } from "../commonErrors.js";
|
|
5
|
+
import { InputConfigTag } from "../configContext.js";
|
|
6
|
+
import { OctokitTag } from "../octokit.js";
|
|
7
|
+
// TODO make better typesignature so that it actually reflects what's returned:
|
|
8
|
+
// stream or parsed body use params as a generic. (but generally fuck github API
|
|
9
|
+
// and their fucking octokit)
|
|
10
|
+
export const RepoPathContentsFromGitHubAPI = Effect.fn('getRepoPathContentsFromGitHubAPI')(function* (format, streamBody) {
|
|
11
|
+
const octokit = yield* OctokitTag;
|
|
12
|
+
const { gitRef, pathToEntityInRepo, repo } = yield* InputConfigTag;
|
|
13
|
+
// TODO: improve sitation on what's default with git ref. Better set null
|
|
14
|
+
// instead of empty string? to signify it's not present actually. Also should
|
|
15
|
+
// note that HEAD could mean something different when ref is not specified.
|
|
16
|
+
// Should consider if we should fallback to HEAD or just not specifiying the
|
|
17
|
+
// property at all.
|
|
18
|
+
return yield* Effect.tryPromise({
|
|
19
|
+
try: signal => octokit.request('GET /repos/{owner}/{repo}/contents/{path}', {
|
|
20
|
+
owner: repo.owner,
|
|
21
|
+
repo: repo.name,
|
|
22
|
+
path: pathToEntityInRepo,
|
|
23
|
+
...(gitRef && { ref: gitRef }),
|
|
24
|
+
request: {
|
|
25
|
+
signal,
|
|
26
|
+
parseSuccessResponseBody: !streamBody,
|
|
27
|
+
},
|
|
28
|
+
mediaType: { format },
|
|
29
|
+
headers: {
|
|
30
|
+
'X-GitHub-Api-Version': '2022-11-28',
|
|
31
|
+
},
|
|
32
|
+
}),
|
|
33
|
+
catch: error => {
|
|
34
|
+
if (!(error instanceof RequestError))
|
|
35
|
+
return new Cause.UnknownException(error, 'Failed to request contents at the path inside GitHub repo');
|
|
36
|
+
const potentialErrorMessage = error.response?.data
|
|
37
|
+
?.message;
|
|
38
|
+
if (error.status === 404 && potentialErrorMessage)
|
|
39
|
+
return parseNotFoundErrors(potentialErrorMessage, error, gitRef);
|
|
40
|
+
return parseCommonGitHubApiErrors(error);
|
|
41
|
+
},
|
|
42
|
+
});
|
|
43
|
+
});
|
|
44
|
+
const parseNotFoundErrors = (potentialErrorMessage, error, gitRef) => {
|
|
45
|
+
if (potentialErrorMessage === 'This repository is empty.')
|
|
46
|
+
return new GitHubApiRepoIsEmptyError(error);
|
|
47
|
+
if (gitRef && potentialErrorMessage.startsWith('No commit found for the ref'))
|
|
48
|
+
return new GitHubApiNoCommitFoundForGitRefError(error, { gitRef });
|
|
49
|
+
return new GitHubApiThingNotExistsOrYouDontHaveAccessError(error);
|
|
50
|
+
};
|
|
51
|
+
//# sourceMappingURL=RepoPathContentsFromGitHubAPI.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RepoPathContentsFromGitHubAPI.js","sourceRoot":"","sources":["../../../src/getPathContents/RepoPathContentsFromGitHubAPI.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAA;AAGrD,OAAO,KAAK,KAAK,MAAM,cAAc,CAAA;AACrC,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AAEvC,OAAO,EACL,oCAAoC,EACpC,yBAAyB,EACzB,+CAA+C,EAC/C,0BAA0B,GAC3B,MAAM,oBAAoB,CAAA;AAC3B,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAA;AACpD,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAA;AAE1C,+EAA+E;AAC/E,gFAAgF;AAChF,6BAA6B;AAC7B,MAAM,CAAC,MAAM,6BAA6B,GAAG,MAAM,CAAC,EAAE,CACpD,kCAAkC,CACnC,CAAC,QAAQ,CAAC,EAAE,MAAwB,EAAE,UAAoB;IACzD,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,UAAU,CAAA;IAEjC,MAAM,EAAE,MAAM,EAAE,kBAAkB,EAAE,IAAI,EAAE,GAAG,KAAK,CAAC,CAAC,cAAc,CAAA;IAClE,yEAAyE;IACzE,6EAA6E;IAC7E,2EAA2E;IAC3E,4EAA4E;IAC5E,mBAAmB;IAEnB,OAAO,KAAK,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC;QAC9B,GAAG,EAAE,MAAM,CAAC,EAAE,CACZ,OAAO,CAAC,OAAO,CAAC,2CAA2C,EAAE;YAC3D,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,IAAI,EAAE,kBAAkB;YACxB,GAAG,CAAC,MAAM,IAAI,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC;YAC9B,OAAO,EAAE;gBACP,MAAM;gBACN,wBAAwB,EAAE,CAAC,UAAU;aACtC;YACD,SAAS,EAAE,EAAE,MAAM,EAAE;YACrB,OAAO,EAAE;gBACP,sBAAsB,EAAE,YAAY;aACrC;SACF,CAAC;QACJ,KAAK,EAAE,KAAK,CAAC,EAAE;YACb,IAAI,CAAC,CAAC,KAAK,YAAY,YAAY,CAAC;gBAClC,OAAO,IAAI,KAAK,CAAC,gBAAgB,CAC/B,KAAK,EACL,2DAA2D,CAC5D,CAAA;YAEH,MAAM,qBAAqB,GAAI,KAAK,CAAC,QAA8B,EAAE,IAAI;gBACvE,EAAE,OAAO,CAAA;YAEX,IAAI,KAAK,CAAC,MAAM,KAAK,GAAG,IAAI,qBAAqB;gBAC/C,OAAO,mBAAmB,CAAC,qBAAqB,EAAE,KAAK,EAAE,MAAM,CAAC,CAAA;YAElE,OAAO,0BAA0B,CAAC,KAAK,CAAC,CAAA;QAC1C,CAAC;KACF,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA;AAEF,MAAM,mBAAmB,GAAG,CAC1B,qBAA6B,EAC7B,KAAmB,EACnB,MAAc,EACd,EAAE;IACF,IAAI,qBAAqB,KAAK,2BAA2B;QACvD,OAAO,IAAI,yBAAyB,CAAC,KAAK,CAAC,CAAA;IAE7C,IAAI,MAAM,IAAI,qBAAqB,CAAC,UAAU,CAAC,6BAA6B,CAAC;QAC3E,OAAO,IAAI,oCAAoC,CAAC,KAAK,EAAE,EAAE,MAAM,EAAE,CAAC,CAAA;IAEpE,OAAO,IAAI,+CAA+C,CAAC,KAAK,CAAC,CAAA;AACnE,CAAC,CAAA"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { FailedToParseResponseFromRepoPathContentsMetaInfoAPIError } from "./ParsedMetaInfoAboutPathContentsFromGitHubAPI.js";
|
|
2
|
+
export { PathContentsMetaInfo } from "./PathContentsMetaInfo.js";
|
|
3
|
+
export { FailedToParseGitLFSInfoError, InconsistentExpectedAndRealContentSizeError, } from "./parseGitLFSObjectEither.js";
|
|
4
|
+
export { RawStreamOfRepoPathContentsFromGitHubAPI } from "./RawStreamOfRepoPathContentsFromGitHubAPI.js";
|
|
5
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/getPathContents/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,yDAAyD,EAAE,MAAM,mDAAmD,CAAA;AAC7H,OAAO,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAA;AAChE,OAAO,EACL,4BAA4B,EAC5B,2CAA2C,GAC5C,MAAM,8BAA8B,CAAA;AACrC,OAAO,EAAE,wCAAwC,EAAE,MAAM,+CAA+C,CAAA"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { outdent } from 'outdent';
|
|
2
|
+
import * as Either from 'effect/Either';
|
|
3
|
+
import * as ParseResult from 'effect/ParseResult';
|
|
4
|
+
import * as Schema from 'effect/Schema';
|
|
5
|
+
import { buildTaggedErrorClassVerifyingCause, } from "../TaggedErrorVerifyingCause.js";
|
|
6
|
+
export const parseGitLFSObjectEither = ({ contentAsBuffer, expectedContentSize, }) => Either.gen(function* () {
|
|
7
|
+
// gitLFS info usually is no longer than MAX_GIT_LFS_INFO_SIZE bytes
|
|
8
|
+
const contentAsString = contentAsBuffer
|
|
9
|
+
.subarray(0, MAX_GIT_LFS_INFO_SIZE)
|
|
10
|
+
.toString('utf8');
|
|
11
|
+
const parsingResult = Either.mapLeft(decodeGitLFSInfoSchema(contentAsString.match(gitLFSInfoRegexp)?.groups), cause => new FailedToParseGitLFSInfoError(cause, {
|
|
12
|
+
partOfContentThatCouldBeGitLFSInfo: contentAsString,
|
|
13
|
+
}));
|
|
14
|
+
const matchedByRegexpAndParsedByEffectSchema = Either.isRight(parsingResult);
|
|
15
|
+
const doesSizeFromGitLFSInfoAlignWithExpectedContentSize = Either.isRight(parsingResult) &&
|
|
16
|
+
parsingResult.right.size === expectedContentSize;
|
|
17
|
+
const shouldFailIfItIsNotGitLFS = contentAsBuffer.byteLength !== expectedContentSize;
|
|
18
|
+
const isThisAGitLFSObject = matchedByRegexpAndParsedByEffectSchema &&
|
|
19
|
+
doesSizeFromGitLFSInfoAlignWithExpectedContentSize;
|
|
20
|
+
if (isThisAGitLFSObject)
|
|
21
|
+
return {
|
|
22
|
+
gitLFSObjectIdSha256: parsingResult.right.oidSha256,
|
|
23
|
+
gitLFSVersion: parsingResult.right.version,
|
|
24
|
+
};
|
|
25
|
+
if (shouldFailIfItIsNotGitLFS)
|
|
26
|
+
return yield* Either.left(new InconsistentExpectedAndRealContentSizeError({
|
|
27
|
+
actual: contentAsBuffer.byteLength,
|
|
28
|
+
expected: expectedContentSize,
|
|
29
|
+
gitLFSInfo: parsingResult,
|
|
30
|
+
}));
|
|
31
|
+
return 'This is not a git LFS object';
|
|
32
|
+
});
|
|
33
|
+
// there are some responses that look like
|
|
34
|
+
// `version https://git-lfs.github.com/spec/v1
|
|
35
|
+
// oid sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
|
|
36
|
+
// size 128
|
|
37
|
+
// `
|
|
38
|
+
// and the only variable thing in it is the size at the end, and I assume
|
|
39
|
+
// that supported file size is not greater than 100 GB
|
|
40
|
+
const MAX_GIT_LFS_INFO_SIZE = 137;
|
|
41
|
+
// Don't add regexp /g modifier, it breaks match groups
|
|
42
|
+
const gitLFSInfoRegexp = /^version (?<version>https:\/\/git-lfs\.github\.com\/spec\/v1)\noid sha256:(?<oidSha256>[0-9a-f]{64})\nsize (?<size>[1-9]\d{0,11})\n$/m;
|
|
43
|
+
const GitLFSInfoSchema = Schema.Struct({
|
|
44
|
+
version: Schema.NonEmptyTrimmedString,
|
|
45
|
+
oidSha256: Schema.NonEmptyTrimmedString,
|
|
46
|
+
size: Schema.NumberFromString,
|
|
47
|
+
});
|
|
48
|
+
const decodeGitLFSInfoSchema = Schema.decodeUnknownEither(GitLFSInfoSchema, {
|
|
49
|
+
exact: true,
|
|
50
|
+
});
|
|
51
|
+
const _1 = buildTaggedErrorClassVerifyingCause()('FailedToParseGitLFSInfoError', `Failed to parse git LFS announcement`, ParseResult.ParseError);
|
|
52
|
+
export class FailedToParseGitLFSInfoError extends _1 {
|
|
53
|
+
}
|
|
54
|
+
// Extracting to a separate type is required by JSR, so that consumers of the
|
|
55
|
+
// library will have much faster type inference
|
|
56
|
+
const _2 = buildTaggedErrorClassVerifyingCause()('InconsistentExpectedAndRealContentSizeError', ctx => `Got file with size ${ctx.actual} bytes while expecting ${ctx.expected} bytes`, void 0, {
|
|
57
|
+
comment: outdent({ newline: ' ' }) `
|
|
58
|
+
If we weren't successful in parsing it as git LFS object
|
|
59
|
+
announcement using RegExp and Effect.Schema, we just do a basic size
|
|
60
|
+
consistency check. The check implements the second marker of it
|
|
61
|
+
being a Git LFS object as a backup to checking does "content" look
|
|
62
|
+
like a Git LFS object. If GitHub API's "size" field is different
|
|
63
|
+
from actual size of "content" field, it means either our schema with
|
|
64
|
+
regexp fucked up, or GitHub API did. If it doesn't throw, it means
|
|
65
|
+
there's no reason to assume it's a Git LFS object.
|
|
66
|
+
`,
|
|
67
|
+
});
|
|
68
|
+
export class InconsistentExpectedAndRealContentSizeError extends _2 {
|
|
69
|
+
}
|
|
70
|
+
//# sourceMappingURL=parseGitLFSObjectEither.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parseGitLFSObjectEither.js","sourceRoot":"","sources":["../../../src/getPathContents/parseGitLFSObjectEither.ts"],"names":[],"mappings":"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"}
|