giget 1.2.2 → 1.2.4

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 CHANGED
@@ -178,7 +178,7 @@ const rainbow: TemplateProvider = async (input, { auth }) => {
178
178
  };
179
179
  };
180
180
 
181
- const { source, dir } = await downloadRepo("rainbow:one", {
181
+ const { source, dir } = await downloadTemplate("rainbow:one", {
182
182
  providers: { rainbow },
183
183
  });
184
184
  ```
@@ -194,7 +194,7 @@ const themes = registryProvider(
194
194
  "https://raw.githubusercontent.com/unjs/giget/main/templates",
195
195
  );
196
196
 
197
- const { source, dir } = await downloadRepo("themes:test", {
197
+ const { source, dir } = await downloadTemplate("themes:test", {
198
198
  providers: { themes },
199
199
  });
200
200
  ```
@@ -205,6 +205,18 @@ For private repositories and sources, you might need a token. In order to provid
205
205
 
206
206
  **Note:** For github private repository access with Fine-grained access tokens, you need to give **Contents** and **Metadata** repository permissions.
207
207
 
208
+ ### GitHub Actions
209
+
210
+ If your project depends on a private GitHub repository, you need to add the access token as a secret. Please see GitHub Actions docs on [creating secrets for a repository](https://docs.github.com/en/actions/security-for-github-actions/security-guides/using-secrets-in-github-actions#creating-secrets-for-a-repository). In your workflow, refer to the token as shown in the example below:
211
+
212
+ ```yml
213
+ - name: Install packages
214
+ run: npm ci
215
+ env:
216
+ GIGET_AUTH: ${{ secrets.GIGET_AUTH }}
217
+ ```
218
+
219
+
208
220
  ## Related projects
209
221
 
210
222
  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.
package/dist/cli.cjs CHANGED
@@ -4,7 +4,7 @@
4
4
  const node_path = require('node:path');
5
5
  const citty = require('citty');
6
6
  const consola = require('consola');
7
- const index = require('./index.cjs');
7
+ const giget = require('./shared/giget.ooq4UIqH.cjs');
8
8
  require('node:fs/promises');
9
9
  require('node:fs');
10
10
  require('tar');
@@ -18,7 +18,7 @@ require('node:util');
18
18
  require('node-fetch-native/proxy');
19
19
 
20
20
  const name = "giget";
21
- const version = "1.2.2";
21
+ const version = "1.2.4";
22
22
  const description = "Download templates and git repositories with pleasure!";
23
23
  const repository = "unjs/giget";
24
24
  const license = "MIT";
@@ -49,8 +49,8 @@ const scripts = {
49
49
  build: "unbuild",
50
50
  dev: "vitest dev",
51
51
  giget: "jiti ./src/cli.ts",
52
- lint: "eslint --ext .ts,.js,.mjs,.cjs . && prettier -c src test",
53
- "lint:fix": "eslint --ext .ts,.js,.mjs,.cjs . --fix && prettier -w src test",
52
+ lint: "eslint . && prettier -c src test",
53
+ "lint:fix": "eslint . --fix && prettier -w src test",
54
54
  prepack: "unbuild",
55
55
  play: "pnpm giget --force-clean --verbose unjs .tmp/clone",
56
56
  release: "pnpm test && changelogen --release && npm publish && git push --follow-tags",
@@ -58,28 +58,28 @@ const scripts = {
58
58
  };
59
59
  const dependencies = {
60
60
  citty: "^0.1.6",
61
- consola: "^3.2.3",
61
+ consola: "^3.4.0",
62
62
  defu: "^6.1.4",
63
- "node-fetch-native": "^1.6.3",
64
- nypm: "^0.3.8",
65
- ohash: "^1.1.3",
66
- pathe: "^1.1.2",
67
- tar: "^6.2.0"
63
+ "node-fetch-native": "^1.6.6",
64
+ nypm: "^0.5.1",
65
+ ohash: "^1.1.4",
66
+ pathe: "^2.0.2",
67
+ tar: "^6.2.1"
68
68
  };
69
69
  const devDependencies = {
70
- "@types/node": "^20.11.30",
71
- "@types/tar": "^6.1.11",
72
- "@vitest/coverage-v8": "^1.4.0",
73
- changelogen: "^0.5.5",
74
- eslint: "^8.57.0",
75
- "eslint-config-unjs": "^0.2.1",
76
- jiti: "^1.21.0",
77
- prettier: "^3.2.5",
78
- typescript: "^5.4.3",
79
- unbuild: "^2.0.0",
80
- vitest: "^1.4.0"
70
+ "@types/node": "^22.10.10",
71
+ "@types/tar": "^6.1.13",
72
+ "@vitest/coverage-v8": "^3.0.4",
73
+ changelogen: "^0.5.7",
74
+ eslint: "^9.19.0",
75
+ "eslint-config-unjs": "^0.4.2",
76
+ jiti: "^2.4.2",
77
+ prettier: "^3.4.2",
78
+ typescript: "^5.7.3",
79
+ unbuild: "^3.3.1",
80
+ vitest: "^3.0.4"
81
81
  };
82
- const packageManager = "pnpm@8.15.5";
82
+ const packageManager = "pnpm@9.15.4";
83
83
  const pkg = {
84
84
  name: name,
85
85
  version: version,
@@ -158,7 +158,7 @@ const mainCommand = citty.defineCommand({
158
158
  if (args.verbose) {
159
159
  process.env.DEBUG = process.env.DEBUG || "true";
160
160
  }
161
- const r = await index.downloadTemplate(args.template, {
161
+ const r = await giget.downloadTemplate(args.template, {
162
162
  dir: args.dir,
163
163
  force: args.force,
164
164
  forceClean: args.forceClean,
@@ -172,7 +172,7 @@ const mainCommand = citty.defineCommand({
172
172
  consola.consola.log(`\u2728 Successfully cloned \`${_from}\` to \`${_to}\`
173
173
  `);
174
174
  if (args.shell) {
175
- index.startShell(r.dir);
175
+ giget.startShell(r.dir);
176
176
  }
177
177
  }
178
178
  });
package/dist/cli.d.cts CHANGED
@@ -1,2 +1 @@
1
1
 
2
- export { }
package/dist/cli.d.mts CHANGED
@@ -1,2 +1 @@
1
1
 
2
- export { }
package/dist/cli.d.ts CHANGED
@@ -1,2 +1 @@
1
1
 
2
- export { }
package/dist/cli.mjs CHANGED
@@ -2,7 +2,7 @@
2
2
  import { relative } from 'node:path';
3
3
  import { defineCommand, runMain } from 'citty';
4
4
  import { consola } from 'consola';
5
- import { downloadTemplate, startShell } from './index.mjs';
5
+ import { d as downloadTemplate, s as startShell } from './shared/giget.D-_6aM9e.mjs';
6
6
  import 'node:fs/promises';
7
7
  import 'node:fs';
8
8
  import 'tar';
@@ -16,7 +16,7 @@ import 'node:util';
16
16
  import 'node-fetch-native/proxy';
17
17
 
18
18
  const name = "giget";
19
- const version = "1.2.2";
19
+ const version = "1.2.4";
20
20
  const description = "Download templates and git repositories with pleasure!";
21
21
  const repository = "unjs/giget";
22
22
  const license = "MIT";
@@ -47,8 +47,8 @@ const scripts = {
47
47
  build: "unbuild",
48
48
  dev: "vitest dev",
49
49
  giget: "jiti ./src/cli.ts",
50
- lint: "eslint --ext .ts,.js,.mjs,.cjs . && prettier -c src test",
51
- "lint:fix": "eslint --ext .ts,.js,.mjs,.cjs . --fix && prettier -w src test",
50
+ lint: "eslint . && prettier -c src test",
51
+ "lint:fix": "eslint . --fix && prettier -w src test",
52
52
  prepack: "unbuild",
53
53
  play: "pnpm giget --force-clean --verbose unjs .tmp/clone",
54
54
  release: "pnpm test && changelogen --release && npm publish && git push --follow-tags",
@@ -56,28 +56,28 @@ const scripts = {
56
56
  };
57
57
  const dependencies = {
58
58
  citty: "^0.1.6",
59
- consola: "^3.2.3",
59
+ consola: "^3.4.0",
60
60
  defu: "^6.1.4",
61
- "node-fetch-native": "^1.6.3",
62
- nypm: "^0.3.8",
63
- ohash: "^1.1.3",
64
- pathe: "^1.1.2",
65
- tar: "^6.2.0"
61
+ "node-fetch-native": "^1.6.6",
62
+ nypm: "^0.5.1",
63
+ ohash: "^1.1.4",
64
+ pathe: "^2.0.2",
65
+ tar: "^6.2.1"
66
66
  };
67
67
  const devDependencies = {
68
- "@types/node": "^20.11.30",
69
- "@types/tar": "^6.1.11",
70
- "@vitest/coverage-v8": "^1.4.0",
71
- changelogen: "^0.5.5",
72
- eslint: "^8.57.0",
73
- "eslint-config-unjs": "^0.2.1",
74
- jiti: "^1.21.0",
75
- prettier: "^3.2.5",
76
- typescript: "^5.4.3",
77
- unbuild: "^2.0.0",
78
- vitest: "^1.4.0"
68
+ "@types/node": "^22.10.10",
69
+ "@types/tar": "^6.1.13",
70
+ "@vitest/coverage-v8": "^3.0.4",
71
+ changelogen: "^0.5.7",
72
+ eslint: "^9.19.0",
73
+ "eslint-config-unjs": "^0.4.2",
74
+ jiti: "^2.4.2",
75
+ prettier: "^3.4.2",
76
+ typescript: "^5.7.3",
77
+ unbuild: "^3.3.1",
78
+ vitest: "^3.0.4"
79
79
  };
80
- const packageManager = "pnpm@8.15.5";
80
+ const packageManager = "pnpm@9.15.4";
81
81
  const pkg = {
82
82
  name: name,
83
83
  version: version,
package/dist/index.cjs CHANGED
@@ -1,365 +1,20 @@
1
1
  'use strict';
2
2
 
3
- const promises = require('node:fs/promises');
4
- const node_fs = require('node:fs');
5
- const tar = require('tar');
6
- const pathe = require('pathe');
7
- const defu = require('defu');
8
- const nypm = require('nypm');
9
- const node_stream = require('node:stream');
10
- const node_child_process = require('node:child_process');
11
- const node_os = require('node:os');
12
- const node_util = require('node:util');
13
- const proxy = require('node-fetch-native/proxy');
3
+ const giget = require('./shared/giget.ooq4UIqH.cjs');
4
+ require('node:fs/promises');
5
+ require('node:fs');
6
+ require('tar');
7
+ require('pathe');
8
+ require('defu');
9
+ require('nypm');
10
+ require('node:stream');
11
+ require('node:child_process');
12
+ require('node:os');
13
+ require('node:util');
14
+ require('node-fetch-native/proxy');
14
15
 
15
- async function download(url, filePath, options = {}) {
16
- const infoPath = filePath + ".json";
17
- const info = JSON.parse(
18
- await promises.readFile(infoPath, "utf8").catch(() => "{}")
19
- );
20
- const headResponse = await sendFetch(url, {
21
- method: "HEAD",
22
- headers: options.headers
23
- }).catch(() => void 0);
24
- const etag = headResponse?.headers.get("etag");
25
- if (info.etag === etag && node_fs.existsSync(filePath)) {
26
- return;
27
- }
28
- if (typeof etag === "string") {
29
- info.etag = etag;
30
- }
31
- const response = await sendFetch(url, { headers: options.headers });
32
- if (response.status >= 400) {
33
- throw new Error(
34
- `Failed to download ${url}: ${response.status} ${response.statusText}`
35
- );
36
- }
37
- const stream = node_fs.createWriteStream(filePath);
38
- await node_util.promisify(node_stream.pipeline)(response.body, stream);
39
- await promises.writeFile(infoPath, JSON.stringify(info), "utf8");
40
- }
41
- const inputRegex = /^(?<repo>[\w.-]+\/[\w.-]+)(?<subdir>[^#]+)?(?<ref>#[\w./-]+)?/;
42
- function parseGitURI(input) {
43
- const m = input.match(inputRegex)?.groups || {};
44
- return {
45
- repo: m.repo,
46
- subdir: m.subdir || "/",
47
- ref: m.ref ? m.ref.slice(1) : "main"
48
- };
49
- }
50
- function debug(...args) {
51
- if (process.env.DEBUG) {
52
- console.debug("[giget]", ...args);
53
- }
54
- }
55
- async function sendFetch(url, options = {}) {
56
- if (options.headers?.["sec-fetch-mode"]) {
57
- options.mode = options.headers["sec-fetch-mode"];
58
- }
59
- const res = await proxy.fetch(url, {
60
- ...options,
61
- headers: normalizeHeaders(options.headers)
62
- }).catch((error) => {
63
- throw new Error(`Failed to download ${url}: ${error}`, { cause: error });
64
- });
65
- if (options.validateStatus && res.status >= 400) {
66
- throw new Error(`Failed to fetch ${url}: ${res.status} ${res.statusText}`);
67
- }
68
- return res;
69
- }
70
- function cacheDirectory() {
71
- return process.env.XDG_CACHE_HOME ? pathe.resolve(process.env.XDG_CACHE_HOME, "giget") : pathe.resolve(node_os.homedir(), ".cache/giget");
72
- }
73
- function normalizeHeaders(headers = {}) {
74
- const normalized = {};
75
- for (const [key, value] of Object.entries(headers)) {
76
- if (!value) {
77
- continue;
78
- }
79
- normalized[key.toLowerCase()] = value;
80
- }
81
- return normalized;
82
- }
83
- function currentShell() {
84
- if (process.env.SHELL) {
85
- return process.env.SHELL;
86
- }
87
- if (process.platform === "win32") {
88
- return "cmd.exe";
89
- }
90
- return "/bin/bash";
91
- }
92
- function startShell(cwd) {
93
- cwd = pathe.resolve(cwd);
94
- const shell = currentShell();
95
- console.info(
96
- `(experimental) Opening shell in ${pathe.relative(process.cwd(), cwd)}...`
97
- );
98
- node_child_process.spawnSync(shell, [], {
99
- cwd,
100
- shell: true,
101
- stdio: "inherit"
102
- });
103
- }
104
16
 
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
- };
156
- const github = (input, options) => {
157
- const parsed = parseGitURI(input);
158
- const githubAPIURL = process.env.GIGET_GITHUB_URL || "https://api.github.com";
159
- return {
160
- name: parsed.repo.replace("/", "-"),
161
- version: parsed.ref,
162
- subdir: parsed.subdir,
163
- headers: {
164
- Authorization: options.auth ? `Bearer ${options.auth}` : void 0,
165
- Accept: "application/vnd.github+json",
166
- "X-GitHub-Api-Version": "2022-11-28"
167
- },
168
- url: `${githubAPIURL.replace("api.github.com", "github.com")}/${parsed.repo}/tree/${parsed.ref}${parsed.subdir}`,
169
- tar: `${githubAPIURL}/repos/${parsed.repo}/tarball/${parsed.ref}`
170
- };
171
- };
172
- const gitlab = (input, options) => {
173
- const parsed = parseGitURI(input);
174
- const gitlab2 = process.env.GIGET_GITLAB_URL || "https://gitlab.com";
175
- return {
176
- name: parsed.repo.replace("/", "-"),
177
- version: parsed.ref,
178
- subdir: parsed.subdir,
179
- headers: {
180
- authorization: options.auth ? `Bearer ${options.auth}` : void 0,
181
- // https://gitlab.com/gitlab-org/gitlab/-/commit/50c11f278d18fe1f3fb12eb595067216bb58ade2
182
- "sec-fetch-mode": "same-origin"
183
- },
184
- url: `${gitlab2}/${parsed.repo}/tree/${parsed.ref}${parsed.subdir}`,
185
- tar: `${gitlab2}/${parsed.repo}/-/archive/${parsed.ref}.tar.gz`
186
- };
187
- };
188
- const bitbucket = (input, options) => {
189
- const parsed = parseGitURI(input);
190
- return {
191
- name: parsed.repo.replace("/", "-"),
192
- version: parsed.ref,
193
- subdir: parsed.subdir,
194
- headers: {
195
- authorization: options.auth ? `Bearer ${options.auth}` : void 0
196
- },
197
- url: `https://bitbucket.com/${parsed.repo}/src/${parsed.ref}${parsed.subdir}`,
198
- tar: `https://bitbucket.org/${parsed.repo}/get/${parsed.ref}.tar.gz`
199
- };
200
- };
201
- const sourcehut = (input, options) => {
202
- const parsed = parseGitURI(input);
203
- return {
204
- name: parsed.repo.replace("/", "-"),
205
- version: parsed.ref,
206
- subdir: parsed.subdir,
207
- headers: {
208
- authorization: options.auth ? `Bearer ${options.auth}` : void 0
209
- },
210
- url: `https://git.sr.ht/~${parsed.repo}/tree/${parsed.ref}/item${parsed.subdir}`,
211
- tar: `https://git.sr.ht/~${parsed.repo}/archive/${parsed.ref}.tar.gz`
212
- };
213
- };
214
- const providers = {
215
- http,
216
- https: http,
217
- github,
218
- gh: github,
219
- gitlab,
220
- bitbucket,
221
- sourcehut
222
- };
223
17
 
224
- const DEFAULT_REGISTRY = "https://raw.githubusercontent.com/unjs/giget/main/templates";
225
- const registryProvider = (registryEndpoint = DEFAULT_REGISTRY, options = {}) => {
226
- return async (input) => {
227
- const start = Date.now();
228
- const registryURL = `${registryEndpoint}/${input}.json`;
229
- const result = await sendFetch(registryURL, {
230
- headers: {
231
- authorization: options.auth ? `Bearer ${options.auth}` : void 0
232
- }
233
- });
234
- if (result.status >= 400) {
235
- throw new Error(
236
- `Failed to download ${input} template info from ${registryURL}: ${result.status} ${result.statusText}`
237
- );
238
- }
239
- const info = await result.json();
240
- if (!info.tar || !info.name) {
241
- throw new Error(
242
- `Invalid template info from ${registryURL}. name or tar fields are missing!`
243
- );
244
- }
245
- debug(
246
- `Fetched ${input} template info from ${registryURL} in ${Date.now() - start}ms`
247
- );
248
- return info;
249
- };
250
- };
251
-
252
- const sourceProtoRe = /^([\w-.]+):/;
253
- async function downloadTemplate(input, options = {}) {
254
- options = defu.defu(
255
- {
256
- registry: process.env.GIGET_REGISTRY,
257
- auth: process.env.GIGET_AUTH
258
- },
259
- options
260
- );
261
- const registry = options.registry === false ? void 0 : registryProvider(options.registry, { auth: options.auth });
262
- let providerName = options.provider || (registry ? "registry" : "github");
263
- let source = input;
264
- const sourceProvierMatch = input.match(sourceProtoRe);
265
- if (sourceProvierMatch) {
266
- providerName = sourceProvierMatch[1];
267
- source = input.slice(sourceProvierMatch[0].length);
268
- if (providerName === "http" || providerName === "https") {
269
- source = input;
270
- }
271
- }
272
- const provider = options.providers?.[providerName] || providers[providerName] || registry;
273
- if (!provider) {
274
- throw new Error(`Unsupported provider: ${providerName}`);
275
- }
276
- const template = await Promise.resolve().then(() => provider(source, { auth: options.auth })).catch((error) => {
277
- throw new Error(
278
- `Failed to download template from ${providerName}: ${error.message}`
279
- );
280
- });
281
- if (!template) {
282
- throw new Error(`Failed to resolve template from ${providerName}`);
283
- }
284
- template.name = (template.name || "template").replace(/[^\da-z-]/gi, "-");
285
- template.defaultDir = (template.defaultDir || template.name).replace(
286
- /[^\da-z-]/gi,
287
- "-"
288
- );
289
- const temporaryDirectory = pathe.resolve(
290
- cacheDirectory(),
291
- providerName,
292
- template.name
293
- );
294
- const tarPath = pathe.resolve(
295
- temporaryDirectory,
296
- (template.version || template.name) + ".tar.gz"
297
- );
298
- if (options.preferOffline && node_fs.existsSync(tarPath)) {
299
- options.offline = true;
300
- }
301
- if (!options.offline) {
302
- await promises.mkdir(pathe.dirname(tarPath), { recursive: true });
303
- const s2 = Date.now();
304
- await download(template.tar, tarPath, {
305
- headers: {
306
- Authorization: options.auth ? `Bearer ${options.auth}` : void 0,
307
- ...normalizeHeaders(template.headers)
308
- }
309
- }).catch((error) => {
310
- if (!node_fs.existsSync(tarPath)) {
311
- throw error;
312
- }
313
- debug("Download error. Using cached version:", error);
314
- options.offline = true;
315
- });
316
- debug(`Downloaded ${template.tar} to ${tarPath} in ${Date.now() - s2}ms`);
317
- }
318
- if (!node_fs.existsSync(tarPath)) {
319
- throw new Error(
320
- `Tarball not found: ${tarPath} (offline: ${options.offline})`
321
- );
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 });
332
- const s = Date.now();
333
- const subdir = template.subdir?.replace(/^\//, "") || "";
334
- await tar.extract({
335
- file: tarPath,
336
- cwd: extractPath,
337
- onentry(entry) {
338
- entry.path = entry.path.split("/").splice(1).join("/");
339
- if (subdir) {
340
- if (entry.path.startsWith(subdir + "/")) {
341
- entry.path = entry.path.slice(subdir.length);
342
- } else {
343
- entry.path = "";
344
- }
345
- }
346
- }
347
- });
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
- }
356
- return {
357
- ...template,
358
- source,
359
- dir: extractPath
360
- };
361
- }
362
-
363
- exports.downloadTemplate = downloadTemplate;
364
- exports.registryProvider = registryProvider;
365
- exports.startShell = startShell;
18
+ exports.downloadTemplate = giget.downloadTemplate;
19
+ exports.registryProvider = giget.registryProvider;
20
+ exports.startShell = giget.startShell;