@org-press/deploy-github-pages 0.9.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +29 -0
- package/README.md +177 -0
- package/dist/index.js +235 -0
- package/package.json +48 -0
- package/src/adapter.test.ts +759 -0
- package/src/adapter.ts +365 -0
- package/src/index.ts +27 -0
- package/src/types.ts +58 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
GNU GENERAL PUBLIC LICENSE
|
|
2
|
+
Version 2, June 1991
|
|
3
|
+
|
|
4
|
+
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
|
|
5
|
+
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
|
6
|
+
|
|
7
|
+
Everyone is permitted to copy and distribute verbatim copies
|
|
8
|
+
of this license document, but changing it is not allowed.
|
|
9
|
+
|
|
10
|
+
For the full license text, see: https://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
Org-Press - Static site generator for org-mode files
|
|
15
|
+
Copyright (C) 2024-2026
|
|
16
|
+
|
|
17
|
+
This program is free software; you can redistribute it and/or modify
|
|
18
|
+
it under the terms of the GNU General Public License as published by
|
|
19
|
+
the Free Software Foundation; either version 2 of the License, or
|
|
20
|
+
(at your option) any later version.
|
|
21
|
+
|
|
22
|
+
This program is distributed in the hope that it will be useful,
|
|
23
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
24
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
25
|
+
GNU General Public License for more details.
|
|
26
|
+
|
|
27
|
+
You should have received a copy of the GNU General Public License
|
|
28
|
+
along with this program; if not, write to the Free Software
|
|
29
|
+
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
package/README.md
ADDED
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
# @org-press/deploy-github-pages
|
|
2
|
+
|
|
3
|
+
GitHub Pages deploy adapter for [org-press](https://orgp.dev).
|
|
4
|
+
|
|
5
|
+
Deploys static sites to GitHub Pages by pushing to the `gh-pages` branch.
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install @org-press/deploy-github-pages
|
|
11
|
+
# or
|
|
12
|
+
pnpm add @org-press/deploy-github-pages
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Usage
|
|
16
|
+
|
|
17
|
+
### Basic Usage
|
|
18
|
+
|
|
19
|
+
```typescript
|
|
20
|
+
import { githubPagesAdapter } from '@org-press/deploy-github-pages';
|
|
21
|
+
|
|
22
|
+
export default defineConfig({
|
|
23
|
+
deploy: {
|
|
24
|
+
adapter: githubPagesAdapter({
|
|
25
|
+
repo: 'user/my-site',
|
|
26
|
+
}),
|
|
27
|
+
},
|
|
28
|
+
});
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
### With Custom Domain
|
|
32
|
+
|
|
33
|
+
```typescript
|
|
34
|
+
import { githubPagesAdapter } from '@org-press/deploy-github-pages';
|
|
35
|
+
|
|
36
|
+
export default defineConfig({
|
|
37
|
+
deploy: {
|
|
38
|
+
adapter: githubPagesAdapter({
|
|
39
|
+
repo: 'user/my-site',
|
|
40
|
+
cname: 'mysite.com',
|
|
41
|
+
}),
|
|
42
|
+
},
|
|
43
|
+
});
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### Full Configuration
|
|
47
|
+
|
|
48
|
+
```typescript
|
|
49
|
+
import { githubPagesAdapter } from '@org-press/deploy-github-pages';
|
|
50
|
+
|
|
51
|
+
export default defineConfig({
|
|
52
|
+
deploy: {
|
|
53
|
+
adapter: githubPagesAdapter({
|
|
54
|
+
// GitHub repository (user/repo or org/repo format)
|
|
55
|
+
// If not specified, auto-detects from git remote
|
|
56
|
+
repo: 'user/my-site',
|
|
57
|
+
|
|
58
|
+
// Target branch (default: 'gh-pages')
|
|
59
|
+
branch: 'gh-pages',
|
|
60
|
+
|
|
61
|
+
// Custom domain for CNAME file
|
|
62
|
+
cname: 'mysite.com',
|
|
63
|
+
|
|
64
|
+
// Add .nojekyll file (default: true)
|
|
65
|
+
// Recommended for pre-built static sites
|
|
66
|
+
noJekyll: true,
|
|
67
|
+
|
|
68
|
+
// Commit message (default: 'Deploy to GitHub Pages')
|
|
69
|
+
message: 'Deploy docs from CI',
|
|
70
|
+
|
|
71
|
+
// Remote name (default: 'origin')
|
|
72
|
+
remote: 'origin',
|
|
73
|
+
}),
|
|
74
|
+
},
|
|
75
|
+
});
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## Configuration Options
|
|
79
|
+
|
|
80
|
+
| Option | Type | Default | Description |
|
|
81
|
+
|--------|------|---------|-------------|
|
|
82
|
+
| `repo` | `string` | Auto-detected | GitHub repository in `user/repo` format |
|
|
83
|
+
| `branch` | `string` | `'gh-pages'` | Target branch for deployment |
|
|
84
|
+
| `cname` | `string` | - | Custom domain (creates CNAME file) |
|
|
85
|
+
| `noJekyll` | `boolean` | `true` | Add `.nojekyll` file to disable Jekyll |
|
|
86
|
+
| `message` | `string` | `'Deploy to GitHub Pages'` | Git commit message |
|
|
87
|
+
| `remote` | `string` | `'origin'` | Git remote name |
|
|
88
|
+
|
|
89
|
+
## How It Works
|
|
90
|
+
|
|
91
|
+
The adapter deploys your site by:
|
|
92
|
+
|
|
93
|
+
1. Adding a `.nojekyll` file (optional, recommended)
|
|
94
|
+
2. Adding a `CNAME` file if a custom domain is configured
|
|
95
|
+
3. Initializing a new git repository in your build output directory
|
|
96
|
+
4. Committing all files
|
|
97
|
+
5. Force pushing to the `gh-pages` branch on GitHub
|
|
98
|
+
|
|
99
|
+
This approach ensures a clean deployment each time without accumulating history.
|
|
100
|
+
|
|
101
|
+
## Auto-Detection
|
|
102
|
+
|
|
103
|
+
If `repo` is not specified, the adapter attempts to auto-detect the repository from your git remote:
|
|
104
|
+
|
|
105
|
+
```bash
|
|
106
|
+
# Supports both HTTPS and SSH remote URLs:
|
|
107
|
+
https://github.com/user/repo.git
|
|
108
|
+
git@github.com:user/repo.git
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
## Dry Run Mode
|
|
112
|
+
|
|
113
|
+
Test your deployment without actually pushing:
|
|
114
|
+
|
|
115
|
+
```typescript
|
|
116
|
+
const result = await deploy({
|
|
117
|
+
adapter: githubPagesAdapter({ repo: 'user/repo' }),
|
|
118
|
+
dryRun: true,
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
console.log(result.url); // Predicted GitHub Pages URL
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
## GitHub Pages URL
|
|
125
|
+
|
|
126
|
+
The adapter returns the correct URL based on your repository:
|
|
127
|
+
|
|
128
|
+
- **User/Org pages** (`username.github.io`): `https://username.github.io`
|
|
129
|
+
- **Project pages** (`user/project`): `https://user.github.io/project`
|
|
130
|
+
- **Custom domain**: `https://your-domain.com`
|
|
131
|
+
|
|
132
|
+
## Requirements
|
|
133
|
+
|
|
134
|
+
- Git must be installed and available in PATH
|
|
135
|
+
- Push access to the target repository
|
|
136
|
+
- For private repos, appropriate authentication (SSH key or token)
|
|
137
|
+
|
|
138
|
+
## CI/CD Example
|
|
139
|
+
|
|
140
|
+
### GitHub Actions
|
|
141
|
+
|
|
142
|
+
```yaml
|
|
143
|
+
name: Deploy to GitHub Pages
|
|
144
|
+
|
|
145
|
+
on:
|
|
146
|
+
push:
|
|
147
|
+
branches: [main]
|
|
148
|
+
|
|
149
|
+
jobs:
|
|
150
|
+
deploy:
|
|
151
|
+
runs-on: ubuntu-latest
|
|
152
|
+
permissions:
|
|
153
|
+
contents: write
|
|
154
|
+
steps:
|
|
155
|
+
- uses: actions/checkout@v4
|
|
156
|
+
|
|
157
|
+
- uses: pnpm/action-setup@v2
|
|
158
|
+
with:
|
|
159
|
+
version: 8
|
|
160
|
+
|
|
161
|
+
- uses: actions/setup-node@v4
|
|
162
|
+
with:
|
|
163
|
+
node-version: 20
|
|
164
|
+
cache: 'pnpm'
|
|
165
|
+
|
|
166
|
+
- run: pnpm install
|
|
167
|
+
- run: pnpm build
|
|
168
|
+
|
|
169
|
+
- name: Deploy
|
|
170
|
+
run: pnpm deploy
|
|
171
|
+
env:
|
|
172
|
+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
## License
|
|
176
|
+
|
|
177
|
+
GPL-2.0
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
// src/adapter.ts
|
|
2
|
+
import { spawnSync } from "child_process";
|
|
3
|
+
import { writeFileSync, existsSync, rmSync } from "fs";
|
|
4
|
+
import { join } from "path";
|
|
5
|
+
var GitHubPagesAdapter = class {
|
|
6
|
+
name = "github-pages";
|
|
7
|
+
description = "Deploy to GitHub Pages";
|
|
8
|
+
config;
|
|
9
|
+
constructor(config = {}) {
|
|
10
|
+
this.config = config;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Validate adapter configuration
|
|
14
|
+
*
|
|
15
|
+
* Checks:
|
|
16
|
+
* - git is available in PATH
|
|
17
|
+
* - Repository format is valid (if specified)
|
|
18
|
+
*/
|
|
19
|
+
async validate(adapterConfig) {
|
|
20
|
+
const errors = [];
|
|
21
|
+
const warnings = [];
|
|
22
|
+
const gitCheck = spawnSync("git", ["--version"], {
|
|
23
|
+
encoding: "utf-8",
|
|
24
|
+
timeout: 5e3
|
|
25
|
+
});
|
|
26
|
+
if (gitCheck.status !== 0) {
|
|
27
|
+
errors.push("git is not available in PATH");
|
|
28
|
+
}
|
|
29
|
+
const repo = adapterConfig.options.repo || this.config.repo;
|
|
30
|
+
if (repo) {
|
|
31
|
+
const repoPattern = /^[\w.-]+\/[\w.-]+$/;
|
|
32
|
+
if (!repoPattern.test(repo)) {
|
|
33
|
+
errors.push(
|
|
34
|
+
`Invalid repository format: "${repo}". Expected format: "user/repo" or "org/repo"`
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
const branch = adapterConfig.options.branch || this.config.branch || "gh-pages";
|
|
39
|
+
const branchPattern = /^[\w./-]+$/;
|
|
40
|
+
if (!branchPattern.test(branch)) {
|
|
41
|
+
errors.push(`Invalid branch name: "${branch}"`);
|
|
42
|
+
}
|
|
43
|
+
if (!repo) {
|
|
44
|
+
warnings.push(
|
|
45
|
+
"No repository specified. Will attempt to auto-detect from git remote."
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
return {
|
|
49
|
+
valid: errors.length === 0,
|
|
50
|
+
errors,
|
|
51
|
+
warnings
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Execute deployment to GitHub Pages
|
|
56
|
+
*
|
|
57
|
+
* Initializes a git repository in the output directory,
|
|
58
|
+
* adds all files, and force pushes to the gh-pages branch.
|
|
59
|
+
*/
|
|
60
|
+
async deploy(context) {
|
|
61
|
+
const { outDir, metadata, adapterConfig, dryRun, logger } = context;
|
|
62
|
+
const branch = adapterConfig.branch || this.config.branch || "gh-pages";
|
|
63
|
+
const cname = adapterConfig.cname ?? this.config.cname;
|
|
64
|
+
const noJekyll = adapterConfig.noJekyll ?? this.config.noJekyll ?? true;
|
|
65
|
+
const message = adapterConfig.message || this.config.message || "Deploy to GitHub Pages";
|
|
66
|
+
const remote = adapterConfig.remote || this.config.remote || "origin";
|
|
67
|
+
let repo = adapterConfig.repo || this.config.repo;
|
|
68
|
+
if (!repo) {
|
|
69
|
+
repo = this.autoDetectRepo();
|
|
70
|
+
if (!repo) {
|
|
71
|
+
return {
|
|
72
|
+
success: false,
|
|
73
|
+
error: "Could not auto-detect repository. Please specify repo in adapter config."
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
logger.info(`Auto-detected repository: ${repo}`);
|
|
77
|
+
}
|
|
78
|
+
logger.info(`Deploying to GitHub Pages: ${repo}`);
|
|
79
|
+
logger.info(`Branch: ${branch}`);
|
|
80
|
+
if (cname) {
|
|
81
|
+
logger.info(`Custom domain: ${cname}`);
|
|
82
|
+
}
|
|
83
|
+
if (dryRun) {
|
|
84
|
+
logger.info("Dry run mode - skipping actual deployment");
|
|
85
|
+
return {
|
|
86
|
+
success: true,
|
|
87
|
+
deploymentId: `dry-run-${Date.now()}`,
|
|
88
|
+
url: this.getPageUrl(repo, cname),
|
|
89
|
+
logs: ["Dry run completed successfully"]
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
try {
|
|
93
|
+
if (noJekyll) {
|
|
94
|
+
const nojekyllPath = join(outDir, ".nojekyll");
|
|
95
|
+
writeFileSync(nojekyllPath, "");
|
|
96
|
+
logger.debug("Added .nojekyll file");
|
|
97
|
+
}
|
|
98
|
+
if (cname) {
|
|
99
|
+
const cnamePath = join(outDir, "CNAME");
|
|
100
|
+
writeFileSync(cnamePath, cname);
|
|
101
|
+
logger.debug(`Added CNAME file: ${cname}`);
|
|
102
|
+
}
|
|
103
|
+
const gitDir = join(outDir, ".git");
|
|
104
|
+
if (existsSync(gitDir)) {
|
|
105
|
+
rmSync(gitDir, { recursive: true });
|
|
106
|
+
}
|
|
107
|
+
const initResult = this.runGit(["init"], outDir);
|
|
108
|
+
if (!initResult.success) {
|
|
109
|
+
return {
|
|
110
|
+
success: false,
|
|
111
|
+
error: `Failed to initialize git repository: ${initResult.error}`
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
logger.debug("Initialized git repository");
|
|
115
|
+
this.runGit(
|
|
116
|
+
["config", "user.email", "github-pages-deploy@org-press"],
|
|
117
|
+
outDir
|
|
118
|
+
);
|
|
119
|
+
this.runGit(["config", "user.name", "org-press deploy"], outDir);
|
|
120
|
+
const addResult = this.runGit(["add", "-A"], outDir);
|
|
121
|
+
if (!addResult.success) {
|
|
122
|
+
return {
|
|
123
|
+
success: false,
|
|
124
|
+
error: `Failed to add files: ${addResult.error}`
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
logger.debug("Added all files to git");
|
|
128
|
+
const commitResult = this.runGit(
|
|
129
|
+
["commit", "-m", message],
|
|
130
|
+
outDir
|
|
131
|
+
);
|
|
132
|
+
if (!commitResult.success) {
|
|
133
|
+
return {
|
|
134
|
+
success: false,
|
|
135
|
+
error: `Failed to create commit: ${commitResult.error}`
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
logger.debug("Created commit");
|
|
139
|
+
const remoteUrl = `https://github.com/${repo}.git`;
|
|
140
|
+
const remoteAddResult = this.runGit(
|
|
141
|
+
["remote", "add", remote, remoteUrl],
|
|
142
|
+
outDir
|
|
143
|
+
);
|
|
144
|
+
if (!remoteAddResult.success) {
|
|
145
|
+
this.runGit(["remote", "set-url", remote, remoteUrl], outDir);
|
|
146
|
+
}
|
|
147
|
+
logger.debug(`Set remote ${remote} to ${remoteUrl}`);
|
|
148
|
+
logger.info(`Pushing to ${remote}/${branch}...`);
|
|
149
|
+
const pushResult = this.runGit(
|
|
150
|
+
["push", "-f", remote, `HEAD:${branch}`],
|
|
151
|
+
outDir
|
|
152
|
+
);
|
|
153
|
+
if (!pushResult.success) {
|
|
154
|
+
return {
|
|
155
|
+
success: false,
|
|
156
|
+
error: `Failed to push to GitHub: ${pushResult.error}`,
|
|
157
|
+
logs: pushResult.output ? [pushResult.output] : void 0
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
logger.info("Successfully deployed to GitHub Pages!");
|
|
161
|
+
return {
|
|
162
|
+
success: true,
|
|
163
|
+
deploymentId: `${repo}@${branch}`,
|
|
164
|
+
url: this.getPageUrl(repo, cname),
|
|
165
|
+
logs: pushResult.output ? [pushResult.output] : void 0
|
|
166
|
+
};
|
|
167
|
+
} catch (err) {
|
|
168
|
+
const error = err instanceof Error ? err.message : String(err);
|
|
169
|
+
logger.error(`Deployment failed: ${error}`);
|
|
170
|
+
return {
|
|
171
|
+
success: false,
|
|
172
|
+
error: `Deployment failed: ${error}`
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* Auto-detect repository from git remote
|
|
178
|
+
*/
|
|
179
|
+
autoDetectRepo() {
|
|
180
|
+
const result = spawnSync("git", ["remote", "get-url", "origin"], {
|
|
181
|
+
encoding: "utf-8",
|
|
182
|
+
timeout: 5e3
|
|
183
|
+
});
|
|
184
|
+
if (result.status !== 0 || !result.stdout) {
|
|
185
|
+
return void 0;
|
|
186
|
+
}
|
|
187
|
+
const url = result.stdout.trim();
|
|
188
|
+
const httpsMatch = url.match(/github\.com[/:]([^/]+)\/([^/.]+)/);
|
|
189
|
+
if (httpsMatch) {
|
|
190
|
+
return `${httpsMatch[1]}/${httpsMatch[2]}`;
|
|
191
|
+
}
|
|
192
|
+
return void 0;
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* Get the GitHub Pages URL for the repository
|
|
196
|
+
*/
|
|
197
|
+
getPageUrl(repo, cname) {
|
|
198
|
+
if (cname) {
|
|
199
|
+
return `https://${cname}`;
|
|
200
|
+
}
|
|
201
|
+
const [user, repoName] = repo.split("/");
|
|
202
|
+
if (repoName === `${user}.github.io`) {
|
|
203
|
+
return `https://${user}.github.io`;
|
|
204
|
+
}
|
|
205
|
+
return `https://${user}.github.io/${repoName}`;
|
|
206
|
+
}
|
|
207
|
+
/**
|
|
208
|
+
* Run a git command and return the result
|
|
209
|
+
*/
|
|
210
|
+
runGit(args, cwd) {
|
|
211
|
+
const result = spawnSync("git", args, {
|
|
212
|
+
cwd,
|
|
213
|
+
encoding: "utf-8",
|
|
214
|
+
timeout: 6e4
|
|
215
|
+
});
|
|
216
|
+
if (result.status !== 0) {
|
|
217
|
+
return {
|
|
218
|
+
success: false,
|
|
219
|
+
output: result.stdout,
|
|
220
|
+
error: result.stderr || result.stdout || "Unknown git error"
|
|
221
|
+
};
|
|
222
|
+
}
|
|
223
|
+
return {
|
|
224
|
+
success: true,
|
|
225
|
+
output: result.stdout
|
|
226
|
+
};
|
|
227
|
+
}
|
|
228
|
+
};
|
|
229
|
+
function githubPagesAdapter(config = {}) {
|
|
230
|
+
return new GitHubPagesAdapter(config);
|
|
231
|
+
}
|
|
232
|
+
export {
|
|
233
|
+
GitHubPagesAdapter,
|
|
234
|
+
githubPagesAdapter
|
|
235
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@org-press/deploy-github-pages",
|
|
3
|
+
"version": "0.9.12",
|
|
4
|
+
"description": "GitHub Pages deploy adapter for org-press",
|
|
5
|
+
"license": "GPL-2.0",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": {
|
|
9
|
+
"types": "./dist/index.d.ts",
|
|
10
|
+
"import": "./dist/index.js"
|
|
11
|
+
}
|
|
12
|
+
},
|
|
13
|
+
"main": "./dist/index.js",
|
|
14
|
+
"types": "./dist/index.d.ts",
|
|
15
|
+
"files": [
|
|
16
|
+
"dist",
|
|
17
|
+
"src",
|
|
18
|
+
"README.md"
|
|
19
|
+
],
|
|
20
|
+
"peerDependencies": {
|
|
21
|
+
"@org-press/deploy": ">=0.9.0"
|
|
22
|
+
},
|
|
23
|
+
"devDependencies": {
|
|
24
|
+
"tsup": "^8.0.0",
|
|
25
|
+
"typescript": "~5.7.3",
|
|
26
|
+
"@types/node": "^20.0.0",
|
|
27
|
+
"vitest": "^3.1.4",
|
|
28
|
+
"@org-press/deploy": "0.9.12"
|
|
29
|
+
},
|
|
30
|
+
"publishConfig": {
|
|
31
|
+
"access": "public"
|
|
32
|
+
},
|
|
33
|
+
"homepage": "https://orgp.dev",
|
|
34
|
+
"repository": {
|
|
35
|
+
"type": "git",
|
|
36
|
+
"url": "https://github.com/org-press/org-press.git"
|
|
37
|
+
},
|
|
38
|
+
"bugs": {
|
|
39
|
+
"url": "https://github.com/org-press/org-press/issues"
|
|
40
|
+
},
|
|
41
|
+
"scripts": {
|
|
42
|
+
"build": "tsup",
|
|
43
|
+
"dev": "tsup --watch",
|
|
44
|
+
"test": "vitest",
|
|
45
|
+
"test:ci": "vitest --run",
|
|
46
|
+
"clean": "rm -rf dist"
|
|
47
|
+
}
|
|
48
|
+
}
|