giget 0.1.4 → 0.1.6
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 +32 -22
- package/dist/cli.cjs +8 -4
- package/dist/cli.mjs +8 -4
- package/dist/index.cjs +2 -1
- package/dist/index.d.ts +12 -12
- package/dist/index.mjs +2 -1
- package/dist/shared/{giget.774476cb.cjs → giget.73314e21.cjs} +32 -11
- package/dist/shared/{giget.1430f5a2.mjs → giget.ae887001.mjs} +32 -11
- package/package.json +4 -3
package/README.md
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
|
|
10
10
|
## Features
|
|
11
11
|
|
|
12
|
-
✔ Support popular git providers (GitHub, GitLab,
|
|
12
|
+
✔ Support popular git providers (GitHub, GitLab, Bitbucket, Sourcehut) out of the box.
|
|
13
13
|
|
|
14
14
|
✔ Built-in and custom [template registry](#template-registry).
|
|
15
15
|
|
|
@@ -21,6 +21,8 @@
|
|
|
21
21
|
|
|
22
22
|
✔ Support extracting with a subdir.
|
|
23
23
|
|
|
24
|
+
✔ Authorization support to download private templates
|
|
25
|
+
|
|
24
26
|
## Usage (CLI)
|
|
25
27
|
|
|
26
28
|
```bash
|
|
@@ -39,13 +41,18 @@ npx giget@latest <template> [<dir>] [...options]
|
|
|
39
41
|
- `--prefer-offline`: Use cache if exists otherwise try to download.
|
|
40
42
|
- `--force-clean`: ⚠️ Remove any existing directory or file recusively before cloning.
|
|
41
43
|
- `--shell`: ⚠️ Open a new shell with current working directory in cloned dir. (Experimental).
|
|
42
|
-
- `--registry`: URL to a custom registry.
|
|
44
|
+
- `--registry`: URL to a custom registry. (Can be overriden with `GIGET_REGISTRY` environment variable).
|
|
43
45
|
- `--no-registry`: Disable registry lookup and functionality.
|
|
44
46
|
- `--verbose`: Show verbose debugging info.
|
|
47
|
+
- `--cwd`: Set current working directory to resolve dirs relative to it.
|
|
48
|
+
- `--auth`: Custom Authorization token to use for downloading template. (Can be overriden with `GIGET_AUTH` environment variable).
|
|
45
49
|
|
|
46
50
|
### Examples
|
|
47
51
|
|
|
48
52
|
```sh
|
|
53
|
+
# Clone nuxt starter from giget template registry
|
|
54
|
+
npx giget@latest nuxt
|
|
55
|
+
|
|
49
56
|
# Clone the main branch of github.com/unjs/template to unjs-template directory
|
|
50
57
|
npx giget@latest gh:unjs/template
|
|
51
58
|
|
|
@@ -64,8 +71,8 @@ npx giget@latest gitlab:unjs/template
|
|
|
64
71
|
# Clone from bitbucket
|
|
65
72
|
npx giget@latest bitbucket:unjs/template
|
|
66
73
|
|
|
67
|
-
# Clone
|
|
68
|
-
npx giget@latest
|
|
74
|
+
# Clone from sourcehut
|
|
75
|
+
npx giget@latest sourcehut:pi0/unjs-template
|
|
69
76
|
```
|
|
70
77
|
|
|
71
78
|
## Template Registry
|
|
@@ -78,11 +85,12 @@ If you want to add your template to the built-in registry, just drop a PR to add
|
|
|
78
85
|
|
|
79
86
|
A custom registry should provide an endpoint with dynamic path `/:template.json` that returns a JSON response with keys same as [custom providers](#custom-providers).
|
|
80
87
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
88
|
+
- `name`: (required) Name of the template.
|
|
89
|
+
- `tar` (required) Link to the tar download link.
|
|
90
|
+
- `defaultDir`: (optional) Default cloning directory.
|
|
91
|
+
- `url`: (optional) Webpage of the template.
|
|
92
|
+
- `subpath`: (optional) Subpath inside the tar file.
|
|
93
|
+
- `headers`: (optional) Custom headers to send while downloading template.
|
|
86
94
|
|
|
87
95
|
Because of the simplicity, you can even use a github repository as template registry but also you can build something more powerful by bringing your own API.
|
|
88
96
|
|
|
@@ -124,7 +132,7 @@ const { source, dir } = await downloadTemplate('github:unjs/template')
|
|
|
124
132
|
- `source`: (string) Input source in format of `[provider]:repo[/subpath][#ref]`.
|
|
125
133
|
- `dir`: (string) Destination directory to clone to. If not provided, `user-name` will be used relative to the current directory.
|
|
126
134
|
- `options`: (object) Options are usually inferred from the input string. You can customize them.
|
|
127
|
-
- `provider`: (string) Either `github`, `gitlab` or `
|
|
135
|
+
- `provider`: (string) Either `github`, `gitlab`, `bitbucket` or `sourcehut`. The default is `github`.
|
|
128
136
|
- `repo`: (string) Name of repository in format of `{username}/{reponame}`.
|
|
129
137
|
- `ref`: (string) Git ref (branch or commit or tag). The default value is `main`.
|
|
130
138
|
- `subdirpath`: (string) subdir of the repo to clone from. The default value is none.
|
|
@@ -133,7 +141,9 @@ const { source, dir } = await downloadTemplate('github:unjs/template')
|
|
|
133
141
|
- `offline`: (boolean) Do not attempt to download and use cached version.
|
|
134
142
|
- `preferOffline`: (boolean) Use cache if exists otherwise try to download.
|
|
135
143
|
- `providers`: (object) A map from provider name to custom providers. Can be used to override built-ins too.
|
|
136
|
-
- `registry`: (string or false) Set to `false` to disable registry. Set to a URL string (without trailing slash) for custom registry.
|
|
144
|
+
- `registry`: (string or false) Set to `false` to disable registry. Set to a URL string (without trailing slash) for custom registry. (Can be overriden with `GIGET_REGISTRY` environment variable).
|
|
145
|
+
- `cwd`: (string) Current working directory to resolve dirs relative to it.
|
|
146
|
+
- `auth`: (string) Custom Authorization token to use for downloading template. (Can be overriden with `GIGET_AUTH` environment variable).
|
|
137
147
|
|
|
138
148
|
**Return value:**
|
|
139
149
|
|
|
@@ -151,10 +161,11 @@ Using programmatic method, you can make your own custom template providers.
|
|
|
151
161
|
```ts
|
|
152
162
|
import type { TemplateProvider } from 'giget'
|
|
153
163
|
|
|
154
|
-
const rainbow: TemplateProvider = async (input) => {
|
|
164
|
+
const rainbow: TemplateProvider = async (input, { auth }) => {
|
|
155
165
|
return {
|
|
156
166
|
name: 'rainbow',
|
|
157
167
|
version: input,
|
|
168
|
+
headers: { Authorization: auth },
|
|
158
169
|
url: `https://rainbow.template/?variant=${input}`,
|
|
159
170
|
tar: `https://rainbow.template/dl/rainbow.${input}.tar.gz`
|
|
160
171
|
}
|
|
@@ -175,19 +186,20 @@ const themes = registryProvider('https://raw.githubusercontent.com/unjs/giget/ma
|
|
|
175
186
|
const { source, dir } = await downloadRepo('themes:test', { providers: { themes } })
|
|
176
187
|
```
|
|
177
188
|
|
|
178
|
-
## 💻 Development
|
|
179
|
-
|
|
180
|
-
- Clone this repository
|
|
181
|
-
- Enable [Corepack](https://github.com/nodejs/corepack) using `corepack enable` (use `npm i -g corepack` for Node.js < 16.10)
|
|
182
|
-
- Install dependencies using `pnpm install`
|
|
183
|
-
- Run interactive tests using `pnpm dev`
|
|
184
|
-
|
|
185
189
|
## Related projects
|
|
186
190
|
|
|
191
|
+
Giget wouldn't be possible without inspering from former projects. In comparation giget does not depend on any local command which increases stability and performance, supports custom template providers, auth and many more features out of the box.
|
|
192
|
+
|
|
187
193
|
- https://github.com/samsonjs/gitter
|
|
188
194
|
- https://github.com/tiged/tiged
|
|
189
195
|
- https://github.com/Rich-Harris/degit
|
|
190
196
|
|
|
197
|
+
## 💻 Development
|
|
198
|
+
|
|
199
|
+
- Clone this repository
|
|
200
|
+
- Enable [Corepack](https://github.com/nodejs/corepack) using `corepack enable` (use `npm i -g corepack` for Node.js < 16.10)
|
|
201
|
+
- Install dependencies using `pnpm install`
|
|
202
|
+
- Run interactive tests using `pnpm dev`
|
|
191
203
|
|
|
192
204
|
## License
|
|
193
205
|
|
|
@@ -196,14 +208,12 @@ Made with 💛
|
|
|
196
208
|
Published under [MIT License](./LICENSE).
|
|
197
209
|
|
|
198
210
|
<!-- Badges -->
|
|
211
|
+
|
|
199
212
|
[npm-version-src]: https://img.shields.io/npm/v/giget?style=flat-square
|
|
200
213
|
[npm-version-href]: https://npmjs.com/package/giget
|
|
201
|
-
|
|
202
214
|
[npm-downloads-src]: https://img.shields.io/npm/dm/giget?style=flat-square
|
|
203
215
|
[npm-downloads-href]: https://npmjs.com/package/giget
|
|
204
|
-
|
|
205
216
|
[github-actions-src]: https://img.shields.io/github/workflow/status/unjs/giget/ci/main?style=flat-square
|
|
206
217
|
[github-actions-href]: https://github.com/unjs/giget/actions?query=workflow%3Aci
|
|
207
|
-
|
|
208
218
|
[codecov-src]: https://img.shields.io/codecov/c/gh/unjs/giget/main?style=flat-square
|
|
209
219
|
[codecov-href]: https://codecov.io/gh/unjs/giget
|
package/dist/cli.cjs
CHANGED
|
@@ -4,12 +4,13 @@
|
|
|
4
4
|
const node_path = require('node:path');
|
|
5
5
|
const mri = require('mri');
|
|
6
6
|
const colorette = require('colorette');
|
|
7
|
-
const giget = require('./shared/giget.
|
|
7
|
+
const giget = require('./shared/giget.73314e21.cjs');
|
|
8
8
|
require('node:fs/promises');
|
|
9
9
|
require('node:os');
|
|
10
10
|
require('node:fs');
|
|
11
11
|
require('tar');
|
|
12
12
|
require('pathe');
|
|
13
|
+
require('defu');
|
|
13
14
|
require('node:stream/promises');
|
|
14
15
|
require('node:child_process');
|
|
15
16
|
require('node-fetch-native');
|
|
@@ -20,12 +21,13 @@ const mri__default = /*#__PURE__*/_interopDefaultLegacy(mri);
|
|
|
20
21
|
|
|
21
22
|
async function main() {
|
|
22
23
|
const args = mri__default(process.argv.slice(2), {
|
|
23
|
-
boolean: ["help", "force", "force-clean", "offline", "prefer-offline", "shell", "
|
|
24
|
+
boolean: ["help", "force", "force-clean", "offline", "prefer-offline", "shell", "verbose"],
|
|
25
|
+
string: ["registry", "cwd", "auth"]
|
|
24
26
|
});
|
|
25
27
|
const input = args._[0];
|
|
26
28
|
const dir = args._[1];
|
|
27
29
|
if (!input || args.help || args.h) {
|
|
28
|
-
console.error("Usage: npx getgit@latest <input> [<dir>] [--force] [--force-clean] [--offline] [--prefer-offline] [--shell] [--registry] [--no-registry] [--verbose]");
|
|
30
|
+
console.error("Usage: npx getgit@latest <input> [<dir>] [--force] [--force-clean] [--offline] [--prefer-offline] [--shell] [--registry] [--no-registry] [--verbose] [--cwd] [--auth]");
|
|
29
31
|
process.exit(1);
|
|
30
32
|
}
|
|
31
33
|
if (args.verbose) {
|
|
@@ -36,7 +38,9 @@ async function main() {
|
|
|
36
38
|
force: args.force,
|
|
37
39
|
forceClean: args["force-clean"],
|
|
38
40
|
offline: args.offline,
|
|
39
|
-
registry: args.registry
|
|
41
|
+
registry: args.registry,
|
|
42
|
+
cwd: args.cwd,
|
|
43
|
+
auth: args.auth
|
|
40
44
|
});
|
|
41
45
|
console.log(`\u2728 Successfully cloned ${colorette.cyan(r.name || r.url)} to ${colorette.cyan(node_path.relative(process.cwd(), r.dir))}
|
|
42
46
|
`);
|
package/dist/cli.mjs
CHANGED
|
@@ -2,24 +2,26 @@
|
|
|
2
2
|
import { relative } from 'node:path';
|
|
3
3
|
import mri from 'mri';
|
|
4
4
|
import { cyan } from 'colorette';
|
|
5
|
-
import { d as downloadTemplate, s as startShell } from './shared/giget.
|
|
5
|
+
import { d as downloadTemplate, s as startShell } from './shared/giget.ae887001.mjs';
|
|
6
6
|
import 'node:fs/promises';
|
|
7
7
|
import 'node:os';
|
|
8
8
|
import 'node:fs';
|
|
9
9
|
import 'tar';
|
|
10
10
|
import 'pathe';
|
|
11
|
+
import 'defu';
|
|
11
12
|
import 'node:stream/promises';
|
|
12
13
|
import 'node:child_process';
|
|
13
14
|
import 'node-fetch-native';
|
|
14
15
|
|
|
15
16
|
async function main() {
|
|
16
17
|
const args = mri(process.argv.slice(2), {
|
|
17
|
-
boolean: ["help", "force", "force-clean", "offline", "prefer-offline", "shell", "
|
|
18
|
+
boolean: ["help", "force", "force-clean", "offline", "prefer-offline", "shell", "verbose"],
|
|
19
|
+
string: ["registry", "cwd", "auth"]
|
|
18
20
|
});
|
|
19
21
|
const input = args._[0];
|
|
20
22
|
const dir = args._[1];
|
|
21
23
|
if (!input || args.help || args.h) {
|
|
22
|
-
console.error("Usage: npx getgit@latest <input> [<dir>] [--force] [--force-clean] [--offline] [--prefer-offline] [--shell] [--registry] [--no-registry] [--verbose]");
|
|
24
|
+
console.error("Usage: npx getgit@latest <input> [<dir>] [--force] [--force-clean] [--offline] [--prefer-offline] [--shell] [--registry] [--no-registry] [--verbose] [--cwd] [--auth]");
|
|
23
25
|
process.exit(1);
|
|
24
26
|
}
|
|
25
27
|
if (args.verbose) {
|
|
@@ -30,7 +32,9 @@ async function main() {
|
|
|
30
32
|
force: args.force,
|
|
31
33
|
forceClean: args["force-clean"],
|
|
32
34
|
offline: args.offline,
|
|
33
|
-
registry: args.registry
|
|
35
|
+
registry: args.registry,
|
|
36
|
+
cwd: args.cwd,
|
|
37
|
+
auth: args.auth
|
|
34
38
|
});
|
|
35
39
|
console.log(`\u2728 Successfully cloned ${cyan(r.name || r.url)} to ${cyan(relative(process.cwd(), r.dir))}
|
|
36
40
|
`);
|
package/dist/index.cjs
CHANGED
|
@@ -2,12 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
4
|
|
|
5
|
-
const giget = require('./shared/giget.
|
|
5
|
+
const giget = require('./shared/giget.73314e21.cjs');
|
|
6
6
|
require('node:fs/promises');
|
|
7
7
|
require('node:os');
|
|
8
8
|
require('node:fs');
|
|
9
9
|
require('tar');
|
|
10
10
|
require('pathe');
|
|
11
|
+
require('defu');
|
|
11
12
|
require('node:stream/promises');
|
|
12
13
|
require('node:child_process');
|
|
13
14
|
require('node-fetch-native');
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
interface GitInfo {
|
|
2
|
-
provider: 'github' | 'gitlab' | 'bitbucket';
|
|
2
|
+
provider: 'github' | 'gitlab' | 'bitbucket' | 'sourcehut';
|
|
3
3
|
repo: string;
|
|
4
4
|
subdir: string;
|
|
5
5
|
ref: string;
|
|
@@ -11,11 +11,14 @@ interface TemplateInfo {
|
|
|
11
11
|
subdir?: string;
|
|
12
12
|
url?: string;
|
|
13
13
|
defaultDir?: string;
|
|
14
|
+
headers?: Record<string, string>;
|
|
14
15
|
source?: never;
|
|
15
16
|
dir?: never;
|
|
16
17
|
[key: string]: any;
|
|
17
18
|
}
|
|
18
|
-
declare type TemplateProvider = (input: string
|
|
19
|
+
declare type TemplateProvider = (input: string, options: {
|
|
20
|
+
auth?: string;
|
|
21
|
+
}) => TemplateInfo | Promise<TemplateInfo> | null;
|
|
19
22
|
|
|
20
23
|
interface DownloadTemplateOptions {
|
|
21
24
|
provider?: string;
|
|
@@ -26,20 +29,17 @@ interface DownloadTemplateOptions {
|
|
|
26
29
|
providers?: Record<string, TemplateProvider>;
|
|
27
30
|
dir?: string;
|
|
28
31
|
registry?: false | string;
|
|
32
|
+
cwd?: string;
|
|
33
|
+
auth?: string;
|
|
29
34
|
}
|
|
30
|
-
declare
|
|
31
|
-
source: string;
|
|
35
|
+
declare type DownloadTemplateResult = Omit<TemplateInfo, 'dir' | 'source'> & {
|
|
32
36
|
dir: string;
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
subdir?: string;
|
|
37
|
-
url?: string;
|
|
38
|
-
defaultDir?: string;
|
|
39
|
-
}>;
|
|
37
|
+
source: string;
|
|
38
|
+
};
|
|
39
|
+
declare function downloadTemplate(input: string, opts?: DownloadTemplateOptions): Promise<DownloadTemplateResult>;
|
|
40
40
|
|
|
41
41
|
declare const registryProvider: (registryEndpoint?: string) => TemplateProvider;
|
|
42
42
|
|
|
43
43
|
declare function startShell(cwd: string): void;
|
|
44
44
|
|
|
45
|
-
export { DownloadTemplateOptions, GitInfo, TemplateInfo, TemplateProvider, downloadTemplate, registryProvider, startShell };
|
|
45
|
+
export { DownloadTemplateOptions, DownloadTemplateResult, GitInfo, TemplateInfo, TemplateProvider, downloadTemplate, registryProvider, startShell };
|
package/dist/index.mjs
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
export { d as downloadTemplate, r as registryProvider, s as startShell } from './shared/giget.
|
|
1
|
+
export { d as downloadTemplate, r as registryProvider, s as startShell } from './shared/giget.ae887001.mjs';
|
|
2
2
|
import 'node:fs/promises';
|
|
3
3
|
import 'node:os';
|
|
4
4
|
import 'node:fs';
|
|
5
5
|
import 'tar';
|
|
6
6
|
import 'pathe';
|
|
7
|
+
import 'defu';
|
|
7
8
|
import 'node:stream/promises';
|
|
8
9
|
import 'node:child_process';
|
|
9
10
|
import 'node-fetch-native';
|
|
@@ -5,6 +5,7 @@ const node_os = require('node:os');
|
|
|
5
5
|
const node_fs = require('node:fs');
|
|
6
6
|
const tar = require('tar');
|
|
7
7
|
const pathe = require('pathe');
|
|
8
|
+
const defu = require('defu');
|
|
8
9
|
const promises$1 = require('node:stream/promises');
|
|
9
10
|
const node_child_process = require('node:child_process');
|
|
10
11
|
const fetch = require('node-fetch-native');
|
|
@@ -13,16 +14,16 @@ function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'defau
|
|
|
13
14
|
|
|
14
15
|
const fetch__default = /*#__PURE__*/_interopDefaultLegacy(fetch);
|
|
15
16
|
|
|
16
|
-
async function download(url, filePath) {
|
|
17
|
+
async function download(url, filePath, opts = {}) {
|
|
17
18
|
const infoPath = filePath + ".json";
|
|
18
19
|
const info = JSON.parse(await promises.readFile(infoPath, "utf8").catch(() => "{}"));
|
|
19
|
-
const headRes = await fetch.fetch(url, { method: "HEAD" }).catch(() => null);
|
|
20
|
+
const headRes = await fetch.fetch(url, { method: "HEAD", headers: opts.headers }).catch(() => null);
|
|
20
21
|
const etag = headRes?.headers.get("etag");
|
|
21
22
|
if (info.etag === etag && node_fs.existsSync(filePath)) {
|
|
22
23
|
return;
|
|
23
24
|
}
|
|
24
25
|
info.etag = etag;
|
|
25
|
-
const res = await fetch.fetch(url);
|
|
26
|
+
const res = await fetch.fetch(url, { headers: opts.headers });
|
|
26
27
|
if (res.status >= 400) {
|
|
27
28
|
throw new Error(`Failed to download ${url}: ${res.status} ${res.statusText}`);
|
|
28
29
|
}
|
|
@@ -64,41 +65,56 @@ function startShell(cwd) {
|
|
|
64
65
|
});
|
|
65
66
|
}
|
|
66
67
|
|
|
67
|
-
const github = (input) => {
|
|
68
|
+
const github = (input, opts) => {
|
|
68
69
|
const parsed = parseGitURI(input);
|
|
69
70
|
return {
|
|
70
71
|
name: parsed.repo.replace("/", "-"),
|
|
71
72
|
version: parsed.ref,
|
|
72
73
|
subdir: parsed.subdir,
|
|
74
|
+
headers: { Authorization: opts.auth ? `Bearer ${opts.auth}` : void 0 },
|
|
73
75
|
url: `https://github.com/${parsed.repo}/tree/${parsed.ref}${parsed.subdir}`,
|
|
74
76
|
tar: `https://github.com/${parsed.repo}/archive/${parsed.ref}.tar.gz`
|
|
75
77
|
};
|
|
76
78
|
};
|
|
77
|
-
const gitlab = (input) => {
|
|
79
|
+
const gitlab = (input, opts) => {
|
|
78
80
|
const parsed = parseGitURI(input);
|
|
79
81
|
return {
|
|
80
82
|
name: parsed.repo.replace("/", "-"),
|
|
81
83
|
version: parsed.ref,
|
|
82
84
|
subdir: parsed.subdir,
|
|
85
|
+
headers: { Authorization: opts.auth ? `Bearer ${opts.auth}` : void 0 },
|
|
83
86
|
url: `https://gitlab.com/${parsed.repo}/tree/${parsed.ref}${parsed.subdir}`,
|
|
84
87
|
tar: `https://gitlab.com/${parsed.repo}/-/archive/${parsed.ref}.tar.gz`
|
|
85
88
|
};
|
|
86
89
|
};
|
|
87
|
-
const bitbucket = (input) => {
|
|
90
|
+
const bitbucket = (input, opts) => {
|
|
88
91
|
const parsed = parseGitURI(input);
|
|
89
92
|
return {
|
|
90
93
|
name: parsed.repo.replace("/", "-"),
|
|
91
94
|
version: parsed.ref,
|
|
92
95
|
subdir: parsed.subdir,
|
|
96
|
+
headers: { Authorization: opts.auth ? `Bearer ${opts.auth}` : void 0 },
|
|
93
97
|
url: `https://bitbucket.com/${parsed.repo}/src/${parsed.ref}${parsed.subdir}`,
|
|
94
98
|
tar: `https://bitbucket.org/${parsed.repo}/get/${parsed.ref}.tar.gz`
|
|
95
99
|
};
|
|
96
100
|
};
|
|
101
|
+
const sourcehut = (input, opts) => {
|
|
102
|
+
const parsed = parseGitURI(input);
|
|
103
|
+
return {
|
|
104
|
+
name: parsed.repo.replace("/", "-"),
|
|
105
|
+
version: parsed.ref,
|
|
106
|
+
subdir: parsed.subdir,
|
|
107
|
+
headers: { Authorization: opts.auth ? `Bearer ${opts.auth}` : void 0 },
|
|
108
|
+
url: `https://git.sr.ht/~${parsed.repo}/tree/${parsed.ref}/item${parsed.subdir}`,
|
|
109
|
+
tar: `https://git.sr.ht/~${parsed.repo}/archive/${parsed.ref}.tar.gz`
|
|
110
|
+
};
|
|
111
|
+
};
|
|
97
112
|
const providers = {
|
|
98
113
|
github,
|
|
99
114
|
gh: github,
|
|
100
115
|
gitlab,
|
|
101
|
-
bitbucket
|
|
116
|
+
bitbucket,
|
|
117
|
+
sourcehut
|
|
102
118
|
};
|
|
103
119
|
|
|
104
120
|
const DEFAULT_REGISTRY = "https://raw.githubusercontent.com/unjs/giget/main/templates";
|
|
@@ -121,6 +137,10 @@ const registryProvider = (registryEndpoint = DEFAULT_REGISTRY) => {
|
|
|
121
137
|
|
|
122
138
|
const sourceProtoRe = /^([\w-.]+):/;
|
|
123
139
|
async function downloadTemplate(input, opts = {}) {
|
|
140
|
+
opts = defu.defu({
|
|
141
|
+
registry: process.env.GIGET_REGISTRY,
|
|
142
|
+
auth: process.env.GIGET_AUTH
|
|
143
|
+
}, opts);
|
|
124
144
|
const registry = opts.registry !== false ? registryProvider(opts.registry) : null;
|
|
125
145
|
let providerName = opts.provider || (registryProvider ? "registry" : "github");
|
|
126
146
|
let source = input;
|
|
@@ -133,12 +153,13 @@ async function downloadTemplate(input, opts = {}) {
|
|
|
133
153
|
if (!provider) {
|
|
134
154
|
throw new Error(`Unsupported provider: ${providerName}`);
|
|
135
155
|
}
|
|
136
|
-
const template = await Promise.resolve().then(() => provider(source)).catch((err) => {
|
|
156
|
+
const template = await Promise.resolve().then(() => provider(source, { auth: opts.auth })).catch((err) => {
|
|
137
157
|
throw new Error(`Failed to download template from ${providerName}: ${err.message}`);
|
|
138
158
|
});
|
|
139
159
|
template.name = (template.name || "template").replace(/[^a-z0-9-]/gi, "-");
|
|
140
160
|
template.defaultDir = (template.defaultDir || template.name).replace(/[^a-z0-9-]/gi, "-");
|
|
141
|
-
const
|
|
161
|
+
const cwd = pathe.resolve(opts.cwd || ".");
|
|
162
|
+
const extractPath = pathe.resolve(cwd, opts.dir || template.defaultDir);
|
|
142
163
|
if (opts.forceClean) {
|
|
143
164
|
await promises.rm(extractPath, { recursive: true, force: true });
|
|
144
165
|
}
|
|
@@ -154,7 +175,7 @@ async function downloadTemplate(input, opts = {}) {
|
|
|
154
175
|
if (!opts.offline) {
|
|
155
176
|
await promises.mkdir(pathe.dirname(tarPath), { recursive: true });
|
|
156
177
|
const s2 = Date.now();
|
|
157
|
-
await download(template.tar, tarPath).catch((err) => {
|
|
178
|
+
await download(template.tar, tarPath, { headers: template.headers }).catch((err) => {
|
|
158
179
|
if (!node_fs.existsSync(tarPath)) {
|
|
159
180
|
throw err;
|
|
160
181
|
}
|
|
@@ -174,7 +195,7 @@ async function downloadTemplate(input, opts = {}) {
|
|
|
174
195
|
onentry(entry) {
|
|
175
196
|
entry.path = entry.path.split("/").splice(1).join("/");
|
|
176
197
|
if (subdir) {
|
|
177
|
-
if (entry.path.startsWith(subdir)) {
|
|
198
|
+
if (entry.path.startsWith(subdir + "/")) {
|
|
178
199
|
entry.path = entry.path.substring(subdir.length);
|
|
179
200
|
} else {
|
|
180
201
|
entry.path = "";
|
|
@@ -3,20 +3,21 @@ import { homedir } from 'node:os';
|
|
|
3
3
|
import { existsSync, createWriteStream, readdirSync } from 'node:fs';
|
|
4
4
|
import { extract } from 'tar';
|
|
5
5
|
import { resolve, relative, dirname } from 'pathe';
|
|
6
|
+
import { defu } from 'defu';
|
|
6
7
|
import { pipeline } from 'node:stream/promises';
|
|
7
8
|
import { spawnSync } from 'node:child_process';
|
|
8
9
|
import fetch$1, { fetch } from 'node-fetch-native';
|
|
9
10
|
|
|
10
|
-
async function download(url, filePath) {
|
|
11
|
+
async function download(url, filePath, opts = {}) {
|
|
11
12
|
const infoPath = filePath + ".json";
|
|
12
13
|
const info = JSON.parse(await readFile(infoPath, "utf8").catch(() => "{}"));
|
|
13
|
-
const headRes = await fetch(url, { method: "HEAD" }).catch(() => null);
|
|
14
|
+
const headRes = await fetch(url, { method: "HEAD", headers: opts.headers }).catch(() => null);
|
|
14
15
|
const etag = headRes?.headers.get("etag");
|
|
15
16
|
if (info.etag === etag && existsSync(filePath)) {
|
|
16
17
|
return;
|
|
17
18
|
}
|
|
18
19
|
info.etag = etag;
|
|
19
|
-
const res = await fetch(url);
|
|
20
|
+
const res = await fetch(url, { headers: opts.headers });
|
|
20
21
|
if (res.status >= 400) {
|
|
21
22
|
throw new Error(`Failed to download ${url}: ${res.status} ${res.statusText}`);
|
|
22
23
|
}
|
|
@@ -58,41 +59,56 @@ function startShell(cwd) {
|
|
|
58
59
|
});
|
|
59
60
|
}
|
|
60
61
|
|
|
61
|
-
const github = (input) => {
|
|
62
|
+
const github = (input, opts) => {
|
|
62
63
|
const parsed = parseGitURI(input);
|
|
63
64
|
return {
|
|
64
65
|
name: parsed.repo.replace("/", "-"),
|
|
65
66
|
version: parsed.ref,
|
|
66
67
|
subdir: parsed.subdir,
|
|
68
|
+
headers: { Authorization: opts.auth ? `Bearer ${opts.auth}` : void 0 },
|
|
67
69
|
url: `https://github.com/${parsed.repo}/tree/${parsed.ref}${parsed.subdir}`,
|
|
68
70
|
tar: `https://github.com/${parsed.repo}/archive/${parsed.ref}.tar.gz`
|
|
69
71
|
};
|
|
70
72
|
};
|
|
71
|
-
const gitlab = (input) => {
|
|
73
|
+
const gitlab = (input, opts) => {
|
|
72
74
|
const parsed = parseGitURI(input);
|
|
73
75
|
return {
|
|
74
76
|
name: parsed.repo.replace("/", "-"),
|
|
75
77
|
version: parsed.ref,
|
|
76
78
|
subdir: parsed.subdir,
|
|
79
|
+
headers: { Authorization: opts.auth ? `Bearer ${opts.auth}` : void 0 },
|
|
77
80
|
url: `https://gitlab.com/${parsed.repo}/tree/${parsed.ref}${parsed.subdir}`,
|
|
78
81
|
tar: `https://gitlab.com/${parsed.repo}/-/archive/${parsed.ref}.tar.gz`
|
|
79
82
|
};
|
|
80
83
|
};
|
|
81
|
-
const bitbucket = (input) => {
|
|
84
|
+
const bitbucket = (input, opts) => {
|
|
82
85
|
const parsed = parseGitURI(input);
|
|
83
86
|
return {
|
|
84
87
|
name: parsed.repo.replace("/", "-"),
|
|
85
88
|
version: parsed.ref,
|
|
86
89
|
subdir: parsed.subdir,
|
|
90
|
+
headers: { Authorization: opts.auth ? `Bearer ${opts.auth}` : void 0 },
|
|
87
91
|
url: `https://bitbucket.com/${parsed.repo}/src/${parsed.ref}${parsed.subdir}`,
|
|
88
92
|
tar: `https://bitbucket.org/${parsed.repo}/get/${parsed.ref}.tar.gz`
|
|
89
93
|
};
|
|
90
94
|
};
|
|
95
|
+
const sourcehut = (input, opts) => {
|
|
96
|
+
const parsed = parseGitURI(input);
|
|
97
|
+
return {
|
|
98
|
+
name: parsed.repo.replace("/", "-"),
|
|
99
|
+
version: parsed.ref,
|
|
100
|
+
subdir: parsed.subdir,
|
|
101
|
+
headers: { Authorization: opts.auth ? `Bearer ${opts.auth}` : void 0 },
|
|
102
|
+
url: `https://git.sr.ht/~${parsed.repo}/tree/${parsed.ref}/item${parsed.subdir}`,
|
|
103
|
+
tar: `https://git.sr.ht/~${parsed.repo}/archive/${parsed.ref}.tar.gz`
|
|
104
|
+
};
|
|
105
|
+
};
|
|
91
106
|
const providers = {
|
|
92
107
|
github,
|
|
93
108
|
gh: github,
|
|
94
109
|
gitlab,
|
|
95
|
-
bitbucket
|
|
110
|
+
bitbucket,
|
|
111
|
+
sourcehut
|
|
96
112
|
};
|
|
97
113
|
|
|
98
114
|
const DEFAULT_REGISTRY = "https://raw.githubusercontent.com/unjs/giget/main/templates";
|
|
@@ -115,6 +131,10 @@ const registryProvider = (registryEndpoint = DEFAULT_REGISTRY) => {
|
|
|
115
131
|
|
|
116
132
|
const sourceProtoRe = /^([\w-.]+):/;
|
|
117
133
|
async function downloadTemplate(input, opts = {}) {
|
|
134
|
+
opts = defu({
|
|
135
|
+
registry: process.env.GIGET_REGISTRY,
|
|
136
|
+
auth: process.env.GIGET_AUTH
|
|
137
|
+
}, opts);
|
|
118
138
|
const registry = opts.registry !== false ? registryProvider(opts.registry) : null;
|
|
119
139
|
let providerName = opts.provider || (registryProvider ? "registry" : "github");
|
|
120
140
|
let source = input;
|
|
@@ -127,12 +147,13 @@ async function downloadTemplate(input, opts = {}) {
|
|
|
127
147
|
if (!provider) {
|
|
128
148
|
throw new Error(`Unsupported provider: ${providerName}`);
|
|
129
149
|
}
|
|
130
|
-
const template = await Promise.resolve().then(() => provider(source)).catch((err) => {
|
|
150
|
+
const template = await Promise.resolve().then(() => provider(source, { auth: opts.auth })).catch((err) => {
|
|
131
151
|
throw new Error(`Failed to download template from ${providerName}: ${err.message}`);
|
|
132
152
|
});
|
|
133
153
|
template.name = (template.name || "template").replace(/[^a-z0-9-]/gi, "-");
|
|
134
154
|
template.defaultDir = (template.defaultDir || template.name).replace(/[^a-z0-9-]/gi, "-");
|
|
135
|
-
const
|
|
155
|
+
const cwd = resolve(opts.cwd || ".");
|
|
156
|
+
const extractPath = resolve(cwd, opts.dir || template.defaultDir);
|
|
136
157
|
if (opts.forceClean) {
|
|
137
158
|
await rm(extractPath, { recursive: true, force: true });
|
|
138
159
|
}
|
|
@@ -148,7 +169,7 @@ async function downloadTemplate(input, opts = {}) {
|
|
|
148
169
|
if (!opts.offline) {
|
|
149
170
|
await mkdir(dirname(tarPath), { recursive: true });
|
|
150
171
|
const s2 = Date.now();
|
|
151
|
-
await download(template.tar, tarPath).catch((err) => {
|
|
172
|
+
await download(template.tar, tarPath, { headers: template.headers }).catch((err) => {
|
|
152
173
|
if (!existsSync(tarPath)) {
|
|
153
174
|
throw err;
|
|
154
175
|
}
|
|
@@ -168,7 +189,7 @@ async function downloadTemplate(input, opts = {}) {
|
|
|
168
189
|
onentry(entry) {
|
|
169
190
|
entry.path = entry.path.split("/").splice(1).join("/");
|
|
170
191
|
if (subdir) {
|
|
171
|
-
if (entry.path.startsWith(subdir)) {
|
|
192
|
+
if (entry.path.startsWith(subdir + "/")) {
|
|
172
193
|
entry.path = entry.path.substring(subdir.length);
|
|
173
194
|
} else {
|
|
174
195
|
entry.path = "";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "giget",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.6",
|
|
4
4
|
"description": "Download templates and git repositories with pleasure!",
|
|
5
5
|
"repository": "unjs/giget",
|
|
6
6
|
"license": "MIT",
|
|
@@ -23,6 +23,7 @@
|
|
|
23
23
|
],
|
|
24
24
|
"dependencies": {
|
|
25
25
|
"colorette": "^2.0.19",
|
|
26
|
+
"defu": "^6.1.0",
|
|
26
27
|
"mri": "^1.2.0",
|
|
27
28
|
"node-fetch-native": "^0.1.4",
|
|
28
29
|
"pathe": "^0.3.7",
|
|
@@ -33,11 +34,11 @@
|
|
|
33
34
|
"@types/node": "^18.7.16",
|
|
34
35
|
"@types/tar": "^6.1.2",
|
|
35
36
|
"@vitest/coverage-c8": "^0.23.2",
|
|
36
|
-
"eslint": "^8.23.
|
|
37
|
+
"eslint": "^8.23.1",
|
|
37
38
|
"jiti": "^1.15.0",
|
|
38
39
|
"standard-version": "^9.5.0",
|
|
39
40
|
"typescript": "^4.8.3",
|
|
40
|
-
"unbuild": "^0.8.
|
|
41
|
+
"unbuild": "^0.8.11",
|
|
41
42
|
"vitest": "^0.23.2"
|
|
42
43
|
},
|
|
43
44
|
"packageManager": "pnpm@7.11.0",
|