@sstar/skill-install 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +296 -0
- package/dist/archive/archive-extractor.d.ts +29 -0
- package/dist/archive/archive-extractor.js +123 -0
- package/dist/auth/auth-service.d.ts +21 -0
- package/dist/auth/auth-service.js +260 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +459 -0
- package/dist/core/errors.d.ts +19 -0
- package/dist/core/errors.js +29 -0
- package/dist/core/logger.d.ts +14 -0
- package/dist/core/logger.js +68 -0
- package/dist/download/download-manager.d.ts +41 -0
- package/dist/download/download-manager.js +184 -0
- package/dist/downloader.d.ts +29 -0
- package/dist/downloader.js +163 -0
- package/dist/http/http-client.d.ts +25 -0
- package/dist/http/http-client.js +172 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +14 -0
- package/dist/installer/install-service.d.ts +40 -0
- package/dist/installer/install-service.js +184 -0
- package/dist/skills/skill-validator.d.ts +33 -0
- package/dist/skills/skill-validator.js +124 -0
- package/dist/skills/skills-manager.d.ts +54 -0
- package/dist/skills/skills-manager.js +127 -0
- package/dist/source/source-detector.d.ts +29 -0
- package/dist/source/source-detector.js +88 -0
- package/package.json +62 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 ekko.bao
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,296 @@
|
|
|
1
|
+
# Agent Skill Installer
|
|
2
|
+
|
|
3
|
+
A command-line tool for installing Agent Skills from various sources (public URLs, Wiki with authentication, or local archive files). Automatically downloads, extracts, validates, and installs skills for **Claude Code** or **Codex**.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **Multi-tool support**: Works with both Claude Code (`~/.claude/skills/`) and Codex (`~/.codex/skills/`)
|
|
8
|
+
- **Auto-detect source**: Automatically detects if the source is a public URL, Wiki URL (with auth), or local file
|
|
9
|
+
- **Multiple archive formats**: Supports `.zip` and `.tar.gz` archives
|
|
10
|
+
- **Strict validation**: Validates that archives contain a valid `SKILL.md` with required frontmatter
|
|
11
|
+
- **Wiki authentication**: Supports authentication with internal Confluence Wiki
|
|
12
|
+
- **Skill management**: List installed skills and uninstall them
|
|
13
|
+
- **Interactive prompts**: Choose between global/local directories and AI tools
|
|
14
|
+
- **Self-signed certificates**: Built-in support for corporate SSL certificates
|
|
15
|
+
|
|
16
|
+
## What are Skills?
|
|
17
|
+
|
|
18
|
+
Skills are a lightweight, open format for extending AI agent capabilities with specialized knowledge and workflows. At its core, a skill is a folder containing a `SKILL.md` file with metadata (`name` and `description`) and instructions.
|
|
19
|
+
|
|
20
|
+
Learn more at: https://agentskills.io/what-are-skills
|
|
21
|
+
|
|
22
|
+
## Installation
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
cd /home/ekko.bao/work/tools/wiki_download
|
|
26
|
+
npm install
|
|
27
|
+
npm run build
|
|
28
|
+
npm link # Optional: for global installation
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Usage
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
# Install with interactive AI tool and directory selection
|
|
35
|
+
skill-install install https://github.com/user/repo/archive/main.zip
|
|
36
|
+
|
|
37
|
+
# Install for specific AI tool (skip prompt)
|
|
38
|
+
skill-install -t claude install https://github.com/user/repo/archive/main.zip
|
|
39
|
+
skill-install -t codex install https://github.com/user/repo/archive/main.zip
|
|
40
|
+
|
|
41
|
+
# Install to global directory explicitly
|
|
42
|
+
skill-install install https://example.com/skill.zip --global
|
|
43
|
+
|
|
44
|
+
# Install to local directory explicitly
|
|
45
|
+
skill-install install https://example.com/skill.zip --local
|
|
46
|
+
|
|
47
|
+
# Install with custom directory
|
|
48
|
+
skill-install -s /path/to/skills install https://example.com/skill.zip
|
|
49
|
+
|
|
50
|
+
# Install from Wiki with authentication
|
|
51
|
+
skill-install install https://wiki.company.com/download/attachments/123/skill.zip -u username
|
|
52
|
+
|
|
53
|
+
# Install from a local archive file
|
|
54
|
+
skill-install install ./my-skill.zip
|
|
55
|
+
|
|
56
|
+
# List installed skills (prompts for AI tool)
|
|
57
|
+
skill-install list
|
|
58
|
+
|
|
59
|
+
# List installed skills for specific AI tool (skip prompt)
|
|
60
|
+
skill-install -t claude list
|
|
61
|
+
skill-install -t codex list
|
|
62
|
+
|
|
63
|
+
# List skills from both global and local directories
|
|
64
|
+
skill-install list --all
|
|
65
|
+
|
|
66
|
+
# Uninstall a skill (prompts for AI tool)
|
|
67
|
+
skill-install uninstall my-skill
|
|
68
|
+
|
|
69
|
+
# Uninstall from specific AI tool (skip prompt)
|
|
70
|
+
skill-install -t claude uninstall my-skill
|
|
71
|
+
skill-install -t codex uninstall my-skill
|
|
72
|
+
|
|
73
|
+
# Force reinstall if skill already exists
|
|
74
|
+
skill-install install ./my-skill.zip --force
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## Options
|
|
78
|
+
|
|
79
|
+
### Global Options
|
|
80
|
+
| Option | Description |
|
|
81
|
+
|--------|-------------|
|
|
82
|
+
| `-t, --tool <tool>` | AI tool: `claude` or `codex` (skip prompt if specified) |
|
|
83
|
+
| `-s, --skills-dir <path>` | Custom skills directory |
|
|
84
|
+
| `-v, --verbose` | Enable verbose logging |
|
|
85
|
+
| `-h, --help` | Display help |
|
|
86
|
+
|
|
87
|
+
**Note**: If `-t` is not specified, the tool will prompt interactively to choose between Claude Code and Codex.
|
|
88
|
+
|
|
89
|
+
### Install Command
|
|
90
|
+
| Option | Description |
|
|
91
|
+
|--------|-------------|
|
|
92
|
+
| `<source>` | URL or local file path to skill archive |
|
|
93
|
+
| `-g, --global` | Install to global directory (`~/.claude/skills/` or `~/.codex/skills/`) |
|
|
94
|
+
| `-l, --local` | Install to local directory (`./.claude/skills/` or `./.codex/skills/`) |
|
|
95
|
+
| `-u, --username <username>` | Wiki username (for Wiki URLs) |
|
|
96
|
+
| `-p, --password <password>` | Wiki password (or use env var) |
|
|
97
|
+
| `--allow-self-signed` | Allow self-signed SSL certificates (default: true) |
|
|
98
|
+
| `-f, --force` | Reinstall if skill already exists |
|
|
99
|
+
|
|
100
|
+
**Note**: If neither `-g` nor `-l` nor `-s` is specified, the tool will prompt interactively to choose between global and local directories.
|
|
101
|
+
|
|
102
|
+
### List Command
|
|
103
|
+
| Option | Description |
|
|
104
|
+
|--------|-------------|
|
|
105
|
+
| `-a, --all` | List skills from both global and local directories |
|
|
106
|
+
|
|
107
|
+
### Uninstall Command
|
|
108
|
+
| Option | Description |
|
|
109
|
+
|--------|-------------|
|
|
110
|
+
| `[name]` | Name of the skill to uninstall (optional - leave empty to select from list) |
|
|
111
|
+
| `-y, --yes` | Skip confirmation prompt |
|
|
112
|
+
|
|
113
|
+
**Note**: If no skill name is provided, the tool will display all installed skills and allow you to select which ones to uninstall by entering numbers separated by spaces (e.g., `1 3 5`).
|
|
114
|
+
|
|
115
|
+
## Environment Variables
|
|
116
|
+
|
|
117
|
+
| Variable | Description |
|
|
118
|
+
|----------|-------------|
|
|
119
|
+
| `WIKI_USERNAME` | Default Wiki username |
|
|
120
|
+
| `WIKI_PASSWORD` | Default Wiki password |
|
|
121
|
+
|
|
122
|
+
## Skill Validation
|
|
123
|
+
|
|
124
|
+
A valid skill must have a `SKILL.md` file at the root with YAML frontmatter containing:
|
|
125
|
+
|
|
126
|
+
```yaml
|
|
127
|
+
---
|
|
128
|
+
name: my-skill
|
|
129
|
+
description: A brief description of what this skill does
|
|
130
|
+
---
|
|
131
|
+
|
|
132
|
+
# My Skill
|
|
133
|
+
|
|
134
|
+
Instructions for the agent...
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
The tool validates:
|
|
138
|
+
- `SKILL.md` exists
|
|
139
|
+
- YAML frontmatter is present (wrapped in `---`)
|
|
140
|
+
- `name` field is present
|
|
141
|
+
- `description` field is present
|
|
142
|
+
|
|
143
|
+
## Skill Directory Structure
|
|
144
|
+
|
|
145
|
+
Skills can be installed to different locations based on the AI tool:
|
|
146
|
+
|
|
147
|
+
### Claude Code
|
|
148
|
+
- **Global**: `~/.claude/skills/` - Available to all projects
|
|
149
|
+
- **Local**: `./.claude/skills/` - Project-specific
|
|
150
|
+
|
|
151
|
+
### Codex
|
|
152
|
+
- **Global**: `~/.codex/skills/` - Available to all projects
|
|
153
|
+
- **Local**: `./.codex/skills/` - Project-specific
|
|
154
|
+
|
|
155
|
+
### Directory Selection
|
|
156
|
+
- **Global**: Use `--global` flag or select "1" when prompted (recommended for commonly used skills)
|
|
157
|
+
- **Local**: Use `--local` flag or select "2" when prompted (recommended for project-specific skills)
|
|
158
|
+
- **Custom**: Use `-s /path/to/skills` for a custom location
|
|
159
|
+
|
|
160
|
+
A typical installed skill:
|
|
161
|
+
|
|
162
|
+
```
|
|
163
|
+
~/.claude/skills/my-skill/
|
|
164
|
+
├── SKILL.md # Required: instructions + metadata
|
|
165
|
+
├── scripts/ # Optional: executable code
|
|
166
|
+
├── references/ # Optional: documentation
|
|
167
|
+
└── assets/ # Optional: templates, resources
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
## Examples
|
|
171
|
+
|
|
172
|
+
### Interactive installation (prompts for AI tool and directory)
|
|
173
|
+
|
|
174
|
+
```bash
|
|
175
|
+
skill-install install https://github.com/user/repo/archive/main.zip
|
|
176
|
+
|
|
177
|
+
# Output:
|
|
178
|
+
# Select AI tool:
|
|
179
|
+
# 1. Claude Code (~/.claude/skills/)
|
|
180
|
+
# 2. Codex (~/.codex/skills/)
|
|
181
|
+
#
|
|
182
|
+
# Choose [1/2]: 1
|
|
183
|
+
#
|
|
184
|
+
# Select installation directory:
|
|
185
|
+
# 1. Global: /home/user/.claude/skills
|
|
186
|
+
# 2. Local: /home/user/project/.claude/skills
|
|
187
|
+
#
|
|
188
|
+
# Choose [1/2]: 1
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
### Install for specific AI tool (skip prompt)
|
|
192
|
+
|
|
193
|
+
```bash
|
|
194
|
+
# Install for Claude Code
|
|
195
|
+
skill-install -t claude install https://example.com/skill.zip
|
|
196
|
+
|
|
197
|
+
# Install for Codex
|
|
198
|
+
skill-install -t codex install https://example.com/skill.zip
|
|
199
|
+
|
|
200
|
+
# Install to Codex global directory
|
|
201
|
+
skill-install -t codex install https://example.com/skill.zip --global
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
### Install to specific directory
|
|
205
|
+
|
|
206
|
+
```bash
|
|
207
|
+
# Install to global directory
|
|
208
|
+
skill-install install https://example.com/skill.zip --global
|
|
209
|
+
|
|
210
|
+
# Install to local directory
|
|
211
|
+
skill-install install https://example.com/skill.zip --local
|
|
212
|
+
|
|
213
|
+
# Install to custom directory
|
|
214
|
+
skill-install -s /custom/path install https://example.com/skill.zip
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
### Install from Wiki
|
|
218
|
+
|
|
219
|
+
```bash
|
|
220
|
+
skill-install install "https://wiki.company.com/download/attachments/12345/skill.zip?api=v2" -u john.doe
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
### Install from local file
|
|
224
|
+
|
|
225
|
+
```bash
|
|
226
|
+
skill-install install ~/Downloads/my-skill.tar.gz
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
### List and uninstall
|
|
230
|
+
|
|
231
|
+
```bash
|
|
232
|
+
# List skills (prompts for AI tool)
|
|
233
|
+
skill-install list
|
|
234
|
+
|
|
235
|
+
# List skills for specific AI tool (skip prompt)
|
|
236
|
+
skill-install -t claude list
|
|
237
|
+
skill-install -t codex list
|
|
238
|
+
|
|
239
|
+
# List skills from both directories
|
|
240
|
+
skill-install -t claude list --all
|
|
241
|
+
|
|
242
|
+
# Uninstall a specific skill (prompts for AI tool)
|
|
243
|
+
skill-install uninstall my-skill
|
|
244
|
+
|
|
245
|
+
# Uninstall without prompts (specify AI tool and skip confirmation)
|
|
246
|
+
skill-install -t codex uninstall my-skill -y
|
|
247
|
+
|
|
248
|
+
# Interactive uninstall (select from list)
|
|
249
|
+
skill-install uninstall
|
|
250
|
+
|
|
251
|
+
# Output:
|
|
252
|
+
# Select AI tool:
|
|
253
|
+
# 1. Claude Code (~/.claude/skills/)
|
|
254
|
+
# 2. Codex (~/.codex/skills/)
|
|
255
|
+
#
|
|
256
|
+
# Choose [1/2]: 1
|
|
257
|
+
#
|
|
258
|
+
# Installed skills:
|
|
259
|
+
#
|
|
260
|
+
# [1] repo-git
|
|
261
|
+
# Provides multi-repository version control capabilities.
|
|
262
|
+
#
|
|
263
|
+
# [2] pdf-processing
|
|
264
|
+
# Extract text and tables from PDF files.
|
|
265
|
+
#
|
|
266
|
+
# Enter the numbers of the skills to uninstall (separated by spaces, e.g., "1 3 5"):
|
|
267
|
+
# Press Enter to cancel:
|
|
268
|
+
# Your choice: 1 2
|
|
269
|
+
#
|
|
270
|
+
# Selected skills: repo-git, pdf-processing
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
## Project Structure
|
|
274
|
+
|
|
275
|
+
```
|
|
276
|
+
src/
|
|
277
|
+
├── cli.ts # CLI entry point
|
|
278
|
+
├── installer/
|
|
279
|
+
│ └── install-service.ts # Core installation logic
|
|
280
|
+
├── download/
|
|
281
|
+
│ └── download-manager.ts # Download manager (wiki + public)
|
|
282
|
+
├── archive/
|
|
283
|
+
│ └── archive-extractor.ts # Archive extraction (ZIP, tar.gz)
|
|
284
|
+
├── source/
|
|
285
|
+
│ └── source-detector.ts # Source type detection
|
|
286
|
+
├── skills/
|
|
287
|
+
│ ├── skills-manager.ts # List/uninstall operations
|
|
288
|
+
│ └── skill-validator.ts # SKILL.md validation
|
|
289
|
+
├── auth/ # Wiki authentication
|
|
290
|
+
├── http/ # HTTP client with cookies
|
|
291
|
+
└── core/ # Error handling & logging
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
## License
|
|
295
|
+
|
|
296
|
+
MIT
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
export type ArchiveType = 'zip' | 'tar' | 'tar.gz' | 'tgz' | 'unknown';
|
|
2
|
+
export declare class ArchiveExtractor {
|
|
3
|
+
private readonly logger;
|
|
4
|
+
/**
|
|
5
|
+
* Detect the archive type from a filename
|
|
6
|
+
*/
|
|
7
|
+
detectArchiveType(filename: string): ArchiveType;
|
|
8
|
+
/**
|
|
9
|
+
* Extract an archive to a directory
|
|
10
|
+
* @param archivePath Path to the archive file
|
|
11
|
+
* @param targetDir Directory to extract to
|
|
12
|
+
* @throws WikiError if extraction fails
|
|
13
|
+
*/
|
|
14
|
+
extract(archivePath: string, targetDir: string): Promise<void>;
|
|
15
|
+
/**
|
|
16
|
+
* Extract a ZIP archive
|
|
17
|
+
*/
|
|
18
|
+
private extractZip;
|
|
19
|
+
/**
|
|
20
|
+
* Extract a tar/tar.gz archive
|
|
21
|
+
*/
|
|
22
|
+
private extractTar;
|
|
23
|
+
/**
|
|
24
|
+
* Get the root directory name from an archive
|
|
25
|
+
* Useful for detecting if the archive contains a single root directory
|
|
26
|
+
*/
|
|
27
|
+
getRootDirectoryName(archivePath: string): Promise<string | null>;
|
|
28
|
+
private getZipRootDir;
|
|
29
|
+
}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.ArchiveExtractor = void 0;
|
|
7
|
+
const promises_1 = require("fs/promises");
|
|
8
|
+
const path_1 = require("path");
|
|
9
|
+
const tar_1 = require("tar");
|
|
10
|
+
const adm_zip_1 = __importDefault(require("adm-zip"));
|
|
11
|
+
const logger_1 = require("../core/logger");
|
|
12
|
+
const errors_1 = require("../core/errors");
|
|
13
|
+
class ArchiveExtractor {
|
|
14
|
+
constructor() {
|
|
15
|
+
this.logger = new logger_1.Logger('ArchiveExtractor');
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Detect the archive type from a filename
|
|
19
|
+
*/
|
|
20
|
+
detectArchiveType(filename) {
|
|
21
|
+
const ext = (0, path_1.extname)(filename).toLowerCase();
|
|
22
|
+
const base = (0, path_1.basename)(filename, ext).toLowerCase();
|
|
23
|
+
// Check for compound extensions
|
|
24
|
+
if (filename.toLowerCase().endsWith('.tar.gz') || filename.toLowerCase().endsWith('.tgz')) {
|
|
25
|
+
return 'tar.gz';
|
|
26
|
+
}
|
|
27
|
+
if (ext === '.zip') {
|
|
28
|
+
return 'zip';
|
|
29
|
+
}
|
|
30
|
+
if (ext === '.tar' || base.endsWith('.tar')) {
|
|
31
|
+
return 'tar';
|
|
32
|
+
}
|
|
33
|
+
return 'unknown';
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Extract an archive to a directory
|
|
37
|
+
* @param archivePath Path to the archive file
|
|
38
|
+
* @param targetDir Directory to extract to
|
|
39
|
+
* @throws WikiError if extraction fails
|
|
40
|
+
*/
|
|
41
|
+
async extract(archivePath, targetDir) {
|
|
42
|
+
const archiveType = this.detectArchiveType(archivePath);
|
|
43
|
+
this.logger.info(`Extracting ${archiveType} archive: ${archivePath} -> ${targetDir}`);
|
|
44
|
+
switch (archiveType) {
|
|
45
|
+
case 'zip':
|
|
46
|
+
await this.extractZip(archivePath, targetDir);
|
|
47
|
+
break;
|
|
48
|
+
case 'tar':
|
|
49
|
+
case 'tar.gz':
|
|
50
|
+
case 'tgz':
|
|
51
|
+
await this.extractTar(archivePath, targetDir);
|
|
52
|
+
break;
|
|
53
|
+
default:
|
|
54
|
+
throw new errors_1.WikiError(errors_1.ErrorType.EXTRACTION_FAILED, `Unknown archive type: ${archivePath}. Supported formats: .zip, .tar, .tar.gz`);
|
|
55
|
+
}
|
|
56
|
+
this.logger.info(`Extraction complete: ${targetDir}`);
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Extract a ZIP archive
|
|
60
|
+
*/
|
|
61
|
+
async extractZip(archivePath, targetDir) {
|
|
62
|
+
try {
|
|
63
|
+
const zip = new adm_zip_1.default(archivePath);
|
|
64
|
+
zip.extractAllTo(targetDir, true);
|
|
65
|
+
}
|
|
66
|
+
catch (error) {
|
|
67
|
+
throw new errors_1.WikiError(errors_1.ErrorType.EXTRACTION_FAILED, `Failed to extract ZIP archive: ${archivePath}`, error);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Extract a tar/tar.gz archive
|
|
72
|
+
*/
|
|
73
|
+
async extractTar(archivePath, targetDir) {
|
|
74
|
+
try {
|
|
75
|
+
await (0, promises_1.mkdir)(targetDir, { recursive: true });
|
|
76
|
+
await (0, tar_1.extract)({
|
|
77
|
+
file: archivePath,
|
|
78
|
+
cwd: targetDir,
|
|
79
|
+
strip: 1 // Strip the root directory if present
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
catch (error) {
|
|
83
|
+
throw new errors_1.WikiError(errors_1.ErrorType.EXTRACTION_FAILED, `Failed to extract tar archive: ${archivePath}`, error);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Get the root directory name from an archive
|
|
88
|
+
* Useful for detecting if the archive contains a single root directory
|
|
89
|
+
*/
|
|
90
|
+
async getRootDirectoryName(archivePath) {
|
|
91
|
+
const archiveType = this.detectArchiveType(archivePath);
|
|
92
|
+
if (archiveType === 'zip') {
|
|
93
|
+
return this.getZipRootDir(archivePath);
|
|
94
|
+
}
|
|
95
|
+
if (archiveType === 'tar' || archiveType === 'tar.gz' || archiveType === 'tgz') {
|
|
96
|
+
// For tar archives, we'll just return null and let the extraction handle it
|
|
97
|
+
return null;
|
|
98
|
+
}
|
|
99
|
+
return null;
|
|
100
|
+
}
|
|
101
|
+
getZipRootDir(archivePath) {
|
|
102
|
+
try {
|
|
103
|
+
const zip = new adm_zip_1.default(archivePath);
|
|
104
|
+
const entries = zip.getEntries();
|
|
105
|
+
if (entries.length === 0) {
|
|
106
|
+
return null;
|
|
107
|
+
}
|
|
108
|
+
// Get the first entry's path
|
|
109
|
+
const firstEntry = entries[0].entryName;
|
|
110
|
+
// Check if all entries share a common root directory
|
|
111
|
+
const parts = firstEntry.split('/');
|
|
112
|
+
if (parts.length > 1) {
|
|
113
|
+
return parts[0];
|
|
114
|
+
}
|
|
115
|
+
return null;
|
|
116
|
+
}
|
|
117
|
+
catch (error) {
|
|
118
|
+
this.logger.warn(`Failed to determine root directory: ${error}`);
|
|
119
|
+
return null;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
exports.ArchiveExtractor = ArchiveExtractor;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { HttpClient } from '../http/http-client';
|
|
2
|
+
export interface AuthConfig {
|
|
3
|
+
baseUrl: string;
|
|
4
|
+
username: string;
|
|
5
|
+
password: string;
|
|
6
|
+
}
|
|
7
|
+
export declare class AuthService {
|
|
8
|
+
private readonly http;
|
|
9
|
+
private readonly config;
|
|
10
|
+
private readonly logger;
|
|
11
|
+
private session;
|
|
12
|
+
private authInFlight;
|
|
13
|
+
constructor(http: HttpClient, config: AuthConfig);
|
|
14
|
+
ensureAuthenticated(): Promise<void>;
|
|
15
|
+
private authenticate;
|
|
16
|
+
private getLoginFormData;
|
|
17
|
+
private performLogin;
|
|
18
|
+
private checkLoginSuccess;
|
|
19
|
+
private isSessionValid;
|
|
20
|
+
clearSession(): void;
|
|
21
|
+
}
|