giget 0.1.7 → 1.0.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/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2022 - UnJS
3
+ Copyright (c) Pooya Parsa <pooya@pi0.io>
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
package/README.md CHANGED
@@ -89,7 +89,7 @@ A custom registry should provide an endpoint with dynamic path `/:template.json`
89
89
  - `tar` (required) Link to the tar download link.
90
90
  - `defaultDir`: (optional) Default cloning directory.
91
91
  - `url`: (optional) Webpage of the template.
92
- - `subpath`: (optional) Subpath inside the tar file.
92
+ - `subdir`: (optional) Directory inside the tar file.
93
93
  - `headers`: (optional) Custom headers to send while downloading template.
94
94
 
95
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.
@@ -135,7 +135,7 @@ const { source, dir } = await downloadTemplate('github:unjs/template')
135
135
  - `provider`: (string) Either `github`, `gitlab`, `bitbucket` or `sourcehut`. The default is `github`.
136
136
  - `repo`: (string) Name of repository in format of `{username}/{reponame}`.
137
137
  - `ref`: (string) Git ref (branch or commit or tag). The default value is `main`.
138
- - `subdirpath`: (string) subdir of the repo to clone from. The default value is none.
138
+ - `subdir`: (string) Directory of the repo to clone from. The default value is none.
139
139
  - `force`: (boolean) Extract to the exisiting dir even if already exsists.
140
140
  - `forceClean`: (boolean) ⚠️ Clean ups any existing directory or file before cloning.
141
141
  - `offline`: (boolean) Do not attempt to download and use cached version.
package/dist/cli.cjs CHANGED
@@ -4,7 +4,7 @@
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.3522139c.cjs');
7
+ const giget = require('./shared/giget.1028e17a.cjs');
8
8
  require('node:fs/promises');
9
9
  require('node:os');
10
10
  require('node:fs');
@@ -15,42 +15,39 @@ require('node:stream');
15
15
  require('node:child_process');
16
16
  require('node:util');
17
17
  require('node-fetch-native');
18
-
19
- function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e["default"] : e; }
20
-
21
- const mri__default = /*#__PURE__*/_interopDefaultLegacy(mri);
18
+ require('https-proxy-agent');
22
19
 
