@uipath/solutionpackager-tool-core 0.0.26
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +308 -0
- package/dist/filesystem/file-system.d.ts +1 -0
- package/dist/filesystem/file-system.js +0 -0
- package/dist/filesystem/index.d.ts +5 -0
- package/dist/filesystem/index.js +3 -0
- package/dist/filesystem/path.d.ts +53 -0
- package/dist/filesystem/path.js +47 -0
- package/dist/filesystem/temporary-storage-service.d.ts +31 -0
- package/dist/filesystem/temporary-storage-service.js +46 -0
- package/dist/filesystem/zip-service.d.ts +25 -0
- package/dist/filesystem/zip-service.js +41 -0
- package/dist/i18n/i18n-manager.d.ts +128 -0
- package/dist/i18n/i18n-manager.js +104 -0
- package/dist/i18n/index.d.ts +15 -0
- package/dist/i18n/index.js +34 -0
- package/dist/i18n/locales/de.d.ts +37 -0
- package/dist/i18n/locales/de.js +38 -0
- package/dist/i18n/locales/en.d.ts +43 -0
- package/dist/i18n/locales/en.js +38 -0
- package/dist/i18n/locales/es-MX.d.ts +37 -0
- package/dist/i18n/locales/es-MX.js +38 -0
- package/dist/i18n/locales/es.d.ts +37 -0
- package/dist/i18n/locales/es.js +38 -0
- package/dist/i18n/locales/fr.d.ts +37 -0
- package/dist/i18n/locales/fr.js +38 -0
- package/dist/i18n/locales/ja.d.ts +37 -0
- package/dist/i18n/locales/ja.js +38 -0
- package/dist/i18n/locales/ko.d.ts +37 -0
- package/dist/i18n/locales/ko.js +38 -0
- package/dist/i18n/locales/pt-BR.d.ts +37 -0
- package/dist/i18n/locales/pt-BR.js +38 -0
- package/dist/i18n/locales/pt.d.ts +37 -0
- package/dist/i18n/locales/pt.js +38 -0
- package/dist/i18n/locales/ro.d.ts +37 -0
- package/dist/i18n/locales/ro.js +38 -0
- package/dist/i18n/locales/ru.d.ts +37 -0
- package/dist/i18n/locales/ru.js +38 -0
- package/dist/i18n/locales/tr.d.ts +37 -0
- package/dist/i18n/locales/tr.js +38 -0
- package/dist/i18n/locales/zh-CN.d.ts +37 -0
- package/dist/i18n/locales/zh-CN.js +38 -0
- package/dist/i18n/locales/zh-TW.d.ts +37 -0
- package/dist/i18n/locales/zh-TW.js +38 -0
- package/dist/i18n/locales/zu.d.ts +37 -0
- package/dist/i18n/locales/zu.js +38 -0
- package/dist/i18n/translation-service.d.ts +61 -0
- package/dist/i18n/translation-service.js +29 -0
- package/dist/i18n/types.d.ts +61 -0
- package/dist/i18n/types.js +20 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +5 -0
- package/dist/models/build-configuration.d.ts +7 -0
- package/dist/models/build-configuration.js +6 -0
- package/dist/models/connection-info.d.ts +26 -0
- package/dist/models/connection-info.js +9 -0
- package/dist/models/index.d.ts +18 -0
- package/dist/models/index.js +8 -0
- package/dist/models/log-message.d.ts +28 -0
- package/dist/models/log-message.js +48 -0
- package/dist/models/nuget-constants.d.ts +34 -0
- package/dist/models/nuget-constants.js +10 -0
- package/dist/models/nuget-feed-model.d.ts +25 -0
- package/dist/models/nuget-feed-model.js +0 -0
- package/dist/models/nuget-package-info.d.ts +63 -0
- package/dist/models/nuget-package-info.js +0 -0
- package/dist/models/package-info.d.ts +29 -0
- package/dist/models/package-info.js +0 -0
- package/dist/models/project-options.d.ts +126 -0
- package/dist/models/project-options.js +7 -0
- package/dist/models/project-type.d.ts +21 -0
- package/dist/models/project-type.js +16 -0
- package/dist/models/solution-options.d.ts +72 -0
- package/dist/models/solution-options.js +0 -0
- package/dist/models/target-frameworks.d.ts +7 -0
- package/dist/models/target-frameworks.js +6 -0
- package/dist/models/tool-error-code.d.ts +18 -0
- package/dist/models/tool-error-code.js +7 -0
- package/dist/models/tool-result.d.ts +31 -0
- package/dist/models/tool-result.js +21 -0
- package/dist/models/uipath-project.d.ts +26 -0
- package/dist/models/uipath-project.js +0 -0
- package/dist/models/uipath-solution.d.ts +14 -0
- package/dist/models/uipath-solution.js +0 -0
- package/dist/package-descriptor/entry-points-file-model.d.ts +26 -0
- package/dist/package-descriptor/entry-points-file-model.js +0 -0
- package/dist/package-descriptor/index.d.ts +5 -0
- package/dist/package-descriptor/index.js +1 -0
- package/dist/package-descriptor/operate-file-model.d.ts +38 -0
- package/dist/package-descriptor/operate-file-model.js +0 -0
- package/dist/package-descriptor/package-descriptor-file-model.d.ts +12 -0
- package/dist/package-descriptor/package-descriptor-file-model.js +0 -0
- package/dist/package-descriptor/project-bindings-file-model.d.ts +82 -0
- package/dist/package-descriptor/project-bindings-file-model.js +7 -0
- package/dist/services/index.d.ts +10 -0
- package/dist/services/index.js +4 -0
- package/dist/services/nuget-packager.d.ts +39 -0
- package/dist/services/nuget-packager.js +105 -0
- package/dist/services/project-operation-context.d.ts +37 -0
- package/dist/services/project-operation-context.js +0 -0
- package/dist/services/project-tool-factory.d.ts +21 -0
- package/dist/services/project-tool-factory.js +0 -0
- package/dist/services/project-tool.d.ts +32 -0
- package/dist/services/project-tool.js +27 -0
- package/dist/services/solution-tool-factory.d.ts +14 -0
- package/dist/services/solution-tool-factory.js +0 -0
- package/dist/services/solution-tool.d.ts +32 -0
- package/dist/services/solution-tool.js +27 -0
- package/dist/services/tool-logger.d.ts +44 -0
- package/dist/services/tool-logger.js +0 -0
- package/dist/services/tools-factory-repository.d.ts +84 -0
- package/dist/services/tools-factory-repository.js +34 -0
- package/package.json +45 -0
package/README.md
ADDED
|
@@ -0,0 +1,308 @@
|
|
|
1
|
+
# UiPath Solution Packager Tool Core
|
|
2
|
+
|
|
3
|
+
Core contracts and interfaces for building UiPath Solution Packager tools. This package provides the type definitions and base classes for creating tools that restore, validate, build, and pack UiPath projects and solutions.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
### From GitHub Packages
|
|
8
|
+
|
|
9
|
+
#### Prerequisites
|
|
10
|
+
|
|
11
|
+
Create a GitHub Personal Access Token with `read:packages` permission:
|
|
12
|
+
|
|
13
|
+
1. Go to GitHub → Settings → Developer settings → Personal access tokens → Tokens (classic)
|
|
14
|
+
2. Generate new token with `read:packages` scope
|
|
15
|
+
3. Set as environment variable:
|
|
16
|
+
|
|
17
|
+
**Windows (PowerShell):**
|
|
18
|
+
|
|
19
|
+
```powershell
|
|
20
|
+
$env:GH_NPM_REGISTRY_TOKEN = "your-token-here"
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
**Linux/macOS:**
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
export GH_NPM_REGISTRY_TOKEN="your-token-here"
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
#### Install
|
|
30
|
+
|
|
31
|
+
Create `.npmrc` in your project root:
|
|
32
|
+
|
|
33
|
+
```text
|
|
34
|
+
@uipath:registry=https://npm.pkg.github.com/
|
|
35
|
+
//npm.pkg.github.com/:_authToken=${GH_NPM_REGISTRY_TOKEN}
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Then install:
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
npm install @uipath/solutionpackager-tool-core
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## Quick Start
|
|
45
|
+
|
|
46
|
+
### 1. Implement a Project Tool
|
|
47
|
+
|
|
48
|
+
Extend `ProjectTool` and override the operations you need:
|
|
49
|
+
|
|
50
|
+
```typescript
|
|
51
|
+
import {
|
|
52
|
+
ProjectTool,
|
|
53
|
+
type IProjectBuildOptions,
|
|
54
|
+
type IProjectRestoreOptions,
|
|
55
|
+
ToolResult,
|
|
56
|
+
type IToolLogger,
|
|
57
|
+
type IFileSystem,
|
|
58
|
+
Path,
|
|
59
|
+
} from "@uipath/solutionpackager-tool-core";
|
|
60
|
+
|
|
61
|
+
export class ApiWorkflowsTool extends ProjectTool {
|
|
62
|
+
constructor(fileSystem: IFileSystem, logger: IToolLogger) {
|
|
63
|
+
super(fileSystem, logger);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
override async restoreAsync(
|
|
67
|
+
options: IProjectRestoreOptions,
|
|
68
|
+
cancellationToken?: AbortSignal
|
|
69
|
+
): Promise<ToolResult> {
|
|
70
|
+
this.logger.info("Restoring dependencies...");
|
|
71
|
+
return ToolResult.success();
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
override async buildAsync(
|
|
75
|
+
options: IProjectBuildOptions,
|
|
76
|
+
cancellationToken?: AbortSignal
|
|
77
|
+
): Promise<ToolResult> {
|
|
78
|
+
this.logger.info("Building project...");
|
|
79
|
+
const outputFolder = Path.join(options.outputPath, "output");
|
|
80
|
+
|
|
81
|
+
await this.fileSystem.mkdir(outputFolder);
|
|
82
|
+
await this.fileSystem.writeFile(
|
|
83
|
+
Path.join(outputFolder, "artifact.txt"),
|
|
84
|
+
"Build Artifact"
|
|
85
|
+
);
|
|
86
|
+
|
|
87
|
+
return new ToolResult(ToolErrorCodes.Success, "Build completed", [outputFolder]);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
override async dispose(): Promise<void> {
|
|
91
|
+
// Cleanup resources
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
### 2. Create a Tool Factory
|
|
97
|
+
|
|
98
|
+
Implement `IProjectToolFactory`:
|
|
99
|
+
|
|
100
|
+
```typescript
|
|
101
|
+
import {
|
|
102
|
+
type IProjectToolFactory,
|
|
103
|
+
type ProjectTool,
|
|
104
|
+
ProjectTypes,
|
|
105
|
+
type ProjectType,
|
|
106
|
+
type IToolLogger,
|
|
107
|
+
type IFileSystem,
|
|
108
|
+
} from "@uipath/solutionpackager-tool-core";
|
|
109
|
+
|
|
110
|
+
export class ApiWorkflowToolFactory implements IProjectToolFactory {
|
|
111
|
+
readonly supportedTypes: readonly ProjectType[] = [ProjectTypes.Api];
|
|
112
|
+
|
|
113
|
+
constructor(private readonly fileSystem: IFileSystem) {}
|
|
114
|
+
|
|
115
|
+
async createAsync(logger: IToolLogger): Promise<ProjectTool> {
|
|
116
|
+
return new ApiWorkflowsTool(this.fileSystem, logger);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
### 3. Register Your Tool
|
|
122
|
+
|
|
123
|
+
Register with the SolutionPackager instance:
|
|
124
|
+
|
|
125
|
+
```typescript
|
|
126
|
+
import type { IToolsFactoryRepositoryConfigurator } from "@uipath/solutionpackager-tool-core";
|
|
127
|
+
|
|
128
|
+
export function registerProjectToolFactory(
|
|
129
|
+
configurator: IToolsFactoryRepositoryConfigurator,
|
|
130
|
+
fileSystem: IFileSystem
|
|
131
|
+
): void {
|
|
132
|
+
configurator.registerProjectToolFactory(
|
|
133
|
+
new ApiWorkflowToolFactory(fileSystem)
|
|
134
|
+
);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// Usage:
|
|
138
|
+
// const solutionPackager = await createBrowserSolutionPackager();
|
|
139
|
+
// registerApiWorkflowTool(solutionPackager, solutionPackager.fileSystem);
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
## Core Concepts
|
|
143
|
+
|
|
144
|
+
### Tool Base Classes
|
|
145
|
+
|
|
146
|
+
**ProjectTool** - Override operations your tool supports:
|
|
147
|
+
|
|
148
|
+
- `restoreAsync()` - Restore dependencies
|
|
149
|
+
- `validateAsync()` - Validate project
|
|
150
|
+
- `buildAsync()` - Build/compile
|
|
151
|
+
- `packAsync()` - Package project
|
|
152
|
+
- `dispose()` - Cleanup
|
|
153
|
+
|
|
154
|
+
**SolutionTool** - Similar to ProjectTool but operates at solution level.
|
|
155
|
+
|
|
156
|
+
### Logging
|
|
157
|
+
|
|
158
|
+
Access logger via `this.logger`:
|
|
159
|
+
|
|
160
|
+
```typescript
|
|
161
|
+
this.logger.info("Starting build");
|
|
162
|
+
this.logger.progress("Building", 50);
|
|
163
|
+
this.logger.warn("Deprecated API");
|
|
164
|
+
this.logger.error("Build failed", { code: "BUILD_001" });
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
### File System
|
|
168
|
+
|
|
169
|
+
Access via `this.fileSystem` with consistent API across Node.js and Browser:
|
|
170
|
+
|
|
171
|
+
```typescript
|
|
172
|
+
// Read file
|
|
173
|
+
const content = await this.fileSystem.readFile("path/to/file.json");
|
|
174
|
+
|
|
175
|
+
// Write file
|
|
176
|
+
await this.fileSystem.writeFile("output/config.xml", "<config></config>");
|
|
177
|
+
|
|
178
|
+
// Create directory (recursive)
|
|
179
|
+
await this.fileSystem.mkdir("dist/assets/images");
|
|
180
|
+
|
|
181
|
+
// Check existence
|
|
182
|
+
if (await this.fileSystem.exists("entrypoints.json")) { }
|
|
183
|
+
|
|
184
|
+
// List directory
|
|
185
|
+
const files = await this.fileSystem.readdir("src/components");
|
|
186
|
+
|
|
187
|
+
// Delete (recursive for directories)
|
|
188
|
+
await this.fileSystem.rm("temp_build");
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
### Tool Results
|
|
192
|
+
|
|
193
|
+
```typescript
|
|
194
|
+
// Success
|
|
195
|
+
return ToolResult.success();
|
|
196
|
+
|
|
197
|
+
// Error with code and message
|
|
198
|
+
return ToolResult.error(ToolErrorCodes.InternalError, "Syntax error");
|
|
199
|
+
|
|
200
|
+
// With package paths
|
|
201
|
+
return new ToolResult(ToolErrorCodes.Success, "done", [packagePath]);
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
## Built-in Types
|
|
205
|
+
|
|
206
|
+
### Project Types
|
|
207
|
+
|
|
208
|
+
- `ProjectTypes.Agent`
|
|
209
|
+
- `ProjectTypes.Api`
|
|
210
|
+
- `ProjectTypes.Connector`
|
|
211
|
+
- `ProjectTypes.Process`
|
|
212
|
+
- `ProjectTypes.Library`
|
|
213
|
+
- `ProjectTypes.WebApp`
|
|
214
|
+
- `ProjectTypes.Tests`
|
|
215
|
+
|
|
216
|
+
### Error Codes
|
|
217
|
+
|
|
218
|
+
- `ToolErrorCodes.Success`
|
|
219
|
+
- `ToolErrorCodes.InternalError`
|
|
220
|
+
|
|
221
|
+
Extend with custom codes:
|
|
222
|
+
|
|
223
|
+
```typescript
|
|
224
|
+
type MyToolErrorCode = ToolErrorCode | "COMPILATION_FAILED" | "VALIDATION_ERROR";
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
## Utilities
|
|
228
|
+
|
|
229
|
+
### Path Utilities
|
|
230
|
+
|
|
231
|
+
```typescript
|
|
232
|
+
import { Path } from "@uipath/solutionpackager-tool-core";
|
|
233
|
+
const fullPath = Path.join(basePath, "subfolder", "file.json");
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
### NuGet Constants
|
|
237
|
+
|
|
238
|
+
```typescript
|
|
239
|
+
import { NugetConstants } from "@uipath/solutionpackager-tool-core";
|
|
240
|
+
|
|
241
|
+
NugetConstants.OutputFolderName; // "bundle"
|
|
242
|
+
NugetConstants.ContentFolderName; // "content"
|
|
243
|
+
NugetConstants.OperateFileName; // "operate.json"
|
|
244
|
+
NugetConstants.EntryPointsFileName; // "entrypoints.json"
|
|
245
|
+
NugetConstants.PackageDescriptorFileName; // "package-descriptor.json"
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
## Architecture
|
|
249
|
+
|
|
250
|
+
```text
|
|
251
|
+
┌─────────────────────────────────────────────────────────────┐
|
|
252
|
+
│ tool.core (contracts) │
|
|
253
|
+
│ IToolLogger IFileSystem ProjectTool SolutionTool │
|
|
254
|
+
└─────────────────────────────────────────────────────────────┘
|
|
255
|
+
▲
|
|
256
|
+
implements/uses │
|
|
257
|
+
┌─────────────────────────┼───────────────────────────────────┐
|
|
258
|
+
│ solutionpackager │
|
|
259
|
+
│ ToolLogger FileSystem ToolsFactory │
|
|
260
|
+
└─────────────────────────────────────────────────────────────┘
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
1. `tool.core` provides interfaces and base classes
|
|
264
|
+
2. Tools implement interfaces and register factories
|
|
265
|
+
3. SolutionPackager discovers and creates tool instances
|
|
266
|
+
4. Tools execute operations with injected logger and file system
|
|
267
|
+
|
|
268
|
+
## Development
|
|
269
|
+
|
|
270
|
+
```bash
|
|
271
|
+
# Build
|
|
272
|
+
npm run build
|
|
273
|
+
|
|
274
|
+
# Run tests
|
|
275
|
+
npm test
|
|
276
|
+
|
|
277
|
+
# Pack
|
|
278
|
+
npm pack
|
|
279
|
+
|
|
280
|
+
# Publish
|
|
281
|
+
npm publish
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
## Troubleshooting
|
|
285
|
+
|
|
286
|
+
### Installation Issues
|
|
287
|
+
|
|
288
|
+
**404 Not Found:**
|
|
289
|
+
|
|
290
|
+
- Verify package exists at <https://github.com/orgs/UiPath/packages>
|
|
291
|
+
- Check `GH_NPM_REGISTRY_TOKEN` environment variable is set
|
|
292
|
+
- Ensure token has `read:packages` permission
|
|
293
|
+
|
|
294
|
+
**401 Unauthorized:**
|
|
295
|
+
|
|
296
|
+
- Verify token hasn't expired
|
|
297
|
+
- Check environment variable: `echo $env:GH_NPM_REGISTRY_TOKEN` (Windows) or `echo $GH_NPM_REGISTRY_TOKEN` (Linux/macOS)
|
|
298
|
+
|
|
299
|
+
## Examples
|
|
300
|
+
|
|
301
|
+
See `@uipath/tool-apiworkflow` for a complete reference implementation.
|
|
302
|
+
|
|
303
|
+
## Package Information
|
|
304
|
+
|
|
305
|
+
- **Registry:** GitHub Packages (npm)
|
|
306
|
+
- **Organization:** UiPath
|
|
307
|
+
- **Package:** `@uipath/solutionpackager-tool-core`
|
|
308
|
+
- **Repository:** <https://github.com/UiPath/Studio.Common>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export type { FileSystemStats, IFileSystem } from "@uipath/filesystem";
|
|
File without changes
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export type { FileSystemStats, IFileSystem } from "./file-system.js";
|
|
2
|
+
export type { FileEntry } from "./path.js";
|
|
3
|
+
export { Path } from "./path.js";
|
|
4
|
+
export { type ITemporaryStorageService, TemporaryStorageService, } from "./temporary-storage-service.js";
|
|
5
|
+
export { type IZipService, ZipService } from "./zip-service.js";
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import type { IFileSystem } from "./file-system.js";
|
|
2
|
+
/**
|
|
3
|
+
* Represents a file entry with relative and absolute paths
|
|
4
|
+
*/
|
|
5
|
+
export interface FileEntry {
|
|
6
|
+
/**
|
|
7
|
+
* Path relative to the root directory
|
|
8
|
+
*/
|
|
9
|
+
relativePath: string;
|
|
10
|
+
/**
|
|
11
|
+
* Absolute path in the filesystem
|
|
12
|
+
*/
|
|
13
|
+
absolutePath: string;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Platform-independent path utilities
|
|
17
|
+
*/
|
|
18
|
+
export declare class Path {
|
|
19
|
+
/**
|
|
20
|
+
* Normalize path separators to forward slashes (ZIP standard)
|
|
21
|
+
*/
|
|
22
|
+
static normalize(path: string): string;
|
|
23
|
+
/**
|
|
24
|
+
* Join path segments with forward slashes
|
|
25
|
+
*/
|
|
26
|
+
static join(...segments: string[]): string;
|
|
27
|
+
/**
|
|
28
|
+
* Get the directory name of a path (platform-independent)
|
|
29
|
+
* @param path - The file path
|
|
30
|
+
* @returns The directory path, or '.' if no directory
|
|
31
|
+
*/
|
|
32
|
+
static dirname(path: string): string;
|
|
33
|
+
/**
|
|
34
|
+
* Get the base name (filename) of a path (platform-independent)
|
|
35
|
+
* @param path - The file path
|
|
36
|
+
* @returns The filename portion of the path
|
|
37
|
+
*/
|
|
38
|
+
static basename(path: string): string;
|
|
39
|
+
/**
|
|
40
|
+
* Get the extension of a path (platform-independent)
|
|
41
|
+
* @param path - The file path
|
|
42
|
+
* @returns The extension including the dot (e.g., '.txt'), or empty string if no extension
|
|
43
|
+
*/
|
|
44
|
+
static extname(path: string): string;
|
|
45
|
+
/**
|
|
46
|
+
* Recursively walk a directory and return all files
|
|
47
|
+
* @param fs - FileSystem implementation
|
|
48
|
+
* @param rootPath - Root directory to walk
|
|
49
|
+
* @param currentRelativePath - Current relative path (used internally for recursion)
|
|
50
|
+
* @returns Array of file entries with relative and absolute paths
|
|
51
|
+
*/
|
|
52
|
+
static walkDirectory(fs: IFileSystem, rootPath: string, currentRelativePath?: string): Promise<FileEntry[]>;
|
|
53
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
class Path {
|
|
2
|
+
static normalize(path) {
|
|
3
|
+
return path.replace(/\\/g, "/").replace(/\/+/g, "/");
|
|
4
|
+
}
|
|
5
|
+
static join(...segments) {
|
|
6
|
+
return Path.normalize(segments.filter((s)=>s.length > 0).join("/"));
|
|
7
|
+
}
|
|
8
|
+
static dirname(path) {
|
|
9
|
+
const normalized = Path.normalize(path).replace(/\/$/, "");
|
|
10
|
+
if ("" === normalized) return ".";
|
|
11
|
+
const lastSlash = normalized.lastIndexOf("/");
|
|
12
|
+
if (-1 === lastSlash) return ".";
|
|
13
|
+
if (0 === lastSlash) return "/";
|
|
14
|
+
return normalized.substring(0, lastSlash);
|
|
15
|
+
}
|
|
16
|
+
static basename(path) {
|
|
17
|
+
const normalized = Path.normalize(path).replace(/\/$/, "");
|
|
18
|
+
if ("" === normalized) return "";
|
|
19
|
+
const lastSlash = normalized.lastIndexOf("/");
|
|
20
|
+
return lastSlash >= 0 ? normalized.substring(lastSlash + 1) : normalized;
|
|
21
|
+
}
|
|
22
|
+
static extname(path) {
|
|
23
|
+
const base = Path.basename(path);
|
|
24
|
+
const lastDot = base.lastIndexOf(".");
|
|
25
|
+
if (-1 === lastDot || 0 === lastDot || lastDot === base.length - 1) return "";
|
|
26
|
+
return base.substring(lastDot);
|
|
27
|
+
}
|
|
28
|
+
static async walkDirectory(fs, rootPath, currentRelativePath = "") {
|
|
29
|
+
const entries = [];
|
|
30
|
+
const absolutePath = currentRelativePath ? Path.join(rootPath, currentRelativePath) : rootPath;
|
|
31
|
+
const items = await fs.readdir(absolutePath);
|
|
32
|
+
for (const item of items){
|
|
33
|
+
const itemRelativePath = currentRelativePath ? Path.join(currentRelativePath, item) : item;
|
|
34
|
+
const itemAbsolutePath = Path.join(rootPath, itemRelativePath);
|
|
35
|
+
const stat = await fs.stat(itemAbsolutePath);
|
|
36
|
+
if (stat?.isDirectory()) {
|
|
37
|
+
const subEntries = await Path.walkDirectory(fs, rootPath, itemRelativePath);
|
|
38
|
+
entries.push(...subEntries);
|
|
39
|
+
} else if (stat?.isFile()) entries.push({
|
|
40
|
+
relativePath: Path.normalize(itemRelativePath),
|
|
41
|
+
absolutePath: Path.normalize(itemAbsolutePath)
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
return entries;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
export { Path };
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { IFileSystem } from "./file-system.js";
|
|
2
|
+
/**
|
|
3
|
+
* Service for managing temporary storage.
|
|
4
|
+
*/
|
|
5
|
+
export interface ITemporaryStorageService {
|
|
6
|
+
/**
|
|
7
|
+
* Ensure temp folder is initialized and get its path.
|
|
8
|
+
*/
|
|
9
|
+
getTempFolderPath(): Promise<string>;
|
|
10
|
+
/**
|
|
11
|
+
* Ensure subfolder in temp folder is initialized and get its path.
|
|
12
|
+
*/
|
|
13
|
+
getTempSubfolderPathAsync(subfolder: string): Promise<string>;
|
|
14
|
+
/**
|
|
15
|
+
* Delete the temporary directory
|
|
16
|
+
*/
|
|
17
|
+
cleanup(): Promise<void>;
|
|
18
|
+
}
|
|
19
|
+
export declare class TemporaryStorageService implements ITemporaryStorageService {
|
|
20
|
+
private readonly fileSystem;
|
|
21
|
+
private _tempFolderPath;
|
|
22
|
+
constructor(fileSystem: IFileSystem);
|
|
23
|
+
getTempFolderPath(): Promise<string>;
|
|
24
|
+
/**
|
|
25
|
+
* Generate a unique folder name using timestamp and random string
|
|
26
|
+
* Format: tool-temp-{timestamp}-{random}
|
|
27
|
+
*/
|
|
28
|
+
private generateUniqueFolderName;
|
|
29
|
+
getTempSubfolderPathAsync(subfolder: string): Promise<string>;
|
|
30
|
+
cleanup(): Promise<void>;
|
|
31
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { Path } from "./path.js";
|
|
2
|
+
class TemporaryStorageService {
|
|
3
|
+
fileSystem;
|
|
4
|
+
_tempFolderPath = null;
|
|
5
|
+
constructor(fileSystem){
|
|
6
|
+
this.fileSystem = fileSystem;
|
|
7
|
+
}
|
|
8
|
+
async getTempFolderPath() {
|
|
9
|
+
if (!this._tempFolderPath) {
|
|
10
|
+
const systemTempDir = await this.fileSystem.getTempDir();
|
|
11
|
+
const uniqueFolderName = this.generateUniqueFolderName();
|
|
12
|
+
this._tempFolderPath = Path.join(systemTempDir, uniqueFolderName);
|
|
13
|
+
await this.fileSystem.mkdir(this._tempFolderPath);
|
|
14
|
+
}
|
|
15
|
+
return this._tempFolderPath;
|
|
16
|
+
}
|
|
17
|
+
generateUniqueFolderName() {
|
|
18
|
+
const timestamp = Date.now();
|
|
19
|
+
const random = Math.random().toString(36).substring(2, 10);
|
|
20
|
+
return `tool-temp-${timestamp}-${random}`;
|
|
21
|
+
}
|
|
22
|
+
async getTempSubfolderPathAsync(subfolder) {
|
|
23
|
+
const tempFolderPath = await this.getTempFolderPath();
|
|
24
|
+
const inputPath = Path.join(tempFolderPath, subfolder);
|
|
25
|
+
await this.fileSystem.mkdir(inputPath);
|
|
26
|
+
return inputPath;
|
|
27
|
+
}
|
|
28
|
+
async cleanup() {
|
|
29
|
+
try {
|
|
30
|
+
if (!this._tempFolderPath) return;
|
|
31
|
+
try {
|
|
32
|
+
const stats = await this.fileSystem.stat(this._tempFolderPath);
|
|
33
|
+
if (!stats) return;
|
|
34
|
+
} catch {
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
const pathToCleanup = this._tempFolderPath;
|
|
38
|
+
await this.fileSystem.rm(this._tempFolderPath);
|
|
39
|
+
this._tempFolderPath = null;
|
|
40
|
+
console.info(`Cleaned up temp folder: ${pathToCleanup}`);
|
|
41
|
+
} catch (error) {
|
|
42
|
+
console.error("Error during cleanup:", error);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
export { TemporaryStorageService };
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { IFileSystem } from "./file-system.js";
|
|
2
|
+
/**
|
|
3
|
+
* Interface for zip compression and extraction operations
|
|
4
|
+
*/
|
|
5
|
+
export interface IZipService {
|
|
6
|
+
/**
|
|
7
|
+
* Extract a zip archive to a directory
|
|
8
|
+
* @param zipData The raw zip archive data
|
|
9
|
+
* @param targetPath The directory path to extract files to
|
|
10
|
+
* @returns List of extracted file paths
|
|
11
|
+
*/
|
|
12
|
+
extractAsync(zipData: Uint8Array, targetPath: string): Promise<string[]>;
|
|
13
|
+
/**
|
|
14
|
+
* Create a zip archive from a directory
|
|
15
|
+
* @param sourcePath The directory path to compress
|
|
16
|
+
* @returns The compressed zip data
|
|
17
|
+
*/
|
|
18
|
+
compressAsync(sourcePath: string): Promise<Uint8Array>;
|
|
19
|
+
}
|
|
20
|
+
export declare class ZipService implements IZipService {
|
|
21
|
+
private readonly fileSystem;
|
|
22
|
+
constructor(fileSystem: IFileSystem);
|
|
23
|
+
extractAsync(zipData: Uint8Array, targetPath: string): Promise<string[]>;
|
|
24
|
+
compressAsync(sourcePath: string): Promise<Uint8Array>;
|
|
25
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { unzipSync, zipSync } from "fflate";
|
|
2
|
+
import { Path } from "./path.js";
|
|
3
|
+
class ZipService {
|
|
4
|
+
fileSystem;
|
|
5
|
+
constructor(fileSystem){
|
|
6
|
+
this.fileSystem = fileSystem;
|
|
7
|
+
}
|
|
8
|
+
async extractAsync(zipData, targetPath) {
|
|
9
|
+
const normalizedTarget = targetPath.replace(/\/$/, "");
|
|
10
|
+
await this.fileSystem.mkdir(normalizedTarget);
|
|
11
|
+
const files = unzipSync(zipData);
|
|
12
|
+
const extractedPaths = [];
|
|
13
|
+
for (const [relativePath, data] of Object.entries(files)){
|
|
14
|
+
if (relativePath.endsWith("/") || 0 === data.length) {
|
|
15
|
+
const dirPath = `${normalizedTarget}/${relativePath.replace(/\/$/, "")}`;
|
|
16
|
+
await this.fileSystem.mkdir(dirPath);
|
|
17
|
+
continue;
|
|
18
|
+
}
|
|
19
|
+
const fullPath = `${normalizedTarget}/${relativePath}`;
|
|
20
|
+
const parentDir = fullPath.split("/").slice(0, -1).join("/");
|
|
21
|
+
if (parentDir) await this.fileSystem.mkdir(parentDir);
|
|
22
|
+
await this.fileSystem.writeFile(fullPath, data);
|
|
23
|
+
extractedPaths.push(fullPath);
|
|
24
|
+
}
|
|
25
|
+
return extractedPaths;
|
|
26
|
+
}
|
|
27
|
+
async compressAsync(sourcePath) {
|
|
28
|
+
const normalizedSource = sourcePath.replace(/\/$/, "");
|
|
29
|
+
const entries = await Path.walkDirectory(this.fileSystem, normalizedSource);
|
|
30
|
+
const zippable = {};
|
|
31
|
+
for (const entry of entries){
|
|
32
|
+
const fileData = await this.fileSystem.readFile(entry.absolutePath);
|
|
33
|
+
if (fileData) zippable[entry.relativePath] = fileData;
|
|
34
|
+
}
|
|
35
|
+
const zipData = zipSync(zippable, {
|
|
36
|
+
level: 6
|
|
37
|
+
});
|
|
38
|
+
return zipData;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
export { ZipService };
|