deckide 3.0.2 → 3.0.3
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/package.json +3 -6
- package/node_modules/@deck-ide/shared/README.md +0 -69
- package/node_modules/@deck-ide/shared/dist/types.d.ts +0 -124
- package/node_modules/@deck-ide/shared/dist/types.d.ts.map +0 -1
- package/node_modules/@deck-ide/shared/dist/types.js +0 -3
- package/node_modules/@deck-ide/shared/dist/types.js.map +0 -1
- package/node_modules/@deck-ide/shared/dist/utils-node.d.ts +0 -22
- package/node_modules/@deck-ide/shared/dist/utils-node.d.ts.map +0 -1
- package/node_modules/@deck-ide/shared/dist/utils-node.js +0 -35
- package/node_modules/@deck-ide/shared/dist/utils-node.js.map +0 -1
- package/node_modules/@deck-ide/shared/dist/utils.d.ts +0 -90
- package/node_modules/@deck-ide/shared/dist/utils.d.ts.map +0 -1
- package/node_modules/@deck-ide/shared/dist/utils.js +0 -186
- package/node_modules/@deck-ide/shared/dist/utils.js.map +0 -1
- package/node_modules/@deck-ide/shared/package.json +0 -16
- package/node_modules/@deck-ide/shared/tsconfig.json +0 -20
- package/node_modules/@deck-ide/shared/types.ts +0 -174
- package/node_modules/@deck-ide/shared/utils-node.ts +0 -50
- package/node_modules/@deck-ide/shared/utils.ts +0 -196
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "deckide",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.3",
|
|
4
4
|
"description": "Deck IDE - Browser-based IDE with terminal, file explorer, and git integration",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -12,10 +12,10 @@
|
|
|
12
12
|
"apps/server/package.json",
|
|
13
13
|
"apps/web/dist/",
|
|
14
14
|
"packages/shared/dist/",
|
|
15
|
-
"packages/shared/package.json"
|
|
15
|
+
"packages/shared/package.json",
|
|
16
|
+
"node_modules/@deck-ide/"
|
|
16
17
|
],
|
|
17
18
|
"dependencies": {
|
|
18
|
-
"@deck-ide/shared": "file:packages/shared",
|
|
19
19
|
"@hono/node-server": "^1.12.2",
|
|
20
20
|
"hono": "^4.5.10",
|
|
21
21
|
"node-pty": "^1.0.0",
|
|
@@ -23,9 +23,6 @@
|
|
|
23
23
|
"ws": "^8.17.0",
|
|
24
24
|
"zod": "^4.0.0"
|
|
25
25
|
},
|
|
26
|
-
"bundledDependencies": [
|
|
27
|
-
"@deck-ide/shared"
|
|
28
|
-
],
|
|
29
26
|
"engines": {
|
|
30
27
|
"node": ">=20"
|
|
31
28
|
},
|
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
# @deck-ide/shared
|
|
2
|
-
|
|
3
|
-
共有型定義とユーティリティ関数を提供するDeck IDEの共有パッケージです。
|
|
4
|
-
|
|
5
|
-
## 概要
|
|
6
|
-
|
|
7
|
-
このパッケージは、Deck IDEモノレポ全体(web, server, desktop)で使用される共通のTypeScript型定義とユーティリティ関数を提供します。
|
|
8
|
-
|
|
9
|
-
## 構成
|
|
10
|
-
|
|
11
|
-
### types.ts (130行)
|
|
12
|
-
|
|
13
|
-
コアドメイン型:
|
|
14
|
-
- `Workspace` - プロジェクトワークスペース定義
|
|
15
|
-
- `Deck` - ターミナルとエディタを持つワークスペースビュー
|
|
16
|
-
- `FileSystemEntry` - ファイルとディレクトリエントリ
|
|
17
|
-
- `FileTreeNode` - UI状態を持つ拡張ファイルツリー
|
|
18
|
-
- `EditorFile` - エディタファイル表現
|
|
19
|
-
- `TerminalSession` - ターミナルセッション
|
|
20
|
-
- APIリクエスト/レスポンス型
|
|
21
|
-
|
|
22
|
-
### utils.ts (196行)
|
|
23
|
-
|
|
24
|
-
ブラウザ互換のユーティリティ関数:
|
|
25
|
-
- パス操作 (normalize, workspace key, workspace name)
|
|
26
|
-
- ファイル操作 (拡張子取得, 言語検出, ソート)
|
|
27
|
-
- エラー処理 (エラーメッセージ, HTTPエラー)
|
|
28
|
-
- 文字列ユーティリティ (切り詰め, 短縮ID)
|
|
29
|
-
- ファイルサイズフォーマット
|
|
30
|
-
|
|
31
|
-
### utils-node.ts (50行)
|
|
32
|
-
|
|
33
|
-
Node.js専用ユーティリティ:
|
|
34
|
-
- `normalizeWorkspacePath()` - Node.js pathモジュールを使用した絶対パス正規化
|
|
35
|
-
- Node.js環境専用のパス操作関数
|
|
36
|
-
- ブラウザ互換ユーティリティの再エクスポート
|
|
37
|
-
|
|
38
|
-
## 使用方法
|
|
39
|
-
|
|
40
|
-
### Webアプリケーション
|
|
41
|
-
|
|
42
|
-
```typescript
|
|
43
|
-
import type { Workspace, Deck } from '@deck-ide/shared/types';
|
|
44
|
-
import { getLanguageFromPath, sortFileEntries } from '@deck-ide/shared/utils';
|
|
45
|
-
```
|
|
46
|
-
|
|
47
|
-
### サーバー (Node.js)
|
|
48
|
-
|
|
49
|
-
```typescript
|
|
50
|
-
import type { Workspace, Deck } from '@deck-ide/shared/types';
|
|
51
|
-
import {
|
|
52
|
-
normalizeWorkspacePath,
|
|
53
|
-
getWorkspaceKey,
|
|
54
|
-
sortFileEntries
|
|
55
|
-
} from '@deck-ide/shared/utils-node';
|
|
56
|
-
```
|
|
57
|
-
|
|
58
|
-
## プラットフォーム対応
|
|
59
|
-
|
|
60
|
-
- **utils.ts** - ブラウザとNode.js両方で動作
|
|
61
|
-
- **utils-node.ts** - Node.js専用 (Node.js APIを使用)
|
|
62
|
-
|
|
63
|
-
Webアプリケーションでは`utils.ts`を、サーバーでは`utils-node.ts`を使用してください。
|
|
64
|
-
|
|
65
|
-
## 開発
|
|
66
|
-
|
|
67
|
-
このパッケージはDeck IDEワークスペースの一部であり、npm workspacesにより自動的に他のパッケージにリンクされます。
|
|
68
|
-
|
|
69
|
-
詳細は `/docs/shared-package.md` を参照してください。
|
|
@@ -1,124 +0,0 @@
|
|
|
1
|
-
export type FileEntryType = 'file' | 'dir';
|
|
2
|
-
export interface Workspace {
|
|
3
|
-
id: string;
|
|
4
|
-
name: string;
|
|
5
|
-
path: string;
|
|
6
|
-
createdAt: string;
|
|
7
|
-
}
|
|
8
|
-
export interface Deck {
|
|
9
|
-
id: string;
|
|
10
|
-
name: string;
|
|
11
|
-
root: string;
|
|
12
|
-
workspaceId: string;
|
|
13
|
-
createdAt: string;
|
|
14
|
-
}
|
|
15
|
-
export interface FileSystemEntry {
|
|
16
|
-
name: string;
|
|
17
|
-
path: string;
|
|
18
|
-
type: FileEntryType;
|
|
19
|
-
}
|
|
20
|
-
export interface FileTreeNode extends FileSystemEntry {
|
|
21
|
-
expanded: boolean;
|
|
22
|
-
loading: boolean;
|
|
23
|
-
children?: FileTreeNode[];
|
|
24
|
-
}
|
|
25
|
-
export interface EditorFile {
|
|
26
|
-
id: string;
|
|
27
|
-
name: string;
|
|
28
|
-
path: string;
|
|
29
|
-
language: string;
|
|
30
|
-
contents: string;
|
|
31
|
-
dirty: boolean;
|
|
32
|
-
}
|
|
33
|
-
export interface TerminalSession {
|
|
34
|
-
id: string;
|
|
35
|
-
title: string;
|
|
36
|
-
createdAt?: string;
|
|
37
|
-
}
|
|
38
|
-
export interface WorkspaceState {
|
|
39
|
-
files: EditorFile[];
|
|
40
|
-
activeFileId: string | null;
|
|
41
|
-
tree: FileTreeNode[];
|
|
42
|
-
treeLoading: boolean;
|
|
43
|
-
treeError: string | null;
|
|
44
|
-
}
|
|
45
|
-
export interface DeckState {
|
|
46
|
-
terminals: TerminalSession[];
|
|
47
|
-
}
|
|
48
|
-
export interface ApiError {
|
|
49
|
-
error: string;
|
|
50
|
-
}
|
|
51
|
-
export interface ApiConfig {
|
|
52
|
-
defaultRoot: string;
|
|
53
|
-
}
|
|
54
|
-
export interface ApiFileResponse {
|
|
55
|
-
path: string;
|
|
56
|
-
contents: string;
|
|
57
|
-
}
|
|
58
|
-
export interface ApiFileSaveResponse {
|
|
59
|
-
path: string;
|
|
60
|
-
saved: boolean;
|
|
61
|
-
}
|
|
62
|
-
export interface ApiTerminalCreateResponse {
|
|
63
|
-
id: string;
|
|
64
|
-
title: string;
|
|
65
|
-
}
|
|
66
|
-
export interface CreateWorkspaceRequest {
|
|
67
|
-
path: string;
|
|
68
|
-
name?: string;
|
|
69
|
-
}
|
|
70
|
-
export interface CreateDeckRequest {
|
|
71
|
-
name?: string;
|
|
72
|
-
workspaceId: string;
|
|
73
|
-
}
|
|
74
|
-
export interface CreateTerminalRequest {
|
|
75
|
-
deckId: string;
|
|
76
|
-
title?: string;
|
|
77
|
-
}
|
|
78
|
-
export interface SaveFileRequest {
|
|
79
|
-
workspaceId: string;
|
|
80
|
-
path: string;
|
|
81
|
-
contents: string;
|
|
82
|
-
}
|
|
83
|
-
export interface GetFileRequest {
|
|
84
|
-
workspaceId: string;
|
|
85
|
-
path: string;
|
|
86
|
-
}
|
|
87
|
-
export interface GetFilesRequest {
|
|
88
|
-
workspaceId: string;
|
|
89
|
-
path?: string;
|
|
90
|
-
}
|
|
91
|
-
export interface GetPreviewRequest {
|
|
92
|
-
path: string;
|
|
93
|
-
subpath?: string;
|
|
94
|
-
}
|
|
95
|
-
export type GitFileStatusCode = 'modified' | 'staged' | 'untracked' | 'deleted' | 'renamed' | 'conflicted';
|
|
96
|
-
export interface GitFileStatus {
|
|
97
|
-
path: string;
|
|
98
|
-
status: GitFileStatusCode;
|
|
99
|
-
staged: boolean;
|
|
100
|
-
}
|
|
101
|
-
export interface GitStatus {
|
|
102
|
-
isGitRepo: boolean;
|
|
103
|
-
branch: string;
|
|
104
|
-
files: GitFileStatus[];
|
|
105
|
-
}
|
|
106
|
-
export interface GitDiff {
|
|
107
|
-
original: string;
|
|
108
|
-
modified: string;
|
|
109
|
-
path: string;
|
|
110
|
-
}
|
|
111
|
-
export interface GitRepoInfo {
|
|
112
|
-
path: string;
|
|
113
|
-
name: string;
|
|
114
|
-
branch: string;
|
|
115
|
-
fileCount: number;
|
|
116
|
-
}
|
|
117
|
-
export interface GitFileStatusWithRepo extends GitFileStatus {
|
|
118
|
-
repoPath: string;
|
|
119
|
-
}
|
|
120
|
-
export interface MultiRepoGitStatus {
|
|
121
|
-
repos: GitRepoInfo[];
|
|
122
|
-
files: GitFileStatusWithRepo[];
|
|
123
|
-
}
|
|
124
|
-
//# sourceMappingURL=types.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../types.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../types.ts"],"names":[],"mappings":"AAAA,yDAAyD"}
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Normalize a workspace path to an absolute path (Node.js version)
|
|
3
|
-
* @param inputPath - Input path (can be relative or absolute)
|
|
4
|
-
* @param defaultPath - Default path to use if inputPath is empty
|
|
5
|
-
* @returns Normalized absolute path
|
|
6
|
-
*/
|
|
7
|
-
export declare function normalizeWorkspacePath(inputPath: string, defaultPath: string): string;
|
|
8
|
-
/**
|
|
9
|
-
* Get a workspace key for indexing (handles case-insensitivity on Windows)
|
|
10
|
-
* @param workspacePath - Workspace path
|
|
11
|
-
* @returns Normalized key for indexing
|
|
12
|
-
*/
|
|
13
|
-
export declare function getWorkspaceKey(workspacePath: string): string;
|
|
14
|
-
/**
|
|
15
|
-
* Extract a workspace name from its path
|
|
16
|
-
* @param workspacePath - Workspace path
|
|
17
|
-
* @param fallbackIndex - Index to use for fallback name
|
|
18
|
-
* @returns Workspace name
|
|
19
|
-
*/
|
|
20
|
-
export declare function getWorkspaceName(workspacePath: string, fallbackIndex: number): string;
|
|
21
|
-
export { getFileExtension, getLanguageFromPath, normalizePathSeparators, isHidden, getErrorMessage, createHttpError, truncate, shortId, formatFileSize, sortFileEntries } from './utils.js';
|
|
22
|
-
//# sourceMappingURL=utils-node.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"utils-node.d.ts","sourceRoot":"","sources":["../utils-node.ts"],"names":[],"mappings":"AAKA;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,SAAS,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,MAAM,CAErF;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,aAAa,EAAE,MAAM,GAAG,MAAM,CAG7D;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,aAAa,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,MAAM,CAIrF;AAGD,OAAO,EACL,gBAAgB,EAChB,mBAAmB,EACnB,uBAAuB,EACvB,QAAQ,EACR,eAAe,EACf,eAAe,EACf,QAAQ,EACR,OAAO,EACP,cAAc,EACd,eAAe,EAChB,MAAM,YAAY,CAAC"}
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
// Node.js-specific utility functions
|
|
2
|
-
// This file should only be imported in Node.js environments (server)
|
|
3
|
-
import path from 'node:path';
|
|
4
|
-
/**
|
|
5
|
-
* Normalize a workspace path to an absolute path (Node.js version)
|
|
6
|
-
* @param inputPath - Input path (can be relative or absolute)
|
|
7
|
-
* @param defaultPath - Default path to use if inputPath is empty
|
|
8
|
-
* @returns Normalized absolute path
|
|
9
|
-
*/
|
|
10
|
-
export function normalizeWorkspacePath(inputPath, defaultPath) {
|
|
11
|
-
return path.resolve(inputPath || defaultPath);
|
|
12
|
-
}
|
|
13
|
-
/**
|
|
14
|
-
* Get a workspace key for indexing (handles case-insensitivity on Windows)
|
|
15
|
-
* @param workspacePath - Workspace path
|
|
16
|
-
* @returns Normalized key for indexing
|
|
17
|
-
*/
|
|
18
|
-
export function getWorkspaceKey(workspacePath) {
|
|
19
|
-
const normalized = workspacePath.replace(/[\\/]+$/, '');
|
|
20
|
-
return process.platform === 'win32' ? normalized.toLowerCase() : normalized;
|
|
21
|
-
}
|
|
22
|
-
/**
|
|
23
|
-
* Extract a workspace name from its path
|
|
24
|
-
* @param workspacePath - Workspace path
|
|
25
|
-
* @param fallbackIndex - Index to use for fallback name
|
|
26
|
-
* @returns Workspace name
|
|
27
|
-
*/
|
|
28
|
-
export function getWorkspaceName(workspacePath, fallbackIndex) {
|
|
29
|
-
const trimmed = workspacePath.replace(/[\\/]+$/, '');
|
|
30
|
-
const base = path.basename(trimmed);
|
|
31
|
-
return base || `Project ${fallbackIndex}`;
|
|
32
|
-
}
|
|
33
|
-
// Re-export browser-compatible utilities
|
|
34
|
-
export { getFileExtension, getLanguageFromPath, normalizePathSeparators, isHidden, getErrorMessage, createHttpError, truncate, shortId, formatFileSize, sortFileEntries } from './utils.js';
|
|
35
|
-
//# sourceMappingURL=utils-node.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"utils-node.js","sourceRoot":"","sources":["../utils-node.ts"],"names":[],"mappings":"AAAA,qCAAqC;AACrC,qEAAqE;AAErE,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B;;;;;GAKG;AACH,MAAM,UAAU,sBAAsB,CAAC,SAAiB,EAAE,WAAmB;IAC3E,OAAO,IAAI,CAAC,OAAO,CAAC,SAAS,IAAI,WAAW,CAAC,CAAC;AAChD,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,eAAe,CAAC,aAAqB;IACnD,MAAM,UAAU,GAAG,aAAa,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC;IACxD,OAAO,OAAO,CAAC,QAAQ,KAAK,OAAO,CAAC,CAAC,CAAC,UAAU,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC;AAC9E,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,gBAAgB,CAAC,aAAqB,EAAE,aAAqB;IAC3E,MAAM,OAAO,GAAG,aAAa,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC;IACrD,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;IACpC,OAAO,IAAI,IAAI,WAAW,aAAa,EAAE,CAAC;AAC5C,CAAC;AAED,yCAAyC;AACzC,OAAO,EACL,gBAAgB,EAChB,mBAAmB,EACnB,uBAAuB,EACvB,QAAQ,EACR,eAAe,EACf,eAAe,EACf,QAAQ,EACR,OAAO,EACP,cAAc,EACd,eAAe,EAChB,MAAM,YAAY,CAAC"}
|
|
@@ -1,90 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Get a workspace key for indexing (handles case-insensitivity on Windows)
|
|
3
|
-
* @param workspacePath - Workspace path
|
|
4
|
-
* @returns Normalized key for indexing
|
|
5
|
-
*/
|
|
6
|
-
export declare function getWorkspaceKey(workspacePath: string): string;
|
|
7
|
-
/**
|
|
8
|
-
* Extract a workspace name from its path
|
|
9
|
-
* @param workspacePath - Workspace path
|
|
10
|
-
* @param fallbackIndex - Index to use for fallback name
|
|
11
|
-
* @returns Workspace name
|
|
12
|
-
*/
|
|
13
|
-
export declare function getWorkspaceName(workspacePath: string, fallbackIndex: number): string;
|
|
14
|
-
/**
|
|
15
|
-
* Normalize a workspace path to an absolute path
|
|
16
|
-
* Note: This function requires Node.js path module
|
|
17
|
-
* For browser usage, import from utils-node.ts instead
|
|
18
|
-
* @param inputPath - Input path (can be relative or absolute)
|
|
19
|
-
* @param defaultPath - Default path to use if inputPath is empty
|
|
20
|
-
* @returns Normalized absolute path
|
|
21
|
-
*/
|
|
22
|
-
export declare function normalizeWorkspacePath(inputPath: string, defaultPath: string): string;
|
|
23
|
-
/**
|
|
24
|
-
* Get file extension from a path
|
|
25
|
-
* @param filePath - File path
|
|
26
|
-
* @returns File extension (without dot) or empty string
|
|
27
|
-
*/
|
|
28
|
-
export declare function getFileExtension(filePath: string): string;
|
|
29
|
-
/**
|
|
30
|
-
* Map file extension to Monaco editor language
|
|
31
|
-
* @param filePath - File path
|
|
32
|
-
* @returns Monaco language identifier
|
|
33
|
-
*/
|
|
34
|
-
export declare function getLanguageFromPath(filePath: string): string;
|
|
35
|
-
/**
|
|
36
|
-
* Normalize path separators to forward slashes
|
|
37
|
-
* @param inputPath - Input path
|
|
38
|
-
* @returns Path with forward slashes
|
|
39
|
-
*/
|
|
40
|
-
export declare function normalizePathSeparators(inputPath: string): string;
|
|
41
|
-
/**
|
|
42
|
-
* Check if a path is a hidden file or directory (starts with .)
|
|
43
|
-
* @param name - File or directory name
|
|
44
|
-
* @returns True if hidden
|
|
45
|
-
*/
|
|
46
|
-
export declare function isHidden(name: string): boolean;
|
|
47
|
-
/**
|
|
48
|
-
* Get error message from unknown error type
|
|
49
|
-
* @param error - Error object
|
|
50
|
-
* @returns Error message string
|
|
51
|
-
*/
|
|
52
|
-
export declare function getErrorMessage(error: unknown): string;
|
|
53
|
-
/**
|
|
54
|
-
* Create an HTTP error with status code
|
|
55
|
-
* @param message - Error message
|
|
56
|
-
* @param status - HTTP status code
|
|
57
|
-
* @returns Error object with status property
|
|
58
|
-
*/
|
|
59
|
-
export declare function createHttpError(message: string, status: number): Error & {
|
|
60
|
-
status: number;
|
|
61
|
-
};
|
|
62
|
-
/**
|
|
63
|
-
* Truncate string to max length with ellipsis
|
|
64
|
-
* @param str - Input string
|
|
65
|
-
* @param maxLength - Maximum length
|
|
66
|
-
* @returns Truncated string
|
|
67
|
-
*/
|
|
68
|
-
export declare function truncate(str: string, maxLength: number): string;
|
|
69
|
-
/**
|
|
70
|
-
* Generate a short ID from a UUID (first 8 characters)
|
|
71
|
-
* @param uuid - Full UUID
|
|
72
|
-
* @returns Short ID
|
|
73
|
-
*/
|
|
74
|
-
export declare function shortId(uuid: string): string;
|
|
75
|
-
/**
|
|
76
|
-
* Format file size in human-readable format
|
|
77
|
-
* @param bytes - File size in bytes
|
|
78
|
-
* @returns Formatted file size string
|
|
79
|
-
*/
|
|
80
|
-
export declare function formatFileSize(bytes: number): string;
|
|
81
|
-
/**
|
|
82
|
-
* Sort file system entries (directories first, then alphabetically)
|
|
83
|
-
* @param entries - Array of file system entries
|
|
84
|
-
* @returns Sorted array
|
|
85
|
-
*/
|
|
86
|
-
export declare function sortFileEntries<T extends {
|
|
87
|
-
name: string;
|
|
88
|
-
type: 'file' | 'dir';
|
|
89
|
-
}>(entries: T[]): T[];
|
|
90
|
-
//# sourceMappingURL=utils.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../utils.ts"],"names":[],"mappings":"AAEA;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,aAAa,EAAE,MAAM,GAAG,MAAM,CAK7D;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,aAAa,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,MAAM,CAMrF;AAED;;;;;;;GAOG;AACH,wBAAgB,sBAAsB,CAAC,SAAS,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,MAAM,CAIrF;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAKzD;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CA+C5D;AAED;;;;GAIG;AACH,wBAAgB,uBAAuB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAEjE;AAED;;;;GAIG;AACH,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAE9C;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAKtD;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,KAAK,GAAG;IAAE,MAAM,EAAE,MAAM,CAAA;CAAE,CAI3F;AAED;;;;;GAKG;AACH,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAG/D;AAED;;;;GAIG;AACH,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAE5C;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAMpD;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,CAAC,SAAS;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,GAAG,KAAK,CAAA;CAAE,EAAE,OAAO,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE,CAOnG"}
|
|
@@ -1,186 +0,0 @@
|
|
|
1
|
-
// Shared utility functions (browser-compatible)
|
|
2
|
-
/**
|
|
3
|
-
* Get a workspace key for indexing (handles case-insensitivity on Windows)
|
|
4
|
-
* @param workspacePath - Workspace path
|
|
5
|
-
* @returns Normalized key for indexing
|
|
6
|
-
*/
|
|
7
|
-
export function getWorkspaceKey(workspacePath) {
|
|
8
|
-
const normalized = workspacePath.replace(/[\\/]+$/, '');
|
|
9
|
-
// In browser, we can't detect platform, so we normalize to lowercase
|
|
10
|
-
const platform = typeof process !== 'undefined' ? process.platform : 'unknown';
|
|
11
|
-
return platform === 'win32' ? normalized.toLowerCase() : normalized;
|
|
12
|
-
}
|
|
13
|
-
/**
|
|
14
|
-
* Extract a workspace name from its path
|
|
15
|
-
* @param workspacePath - Workspace path
|
|
16
|
-
* @param fallbackIndex - Index to use for fallback name
|
|
17
|
-
* @returns Workspace name
|
|
18
|
-
*/
|
|
19
|
-
export function getWorkspaceName(workspacePath, fallbackIndex) {
|
|
20
|
-
const trimmed = workspacePath.replace(/[\\/]+$/, '');
|
|
21
|
-
// Browser-compatible basename
|
|
22
|
-
const parts = trimmed.split(/[\\/]/);
|
|
23
|
-
const base = parts[parts.length - 1] || '';
|
|
24
|
-
return base || `Project ${fallbackIndex}`;
|
|
25
|
-
}
|
|
26
|
-
/**
|
|
27
|
-
* Normalize a workspace path to an absolute path
|
|
28
|
-
* Note: This function requires Node.js path module
|
|
29
|
-
* For browser usage, import from utils-node.ts instead
|
|
30
|
-
* @param inputPath - Input path (can be relative or absolute)
|
|
31
|
-
* @param defaultPath - Default path to use if inputPath is empty
|
|
32
|
-
* @returns Normalized absolute path
|
|
33
|
-
*/
|
|
34
|
-
export function normalizeWorkspacePath(inputPath, defaultPath) {
|
|
35
|
-
// This is a simplified version for browsers
|
|
36
|
-
// Server code should use the Node.js version from utils-node.ts
|
|
37
|
-
return inputPath || defaultPath;
|
|
38
|
-
}
|
|
39
|
-
/**
|
|
40
|
-
* Get file extension from a path
|
|
41
|
-
* @param filePath - File path
|
|
42
|
-
* @returns File extension (without dot) or empty string
|
|
43
|
-
*/
|
|
44
|
-
export function getFileExtension(filePath) {
|
|
45
|
-
const lastDot = filePath.lastIndexOf('.');
|
|
46
|
-
if (lastDot === -1 || lastDot === 0)
|
|
47
|
-
return '';
|
|
48
|
-
const ext = filePath.slice(lastDot + 1);
|
|
49
|
-
return ext.toLowerCase();
|
|
50
|
-
}
|
|
51
|
-
/**
|
|
52
|
-
* Map file extension to Monaco editor language
|
|
53
|
-
* @param filePath - File path
|
|
54
|
-
* @returns Monaco language identifier
|
|
55
|
-
*/
|
|
56
|
-
export function getLanguageFromPath(filePath) {
|
|
57
|
-
const ext = getFileExtension(filePath);
|
|
58
|
-
const languageMap = {
|
|
59
|
-
'js': 'javascript',
|
|
60
|
-
'jsx': 'javascript',
|
|
61
|
-
'ts': 'typescript',
|
|
62
|
-
'tsx': 'typescript',
|
|
63
|
-
'json': 'json',
|
|
64
|
-
'html': 'html',
|
|
65
|
-
'css': 'css',
|
|
66
|
-
'scss': 'scss',
|
|
67
|
-
'sass': 'sass',
|
|
68
|
-
'less': 'less',
|
|
69
|
-
'md': 'markdown',
|
|
70
|
-
'py': 'python',
|
|
71
|
-
'rb': 'ruby',
|
|
72
|
-
'go': 'go',
|
|
73
|
-
'rs': 'rust',
|
|
74
|
-
'java': 'java',
|
|
75
|
-
'c': 'c',
|
|
76
|
-
'cpp': 'cpp',
|
|
77
|
-
'cc': 'cpp',
|
|
78
|
-
'cxx': 'cpp',
|
|
79
|
-
'h': 'c',
|
|
80
|
-
'hpp': 'cpp',
|
|
81
|
-
'sh': 'shell',
|
|
82
|
-
'bash': 'shell',
|
|
83
|
-
'zsh': 'shell',
|
|
84
|
-
'fish': 'shell',
|
|
85
|
-
'xml': 'xml',
|
|
86
|
-
'yaml': 'yaml',
|
|
87
|
-
'yml': 'yaml',
|
|
88
|
-
'toml': 'toml',
|
|
89
|
-
'sql': 'sql',
|
|
90
|
-
'graphql': 'graphql',
|
|
91
|
-
'vue': 'vue',
|
|
92
|
-
'svelte': 'svelte',
|
|
93
|
-
'php': 'php',
|
|
94
|
-
'r': 'r',
|
|
95
|
-
'swift': 'swift',
|
|
96
|
-
'kt': 'kotlin',
|
|
97
|
-
'dart': 'dart',
|
|
98
|
-
'lua': 'lua',
|
|
99
|
-
'dockerfile': 'dockerfile',
|
|
100
|
-
};
|
|
101
|
-
return languageMap[ext] || 'plaintext';
|
|
102
|
-
}
|
|
103
|
-
/**
|
|
104
|
-
* Normalize path separators to forward slashes
|
|
105
|
-
* @param inputPath - Input path
|
|
106
|
-
* @returns Path with forward slashes
|
|
107
|
-
*/
|
|
108
|
-
export function normalizePathSeparators(inputPath) {
|
|
109
|
-
return inputPath.replace(/\\/g, '/');
|
|
110
|
-
}
|
|
111
|
-
/**
|
|
112
|
-
* Check if a path is a hidden file or directory (starts with .)
|
|
113
|
-
* @param name - File or directory name
|
|
114
|
-
* @returns True if hidden
|
|
115
|
-
*/
|
|
116
|
-
export function isHidden(name) {
|
|
117
|
-
return name.startsWith('.');
|
|
118
|
-
}
|
|
119
|
-
/**
|
|
120
|
-
* Get error message from unknown error type
|
|
121
|
-
* @param error - Error object
|
|
122
|
-
* @returns Error message string
|
|
123
|
-
*/
|
|
124
|
-
export function getErrorMessage(error) {
|
|
125
|
-
if (error instanceof Error) {
|
|
126
|
-
return error.message;
|
|
127
|
-
}
|
|
128
|
-
return String(error);
|
|
129
|
-
}
|
|
130
|
-
/**
|
|
131
|
-
* Create an HTTP error with status code
|
|
132
|
-
* @param message - Error message
|
|
133
|
-
* @param status - HTTP status code
|
|
134
|
-
* @returns Error object with status property
|
|
135
|
-
*/
|
|
136
|
-
export function createHttpError(message, status) {
|
|
137
|
-
const error = new Error(message);
|
|
138
|
-
error.status = status;
|
|
139
|
-
return error;
|
|
140
|
-
}
|
|
141
|
-
/**
|
|
142
|
-
* Truncate string to max length with ellipsis
|
|
143
|
-
* @param str - Input string
|
|
144
|
-
* @param maxLength - Maximum length
|
|
145
|
-
* @returns Truncated string
|
|
146
|
-
*/
|
|
147
|
-
export function truncate(str, maxLength) {
|
|
148
|
-
if (str.length <= maxLength)
|
|
149
|
-
return str;
|
|
150
|
-
return str.slice(0, maxLength - 3) + '...';
|
|
151
|
-
}
|
|
152
|
-
/**
|
|
153
|
-
* Generate a short ID from a UUID (first 8 characters)
|
|
154
|
-
* @param uuid - Full UUID
|
|
155
|
-
* @returns Short ID
|
|
156
|
-
*/
|
|
157
|
-
export function shortId(uuid) {
|
|
158
|
-
return uuid.slice(0, 8);
|
|
159
|
-
}
|
|
160
|
-
/**
|
|
161
|
-
* Format file size in human-readable format
|
|
162
|
-
* @param bytes - File size in bytes
|
|
163
|
-
* @returns Formatted file size string
|
|
164
|
-
*/
|
|
165
|
-
export function formatFileSize(bytes) {
|
|
166
|
-
if (bytes === 0)
|
|
167
|
-
return '0 B';
|
|
168
|
-
const k = 1024;
|
|
169
|
-
const sizes = ['B', 'KB', 'MB', 'GB', 'TB'];
|
|
170
|
-
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
171
|
-
return `${parseFloat((bytes / Math.pow(k, i)).toFixed(2))} ${sizes[i]}`;
|
|
172
|
-
}
|
|
173
|
-
/**
|
|
174
|
-
* Sort file system entries (directories first, then alphabetically)
|
|
175
|
-
* @param entries - Array of file system entries
|
|
176
|
-
* @returns Sorted array
|
|
177
|
-
*/
|
|
178
|
-
export function sortFileEntries(entries) {
|
|
179
|
-
return entries.sort((a, b) => {
|
|
180
|
-
if (a.type !== b.type) {
|
|
181
|
-
return a.type === 'dir' ? -1 : 1;
|
|
182
|
-
}
|
|
183
|
-
return a.name.localeCompare(b.name);
|
|
184
|
-
});
|
|
185
|
-
}
|
|
186
|
-
//# sourceMappingURL=utils.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../utils.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@deck-ide/shared",
|
|
3
|
-
"version": "1.0.0",
|
|
4
|
-
"type": "module",
|
|
5
|
-
"exports": {
|
|
6
|
-
"./types": "./dist/types.js",
|
|
7
|
-
"./utils": "./dist/utils.js",
|
|
8
|
-
"./utils-node": "./dist/utils-node.js"
|
|
9
|
-
},
|
|
10
|
-
"scripts": {
|
|
11
|
-
"build": "tsc"
|
|
12
|
-
},
|
|
13
|
-
"devDependencies": {
|
|
14
|
-
"typescript": "^5.7.2"
|
|
15
|
-
}
|
|
16
|
-
}
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"compilerOptions": {
|
|
3
|
-
"target": "ES2022",
|
|
4
|
-
"lib": ["ES2022"],
|
|
5
|
-
"module": "NodeNext",
|
|
6
|
-
"moduleResolution": "NodeNext",
|
|
7
|
-
"resolveJsonModule": true,
|
|
8
|
-
"declaration": true,
|
|
9
|
-
"declarationMap": true,
|
|
10
|
-
"sourceMap": true,
|
|
11
|
-
"outDir": "./dist",
|
|
12
|
-
"strict": true,
|
|
13
|
-
"esModuleInterop": true,
|
|
14
|
-
"skipLibCheck": true,
|
|
15
|
-
"forceConsistentCasingInFileNames": true,
|
|
16
|
-
"types": ["node"]
|
|
17
|
-
},
|
|
18
|
-
"include": ["*.ts"],
|
|
19
|
-
"exclude": ["node_modules", "dist"]
|
|
20
|
-
}
|
|
@@ -1,174 +0,0 @@
|
|
|
1
|
-
// Core domain types shared across the entire application
|
|
2
|
-
|
|
3
|
-
export type FileEntryType = 'file' | 'dir';
|
|
4
|
-
|
|
5
|
-
// Workspace represents a project root directory
|
|
6
|
-
export interface Workspace {
|
|
7
|
-
id: string;
|
|
8
|
-
name: string;
|
|
9
|
-
path: string;
|
|
10
|
-
createdAt: string;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
// Deck represents a workspace view with terminals and editors
|
|
14
|
-
export interface Deck {
|
|
15
|
-
id: string;
|
|
16
|
-
name: string;
|
|
17
|
-
root: string;
|
|
18
|
-
workspaceId: string;
|
|
19
|
-
createdAt: string;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
// File system entry (file or directory)
|
|
23
|
-
export interface FileSystemEntry {
|
|
24
|
-
name: string;
|
|
25
|
-
path: string;
|
|
26
|
-
type: FileEntryType;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
// Extended file tree node with UI state
|
|
30
|
-
export interface FileTreeNode extends FileSystemEntry {
|
|
31
|
-
expanded: boolean;
|
|
32
|
-
loading: boolean;
|
|
33
|
-
children?: FileTreeNode[];
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
// Editor file representation
|
|
37
|
-
export interface EditorFile {
|
|
38
|
-
id: string;
|
|
39
|
-
name: string;
|
|
40
|
-
path: string;
|
|
41
|
-
language: string;
|
|
42
|
-
contents: string;
|
|
43
|
-
dirty: boolean;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
// Terminal session
|
|
47
|
-
export interface TerminalSession {
|
|
48
|
-
id: string;
|
|
49
|
-
title: string;
|
|
50
|
-
createdAt?: string;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
// UI State types
|
|
54
|
-
|
|
55
|
-
export interface WorkspaceState {
|
|
56
|
-
files: EditorFile[];
|
|
57
|
-
activeFileId: string | null;
|
|
58
|
-
tree: FileTreeNode[];
|
|
59
|
-
treeLoading: boolean;
|
|
60
|
-
treeError: string | null;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
export interface DeckState {
|
|
64
|
-
terminals: TerminalSession[];
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
// API Response types
|
|
68
|
-
|
|
69
|
-
export interface ApiError {
|
|
70
|
-
error: string;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
export interface ApiConfig {
|
|
74
|
-
defaultRoot: string;
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
export interface ApiFileResponse {
|
|
78
|
-
path: string;
|
|
79
|
-
contents: string;
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
export interface ApiFileSaveResponse {
|
|
83
|
-
path: string;
|
|
84
|
-
saved: boolean;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
export interface ApiTerminalCreateResponse {
|
|
88
|
-
id: string;
|
|
89
|
-
title: string;
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
// API Request types
|
|
93
|
-
|
|
94
|
-
export interface CreateWorkspaceRequest {
|
|
95
|
-
path: string;
|
|
96
|
-
name?: string;
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
export interface CreateDeckRequest {
|
|
100
|
-
name?: string;
|
|
101
|
-
workspaceId: string;
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
export interface CreateTerminalRequest {
|
|
105
|
-
deckId: string;
|
|
106
|
-
title?: string;
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
export interface SaveFileRequest {
|
|
110
|
-
workspaceId: string;
|
|
111
|
-
path: string;
|
|
112
|
-
contents: string;
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
export interface GetFileRequest {
|
|
116
|
-
workspaceId: string;
|
|
117
|
-
path: string;
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
export interface GetFilesRequest {
|
|
121
|
-
workspaceId: string;
|
|
122
|
-
path?: string;
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
export interface GetPreviewRequest {
|
|
126
|
-
path: string;
|
|
127
|
-
subpath?: string;
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
// Git types
|
|
131
|
-
|
|
132
|
-
export type GitFileStatusCode =
|
|
133
|
-
| 'modified'
|
|
134
|
-
| 'staged'
|
|
135
|
-
| 'untracked'
|
|
136
|
-
| 'deleted'
|
|
137
|
-
| 'renamed'
|
|
138
|
-
| 'conflicted';
|
|
139
|
-
|
|
140
|
-
export interface GitFileStatus {
|
|
141
|
-
path: string;
|
|
142
|
-
status: GitFileStatusCode;
|
|
143
|
-
staged: boolean;
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
export interface GitStatus {
|
|
147
|
-
isGitRepo: boolean;
|
|
148
|
-
branch: string;
|
|
149
|
-
files: GitFileStatus[];
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
export interface GitDiff {
|
|
153
|
-
original: string;
|
|
154
|
-
modified: string;
|
|
155
|
-
path: string;
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
// Multi-repo support types
|
|
159
|
-
|
|
160
|
-
export interface GitRepoInfo {
|
|
161
|
-
path: string; // Relative path from workspace root (empty string for root repo)
|
|
162
|
-
name: string; // Display name (folder name or 'root')
|
|
163
|
-
branch: string;
|
|
164
|
-
fileCount: number; // Number of changed files
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
export interface GitFileStatusWithRepo extends GitFileStatus {
|
|
168
|
-
repoPath: string; // Which repo this file belongs to
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
export interface MultiRepoGitStatus {
|
|
172
|
-
repos: GitRepoInfo[];
|
|
173
|
-
files: GitFileStatusWithRepo[];
|
|
174
|
-
}
|
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
// Node.js-specific utility functions
|
|
2
|
-
// This file should only be imported in Node.js environments (server)
|
|
3
|
-
|
|
4
|
-
import path from 'node:path';
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* Normalize a workspace path to an absolute path (Node.js version)
|
|
8
|
-
* @param inputPath - Input path (can be relative or absolute)
|
|
9
|
-
* @param defaultPath - Default path to use if inputPath is empty
|
|
10
|
-
* @returns Normalized absolute path
|
|
11
|
-
*/
|
|
12
|
-
export function normalizeWorkspacePath(inputPath: string, defaultPath: string): string {
|
|
13
|
-
return path.resolve(inputPath || defaultPath);
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* Get a workspace key for indexing (handles case-insensitivity on Windows)
|
|
18
|
-
* @param workspacePath - Workspace path
|
|
19
|
-
* @returns Normalized key for indexing
|
|
20
|
-
*/
|
|
21
|
-
export function getWorkspaceKey(workspacePath: string): string {
|
|
22
|
-
const normalized = workspacePath.replace(/[\\/]+$/, '');
|
|
23
|
-
return process.platform === 'win32' ? normalized.toLowerCase() : normalized;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* Extract a workspace name from its path
|
|
28
|
-
* @param workspacePath - Workspace path
|
|
29
|
-
* @param fallbackIndex - Index to use for fallback name
|
|
30
|
-
* @returns Workspace name
|
|
31
|
-
*/
|
|
32
|
-
export function getWorkspaceName(workspacePath: string, fallbackIndex: number): string {
|
|
33
|
-
const trimmed = workspacePath.replace(/[\\/]+$/, '');
|
|
34
|
-
const base = path.basename(trimmed);
|
|
35
|
-
return base || `Project ${fallbackIndex}`;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
// Re-export browser-compatible utilities
|
|
39
|
-
export {
|
|
40
|
-
getFileExtension,
|
|
41
|
-
getLanguageFromPath,
|
|
42
|
-
normalizePathSeparators,
|
|
43
|
-
isHidden,
|
|
44
|
-
getErrorMessage,
|
|
45
|
-
createHttpError,
|
|
46
|
-
truncate,
|
|
47
|
-
shortId,
|
|
48
|
-
formatFileSize,
|
|
49
|
-
sortFileEntries
|
|
50
|
-
} from './utils.js';
|
|
@@ -1,196 +0,0 @@
|
|
|
1
|
-
// Shared utility functions (browser-compatible)
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Get a workspace key for indexing (handles case-insensitivity on Windows)
|
|
5
|
-
* @param workspacePath - Workspace path
|
|
6
|
-
* @returns Normalized key for indexing
|
|
7
|
-
*/
|
|
8
|
-
export function getWorkspaceKey(workspacePath: string): string {
|
|
9
|
-
const normalized = workspacePath.replace(/[\\/]+$/, '');
|
|
10
|
-
// In browser, we can't detect platform, so we normalize to lowercase
|
|
11
|
-
const platform = typeof process !== 'undefined' ? process.platform : 'unknown';
|
|
12
|
-
return platform === 'win32' ? normalized.toLowerCase() : normalized;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* Extract a workspace name from its path
|
|
17
|
-
* @param workspacePath - Workspace path
|
|
18
|
-
* @param fallbackIndex - Index to use for fallback name
|
|
19
|
-
* @returns Workspace name
|
|
20
|
-
*/
|
|
21
|
-
export function getWorkspaceName(workspacePath: string, fallbackIndex: number): string {
|
|
22
|
-
const trimmed = workspacePath.replace(/[\\/]+$/, '');
|
|
23
|
-
// Browser-compatible basename
|
|
24
|
-
const parts = trimmed.split(/[\\/]/);
|
|
25
|
-
const base = parts[parts.length - 1] || '';
|
|
26
|
-
return base || `Project ${fallbackIndex}`;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
/**
|
|
30
|
-
* Normalize a workspace path to an absolute path
|
|
31
|
-
* Note: This function requires Node.js path module
|
|
32
|
-
* For browser usage, import from utils-node.ts instead
|
|
33
|
-
* @param inputPath - Input path (can be relative or absolute)
|
|
34
|
-
* @param defaultPath - Default path to use if inputPath is empty
|
|
35
|
-
* @returns Normalized absolute path
|
|
36
|
-
*/
|
|
37
|
-
export function normalizeWorkspacePath(inputPath: string, defaultPath: string): string {
|
|
38
|
-
// This is a simplified version for browsers
|
|
39
|
-
// Server code should use the Node.js version from utils-node.ts
|
|
40
|
-
return inputPath || defaultPath;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
/**
|
|
44
|
-
* Get file extension from a path
|
|
45
|
-
* @param filePath - File path
|
|
46
|
-
* @returns File extension (without dot) or empty string
|
|
47
|
-
*/
|
|
48
|
-
export function getFileExtension(filePath: string): string {
|
|
49
|
-
const lastDot = filePath.lastIndexOf('.');
|
|
50
|
-
if (lastDot === -1 || lastDot === 0) return '';
|
|
51
|
-
const ext = filePath.slice(lastDot + 1);
|
|
52
|
-
return ext.toLowerCase();
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
/**
|
|
56
|
-
* Map file extension to Monaco editor language
|
|
57
|
-
* @param filePath - File path
|
|
58
|
-
* @returns Monaco language identifier
|
|
59
|
-
*/
|
|
60
|
-
export function getLanguageFromPath(filePath: string): string {
|
|
61
|
-
const ext = getFileExtension(filePath);
|
|
62
|
-
const languageMap: Record<string, string> = {
|
|
63
|
-
'js': 'javascript',
|
|
64
|
-
'jsx': 'javascript',
|
|
65
|
-
'ts': 'typescript',
|
|
66
|
-
'tsx': 'typescript',
|
|
67
|
-
'json': 'json',
|
|
68
|
-
'html': 'html',
|
|
69
|
-
'css': 'css',
|
|
70
|
-
'scss': 'scss',
|
|
71
|
-
'sass': 'sass',
|
|
72
|
-
'less': 'less',
|
|
73
|
-
'md': 'markdown',
|
|
74
|
-
'py': 'python',
|
|
75
|
-
'rb': 'ruby',
|
|
76
|
-
'go': 'go',
|
|
77
|
-
'rs': 'rust',
|
|
78
|
-
'java': 'java',
|
|
79
|
-
'c': 'c',
|
|
80
|
-
'cpp': 'cpp',
|
|
81
|
-
'cc': 'cpp',
|
|
82
|
-
'cxx': 'cpp',
|
|
83
|
-
'h': 'c',
|
|
84
|
-
'hpp': 'cpp',
|
|
85
|
-
'sh': 'shell',
|
|
86
|
-
'bash': 'shell',
|
|
87
|
-
'zsh': 'shell',
|
|
88
|
-
'fish': 'shell',
|
|
89
|
-
'xml': 'xml',
|
|
90
|
-
'yaml': 'yaml',
|
|
91
|
-
'yml': 'yaml',
|
|
92
|
-
'toml': 'toml',
|
|
93
|
-
'sql': 'sql',
|
|
94
|
-
'graphql': 'graphql',
|
|
95
|
-
'vue': 'vue',
|
|
96
|
-
'svelte': 'svelte',
|
|
97
|
-
'php': 'php',
|
|
98
|
-
'r': 'r',
|
|
99
|
-
'swift': 'swift',
|
|
100
|
-
'kt': 'kotlin',
|
|
101
|
-
'dart': 'dart',
|
|
102
|
-
'lua': 'lua',
|
|
103
|
-
'dockerfile': 'dockerfile',
|
|
104
|
-
};
|
|
105
|
-
|
|
106
|
-
return languageMap[ext] || 'plaintext';
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
/**
|
|
110
|
-
* Normalize path separators to forward slashes
|
|
111
|
-
* @param inputPath - Input path
|
|
112
|
-
* @returns Path with forward slashes
|
|
113
|
-
*/
|
|
114
|
-
export function normalizePathSeparators(inputPath: string): string {
|
|
115
|
-
return inputPath.replace(/\\/g, '/');
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
/**
|
|
119
|
-
* Check if a path is a hidden file or directory (starts with .)
|
|
120
|
-
* @param name - File or directory name
|
|
121
|
-
* @returns True if hidden
|
|
122
|
-
*/
|
|
123
|
-
export function isHidden(name: string): boolean {
|
|
124
|
-
return name.startsWith('.');
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
/**
|
|
128
|
-
* Get error message from unknown error type
|
|
129
|
-
* @param error - Error object
|
|
130
|
-
* @returns Error message string
|
|
131
|
-
*/
|
|
132
|
-
export function getErrorMessage(error: unknown): string {
|
|
133
|
-
if (error instanceof Error) {
|
|
134
|
-
return error.message;
|
|
135
|
-
}
|
|
136
|
-
return String(error);
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
/**
|
|
140
|
-
* Create an HTTP error with status code
|
|
141
|
-
* @param message - Error message
|
|
142
|
-
* @param status - HTTP status code
|
|
143
|
-
* @returns Error object with status property
|
|
144
|
-
*/
|
|
145
|
-
export function createHttpError(message: string, status: number): Error & { status: number } {
|
|
146
|
-
const error = new Error(message) as Error & { status: number };
|
|
147
|
-
error.status = status;
|
|
148
|
-
return error;
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
/**
|
|
152
|
-
* Truncate string to max length with ellipsis
|
|
153
|
-
* @param str - Input string
|
|
154
|
-
* @param maxLength - Maximum length
|
|
155
|
-
* @returns Truncated string
|
|
156
|
-
*/
|
|
157
|
-
export function truncate(str: string, maxLength: number): string {
|
|
158
|
-
if (str.length <= maxLength) return str;
|
|
159
|
-
return str.slice(0, maxLength - 3) + '...';
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
/**
|
|
163
|
-
* Generate a short ID from a UUID (first 8 characters)
|
|
164
|
-
* @param uuid - Full UUID
|
|
165
|
-
* @returns Short ID
|
|
166
|
-
*/
|
|
167
|
-
export function shortId(uuid: string): string {
|
|
168
|
-
return uuid.slice(0, 8);
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
/**
|
|
172
|
-
* Format file size in human-readable format
|
|
173
|
-
* @param bytes - File size in bytes
|
|
174
|
-
* @returns Formatted file size string
|
|
175
|
-
*/
|
|
176
|
-
export function formatFileSize(bytes: number): string {
|
|
177
|
-
if (bytes === 0) return '0 B';
|
|
178
|
-
const k = 1024;
|
|
179
|
-
const sizes = ['B', 'KB', 'MB', 'GB', 'TB'];
|
|
180
|
-
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
181
|
-
return `${parseFloat((bytes / Math.pow(k, i)).toFixed(2))} ${sizes[i]}`;
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
/**
|
|
185
|
-
* Sort file system entries (directories first, then alphabetically)
|
|
186
|
-
* @param entries - Array of file system entries
|
|
187
|
-
* @returns Sorted array
|
|
188
|
-
*/
|
|
189
|
-
export function sortFileEntries<T extends { name: string; type: 'file' | 'dir' }>(entries: T[]): T[] {
|
|
190
|
-
return entries.sort((a, b) => {
|
|
191
|
-
if (a.type !== b.type) {
|
|
192
|
-
return a.type === 'dir' ? -1 : 1;
|
|
193
|
-
}
|
|
194
|
-
return a.name.localeCompare(b.name);
|
|
195
|
-
});
|
|
196
|
-
}
|