@hamak/ui-remote-fs 0.5.1
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/dist/api/contracts/i-remote-fs-service.d.ts +85 -0
- package/dist/api/contracts/i-remote-fs-service.d.ts.map +1 -0
- package/dist/api/contracts/i-remote-fs-service.js +6 -0
- package/dist/api/contracts/index.d.ts +5 -0
- package/dist/api/contracts/index.d.ts.map +1 -0
- package/dist/api/contracts/index.js +4 -0
- package/dist/api/index.d.ts +8 -0
- package/dist/api/index.d.ts.map +1 -0
- package/dist/api/index.js +7 -0
- package/dist/api/tokens/index.d.ts +5 -0
- package/dist/api/tokens/index.d.ts.map +1 -0
- package/dist/api/tokens/index.js +4 -0
- package/dist/api/tokens/remote-fs.tokens.d.ts +29 -0
- package/dist/api/tokens/remote-fs.tokens.d.ts.map +1 -0
- package/dist/api/tokens/remote-fs.tokens.js +28 -0
- package/dist/api/types/index.d.ts +7 -0
- package/dist/api/types/index.d.ts.map +1 -0
- package/dist/api/types/index.js +6 -0
- package/dist/api/types/remote-fs-action.types.d.ts +34 -0
- package/dist/api/types/remote-fs-action.types.d.ts.map +1 -0
- package/dist/api/types/remote-fs-action.types.js +42 -0
- package/dist/api/types/remote-fs-config.types.d.ts +40 -0
- package/dist/api/types/remote-fs-config.types.d.ts.map +1 -0
- package/dist/api/types/remote-fs-config.types.js +12 -0
- package/dist/api/types/remote-fs-error.types.d.ts +28 -0
- package/dist/api/types/remote-fs-error.types.d.ts.map +1 -0
- package/dist/api/types/remote-fs-error.types.js +15 -0
- package/dist/impl/actions/index.d.ts +5 -0
- package/dist/impl/actions/index.d.ts.map +1 -0
- package/dist/impl/actions/index.js +4 -0
- package/dist/impl/actions/remote-fs-actions.d.ts +196 -0
- package/dist/impl/actions/remote-fs-actions.d.ts.map +1 -0
- package/dist/impl/actions/remote-fs-actions.js +151 -0
- package/dist/impl/autosave/index.d.ts +5 -0
- package/dist/impl/autosave/index.d.ts.map +1 -0
- package/dist/impl/autosave/index.js +4 -0
- package/dist/impl/autosave/remote-fs-autosave-provider.d.ts +46 -0
- package/dist/impl/autosave/remote-fs-autosave-provider.d.ts.map +1 -0
- package/dist/impl/autosave/remote-fs-autosave-provider.js +80 -0
- package/dist/impl/index.d.ts +14 -0
- package/dist/impl/index.d.ts.map +1 -0
- package/dist/impl/index.js +13 -0
- package/dist/impl/middleware/index.d.ts +6 -0
- package/dist/impl/middleware/index.d.ts.map +1 -0
- package/dist/impl/middleware/index.js +5 -0
- package/dist/impl/middleware/remote-fs-middleware.d.ts +38 -0
- package/dist/impl/middleware/remote-fs-middleware.d.ts.map +1 -0
- package/dist/impl/middleware/remote-fs-middleware.js +192 -0
- package/dist/impl/middleware/store-sync-middleware.d.ts +35 -0
- package/dist/impl/middleware/store-sync-middleware.d.ts.map +1 -0
- package/dist/impl/middleware/store-sync-middleware.js +135 -0
- package/dist/impl/plugin/index.d.ts +5 -0
- package/dist/impl/plugin/index.d.ts.map +1 -0
- package/dist/impl/plugin/index.js +4 -0
- package/dist/impl/plugin/remote-fs-plugin-factory.d.ts +84 -0
- package/dist/impl/plugin/remote-fs-plugin-factory.d.ts.map +1 -0
- package/dist/impl/plugin/remote-fs-plugin-factory.js +150 -0
- package/dist/impl/providers/http-workspace-client.d.ts +103 -0
- package/dist/impl/providers/http-workspace-client.d.ts.map +1 -0
- package/dist/impl/providers/http-workspace-client.js +215 -0
- package/dist/impl/providers/index.d.ts +5 -0
- package/dist/impl/providers/index.d.ts.map +1 -0
- package/dist/impl/providers/index.js +4 -0
- package/dist/impl/services/index.d.ts +5 -0
- package/dist/impl/services/index.d.ts.map +1 -0
- package/dist/impl/services/index.js +4 -0
- package/dist/impl/services/remote-fs-service.d.ts +10 -0
- package/dist/impl/services/remote-fs-service.d.ts.map +1 -0
- package/dist/impl/services/remote-fs-service.js +12 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +5 -0
- package/dist/spi/index.d.ts +8 -0
- package/dist/spi/index.d.ts.map +1 -0
- package/dist/spi/index.js +7 -0
- package/dist/spi/middleware/index.d.ts +5 -0
- package/dist/spi/middleware/index.d.ts.map +1 -0
- package/dist/spi/middleware/index.js +4 -0
- package/dist/spi/middleware/remote-fs-middleware.types.d.ts +61 -0
- package/dist/spi/middleware/remote-fs-middleware.types.d.ts.map +1 -0
- package/dist/spi/middleware/remote-fs-middleware.types.js +6 -0
- package/dist/spi/providers/i-path-translator.d.ts +74 -0
- package/dist/spi/providers/i-path-translator.d.ts.map +1 -0
- package/dist/spi/providers/i-path-translator.js +61 -0
- package/dist/spi/providers/i-remote-fs-provider.d.ts +78 -0
- package/dist/spi/providers/i-remote-fs-provider.d.ts.map +1 -0
- package/dist/spi/providers/i-remote-fs-provider.js +6 -0
- package/dist/spi/providers/i-workspace-client.d.ts +97 -0
- package/dist/spi/providers/i-workspace-client.d.ts.map +1 -0
- package/dist/spi/providers/i-workspace-client.js +7 -0
- package/dist/spi/providers/index.d.ts +7 -0
- package/dist/spi/providers/index.d.ts.map +1 -0
- package/dist/spi/providers/index.js +6 -0
- package/package.json +69 -0
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HTTP Workspace Client
|
|
3
|
+
*
|
|
4
|
+
* HTTP-based implementation of IWorkspaceClient using Axios.
|
|
5
|
+
* Migrated from amk/libs/server/ws/ws-client/src/lib/server-ws-ws-client.ts
|
|
6
|
+
*/
|
|
7
|
+
import axios from 'axios';
|
|
8
|
+
/**
|
|
9
|
+
* HTTP-based implementation of IWorkspaceClient
|
|
10
|
+
*
|
|
11
|
+
* This implementation uses Axios to communicate with a REST API backend.
|
|
12
|
+
* Supports configurable base URL, timeout, and custom axios instances.
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```typescript
|
|
16
|
+
* const client = new HttpWorkspaceClient({
|
|
17
|
+
* workspaceId: '0',
|
|
18
|
+
* baseUrl: 'http://localhost:3000/api'
|
|
19
|
+
* });
|
|
20
|
+
*
|
|
21
|
+
* const files = await client.listFiles(['folder', 'subfolder']);
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
export class HttpWorkspaceClient {
|
|
25
|
+
constructor(config) {
|
|
26
|
+
Object.defineProperty(this, "workspaceId", {
|
|
27
|
+
enumerable: true,
|
|
28
|
+
configurable: true,
|
|
29
|
+
writable: true,
|
|
30
|
+
value: void 0
|
|
31
|
+
});
|
|
32
|
+
Object.defineProperty(this, "baseUrl", {
|
|
33
|
+
enumerable: true,
|
|
34
|
+
configurable: true,
|
|
35
|
+
writable: true,
|
|
36
|
+
value: void 0
|
|
37
|
+
});
|
|
38
|
+
Object.defineProperty(this, "axios", {
|
|
39
|
+
enumerable: true,
|
|
40
|
+
configurable: true,
|
|
41
|
+
writable: true,
|
|
42
|
+
value: void 0
|
|
43
|
+
});
|
|
44
|
+
this.workspaceId = config.workspaceId;
|
|
45
|
+
// Default base URL to current origin if not provided
|
|
46
|
+
this.baseUrl = config.baseUrl ||
|
|
47
|
+
(typeof globalThis !== 'undefined' && 'location' in globalThis
|
|
48
|
+
? `${globalThis.location.protocol}//${globalThis.location.host}/api`
|
|
49
|
+
: '/api');
|
|
50
|
+
// Use provided axios instance or create new one
|
|
51
|
+
this.axios = config.axiosInstance || axios.create({
|
|
52
|
+
baseURL: this.baseUrl,
|
|
53
|
+
timeout: config.timeout || 30000,
|
|
54
|
+
headers: {
|
|
55
|
+
'Content-Type': 'application/json',
|
|
56
|
+
},
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Format path segments to URL path string
|
|
61
|
+
*/
|
|
62
|
+
formatPath(path) {
|
|
63
|
+
return path.join('/');
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Build URL with optional query parameters
|
|
67
|
+
*/
|
|
68
|
+
buildUrl(basePath, options) {
|
|
69
|
+
if (!options?.queryParams) {
|
|
70
|
+
return basePath;
|
|
71
|
+
}
|
|
72
|
+
const params = new URLSearchParams();
|
|
73
|
+
for (const [key, value] of Object.entries(options.queryParams)) {
|
|
74
|
+
if (value === undefined)
|
|
75
|
+
continue;
|
|
76
|
+
if (Array.isArray(value)) {
|
|
77
|
+
value.forEach((v) => params.append(key, String(v)));
|
|
78
|
+
}
|
|
79
|
+
else {
|
|
80
|
+
params.append(key, String(value));
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
const queryString = params.toString();
|
|
84
|
+
return queryString ? `${basePath}?${queryString}` : basePath;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Handle axios errors and convert to ErrorObject
|
|
88
|
+
*/
|
|
89
|
+
handleError(error) {
|
|
90
|
+
if (axios.isAxiosError(error)) {
|
|
91
|
+
const axiosError = error;
|
|
92
|
+
// Try to extract error from response
|
|
93
|
+
if (axiosError.response?.data?.error) {
|
|
94
|
+
throw axiosError.response.data.error;
|
|
95
|
+
}
|
|
96
|
+
// Create error from axios error
|
|
97
|
+
const errorObj = {
|
|
98
|
+
code: axiosError.code || 'UNKNOWN',
|
|
99
|
+
message: axiosError.message || 'Unknown error occurred',
|
|
100
|
+
params: {
|
|
101
|
+
status: axiosError.response?.status,
|
|
102
|
+
statusText: axiosError.response?.statusText,
|
|
103
|
+
},
|
|
104
|
+
};
|
|
105
|
+
throw errorObj;
|
|
106
|
+
}
|
|
107
|
+
// Handle non-axios errors
|
|
108
|
+
const errorObj = {
|
|
109
|
+
code: 'UNKNOWN',
|
|
110
|
+
message: error instanceof Error ? error.message : 'Unknown error occurred',
|
|
111
|
+
};
|
|
112
|
+
throw errorObj;
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Serialize content to string for transmission
|
|
116
|
+
*/
|
|
117
|
+
serializeContent(content) {
|
|
118
|
+
if (typeof content === 'string') {
|
|
119
|
+
return content;
|
|
120
|
+
}
|
|
121
|
+
return JSON.stringify(content);
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* List files and directories at the specified path
|
|
125
|
+
*/
|
|
126
|
+
async listFiles(path, options) {
|
|
127
|
+
try {
|
|
128
|
+
const formattedPath = this.formatPath(path);
|
|
129
|
+
const url = this.buildUrl(`/${this.workspaceId}/files/${formattedPath}`, options);
|
|
130
|
+
const response = await this.axios.get(url);
|
|
131
|
+
return response.data;
|
|
132
|
+
}
|
|
133
|
+
catch (error) {
|
|
134
|
+
this.handleError(error);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Create a directory at the specified path
|
|
139
|
+
*/
|
|
140
|
+
async createDirectory(path, options) {
|
|
141
|
+
try {
|
|
142
|
+
const formattedPath = this.formatPath(path);
|
|
143
|
+
const url = this.buildUrl(`/${this.workspaceId}/mkdir/${formattedPath}`, options);
|
|
144
|
+
const response = await this.axios.post(url);
|
|
145
|
+
return response.data;
|
|
146
|
+
}
|
|
147
|
+
catch (error) {
|
|
148
|
+
this.handleError(error);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Read a file's metadata and content
|
|
153
|
+
*/
|
|
154
|
+
async readFile(path, options) {
|
|
155
|
+
try {
|
|
156
|
+
const formattedPath = this.formatPath(path);
|
|
157
|
+
const url = this.buildUrl(`/${this.workspaceId}/read/${formattedPath}`, options);
|
|
158
|
+
const response = await this.axios.get(url);
|
|
159
|
+
return response.data;
|
|
160
|
+
}
|
|
161
|
+
catch (error) {
|
|
162
|
+
this.handleError(error);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Write or update a file's content (uses PUT method)
|
|
167
|
+
*/
|
|
168
|
+
async putFile(path, content, options) {
|
|
169
|
+
try {
|
|
170
|
+
const formattedPath = this.formatPath(path);
|
|
171
|
+
const serializedContent = this.serializeContent(content);
|
|
172
|
+
const url = this.buildUrl(`/${this.workspaceId}/put/${formattedPath}`, options);
|
|
173
|
+
const response = await this.axios.put(url, { content: serializedContent });
|
|
174
|
+
return response.data;
|
|
175
|
+
}
|
|
176
|
+
catch (error) {
|
|
177
|
+
this.handleError(error);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* Delete a file or directory
|
|
182
|
+
*/
|
|
183
|
+
async deleteFile(path, options) {
|
|
184
|
+
try {
|
|
185
|
+
const formattedPath = this.formatPath(path);
|
|
186
|
+
const url = this.buildUrl(`/${this.workspaceId}/delete/${formattedPath}`, options);
|
|
187
|
+
const response = await this.axios.delete(url);
|
|
188
|
+
return response.data;
|
|
189
|
+
}
|
|
190
|
+
catch (error) {
|
|
191
|
+
this.handleError(error);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* Get the workspace ID
|
|
196
|
+
*/
|
|
197
|
+
getWorkspaceId() {
|
|
198
|
+
return this.workspaceId;
|
|
199
|
+
}
|
|
200
|
+
/**
|
|
201
|
+
* Get the base URL
|
|
202
|
+
*/
|
|
203
|
+
getBaseUrl() {
|
|
204
|
+
return this.baseUrl;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
/**
|
|
208
|
+
* Factory function to create HTTP workspace client with default configuration
|
|
209
|
+
*/
|
|
210
|
+
export function createHttpWorkspaceClient(workspaceId, baseUrl) {
|
|
211
|
+
return new HttpWorkspaceClient({
|
|
212
|
+
workspaceId,
|
|
213
|
+
baseUrl,
|
|
214
|
+
});
|
|
215
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/impl/providers/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,cAAc,yBAAyB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/impl/services/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,cAAc,qBAAqB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"remote-fs-service.d.ts","sourceRoot":"","sources":["../../../src/impl/services/remote-fs-service.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,qBAAa,eAAe;;CAI3B"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Remote FS Service
|
|
3
|
+
*
|
|
4
|
+
* Service implementation for remote filesystem operations.
|
|
5
|
+
* Will be implemented in future phases.
|
|
6
|
+
*/
|
|
7
|
+
// Placeholder - will be implemented in future phases
|
|
8
|
+
export class RemoteFsService {
|
|
9
|
+
constructor() {
|
|
10
|
+
throw new Error('Not yet implemented');
|
|
11
|
+
}
|
|
12
|
+
}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,cAAc,QAAQ,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/spi/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,cAAc,QAAQ,CAAC;AACvB,cAAc,aAAa,CAAC;AAC5B,cAAc,cAAc,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/spi/middleware/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,cAAc,8BAA8B,CAAC"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Remote FS Middleware Types
|
|
3
|
+
*
|
|
4
|
+
* Type definitions for remote filesystem middleware.
|
|
5
|
+
*/
|
|
6
|
+
import { Middleware } from 'redux';
|
|
7
|
+
import { IWorkspaceClient } from '../providers/i-workspace-client';
|
|
8
|
+
import { IPathTranslator } from '../providers/i-path-translator';
|
|
9
|
+
/**
|
|
10
|
+
* Configuration for remote FS middleware
|
|
11
|
+
*/
|
|
12
|
+
export interface RemoteFsMiddlewareConfig {
|
|
13
|
+
/**
|
|
14
|
+
* Workspace client for remote operations
|
|
15
|
+
*/
|
|
16
|
+
client: IWorkspaceClient;
|
|
17
|
+
/**
|
|
18
|
+
* Path translator for mount point translation
|
|
19
|
+
*/
|
|
20
|
+
pathTranslator: IPathTranslator;
|
|
21
|
+
/**
|
|
22
|
+
* Optional error handler
|
|
23
|
+
*/
|
|
24
|
+
onError?: (error: Error, action: any) => void;
|
|
25
|
+
/**
|
|
26
|
+
* Optional success handler
|
|
27
|
+
*/
|
|
28
|
+
onSuccess?: (result: any, action: any) => void;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Configuration for store sync middleware
|
|
32
|
+
*/
|
|
33
|
+
export interface StoreSyncMiddlewareConfig {
|
|
34
|
+
/**
|
|
35
|
+
* Filesystem adapter for Store FS operations
|
|
36
|
+
* Must be obtained from @hamak/ui-store-impl
|
|
37
|
+
*/
|
|
38
|
+
fileSystemAdapter: any;
|
|
39
|
+
/**
|
|
40
|
+
* Path translator for converting remote paths to local paths
|
|
41
|
+
*/
|
|
42
|
+
pathTranslator: IPathTranslator;
|
|
43
|
+
/**
|
|
44
|
+
* Whether to automatically reload file content after PUT/POST
|
|
45
|
+
* Default: true
|
|
46
|
+
*/
|
|
47
|
+
autoReload?: boolean;
|
|
48
|
+
/**
|
|
49
|
+
* Optional transform function for file content before storing
|
|
50
|
+
*/
|
|
51
|
+
transformContent?: (content: any) => any;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Type for remote FS middleware factory
|
|
55
|
+
*/
|
|
56
|
+
export type RemoteFsMiddlewareFactory<S = any> = (config: RemoteFsMiddlewareConfig) => Middleware<{}, S>;
|
|
57
|
+
/**
|
|
58
|
+
* Type for store sync middleware factory
|
|
59
|
+
*/
|
|
60
|
+
export type StoreSyncMiddlewareFactory<S = any> = (config: StoreSyncMiddlewareConfig) => Middleware<{}, S>;
|
|
61
|
+
//# sourceMappingURL=remote-fs-middleware.types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"remote-fs-middleware.types.d.ts","sourceRoot":"","sources":["../../../src/spi/middleware/remote-fs-middleware.types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,OAAO,CAAC;AACnC,OAAO,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAC;AACnE,OAAO,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAC;AAEjE;;GAEG;AACH,MAAM,WAAW,wBAAwB;IACvC;;OAEG;IACH,MAAM,EAAE,gBAAgB,CAAC;IAEzB;;OAEG;IACH,cAAc,EAAE,eAAe,CAAC;IAEhC;;OAEG;IACH,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,KAAK,IAAI,CAAC;IAE9C;;OAEG;IACH,SAAS,CAAC,EAAE,CAAC,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,KAAK,IAAI,CAAC;CAChD;AAED;;GAEG;AACH,MAAM,WAAW,yBAAyB;IACxC;;;OAGG;IACH,iBAAiB,EAAE,GAAG,CAAC;IAEvB;;OAEG;IACH,cAAc,EAAE,eAAe,CAAC;IAEhC;;;OAGG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IAErB;;OAEG;IACH,gBAAgB,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,KAAK,GAAG,CAAC;CAC1C;AAED;;GAEG;AACH,MAAM,MAAM,yBAAyB,CAAC,CAAC,GAAG,GAAG,IAAI,CAC/C,MAAM,EAAE,wBAAwB,KAC7B,UAAU,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;AAEvB;;GAEG;AACH,MAAM,MAAM,0BAA0B,CAAC,CAAC,GAAG,GAAG,IAAI,CAChD,MAAM,EAAE,yBAAyB,KAC9B,UAAU,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Path Translator Interface
|
|
3
|
+
*
|
|
4
|
+
* Abstraction for translating between local and remote paths.
|
|
5
|
+
*/
|
|
6
|
+
import { Pathway } from '@hamak/shared-utils';
|
|
7
|
+
/**
|
|
8
|
+
* Interface for path translation implementations
|
|
9
|
+
*
|
|
10
|
+
* Implementations handle the translation between local mount paths
|
|
11
|
+
* and remote filesystem paths. This is useful when the remote filesystem
|
|
12
|
+
* is mounted at a specific location in the local filesystem tree.
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```typescript
|
|
16
|
+
* // Mount remote FS at /remote
|
|
17
|
+
* const translator = new PathTranslator(Pathway.ofRoot().resolve('remote'));
|
|
18
|
+
*
|
|
19
|
+
* // Local path: /remote/workspace/file.txt
|
|
20
|
+
* // Remote path: /workspace/file.txt
|
|
21
|
+
* const remotePath = translator.toRemotePath(['remote', 'workspace', 'file.txt']);
|
|
22
|
+
* // Returns: ['workspace', 'file.txt']
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
25
|
+
export interface IPathTranslator {
|
|
26
|
+
/**
|
|
27
|
+
* Translate a local path to a remote path
|
|
28
|
+
*
|
|
29
|
+
* @param localPath - Local filesystem path (array or Pathway)
|
|
30
|
+
* @returns Remote filesystem path, or undefined if path is not under mount point
|
|
31
|
+
*/
|
|
32
|
+
toRemotePath(localPath: string[] | Pathway): Pathway | undefined;
|
|
33
|
+
/**
|
|
34
|
+
* Translate a remote path to a local path
|
|
35
|
+
*
|
|
36
|
+
* @param remotePath - Remote filesystem path (array or Pathway)
|
|
37
|
+
* @returns Local filesystem path under the mount point
|
|
38
|
+
*/
|
|
39
|
+
toLocalPath(remotePath: string[] | Pathway): Pathway;
|
|
40
|
+
/**
|
|
41
|
+
* Check if a path is under the mount point
|
|
42
|
+
*
|
|
43
|
+
* @param path - Path to check (array or Pathway)
|
|
44
|
+
* @returns true if the path is under the mount point, false otherwise
|
|
45
|
+
*/
|
|
46
|
+
isUnderMountPoint(path: string[] | Pathway): boolean;
|
|
47
|
+
/**
|
|
48
|
+
* Get the mount point path
|
|
49
|
+
*
|
|
50
|
+
* @returns Mount point Pathway
|
|
51
|
+
*/
|
|
52
|
+
getMountPoint(): Pathway;
|
|
53
|
+
/**
|
|
54
|
+
* Format a path for display (e.g., convert to string with separators)
|
|
55
|
+
*
|
|
56
|
+
* @param path - Path to format (array or Pathway)
|
|
57
|
+
* @param separator - Path separator (default: '/')
|
|
58
|
+
* @returns Formatted path string
|
|
59
|
+
*/
|
|
60
|
+
formatPath(path: string[] | Pathway, separator?: string): string;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Default path translator implementation
|
|
64
|
+
*/
|
|
65
|
+
export declare class PathTranslator implements IPathTranslator {
|
|
66
|
+
private readonly mountPoint;
|
|
67
|
+
constructor(mountPoint: Pathway);
|
|
68
|
+
toRemotePath(localPath: string[] | Pathway): Pathway | undefined;
|
|
69
|
+
toLocalPath(remotePath: string[] | Pathway): Pathway;
|
|
70
|
+
isUnderMountPoint(path: string[] | Pathway): boolean;
|
|
71
|
+
getMountPoint(): Pathway;
|
|
72
|
+
formatPath(path: string[] | Pathway, separator?: string): string;
|
|
73
|
+
}
|
|
74
|
+
//# sourceMappingURL=i-path-translator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"i-path-translator.d.ts","sourceRoot":"","sources":["../../../src/spi/providers/i-path-translator.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAE9C;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,WAAW,eAAe;IAC9B;;;;;OAKG;IACH,YAAY,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,OAAO,GAAG,OAAO,GAAG,SAAS,CAAC;IAEjE;;;;;OAKG;IACH,WAAW,CAAC,UAAU,EAAE,MAAM,EAAE,GAAG,OAAO,GAAG,OAAO,CAAC;IAErD;;;;;OAKG;IACH,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,GAAG,OAAO,CAAC;IAErD;;;;OAIG;IACH,aAAa,IAAI,OAAO,CAAC;IAEzB;;;;;;OAMG;IACH,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;CAClE;AAED;;GAEG;AACH,qBAAa,cAAe,YAAW,eAAe;IACxC,OAAO,CAAC,QAAQ,CAAC,UAAU;gBAAV,UAAU,EAAE,OAAO;IAEhD,YAAY,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,OAAO,GAAG,OAAO,GAAG,SAAS;IAgBhE,WAAW,CAAC,UAAU,EAAE,MAAM,EAAE,GAAG,OAAO,GAAG,OAAO;IAKpD,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,GAAG,OAAO;IAwBpD,aAAa,IAAI,OAAO;IAIxB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,EAAE,SAAS,GAAE,MAAY,GAAG,MAAM;CAItE"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Path Translator Interface
|
|
3
|
+
*
|
|
4
|
+
* Abstraction for translating between local and remote paths.
|
|
5
|
+
*/
|
|
6
|
+
import { Pathway } from '@hamak/shared-utils';
|
|
7
|
+
/**
|
|
8
|
+
* Default path translator implementation
|
|
9
|
+
*/
|
|
10
|
+
export class PathTranslator {
|
|
11
|
+
constructor(mountPoint) {
|
|
12
|
+
Object.defineProperty(this, "mountPoint", {
|
|
13
|
+
enumerable: true,
|
|
14
|
+
configurable: true,
|
|
15
|
+
writable: true,
|
|
16
|
+
value: mountPoint
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
toRemotePath(localPath) {
|
|
20
|
+
let pathway = Array.isArray(localPath) ? Pathway.of(localPath) : localPath;
|
|
21
|
+
// If mount point is absolute but path is relative, convert path to absolute
|
|
22
|
+
// This handles the case where paths are passed as segment arrays like ['git-demo', 'file.txt']
|
|
23
|
+
if (this.mountPoint.isAbsolute() && !pathway.isAbsolute()) {
|
|
24
|
+
pathway = Pathway.ofRoot().resolve(pathway);
|
|
25
|
+
}
|
|
26
|
+
if (!this.isUnderMountPoint(pathway)) {
|
|
27
|
+
return undefined;
|
|
28
|
+
}
|
|
29
|
+
return this.mountPoint.relativize(pathway);
|
|
30
|
+
}
|
|
31
|
+
toLocalPath(remotePath) {
|
|
32
|
+
const pathway = Array.isArray(remotePath) ? Pathway.of(remotePath) : remotePath;
|
|
33
|
+
return this.mountPoint.resolve(pathway);
|
|
34
|
+
}
|
|
35
|
+
isUnderMountPoint(path) {
|
|
36
|
+
let pathway = Array.isArray(path) ? Pathway.of(path) : path;
|
|
37
|
+
// If mount point is absolute but path is relative, convert path to absolute
|
|
38
|
+
if (this.mountPoint.isAbsolute() && !pathway.isAbsolute()) {
|
|
39
|
+
pathway = Pathway.ofRoot().resolve(pathway);
|
|
40
|
+
}
|
|
41
|
+
// Path is under mount point if it equals the mount point OR is a descendant
|
|
42
|
+
const pathSegments = pathway.getSegments();
|
|
43
|
+
const mountSegments = this.mountPoint.getSegments();
|
|
44
|
+
// Check if paths are equal
|
|
45
|
+
if (pathSegments.length === mountSegments.length) {
|
|
46
|
+
const isEqual = pathSegments.every((seg, idx) => seg === mountSegments[idx]);
|
|
47
|
+
if (isEqual) {
|
|
48
|
+
return true;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
// Check if path is a descendant
|
|
52
|
+
return this.mountPoint.isDescendant(pathway);
|
|
53
|
+
}
|
|
54
|
+
getMountPoint() {
|
|
55
|
+
return this.mountPoint;
|
|
56
|
+
}
|
|
57
|
+
formatPath(path, separator = '/') {
|
|
58
|
+
const segments = Array.isArray(path) ? path : path.getSegments();
|
|
59
|
+
return segments.join(separator);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Remote FS Provider Interface
|
|
3
|
+
*
|
|
4
|
+
* Provider abstraction for remote filesystem backends.
|
|
5
|
+
*/
|
|
6
|
+
import { IWorkspaceClient } from './i-workspace-client';
|
|
7
|
+
/**
|
|
8
|
+
* Interface for remote filesystem provider implementations
|
|
9
|
+
*
|
|
10
|
+
* This interface allows for different backend implementations
|
|
11
|
+
* (e.g., REST API, S3, Azure Blob Storage, Firebase, etc.)
|
|
12
|
+
*/
|
|
13
|
+
export interface IRemoteFsProvider {
|
|
14
|
+
/**
|
|
15
|
+
* Get a workspace client for the specified workspace ID
|
|
16
|
+
*
|
|
17
|
+
* @param workspaceId - Unique identifier for the workspace
|
|
18
|
+
* @returns IWorkspaceClient instance for the workspace
|
|
19
|
+
*/
|
|
20
|
+
getClient(workspaceId: string): IWorkspaceClient;
|
|
21
|
+
/**
|
|
22
|
+
* Connect to the remote filesystem backend
|
|
23
|
+
*
|
|
24
|
+
* @returns Promise that resolves when connection is established
|
|
25
|
+
* @throws Error if connection fails
|
|
26
|
+
*/
|
|
27
|
+
connect(): Promise<void>;
|
|
28
|
+
/**
|
|
29
|
+
* Disconnect from the remote filesystem backend
|
|
30
|
+
*
|
|
31
|
+
* @returns Promise that resolves when disconnection is complete
|
|
32
|
+
*/
|
|
33
|
+
disconnect(): Promise<void>;
|
|
34
|
+
/**
|
|
35
|
+
* Check if the provider is currently connected
|
|
36
|
+
*
|
|
37
|
+
* @returns true if connected, false otherwise
|
|
38
|
+
*/
|
|
39
|
+
isConnected(): boolean;
|
|
40
|
+
/**
|
|
41
|
+
* Get the provider's configuration
|
|
42
|
+
*
|
|
43
|
+
* @returns Provider-specific configuration object
|
|
44
|
+
*/
|
|
45
|
+
getConfig(): any;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Configuration for remote FS provider
|
|
49
|
+
*/
|
|
50
|
+
export interface RemoteFsProviderConfig {
|
|
51
|
+
/**
|
|
52
|
+
* Base URL or endpoint for the remote filesystem
|
|
53
|
+
*/
|
|
54
|
+
endpoint: string;
|
|
55
|
+
/**
|
|
56
|
+
* Authentication token or credentials
|
|
57
|
+
*/
|
|
58
|
+
auth?: {
|
|
59
|
+
type: 'bearer' | 'basic' | 'apikey';
|
|
60
|
+
token?: string;
|
|
61
|
+
username?: string;
|
|
62
|
+
password?: string;
|
|
63
|
+
apiKey?: string;
|
|
64
|
+
};
|
|
65
|
+
/**
|
|
66
|
+
* Timeout for requests in milliseconds
|
|
67
|
+
*/
|
|
68
|
+
timeout?: number;
|
|
69
|
+
/**
|
|
70
|
+
* Number of retry attempts for failed requests
|
|
71
|
+
*/
|
|
72
|
+
retries?: number;
|
|
73
|
+
/**
|
|
74
|
+
* Provider-specific options
|
|
75
|
+
*/
|
|
76
|
+
options?: Record<string, any>;
|
|
77
|
+
}
|
|
78
|
+
//# sourceMappingURL=i-remote-fs-provider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"i-remote-fs-provider.d.ts","sourceRoot":"","sources":["../../../src/spi/providers/i-remote-fs-provider.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAExD;;;;;GAKG;AACH,MAAM,WAAW,iBAAiB;IAChC;;;;;OAKG;IACH,SAAS,CAAC,WAAW,EAAE,MAAM,GAAG,gBAAgB,CAAC;IAEjD;;;;;OAKG;IACH,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAEzB;;;;OAIG;IACH,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAE5B;;;;OAIG;IACH,WAAW,IAAI,OAAO,CAAC;IAEvB;;;;OAIG;IACH,SAAS,IAAI,GAAG,CAAC;CAClB;AAED;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC;;OAEG;IACH,QAAQ,EAAE,MAAM,CAAC;IAEjB;;OAEG;IACH,IAAI,CAAC,EAAE;QACL,IAAI,EAAE,QAAQ,GAAG,OAAO,GAAG,QAAQ,CAAC;QACpC,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,MAAM,CAAC,EAAE,MAAM,CAAC;KACjB,CAAC;IAEF;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CAC/B"}
|