Init: RoggioApp Architecture, Prisma Schema, API MVP
This commit is contained in:
+184
@@ -0,0 +1,184 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) Pooya Parsa <pooya@pi0.io>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
---
|
||||
|
||||
Third party bundled dependencies
|
||||
|
||||
- https://github.com/isaacs/node-tar
|
||||
- https://github.com/isaacs/fs-minipass
|
||||
|
||||
"""
|
||||
The ISC License
|
||||
|
||||
Copyright (c) Isaac Z. Schlueter and Contributors
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
|
||||
IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
""""
|
||||
|
||||
- https://github.com/isaacs/minipass
|
||||
|
||||
"""
|
||||
The ISC License
|
||||
|
||||
Copyright (c) 2017-2023 npm, Inc., Isaac Z. Schlueter, and Contributors
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
|
||||
IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
"""
|
||||
|
||||
- https://github.com/isaacs/minizlib
|
||||
|
||||
"""
|
||||
Minizlib was created by Isaac Z. Schlueter.
|
||||
It is a derivative work of the Node.js project.
|
||||
|
||||
"""
|
||||
Copyright (c) 2017-2023 Isaac Z. Schlueter and Contributors
|
||||
Copyright (c) 2017-2023 Node.js contributors. All rights reserved.
|
||||
Copyright (c) 2017-2023 Joyent, Inc. and other Node contributors. All rights reserved.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
to deal in the Software without restriction, including without limitation
|
||||
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
and/or sell copies of the Software, and to permit persons to whom the
|
||||
Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
"""
|
||||
|
||||
- https://github.com/isaacs/node-mkdirp
|
||||
|
||||
"""
|
||||
Copyright (c) 2011-2023 James Halliday (mail@substack.net) and Isaac Z. Schlueter (i@izs.me)
|
||||
|
||||
This project is free software released under the MIT license:
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
"""
|
||||
|
||||
- https://github.com/isaacs/yallist/blob/main/LICENSE.md
|
||||
- https://github.com/isaacs/chownr/blob/main/LICENSE.md
|
||||
|
||||
"""
|
||||
|
||||
# Blue Oak Model License
|
||||
|
||||
Version 1.0.0
|
||||
|
||||
## Purpose
|
||||
|
||||
This license gives everyone as much permission to work with
|
||||
this software as possible, while protecting contributors
|
||||
from liability.
|
||||
|
||||
## Acceptance
|
||||
|
||||
In order to receive this license, you must agree to its
|
||||
rules. The rules of this license are both obligations
|
||||
under that agreement and conditions to your license.
|
||||
You must not do anything with this software that triggers
|
||||
a rule that you cannot or will not follow.
|
||||
|
||||
## Copyright
|
||||
|
||||
Each contributor licenses you to do everything with this
|
||||
software that would otherwise infringe that contributor's
|
||||
copyright in it.
|
||||
|
||||
## Notices
|
||||
|
||||
You must ensure that everyone who gets a copy of
|
||||
any part of this software from you, with or without
|
||||
changes, also gets the text of this license or a link to
|
||||
<https://blueoakcouncil.org/license/1.0.0>.
|
||||
|
||||
## Excuse
|
||||
|
||||
If anyone notifies you in writing that you have not
|
||||
complied with [Notices](#notices), you can keep your
|
||||
license by taking all practical steps to comply within 30
|
||||
days after the notice. If you do not do so, your license
|
||||
ends immediately.
|
||||
|
||||
## Patent
|
||||
|
||||
Each contributor licenses you to do everything with this
|
||||
software that would otherwise infringe any patent claims
|
||||
they can license or become able to license.
|
||||
|
||||
## Reliability
|
||||
|
||||
No contributor can revoke this license.
|
||||
|
||||
## No Liability
|
||||
|
||||
**_As far as the law allows, this software comes as is,
|
||||
without any warranty or condition, and no contributor
|
||||
will be liable to anyone for any damages related to this
|
||||
software or this license, under any kind of legal claim._**
|
||||
"""
|
||||
+296
@@ -0,0 +1,296 @@
|
||||
# giget
|
||||
|
||||
[![npm version][npm-version-src]][npm-version-href]
|
||||
[![npm downloads][npm-downloads-src]][npm-downloads-href]
|
||||
[![Codecov][codecov-src]][codecov-href]
|
||||
|
||||
> Download templates and git repositories with pleasure!
|
||||
|
||||
## Features
|
||||
|
||||
✨ Zero dependency
|
||||
|
||||
✨ Support popular git providers (GitHub, GitLab, Bitbucket, Sourcehut) out of the box.
|
||||
|
||||
✨ Native [git clone provider](#git-clone-provider) with sparse checkout for subdirectories.
|
||||
|
||||
✨ Built-in and custom [template registry](#template-registry).
|
||||
|
||||
✨ Fast cloning using tarball gzip without depending on local `git` and `tar`.
|
||||
|
||||
✨ Works online and offline with disk cache support.
|
||||
|
||||
✨ Custom template provider support with programmatic usage.
|
||||
|
||||
✨ Support extracting with a sub dir.
|
||||
|
||||
✨ Authorization support to download private templates
|
||||
|
||||
✨ Optionally install dependencies after clone using [unjs/nypm](https://github.com/unjs/nypm)
|
||||
|
||||
## Usage (CLI)
|
||||
|
||||
```bash
|
||||
npx giget@latest <template> [<dir>] [...options]
|
||||
```
|
||||
|
||||
### Arguments
|
||||
|
||||
- **template**: Template name or a URI describing provider, repository, sub dir, and branch/ref. (See [Examples](#examples))
|
||||
- **dir**: A relative or absolute path where to extract the template.
|
||||
|
||||
### Options
|
||||
|
||||
- `--force`: Clone to existing directory even if exists.
|
||||
- `--offline`: Do not attempt to download and use the cached version.
|
||||
- `--prefer-offline`: Use cache if exists otherwise try to download.
|
||||
- `--force-clean`: ⚠️ Remove any existing directory or file recursively before cloning.
|
||||
- `--shell`: ⚠️ Open a new shell with the current working directory in cloned dir. (Experimental).
|
||||
- `--registry`: URL to a custom registry. (Can be overridden with `GIGET_REGISTRY` environment variable).
|
||||
- `--no-registry`: Disable registry lookup and functionality.
|
||||
- `--verbose`: Show verbose debugging info.
|
||||
- `--cwd`: Set the current working directory to resolve dirs relative to it.
|
||||
- `--auth`: Custom Authorization token to use for downloading template. (Can be overridden with `GIGET_AUTH` environment variable).
|
||||
- `--install`: Install dependencies after cloning using [unjs/nypm](https://github.com/unjs/nypm).
|
||||
|
||||
### Examples
|
||||
|
||||
```sh
|
||||
# Clone nuxt starter from giget template registry
|
||||
npx giget@latest nuxt
|
||||
|
||||
# Clone the main branch of github.com/unjs/template to unjs-template directory
|
||||
npx giget@latest gh:unjs/template
|
||||
|
||||
# Clone to myProject directory
|
||||
npx giget@latest gh:unjs/template myProject
|
||||
|
||||
# Clone dev branch
|
||||
npx giget@latest gh:unjs/template#dev
|
||||
|
||||
# Clone /test directory from main branch
|
||||
npx giget@latest gh:unjs/template/test
|
||||
|
||||
# Clone from gitlab
|
||||
npx giget@latest gitlab:unjs/template
|
||||
|
||||
# Clone from gitlab with subgroups
|
||||
npx giget@latest gitlab:group/subgroup/project
|
||||
|
||||
# Clone from gitlab with subgroups and subdirectory (using :: delimiter)
|
||||
npx giget@latest gitlab:group/subgroup/project::src/template
|
||||
|
||||
# Clone from bitbucket
|
||||
npx giget@latest bitbucket:unjs/template
|
||||
|
||||
# Clone from sourcehut
|
||||
npx giget@latest sourcehut:pi0/unjs-template
|
||||
|
||||
# Clone using local git over HTTPS (see "Git Clone Provider" section)
|
||||
npx giget@latest git:unjs/template
|
||||
|
||||
# Clone from https URL (tarball)
|
||||
npx giget@latest https://api.github.com/repos/unjs/template/tarball/main
|
||||
|
||||
# Clone from https URL (JSON)
|
||||
npx giget@latest https://raw.githubusercontent.com/unjs/giget/main/templates/unjs.json
|
||||
```
|
||||
|
||||
## Template Registry
|
||||
|
||||
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/).
|
||||
|
||||
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.
|
||||
|
||||
### Custom Registry
|
||||
|
||||
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).
|
||||
|
||||
- `name`: (required) Name of the template.
|
||||
- `tar` (required) Link to the tar download link.
|
||||
- `defaultDir`: (optional) Default cloning directory.
|
||||
- `url`: (optional) Webpage of the template.
|
||||
- `subdir`: (optional) Directory inside the tar file.
|
||||
- `headers`: (optional) Custom headers to send while downloading template.
|
||||
|
||||
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.
|
||||
|
||||
## Usage (Programmatic)
|
||||
|
||||
Install package:
|
||||
|
||||
```sh
|
||||
# npm
|
||||
npm install giget
|
||||
|
||||
# yarn
|
||||
yarn install giget
|
||||
|
||||
# pnpm
|
||||
pnpm install giget
|
||||
```
|
||||
|
||||
Import:
|
||||
|
||||
```js
|
||||
// ESM
|
||||
import { downloadTemplate } from "giget";
|
||||
|
||||
// CommonJS
|
||||
const { downloadTemplate } = require("giget");
|
||||
```
|
||||
|
||||
### `downloadTemplate(source, options?)`
|
||||
|
||||
**Example:**
|
||||
|
||||
```js
|
||||
const { source, dir } = await downloadTemplate("github:unjs/template");
|
||||
```
|
||||
|
||||
**Options:**
|
||||
|
||||
- `source`: (string) Input source in format of `[provider]:repo[/subpath][#ref]`. Use `::` to separate repo from subdir when the repo path has more than two segments (e.g., GitLab subgroups): `[provider]:group/subgroup/repo[::subdir][#ref]`.
|
||||
- `options`: (object) Options are usually inferred from the input string. You can customize them.
|
||||
- `dir`: (string) Destination directory to clone to. If not provided, `user-name` will be used relative to the current directory.
|
||||
- `provider`: (string) Either `github`, `gitlab`, `bitbucket`, `sourcehut`, or `git`. The default is `github`.
|
||||
- `force`: (boolean) Extract to the existing dir even if already exists.
|
||||
- `forceClean`: (boolean) ⚠️ Clean up any existing directory or file before cloning.
|
||||
- `offline`: (boolean) Do not attempt to download and use the cached version.
|
||||
- `preferOffline`: (boolean) Use cache if exists otherwise try to download.
|
||||
- `providers`: (object) A map from provider name to custom providers. Can be used to override built-ins too.
|
||||
- `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).
|
||||
- `cwd`: (string) Current working directory to resolve dirs relative to it.
|
||||
- `auth`: (string) Custom Authorization token to use for downloading template. (Can be overridden with `GIGET_AUTH` environment variable).
|
||||
|
||||
**Return value:**
|
||||
|
||||
The return value is a promise that resolves to the resolved template.
|
||||
|
||||
- `dir`: (string) Path to extracted dir.
|
||||
- `source`: (string) Normalized version of the input source without provider.
|
||||
- [other provider template keys]
|
||||
- `url`: (string) URL of the repository that can be opened in the browser. Useful for logging.
|
||||
|
||||
## Custom Providers
|
||||
|
||||
Using the programmatic method, you can make your custom template providers.
|
||||
|
||||
```ts
|
||||
import type { TemplateProvider } from "giget";
|
||||
|
||||
const rainbow: TemplateProvider = async (input, { auth }) => {
|
||||
return {
|
||||
name: "rainbow",
|
||||
version: input,
|
||||
headers: { authorization: auth },
|
||||
url: `https://rainbow.template/?variant=${input}`,
|
||||
tar: `https://rainbow.template/dl/rainbow.${input}.tar.gz`,
|
||||
};
|
||||
};
|
||||
|
||||
const { source, dir } = await downloadTemplate("rainbow:one", {
|
||||
providers: { rainbow },
|
||||
});
|
||||
```
|
||||
|
||||
`tar` can also be a function returning a `Readable` or `ReadableStream`:
|
||||
|
||||
```ts
|
||||
const myorg: TemplateProvider = async (input, { auth }) => {
|
||||
return {
|
||||
name: input,
|
||||
tar: async () =>
|
||||
(await fetch(`http://my-org.internal/archive/${input}.tar.gz`)).body!,
|
||||
};
|
||||
};
|
||||
|
||||
const { source, dir } = await downloadTemplate("myorg:my-project", {
|
||||
providers: { myorg },
|
||||
});
|
||||
```
|
||||
|
||||
### Custom Registry Providers
|
||||
|
||||
You can define additional [custom registry](#custom-registry) providers using `registryProvider` utility and register to `providers`.
|
||||
|
||||
```ts
|
||||
import { registryProvider } from "giget";
|
||||
|
||||
const themes = registryProvider("https://raw.githubusercontent.com/unjs/giget/main/templates");
|
||||
|
||||
const { source, dir } = await downloadTemplate("themes:test", {
|
||||
providers: { themes },
|
||||
});
|
||||
```
|
||||
|
||||
## Git Clone Provider
|
||||
|
||||
The `git:` provider clones repositories using the local `git` command instead of downloading tarballs via HTTP APIs. Useful for private or self-hosted servers that don't expose tarball endpoints.
|
||||
|
||||
```sh
|
||||
git:unjs/template # HTTPS clone (github.com by default)
|
||||
git:unjs/template#v2 # Specific branch or tag
|
||||
git:unjs/template#e24616c # Specific commit (full clone fallback)
|
||||
git:unjs/template#main:src # Subdirectory (sparse checkout)
|
||||
git:git@github.com:unjs/template # Explicit SSH
|
||||
git:./path/to/local/repo # Local repository
|
||||
gh+git:unjs/template # Host shorthand (github.com)
|
||||
gitlab+git:org/repo # Host shorthand (gitlab.com)
|
||||
```
|
||||
|
||||
Subdirectories use sparse checkout with `--filter=blob:none` to avoid downloading the full repository.
|
||||
|
||||
**Environment variables:**
|
||||
|
||||
| Variable | Description |
|
||||
| --- | --- |
|
||||
| `GIGET_GIT_HOST` | Default HTTPS host (default: `https://github.com/`) |
|
||||
|
||||
## Providing token for private repositories
|
||||
|
||||
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.
|
||||
|
||||
**Note:** For github private repository access with Fine-grained access tokens, you need to give **Contents** and **Metadata** repository permissions.
|
||||
|
||||
### GitHub Actions
|
||||
|
||||
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:
|
||||
|
||||
```yml
|
||||
- name: Install packages
|
||||
run: npm ci
|
||||
env:
|
||||
GIGET_AUTH: ${{ secrets.GIGET_AUTH }}
|
||||
```
|
||||
|
||||
## Related projects
|
||||
|
||||
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.
|
||||
|
||||
- [tiged/tiged](https://github.com/tiged/tiged) (maintained fork of degit)
|
||||
- [nrjdalal/gitpick](https://github.com/nrjdalal/gitpick) (alternative approach)
|
||||
- [Rich-Harris/degit](https://github.com/Rich-Harris/degit) (last updated - 2021)
|
||||
- [samsonjs/gitter](https://github.com/samsonjs/gitter) (archived/updated - 2012)
|
||||
|
||||
## 💻 Development
|
||||
|
||||
- Clone this repository
|
||||
- Enable [Corepack](https://github.com/nodejs/corepack) using `corepack enable` (use `npm i -g corepack` for Node.js < 16.10)
|
||||
- Install dependencies using `pnpm install`
|
||||
- Run interactive tests using `pnpm dev`
|
||||
|
||||
## License
|
||||
|
||||
Made with 💛
|
||||
|
||||
Published under [MIT License](./LICENSE).
|
||||
|
||||
<!-- Badges -->
|
||||
|
||||
[npm-version-src]: https://img.shields.io/npm/v/giget?style=flat&colorA=18181B&colorB=F0DB4F
|
||||
[npm-version-href]: https://npmjs.com/package/giget
|
||||
[npm-downloads-src]: https://img.shields.io/npm/dm/giget?style=flat&colorA=18181B&colorB=F0DB4F
|
||||
[npm-downloads-href]: https://npmjs.com/package/giget
|
||||
[codecov-src]: https://img.shields.io/codecov/c/gh/unjs/giget/main?style=flat&colorA=18181B&colorB=F0DB4F
|
||||
[codecov-href]: https://codecov.io/gh/unjs/giget
|
||||
+205
@@ -0,0 +1,205 @@
|
||||
# Licenses of Bundled Dependencies
|
||||
|
||||
The published artifact additionally contains code with the following licenses:
|
||||
BlueOak-1.0.0, MIT
|
||||
|
||||
# Bundled Dependencies
|
||||
|
||||
## citty, nypm
|
||||
|
||||
License: MIT
|
||||
Repositories: https://github.com/unjs/citty, https://github.com/unjs/nypm
|
||||
|
||||
> MIT License
|
||||
>
|
||||
> Copyright (c) Pooya Parsa <pooya@pi0.io>
|
||||
>
|
||||
> Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
> of this software and associated documentation files (the "Software"), to deal
|
||||
> in the Software without restriction, including without limitation the rights
|
||||
> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
> copies of the Software, and to permit persons to whom the Software is
|
||||
> furnished to do so, subject to the following conditions:
|
||||
>
|
||||
> The above copyright notice and this permission notice shall be included in all
|
||||
> copies or substantial portions of the Software.
|
||||
>
|
||||
> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
> SOFTWARE.
|
||||
|
||||
---------------------------------------
|
||||
|
||||
## pathe
|
||||
|
||||
License: MIT
|
||||
Repository: https://github.com/unjs/pathe
|
||||
|
||||
> MIT License
|
||||
>
|
||||
> Copyright (c) Pooya Parsa <pooya@pi0.io> - Daniel Roe <daniel@roe.dev>
|
||||
>
|
||||
> Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
> of this software and associated documentation files (the "Software"), to deal
|
||||
> in the Software without restriction, including without limitation the rights
|
||||
> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
> copies of the Software, and to permit persons to whom the Software is
|
||||
> furnished to do so, subject to the following conditions:
|
||||
>
|
||||
> The above copyright notice and this permission notice shall be included in all
|
||||
> copies or substantial portions of the Software.
|
||||
>
|
||||
> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
> SOFTWARE.
|
||||
>
|
||||
> ---
|
||||
>
|
||||
> Copyright Joyent, Inc. and other Node contributors.
|
||||
>
|
||||
> Permission is hereby granted, free of charge, to any person obtaining a
|
||||
> copy of this software and associated documentation files (the
|
||||
> "Software"), to deal in the Software without restriction, including
|
||||
> without limitation the rights to use, copy, modify, merge, publish,
|
||||
> distribute, sublicense, and/or sell copies of the Software, and to permit
|
||||
> persons to whom the Software is furnished to do so, subject to the
|
||||
> following conditions:
|
||||
>
|
||||
> The above copyright notice and this permission notice shall be included
|
||||
> in all copies or substantial portions of the Software.
|
||||
>
|
||||
> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
> OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
> MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
||||
> NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
> DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
> OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||
> USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
>
|
||||
> ---
|
||||
>
|
||||
> Bundled zeptomatch (https://github.com/fabiospampinato/zeptomatch)
|
||||
>
|
||||
> The MIT License (MIT)
|
||||
>
|
||||
> Copyright (c) 2023-present Fabio Spampinato
|
||||
>
|
||||
> Permission is hereby granted, free of charge, to any person obtaining a
|
||||
> copy of this software and associated documentation files (the "Software"),
|
||||
> to deal in the Software without restriction, including without limitation
|
||||
> the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
> and/or sell copies of the Software, and to permit persons to whom the
|
||||
> Software is furnished to do so, subject to the following conditions:
|
||||
>
|
||||
> The above copyright notice and this permission notice shall be included in
|
||||
> all copies or substantial portions of the Software.
|
||||
>
|
||||
> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
> FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
> DEALINGS IN THE SOFTWARE.
|
||||
|
||||
---------------------------------------
|
||||
|
||||
## tar
|
||||
|
||||
License: BlueOak-1.0.0
|
||||
By: Isaac Z. Schlueter
|
||||
Repository: https://github.com/isaacs/node-tar
|
||||
|
||||
> # Blue Oak Model License
|
||||
>
|
||||
> Version 1.0.0
|
||||
>
|
||||
> ## Purpose
|
||||
>
|
||||
> This license gives everyone as much permission to work with
|
||||
> this software as possible, while protecting contributors
|
||||
> from liability.
|
||||
>
|
||||
> ## Acceptance
|
||||
>
|
||||
> In order to receive this license, you must agree to its
|
||||
> rules. The rules of this license are both obligations
|
||||
> under that agreement and conditions to your license.
|
||||
> You must not do anything with this software that triggers
|
||||
> a rule that you cannot or will not follow.
|
||||
>
|
||||
> ## Copyright
|
||||
>
|
||||
> Each contributor licenses you to do everything with this
|
||||
> software that would otherwise infringe that contributor's
|
||||
> copyright in it.
|
||||
>
|
||||
> ## Notices
|
||||
>
|
||||
> You must ensure that everyone who gets a copy of
|
||||
> any part of this software from you, with or without
|
||||
> changes, also gets the text of this license or a link to
|
||||
> <https://blueoakcouncil.org/license/1.0.0>.
|
||||
>
|
||||
> ## Excuse
|
||||
>
|
||||
> If anyone notifies you in writing that you have not
|
||||
> complied with [Notices](#notices), you can keep your
|
||||
> license by taking all practical steps to comply within 30
|
||||
> days after the notice. If you do not do so, your license
|
||||
> ends immediately.
|
||||
>
|
||||
> ## Patent
|
||||
>
|
||||
> Each contributor licenses you to do everything with this
|
||||
> software that would otherwise infringe any patent claims
|
||||
> they can license or become able to license.
|
||||
>
|
||||
> ## Reliability
|
||||
>
|
||||
> No contributor can revoke this license.
|
||||
>
|
||||
> ## No Liability
|
||||
>
|
||||
> ***As far as the law allows, this software comes as is,
|
||||
> without any warranty or condition, and no contributor
|
||||
> will be liable to anyone for any damages related to this
|
||||
> software or this license, under any kind of legal claim.***
|
||||
|
||||
---------------------------------------
|
||||
|
||||
## tinyexec
|
||||
|
||||
License: MIT
|
||||
By: James Garbutt
|
||||
Repository: https://github.com/tinylibs/tinyexec
|
||||
|
||||
> MIT License
|
||||
>
|
||||
> Copyright (c) 2024 Tinylibs
|
||||
>
|
||||
> Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
> of this software and associated documentation files (the "Software"), to deal
|
||||
> in the Software without restriction, including without limitation the rights
|
||||
> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
> copies of the Software, and to permit persons to whom the Software is
|
||||
> furnished to do so, subject to the following conditions:
|
||||
>
|
||||
> The above copyright notice and this permission notice shall be included in all
|
||||
> copies or substantial portions of the Software.
|
||||
>
|
||||
> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
> SOFTWARE.
|
||||
+508
@@ -0,0 +1,508 @@
|
||||
import { a as resolve$1, i as relative, n as basename$1, r as dirname$1 } from "./libs/nypm.mjs";
|
||||
import { createWriteStream, existsSync, readdirSync, renameSync } from "node:fs";
|
||||
import { mkdir, mkdtemp, readFile, rm, writeFile } from "node:fs/promises";
|
||||
import { PassThrough, Readable, pipeline } from "node:stream";
|
||||
import { pipeline as pipeline$1 } from "node:stream/promises";
|
||||
import { spawn, spawnSync } from "node:child_process";
|
||||
import { homedir, tmpdir } from "node:os";
|
||||
import { promisify } from "node:util";
|
||||
import { join } from "node:path";
|
||||
//#region src/_utils.ts
|
||||
async function download(url, filePath, options = {}) {
|
||||
const infoPath = filePath + ".json";
|
||||
const info = JSON.parse(await readFile(infoPath, "utf8").catch(() => "{}"));
|
||||
const etag = (await sendFetch(url, {
|
||||
method: "HEAD",
|
||||
headers: options.headers
|
||||
}).catch(() => void 0))?.headers.get("etag");
|
||||
if (info.etag === etag && existsSync(filePath)) return;
|
||||
if (typeof etag === "string") info.etag = etag;
|
||||
const response = await sendFetch(url, { headers: options.headers });
|
||||
if (response.status >= 400) throw new Error(`Failed to download ${url}: ${response.status} ${response.statusText}`);
|
||||
const stream = createWriteStream(filePath);
|
||||
await promisify(pipeline)(response.body, stream);
|
||||
await writeFile(infoPath, JSON.stringify(info), "utf8");
|
||||
}
|
||||
const inputRegex = /^(?<repo>[-\w.]+\/[-\w.]+)(?<subdir>[^#]+)?(?<ref>#[-\w./@]+)?/;
|
||||
const expandedInputRegex = /^(?<repo>[-\w.]+(?:\/[-\w.]+)+?)(?:::(?<subdir>[^#]*))?(?<ref>#[-\w./@]+)?$/;
|
||||
function parseGitURI(input, options) {
|
||||
const useExpanded = options?.expandRepo || input.includes("::");
|
||||
const m = input.match(useExpanded ? expandedInputRegex : inputRegex)?.groups || {};
|
||||
const subdir = useExpanded ? m.subdir ? "/" + m.subdir : "/" : m.subdir || "/";
|
||||
return {
|
||||
repo: m.repo || "",
|
||||
subdir,
|
||||
ref: m.ref ? m.ref.slice(1) : "main"
|
||||
};
|
||||
}
|
||||
function debug(...args) {
|
||||
if (process.env.DEBUG) console.debug("[giget]", ...args);
|
||||
}
|
||||
async function sendFetch(url, options = {}) {
|
||||
if (options.headers?.["sec-fetch-mode"]) options.mode = options.headers["sec-fetch-mode"];
|
||||
const res = await fetch(url, {
|
||||
...options,
|
||||
headers: normalizeHeaders(options.headers)
|
||||
}).catch((error) => {
|
||||
throw new Error(`Failed to download ${url}: ${error}`, { cause: error });
|
||||
});
|
||||
if (options.validateStatus && res.status >= 400) throw new Error(`Failed to fetch ${url}: ${res.status} ${res.statusText}`);
|
||||
return res;
|
||||
}
|
||||
function cacheDirectory() {
|
||||
const cacheDir = process.env.XDG_CACHE_HOME ? resolve$1(process.env.XDG_CACHE_HOME, "giget") : resolve$1(homedir(), ".cache/giget");
|
||||
if (process.platform === "win32") {
|
||||
const windowsCacheDir = resolve$1(tmpdir(), "giget");
|
||||
if (!existsSync(windowsCacheDir) && existsSync(cacheDir)) try {
|
||||
renameSync(cacheDir, windowsCacheDir);
|
||||
} catch {}
|
||||
return windowsCacheDir;
|
||||
}
|
||||
return cacheDir;
|
||||
}
|
||||
function normalizeHeaders(headers = {}) {
|
||||
const normalized = {};
|
||||
for (const [key, value] of Object.entries(headers)) {
|
||||
if (!value) continue;
|
||||
normalized[key.toLowerCase()] = value;
|
||||
}
|
||||
return normalized;
|
||||
}
|
||||
function currentShell() {
|
||||
if (process.env.SHELL) return process.env.SHELL;
|
||||
if (process.platform === "win32") return "cmd.exe";
|
||||
return "/bin/bash";
|
||||
}
|
||||
function startShell(cwd) {
|
||||
cwd = resolve$1(cwd);
|
||||
const shell = currentShell();
|
||||
console.info(`(experimental) Opening shell in ${relative(process.cwd(), cwd)}...`);
|
||||
spawnSync(shell, [], {
|
||||
cwd,
|
||||
shell: true,
|
||||
stdio: "inherit"
|
||||
});
|
||||
}
|
||||
//#endregion
|
||||
//#region src/git.ts
|
||||
const git = (input, options) => {
|
||||
const parsed = parseGitCloneURI(input);
|
||||
return {
|
||||
name: parsed.name,
|
||||
version: parsed.subdir ? `${parsed.version || "default"}-${parsed.subdir.replaceAll("/", "-")}` : parsed.version,
|
||||
tar: ({ auth } = {}) => _cloneAndTar(parsed, auth ?? options.auth)
|
||||
};
|
||||
};
|
||||
function parseGitCloneURI(input, opts = {}) {
|
||||
const cwd = opts.cwd ?? process.cwd();
|
||||
let uri = input.replace(/#.*$/, "");
|
||||
let pathSubdir;
|
||||
if (/^[./]/.test(input)) uri = resolve$1(cwd, uri);
|
||||
else if (/^https?:\/\//.test(uri)) {
|
||||
const httpMatch = /^(https?:\/\/[^/]+)\/([\w.-]+\/[\w.-]+?)(?:\.git)?(?:\/(.+))?$/.exec(uri);
|
||||
if (httpMatch) {
|
||||
const [, origin, repo, rest] = httpMatch;
|
||||
uri = `${origin}/${repo}`;
|
||||
if (rest) pathSubdir = rest;
|
||||
}
|
||||
} else if (uri.includes("@")) {
|
||||
const sshMatch = /^(.*?:[\w.-]+\/[\w.-]+?)(?:\.git)?(?:\/(.+))?$/.exec(uri);
|
||||
if (sshMatch) {
|
||||
const [, repoUri, rest] = sshMatch;
|
||||
uri = repoUri;
|
||||
if (rest) pathSubdir = rest;
|
||||
}
|
||||
} else {
|
||||
const hostMap = {
|
||||
"github:": "https://github.com/",
|
||||
"gh:": "https://github.com/",
|
||||
"gitlab:": "https://gitlab.com/",
|
||||
"bitbucket:": "https://bitbucket.org/",
|
||||
"sourcehut:": "https://git.sr.ht/~"
|
||||
};
|
||||
const host = /^(.+?:)/.exec(uri)?.at(1);
|
||||
if (host && hostMap[host]) uri = uri.replace(host, hostMap[host]);
|
||||
else if (!host) uri = `${(process.env.GIGET_GIT_HOST || "https://github.com/").replace(/\/$/, "")}/${uri}`;
|
||||
const httpMatch = /^(https?:\/\/[^/]+\/~?[\w.-]+\/[\w.-]+?)(?:\.git)?(?:\/(.+))?$/.exec(uri);
|
||||
if (httpMatch) {
|
||||
const [, repoUri, rest] = httpMatch;
|
||||
uri = repoUri;
|
||||
if (rest) pathSubdir = rest;
|
||||
}
|
||||
}
|
||||
const name = uri.replace(/^https?:\/\//, "").replace(/^.+@/, "").replace(/(\.git)?(#.*)?$/, "").replace(/^\W+/, "").replaceAll(/[:/]/g, "-");
|
||||
const [version, hashSubdir] = /#(.+)$/.exec(input)?.at(1)?.split(":") ?? [];
|
||||
const resolvedVersion = version || void 0;
|
||||
const subdir = hashSubdir || pathSubdir;
|
||||
return {
|
||||
uri,
|
||||
name,
|
||||
...resolvedVersion && { version: resolvedVersion },
|
||||
...subdir && { subdir }
|
||||
};
|
||||
}
|
||||
async function _cloneAndTar(parsed, token) {
|
||||
const tmpDir = await mkdtemp(join(tmpdir(), "giget-git-"));
|
||||
if (token && /[\r\n]/.test(token)) throw new Error("Auth token must not contain newline characters");
|
||||
const execEnv = {
|
||||
...process.env,
|
||||
GIT_TERMINAL_PROMPT: "0"
|
||||
};
|
||||
if (token) {
|
||||
execEnv.GIT_CONFIG_COUNT = "1";
|
||||
execEnv.GIT_CONFIG_KEY_0 = "http.extraHeader";
|
||||
execEnv.GIT_CONFIG_VALUE_0 = `Authorization: Bearer ${token}`;
|
||||
}
|
||||
const execOpts = {
|
||||
env: execEnv,
|
||||
timeout: 6e4
|
||||
};
|
||||
const status = _createStatus();
|
||||
const gitExec = (args) => _gitSpawn(args, execOpts, status);
|
||||
const gitExecIn = (args) => _gitSpawn(args, {
|
||||
...execOpts,
|
||||
cwd: tmpDir
|
||||
}, status);
|
||||
try {
|
||||
const cloneArgs = [
|
||||
"clone",
|
||||
"--progress",
|
||||
"--depth",
|
||||
"1"
|
||||
];
|
||||
if (parsed.subdir) cloneArgs.push("--filter=blob:none", "--sparse", "--no-checkout");
|
||||
if (parsed.version) cloneArgs.push("--branch", parsed.version);
|
||||
cloneArgs.push("--", parsed.uri, tmpDir);
|
||||
try {
|
||||
status.update("Cloning...");
|
||||
await gitExec(cloneArgs);
|
||||
status.update("Cloned.");
|
||||
} catch (cloneError) {
|
||||
if (!parsed.version) throw cloneError;
|
||||
debug("Shallow clone failed, falling back to full clone:", cloneError);
|
||||
status.update("Shallow clone failed, cloning...");
|
||||
await rm(tmpDir, {
|
||||
recursive: true,
|
||||
force: true
|
||||
});
|
||||
await mkdir(tmpDir, { recursive: true });
|
||||
await gitExecIn(["init"]);
|
||||
await gitExecIn([
|
||||
"remote",
|
||||
"add",
|
||||
"origin",
|
||||
parsed.uri
|
||||
]);
|
||||
await gitExecIn(["fetch", "origin"]);
|
||||
await gitExecIn(["checkout", parsed.version]);
|
||||
status.update("Fetched.");
|
||||
}
|
||||
if (parsed.subdir) {
|
||||
status.update(`Sparse checkout ${parsed.subdir}...`);
|
||||
await gitExecIn([
|
||||
"sparse-checkout",
|
||||
"set",
|
||||
parsed.subdir
|
||||
]);
|
||||
await gitExecIn(["checkout"]);
|
||||
}
|
||||
status.update("Packing...");
|
||||
const tarDir = parsed.subdir ? join(tmpDir, parsed.subdir) : tmpDir;
|
||||
const { create } = await import("./libs/tar.mjs").then((n) => n.t);
|
||||
status.done();
|
||||
const stream = create({
|
||||
gzip: true,
|
||||
cwd: tarDir,
|
||||
filter: (path) => !path.startsWith(".git/") && path !== ".git" && !path.startsWith("./.git/") && path !== "./.git"
|
||||
}, ["."]).pipe(new PassThrough());
|
||||
let cleaned = false;
|
||||
const cleanup = () => {
|
||||
if (cleaned) return;
|
||||
cleaned = true;
|
||||
rm(tmpDir, {
|
||||
recursive: true,
|
||||
force: true
|
||||
});
|
||||
};
|
||||
stream.on("end", cleanup);
|
||||
stream.on("error", cleanup);
|
||||
stream.on("close", cleanup);
|
||||
return stream;
|
||||
} catch (error) {
|
||||
status.done();
|
||||
await rm(tmpDir, {
|
||||
recursive: true,
|
||||
force: true
|
||||
});
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
const _spinnerFrames = [
|
||||
"⠋",
|
||||
"⠙",
|
||||
"⠹",
|
||||
"⠸",
|
||||
"⠼",
|
||||
"⠴",
|
||||
"⠦",
|
||||
"⠧",
|
||||
"⠇",
|
||||
"⠏"
|
||||
];
|
||||
function _gitSpawn(args, opts, status) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const proc = spawn("git", args, {
|
||||
...opts,
|
||||
stdio: [
|
||||
"ignore",
|
||||
"pipe",
|
||||
"pipe"
|
||||
]
|
||||
});
|
||||
proc.stdout.resume();
|
||||
let lastLine = "";
|
||||
proc.stderr?.on("data", (chunk) => {
|
||||
const str = chunk.toString();
|
||||
for (const line of str.split(/[\r\n]/)) {
|
||||
const clean = line.trim();
|
||||
if (clean) lastLine = clean;
|
||||
}
|
||||
if (status) status.update(lastLine);
|
||||
});
|
||||
proc.on("close", (code) => {
|
||||
if (code === 0) resolve(lastLine);
|
||||
else reject(/* @__PURE__ */ new Error(`git ${args[0]} exited with code ${code}. Is git installed?`));
|
||||
});
|
||||
proc.on("error", (err) => {
|
||||
if (err.code === "ENOENT") reject(/* @__PURE__ */ new Error("git is not installed or not found in PATH"));
|
||||
else reject(err);
|
||||
});
|
||||
});
|
||||
}
|
||||
function _createStatus() {
|
||||
if (!process.stderr.isTTY) return {
|
||||
update(_text) {},
|
||||
done() {}
|
||||
};
|
||||
let msg = "";
|
||||
let frame = 0;
|
||||
const render = () => {
|
||||
const spinner = _spinnerFrames[frame % _spinnerFrames.length];
|
||||
frame++;
|
||||
process.stderr.write(`\x1B[2K\r\x1B[2m${spinner} ${msg}\x1B[0m`);
|
||||
};
|
||||
const interval = setInterval(render, 80);
|
||||
return {
|
||||
update(text) {
|
||||
msg = text;
|
||||
render();
|
||||
},
|
||||
done() {
|
||||
clearInterval(interval);
|
||||
process.stderr.write("\x1B[2K\r");
|
||||
}
|
||||
};
|
||||
}
|
||||
//#endregion
|
||||
//#region src/providers.ts
|
||||
const http = async (input, options) => {
|
||||
if (input.endsWith(".json")) return await _httpJSON(input, options);
|
||||
const url = new URL(input);
|
||||
let name = basename$1(url.pathname);
|
||||
try {
|
||||
const head = await sendFetch(url.href, {
|
||||
method: "HEAD",
|
||||
validateStatus: true,
|
||||
headers: { authorization: options.auth ? `Bearer ${options.auth}` : void 0 }
|
||||
});
|
||||
if ((head.headers.get("content-type") || "").includes("application/json")) return await _httpJSON(input, options);
|
||||
const filename = head.headers.get("content-disposition")?.match(/filename="?(.+)"?/)?.[1];
|
||||
if (filename) name = filename.split(".")[0];
|
||||
} catch (error) {
|
||||
debug(`Failed to fetch HEAD for ${url.href}:`, error);
|
||||
}
|
||||
return {
|
||||
name: `${name}-${url.href.slice(0, 8)}`,
|
||||
version: "",
|
||||
subdir: "",
|
||||
tar: url.href,
|
||||
defaultDir: name,
|
||||
headers: { Authorization: options.auth ? `Bearer ${options.auth}` : void 0 }
|
||||
};
|
||||
};
|
||||
const _httpJSON = async (input, options) => {
|
||||
const info = await (await sendFetch(input, {
|
||||
validateStatus: true,
|
||||
headers: { authorization: options.auth ? `Bearer ${options.auth}` : void 0 }
|
||||
})).json();
|
||||
if (!info.tar || !info.name) throw new Error(`Invalid template info from ${input}. name or tar fields are missing!`);
|
||||
return info;
|
||||
};
|
||||
const github = (input, options) => {
|
||||
const parsed = parseGitURI(input);
|
||||
const githubAPIURL = process.env.GIGET_GITHUB_URL || "https://api.github.com";
|
||||
return {
|
||||
name: parsed.repo.replace("/", "-"),
|
||||
version: parsed.ref,
|
||||
subdir: parsed.subdir,
|
||||
headers: {
|
||||
Authorization: options.auth ? `Bearer ${options.auth}` : void 0,
|
||||
Accept: "application/vnd.github+json",
|
||||
"X-GitHub-Api-Version": "2022-11-28"
|
||||
},
|
||||
url: `${githubAPIURL.replace("api.github.com", "github.com")}/${parsed.repo}/tree/${parsed.ref}${parsed.subdir}`,
|
||||
tar: `${githubAPIURL}/repos/${parsed.repo}/tarball/${parsed.ref}`
|
||||
};
|
||||
};
|
||||
const gitlab = (input, options) => {
|
||||
const parsed = parseGitURI(input, { expandRepo: true });
|
||||
const gitlab = process.env.GIGET_GITLAB_URL || "https://gitlab.com";
|
||||
return {
|
||||
name: parsed.repo.replace("/", "-"),
|
||||
version: parsed.ref,
|
||||
subdir: parsed.subdir,
|
||||
headers: {
|
||||
authorization: options.auth ? `Bearer ${options.auth}` : void 0,
|
||||
"sec-fetch-mode": "same-origin"
|
||||
},
|
||||
url: `${gitlab}/${parsed.repo}/tree/${parsed.ref}${parsed.subdir}`,
|
||||
tar: `${gitlab}/${parsed.repo}/-/archive/${parsed.ref}.tar.gz`
|
||||
};
|
||||
};
|
||||
const bitbucket = (input, options) => {
|
||||
const parsed = parseGitURI(input);
|
||||
return {
|
||||
name: parsed.repo.replace("/", "-"),
|
||||
version: parsed.ref,
|
||||
subdir: parsed.subdir,
|
||||
headers: { authorization: options.auth ? `Bearer ${options.auth}` : void 0 },
|
||||
url: `https://bitbucket.com/${parsed.repo}/src/${parsed.ref}${parsed.subdir}`,
|
||||
tar: `https://bitbucket.org/${parsed.repo}/get/${parsed.ref}.tar.gz`
|
||||
};
|
||||
};
|
||||
const sourcehut = (input, options) => {
|
||||
const parsed = parseGitURI(input);
|
||||
return {
|
||||
name: parsed.repo.replace("/", "-"),
|
||||
version: parsed.ref,
|
||||
subdir: parsed.subdir,
|
||||
headers: { authorization: options.auth ? `Bearer ${options.auth}` : void 0 },
|
||||
url: `https://git.sr.ht/~${parsed.repo}/tree/${parsed.ref}/item${parsed.subdir}`,
|
||||
tar: `https://git.sr.ht/~${parsed.repo}/archive/${parsed.ref}.tar.gz`
|
||||
};
|
||||
};
|
||||
const providers = {
|
||||
http,
|
||||
https: http,
|
||||
git,
|
||||
github,
|
||||
gh: github,
|
||||
gitlab,
|
||||
bitbucket,
|
||||
sourcehut
|
||||
};
|
||||
//#endregion
|
||||
//#region src/registry.ts
|
||||
const DEFAULT_REGISTRY = "https://raw.githubusercontent.com/unjs/giget/main/templates";
|
||||
const registryProvider = (registryEndpoint = DEFAULT_REGISTRY, options = {}) => {
|
||||
return (async (input) => {
|
||||
const start = Date.now();
|
||||
const registryURL = `${registryEndpoint}/${input}.json`;
|
||||
const result = await sendFetch(registryURL, { headers: { authorization: options.auth ? `Bearer ${options.auth}` : void 0 } });
|
||||
if (result.status >= 400) throw new Error(`Failed to download ${input} template info from ${registryURL}: ${result.status} ${result.statusText}`);
|
||||
const info = await result.json();
|
||||
if (!info.tar || !info.name) throw new Error(`Invalid template info from ${registryURL}. name or tar fields are missing!`);
|
||||
debug(`Fetched ${input} template info from ${registryURL} in ${Date.now() - start}ms`);
|
||||
return info;
|
||||
});
|
||||
};
|
||||
//#endregion
|
||||
//#region src/giget.ts
|
||||
const sourceProtoRe = /^([\w+-.]+):/;
|
||||
async function downloadTemplate(input, options = {}) {
|
||||
options.registry = process.env.GIGET_REGISTRY ?? options.registry;
|
||||
options.auth = process.env.GIGET_AUTH ?? options.auth;
|
||||
const registry = options.registry === false ? void 0 : registryProvider(options.registry, { auth: options.auth });
|
||||
let providerName = options.provider || (registry ? "registry" : "github");
|
||||
let source = input;
|
||||
const sourceProviderMatch = input.match(sourceProtoRe);
|
||||
if (sourceProviderMatch) {
|
||||
providerName = sourceProviderMatch[1];
|
||||
source = input.slice(sourceProviderMatch[0].length);
|
||||
if (providerName === "http" || providerName === "https") source = input;
|
||||
}
|
||||
if (providerName.endsWith("+git")) {
|
||||
source = `${providerName.slice(0, -4)}:${source}`;
|
||||
providerName = "git";
|
||||
}
|
||||
const provider = options.providers?.[providerName] || providers[providerName] || registry;
|
||||
if (!provider) throw new Error(`Unsupported provider: ${providerName}`);
|
||||
const template = await Promise.resolve().then(() => provider(source, { auth: options.auth })).catch((error) => {
|
||||
throw new Error(`Failed to download template from ${providerName}: ${error.message}`);
|
||||
});
|
||||
if (!template) throw new Error(`Failed to resolve template from ${providerName}`);
|
||||
template.name = (template.name || "template").replace(/[^\da-z-]/gi, "-");
|
||||
template.defaultDir = (template.defaultDir || template.name).replace(/[^\da-z-]/gi, "-");
|
||||
const tarPath = resolve$1(resolve$1(cacheDirectory(), providerName, template.name), (template.version || template.name) + ".tar.gz");
|
||||
if (options.preferOffline && existsSync(tarPath)) options.offline = true;
|
||||
if (!options.offline) {
|
||||
await mkdir(dirname$1(tarPath), { recursive: true });
|
||||
const s = Date.now();
|
||||
if (typeof template.tar === "function") {
|
||||
const tarFn = template.tar;
|
||||
await (async () => {
|
||||
const stream = await tarFn({ auth: options.auth });
|
||||
await pipeline$1(stream instanceof Readable ? stream : Readable.fromWeb(stream), createWriteStream(tarPath));
|
||||
})().catch((error) => {
|
||||
if (!existsSync(tarPath)) throw error;
|
||||
debug("Download error. Using cached version:", error);
|
||||
options.offline = true;
|
||||
});
|
||||
} else await download(template.tar, tarPath, { headers: {
|
||||
Authorization: options.auth ? `Bearer ${options.auth}` : void 0,
|
||||
...normalizeHeaders(template.headers)
|
||||
} }).catch((error) => {
|
||||
if (!existsSync(tarPath)) throw error;
|
||||
debug("Download error. Using cached version:", error);
|
||||
options.offline = true;
|
||||
});
|
||||
debug(`Downloaded to ${tarPath} in ${Date.now() - s}ms`);
|
||||
}
|
||||
if (!existsSync(tarPath)) throw new Error(`Tarball not found: ${tarPath} (offline: ${options.offline})`);
|
||||
const extractPath = resolve$1(resolve$1(options.cwd || "."), options.dir || template.defaultDir);
|
||||
if (options.forceClean) await rm(extractPath, {
|
||||
recursive: true,
|
||||
force: true
|
||||
});
|
||||
if (!options.force && existsSync(extractPath) && readdirSync(extractPath).length > 0) throw new Error(`Destination ${extractPath} already exists.`);
|
||||
await mkdir(extractPath, { recursive: true });
|
||||
const s = Date.now();
|
||||
const subdir = template.subdir?.replace(/^\//, "") || "";
|
||||
const { extract } = await import("./libs/tar.mjs").then((n) => n.t);
|
||||
await extract({
|
||||
file: tarPath,
|
||||
cwd: extractPath,
|
||||
onReadEntry(entry) {
|
||||
entry.path = entry.path.split("/").splice(1).join("/");
|
||||
if (subdir) if (entry.path.startsWith(subdir + "/")) entry.path = entry.path.slice(subdir.length);
|
||||
else entry.path = "";
|
||||
}
|
||||
});
|
||||
debug(`Extracted to ${extractPath} in ${Date.now() - s}ms`);
|
||||
if (options.install) {
|
||||
debug("Installing dependencies...");
|
||||
const { installDependencies } = await import("./libs/nypm.mjs").then((n) => n.t);
|
||||
await installDependencies({
|
||||
cwd: extractPath,
|
||||
silent: options.silent,
|
||||
...typeof options.install === "object" ? options.install : {}
|
||||
});
|
||||
}
|
||||
return {
|
||||
...template,
|
||||
source,
|
||||
dir: extractPath
|
||||
};
|
||||
}
|
||||
//#endregion
|
||||
export { registryProvider as n, startShell as r, downloadTemplate as t };
|
||||
+269
@@ -0,0 +1,269 @@
|
||||
import { parseArgs as e } from "node:util";
|
||||
const t = /\d/, n = [
|
||||
`-`,
|
||||
`_`,
|
||||
`/`,
|
||||
`.`
|
||||
];
|
||||
function r(e = ``) {
|
||||
if (!t.test(e)) return e !== e.toLowerCase();
|
||||
}
|
||||
function i(e, t) {
|
||||
let i = t ?? n, a = [];
|
||||
if (!e || typeof e != `string`) return a;
|
||||
let o = ``, s, c;
|
||||
for (let t of e) {
|
||||
let e = i.includes(t);
|
||||
if (e === !0) {
|
||||
a.push(o), o = ``, s = void 0;
|
||||
continue;
|
||||
}
|
||||
let n = r(t);
|
||||
if (c === !1) {
|
||||
if (s === !1 && n === !0) {
|
||||
a.push(o), o = t, s = n;
|
||||
continue;
|
||||
}
|
||||
if (s === !0 && n === !1 && o.length > 1) {
|
||||
let e = o.at(-1);
|
||||
a.push(o.slice(0, Math.max(0, o.length - 1))), o = e + t, s = n;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
o += t, s = n, c = e;
|
||||
}
|
||||
return a.push(o), a;
|
||||
}
|
||||
function a(e) {
|
||||
return e ? e[0].toUpperCase() + e.slice(1) : ``;
|
||||
}
|
||||
function o(e) {
|
||||
return e ? e[0].toLowerCase() + e.slice(1) : ``;
|
||||
}
|
||||
function s(e, t) {
|
||||
return e ? (Array.isArray(e) ? e : i(e)).map((e) => a(t?.normalize ? e.toLowerCase() : e)).join(``) : ``;
|
||||
}
|
||||
function c(e, t) {
|
||||
return o(s(e || ``, t));
|
||||
}
|
||||
function l(e, t) {
|
||||
return e ? (Array.isArray(e) ? e : i(e)).map((e) => e.toLowerCase()).join(t ?? `-`) : ``;
|
||||
}
|
||||
function u(e) {
|
||||
return Array.isArray(e) ? e : e === void 0 ? [] : [e];
|
||||
}
|
||||
function d(e, t = ``) {
|
||||
let n = [];
|
||||
for (let t of e) for (let [e, r] of t.entries()) n[e] = Math.max(n[e] || 0, r.length);
|
||||
return e.map((e) => e.map((e, r) => t + e[r === 0 ? `padStart` : `padEnd`](n[r])).join(` `)).join(`
|
||||
`);
|
||||
}
|
||||
function f(e) {
|
||||
return typeof e == `function` ? e() : e;
|
||||
}
|
||||
var p = class extends Error {
|
||||
code;
|
||||
constructor(e, t) {
|
||||
super(e), this.name = `CLIError`, this.code = t;
|
||||
}
|
||||
};
|
||||
function m(t = [], n = {}) {
|
||||
let r = new Set(n.boolean || []), i = new Set(n.string || []), a = n.alias || {}, o = n.default || {}, s = /* @__PURE__ */ new Map(), c = /* @__PURE__ */ new Map();
|
||||
for (let [e, t] of Object.entries(a)) {
|
||||
let n = t;
|
||||
for (let t of n) s.set(e, t), c.has(t) || c.set(t, []), c.get(t).push(e), s.set(t, e), c.has(e) || c.set(e, []), c.get(e).push(t);
|
||||
}
|
||||
let l = {};
|
||||
function u(e) {
|
||||
if (r.has(e)) return `boolean`;
|
||||
let t = c.get(e) || [];
|
||||
for (let e of t) if (r.has(e)) return `boolean`;
|
||||
return `string`;
|
||||
}
|
||||
let d = new Set([
|
||||
...r,
|
||||
...i,
|
||||
...Object.keys(a),
|
||||
...Object.values(a).flat(),
|
||||
...Object.keys(o)
|
||||
]);
|
||||
for (let e of d) l[e] || (l[e] = {
|
||||
type: u(e),
|
||||
default: o[e]
|
||||
});
|
||||
for (let [e, t] of s.entries()) e.length === 1 && l[t] && !l[t].short && (l[t].short = e);
|
||||
let f = [], p = {};
|
||||
for (let e = 0; e < t.length; e++) {
|
||||
let n = t[e];
|
||||
if (n === `--`) {
|
||||
f.push(...t.slice(e));
|
||||
break;
|
||||
}
|
||||
if (n.startsWith(`--no-`)) {
|
||||
let e = n.slice(5);
|
||||
p[e] = !0;
|
||||
continue;
|
||||
}
|
||||
f.push(n);
|
||||
}
|
||||
let m;
|
||||
try {
|
||||
m = e({
|
||||
args: f,
|
||||
options: Object.keys(l).length > 0 ? l : void 0,
|
||||
allowPositionals: !0,
|
||||
strict: !1
|
||||
});
|
||||
} catch {
|
||||
m = {
|
||||
values: {},
|
||||
positionals: f
|
||||
};
|
||||
}
|
||||
let h = { _: [] };
|
||||
h._ = m.positionals;
|
||||
for (let [e, t] of Object.entries(m.values)) h[e] = t;
|
||||
for (let [e] of Object.entries(p)) {
|
||||
h[e] = !1;
|
||||
let t = s.get(e);
|
||||
t && (h[t] = !1);
|
||||
let n = c.get(e);
|
||||
if (n) for (let e of n) h[e] = !1;
|
||||
}
|
||||
for (let [e, t] of s.entries()) h[e] !== void 0 && h[t] === void 0 && (h[t] = h[e]), h[t] !== void 0 && h[e] === void 0 && (h[e] = h[t]);
|
||||
return h;
|
||||
}
|
||||
const h = (() => {
|
||||
let e = globalThis.process?.env ?? {};
|
||||
return e.NO_COLOR === `1` || e.TERM === `dumb` || e.TEST || e.CI;
|
||||
})(), g = (e, t = 39) => (n) => h ? n : `\u001B[${e}m${n}\u001B[${t}m`, _ = g(1, 22), v = g(36), y = g(90), b = g(4, 24);
|
||||
function x(e, t) {
|
||||
let n = {
|
||||
boolean: [],
|
||||
string: [],
|
||||
alias: {},
|
||||
default: {}
|
||||
}, r = S(t);
|
||||
for (let e of r) {
|
||||
if (e.type === `positional`) continue;
|
||||
e.type === `string` || e.type === `enum` ? n.string.push(e.name) : e.type === `boolean` && n.boolean.push(e.name), e.default !== void 0 && (n.default[e.name] = e.default), e.alias && (n.alias[e.name] = e.alias);
|
||||
let t = c(e.name), r = l(e.name);
|
||||
if (t !== e.name || r !== e.name) {
|
||||
let i = u(n.alias[e.name] || []);
|
||||
t !== e.name && !i.includes(t) && i.push(t), r !== e.name && !i.includes(r) && i.push(r), i.length > 0 && (n.alias[e.name] = i);
|
||||
}
|
||||
}
|
||||
let i = m(e, n), [ ...a] = i._, o = new Proxy(i, { get(e, t) {
|
||||
return e[t] ?? e[c(t)] ?? e[l(t)];
|
||||
} });
|
||||
for (let [, e] of r.entries()) if (e.type === `positional`) {
|
||||
let t = a.shift();
|
||||
if (t !== void 0) o[e.name] = t;
|
||||
else if (e.default === void 0 && e.required !== !1) throw new p(`Missing required positional argument: ${e.name.toUpperCase()}`, `EARG`);
|
||||
else o[e.name] = e.default;
|
||||
} else if (e.type === `enum`) {
|
||||
let t = o[e.name], n = e.options || [];
|
||||
if (t !== void 0 && n.length > 0 && !n.includes(t)) throw new p(`Invalid value for argument: ${v(`--${e.name}`)} (${v(t)}). Expected one of: ${n.map((e) => v(e)).join(`, `)}.`, `EARG`);
|
||||
} else if (e.required && o[e.name] === void 0) throw new p(`Missing required argument: --${e.name}`, `EARG`);
|
||||
return o;
|
||||
}
|
||||
function S(e) {
|
||||
let t = [];
|
||||
for (let [n, r] of Object.entries(e || {})) t.push({
|
||||
...r,
|
||||
name: n,
|
||||
alias: u(r.alias)
|
||||
});
|
||||
return t;
|
||||
}
|
||||
function C(e) {
|
||||
return e;
|
||||
}
|
||||
async function w(e, t) {
|
||||
let n = await f(e.args || {}), r = x(t.rawArgs, n), i = {
|
||||
rawArgs: t.rawArgs,
|
||||
args: r,
|
||||
data: t.data,
|
||||
cmd: e
|
||||
};
|
||||
typeof e.setup == `function` && await e.setup(i);
|
||||
let a;
|
||||
try {
|
||||
let n = await f(e.subCommands);
|
||||
if (n && Object.keys(n).length > 0) {
|
||||
let r = t.rawArgs.findIndex((e) => !e.startsWith(`-`)), i = t.rawArgs[r];
|
||||
if (i) {
|
||||
if (!n[i]) throw new p(`Unknown command ${v(i)}`, `E_UNKNOWN_COMMAND`);
|
||||
let e = await f(n[i]);
|
||||
e && await w(e, { rawArgs: t.rawArgs.slice(r + 1) });
|
||||
} else if (!e.run) throw new p(`No command specified.`, `E_NO_COMMAND`);
|
||||
}
|
||||
typeof e.run == `function` && (a = await e.run(i));
|
||||
} finally {
|
||||
typeof e.cleanup == `function` && await e.cleanup(i);
|
||||
}
|
||||
return { result: a };
|
||||
}
|
||||
async function T(e, t, n) {
|
||||
let r = await f(e.subCommands);
|
||||
if (r && Object.keys(r).length > 0) {
|
||||
let n = t.findIndex((e) => !e.startsWith(`-`)), i = t[n], a = await f(r[i]);
|
||||
if (a) return T(a, t.slice(n + 1), e);
|
||||
}
|
||||
return [e, n];
|
||||
}
|
||||
async function E(e, t) {
|
||||
try {
|
||||
console.log(await O(e, t) + `
|
||||
`);
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
}
|
||||
const D = /^no[-A-Z]/;
|
||||
async function O(e, t) {
|
||||
let n = await f(e.meta || {}), r = S(await f(e.args || {})), i = await f(t?.meta || {}), a = `${i.name ? `${i.name} ` : ``}` + (n.name || process.argv[1]), o = [], s = [], c = [], l = [];
|
||||
for (let e of r) if (e.type === `positional`) {
|
||||
let t = e.name.toUpperCase(), n = e.required !== !1 && e.default === void 0, r = e.default ? `="${e.default}"` : ``;
|
||||
s.push([
|
||||
v(t + r),
|
||||
e.description || ``,
|
||||
e.valueHint ? `<${e.valueHint}>` : ``
|
||||
]), l.push(n ? `<${t}>` : `[${t}]`);
|
||||
} else {
|
||||
let t = e.required === !0 && e.default === void 0, n = [...(e.alias || []).map((e) => `-${e}`), `--${e.name}`].join(`, `) + (e.type === `string` && (e.valueHint || e.default) ? `=${e.valueHint ? `<${e.valueHint}>` : `"${e.default || ``}"`}` : ``) + (e.type === `enum` && e.options ? `=<${e.options.join(`|`)}>` : ``);
|
||||
if (o.push([v(n + (t ? ` (required)` : ``)), e.description || ``]), e.type === `boolean` && (e.default === !0 || e.negativeDescription) && !D.test(e.name)) {
|
||||
let n = [...(e.alias || []).map((e) => `--no-${e}`), `--no-${e.name}`].join(`, `);
|
||||
o.push([v(n + (t ? ` (required)` : ``)), e.negativeDescription || ``]);
|
||||
}
|
||||
t && l.push(n);
|
||||
}
|
||||
if (e.subCommands) {
|
||||
let t = [], n = await f(e.subCommands);
|
||||
for (let [e, r] of Object.entries(n)) {
|
||||
let n = await f((await f(r))?.meta);
|
||||
n?.hidden || (c.push([v(e), n?.description || ``]), t.push(e));
|
||||
}
|
||||
l.push(t.join(`|`));
|
||||
}
|
||||
let u = [], p = n.version || i.version;
|
||||
u.push(y(`${n.description} (${a + (p ? ` v${p}` : ``)})`), ``);
|
||||
let m = o.length > 0 || s.length > 0;
|
||||
return u.push(`${b(_(`USAGE`))} ${v(`${a}${m ? ` [OPTIONS]` : ``} ${l.join(` `)}`)}`, ``), s.length > 0 && (u.push(b(_(`ARGUMENTS`)), ``), u.push(d(s, ` `)), u.push(``)), o.length > 0 && (u.push(b(_(`OPTIONS`)), ``), u.push(d(o, ` `)), u.push(``)), c.length > 0 && (u.push(b(_(`COMMANDS`)), ``), u.push(d(c, ` `)), u.push(``, `Use ${v(`${a} <command> --help`)} for more information about a command.`)), u.filter((e) => typeof e == `string`).join(`
|
||||
`);
|
||||
}
|
||||
async function k(e, t = {}) {
|
||||
let n = t.rawArgs || process.argv.slice(2), r = t.showUsage || E;
|
||||
try {
|
||||
if (n.includes(`--help`) || n.includes(`-h`)) await r(...await T(e, n)), process.exit(0);
|
||||
else if (n.length === 1 && n[0] === `--version`) {
|
||||
let t = typeof e.meta == `function` ? await e.meta() : await e.meta;
|
||||
if (!t?.version) throw new p(`No version specified`, `E_NO_VERSION`);
|
||||
console.log(t.version);
|
||||
} else await w(e, { rawArgs: n });
|
||||
} catch (t) {
|
||||
t instanceof p ? (await r(...await T(e, n)), console.error(t.message)) : console.error(t, `
|
||||
`), process.exit(1);
|
||||
}
|
||||
}
|
||||
export { k as n, C as t };
|
||||
+1
@@ -0,0 +1 @@
|
||||
type e=`npm`|`yarn`|`pnpm`|`bun`|`deno`;type t={name:e;command:string;version?:string;buildMeta?:string;majorVersion?:string;lockFile?:string|string[];files?:string[];};type n={cwd?:string;env?:Record<string,string>;silent?:boolean;packageManager?:t|e;installPeerDependencies?:boolean;dev?:boolean;workspace?:boolean|string;global?:boolean;corepack?:boolean;dry?:boolean;};type r={exec?:{command:string;args:string[];};};declare function i(e?:Pick<n,`cwd`|`silent`|`packageManager`|`dry`|`corepack`>&{frozenLockFile?:boolean;ignoreWorkspace?:boolean;}): Promise<r>;export{i as t};
|
||||
+669
@@ -0,0 +1,669 @@
|
||||
import { t as e } from "../rolldown-runtime.mjs";
|
||||
import { createRequire as t } from "node:module";
|
||||
import { existsSync as n } from "node:fs";
|
||||
import { readFile as r } from "node:fs/promises";
|
||||
import { PassThrough as i } from "node:stream";
|
||||
import { spawn as a } from "node:child_process";
|
||||
import { delimiter as o, dirname as s, normalize as c, resolve as l } from "node:path";
|
||||
import { cwd as u } from "node:process";
|
||||
import d from "node:readline";
|
||||
const f = /^[A-Za-z]:\//;
|
||||
function p(e = ``) {
|
||||
return e && e.replace(/\\/g, `/`).replace(f, (e) => e.toUpperCase());
|
||||
}
|
||||
const ee = /^[/\\]{2}/, te = /^[/\\](?![/\\])|^[/\\]{2}(?!\.)|^[A-Za-z]:[/\\]/, m = /^[A-Za-z]:$/, h = /^\/([A-Za-z]:)?$/, g = function(e) {
|
||||
if (e.length === 0) return `.`;
|
||||
e = p(e);
|
||||
let t = e.match(ee), n = x(e), r = e[e.length - 1] === `/`;
|
||||
return e = b(e, !n), e.length === 0 ? n ? `/` : r ? `./` : `.` : (r && (e += `/`), m.test(e) && (e += `/`), t ? n ? `//${e}` : `//./${e}` : n && !x(e) ? `/${e}` : e);
|
||||
}, _ = function(...e) {
|
||||
let t = ``;
|
||||
for (let n of e) if (n) if (t.length > 0) {
|
||||
let e = t[t.length - 1] === `/`, r = n[0] === `/`;
|
||||
e && r ? t += n.slice(1) : t += e || r ? n : `/${n}`;
|
||||
} else t += n;
|
||||
return g(t);
|
||||
};
|
||||
function v() {
|
||||
return typeof process < `u` && typeof process.cwd == `function` ? process.cwd().replace(/\\/g, `/`) : `/`;
|
||||
}
|
||||
const y = function(...e) {
|
||||
e = e.map((e) => p(e));
|
||||
let t = ``, n = !1;
|
||||
for (let r = e.length - 1; r >= -1 && !n; r--) {
|
||||
let i = r >= 0 ? e[r] : v();
|
||||
!i || i.length === 0 || (t = `${i}/${t}`, n = x(i));
|
||||
}
|
||||
return t = b(t, !n), n && !x(t) ? `/${t}` : t.length > 0 ? t : `.`;
|
||||
};
|
||||
function b(e, t) {
|
||||
let n = ``, r = 0, i = -1, a = 0, o = null;
|
||||
for (let s = 0; s <= e.length; ++s) {
|
||||
if (s < e.length) o = e[s];
|
||||
else if (o === `/`) break;
|
||||
else o = `/`;
|
||||
if (o === `/`) {
|
||||
if (!(i === s - 1 || a === 1)) if (a === 2) {
|
||||
if (n.length < 2 || r !== 2 || n[n.length - 1] !== `.` || n[n.length - 2] !== `.`) {
|
||||
if (n.length > 2) {
|
||||
let e = n.lastIndexOf(`/`);
|
||||
e === -1 ? (n = ``, r = 0) : (n = n.slice(0, e), r = n.length - 1 - n.lastIndexOf(`/`)), i = s, a = 0;
|
||||
continue;
|
||||
} else if (n.length > 0) {
|
||||
n = ``, r = 0, i = s, a = 0;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
t && (n += n.length > 0 ? `/..` : `..`, r = 2);
|
||||
} else n.length > 0 ? n += `/${e.slice(i + 1, s)}` : n = e.slice(i + 1, s), r = s - i - 1;
|
||||
i = s, a = 0;
|
||||
} else o === `.` && a !== -1 ? ++a : a = -1;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
const x = function(e) {
|
||||
return te.test(e);
|
||||
}, S = function(e, t) {
|
||||
let n = y(e).replace(h, `$1`).split(`/`), r = y(t).replace(h, `$1`).split(`/`);
|
||||
if (r[0][1] === `:` && n[0][1] === `:` && n[0] !== r[0]) return r.join(`/`);
|
||||
let i = [...n];
|
||||
for (let e of i) {
|
||||
if (r[0] !== e) break;
|
||||
n.shift(), r.shift();
|
||||
}
|
||||
return [...n.map(() => `..`), ...r].join(`/`);
|
||||
}, C = function(e) {
|
||||
let t = p(e).replace(/\/$/, ``).split(`/`).slice(0, -1);
|
||||
return t.length === 1 && m.test(t[0]) && (t[0] += `/`), t.join(`/`) || (x(e) ? `/` : `.`);
|
||||
}, ne = function(e, t) {
|
||||
let n = p(e).split(`/`), r = ``;
|
||||
for (let e = n.length - 1; e >= 0; e--) {
|
||||
let t = n[e];
|
||||
if (t) {
|
||||
r = t;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return t && r.endsWith(t) ? r.slice(0, -t.length) : r;
|
||||
};
|
||||
globalThis.process?.platform;
|
||||
var w = (e, t) => () => (t || e((t = { exports: {} }).exports, t), t.exports), T = t(import.meta.url);
|
||||
const re = /^path$/i, E = {
|
||||
key: `PATH`,
|
||||
value: ``
|
||||
};
|
||||
function D(e) {
|
||||
for (let t in e) {
|
||||
if (!Object.prototype.hasOwnProperty.call(e, t) || !re.test(t)) continue;
|
||||
let n = e[t];
|
||||
return n ? {
|
||||
key: t,
|
||||
value: n
|
||||
} : E;
|
||||
}
|
||||
return E;
|
||||
}
|
||||
function O(e, t) {
|
||||
let n = t.value.split(o), r = [], i = e, a;
|
||||
do
|
||||
r.push(l(i, `node_modules`, `.bin`)), a = i, i = s(i);
|
||||
while (i !== a);
|
||||
let c = r.concat(n).join(o);
|
||||
return {
|
||||
key: t.key,
|
||||
value: c
|
||||
};
|
||||
}
|
||||
function k(e, t) {
|
||||
let n = {
|
||||
...process.env,
|
||||
...t
|
||||
}, r = O(e, D(n));
|
||||
return n[r.key] = r.value, n;
|
||||
}
|
||||
const A = (e) => {
|
||||
let t = e.length, n = new i(), r = () => {
|
||||
--t === 0 && n.emit(`end`);
|
||||
};
|
||||
for (let t of e) t.pipe(n, { end: !1 }), t.on(`end`, r);
|
||||
return n;
|
||||
};
|
||||
var j = w(((e, t) => {
|
||||
t.exports = a, a.sync = o;
|
||||
var n = T(`fs`);
|
||||
function r(e, t) {
|
||||
var n = t.pathExt === void 0 ? process.env.PATHEXT : t.pathExt;
|
||||
if (!n || (n = n.split(`;`), n.indexOf(``) !== -1)) return !0;
|
||||
for (var r = 0; r < n.length; r++) {
|
||||
var i = n[r].toLowerCase();
|
||||
if (i && e.substr(-i.length).toLowerCase() === i) return !0;
|
||||
}
|
||||
return !1;
|
||||
}
|
||||
function i(e, t, n) {
|
||||
return !e.isSymbolicLink() && !e.isFile() ? !1 : r(t, n);
|
||||
}
|
||||
function a(e, t, r) {
|
||||
n.stat(e, function(n, a) {
|
||||
r(n, n ? !1 : i(a, e, t));
|
||||
});
|
||||
}
|
||||
function o(e, t) {
|
||||
return i(n.statSync(e), e, t);
|
||||
}
|
||||
})), M = w(((e, t) => {
|
||||
t.exports = r, r.sync = i;
|
||||
var n = T(`fs`);
|
||||
function r(e, t, r) {
|
||||
n.stat(e, function(e, n) {
|
||||
r(e, e ? !1 : a(n, t));
|
||||
});
|
||||
}
|
||||
function i(e, t) {
|
||||
return a(n.statSync(e), t);
|
||||
}
|
||||
function a(e, t) {
|
||||
return e.isFile() && o(e, t);
|
||||
}
|
||||
function o(e, t) {
|
||||
var n = e.mode, r = e.uid, i = e.gid, a = t.uid === void 0 ? process.getuid && process.getuid() : t.uid, o = t.gid === void 0 ? process.getgid && process.getgid() : t.gid, s = 64, c = 8, l = 1, u = s | c;
|
||||
return n & l || n & c && i === o || n & s && r === a || n & u && a === 0;
|
||||
}
|
||||
})), N = w(((e, t) => {
|
||||
T(`fs`);
|
||||
var n = process.platform === `win32` || global.TESTING_WINDOWS ? j() : M();
|
||||
t.exports = r, r.sync = i;
|
||||
function r(e, t, i) {
|
||||
if (typeof t == `function` && (i = t, t = {}), !i) {
|
||||
if (typeof Promise != `function`) throw TypeError(`callback not provided`);
|
||||
return new Promise(function(n, i) {
|
||||
r(e, t || {}, function(e, t) {
|
||||
e ? i(e) : n(t);
|
||||
});
|
||||
});
|
||||
}
|
||||
n(e, t || {}, function(e, n) {
|
||||
e && (e.code === `EACCES` || t && t.ignoreErrors) && (e = null, n = !1), i(e, n);
|
||||
});
|
||||
}
|
||||
function i(e, t) {
|
||||
try {
|
||||
return n.sync(e, t || {});
|
||||
} catch (e) {
|
||||
if (t && t.ignoreErrors || e.code === `EACCES`) return !1;
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
})), P = w(((e, t) => {
|
||||
let n = process.platform === `win32` || process.env.OSTYPE === `cygwin` || process.env.OSTYPE === `msys`, r = T(`path`), i = n ? `;` : `:`, a = N(), o = (e) => Object.assign(Error(`not found: ${e}`), { code: `ENOENT` }), s = (e, t) => {
|
||||
let r = t.colon || i, a = e.match(/\//) || n && e.match(/\\/) ? [``] : [...n ? [process.cwd()] : [], ...(t.path || process.env.PATH || ``).split(r)], o = n ? t.pathExt || process.env.PATHEXT || `.EXE;.CMD;.BAT;.COM` : ``, s = n ? o.split(r) : [``];
|
||||
return n && e.indexOf(`.`) !== -1 && s[0] !== `` && s.unshift(``), {
|
||||
pathEnv: a,
|
||||
pathExt: s,
|
||||
pathExtExe: o
|
||||
};
|
||||
}, c = (e, t, n) => {
|
||||
typeof t == `function` && (n = t, t = {}), t ||= {};
|
||||
let { pathEnv: i, pathExt: c, pathExtExe: l } = s(e, t), u = [], d = (n) => new Promise((a, s) => {
|
||||
if (n === i.length) return t.all && u.length ? a(u) : s(o(e));
|
||||
let c = i[n], l = /^".*"$/.test(c) ? c.slice(1, -1) : c, d = r.join(l, e);
|
||||
a(f(!l && /^\.[\\\/]/.test(e) ? e.slice(0, 2) + d : d, n, 0));
|
||||
}), f = (e, n, r) => new Promise((i, o) => {
|
||||
if (r === c.length) return i(d(n + 1));
|
||||
let s = c[r];
|
||||
a(e + s, { pathExt: l }, (a, o) => {
|
||||
if (!a && o) if (t.all) u.push(e + s);
|
||||
else return i(e + s);
|
||||
return i(f(e, n, r + 1));
|
||||
});
|
||||
});
|
||||
return n ? d(0).then((e) => n(null, e), n) : d(0);
|
||||
};
|
||||
t.exports = c, c.sync = (e, t) => {
|
||||
t ||= {};
|
||||
let { pathEnv: n, pathExt: i, pathExtExe: c } = s(e, t), l = [];
|
||||
for (let o = 0; o < n.length; o++) {
|
||||
let s = n[o], u = /^".*"$/.test(s) ? s.slice(1, -1) : s, d = r.join(u, e), f = !u && /^\.[\\\/]/.test(e) ? e.slice(0, 2) + d : d;
|
||||
for (let e = 0; e < i.length; e++) {
|
||||
let n = f + i[e];
|
||||
try {
|
||||
if (a.sync(n, { pathExt: c })) if (t.all) l.push(n);
|
||||
else return n;
|
||||
} catch {}
|
||||
}
|
||||
}
|
||||
if (t.all && l.length) return l;
|
||||
if (t.nothrow) return null;
|
||||
throw o(e);
|
||||
};
|
||||
})), F = w(((e, t) => {
|
||||
let n = (e = {}) => {
|
||||
let t = e.env || process.env;
|
||||
return (e.platform || process.platform) === `win32` ? Object.keys(t).reverse().find((e) => e.toUpperCase() === `PATH`) || `Path` : `PATH`;
|
||||
};
|
||||
t.exports = n, t.exports.default = n;
|
||||
})), I = w(((e, t) => {
|
||||
let n = T(`path`), r = P(), i = F();
|
||||
function a(e, t) {
|
||||
let a = e.options.env || process.env, o = process.cwd(), s = e.options.cwd != null, c = s && process.chdir !== void 0 && !process.chdir.disabled;
|
||||
if (c) try {
|
||||
process.chdir(e.options.cwd);
|
||||
} catch {}
|
||||
let l;
|
||||
try {
|
||||
l = r.sync(e.command, {
|
||||
path: a[i({ env: a })],
|
||||
pathExt: t ? n.delimiter : void 0
|
||||
});
|
||||
} catch {} finally {
|
||||
c && process.chdir(o);
|
||||
}
|
||||
return l &&= n.resolve(s ? e.options.cwd : ``, l), l;
|
||||
}
|
||||
function o(e) {
|
||||
return a(e) || a(e, !0);
|
||||
}
|
||||
t.exports = o;
|
||||
})), L = w(((e, t) => {
|
||||
let n = /([()\][%!^"`<>&|;, *?])/g;
|
||||
function r(e) {
|
||||
return e = e.replace(n, `^$1`), e;
|
||||
}
|
||||
function i(e, t) {
|
||||
return e = `${e}`, e = e.replace(/(?=(\\+?)?)\1"/g, `$1$1\\"`), e = e.replace(/(?=(\\+?)?)\1$/, `$1$1`), e = `"${e}"`, e = e.replace(n, `^$1`), t && (e = e.replace(n, `^$1`)), e;
|
||||
}
|
||||
t.exports.command = r, t.exports.argument = i;
|
||||
})), R = w(((e, t) => {
|
||||
t.exports = /^#!(.*)/;
|
||||
})), z = w(((e, t) => {
|
||||
let n = R();
|
||||
t.exports = (e = ``) => {
|
||||
let t = e.match(n);
|
||||
if (!t) return null;
|
||||
let [r, i] = t[0].replace(/#! ?/, ``).split(` `), a = r.split(`/`).pop();
|
||||
return a === `env` ? i : i ? `${a} ${i}` : a;
|
||||
};
|
||||
})), B = w(((e, t) => {
|
||||
let n = T(`fs`), r = z();
|
||||
function i(e) {
|
||||
let t = Buffer.alloc(150), i;
|
||||
try {
|
||||
i = n.openSync(e, `r`), n.readSync(i, t, 0, 150, 0), n.closeSync(i);
|
||||
} catch {}
|
||||
return r(t.toString());
|
||||
}
|
||||
t.exports = i;
|
||||
})), V = w(((e, t) => {
|
||||
let n = T(`path`), r = I(), i = L(), a = B(), o = process.platform === `win32`, s = /\.(?:com|exe)$/i, c = /node_modules[\\/].bin[\\/][^\\/]+\.cmd$/i;
|
||||
function l(e) {
|
||||
e.file = r(e);
|
||||
let t = e.file && a(e.file);
|
||||
return t ? (e.args.unshift(e.file), e.command = t, r(e)) : e.file;
|
||||
}
|
||||
function u(e) {
|
||||
if (!o) return e;
|
||||
let t = l(e), r = !s.test(t);
|
||||
if (e.options.forceShell || r) {
|
||||
let r = c.test(t);
|
||||
e.command = n.normalize(e.command), e.command = i.command(e.command), e.args = e.args.map((e) => i.argument(e, r)), e.args = [
|
||||
`/d`,
|
||||
`/s`,
|
||||
`/c`,
|
||||
`"${[e.command].concat(e.args).join(` `)}"`
|
||||
], e.command = process.env.comspec || `cmd.exe`, e.options.windowsVerbatimArguments = !0;
|
||||
}
|
||||
return e;
|
||||
}
|
||||
function d(e, t, n) {
|
||||
t && !Array.isArray(t) && (n = t, t = null), t = t ? t.slice(0) : [], n = Object.assign({}, n);
|
||||
let r = {
|
||||
command: e,
|
||||
args: t,
|
||||
options: n,
|
||||
file: void 0,
|
||||
original: {
|
||||
command: e,
|
||||
args: t
|
||||
}
|
||||
};
|
||||
return n.shell ? r : u(r);
|
||||
}
|
||||
t.exports = d;
|
||||
})), ie = w(((e, t) => {
|
||||
let n = process.platform === `win32`;
|
||||
function r(e, t) {
|
||||
return Object.assign(Error(`${t} ${e.command} ENOENT`), {
|
||||
code: `ENOENT`,
|
||||
errno: `ENOENT`,
|
||||
syscall: `${t} ${e.command}`,
|
||||
path: e.command,
|
||||
spawnargs: e.args
|
||||
});
|
||||
}
|
||||
function i(e, t) {
|
||||
if (!n) return;
|
||||
let r = e.emit;
|
||||
e.emit = function(n, i) {
|
||||
if (n === `exit`) {
|
||||
let n = a(i, t);
|
||||
if (n) return r.call(e, `error`, n);
|
||||
}
|
||||
return r.apply(e, arguments);
|
||||
};
|
||||
}
|
||||
function a(e, t) {
|
||||
return n && e === 1 && !t.file ? r(t.original, `spawn`) : null;
|
||||
}
|
||||
function o(e, t) {
|
||||
return n && e === 1 && !t.file ? r(t.original, `spawnSync`) : null;
|
||||
}
|
||||
t.exports = {
|
||||
hookChildProcess: i,
|
||||
verifyENOENT: a,
|
||||
verifyENOENTSync: o,
|
||||
notFoundError: r
|
||||
};
|
||||
})), H = w(((e, t) => {
|
||||
let n = T(`child_process`), r = V(), i = ie();
|
||||
function a(e, t, a) {
|
||||
let o = r(e, t, a), s = n.spawn(o.command, o.args, o.options);
|
||||
return i.hookChildProcess(s, o), s;
|
||||
}
|
||||
function o(e, t, a) {
|
||||
let o = r(e, t, a), s = n.spawnSync(o.command, o.args, o.options);
|
||||
return s.error = s.error || i.verifyENOENTSync(s.status, o), s;
|
||||
}
|
||||
t.exports = a, t.exports.spawn = a, t.exports.sync = o, t.exports._parse = r, t.exports._enoent = i;
|
||||
}))(), U = class extends Error {
|
||||
result;
|
||||
output;
|
||||
get exitCode() {
|
||||
if (this.result.exitCode !== null) return this.result.exitCode;
|
||||
}
|
||||
constructor(e, t) {
|
||||
super(`Process exited with non-zero status (${e.exitCode})`), this.result = e, this.output = t;
|
||||
}
|
||||
};
|
||||
const W = {
|
||||
timeout: void 0,
|
||||
persist: !1
|
||||
}, G = { windowsHide: !0 };
|
||||
function K(e, t) {
|
||||
return {
|
||||
command: c(e),
|
||||
args: t ?? []
|
||||
};
|
||||
}
|
||||
function q(e) {
|
||||
let t = new AbortController();
|
||||
for (let n of e) {
|
||||
if (n.aborted) return t.abort(), n;
|
||||
n.addEventListener(`abort`, () => {
|
||||
t.abort(n.reason);
|
||||
}, { signal: t.signal });
|
||||
}
|
||||
return t.signal;
|
||||
}
|
||||
async function J(e) {
|
||||
let t = ``;
|
||||
for await (let n of e) t += n.toString();
|
||||
return t;
|
||||
}
|
||||
var Y = class {
|
||||
_process;
|
||||
_aborted = !1;
|
||||
_options;
|
||||
_command;
|
||||
_args;
|
||||
_resolveClose;
|
||||
_processClosed;
|
||||
_thrownError;
|
||||
get process() {
|
||||
return this._process;
|
||||
}
|
||||
get pid() {
|
||||
return this._process?.pid;
|
||||
}
|
||||
get exitCode() {
|
||||
if (this._process && this._process.exitCode !== null) return this._process.exitCode;
|
||||
}
|
||||
constructor(e, t, n) {
|
||||
this._options = {
|
||||
...W,
|
||||
...n
|
||||
}, this._command = e, this._args = t ?? [], this._processClosed = new Promise((e) => {
|
||||
this._resolveClose = e;
|
||||
});
|
||||
}
|
||||
kill(e) {
|
||||
return this._process?.kill(e) === !0;
|
||||
}
|
||||
get aborted() {
|
||||
return this._aborted;
|
||||
}
|
||||
get killed() {
|
||||
return this._process?.killed === !0;
|
||||
}
|
||||
pipe(e, t, n) {
|
||||
return ae(e, t, {
|
||||
...n,
|
||||
stdin: this
|
||||
});
|
||||
}
|
||||
async *[Symbol.asyncIterator]() {
|
||||
let e = this._process;
|
||||
if (!e) return;
|
||||
let t = [];
|
||||
this._streamErr && t.push(this._streamErr), this._streamOut && t.push(this._streamOut);
|
||||
let n = A(t), r = d.createInterface({ input: n });
|
||||
for await (let e of r) yield e.toString();
|
||||
if (await this._processClosed, e.removeAllListeners(), this._thrownError) throw this._thrownError;
|
||||
if (this._options?.throwOnError && this.exitCode !== 0 && this.exitCode !== void 0) throw new U(this);
|
||||
}
|
||||
async _waitForOutput() {
|
||||
let e = this._process;
|
||||
if (!e) throw Error(`No process was started`);
|
||||
let [t, n] = await Promise.all([this._streamOut ? J(this._streamOut) : ``, this._streamErr ? J(this._streamErr) : ``]);
|
||||
if (await this._processClosed, this._options?.stdin && await this._options.stdin, e.removeAllListeners(), this._thrownError) throw this._thrownError;
|
||||
let r = {
|
||||
stderr: n,
|
||||
stdout: t,
|
||||
exitCode: this.exitCode
|
||||
};
|
||||
if (this._options.throwOnError && this.exitCode !== 0 && this.exitCode !== void 0) throw new U(this, r);
|
||||
return r;
|
||||
}
|
||||
then(e, t) {
|
||||
return this._waitForOutput().then(e, t);
|
||||
}
|
||||
_streamOut;
|
||||
_streamErr;
|
||||
spawn() {
|
||||
let e = u(), t = this._options, n = {
|
||||
...G,
|
||||
...t.nodeOptions
|
||||
}, r = [];
|
||||
this._resetState(), t.timeout !== void 0 && r.push(AbortSignal.timeout(t.timeout)), t.signal !== void 0 && r.push(t.signal), t.persist === !0 && (n.detached = !0), r.length > 0 && (n.signal = q(r)), n.env = k(e, n.env);
|
||||
let { command: i, args: o } = K(this._command, this._args), s = (0, H._parse)(i, o, n), c = a(s.command, s.args, s.options);
|
||||
if (c.stderr && (this._streamErr = c.stderr), c.stdout && (this._streamOut = c.stdout), this._process = c, c.once(`error`, this._onError), c.once(`close`, this._onClose), t.stdin !== void 0 && c.stdin && t.stdin.process) {
|
||||
let { stdout: e } = t.stdin.process;
|
||||
e && e.pipe(c.stdin);
|
||||
}
|
||||
}
|
||||
_resetState() {
|
||||
this._aborted = !1, this._processClosed = new Promise((e) => {
|
||||
this._resolveClose = e;
|
||||
}), this._thrownError = void 0;
|
||||
}
|
||||
_onError = (e) => {
|
||||
if (e.name === `AbortError` && (!(e.cause instanceof Error) || e.cause.name !== `TimeoutError`)) {
|
||||
this._aborted = !0;
|
||||
return;
|
||||
}
|
||||
this._thrownError = e;
|
||||
};
|
||||
_onClose = () => {
|
||||
this._resolveClose && this._resolveClose();
|
||||
};
|
||||
};
|
||||
const X = (e, t, n) => {
|
||||
let r = new Y(e, t, n);
|
||||
return r.spawn(), r;
|
||||
}, ae = X;
|
||||
var oe = e({
|
||||
detectPackageManager: () => $,
|
||||
installDependencies: () => fe,
|
||||
packageManagers: () => Q
|
||||
});
|
||||
async function se(e, t, n = {}) {
|
||||
let r = g(e).split(`/`);
|
||||
for (; r.length > 0;) {
|
||||
let e = await t(r.join(`/`) || `/`);
|
||||
if (e || !n.includeParentDirs) return e;
|
||||
r.pop();
|
||||
}
|
||||
}
|
||||
function ce(e) {
|
||||
let t;
|
||||
return () => (t === void 0 && (t = e().then((e) => (t = e, t))), t);
|
||||
}
|
||||
const Z = ce(async () => {
|
||||
if (globalThis.process?.versions?.webcontainer) return !1;
|
||||
try {
|
||||
let { exitCode: e } = await X(`corepack`, [`--version`]);
|
||||
return e === 0;
|
||||
} catch {
|
||||
return !1;
|
||||
}
|
||||
});
|
||||
async function le(e, t, n = {}) {
|
||||
let r = e !== `npm` && e !== `bun` && e !== `deno` && n.corepack !== !1 && await Z() ? [`corepack`, [e, ...t]] : [e, t], { exitCode: i, stdout: a, stderr: o } = await X(r[0], r[1], { nodeOptions: {
|
||||
cwd: y(n.cwd || process.cwd()),
|
||||
env: n.env,
|
||||
stdio: n.silent ? `pipe` : `inherit`
|
||||
} });
|
||||
if (i !== 0) throw Error(`\`${r.flat().join(` `)}\` failed.${n.silent ? [
|
||||
``,
|
||||
a,
|
||||
o
|
||||
].join(`
|
||||
`) : ``}`);
|
||||
}
|
||||
async function ue(e = {}) {
|
||||
let t = e.cwd || process.cwd(), n = {
|
||||
...process.env,
|
||||
...e.env
|
||||
}, r = (typeof e.packageManager == `string` ? Q.find((t) => t.name === e.packageManager) : e.packageManager) || await $(e.cwd || process.cwd());
|
||||
if (!r) throw Error(`No package manager auto-detected.`);
|
||||
return {
|
||||
cwd: t,
|
||||
env: n,
|
||||
silent: e.silent ?? !1,
|
||||
packageManager: r,
|
||||
dev: e.dev ?? !1,
|
||||
workspace: e.workspace,
|
||||
global: e.global ?? !1,
|
||||
dry: e.dry ?? !1,
|
||||
corepack: e.corepack ?? !0
|
||||
};
|
||||
}
|
||||
function de(e) {
|
||||
let [t, n] = (e || ``).split(`@`), [r, i] = n?.split(`+`) || [];
|
||||
if (t && t !== `-` && /^(@[a-z0-9-~][a-z0-9-._~]*\/)?[a-z0-9-~][a-z0-9-._~]*$/.test(t)) return {
|
||||
name: t,
|
||||
version: r,
|
||||
buildMeta: i
|
||||
};
|
||||
let a = (t || ``).replace(/\W+/g, ``);
|
||||
return {
|
||||
name: a,
|
||||
version: r,
|
||||
buildMeta: i,
|
||||
warnings: [`Abnormal characters found in \`packageManager\` field, sanitizing from \`${t}\` to \`${a}\``]
|
||||
};
|
||||
}
|
||||
const Q = [
|
||||
{
|
||||
name: `npm`,
|
||||
command: `npm`,
|
||||
lockFile: `package-lock.json`
|
||||
},
|
||||
{
|
||||
name: `pnpm`,
|
||||
command: `pnpm`,
|
||||
lockFile: `pnpm-lock.yaml`,
|
||||
files: [`pnpm-workspace.yaml`]
|
||||
},
|
||||
{
|
||||
name: `bun`,
|
||||
command: `bun`,
|
||||
lockFile: [`bun.lockb`, `bun.lock`]
|
||||
},
|
||||
{
|
||||
name: `yarn`,
|
||||
command: `yarn`,
|
||||
lockFile: `yarn.lock`,
|
||||
files: [`.yarnrc.yml`]
|
||||
},
|
||||
{
|
||||
name: `deno`,
|
||||
command: `deno`,
|
||||
lockFile: `deno.lock`,
|
||||
files: [`deno.json`]
|
||||
}
|
||||
];
|
||||
async function $(e, t = {}) {
|
||||
let i = await se(y(e || `.`), async (e) => {
|
||||
if (!t.ignorePackageJSON) {
|
||||
let t = _(e, `package.json`);
|
||||
if (n(t)) {
|
||||
let e = JSON.parse(await r(t, `utf8`));
|
||||
if (e?.packageManager) {
|
||||
let { name: t, version: n = `0.0.0`, buildMeta: r, warnings: i } = de(e.packageManager);
|
||||
if (t) {
|
||||
let e = n.split(`.`)[0], a = Q.find((n) => n.name === t && n.majorVersion === e) || Q.find((e) => e.name === t);
|
||||
return {
|
||||
name: t,
|
||||
command: t,
|
||||
version: n,
|
||||
majorVersion: e,
|
||||
buildMeta: r,
|
||||
warnings: i,
|
||||
files: a?.files,
|
||||
lockFile: a?.lockFile
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
if (n(_(e, `deno.json`))) return Q.find((e) => e.name === `deno`);
|
||||
}
|
||||
if (!t.ignoreLockFile) {
|
||||
for (let t of Q) if ([t.lockFile, t.files].flat().filter(Boolean).some((t) => n(y(e, t)))) return { ...t };
|
||||
}
|
||||
}, { includeParentDirs: t.includeParentDirs ?? !0 });
|
||||
if (!i && !t.ignoreArgv) {
|
||||
let e = process.argv[1];
|
||||
if (e) {
|
||||
for (let t of Q) if (RegExp(`[/\\\\]\\.?${t.command}`).test(e)) return t;
|
||||
}
|
||||
}
|
||||
return i;
|
||||
}
|
||||
async function fe(e = {}) {
|
||||
let t = await ue(e), n = e.frozenLockFile ? {
|
||||
npm: [`ci`],
|
||||
yarn: [`install`, `--immutable`],
|
||||
bun: [`install`, `--frozen-lockfile`],
|
||||
pnpm: [`install`, `--frozen-lockfile`],
|
||||
deno: [`install`, `--frozen`]
|
||||
}[t.packageManager.name] : [`install`];
|
||||
return e.ignoreWorkspace && t.packageManager.name === `pnpm` && n.push(`--ignore-workspace`), t.dry || await le(t.packageManager.command, n, {
|
||||
cwd: t.cwd,
|
||||
silent: t.silent,
|
||||
corepack: t.corepack
|
||||
}), { exec: {
|
||||
command: t.packageManager.command,
|
||||
args: n
|
||||
} };
|
||||
}
|
||||
export { y as a, S as i, ne as n, C as r, oe as t };
|
||||
+2931
File diff suppressed because it is too large
Load Diff
+14
@@ -0,0 +1,14 @@
|
||||
import "node:module";
|
||||
//#region \0rolldown/runtime.js
|
||||
var __defProp = Object.defineProperty;
|
||||
var __exportAll = (all, no_symbols) => {
|
||||
let target = {};
|
||||
for (var name in all) __defProp(target, name, {
|
||||
get: all[name],
|
||||
enumerable: true
|
||||
});
|
||||
if (!no_symbols) __defProp(target, Symbol.toStringTag, { value: "Module" });
|
||||
return target;
|
||||
};
|
||||
//#endregion
|
||||
export { __exportAll as t };
|
||||
+1
@@ -0,0 +1 @@
|
||||
export { };
|
||||
+90
@@ -0,0 +1,90 @@
|
||||
#!/usr/bin/env node
|
||||
import { i as relative } from "./_chunks/libs/nypm.mjs";
|
||||
import { r as startShell, t as downloadTemplate } from "./_chunks/giget.mjs";
|
||||
import { n as runMain, t as defineCommand } from "./_chunks/libs/citty.mjs";
|
||||
//#endregion
|
||||
//#region src/cli.ts
|
||||
runMain(defineCommand({
|
||||
meta: {
|
||||
name: "giget",
|
||||
version: "3.1.2",
|
||||
description: "Download templates and git repositories with pleasure!"
|
||||
},
|
||||
args: {
|
||||
template: {
|
||||
type: "positional",
|
||||
required: true,
|
||||
description: "Template name or a URI describing provider, repository, subdir, and branch/ref"
|
||||
},
|
||||
dir: {
|
||||
type: "positional",
|
||||
description: "A relative or absolute path where to extract the template",
|
||||
required: false
|
||||
},
|
||||
auth: {
|
||||
type: "string",
|
||||
description: "Custom Authorization token to use for downloading template. (Can be overridden with `GIGET_AUTH` environment variable)"
|
||||
},
|
||||
cwd: {
|
||||
type: "string",
|
||||
description: "Set current working directory to resolve dirs relative to it"
|
||||
},
|
||||
force: {
|
||||
type: "boolean",
|
||||
description: "Clone to existing directory even if exists"
|
||||
},
|
||||
forceClean: {
|
||||
type: "boolean",
|
||||
description: "Remove any existing directory or file recursively before cloning"
|
||||
},
|
||||
offline: {
|
||||
type: "boolean",
|
||||
description: "Do not attempt to download and use cached version"
|
||||
},
|
||||
preferOffline: {
|
||||
type: "boolean",
|
||||
description: "Use cache if exists otherwise try to download"
|
||||
},
|
||||
shell: {
|
||||
type: "boolean",
|
||||
description: "Open a new shell with the current working directory set to the cloned directory (experimental)"
|
||||
},
|
||||
install: {
|
||||
type: "boolean",
|
||||
description: "Install dependencies after cloning"
|
||||
},
|
||||
verbose: {
|
||||
type: "boolean",
|
||||
description: "Show verbose debugging info"
|
||||
}
|
||||
},
|
||||
run: async ({ args }) => {
|
||||
if (args.verbose) process.env.DEBUG = process.env.DEBUG || "true";
|
||||
let r;
|
||||
try {
|
||||
r = await downloadTemplate(args.template, {
|
||||
dir: args.dir,
|
||||
force: args.force,
|
||||
forceClean: args.forceClean,
|
||||
offline: args.offline,
|
||||
preferOffline: args.preferOffline,
|
||||
auth: args.auth,
|
||||
install: args.install
|
||||
});
|
||||
} catch (error) {
|
||||
if (args.verbose) console.error(error);
|
||||
else {
|
||||
const message = error instanceof Error ? error.message : `Failed to download ${args.template}: unknown error`;
|
||||
console.error(message);
|
||||
}
|
||||
process.exitCode = 1;
|
||||
return;
|
||||
}
|
||||
const _from = r.name || r.url;
|
||||
const _to = relative(process.cwd(), r.dir) || "./";
|
||||
console.log(`✨ Successfully cloned \`${_from}\` to \`${_to}\`\n`);
|
||||
if (args.shell) startShell(r.dir);
|
||||
}
|
||||
}));
|
||||
//#endregion
|
||||
export {};
|
||||
+60
@@ -0,0 +1,60 @@
|
||||
import { t as installDependencies } from "./_chunks/libs/nypm.mjs";
|
||||
import { Readable } from "node:stream";
|
||||
|
||||
//#region src/types.d.ts
|
||||
interface GitInfo {
|
||||
provider: "github" | "gitlab" | "bitbucket" | "sourcehut";
|
||||
repo: string;
|
||||
subdir: string;
|
||||
ref: string;
|
||||
}
|
||||
type TarOutput = Readable | ReadableStream<Uint8Array>;
|
||||
interface TemplateInfo {
|
||||
name: string;
|
||||
tar: string | ((options?: {
|
||||
auth?: string;
|
||||
}) => TarOutput | Promise<TarOutput>);
|
||||
version?: string;
|
||||
subdir?: string;
|
||||
url?: string;
|
||||
defaultDir?: string;
|
||||
headers?: Record<string, string | undefined>;
|
||||
source?: never;
|
||||
dir?: never;
|
||||
[key: string]: any;
|
||||
}
|
||||
type TemplateProvider = (input: string, options: {
|
||||
auth?: string;
|
||||
}) => TemplateInfo | Promise<TemplateInfo> | null;
|
||||
//#endregion
|
||||
//#region src/giget.d.ts
|
||||
type InstallOptions = Parameters<typeof installDependencies>[0];
|
||||
interface DownloadTemplateOptions {
|
||||
provider?: string;
|
||||
force?: boolean;
|
||||
forceClean?: boolean;
|
||||
offline?: boolean;
|
||||
preferOffline?: boolean;
|
||||
providers?: Record<string, TemplateProvider>;
|
||||
dir?: string;
|
||||
registry?: false | string;
|
||||
cwd?: string;
|
||||
auth?: string;
|
||||
install?: boolean | InstallOptions;
|
||||
silent?: boolean;
|
||||
}
|
||||
type DownloadTemplateResult = Omit<TemplateInfo, "dir" | "source"> & {
|
||||
dir: string;
|
||||
source: string;
|
||||
};
|
||||
declare function downloadTemplate(input: string, options?: DownloadTemplateOptions): Promise<DownloadTemplateResult>;
|
||||
//#endregion
|
||||
//#region src/registry.d.ts
|
||||
declare const registryProvider: (registryEndpoint?: string, options?: {
|
||||
auth?: string;
|
||||
}) => TemplateProvider;
|
||||
//#endregion
|
||||
//#region src/_utils.d.ts
|
||||
declare function startShell(cwd: string): void;
|
||||
//#endregion
|
||||
export { DownloadTemplateOptions, DownloadTemplateResult, GitInfo, TarOutput, TemplateInfo, TemplateProvider, downloadTemplate, registryProvider, startShell };
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
import { n as registryProvider, r as startShell, t as downloadTemplate } from "./_chunks/giget.mjs";
|
||||
export { downloadTemplate, registryProvider, startShell };
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
{
|
||||
"name": "giget",
|
||||
"version": "3.2.0",
|
||||
"description": "Download templates and git repositories with pleasure!",
|
||||
"license": "MIT",
|
||||
"repository": "unjs/giget",
|
||||
"bin": {
|
||||
"giget": "./dist/cli.mjs"
|
||||
},
|
||||
"files": [
|
||||
"dist"
|
||||
],
|
||||
"type": "module",
|
||||
"sideEffects": false,
|
||||
"types": "./dist/index.d.mts",
|
||||
"exports": {
|
||||
".": "./dist/index.mjs"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "obuild",
|
||||
"dev": "vitest dev",
|
||||
"giget": "node ./src/cli.ts",
|
||||
"lint": "oxlint . && oxfmt --check src test",
|
||||
"lint:fix": "oxlint . --fix && oxfmt src test",
|
||||
"play": "pnpm giget --force-clean --verbose unjs .tmp/clone",
|
||||
"release": "pnpm test && pnpm build && changelogen --release && npm publish && git push --follow-tags",
|
||||
"test": "pnpm lint && pnpm test:types && vitest run --coverage",
|
||||
"test:types": "tsgo --noEmit"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^25.5.0",
|
||||
"@typescript/native-preview": "^7.0.0-dev.20260326.1",
|
||||
"@vitest/coverage-v8": "^4.1.2",
|
||||
"changelogen": "^0.6.2",
|
||||
"citty": "^0.2.1",
|
||||
"eslint-config-unjs": "^0.6.2",
|
||||
"nypm": "^0.6.5",
|
||||
"obuild": "^0.4.32",
|
||||
"oxfmt": "^0.42.0",
|
||||
"oxlint": "^1.57.0",
|
||||
"pathe": "^2.0.3",
|
||||
"rolldown": "^1.0.0-rc.12",
|
||||
"tar": "^7.5.13",
|
||||
"typescript": "^6.0.2",
|
||||
"unbuild": "^3.6.1",
|
||||
"vitest": "^4.1.2"
|
||||
},
|
||||
"packageManager": "pnpm@10.33.0"
|
||||
}
|
||||
Reference in New Issue
Block a user