giget 1.1.3 → 1.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 +54 -37
- package/dist/cli.cjs +161 -53
- package/dist/cli.mjs +162 -50
- package/dist/index.cjs +86 -20
- package/dist/index.d.cts +2 -0
- package/dist/index.d.mts +2 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.mjs +88 -22
- package/package.json +27 -21
package/README.md
CHANGED
|
@@ -1,27 +1,31 @@
|
|
|
1
|
-
#
|
|
1
|
+
# giget
|
|
2
2
|
|
|
3
3
|
[![npm version][npm-version-src]][npm-version-href]
|
|
4
4
|
[![npm downloads][npm-downloads-src]][npm-downloads-href]
|
|
5
|
-
[![
|
|
5
|
+
[![bundle][bundle-src]][bundle-href]
|
|
6
6
|
[![Codecov][codecov-src]][codecov-href]
|
|
7
7
|
|
|
8
8
|
> Download templates and git repositories with pleasure!
|
|
9
9
|
|
|
10
10
|
## Features
|
|
11
11
|
|
|
12
|
-
|
|
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
|
|
|
16
|
-
|
|
16
|
+
✨ Fast cloning using tarball gzip without depending on local `git` and `tar`.
|
|
17
17
|
|
|
18
|
-
|
|
18
|
+
✨ Works online and offline with disk cache support.
|
|
19
19
|
|
|
20
|
-
|
|
20
|
+
✨ Custom template provider support with programmatic usage.
|
|
21
21
|
|
|
22
|
-
|
|
22
|
+
✨ Support extracting with a sub dir.
|
|
23
23
|
|
|
24
|
-
|
|
24
|
+
✨ Authorization support to download private templates
|
|
25
|
+
|
|
26
|
+
✨ Optionally install dependencies after clone using [unjs/nypm](https://github.com/unjs/nypm)
|
|
27
|
+
|
|
28
|
+
✨ HTTP proxy support and native fetch via [unjs/node-fetch-native](https://github.com/unjs/node-fetch-native)
|
|
25
29
|
|
|
26
30
|
## Usage (CLI)
|
|
27
31
|
|
|
@@ -31,21 +35,22 @@ npx giget@latest <template> [<dir>] [...options]
|
|
|
31
35
|
|
|
32
36
|
### Arguments
|
|
33
37
|
|
|
34
|
-
- **template**: Template name or a
|
|
38
|
+
- **template**: Template name or a URI describing provider, repository, sub dir, and branch/ref. (See [Examples](#examples))
|
|
35
39
|
- **dir**: A relative or absolute path where to extract the template.
|
|
36
40
|
|
|
37
41
|
### Options
|
|
38
42
|
|
|
39
43
|
- `--force`: Clone to existing directory even if exists.
|
|
40
|
-
- `--offline`: Do not attempt to download and use cached version.
|
|
44
|
+
- `--offline`: Do not attempt to download and use the cached version.
|
|
41
45
|
- `--prefer-offline`: Use cache if exists otherwise try to download.
|
|
42
|
-
- `--force-clean`: ⚠️ Remove any existing directory or file
|
|
43
|
-
- `--shell`: ⚠️ Open a new shell with current working directory in cloned dir. (Experimental).
|
|
44
|
-
- `--registry`: URL to a custom registry. (Can be
|
|
46
|
+
- `--force-clean`: ⚠️ Remove any existing directory or file recursively before cloning.
|
|
47
|
+
- `--shell`: ⚠️ Open a new shell with the current working directory in cloned dir. (Experimental).
|
|
48
|
+
- `--registry`: URL to a custom registry. (Can be overridden with `GIGET_REGISTRY` environment variable).
|
|
45
49
|
- `--no-registry`: Disable registry lookup and functionality.
|
|
46
50
|
- `--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
|
|
51
|
+
- `--cwd`: Set the current working directory to resolve dirs relative to it.
|
|
52
|
+
- `--auth`: Custom Authorization token to use for downloading template. (Can be overridden with `GIGET_AUTH` environment variable).
|
|
53
|
+
- `--install`: Install dependencies after cloning using [unjs/nypm](https://github.com/unjs/nypm).
|
|
49
54
|
|
|
50
55
|
### Examples
|
|
51
56
|
|
|
@@ -73,17 +78,23 @@ npx giget@latest bitbucket:unjs/template
|
|
|
73
78
|
|
|
74
79
|
# Clone from sourcehut
|
|
75
80
|
npx giget@latest sourcehut:pi0/unjs-template
|
|
81
|
+
|
|
82
|
+
# Clone from https URL (tarball)
|
|
83
|
+
npx giget@latest https://api.github.com/repos/unjs/template/tarball/main
|
|
84
|
+
|
|
85
|
+
# Clone from https URL (JSON)
|
|
86
|
+
npx giget@latest https://raw.githubusercontent.com/unjs/giget/main/templates/unjs.json
|
|
76
87
|
```
|
|
77
88
|
|
|
78
89
|
## Template Registry
|
|
79
90
|
|
|
80
|
-
Giget has a built-in HTTP registry system for resolving templates. This way you can support template name shortcuts and meta-data.
|
|
91
|
+
Giget has a built-in HTTP registry system for resolving templates. This way you can support template name shortcuts and meta-data. The default registry is served from [unjs/giget/templates](./templates/).
|
|
81
92
|
|
|
82
|
-
If you want to add your template to the built-in registry, just drop a PR to add it to the [./templates](./templates) directory. Slugs are added on first-come first-served basis but this might change in the future.
|
|
93
|
+
If you want to add your template to the built-in registry, just drop a PR to add it to the [./templates](./templates) directory. Slugs are added on a first-come first-served basis but this might change in the future.
|
|
83
94
|
|
|
84
95
|
### Custom Registry
|
|
85
96
|
|
|
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).
|
|
97
|
+
A custom registry should provide an endpoint with the dynamic path `/:template.json` that returns a JSON response with keys the same as [custom providers](#custom-providers).
|
|
87
98
|
|
|
88
99
|
- `name`: (required) Name of the template.
|
|
89
100
|
- `tar` (required) Link to the tar download link.
|
|
@@ -92,7 +103,7 @@ A custom registry should provide an endpoint with dynamic path `/:template.json`
|
|
|
92
103
|
- `subdir`: (optional) Directory inside the tar file.
|
|
93
104
|
- `headers`: (optional) Custom headers to send while downloading template.
|
|
94
105
|
|
|
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.
|
|
106
|
+
Because of the simplicity, you can even use a GitHub repository as a template registry but also you can build something more powerful by bringing your own API.
|
|
96
107
|
|
|
97
108
|
## Usage (Programmatic)
|
|
98
109
|
|
|
@@ -133,17 +144,17 @@ const { source, dir } = await downloadTemplate("github:unjs/template");
|
|
|
133
144
|
- `options`: (object) Options are usually inferred from the input string. You can customize them.
|
|
134
145
|
- `dir`: (string) Destination directory to clone to. If not provided, `user-name` will be used relative to the current directory.
|
|
135
146
|
- `provider`: (string) Either `github`, `gitlab`, `bitbucket` or `sourcehut`. The default is `github`.
|
|
136
|
-
- `repo`: (string) Name of repository in format of `{username}/{reponame}`.
|
|
147
|
+
- `repo`: (string) Name of the repository in the format of `{username}/{reponame}`.
|
|
137
148
|
- `ref`: (string) Git ref (branch or commit or tag). The default value is `main`.
|
|
138
149
|
- `subdir`: (string) Directory of the repo to clone from. The default value is none.
|
|
139
|
-
- `force`: (boolean) Extract to the
|
|
140
|
-
- `forceClean`: (boolean) ⚠️ Clean
|
|
141
|
-
- `offline`: (boolean) Do not attempt to download and use cached version.
|
|
150
|
+
- `force`: (boolean) Extract to the existing dir even if already exists.
|
|
151
|
+
- `forceClean`: (boolean) ⚠️ Clean up any existing directory or file before cloning.
|
|
152
|
+
- `offline`: (boolean) Do not attempt to download and use the cached version.
|
|
142
153
|
- `preferOffline`: (boolean) Use cache if exists otherwise try to download.
|
|
143
154
|
- `providers`: (object) A map from provider name to custom providers. Can be used to override built-ins too.
|
|
144
|
-
- `registry`: (string or false) Set to `false` to disable registry. Set to a URL string (without trailing slash) for custom registry. (Can be
|
|
155
|
+
- `registry`: (string or false) Set to `false` to disable registry. Set to a URL string (without trailing slash) for custom registry. (Can be overridden with `GIGET_REGISTRY` environment variable).
|
|
145
156
|
- `cwd`: (string) Current working directory to resolve dirs relative to it.
|
|
146
|
-
- `auth`: (string) Custom Authorization token to use for downloading template. (Can be
|
|
157
|
+
- `auth`: (string) Custom Authorization token to use for downloading template. (Can be overridden with `GIGET_AUTH` environment variable).
|
|
147
158
|
|
|
148
159
|
**Return value:**
|
|
149
160
|
|
|
@@ -152,11 +163,11 @@ The return value is a promise that resolves to the resolved template.
|
|
|
152
163
|
- `dir`: (string) Path to extracted dir.
|
|
153
164
|
- `source`: (string) Normalized version of the input source without provider.
|
|
154
165
|
- [other provider template keys]
|
|
155
|
-
- `url`: (string) URL of
|
|
166
|
+
- `url`: (string) URL of the repository that can be opened in the browser. Useful for logging.
|
|
156
167
|
|
|
157
168
|
## Custom Providers
|
|
158
169
|
|
|
159
|
-
Using programmatic method, you can make your
|
|
170
|
+
Using the programmatic method, you can make your custom template providers.
|
|
160
171
|
|
|
161
172
|
```ts
|
|
162
173
|
import type { TemplateProvider } from "giget";
|
|
@@ -192,9 +203,15 @@ const { source, dir } = await downloadRepo("themes:test", {
|
|
|
192
203
|
});
|
|
193
204
|
```
|
|
194
205
|
|
|
206
|
+
## Providing token for private repositories
|
|
207
|
+
|
|
208
|
+
For private repositories and sources, you might need a token. In order to provide it, using CLI, you can use `--auth`, using programmatic API using `auth` option and in both modes also it is possible to use `GIGET_AUTH` environment variable to set it. The value will be set in `Authorization: Bearer ...` header by default.
|
|
209
|
+
|
|
210
|
+
**Note:** For github private repository access with Fine-grained access tokens, you need to give **Contents** and **Metadata** repository permissions.
|
|
211
|
+
|
|
195
212
|
## Related projects
|
|
196
213
|
|
|
197
|
-
Giget wouldn't be possible without inspiration from former projects. In comparison, giget does not depend on any local command which increases stability and performance
|
|
214
|
+
Giget wouldn't be possible without inspiration from former projects. In comparison, giget does not depend on any local command which increases stability and performance and supports custom template providers, auth, and many more features out of the box.
|
|
198
215
|
|
|
199
216
|
- https://github.com/samsonjs/gitter
|
|
200
217
|
- https://github.com/tiged/tiged
|
|
@@ -215,11 +232,11 @@ Published under [MIT License](./LICENSE).
|
|
|
215
232
|
|
|
216
233
|
<!-- Badges -->
|
|
217
234
|
|
|
218
|
-
[npm-version-src]: https://img.shields.io/npm/v/
|
|
219
|
-
[npm-version-href]: https://npmjs.com/package/
|
|
220
|
-
[npm-downloads-src]: https://img.shields.io/npm/dm/
|
|
221
|
-
[npm-downloads-href]: https://npmjs.com/package/
|
|
222
|
-
[
|
|
223
|
-
[
|
|
224
|
-
[
|
|
225
|
-
[
|
|
235
|
+
[npm-version-src]: https://img.shields.io/npm/v/packageName?style=flat&colorA=18181B&colorB=F0DB4F
|
|
236
|
+
[npm-version-href]: https://npmjs.com/package/packageName
|
|
237
|
+
[npm-downloads-src]: https://img.shields.io/npm/dm/packageName?style=flat&colorA=18181B&colorB=F0DB4F
|
|
238
|
+
[npm-downloads-href]: https://npmjs.com/package/packageName
|
|
239
|
+
[codecov-src]: https://img.shields.io/codecov/c/gh/unjs/packageName/main?style=flat&colorA=18181B&colorB=F0DB4F
|
|
240
|
+
[codecov-href]: https://codecov.io/gh/unjs/packageName
|
|
241
|
+
[bundle-src]: https://img.shields.io/bundlephobia/minzip/packageName?style=flat&colorA=18181B&colorB=F0DB4F
|
|
242
|
+
[bundle-href]: https://bundlephobia.com/result?p=packageName
|
package/dist/cli.cjs
CHANGED
|
@@ -1,70 +1,178 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
1
|
'use strict';
|
|
3
2
|
|
|
4
3
|
const node_path = require('node:path');
|
|
5
|
-
const
|
|
6
|
-
const
|
|
4
|
+
const citty = require('citty');
|
|
5
|
+
const consola = require('consola');
|
|
7
6
|
const index = require('./index.cjs');
|
|
8
7
|
require('node:fs/promises');
|
|
9
8
|
require('node:fs');
|
|
10
9
|
require('tar');
|
|
11
10
|
require('pathe');
|
|
12
11
|
require('defu');
|
|
12
|
+
require('nypm');
|
|
13
13
|
require('node:stream');
|
|
14
14
|
require('node:child_process');
|
|
15
15
|
require('node:os');
|
|
16
16
|
require('node:util');
|
|
17
|
-
require('node-fetch-native');
|
|
17
|
+
require('node-fetch-native/proxy');
|
|
18
18
|
|
|
19
|
-
|
|
19
|
+
const name = "giget";
|
|
20
|
+
const version = "1.2.0";
|
|
21
|
+
const description = "Download templates and git repositories with pleasure!";
|
|
22
|
+
const repository = "unjs/giget";
|
|
23
|
+
const license = "MIT";
|
|
24
|
+
const sideEffects = false;
|
|
25
|
+
const type = "module";
|
|
26
|
+
const exports$1 = {
|
|
27
|
+
".": {
|
|
28
|
+
"import": {
|
|
29
|
+
types: "./dist/index.d.mts",
|
|
30
|
+
"default": "./dist/index.mjs"
|
|
31
|
+
},
|
|
32
|
+
require: {
|
|
33
|
+
types: "./dist/index.d.cts",
|
|
34
|
+
"default": "./dist/index.cjs"
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
const main = "./dist/index.cjs";
|
|
39
|
+
const module$1 = "./dist/index.mjs";
|
|
40
|
+
const types = "./dist/index.d.ts";
|
|
41
|
+
const bin = {
|
|
42
|
+
giget: "./dist/cli.mjs"
|
|
43
|
+
};
|
|
44
|
+
const files = [
|
|
45
|
+
"dist"
|
|
46
|
+
];
|
|
47
|
+
const scripts = {
|
|
48
|
+
build: "unbuild",
|
|
49
|
+
dev: "vitest dev",
|
|
50
|
+
giget: "jiti ./src/cli.ts",
|
|
51
|
+
lint: "eslint --ext .ts,.js,.mjs,.cjs . && prettier -c src test",
|
|
52
|
+
"lint:fix": "eslint --ext .ts,.js,.mjs,.cjs . --fix && prettier -w src test",
|
|
53
|
+
prepack: "unbuild",
|
|
54
|
+
play: "pnpm giget --force-clean --verbose unjs .tmp/clone",
|
|
55
|
+
release: "pnpm test && changelogen --release && npm publish && git push --follow-tags",
|
|
56
|
+
test: "pnpm lint && vitest run --coverage"
|
|
57
|
+
};
|
|
58
|
+
const dependencies = {
|
|
59
|
+
citty: "^0.1.5",
|
|
60
|
+
consola: "^3.2.3",
|
|
61
|
+
defu: "^6.1.3",
|
|
62
|
+
"node-fetch-native": "^1.6.1",
|
|
63
|
+
nypm: "^0.3.3",
|
|
64
|
+
ohash: "^1.1.3",
|
|
65
|
+
pathe: "^1.1.1",
|
|
66
|
+
tar: "^6.2.0"
|
|
67
|
+
};
|
|
68
|
+
const devDependencies = {
|
|
69
|
+
"@types/node": "^20.10.5",
|
|
70
|
+
"@types/tar": "^6.1.10",
|
|
71
|
+
"@vitest/coverage-v8": "^1.1.0",
|
|
72
|
+
changelogen: "^0.5.5",
|
|
73
|
+
eslint: "^8.56.0",
|
|
74
|
+
"eslint-config-unjs": "^0.2.1",
|
|
75
|
+
jiti: "^1.21.0",
|
|
76
|
+
prettier: "^3.1.1",
|
|
77
|
+
typescript: "^5.3.3",
|
|
78
|
+
unbuild: "^2.0.0",
|
|
79
|
+
vitest: "^1.1.0"
|
|
80
|
+
};
|
|
81
|
+
const packageManager = "pnpm@8.12.1";
|
|
82
|
+
const pkg = {
|
|
83
|
+
name: name,
|
|
84
|
+
version: version,
|
|
85
|
+
description: description,
|
|
86
|
+
repository: repository,
|
|
87
|
+
license: license,
|
|
88
|
+
sideEffects: sideEffects,
|
|
89
|
+
type: type,
|
|
90
|
+
exports: exports$1,
|
|
91
|
+
main: main,
|
|
92
|
+
module: module$1,
|
|
93
|
+
types: types,
|
|
94
|
+
bin: bin,
|
|
95
|
+
files: files,
|
|
96
|
+
scripts: scripts,
|
|
97
|
+
dependencies: dependencies,
|
|
98
|
+
devDependencies: devDependencies,
|
|
99
|
+
packageManager: packageManager
|
|
100
|
+
};
|
|
20
101
|
|
|
21
|
-
const
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
"
|
|
31
|
-
"
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
forceClean:
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
102
|
+
const mainCommand = citty.defineCommand({
|
|
103
|
+
meta: {
|
|
104
|
+
name: pkg.name,
|
|
105
|
+
version: pkg.version,
|
|
106
|
+
description: pkg.description
|
|
107
|
+
},
|
|
108
|
+
args: {
|
|
109
|
+
// TODO: Make it `-t` in the next major version
|
|
110
|
+
template: {
|
|
111
|
+
type: "positional",
|
|
112
|
+
description: "Template name or a a URI describing provider, repository, subdir, and branch/ref"
|
|
113
|
+
},
|
|
114
|
+
dir: {
|
|
115
|
+
type: "positional",
|
|
116
|
+
description: "A relative or absolute path where to extract the template",
|
|
117
|
+
required: false
|
|
118
|
+
},
|
|
119
|
+
auth: {
|
|
120
|
+
type: "string",
|
|
121
|
+
description: "Custom Authorization token to use for downloading template. (Can be overriden with `GIGET_AUTH` environment variable)"
|
|
122
|
+
},
|
|
123
|
+
cwd: {
|
|
124
|
+
type: "string",
|
|
125
|
+
description: "Set current working directory to resolve dirs relative to it"
|
|
126
|
+
},
|
|
127
|
+
force: {
|
|
128
|
+
type: "boolean",
|
|
129
|
+
description: "Clone to existing directory even if exists"
|
|
130
|
+
},
|
|
131
|
+
forceClean: {
|
|
132
|
+
type: "boolean",
|
|
133
|
+
description: "Remove any existing directory or file recusively before cloning"
|
|
134
|
+
},
|
|
135
|
+
offline: {
|
|
136
|
+
type: "boolean",
|
|
137
|
+
description: "o not attempt to download and use cached version"
|
|
138
|
+
},
|
|
139
|
+
preferOffline: {
|
|
140
|
+
type: "boolean",
|
|
141
|
+
description: "Use cache if exists otherwise try to download"
|
|
142
|
+
},
|
|
143
|
+
shell: {
|
|
144
|
+
type: "boolean",
|
|
145
|
+
description: "Open a new shell with current working "
|
|
146
|
+
},
|
|
147
|
+
install: {
|
|
148
|
+
type: "boolean",
|
|
149
|
+
description: "Install dependencies after cloning"
|
|
150
|
+
},
|
|
151
|
+
verbose: {
|
|
152
|
+
type: "boolean",
|
|
153
|
+
description: "Show verbose debugging info"
|
|
154
|
+
}
|
|
155
|
+
},
|
|
156
|
+
run: async ({ args }) => {
|
|
157
|
+
if (args.verbose) {
|
|
158
|
+
process.env.DEBUG = process.env.DEBUG || "true";
|
|
159
|
+
}
|
|
160
|
+
const r = await index.downloadTemplate(args.template, {
|
|
161
|
+
dir: args.dir,
|
|
162
|
+
force: args.force,
|
|
163
|
+
forceClean: args.forceClean,
|
|
164
|
+
offline: args.offline,
|
|
165
|
+
preferOffline: args.preferOffline,
|
|
166
|
+
auth: args.auth,
|
|
167
|
+
install: args.install
|
|
168
|
+
});
|
|
169
|
+
const _from = r.name || r.url;
|
|
170
|
+
const _to = node_path.relative(process.cwd(), r.dir) || "./";
|
|
171
|
+
consola.consola.log(`\u2728 Successfully cloned \`${_from}\` to \`${_to}\`
|
|
172
|
+
`);
|
|
173
|
+
if (args.shell) {
|
|
174
|
+
index.startShell(r.dir);
|
|
175
|
+
}
|
|
64
176
|
}
|
|
65
|
-
process.exit(0);
|
|
66
|
-
}
|
|
67
|
-
main().catch((error) => {
|
|
68
|
-
console.error(error);
|
|
69
|
-
process.exit(1);
|
|
70
177
|
});
|
|
178
|
+
citty.runMain(mainCommand);
|
package/dist/cli.mjs
CHANGED
|
@@ -1,64 +1,176 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
1
|
import { relative } from 'node:path';
|
|
3
|
-
import
|
|
4
|
-
import {
|
|
2
|
+
import { defineCommand, runMain } from 'citty';
|
|
3
|
+
import { consola } from 'consola';
|
|
5
4
|
import { downloadTemplate, startShell } from './index.mjs';
|
|
6
5
|
import 'node:fs/promises';
|
|
7
6
|
import 'node:fs';
|
|
8
7
|
import 'tar';
|
|
9
8
|
import 'pathe';
|
|
10
9
|
import 'defu';
|
|
10
|
+
import 'nypm';
|
|
11
11
|
import 'node:stream';
|
|
12
12
|
import 'node:child_process';
|
|
13
13
|
import 'node:os';
|
|
14
14
|
import 'node:util';
|
|
15
|
-
import 'node-fetch-native';
|
|
15
|
+
import 'node-fetch-native/proxy';
|
|
16
16
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
17
|
+
const name = "giget";
|
|
18
|
+
const version = "1.2.0";
|
|
19
|
+
const description = "Download templates and git repositories with pleasure!";
|
|
20
|
+
const repository = "unjs/giget";
|
|
21
|
+
const license = "MIT";
|
|
22
|
+
const sideEffects = false;
|
|
23
|
+
const type = "module";
|
|
24
|
+
const exports = {
|
|
25
|
+
".": {
|
|
26
|
+
"import": {
|
|
27
|
+
types: "./dist/index.d.mts",
|
|
28
|
+
"default": "./dist/index.mjs"
|
|
29
|
+
},
|
|
30
|
+
require: {
|
|
31
|
+
types: "./dist/index.d.cts",
|
|
32
|
+
"default": "./dist/index.cjs"
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
const main = "./dist/index.cjs";
|
|
37
|
+
const module = "./dist/index.mjs";
|
|
38
|
+
const types = "./dist/index.d.ts";
|
|
39
|
+
const bin = {
|
|
40
|
+
giget: "./dist/cli.mjs"
|
|
41
|
+
};
|
|
42
|
+
const files = [
|
|
43
|
+
"dist"
|
|
44
|
+
];
|
|
45
|
+
const scripts = {
|
|
46
|
+
build: "unbuild",
|
|
47
|
+
dev: "vitest dev",
|
|
48
|
+
giget: "jiti ./src/cli.ts",
|
|
49
|
+
lint: "eslint --ext .ts,.js,.mjs,.cjs . && prettier -c src test",
|
|
50
|
+
"lint:fix": "eslint --ext .ts,.js,.mjs,.cjs . --fix && prettier -w src test",
|
|
51
|
+
prepack: "unbuild",
|
|
52
|
+
play: "pnpm giget --force-clean --verbose unjs .tmp/clone",
|
|
53
|
+
release: "pnpm test && changelogen --release && npm publish && git push --follow-tags",
|
|
54
|
+
test: "pnpm lint && vitest run --coverage"
|
|
55
|
+
};
|
|
56
|
+
const dependencies = {
|
|
57
|
+
citty: "^0.1.5",
|
|
58
|
+
consola: "^3.2.3",
|
|
59
|
+
defu: "^6.1.3",
|
|
60
|
+
"node-fetch-native": "^1.6.1",
|
|
61
|
+
nypm: "^0.3.3",
|
|
62
|
+
ohash: "^1.1.3",
|
|
63
|
+
pathe: "^1.1.1",
|
|
64
|
+
tar: "^6.2.0"
|
|
65
|
+
};
|
|
66
|
+
const devDependencies = {
|
|
67
|
+
"@types/node": "^20.10.5",
|
|
68
|
+
"@types/tar": "^6.1.10",
|
|
69
|
+
"@vitest/coverage-v8": "^1.1.0",
|
|
70
|
+
changelogen: "^0.5.5",
|
|
71
|
+
eslint: "^8.56.0",
|
|
72
|
+
"eslint-config-unjs": "^0.2.1",
|
|
73
|
+
jiti: "^1.21.0",
|
|
74
|
+
prettier: "^3.1.1",
|
|
75
|
+
typescript: "^5.3.3",
|
|
76
|
+
unbuild: "^2.0.0",
|
|
77
|
+
vitest: "^1.1.0"
|
|
78
|
+
};
|
|
79
|
+
const packageManager = "pnpm@8.12.1";
|
|
80
|
+
const pkg = {
|
|
81
|
+
name: name,
|
|
82
|
+
version: version,
|
|
83
|
+
description: description,
|
|
84
|
+
repository: repository,
|
|
85
|
+
license: license,
|
|
86
|
+
sideEffects: sideEffects,
|
|
87
|
+
type: type,
|
|
88
|
+
exports: exports,
|
|
89
|
+
main: main,
|
|
90
|
+
module: module,
|
|
91
|
+
types: types,
|
|
92
|
+
bin: bin,
|
|
93
|
+
files: files,
|
|
94
|
+
scripts: scripts,
|
|
95
|
+
dependencies: dependencies,
|
|
96
|
+
devDependencies: devDependencies,
|
|
97
|
+
packageManager: packageManager
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
const mainCommand = defineCommand({
|
|
101
|
+
meta: {
|
|
102
|
+
name: pkg.name,
|
|
103
|
+
version: pkg.version,
|
|
104
|
+
description: pkg.description
|
|
105
|
+
},
|
|
106
|
+
args: {
|
|
107
|
+
// TODO: Make it `-t` in the next major version
|
|
108
|
+
template: {
|
|
109
|
+
type: "positional",
|
|
110
|
+
description: "Template name or a a URI describing provider, repository, subdir, and branch/ref"
|
|
111
|
+
},
|
|
112
|
+
dir: {
|
|
113
|
+
type: "positional",
|
|
114
|
+
description: "A relative or absolute path where to extract the template",
|
|
115
|
+
required: false
|
|
116
|
+
},
|
|
117
|
+
auth: {
|
|
118
|
+
type: "string",
|
|
119
|
+
description: "Custom Authorization token to use for downloading template. (Can be overriden with `GIGET_AUTH` environment variable)"
|
|
120
|
+
},
|
|
121
|
+
cwd: {
|
|
122
|
+
type: "string",
|
|
123
|
+
description: "Set current working directory to resolve dirs relative to it"
|
|
124
|
+
},
|
|
125
|
+
force: {
|
|
126
|
+
type: "boolean",
|
|
127
|
+
description: "Clone to existing directory even if exists"
|
|
128
|
+
},
|
|
129
|
+
forceClean: {
|
|
130
|
+
type: "boolean",
|
|
131
|
+
description: "Remove any existing directory or file recusively before cloning"
|
|
132
|
+
},
|
|
133
|
+
offline: {
|
|
134
|
+
type: "boolean",
|
|
135
|
+
description: "o not attempt to download and use cached version"
|
|
136
|
+
},
|
|
137
|
+
preferOffline: {
|
|
138
|
+
type: "boolean",
|
|
139
|
+
description: "Use cache if exists otherwise try to download"
|
|
140
|
+
},
|
|
141
|
+
shell: {
|
|
142
|
+
type: "boolean",
|
|
143
|
+
description: "Open a new shell with current working "
|
|
144
|
+
},
|
|
145
|
+
install: {
|
|
146
|
+
type: "boolean",
|
|
147
|
+
description: "Install dependencies after cloning"
|
|
148
|
+
},
|
|
149
|
+
verbose: {
|
|
150
|
+
type: "boolean",
|
|
151
|
+
description: "Show verbose debugging info"
|
|
152
|
+
}
|
|
153
|
+
},
|
|
154
|
+
run: async ({ args }) => {
|
|
155
|
+
if (args.verbose) {
|
|
156
|
+
process.env.DEBUG = process.env.DEBUG || "true";
|
|
157
|
+
}
|
|
158
|
+
const r = await downloadTemplate(args.template, {
|
|
159
|
+
dir: args.dir,
|
|
160
|
+
force: args.force,
|
|
161
|
+
forceClean: args.forceClean,
|
|
162
|
+
offline: args.offline,
|
|
163
|
+
preferOffline: args.preferOffline,
|
|
164
|
+
auth: args.auth,
|
|
165
|
+
install: args.install
|
|
166
|
+
});
|
|
167
|
+
const _from = r.name || r.url;
|
|
168
|
+
const _to = relative(process.cwd(), r.dir) || "./";
|
|
169
|
+
consola.log(`\u2728 Successfully cloned \`${_from}\` to \`${_to}\`
|
|
170
|
+
`);
|
|
171
|
+
if (args.shell) {
|
|
172
|
+
startShell(r.dir);
|
|
173
|
+
}
|
|
58
174
|
}
|
|
59
|
-
process.exit(0);
|
|
60
|
-
}
|
|
61
|
-
main().catch((error) => {
|
|
62
|
-
console.error(error);
|
|
63
|
-
process.exit(1);
|
|
64
175
|
});
|
|
176
|
+
runMain(mainCommand);
|
package/dist/index.cjs
CHANGED
|
@@ -5,11 +5,12 @@ const node_fs = require('node:fs');
|
|
|
5
5
|
const tar = require('tar');
|
|
6
6
|
const pathe = require('pathe');
|
|
7
7
|
const defu = require('defu');
|
|
8
|
+
const nypm = require('nypm');
|
|
8
9
|
const node_stream = require('node:stream');
|
|
9
10
|
const node_child_process = require('node:child_process');
|
|
10
11
|
const node_os = require('node:os');
|
|
11
12
|
const node_util = require('node:util');
|
|
12
|
-
const
|
|
13
|
+
const proxy = require('node-fetch-native/proxy');
|
|
13
14
|
|
|
14
15
|
async function download(url, filePath, options = {}) {
|
|
15
16
|
const infoPath = filePath + ".json";
|
|
@@ -52,19 +53,19 @@ function debug(...args) {
|
|
|
52
53
|
}
|
|
53
54
|
}
|
|
54
55
|
async function sendFetch(url, options = {}) {
|
|
55
|
-
if (
|
|
56
|
-
|
|
57
|
-
if (proxyEnv) {
|
|
58
|
-
const HttpsProxyAgent = await import('https-proxy-agent').then(
|
|
59
|
-
(r) => r.HttpsProxyAgent || r.default
|
|
60
|
-
);
|
|
61
|
-
options.agent = new HttpsProxyAgent(proxyEnv);
|
|
62
|
-
}
|
|
56
|
+
if (options.headers?.["sec-fetch-mode"]) {
|
|
57
|
+
options.mode = options.headers["sec-fetch-mode"];
|
|
63
58
|
}
|
|
64
|
-
|
|
59
|
+
const res = await proxy.fetch(url, {
|
|
65
60
|
...options,
|
|
66
61
|
headers: normalizeHeaders(options.headers)
|
|
62
|
+
}).catch((error) => {
|
|
63
|
+
throw new Error(`Failed to download ${url}: ${error}`, { cause: error });
|
|
67
64
|
});
|
|
65
|
+
if (options.validateStatus && res.status >= 400) {
|
|
66
|
+
throw new Error(`Failed to fetch ${url}: ${res.status} ${res.statusText}`);
|
|
67
|
+
}
|
|
68
|
+
return res;
|
|
68
69
|
}
|
|
69
70
|
function cacheDirectory() {
|
|
70
71
|
return process.env.XDG_CACHE_HOME ? pathe.resolve(process.env.XDG_CACHE_HOME, "giget") : pathe.resolve(node_os.homedir(), ".cache/giget");
|
|
@@ -101,6 +102,57 @@ function startShell(cwd) {
|
|
|
101
102
|
});
|
|
102
103
|
}
|
|
103
104
|
|
|
105
|
+
const http = async (input, options) => {
|
|
106
|
+
if (input.endsWith(".json")) {
|
|
107
|
+
return await _httpJSON(input, options);
|
|
108
|
+
}
|
|
109
|
+
const url = new URL(input);
|
|
110
|
+
let name = pathe.basename(url.pathname);
|
|
111
|
+
try {
|
|
112
|
+
const head = await sendFetch(url.href, {
|
|
113
|
+
method: "HEAD",
|
|
114
|
+
validateStatus: true,
|
|
115
|
+
headers: {
|
|
116
|
+
authorization: options.auth ? `Bearer ${options.auth}` : void 0
|
|
117
|
+
}
|
|
118
|
+
});
|
|
119
|
+
const _contentType = head.headers.get("content-type") || "";
|
|
120
|
+
if (_contentType.includes("application/json")) {
|
|
121
|
+
return await _httpJSON(input, options);
|
|
122
|
+
}
|
|
123
|
+
const filename = head.headers.get("content-disposition")?.match(/filename="?(.+)"?/)?.[1];
|
|
124
|
+
if (filename) {
|
|
125
|
+
name = filename.split(".")[0];
|
|
126
|
+
}
|
|
127
|
+
} catch (error) {
|
|
128
|
+
debug(`Failed to fetch HEAD for ${url.href}:`, error);
|
|
129
|
+
}
|
|
130
|
+
return {
|
|
131
|
+
name: `${name}-${url.href.slice(0, 8)}`,
|
|
132
|
+
version: "",
|
|
133
|
+
subdir: "",
|
|
134
|
+
tar: url.href,
|
|
135
|
+
defaultDir: name,
|
|
136
|
+
headers: {
|
|
137
|
+
Authorization: options.auth ? `Bearer ${options.auth}` : void 0
|
|
138
|
+
}
|
|
139
|
+
};
|
|
140
|
+
};
|
|
141
|
+
const _httpJSON = async (input, options) => {
|
|
142
|
+
const result = await sendFetch(input, {
|
|
143
|
+
validateStatus: true,
|
|
144
|
+
headers: {
|
|
145
|
+
authorization: options.auth ? `Bearer ${options.auth}` : void 0
|
|
146
|
+
}
|
|
147
|
+
});
|
|
148
|
+
const info = await result.json();
|
|
149
|
+
if (!info.tar || !info.name) {
|
|
150
|
+
throw new Error(
|
|
151
|
+
`Invalid template info from ${input}. name or tar fields are missing!`
|
|
152
|
+
);
|
|
153
|
+
}
|
|
154
|
+
return info;
|
|
155
|
+
};
|
|
104
156
|
const github = (input, options) => {
|
|
105
157
|
const parsed = parseGitURI(input);
|
|
106
158
|
const githubAPIURL = process.env.GIGET_GITHUB_URL || "https://api.github.com";
|
|
@@ -125,7 +177,9 @@ const gitlab = (input, options) => {
|
|
|
125
177
|
version: parsed.ref,
|
|
126
178
|
subdir: parsed.subdir,
|
|
127
179
|
headers: {
|
|
128
|
-
authorization: options.auth ? `Bearer ${options.auth}` : void 0
|
|
180
|
+
authorization: options.auth ? `Bearer ${options.auth}` : void 0,
|
|
181
|
+
// https://gitlab.com/gitlab-org/gitlab/-/commit/50c11f278d18fe1f3fb12eb595067216bb58ade2
|
|
182
|
+
"sec-fetch-mode": "same-origin"
|
|
129
183
|
},
|
|
130
184
|
url: `${gitlab2}/${parsed.repo}/tree/${parsed.ref}${parsed.subdir}`,
|
|
131
185
|
tar: `${gitlab2}/${parsed.repo}/-/archive/${parsed.ref}.tar.gz`
|
|
@@ -158,6 +212,8 @@ const sourcehut = (input, options) => {
|
|
|
158
212
|
};
|
|
159
213
|
};
|
|
160
214
|
const providers = {
|
|
215
|
+
http,
|
|
216
|
+
https: http,
|
|
161
217
|
github,
|
|
162
218
|
gh: github,
|
|
163
219
|
gitlab,
|
|
@@ -209,6 +265,9 @@ async function downloadTemplate(input, options = {}) {
|
|
|
209
265
|
if (sourceProvierMatch) {
|
|
210
266
|
providerName = sourceProvierMatch[1];
|
|
211
267
|
source = input.slice(sourceProvierMatch[0].length);
|
|
268
|
+
if (providerName === "http" || providerName === "https") {
|
|
269
|
+
source = input;
|
|
270
|
+
}
|
|
212
271
|
}
|
|
213
272
|
const provider = options.providers?.[providerName] || providers[providerName] || registry;
|
|
214
273
|
if (!provider) {
|
|
@@ -227,15 +286,6 @@ async function downloadTemplate(input, options = {}) {
|
|
|
227
286
|
/[^\da-z-]/gi,
|
|
228
287
|
"-"
|
|
229
288
|
);
|
|
230
|
-
const cwd = pathe.resolve(options.cwd || ".");
|
|
231
|
-
const extractPath = pathe.resolve(cwd, options.dir || template.defaultDir);
|
|
232
|
-
if (options.forceClean) {
|
|
233
|
-
await promises.rm(extractPath, { recursive: true, force: true });
|
|
234
|
-
}
|
|
235
|
-
if (!options.force && node_fs.existsSync(extractPath) && node_fs.readdirSync(extractPath).length > 0) {
|
|
236
|
-
throw new Error(`Destination ${extractPath} already exists.`);
|
|
237
|
-
}
|
|
238
|
-
await promises.mkdir(extractPath, { recursive: true });
|
|
239
289
|
const temporaryDirectory = pathe.resolve(
|
|
240
290
|
cacheDirectory(),
|
|
241
291
|
providerName,
|
|
@@ -270,6 +320,15 @@ async function downloadTemplate(input, options = {}) {
|
|
|
270
320
|
`Tarball not found: ${tarPath} (offline: ${options.offline})`
|
|
271
321
|
);
|
|
272
322
|
}
|
|
323
|
+
const cwd = pathe.resolve(options.cwd || ".");
|
|
324
|
+
const extractPath = pathe.resolve(cwd, options.dir || template.defaultDir);
|
|
325
|
+
if (options.forceClean) {
|
|
326
|
+
await promises.rm(extractPath, { recursive: true, force: true });
|
|
327
|
+
}
|
|
328
|
+
if (!options.force && node_fs.existsSync(extractPath) && node_fs.readdirSync(extractPath).length > 0) {
|
|
329
|
+
throw new Error(`Destination ${extractPath} already exists.`);
|
|
330
|
+
}
|
|
331
|
+
await promises.mkdir(extractPath, { recursive: true });
|
|
273
332
|
const s = Date.now();
|
|
274
333
|
const subdir = template.subdir?.replace(/^\//, "") || "";
|
|
275
334
|
await tar.extract({
|
|
@@ -287,6 +346,13 @@ async function downloadTemplate(input, options = {}) {
|
|
|
287
346
|
}
|
|
288
347
|
});
|
|
289
348
|
debug(`Extracted to ${extractPath} in ${Date.now() - s}ms`);
|
|
349
|
+
if (options.install) {
|
|
350
|
+
debug("Installing dependencies...");
|
|
351
|
+
await nypm.installDependencies({
|
|
352
|
+
cwd: extractPath,
|
|
353
|
+
silent: options.silent
|
|
354
|
+
});
|
|
355
|
+
}
|
|
290
356
|
return {
|
|
291
357
|
...template,
|
|
292
358
|
source,
|
package/dist/index.d.cts
CHANGED
package/dist/index.d.mts
CHANGED
package/dist/index.d.ts
CHANGED
package/dist/index.mjs
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
|
-
import { readFile, writeFile,
|
|
1
|
+
import { readFile, writeFile, mkdir, rm } from 'node:fs/promises';
|
|
2
2
|
import { existsSync, createWriteStream, readdirSync } from 'node:fs';
|
|
3
3
|
import { extract } from 'tar';
|
|
4
|
-
import { resolve, relative, dirname } from 'pathe';
|
|
4
|
+
import { resolve, relative, basename, dirname } from 'pathe';
|
|
5
5
|
import { defu } from 'defu';
|
|
6
|
+
import { installDependencies } from 'nypm';
|
|
6
7
|
import { pipeline } from 'node:stream';
|
|
7
8
|
import { spawnSync } from 'node:child_process';
|
|
8
9
|
import { homedir } from 'node:os';
|
|
9
10
|
import { promisify } from 'node:util';
|
|
10
|
-
import { fetch } from 'node-fetch-native';
|
|
11
|
+
import { fetch } from 'node-fetch-native/proxy';
|
|
11
12
|
|
|
12
13
|
async function download(url, filePath, options = {}) {
|
|
13
14
|
const infoPath = filePath + ".json";
|
|
@@ -50,19 +51,19 @@ function debug(...args) {
|
|
|
50
51
|
}
|
|
51
52
|
}
|
|
52
53
|
async function sendFetch(url, options = {}) {
|
|
53
|
-
if (
|
|
54
|
-
|
|
55
|
-
if (proxyEnv) {
|
|
56
|
-
const HttpsProxyAgent = await import('https-proxy-agent').then(
|
|
57
|
-
(r) => r.HttpsProxyAgent || r.default
|
|
58
|
-
);
|
|
59
|
-
options.agent = new HttpsProxyAgent(proxyEnv);
|
|
60
|
-
}
|
|
54
|
+
if (options.headers?.["sec-fetch-mode"]) {
|
|
55
|
+
options.mode = options.headers["sec-fetch-mode"];
|
|
61
56
|
}
|
|
62
|
-
|
|
57
|
+
const res = await fetch(url, {
|
|
63
58
|
...options,
|
|
64
59
|
headers: normalizeHeaders(options.headers)
|
|
60
|
+
}).catch((error) => {
|
|
61
|
+
throw new Error(`Failed to download ${url}: ${error}`, { cause: error });
|
|
65
62
|
});
|
|
63
|
+
if (options.validateStatus && res.status >= 400) {
|
|
64
|
+
throw new Error(`Failed to fetch ${url}: ${res.status} ${res.statusText}`);
|
|
65
|
+
}
|
|
66
|
+
return res;
|
|
66
67
|
}
|
|
67
68
|
function cacheDirectory() {
|
|
68
69
|
return process.env.XDG_CACHE_HOME ? resolve(process.env.XDG_CACHE_HOME, "giget") : resolve(homedir(), ".cache/giget");
|
|
@@ -99,6 +100,57 @@ function startShell(cwd) {
|
|
|
99
100
|
});
|
|
100
101
|
}
|
|
101
102
|
|
|
103
|
+
const http = async (input, options) => {
|
|
104
|
+
if (input.endsWith(".json")) {
|
|
105
|
+
return await _httpJSON(input, options);
|
|
106
|
+
}
|
|
107
|
+
const url = new URL(input);
|
|
108
|
+
let name = basename(url.pathname);
|
|
109
|
+
try {
|
|
110
|
+
const head = await sendFetch(url.href, {
|
|
111
|
+
method: "HEAD",
|
|
112
|
+
validateStatus: true,
|
|
113
|
+
headers: {
|
|
114
|
+
authorization: options.auth ? `Bearer ${options.auth}` : void 0
|
|
115
|
+
}
|
|
116
|
+
});
|
|
117
|
+
const _contentType = head.headers.get("content-type") || "";
|
|
118
|
+
if (_contentType.includes("application/json")) {
|
|
119
|
+
return await _httpJSON(input, options);
|
|
120
|
+
}
|
|
121
|
+
const filename = head.headers.get("content-disposition")?.match(/filename="?(.+)"?/)?.[1];
|
|
122
|
+
if (filename) {
|
|
123
|
+
name = filename.split(".")[0];
|
|
124
|
+
}
|
|
125
|
+
} catch (error) {
|
|
126
|
+
debug(`Failed to fetch HEAD for ${url.href}:`, error);
|
|
127
|
+
}
|
|
128
|
+
return {
|
|
129
|
+
name: `${name}-${url.href.slice(0, 8)}`,
|
|
130
|
+
version: "",
|
|
131
|
+
subdir: "",
|
|
132
|
+
tar: url.href,
|
|
133
|
+
defaultDir: name,
|
|
134
|
+
headers: {
|
|
135
|
+
Authorization: options.auth ? `Bearer ${options.auth}` : void 0
|
|
136
|
+
}
|
|
137
|
+
};
|
|
138
|
+
};
|
|
139
|
+
const _httpJSON = async (input, options) => {
|
|
140
|
+
const result = await sendFetch(input, {
|
|
141
|
+
validateStatus: true,
|
|
142
|
+
headers: {
|
|
143
|
+
authorization: options.auth ? `Bearer ${options.auth}` : void 0
|
|
144
|
+
}
|
|
145
|
+
});
|
|
146
|
+
const info = await result.json();
|
|
147
|
+
if (!info.tar || !info.name) {
|
|
148
|
+
throw new Error(
|
|
149
|
+
`Invalid template info from ${input}. name or tar fields are missing!`
|
|
150
|
+
);
|
|
151
|
+
}
|
|
152
|
+
return info;
|
|
153
|
+
};
|
|
102
154
|
const github = (input, options) => {
|
|
103
155
|
const parsed = parseGitURI(input);
|
|
104
156
|
const githubAPIURL = process.env.GIGET_GITHUB_URL || "https://api.github.com";
|
|
@@ -123,7 +175,9 @@ const gitlab = (input, options) => {
|
|
|
123
175
|
version: parsed.ref,
|
|
124
176
|
subdir: parsed.subdir,
|
|
125
177
|
headers: {
|
|
126
|
-
authorization: options.auth ? `Bearer ${options.auth}` : void 0
|
|
178
|
+
authorization: options.auth ? `Bearer ${options.auth}` : void 0,
|
|
179
|
+
// https://gitlab.com/gitlab-org/gitlab/-/commit/50c11f278d18fe1f3fb12eb595067216bb58ade2
|
|
180
|
+
"sec-fetch-mode": "same-origin"
|
|
127
181
|
},
|
|
128
182
|
url: `${gitlab2}/${parsed.repo}/tree/${parsed.ref}${parsed.subdir}`,
|
|
129
183
|
tar: `${gitlab2}/${parsed.repo}/-/archive/${parsed.ref}.tar.gz`
|
|
@@ -156,6 +210,8 @@ const sourcehut = (input, options) => {
|
|
|
156
210
|
};
|
|
157
211
|
};
|
|
158
212
|
const providers = {
|
|
213
|
+
http,
|
|
214
|
+
https: http,
|
|
159
215
|
github,
|
|
160
216
|
gh: github,
|
|
161
217
|
gitlab,
|
|
@@ -207,6 +263,9 @@ async function downloadTemplate(input, options = {}) {
|
|
|
207
263
|
if (sourceProvierMatch) {
|
|
208
264
|
providerName = sourceProvierMatch[1];
|
|
209
265
|
source = input.slice(sourceProvierMatch[0].length);
|
|
266
|
+
if (providerName === "http" || providerName === "https") {
|
|
267
|
+
source = input;
|
|
268
|
+
}
|
|
210
269
|
}
|
|
211
270
|
const provider = options.providers?.[providerName] || providers[providerName] || registry;
|
|
212
271
|
if (!provider) {
|
|
@@ -225,15 +284,6 @@ async function downloadTemplate(input, options = {}) {
|
|
|
225
284
|
/[^\da-z-]/gi,
|
|
226
285
|
"-"
|
|
227
286
|
);
|
|
228
|
-
const cwd = resolve(options.cwd || ".");
|
|
229
|
-
const extractPath = resolve(cwd, options.dir || template.defaultDir);
|
|
230
|
-
if (options.forceClean) {
|
|
231
|
-
await rm(extractPath, { recursive: true, force: true });
|
|
232
|
-
}
|
|
233
|
-
if (!options.force && existsSync(extractPath) && readdirSync(extractPath).length > 0) {
|
|
234
|
-
throw new Error(`Destination ${extractPath} already exists.`);
|
|
235
|
-
}
|
|
236
|
-
await mkdir(extractPath, { recursive: true });
|
|
237
287
|
const temporaryDirectory = resolve(
|
|
238
288
|
cacheDirectory(),
|
|
239
289
|
providerName,
|
|
@@ -268,6 +318,15 @@ async function downloadTemplate(input, options = {}) {
|
|
|
268
318
|
`Tarball not found: ${tarPath} (offline: ${options.offline})`
|
|
269
319
|
);
|
|
270
320
|
}
|
|
321
|
+
const cwd = resolve(options.cwd || ".");
|
|
322
|
+
const extractPath = resolve(cwd, options.dir || template.defaultDir);
|
|
323
|
+
if (options.forceClean) {
|
|
324
|
+
await rm(extractPath, { recursive: true, force: true });
|
|
325
|
+
}
|
|
326
|
+
if (!options.force && existsSync(extractPath) && readdirSync(extractPath).length > 0) {
|
|
327
|
+
throw new Error(`Destination ${extractPath} already exists.`);
|
|
328
|
+
}
|
|
329
|
+
await mkdir(extractPath, { recursive: true });
|
|
271
330
|
const s = Date.now();
|
|
272
331
|
const subdir = template.subdir?.replace(/^\//, "") || "";
|
|
273
332
|
await extract({
|
|
@@ -285,6 +344,13 @@ async function downloadTemplate(input, options = {}) {
|
|
|
285
344
|
}
|
|
286
345
|
});
|
|
287
346
|
debug(`Extracted to ${extractPath} in ${Date.now() - s}ms`);
|
|
347
|
+
if (options.install) {
|
|
348
|
+
debug("Installing dependencies...");
|
|
349
|
+
await installDependencies({
|
|
350
|
+
cwd: extractPath,
|
|
351
|
+
silent: options.silent
|
|
352
|
+
});
|
|
353
|
+
}
|
|
288
354
|
return {
|
|
289
355
|
...template,
|
|
290
356
|
source,
|
package/package.json
CHANGED
|
@@ -1,24 +1,29 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "giget",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"description": "Download templates and git repositories with pleasure!",
|
|
5
5
|
"repository": "unjs/giget",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"sideEffects": false,
|
|
8
8
|
"type": "module",
|
|
9
|
-
"bin": {
|
|
10
|
-
"giget": "./dist/cli.mjs"
|
|
11
|
-
},
|
|
12
9
|
"exports": {
|
|
13
10
|
".": {
|
|
14
|
-
"import":
|
|
15
|
-
|
|
16
|
-
|
|
11
|
+
"import": {
|
|
12
|
+
"types": "./dist/index.d.mts",
|
|
13
|
+
"default": "./dist/index.mjs"
|
|
14
|
+
},
|
|
15
|
+
"require": {
|
|
16
|
+
"types": "./dist/index.d.cts",
|
|
17
|
+
"default": "./dist/index.cjs"
|
|
18
|
+
}
|
|
17
19
|
}
|
|
18
20
|
},
|
|
19
21
|
"main": "./dist/index.cjs",
|
|
20
22
|
"module": "./dist/index.mjs",
|
|
21
23
|
"types": "./dist/index.d.ts",
|
|
24
|
+
"bin": {
|
|
25
|
+
"giget": "./dist/cli.mjs"
|
|
26
|
+
},
|
|
22
27
|
"files": [
|
|
23
28
|
"dist"
|
|
24
29
|
],
|
|
@@ -34,26 +39,27 @@
|
|
|
34
39
|
"test": "pnpm lint && vitest run --coverage"
|
|
35
40
|
},
|
|
36
41
|
"dependencies": {
|
|
37
|
-
"
|
|
38
|
-
"
|
|
39
|
-
"
|
|
40
|
-
"
|
|
41
|
-
"
|
|
42
|
+
"citty": "^0.1.5",
|
|
43
|
+
"consola": "^3.2.3",
|
|
44
|
+
"defu": "^6.1.3",
|
|
45
|
+
"node-fetch-native": "^1.6.1",
|
|
46
|
+
"nypm": "^0.3.3",
|
|
47
|
+
"ohash": "^1.1.3",
|
|
42
48
|
"pathe": "^1.1.1",
|
|
43
49
|
"tar": "^6.2.0"
|
|
44
50
|
},
|
|
45
51
|
"devDependencies": {
|
|
46
|
-
"@types/node": "^20.
|
|
47
|
-
"@types/tar": "^6.1.
|
|
48
|
-
"@vitest/coverage-v8": "^
|
|
52
|
+
"@types/node": "^20.10.5",
|
|
53
|
+
"@types/tar": "^6.1.10",
|
|
54
|
+
"@vitest/coverage-v8": "^1.1.0",
|
|
49
55
|
"changelogen": "^0.5.5",
|
|
50
|
-
"eslint": "^8.
|
|
56
|
+
"eslint": "^8.56.0",
|
|
51
57
|
"eslint-config-unjs": "^0.2.1",
|
|
52
|
-
"jiti": "^1.
|
|
53
|
-
"prettier": "^3.
|
|
54
|
-
"typescript": "^5.
|
|
58
|
+
"jiti": "^1.21.0",
|
|
59
|
+
"prettier": "^3.1.1",
|
|
60
|
+
"typescript": "^5.3.3",
|
|
55
61
|
"unbuild": "^2.0.0",
|
|
56
|
-
"vitest": "^
|
|
62
|
+
"vitest": "^1.1.0"
|
|
57
63
|
},
|
|
58
|
-
"packageManager": "pnpm@8.
|
|
64
|
+
"packageManager": "pnpm@8.12.1"
|
|
59
65
|
}
|