23
20
  async function main() {
24
- const args = mri__default(process.argv.slice(2), {
21
+ const arguments_ = mri(process.argv.slice(2), {
25
22
  boolean: ["help", "force", "force-clean", "offline", "prefer-offline", "shell", "verbose"],
26
23
  string: ["registry", "cwd", "auth"]
27
24
  });
28
- const input = args._[0];
29
- const dir = args._[1];
30
- if (!input || args.help || args.h) {
25
+ const input = arguments_._[0];
26
+ const dir = arguments_._[1];
27
+ if (!input || arguments_.help || arguments_.h) {
31
28
  console.error("Usage: npx getgit@latest <input> [<dir>] [--force] [--force-clean] [--offline] [--prefer-offline] [--shell] [--registry] [--no-registry] [--verbose] [--cwd] [--auth]");
32
29
  process.exit(1);
33
30
  }
34
- if (args.verbose) {
31
+ if (arguments_.verbose) {
35
32
  process.env.DEBUG = process.env.DEBUG || "true";
36
33
  }
37
34
  const r = await giget.downloadTemplate(input, {
38
35
  dir,
39
- force: args.force,
40
- forceClean: args["force-clean"],
41
- offline: args.offline,
42
- registry: args.registry,
43
- cwd: args.cwd,
44
- auth: args.auth
36
+ force: arguments_.force,
37
+ forceClean: arguments_["force-clean"],
38
+ offline: arguments_.offline,
39
+ registry: arguments_.registry,
40
+ cwd: arguments_.cwd,
41
+ auth: arguments_.auth
45
42
  });
46
43
  console.log(`\u2728 Successfully cloned ${colorette.cyan(r.name || r.url)} to ${colorette.cyan(node_path.relative(process.cwd(), r.dir))}
47
44
  `);
48
- if (args.shell) {
45
+ if (arguments_.shell) {
49
46
  giget.startShell(r.dir);
50
47
  }
51
48
  process.exit(0);
52
49
  }
53
- main().catch((err) => {
54
- console.error(err);
50
+ main().catch((error) => {
51
+ console.error(error);
55
52
  process.exit(1);
56
53
  });
package/dist/cli.mjs CHANGED
@@ -2,7 +2,7 @@
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.dd19862e.mjs';
5
+ import { d as downloadTemplate, s as startShell } from './shared/giget.5e7ec864.mjs';
6
6
  import 'node:fs/promises';
7
7
  import 'node:os';
8
8
  import 'node:fs';
@@ -13,38 +13,39 @@ import 'node:stream';
13
13
  import 'node:child_process';
14
14
  import 'node:util';
15
15
  import 'node-fetch-native';
16
+ import 'https-proxy-agent';
16
17
 
17
18
  async function main() {
18
- const args = mri(process.argv.slice(2), {
19
+ const arguments_ = mri(process.argv.slice(2), {
19
20
  boolean: ["help", "force", "force-clean", "offline", "prefer-offline", "shell", "verbose"],
20
21
  string: ["registry", "cwd", "auth"]
21
22
  });
22
- const input = args._[0];
23
- const dir = args._[1];
24
- if (!input || args.help || args.h) {
23
+ const input = arguments_._[0];
24
+ const dir = arguments_._[1];
25
+ if (!input || arguments_.help || arguments_.h) {
25
26
  console.error("Usage: npx getgit@latest <input> [<dir>] [--force] [--force-clean] [--offline] [--prefer-offline] [--shell] [--registry] [--no-registry] [--verbose] [--cwd] [--auth]");
26
27
  process.exit(1);
27
28
  }
28
- if (args.verbose) {
29
+ if (arguments_.verbose) {
29
30
  process.env.DEBUG = process.env.DEBUG || "true";
30
31
  }
31
32
  const r = await downloadTemplate(input, {
32
33
  dir,
33
- force: args.force,
34
- forceClean: args["force-clean"],
35
- offline: args.offline,
36
- registry: args.registry,
37
- cwd: args.cwd,
38
- auth: args.auth
34
+ force: arguments_.force,
35
+ forceClean: arguments_["force-clean"],
36
+ offline: arguments_.offline,
37
+ registry: arguments_.registry,
38
+ cwd: arguments_.cwd,
39
+ auth: arguments_.auth
39
40
  });
40
41
  console.log(`\u2728 Successfully cloned ${cyan(r.name || r.url)} to ${cyan(relative(process.cwd(), r.dir))}
41
42
  `);
42
- if (args.shell) {
43
+ if (arguments_.shell) {
43
44
  startShell(r.dir);
44
45
  }
45
46
  process.exit(0);
46
47
  }
47
- main().catch((err) => {
48
- console.error(err);
48
+ main().catch((error) => {
49
+ console.error(error);
49
50
  process.exit(1);
50
51
  });
package/dist/index.cjs CHANGED
@@ -1,8 +1,6 @@
1
1
  'use strict';
2
2
 
3
- Object.defineProperty(exports, '__esModule', { value: true });
4
-
5
- const giget = require('./shared/giget.3522139c.cjs');
3
+ const giget = require('./shared/giget.1028e17a.cjs');
6
4
  require('node:fs/promises');
7
5
  require('node:os');
8
6
  require('node:fs');
@@ -13,6 +11,7 @@ require('node:stream');
13
11
  require('node:child_process');
14
12
  require('node:util');
15
13
  require('node-fetch-native');
14
+ require('https-proxy-agent');
16
15
 
17
16
 
18
17
 
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  interface GitInfo {
2
- provider: 'github' | 'gitlab' | 'bitbucket' | 'sourcehut';
2
+ provider: "github" | "gitlab" | "bitbucket" | "sourcehut";
3
3
  repo: string;
4
4
  subdir: string;
5
5
  ref: string;
@@ -32,11 +32,11 @@ interface DownloadTemplateOptions {
32
32
  cwd?: string;
33
33
  auth?: string;
34
34
  }
35
- declare type DownloadTemplateResult = Omit<TemplateInfo, 'dir' | 'source'> & {
35
+ declare type DownloadTemplateResult = Omit<TemplateInfo, "dir" | "source"> & {
36
36
  dir: string;
37
37
  source: string;
38
38
  };
39
- declare function downloadTemplate(input: string, opts?: DownloadTemplateOptions): Promise<DownloadTemplateResult>;
39
+ declare function downloadTemplate(input: string, options?: DownloadTemplateOptions): Promise<DownloadTemplateResult>;
40
40
 
41
41
  declare const registryProvider: (registryEndpoint?: string) => TemplateProvider;
42
42
 
package/dist/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
- export { d as downloadTemplate, r as registryProvider, s as startShell } from './shared/giget.dd19862e.mjs';
1
+ export { d as downloadTemplate, r as registryProvider, s as startShell } from './shared/giget.5e7ec864.mjs';
2
2
  import 'node:fs/promises';
3
3
  import 'node:os';
4
4
  import 'node:fs';
@@ -9,3 +9,4 @@ import 'node:stream';
9
9
  import 'node:child_process';
10
10
  import 'node:util';
11
11
  import 'node-fetch-native';
12
+ import 'https-proxy-agent';
@@ -9,27 +9,24 @@ const defu = require('defu');
9
9
  const node_stream = require('node:stream');
10
10
  const node_child_process = require('node:child_process');
11
11
  const node_util = require('node:util');
12
- const fetch = require('node-fetch-native');
12
+ const nodeFetchNative = require('node-fetch-native');
13
+ const createHttpsProxyAgent = require('https-proxy-agent');
13
14
 
14
- function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e["default"] : e; }
15
-
16
- const fetch__default = /*#__PURE__*/_interopDefaultLegacy(fetch);
17
-
18
- async function download(url, filePath, opts = {}) {
15
+ async function download(url, filePath, options = {}) {
19
16
  const infoPath = filePath + ".json";
20
17
  const info = JSON.parse(await promises.readFile(infoPath, "utf8").catch(() => "{}"));
21
- const headRes = await fetch.fetch(url, { method: "HEAD", headers: opts.headers }).catch(() => null);
22
- const etag = headRes?.headers.get("etag");
18
+ const headResponse = await sendFetch(url, { method: "HEAD", headers: options.headers }).catch(() => void 0);
19
+ const etag = headResponse?.headers.get("etag");
23
20
  if (info.etag === etag && node_fs.existsSync(filePath)) {
24
21
  return;
25
22
  }
26
23
  info.etag = etag;
27
- const res = await fetch.fetch(url, { headers: opts.headers });
28
- if (res.status >= 400) {
29
- throw new Error(`Failed to download ${url}: ${res.status} ${res.statusText}`);
24
+ const response = await sendFetch(url, { headers: options.headers });
25
+ if (response.status >= 400) {
26
+ throw new Error(`Failed to download ${url}: ${response.status} ${response.statusText}`);
30
27
  }
31
28
  const stream = node_fs.createWriteStream(filePath);
32
- await node_util.promisify(node_stream.pipeline)(res.body, stream);
29
+ await node_util.promisify(node_stream.pipeline)(response.body, stream);
33
30
  await promises.writeFile(infoPath, JSON.stringify(info), "utf8");
34
31
  }
35
32
  const inputRegex = /^(?<repo>[\w.-]+\/[\w.-]+)(?<subdir>[^#]+)?(?<ref>#[\w.-]+)?/;
@@ -38,14 +35,19 @@ function parseGitURI(input) {
38
35
  return {
39
36
  repo: m.repo,
40
37
  subdir: m.subdir || "/",
41
- ref: m.ref ? m.ref.substring(1) : "main"
38
+ ref: m.ref ? m.ref.slice(1) : "main"
42
39
  };
43
40
  }
44
- function debug(...args) {
41
+ function debug(...arguments_) {
45
42
  if (process.env.DEBUG) {
46
- console.debug("[giget]", ...args);
43
+ console.debug("[giget]", ...arguments_);
47
44
  }
48
45
  }
46
+ async function sendFetch(url, options) {
47
+ const proxy = process.env.HTTPS_PROXY || process.env.https_proxy || process.env.HTTP_PROXY || process.env.http_proxy;
48
+ const requestOptions = proxy ? { agent: createHttpsProxyAgent(proxy), ...options } : options;
49
+ return await nodeFetchNative.fetch(url, requestOptions);
50
+ }
49
51
  function currentShell() {
50
52
  if (process.env.SHELL) {
51
53
  return process.env.SHELL;
@@ -66,46 +68,46 @@ function startShell(cwd) {
66
68
  });
67
69
  }
68
70
 
69
- const github = (input, opts) => {
71
+ const github = (input, options) => {
70
72
  const parsed = parseGitURI(input);
71
73
  return {
72
74
  name: parsed.repo.replace("/", "-"),
73
75
  version: parsed.ref,
74
76
  subdir: parsed.subdir,
75
- headers: { Authorization: opts.auth ? `Bearer ${opts.auth}` : void 0 },
77
+ headers: { Authorization: options.auth ? `Bearer ${options.auth}` : void 0 },
76
78
  url: `https://github.com/${parsed.repo}/tree/${parsed.ref}${parsed.subdir}`,
77
79
  tar: `https://github.com/${parsed.repo}/archive/${parsed.ref}.tar.gz`
78
80
  };
79
81
  };
80
- const gitlab = (input, opts) => {
82
+ const gitlab = (input, options) => {
81
83
  const parsed = parseGitURI(input);
82
84
  return {
83
85
  name: parsed.repo.replace("/", "-"),
84
86
  version: parsed.ref,
85
87
  subdir: parsed.subdir,
86
- headers: { Authorization: opts.auth ? `Bearer ${opts.auth}` : void 0 },
88
+ headers: { Authorization: options.auth ? `Bearer ${options.auth}` : void 0 },
87
89
  url: `https://gitlab.com/${parsed.repo}/tree/${parsed.ref}${parsed.subdir}`,
88
90
  tar: `https://gitlab.com/${parsed.repo}/-/archive/${parsed.ref}.tar.gz`
89
91
  };
90
92
  };
91
- const bitbucket = (input, opts) => {
93
+ const bitbucket = (input, options) => {
92
94
  const parsed = parseGitURI(input);
93
95
  return {
94
96
  name: parsed.repo.replace("/", "-"),
95
97
  version: parsed.ref,
96
98
  subdir: parsed.subdir,
97
- headers: { Authorization: opts.auth ? `Bearer ${opts.auth}` : void 0 },
99
+ headers: { Authorization: options.auth ? `Bearer ${options.auth}` : void 0 },
98
100
  url: `https://bitbucket.com/${parsed.repo}/src/${parsed.ref}${parsed.subdir}`,
99
101
  tar: `https://bitbucket.org/${parsed.repo}/get/${parsed.ref}.tar.gz`
100
102
  };
101
103
  };
102
- const sourcehut = (input, opts) => {
104
+ const sourcehut = (input, options) => {
103
105
  const parsed = parseGitURI(input);
104
106
  return {
105
107
  name: parsed.repo.replace("/", "-"),
106
108
  version: parsed.ref,
107
109
  subdir: parsed.subdir,
108
- headers: { Authorization: opts.auth ? `Bearer ${opts.auth}` : void 0 },
110
+ headers: { Authorization: options.auth ? `Bearer ${options.auth}` : void 0 },
109
111
  url: `https://git.sr.ht/~${parsed.repo}/tree/${parsed.ref}/item${parsed.subdir}`,
110
112
  tar: `https://git.sr.ht/~${parsed.repo}/archive/${parsed.ref}.tar.gz`
111
113
  };
@@ -123,11 +125,11 @@ const registryProvider = (registryEndpoint = DEFAULT_REGISTRY) => {
123
125
  return async (input) => {
124
126
  const start = Date.now();
125
127
  const registryURL = `${registryEndpoint}/${input}.json`;
126
- const res = await fetch__default(registryURL);
127
- if (res.status >= 400) {
128
- throw new Error(`Failed to download ${input} template info from ${registryURL}: ${res.status} ${res.statusText}`);
128
+ const result = await sendFetch(registryURL);
129
+ if (result.status >= 400) {
130
+ throw new Error(`Failed to download ${input} template info from ${registryURL}: ${result.status} ${result.statusText}`);
129
131
  }
130
- const info = await res.json();
132
+ const info = await result.json();
131
133
  if (!info.tar || !info.name) {
132
134
  throw new Error(`Invalid template info from ${registryURL}. name or tar fields are missing!`);
133
135
  }
@@ -137,56 +139,56 @@ const registryProvider = (registryEndpoint = DEFAULT_REGISTRY) => {
137
139
  };
138
140
 
139
141
  const sourceProtoRe = /^([\w-.]+):/;
140
- async function downloadTemplate(input, opts = {}) {
141
- opts = defu.defu({
142
+ async function downloadTemplate(input, options = {}) {
143
+ options = defu.defu({
142
144
  registry: process.env.GIGET_REGISTRY,
143
145
  auth: process.env.GIGET_AUTH
144
- }, opts);
145
- const registry = opts.registry !== false ? registryProvider(opts.registry) : null;
146
- let providerName = opts.provider || (registryProvider ? "registry" : "github");
146
+ }, options);
147
+ const registry = options.registry !== false ? registryProvider(options.registry) : void 0;
148
+ let providerName = options.provider || (registryProvider ? "registry" : "github");
147
149
  let source = input;
148
150
  const sourceProvierMatch = input.match(sourceProtoRe);
149
151
  if (sourceProvierMatch) {
150
152
  providerName = sourceProvierMatch[1];
151
- source = input.substring(sourceProvierMatch[0].length);
153
+ source = input.slice(sourceProvierMatch[0].length);
152
154
  }
153
- const provider = opts.providers?.[providerName] || providers[providerName] || registry;
155
+ const provider = options.providers?.[providerName] || providers[providerName] || registry;
154
156
  if (!provider) {
155
157
  throw new Error(`Unsupported provider: ${providerName}`);
156
158
  }
157
- const template = await Promise.resolve().then(() => provider(source, { auth: opts.auth })).catch((err) => {
158
- throw new Error(`Failed to download template from ${providerName}: ${err.message}`);
159
+ const template = await Promise.resolve().then(() => provider(source, { auth: options.auth })).catch((error) => {
160
+ throw new Error(`Failed to download template from ${providerName}: ${error.message}`);
159
161
  });
160
- template.name = (template.name || "template").replace(/[^a-z0-9-]/gi, "-");
161
- template.defaultDir = (template.defaultDir || template.name).replace(/[^a-z0-9-]/gi, "-");
162
- const cwd = pathe.resolve(opts.cwd || ".");
163
- const extractPath = pathe.resolve(cwd, opts.dir || template.defaultDir);
164
- if (opts.forceClean) {
162
+ template.name = (template.name || "template").replace(/[^\da-z-]/gi, "-");
163
+ template.defaultDir = (template.defaultDir || template.name).replace(/[^\da-z-]/gi, "-");
164
+ const cwd = pathe.resolve(options.cwd || ".");
165
+ const extractPath = pathe.resolve(cwd, options.dir || template.defaultDir);
166
+ if (options.forceClean) {
165
167
  await promises.rm(extractPath, { recursive: true, force: true });
166
168
  }
167
- if (!opts.force && node_fs.existsSync(extractPath) && node_fs.readdirSync(extractPath).length) {
169
+ if (!options.force && node_fs.existsSync(extractPath) && node_fs.readdirSync(extractPath).length > 0) {
168
170
  throw new Error(`Destination ${extractPath} already exists.`);
169
171
  }
170
172
  await promises.mkdir(extractPath, { recursive: true });
171
- const tmpDir = pathe.resolve(node_os.homedir(), ".giget", opts.provider, template.name);
172
- const tarPath = pathe.resolve(tmpDir, (template.version || template.name) + ".tar.gz");
173
- if (opts.preferOffline && node_fs.existsSync(tarPath)) {
174
- opts.offline = true;
173
+ const temporaryDirectory = pathe.resolve(node_os.homedir(), ".giget", options.provider, template.name);
174
+ const tarPath = pathe.resolve(temporaryDirectory, (template.version || template.name) + ".tar.gz");
175
+ if (options.preferOffline && node_fs.existsSync(tarPath)) {
176
+ options.offline = true;
175
177
  }
176
- if (!opts.offline) {
178
+ if (!options.offline) {
177
179
  await promises.mkdir(pathe.dirname(tarPath), { recursive: true });
178
180
  const s2 = Date.now();
179
- await download(template.tar, tarPath, { headers: template.headers }).catch((err) => {
181
+ await download(template.tar, tarPath, { headers: template.headers }).catch((error) => {
180
182
  if (!node_fs.existsSync(tarPath)) {
181
- throw err;
183
+ throw error;
182
184
  }
183
- debug("Download error. Using cached version:", err);
184
- opts.offline = true;
185
+ debug("Download error. Using cached version:", error);
186
+ options.offline = true;
185
187
  });
186
188
  debug(`Downloaded ${template.tar} to ${tarPath} in ${Date.now() - s2}ms`);
187
189
  }
188
190
  if (!node_fs.existsSync(tarPath)) {
189
- throw new Error(`Tarball not found: ${tarPath} (offline: ${opts.offline})`);
191
+ throw new Error(`Tarball not found: ${tarPath} (offline: ${options.offline})`);
190
192
  }
191
193
  const s = Date.now();
192
194
  const subdir = template.subdir?.replace(/^\//, "") || "";
@@ -197,7 +199,7 @@ async function downloadTemplate(input, opts = {}) {
197
199
  entry.path = entry.path.split("/").splice(1).join("/");
198
200
  if (subdir) {
199
201
  if (entry.path.startsWith(subdir + "/")) {
200
- entry.path = entry.path.substring(subdir.length);
202
+ entry.path = entry.path.slice(subdir.length);
201
203
  } else {
202
204
  entry.path = "";
203
205
  }
@@ -7,23 +7,24 @@ import { defu } from 'defu';
7
7
  import { pipeline } from 'node:stream';
8
8
  import { spawnSync } from 'node:child_process';
9
9
  import { promisify } from 'node:util';
10
- import fetch$1, { fetch } from 'node-fetch-native';
10
+ import { fetch } from 'node-fetch-native';
11
+ import createHttpsProxyAgent from 'https-proxy-agent';
11
12
 
12
- async function download(url, filePath, opts = {}) {
13
+ async function download(url, filePath, options = {}) {
13
14
  const infoPath = filePath + ".json";
14
15
  const info = JSON.parse(await readFile(infoPath, "utf8").catch(() => "{}"));
15
- const headRes = await fetch(url, { method: "HEAD", headers: opts.headers }).catch(() => null);
16
- const etag = headRes?.headers.get("etag");
16
+ const headResponse = await sendFetch(url, { method: "HEAD", headers: options.headers }).catch(() => void 0);
17
+ const etag = headResponse?.headers.get("etag");
17
18
  if (info.etag === etag && existsSync(filePath)) {
18
19
  return;
19
20
  }
20
21
  info.etag = etag;
21
- const res = await fetch(url, { headers: opts.headers });
22
- if (res.status >= 400) {
23
- throw new Error(`Failed to download ${url}: ${res.status} ${res.statusText}`);
22
+ const response = await sendFetch(url, { headers: options.headers });
23
+ if (response.status >= 400) {
24
+ throw new Error(`Failed to download ${url}: ${response.status} ${response.statusText}`);
24
25
  }
25
26
  const stream = createWriteStream(filePath);
26
- await promisify(pipeline)(res.body, stream);
27
+ await promisify(pipeline)(response.body, stream);
27
28
  await writeFile(infoPath, JSON.stringify(info), "utf8");
28
29
  }
29
30
  const inputRegex = /^(?<repo>[\w.-]+\/[\w.-]+)(?<subdir>[^#]+)?(?<ref>#[\w.-]+)?/;
@@ -32,14 +33,19 @@ function parseGitURI(input) {
32
33
  return {
33
34
  repo: m.repo,
34
35
  subdir: m.subdir || "/",
35
- ref: m.ref ? m.ref.substring(1) : "main"
36
+ ref: m.ref ? m.ref.slice(1) : "main"
36
37
  };
37
38
  }
38
- function debug(...args) {
39
+ function debug(...arguments_) {
39
40
  if (process.env.DEBUG) {
40
- console.debug("[giget]", ...args);
41
+ console.debug("[giget]", ...arguments_);
41
42
  }
42
43
  }
44
+ async function sendFetch(url, options) {
45
+ const proxy = process.env.HTTPS_PROXY || process.env.https_proxy || process.env.HTTP_PROXY || process.env.http_proxy;
46
+ const requestOptions = proxy ? { agent: createHttpsProxyAgent(proxy), ...options } : options;
47
+ return await fetch(url, requestOptions);
48
+ }
43
49
  function currentShell() {
44
50
  if (process.env.SHELL) {
45
51
  return process.env.SHELL;
@@ -60,46 +66,46 @@ function startShell(cwd) {
60
66
  });
61
67
  }
62
68
 
63
- const github = (input, opts) => {
69
+ const github = (input, options) => {
64
70
  const parsed = parseGitURI(input);
65
71
  return {
66
72
  name: parsed.repo.replace("/", "-"),
67
73
  version: parsed.ref,
68
74
  subdir: parsed.subdir,
69
- headers: { Authorization: opts.auth ? `Bearer ${opts.auth}` : void 0 },
75
+ headers: { Authorization: options.auth ? `Bearer ${options.auth}` : void 0 },
70
76
  url: `https://github.com/${parsed.repo}/tree/${parsed.ref}${parsed.subdir}`,
71
77
  tar: `https://github.com/${parsed.repo}/archive/${parsed.ref}.tar.gz`
72
78
  };
73
79
  };
74
- const gitlab = (input, opts) => {
80
+ const gitlab = (input, options) => {
75
81
  const parsed = parseGitURI(input);
76
82
  return {
77
83
  name: parsed.repo.replace("/", "-"),
78
84
  version: parsed.ref,
79
85
  subdir: parsed.subdir,
80
- headers: { Authorization: opts.auth ? `Bearer ${opts.auth}` : void 0 },
86
+ headers: { Authorization: options.auth ? `Bearer ${options.auth}` : void 0 },
81
87
  url: `https://gitlab.com/${parsed.repo}/tree/${parsed.ref}${parsed.subdir}`,
82
88
  tar: `https://gitlab.com/${parsed.repo}/-/archive/${parsed.ref}.tar.gz`
83
89
  };
84
90
  };
85
- const bitbucket = (input, opts) => {
91
+ const bitbucket = (input, options) => {
86
92
  const parsed = parseGitURI(input);
87
93
  return {
88
94
  name: parsed.repo.replace("/", "-"),
89
95
  version: parsed.ref,
90
96
  subdir: parsed.subdir,
91
- headers: { Authorization: opts.auth ? `Bearer ${opts.auth}` : void 0 },
97
+ headers: { Authorization: options.auth ? `Bearer ${options.auth}` : void 0 },
92
98
  url: `https://bitbucket.com/${parsed.repo}/src/${parsed.ref}${parsed.subdir}`,
93
99
  tar: `https://bitbucket.org/${parsed.repo}/get/${parsed.ref}.tar.gz`
94
100
  };
95
101
  };
96
- const sourcehut = (input, opts) => {
102
+ const sourcehut = (input, options) => {
97
103
  const parsed = parseGitURI(input);
98
104
  return {
99
105
  name: parsed.repo.replace("/", "-"),
100
106
  version: parsed.ref,
101
107
  subdir: parsed.subdir,
102
- headers: { Authorization: opts.auth ? `Bearer ${opts.auth}` : void 0 },
108
+ headers: { Authorization: options.auth ? `Bearer ${options.auth}` : void 0 },
103
109
  url: `https://git.sr.ht/~${parsed.repo}/tree/${parsed.ref}/item${parsed.subdir}`,
104
110
  tar: `https://git.sr.ht/~${parsed.repo}/archive/${parsed.ref}.tar.gz`
105
111
  };
@@ -117,11 +123,11 @@ const registryProvider = (registryEndpoint = DEFAULT_REGISTRY) => {
117
123
  return async (input) => {
118
124
  const start = Date.now();
119
125
  const registryURL = `${registryEndpoint}/${input}.json`;
120
- const res = await fetch$1(registryURL);
121
- if (res.status >= 400) {
122
- throw new Error(`Failed to download ${input} template info from ${registryURL}: ${res.status} ${res.statusText}`);
126
+ const result = await sendFetch(registryURL);
127
+ if (result.status >= 400) {
128
+ throw new Error(`Failed to download ${input} template info from ${registryURL}: ${result.status} ${result.statusText}`);
123
129
  }
124
- const info = await res.json();
130
+ const info = await result.json();
125
131
  if (!info.tar || !info.name) {
126
132
  throw new Error(`Invalid template info from ${registryURL}. name or tar fields are missing!`);
127
133
  }
@@ -131,56 +137,56 @@ const registryProvider = (registryEndpoint = DEFAULT_REGISTRY) => {
131
137
  };
132
138
 
133
139
  const sourceProtoRe = /^([\w-.]+):/;
134
- async function downloadTemplate(input, opts = {}) {
135
- opts = defu({
140
+ async function downloadTemplate(input, options = {}) {
141
+ options = defu({
136
142
  registry: process.env.GIGET_REGISTRY,
137
143
  auth: process.env.GIGET_AUTH
138
- }, opts);
139
- const registry = opts.registry !== false ? registryProvider(opts.registry) : null;
140
- let providerName = opts.provider || (registryProvider ? "registry" : "github");
144
+ }, options);
145
+ const registry = options.registry !== false ? registryProvider(options.registry) : void 0;
146
+ let providerName = options.provider || (registryProvider ? "registry" : "github");
141
147
  let source = input;
142
148
  const sourceProvierMatch = input.match(sourceProtoRe);
143
149
  if (sourceProvierMatch) {
144
150
  providerName = sourceProvierMatch[1];
145
- source = input.substring(sourceProvierMatch[0].length);
151
+ source = input.slice(sourceProvierMatch[0].length);
146
152
  }
147
- const provider = opts.providers?.[providerName] || providers[providerName] || registry;
153
+ const provider = options.providers?.[providerName] || providers[providerName] || registry;
148
154
  if (!provider) {
149
155
  throw new Error(`Unsupported provider: ${providerName}`);
150
156
  }
151
- const template = await Promise.resolve().then(() => provider(source, { auth: opts.auth })).catch((err) => {
152
- throw new Error(`Failed to download template from ${providerName}: ${err.message}`);
157
+ const template = await Promise.resolve().then(() => provider(source, { auth: options.auth })).catch((error) => {
158
+ throw new Error(`Failed to download template from ${providerName}: ${error.message}`);
153
159
  });
154
- template.name = (template.name || "template").replace(/[^a-z0-9-]/gi, "-");
155
- template.defaultDir = (template.defaultDir || template.name).replace(/[^a-z0-9-]/gi, "-");
156
- const cwd = resolve(opts.cwd || ".");
157
- const extractPath = resolve(cwd, opts.dir || template.defaultDir);
158
- if (opts.forceClean) {
160
+ template.name = (template.name || "template").replace(/[^\da-z-]/gi, "-");
161
+ template.defaultDir = (template.defaultDir || template.name).replace(/[^\da-z-]/gi, "-");
162
+ const cwd = resolve(options.cwd || ".");
163
+ const extractPath = resolve(cwd, options.dir || template.defaultDir);
164
+ if (options.forceClean) {
159
165
  await rm(extractPath, { recursive: true, force: true });
160
166
  }
161
- if (!opts.force && existsSync(extractPath) && readdirSync(extractPath).length) {
167
+ if (!options.force && existsSync(extractPath) && readdirSync(extractPath).length > 0) {
162
168
  throw new Error(`Destination ${extractPath} already exists.`);
163
169
  }
164
170
  await mkdir(extractPath, { recursive: true });
165
- const tmpDir = resolve(homedir(), ".giget", opts.provider, template.name);
166
- const tarPath = resolve(tmpDir, (template.version || template.name) + ".tar.gz");
167
- if (opts.preferOffline && existsSync(tarPath)) {
168
- opts.offline = true;
171
+ const temporaryDirectory = resolve(homedir(), ".giget", options.provider, template.name);
172
+ const tarPath = resolve(temporaryDirectory, (template.version || template.name) + ".tar.gz");
173
+ if (options.preferOffline && existsSync(tarPath)) {
174
+ options.offline = true;
169
175
  }
170
- if (!opts.offline) {
176
+ if (!options.offline) {
171
177
  await mkdir(dirname(tarPath), { recursive: true });
172
178
  const s2 = Date.now();
173
- await download(template.tar, tarPath, { headers: template.headers }).catch((err) => {
179
+ await download(template.tar, tarPath, { headers: template.headers }).catch((error) => {
174
180
  if (!existsSync(tarPath)) {
175
- throw err;
181
+ throw error;
176
182
  }
177
- debug("Download error. Using cached version:", err);
178
- opts.offline = true;
183
+ debug("Download error. Using cached version:", error);
184
+ options.offline = true;
179
185
  });
180
186
  debug(`Downloaded ${template.tar} to ${tarPath} in ${Date.now() - s2}ms`);
181
187
  }
182
188
  if (!existsSync(tarPath)) {
183
- throw new Error(`Tarball not found: ${tarPath} (offline: ${opts.offline})`);
189
+ throw new Error(`Tarball not found: ${tarPath} (offline: ${options.offline})`);
184
190
  }
185
191
  const s = Date.now();
186
192
  const subdir = template.subdir?.replace(/^\//, "") || "";
@@ -191,7 +197,7 @@ async function downloadTemplate(input, opts = {}) {
191
197
  entry.path = entry.path.split("/").splice(1).join("/");
192
198
  if (subdir) {
193
199
  if (entry.path.startsWith(subdir + "/")) {
194
- entry.path = entry.path.substring(subdir.length);
200
+ entry.path = entry.path.slice(subdir.length);
195
201
  } else {
196
202
  entry.path = "";
197
203
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "giget",
3
- "version": "0.1.7",
3
+ "version": "1.0.0",
4
4
  "description": "Download templates and git repositories with pleasure!",
5
5
  "repository": "unjs/giget",
6
6
  "license": "MIT",
@@ -12,6 +12,7 @@
12
12
  "exports": {
13
13
  ".": {
14
14
  "import": "./dist/index.mjs",
15
+ "types": "./dist/index.d.ts",
15
16
  "require": "./dist/index.cjs"
16
17
  }
17
18
  },
@@ -21,34 +22,36 @@
21
22
  "files": [
22
23
  "dist"
23
24
  ],
24
- "dependencies": {
25
- "colorette": "^2.0.19",
26
- "defu": "^6.1.0",
27
- "mri": "^1.2.0",
28
- "node-fetch-native": "^0.1.4",
29
- "pathe": "^0.3.8",
30
- "tar": "^6.1.11"
31
- },
32
- "devDependencies": {
33
- "@nuxtjs/eslint-config-typescript": "^11.0.0",
34
- "@types/node": "^18.7.16",
35
- "@types/tar": "^6.1.2",
36
- "@vitest/coverage-c8": "^0.23.4",
37
- "eslint": "^8.23.1",
38
- "jiti": "^1.16.0",
39
- "standard-version": "^9.5.0",
40
- "typescript": "^4.8.3",
41
- "unbuild": "^0.8.11",
42
- "vitest": "^0.23.4"
43
- },
44
- "packageManager": "pnpm@7.12.0",
45
25
  "scripts": {
46
26
  "build": "unbuild",
47
27
  "dev": "vitest dev",
48
28
  "giget": "jiti ./src/cli.ts",
49
29
  "lint": "eslint --ext .ts,.js,.mjs,.cjs .",
30
+ "prepack": "unbuild",
50
31
  "play": "pnpm giget --force-clean --verbose unjs .tmp/clone",
51
32
  "release": "pnpm test && standard-version && git push --follow-tags && pnpm publish",
52
33
  "test": "pnpm lint && vitest run --coverage"
53
- }
54
- }
34
+ },
35
+ "dependencies": {
36
+ "colorette": "^2.0.19",
37
+ "defu": "^6.1.1",
38
+ "https-proxy-agent": "^5.0.1",
39
+ "mri": "^1.2.0",
40
+ "node-fetch-native": "^1.0.1",
41
+ "pathe": "^1.0.0",
42
+ "tar": "^6.1.12"
43
+ },
44
+ "devDependencies": {
45
+ "@types/node": "^18.11.9",
46
+ "@types/tar": "^6.1.3",
47
+ "@vitest/coverage-c8": "^0.25.2",
48
+ "eslint": "^8.27.0",
49
+ "eslint-config-unjs": "^0.0.2",
50
+ "jiti": "^1.16.0",
51
+ "standard-version": "^9.5.0",
52
+ "typescript": "^4.8.4",
53
+ "unbuild": "^0.9.4",
54
+ "vitest": "^0.25.2"
55
+ },
56
+ "packageManager": "pnpm@7.16.0"
57
+ }