• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

nikelborm / fetch-github-folder / 12806528642

16 Jan 2025 10:05AM UTC coverage: 55.882% (+0.5%) from 55.394%
12806528642

push

github

nikelborm
quick save: Thu Jan 16 13:05:29 MSK 2025

51 of 64 branches covered (79.69%)

Branch coverage included in aggregate %.

0 of 49 new or added lines in 1 file covered. (0.0%)

1 existing line in 1 file now uncovered.

329 of 616 relevant lines covered (53.41%)

2.34 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/fetch-github-folder.ts
1
#!/usr/bin/env node
×
2

3
import { make, run } from '@effect/cli/Command';
4
import {
5
  text,
6
  withDefault,
7
  withDescription,
8
  withFallbackConfig,
9
  withSchema,
10
} from '@effect/cli/Options';
11
import { layer as NodeFileSystemLayer } from '@effect/platform-node/NodeFileSystem';
12
import { layer as NodePathLayer } from '@effect/platform-node/NodePath';
13
import { runMain } from '@effect/platform-node/NodeRuntime';
14
import { layer as NodeTerminalLayer } from '@effect/platform-node/NodeTerminal';
15
import { Path } from '@effect/platform/Path';
16
import { Octokit as OctokitClient } from '@octokit/core';
17
// import { ParseResult, Schema } from 'effect';
18
import { nonEmptyString } from 'effect/Config';
19
import { flatMap, provide, provideService } from 'effect/Effect';
20
import { pipe } from 'effect/Function';
21
import { Type, fail, succeed } from 'effect/ParseResult';
22
import { NonEmptyString, filter, transformOrFail } from 'effect/Schema';
23
import { outdent } from 'outdent';
24
import {
25
  OctokitTag,
26
  createSingleTargetConfigContext,
27
  downloadEntityFromRepo,
28
} from './src/index.js';
29

30
// Those values updated automatically. If you edit names of constants or
31
// move them to a different file, update ./scripts/build.sh
32
const PACKAGE_VERSION = '0.1.6';
×
33
const PACKAGE_NAME = 'fetch-github-folder';
×
34

35
// TODO: add support for effect CLI, to properly render what env vars can be used as fallback and also what default values are.
36

NEW
37
const GitHubStringHandle = NonEmptyString.pipe(
×
NEW
38
  filter(
×
NEW
39
    s =>
×
NEW
40
      s.match(/^[a-z0-9.\-_]+$/gi) ||
×
NEW
41
      `GitHub handle "${s}" should have only ASCII letters, digits, and the characters ".", "-", and "_"`,
×
NEW
42
  ),
×
NEW
43
);
×
44

NEW
45
const pathToEntityInRepo = pipe(
×
NEW
46
  text('pathToEntityInRepo'),
×
NEW
47
  withDescription('Path to file or directory in repo'),
×
NEW
48
  withFallbackConfig(nonEmptyString('PATH_TO_ENTITY_IN_REPO')),
×
UNCOV
49
);
×
50

51
const repoOwner = pipe(
×
NEW
52
  text('repoOwner'),
×
NEW
53
  withDescription(outdent`
×
54
    This is a username (login handle) of a person owning repo you
55
    are trying to download from. For example, if the repository's URL is
56
    \`https://github.com/apache/superset\`, the owner is \`apache\`
NEW
57
  `),
×
NEW
58
  withSchema(GitHubStringHandle),
×
59
  withFallbackConfig(nonEmptyString('GITHUB_REPO_OWNER')),
×
60
);
×
61

62
const repoName = pipe(
×
NEW
63
  text('repoName'),
×
NEW
64
  withDescription(outdent`
×
65
    This is the name handle of the repository you are trying to download
66
    from. For example, if the repository's URL is
67
    \`https://github.com/apache/superset\`, the name is \`superset\`
NEW
68
  `),
×
NEW
69
  withSchema(GitHubStringHandle),
×
70
  withFallbackConfig(nonEmptyString('GITHUB_REPO_NAME')),
×
71
);
×
72

NEW
73
export const CleanedPathString = transformOrFail(
×
NEW
74
  NonEmptyString,
×
NEW
75
  NonEmptyString,
×
76
  {
×
77
    strict: true,
×
78
    decode: (dirtyPathToEntityInRepo, _, ast) =>
×
NEW
79
      flatMap(Path, path => {
×
80
        // dot can be there only when that's all there is. path.join(...)
81
        // removes all './', so '.' will never be just left by themself. If it's
82
        // there, it's very intentional and no other elements in the path exist.
NEW
83
        const cleanPathToEntityInRepo = path.join(dirtyPathToEntityInRepo);
×
84

NEW
85
        if (cleanPathToEntityInRepo.startsWith('..'))
×
NEW
86
          return fail(
×
NEW
87
            new Type(
×
NEW
88
              ast,
×
NEW
89
              dirtyPathToEntityInRepo,
×
NEW
90
              "Can\'t request contents that lie higher than the root of the repo",
×
NEW
91
            ),
×
NEW
92
          );
×
NEW
93
        return succeed(cleanPathToEntityInRepo);
×
NEW
94
      }),
×
NEW
95
    encode: succeed,
×
96
  },
×
97
);
×
98

99
const localPathAtWhichEntityFromRepoWillBeAvailable = pipe(
×
NEW
100
  text('destinationPath'),
×
NEW
101
  withDescription(outdent`
×
102
    Local path of the downloaded file or directory. If
103
    "pathToEntityInRepo" points to a file, then last element of the
104
    destination path will be new file name. If "pathToEntityInRepo" points
105
    to a directory then all files and directories inside directory at
106
    "pathToEntityInRepo" will be put into a directory with name equal last
107
    element of destination path. If the directory doesn't exist, it will
108
    be automatically created.
NEW
109
  `),
×
110
  withFallbackConfig(nonEmptyString('DESTINATION_PATH')),
×
NEW
111
  withSchema(CleanedPathString),
×
112
  withDefault('./destination'),
×
113
);
×
114

115
const gitRef = pipe(
×
NEW
116
  text('gitRef'),
×
NEW
117
  withDescription(outdent`
×
118
    This is the commit's SHA hash, branch name, tag name, or any other ref
119
    you want to download from. If you don't specify it, the default branch
120
    in the repository will be used.
NEW
121
  `),
×
NEW
122
  withFallbackConfig(nonEmptyString('GIT_REF')),
×
123
  withDefault('HEAD'),
×
124
);
×
125

126
const appCommand = make(
×
127
  'fetch-github-folder',
×
128
  {
×
NEW
129
    repo: {
×
NEW
130
      owner: repoOwner,
×
NEW
131
      name: repoName,
×
NEW
132
    },
×
NEW
133
    pathToEntityInRepo,
×
134
    localPathAtWhichEntityFromRepoWillBeAvailable,
×
135
    gitRef,
×
136
  },
×
NEW
137
  x => provide(downloadEntityFromRepo, createSingleTargetConfigContext(x)),
×
138
);
×
139

140
const cli = run(appCommand, {
×
141
  // those values will be filled automatically from package.json
142
  name: PACKAGE_NAME,
×
143
  version: PACKAGE_VERSION,
×
144
});
×
145

146
pipe(
×
147
  process.argv,
×
148
  cli,
×
149
  provide(NodeFileSystemLayer),
×
150
  provide(NodePathLayer),
×
151
  provide(NodeTerminalLayer),
×
152
  provideService(
×
153
    OctokitTag,
×
154
    new OctokitClient({
×
155
      // auth: getEnvVarOrFail('GITHUB_ACCESS_TOKEN'),
156
    }),
×
157
  ),
×
158
  runMain,
×
159
);
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc