@kadi.build/file-sharing 1.2.0 → 1.2.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/package.json CHANGED
@@ -1,18 +1,21 @@
1
1
  {
2
2
  "name": "@kadi.build/file-sharing",
3
- "version": "1.2.0",
3
+ "version": "1.2.1",
4
4
  "description": "File sharing service with tunneling and local S3-compatible interface",
5
5
  "type": "module",
6
6
  "main": "src/index.js",
7
+ "types": "types/index.d.ts",
7
8
  "exports": {
8
9
  ".": {
9
- "import": "./src/index.js",
10
- "types": "./types/index.d.ts"
10
+ "types": "./types/index.d.ts",
11
+ "import": "./src/index.js"
11
12
  },
12
13
  "./s3": {
14
+ "types": "./types/S3Server.d.ts",
13
15
  "import": "./src/S3Server.js"
14
16
  },
15
17
  "./http": {
18
+ "types": "./types/HttpServerProvider.d.ts",
16
19
  "import": "./src/HttpServerProvider.js"
17
20
  }
18
21
  },
@@ -52,6 +55,7 @@
52
55
  },
53
56
  "devDependencies": {
54
57
  "@aws-sdk/client-s3": "^3.0.0",
58
+ "@types/node": "^20.19.33",
55
59
  "supertest": "^6.0.0"
56
60
  },
57
61
  "engines": {
@@ -0,0 +1,100 @@
1
+ /// <reference types="node" />
2
+ import { EventEmitter } from 'events';
3
+
4
+ export interface DownloadRecord {
5
+ id: string;
6
+ file: string;
7
+ totalSize: number;
8
+ clientIp: string;
9
+ bytesTransferred: number;
10
+ progress: number;
11
+ speed: number;
12
+ startTime: number;
13
+ endTime?: number;
14
+ duration?: number;
15
+ status: 'active' | 'completed' | 'failed' | 'cancelled';
16
+ error?: string;
17
+ [key: string]: any;
18
+ }
19
+
20
+ export interface DownloadMetadata {
21
+ file?: string;
22
+ totalSize?: number;
23
+ size?: number;
24
+ clientIp?: string;
25
+ [key: string]: any;
26
+ }
27
+
28
+ export interface DownloadStats {
29
+ totalBytes: number;
30
+ totalDownloads: number;
31
+ activeCount: number;
32
+ failedCount: number;
33
+ averageSpeed: number;
34
+ peakConcurrent: number;
35
+ activeDownloads: DownloadRecord[];
36
+ }
37
+
38
+ export class DownloadMonitor extends EventEmitter {
39
+ constructor();
40
+
41
+ activeDownloads: Map<string, DownloadRecord>;
42
+ completedDownloads: DownloadRecord[];
43
+ stats: Omit<DownloadStats, 'activeDownloads'>;
44
+
45
+ /**
46
+ * Register a new download being tracked
47
+ * @param id - Unique download identifier
48
+ * @param metadata - Download metadata
49
+ */
50
+ startDownload(id: string, metadata?: DownloadMetadata): DownloadRecord;
51
+
52
+ /**
53
+ * Update download progress
54
+ * @param id - Download identifier
55
+ * @param bytesTransferred - Bytes transferred so far
56
+ */
57
+ updateProgress(id: string, bytesTransferred: number): void;
58
+
59
+ /**
60
+ * Mark a download as completed
61
+ * @param id - Download identifier
62
+ */
63
+ completeDownload(id: string): void;
64
+
65
+ /**
66
+ * Mark a download as failed
67
+ * @param id - Download identifier
68
+ * @param error - The error that caused the failure
69
+ */
70
+ failDownload(id: string, error: Error): void;
71
+
72
+ /**
73
+ * Cancel an active download
74
+ * @param id - Download identifier
75
+ */
76
+ cancelDownload(id: string): void;
77
+
78
+ /**
79
+ * Get current download statistics
80
+ */
81
+ getStats(): DownloadStats;
82
+
83
+ /**
84
+ * Get all active downloads
85
+ */
86
+ getActiveDownloads(): DownloadRecord[];
87
+
88
+ /**
89
+ * Get completed downloads
90
+ * @param limit - Max number of records to return (default: 100)
91
+ */
92
+ getCompletedDownloads(limit?: number): DownloadRecord[];
93
+
94
+ /**
95
+ * Clear completed download history
96
+ */
97
+ clearHistory(): void;
98
+ }
99
+
100
+ export default DownloadMonitor;
@@ -0,0 +1,71 @@
1
+ /// <reference types="node" />
2
+ import { EventEmitter } from 'events';
3
+
4
+ export interface EventNotifierConfig {
5
+ /** Maximum number of retry attempts for failed notifications (default: 3) */
6
+ maxRetries?: number;
7
+ /** Delay in ms between retries (default: 1000) */
8
+ retryDelay?: number;
9
+ /** Request timeout in ms (default: 5000) */
10
+ timeout?: number;
11
+ }
12
+
13
+ export interface WebhookOptions {
14
+ /** Custom HTTP headers to send with notifications */
15
+ headers?: Record<string, string>;
16
+ }
17
+
18
+ export interface WebhookInfo {
19
+ url: string;
20
+ events: string[];
21
+ active: boolean;
22
+ failCount: number;
23
+ lastNotified: string | null;
24
+ }
25
+
26
+ export interface NotificationHistoryEntry {
27
+ event: string;
28
+ timestamp: string;
29
+ recipientCount: number;
30
+ }
31
+
32
+ export class EventNotifier extends EventEmitter {
33
+ constructor(config?: EventNotifierConfig);
34
+
35
+ config: Required<EventNotifierConfig>;
36
+ webhooks: Map<string, any>;
37
+
38
+ /**
39
+ * Register a webhook for event notifications
40
+ * @param url - Webhook URL to send notifications to
41
+ * @param events - Array of event names to subscribe to (empty = all events)
42
+ * @param options - Additional options (headers, etc.)
43
+ */
44
+ addWebhook(url: string, events?: string[], options?: WebhookOptions): void;
45
+
46
+ /**
47
+ * Remove a registered webhook
48
+ * @param url - Webhook URL to remove
49
+ */
50
+ removeWebhook(url: string): void;
51
+
52
+ /**
53
+ * Send a notification for an event
54
+ * @param event - Event name
55
+ * @param data - Event data payload
56
+ */
57
+ notify(event: string, data?: Record<string, any>): Promise<void>;
58
+
59
+ /**
60
+ * Get list of registered webhooks
61
+ */
62
+ getWebhooks(): WebhookInfo[];
63
+
64
+ /**
65
+ * Get notification history
66
+ * @param limit - Max records to return (default: 50)
67
+ */
68
+ getHistory(limit?: number): NotificationHistoryEntry[];
69
+ }
70
+
71
+ export default EventNotifier;
@@ -0,0 +1,229 @@
1
+ /// <reference types="node" />
2
+ import { EventEmitter } from 'events';
3
+ import type { HttpServerProvider, HttpAuthConfig } from './HttpServerProvider.js';
4
+ import type { S3Server } from './S3Server.js';
5
+ import type { DownloadMonitor, DownloadStats } from './DownloadMonitor.js';
6
+ import type { ShutdownManager } from './ShutdownManager.js';
7
+ import type { MonitoringDashboard } from './MonitoringDashboard.js';
8
+ import type { EventNotifier } from './EventNotifier.js';
9
+
10
+ export interface TunnelConfig {
11
+ /** Enable tunneling (default: false) */
12
+ enabled?: boolean;
13
+ /** Tunnel service to use (default: 'kadi') */
14
+ service?: string;
15
+ /** Extra service-specific options */
16
+ options?: Record<string, any>;
17
+ /** Auto-reconnect on failure (default: true) */
18
+ autoReconnect?: boolean;
19
+ /** Reconnect delay in ms (default: 5000) */
20
+ reconnectDelay?: number;
21
+ /** Auto-fallback to other services */
22
+ autoFallback?: boolean;
23
+ /** KĀDI tunnel auth token */
24
+ kadiToken?: string;
25
+ /** KĀDI broker server address */
26
+ kadiServer?: string;
27
+ /** KĀDI tunnel domain */
28
+ kadiDomain?: string;
29
+ /** KĀDI frpc port */
30
+ kadiPort?: number;
31
+ /** KĀDI SSH gateway port */
32
+ kadiSshPort?: number;
33
+ /** KĀDI tunnel mode ('ssh' | 'frpc' | 'auto') */
34
+ kadiMode?: string;
35
+ /** KĀDI agent identifier */
36
+ kadiAgentId?: string;
37
+ /** KĀDI transport ('wss' | 'tcp') */
38
+ kadiTransport?: string;
39
+ /** KĀDI WSS gateway hostname */
40
+ kadiWssControlHost?: string;
41
+ /** Ngrok auth token */
42
+ ngrokAuthToken?: string;
43
+ /** Override for TunnelManager options */
44
+ managerOptions?: Record<string, any>;
45
+ /** Port to tunnel (defaults to s3Port if running, else httpPort) */
46
+ port?: number;
47
+ }
48
+
49
+ export interface MonitoringConfig {
50
+ /** Enable monitoring (default: true) */
51
+ enabled?: boolean;
52
+ /** Enable console dashboard (default: false) */
53
+ dashboard?: boolean;
54
+ /** Webhook configurations */
55
+ webhooks?: Array<{
56
+ url: string;
57
+ events?: string[];
58
+ options?: Record<string, any>;
59
+ }>;
60
+ }
61
+
62
+ export interface ShutdownConfig {
63
+ /** Timeout in ms for graceful shutdown (default: 30000) */
64
+ gracefulTimeout?: number;
65
+ /** Whether to finish active downloads (default: true) */
66
+ finishActiveDownloads?: boolean;
67
+ /** Timeout in ms before force kill (default: 60000) */
68
+ forceKillTimeout?: number;
69
+ }
70
+
71
+ export interface FileSharingServerConfig {
72
+ /** Directory to serve files from (default: process.cwd()) */
73
+ staticDir?: string;
74
+ /** HTTP port (default: 3000) */
75
+ port?: number;
76
+ /** Bind host (default: '0.0.0.0') */
77
+ host?: string;
78
+ /** Enable local S3-compatible API (default: false) */
79
+ enableS3?: boolean;
80
+ /** S3 server port (default: 9000) */
81
+ s3Port?: number;
82
+ /** S3 server config overrides */
83
+ s3Config?: Record<string, any>;
84
+ /** Enable directory listing (default: true) */
85
+ enableDirectoryListing?: boolean;
86
+ /** Enable CORS (default: true) */
87
+ cors?: boolean;
88
+ /** HTTP authentication config */
89
+ auth?: HttpAuthConfig | null;
90
+ /** Tunnel configuration */
91
+ tunnel?: TunnelConfig;
92
+ /** Monitoring configuration */
93
+ monitoring?: MonitoringConfig;
94
+ /** Shutdown configuration */
95
+ shutdown?: ShutdownConfig;
96
+ /** Additional HTTP server config overrides */
97
+ httpConfig?: Record<string, any>;
98
+ }
99
+
100
+ export interface ServerInfo {
101
+ isRunning: boolean;
102
+ localUrl: string;
103
+ publicUrl: string | null;
104
+ s3Endpoint: string | null;
105
+ staticDir: string;
106
+ stats: DownloadStats;
107
+ uptime: number;
108
+ tunnelStatus: TunnelInfo | null;
109
+ }
110
+
111
+ export interface TunnelInfo {
112
+ id: string;
113
+ publicUrl: string;
114
+ [key: string]: any;
115
+ }
116
+
117
+ export interface FileEntry {
118
+ name: string;
119
+ type: 'file' | 'directory';
120
+ size: number;
121
+ modified: string;
122
+ }
123
+
124
+ export class FileSharingServer extends EventEmitter {
125
+ constructor(config?: FileSharingServerConfig);
126
+
127
+ config: FileSharingServerConfig & {
128
+ staticDir: string;
129
+ port: number;
130
+ host: string;
131
+ enableS3: boolean;
132
+ s3Port: number;
133
+ tunnel: Required<Pick<TunnelConfig, 'enabled' | 'service' | 'options' | 'autoReconnect' | 'reconnectDelay'>> & TunnelConfig;
134
+ };
135
+
136
+ /** The file manager instance */
137
+ fileManager: any;
138
+ /** The HTTP server provider instance */
139
+ httpServer: HttpServerProvider;
140
+ /** The S3 server instance (null if S3 disabled) */
141
+ s3Server: S3Server | null;
142
+ /** The tunnel manager instance */
143
+ tunnelManager: any;
144
+ /** The download monitor instance */
145
+ downloadMonitor: DownloadMonitor;
146
+ /** The shutdown manager instance */
147
+ shutdownManager: ShutdownManager;
148
+ /** The monitoring dashboard instance */
149
+ monitoringDashboard: MonitoringDashboard;
150
+ /** The event notifier instance */
151
+ eventNotifier: EventNotifier;
152
+ /** Whether the server is running */
153
+ isRunning: boolean;
154
+ /** Active tunnel info (null if no tunnel active) */
155
+ tunnel: TunnelInfo | null;
156
+
157
+ /** HTTP port */
158
+ readonly port: number;
159
+ /** Public tunnel URL (null if no tunnel) */
160
+ readonly tunnelUrl: string | null;
161
+ /** S3 endpoint URL (null if S3 not running) */
162
+ readonly s3Endpoint: string | null;
163
+ /** Served directory */
164
+ readonly staticDir: string;
165
+
166
+ /**
167
+ * Start the file sharing server
168
+ */
169
+ start(): Promise<ServerInfo>;
170
+
171
+ /**
172
+ * Stop the file sharing server.
173
+ * Gracefully shuts down all components.
174
+ */
175
+ stop(): Promise<void>;
176
+
177
+ /**
178
+ * Enable tunnel to expose server publicly
179
+ * @param options - Tunnel options
180
+ */
181
+ enableTunnel(options?: TunnelConfig): Promise<TunnelInfo>;
182
+
183
+ /**
184
+ * Disable active tunnel
185
+ */
186
+ disableTunnel(): Promise<void>;
187
+
188
+ /**
189
+ * Enable S3-compatible API dynamically
190
+ * @param options - S3 server options
191
+ */
192
+ enableS3(options?: Record<string, any>): Promise<{ port: number; endpoint: string }>;
193
+
194
+ /**
195
+ * Disable S3 API
196
+ */
197
+ disableS3(): Promise<void>;
198
+
199
+ /**
200
+ * Get current server information and statistics
201
+ */
202
+ getInfo(): ServerInfo;
203
+
204
+ /**
205
+ * Get download statistics
206
+ */
207
+ getStats(): DownloadStats;
208
+
209
+ /**
210
+ * List files in the served directory
211
+ * @param subPath - Optional subdirectory path
212
+ */
213
+ listFiles(subPath?: string): Promise<FileEntry[]>;
214
+
215
+ /**
216
+ * Add a webhook for event notifications
217
+ * @param url - Webhook URL
218
+ * @param events - Events to subscribe to
219
+ */
220
+ addWebhook(url: string, events?: string[]): void;
221
+
222
+ /**
223
+ * Remove a webhook
224
+ * @param url - Webhook URL to remove
225
+ */
226
+ removeWebhook(url: string): void;
227
+ }
228
+
229
+ export default FileSharingServer;
@@ -0,0 +1,152 @@
1
+ /// <reference types="node" />
2
+ import { EventEmitter } from 'events';
3
+ import type { Server as HttpServer, IncomingMessage, ServerResponse } from 'http';
4
+
5
+ export interface HttpAuthConfig {
6
+ /** API key for Bearer / X-API-Key authentication */
7
+ apiKey?: string;
8
+ /** Bearer token for Authorization header */
9
+ bearerToken?: string;
10
+ /** Username for HTTP Basic auth */
11
+ username?: string;
12
+ /** Password for HTTP Basic auth */
13
+ password?: string;
14
+ }
15
+
16
+ export interface SslConfig {
17
+ key: string | Buffer;
18
+ cert: string | Buffer;
19
+ ca?: string | Buffer;
20
+ }
21
+
22
+ export interface HttpServerProviderConfig {
23
+ /** HTTP port (default: 3000) */
24
+ port?: number;
25
+ /** Bind host (default: '0.0.0.0') */
26
+ host?: string;
27
+ /** Directory to serve files from (default: process.cwd()) */
28
+ staticDir?: string;
29
+ /** Whether to show directory listing (default: true) */
30
+ enableDirectoryListing?: boolean;
31
+ /** Enable CORS (default: true) */
32
+ cors?: boolean;
33
+ /** Authentication configuration */
34
+ auth?: HttpAuthConfig | null;
35
+ /** SSL/TLS configuration */
36
+ ssl?: SslConfig | null;
37
+ /** Maximum file size in bytes (null = unlimited) */
38
+ maxFileSize?: number | null;
39
+ /** Directory for uploads (null = same as staticDir) */
40
+ uploadDir?: string | null;
41
+ }
42
+
43
+ export interface HttpStartResult {
44
+ port: number;
45
+ host: string;
46
+ url: string;
47
+ already?: boolean;
48
+ }
49
+
50
+ export interface MiddlewareInfo {
51
+ name: string;
52
+ priority: number;
53
+ }
54
+
55
+ export interface CustomRouteInfo {
56
+ method: string;
57
+ path: string;
58
+ priority: number;
59
+ }
60
+
61
+ type MiddlewareHandler = (
62
+ req: IncomingMessage,
63
+ res: ServerResponse,
64
+ next: (err?: Error) => void
65
+ ) => void | Promise<void>;
66
+
67
+ type RouteHandler = (req: IncomingMessage & { params?: Record<string, string> }, res: ServerResponse) => void | Promise<void>;
68
+
69
+ export class HttpServerProvider extends EventEmitter {
70
+ constructor(config?: HttpServerProviderConfig);
71
+
72
+ config: Required<HttpServerProviderConfig>;
73
+ server: HttpServer | null;
74
+ isRunning: boolean;
75
+ activeConnections: Map<string, any>;
76
+ startTime: Date | null;
77
+ requestCount: number;
78
+ errorCount: number;
79
+
80
+ /**
81
+ * Start the HTTP server
82
+ */
83
+ start(): Promise<HttpStartResult>;
84
+
85
+ /**
86
+ * Stop the HTTP server
87
+ */
88
+ stop(): Promise<void>;
89
+
90
+ /**
91
+ * Get active connection count
92
+ */
93
+ getActiveConnections(): number;
94
+
95
+ /**
96
+ * Force close all active connections
97
+ */
98
+ closeAllConnections(): void;
99
+
100
+ /**
101
+ * Register a named middleware function into the request pipeline.
102
+ * Middleware runs BEFORE built-in auth and static-file handling.
103
+ * @param name - Unique middleware identifier
104
+ * @param handler - Middleware handler function
105
+ * @param opts - Options
106
+ */
107
+ addMiddleware(
108
+ name: string,
109
+ handler: MiddlewareHandler,
110
+ opts?: { priority?: number }
111
+ ): void;
112
+
113
+ /**
114
+ * Remove a named middleware.
115
+ * @param name - Middleware identifier to remove
116
+ */
117
+ removeMiddleware(name: string): boolean;
118
+
119
+ /**
120
+ * Get the list of registered middleware names (in execution order).
121
+ */
122
+ getMiddleware(): MiddlewareInfo[];
123
+
124
+ /**
125
+ * Register a custom route handler.
126
+ * Custom routes are matched BEFORE built-in static-file/upload handling.
127
+ * @param method - HTTP method ('GET', 'POST', etc.)
128
+ * @param urlPath - URL path or Express-style pattern
129
+ * @param handler - Route handler
130
+ * @param opts - Options
131
+ */
132
+ addCustomRoute(
133
+ method: string,
134
+ urlPath: string,
135
+ handler: RouteHandler,
136
+ opts?: { priority?: number }
137
+ ): void;
138
+
139
+ /**
140
+ * Remove a custom route.
141
+ * @param method - HTTP method
142
+ * @param urlPath - URL path pattern
143
+ */
144
+ removeCustomRoute(method: string, urlPath: string): boolean;
145
+
146
+ /**
147
+ * Get the list of registered custom routes.
148
+ */
149
+ getCustomRoutes(): CustomRouteInfo[];
150
+ }
151
+
152
+ export default HttpServerProvider;
@@ -0,0 +1,64 @@
1
+ /// <reference types="node" />
2
+ import { EventEmitter } from 'events';
3
+
4
+ export interface MonitoringDashboardConfig {
5
+ /** Refresh interval in ms (default: 1000) */
6
+ refreshInterval?: number;
7
+ /** Whether to show progress bars in output (default: true) */
8
+ showProgressBars?: boolean;
9
+ /** Max number of active downloads to display (default: 10) */
10
+ maxDisplayItems?: number;
11
+ }
12
+
13
+ export interface DashboardStats {
14
+ totalBytes: number;
15
+ totalDownloads: number;
16
+ activeCount: number;
17
+ activeDownloads: Array<{
18
+ id?: string;
19
+ file?: string;
20
+ progress?: number;
21
+ [key: string]: any;
22
+ }>;
23
+ averageSpeed: number;
24
+ peakConcurrent: number;
25
+ uptime: number;
26
+ }
27
+
28
+ export interface DashboardServerInfo {
29
+ localUrl?: string;
30
+ publicUrl?: string;
31
+ s3Endpoint?: string;
32
+ [key: string]: any;
33
+ }
34
+
35
+ export class MonitoringDashboard extends EventEmitter {
36
+ constructor(config?: MonitoringDashboardConfig);
37
+
38
+ config: Required<MonitoringDashboardConfig>;
39
+ isRunning: boolean;
40
+
41
+ /**
42
+ * Start the monitoring dashboard
43
+ */
44
+ start(): Promise<{ running: boolean }>;
45
+
46
+ /**
47
+ * Stop the monitoring dashboard
48
+ */
49
+ stop(): Promise<void>;
50
+
51
+ /**
52
+ * Update dashboard statistics
53
+ * @param stats - New stats to display
54
+ */
55
+ updateStats(stats: Partial<DashboardStats>): void;
56
+
57
+ /**
58
+ * Set server information
59
+ * @param info - Server info (localUrl, publicUrl, etc.)
60
+ */
61
+ setServerInfo(info: DashboardServerInfo): void;
62
+ }
63
+
64
+ export default MonitoringDashboard;
@@ -0,0 +1,109 @@
1
+ /// <reference types="node" />
2
+ import { EventEmitter } from 'events';
3
+ import type { Server as HttpServer, IncomingMessage } from 'http';
4
+
5
+ export interface S3ServerConfig {
6
+ /** S3 server port (default: 9000) */
7
+ port?: number;
8
+ /** Bind host (default: '0.0.0.0') */
9
+ host?: string;
10
+ /** Root directory for object storage (default: process.cwd()) */
11
+ rootDir?: string;
12
+ /** S3 access key ID (default: 'minioadmin') */
13
+ accessKeyId?: string;
14
+ /** S3 secret access key (default: 'minioadmin') */
15
+ secretAccessKey?: string;
16
+ /** Default bucket name (default: 'local') */
17
+ bucketName?: string;
18
+ /** AWS region (default: 'us-east-1') */
19
+ region?: string;
20
+ /** Maximum file size in bytes (null = unlimited) */
21
+ maxFileSize?: number | null;
22
+ }
23
+
24
+ export interface S3StartResult {
25
+ port: number;
26
+ host: string;
27
+ endpoint: string;
28
+ serverId: string;
29
+ }
30
+
31
+ export interface S3BucketInfo {
32
+ name: string;
33
+ rootDir: string;
34
+ }
35
+
36
+ export interface S3ObjectEntry {
37
+ key: string;
38
+ size: number;
39
+ lastModified: string;
40
+ [key: string]: any;
41
+ }
42
+
43
+ export interface S3AuthResult {
44
+ success: boolean;
45
+ user?: { accessKey: string };
46
+ error?: string;
47
+ }
48
+
49
+ export interface S3TemporaryCredentials {
50
+ accessKey: string;
51
+ secretKey: string;
52
+ expiresAt: string;
53
+ /** Backward-compat alias for expiresAt as Date */
54
+ expiry: Date;
55
+ }
56
+
57
+ export class S3Server extends EventEmitter {
58
+ constructor(config?: S3ServerConfig);
59
+
60
+ config: Required<S3ServerConfig>;
61
+ server: HttpServer | null;
62
+ isRunning: boolean;
63
+ multipartUploads: Map<string, any>;
64
+ requestCount: number;
65
+
66
+ /** Stable server identifier */
67
+ readonly serverId: string;
68
+
69
+ /**
70
+ * Start the S3 server
71
+ */
72
+ start(): Promise<S3StartResult>;
73
+
74
+ /**
75
+ * Stop the S3 server
76
+ */
77
+ stop(): Promise<void>;
78
+
79
+ /**
80
+ * Get bucket configuration
81
+ */
82
+ getBucket(): S3BucketInfo;
83
+
84
+ /**
85
+ * List objects in bucket (programmatic access)
86
+ * @param prefix - Optional prefix filter
87
+ */
88
+ listObjects(prefix?: string): Promise<S3ObjectEntry[]>;
89
+
90
+ /**
91
+ * Validate an incoming request against the server's configured credentials.
92
+ * @param req - HTTP incoming request
93
+ */
94
+ validateAuthentication(req: IncomingMessage): S3AuthResult;
95
+
96
+ /**
97
+ * Programmatically remove a bucket (force-deletes even non-empty directories).
98
+ * @param bucketName - The bucket/directory name to remove
99
+ */
100
+ removeBucket(bucketName: string): Promise<void>;
101
+
102
+ /**
103
+ * Generate temporary S3 credentials with an expiry.
104
+ * @param opts - Options
105
+ */
106
+ generateTemporaryCredentials(opts?: { ttl?: number }): S3TemporaryCredentials;
107
+ }
108
+
109
+ export default S3Server;
@@ -0,0 +1,51 @@
1
+ /// <reference types="node" />
2
+ import { EventEmitter } from 'events';
3
+
4
+ export interface ShutdownManagerConfig {
5
+ /** Timeout in ms for graceful shutdown (default: 30000) */
6
+ gracefulTimeout?: number;
7
+ /** Whether to wait for active downloads before shutting down (default: true) */
8
+ finishActiveDownloads?: boolean;
9
+ /** Timeout in ms before force kill (default: 60000) */
10
+ forceKillTimeout?: number;
11
+ }
12
+
13
+ export class ShutdownManager extends EventEmitter {
14
+ constructor(config?: ShutdownManagerConfig);
15
+
16
+ config: Required<ShutdownManagerConfig>;
17
+ isShuttingDown: boolean;
18
+ shutdownCallbacks: Array<{ callback: () => Promise<void>; priority: number }>;
19
+
20
+ /**
21
+ * Register a shutdown callback with priority.
22
+ * Lower priority numbers execute first.
23
+ * @param callback - Async callback to execute during shutdown
24
+ * @param priority - Execution priority (lower = earlier, default: 10)
25
+ */
26
+ register(callback: () => Promise<void>, priority?: number): void;
27
+
28
+ /**
29
+ * Unregister a previously registered callback
30
+ * @param callback - The callback to remove
31
+ */
32
+ unregister(callback: () => Promise<void>): void;
33
+
34
+ /**
35
+ * Install process signal handlers (SIGINT, SIGTERM)
36
+ */
37
+ installSignalHandlers(): void;
38
+
39
+ /**
40
+ * Perform graceful shutdown.
41
+ * Executes all registered callbacks in priority order with timeout.
42
+ */
43
+ shutdown(): Promise<void>;
44
+
45
+ /**
46
+ * Force shutdown - skip remaining callbacks
47
+ */
48
+ forceShutdown(): Promise<void>;
49
+ }
50
+
51
+ export default ShutdownManager;
@@ -0,0 +1,116 @@
1
+ /**
2
+ * @kadi.build/file-sharing - Type declarations
3
+ *
4
+ * File sharing service with tunneling and local S3-compatible interface.
5
+ */
6
+
7
+ import type { FileSharingServerConfig } from './FileSharingServer.js';
8
+ import type { FileSharingServer } from './FileSharingServer.js';
9
+ import type { HttpAuthConfig } from './HttpServerProvider.js';
10
+
11
+ // Core classes
12
+ export {
13
+ FileSharingServer,
14
+ FileSharingServerConfig,
15
+ TunnelConfig,
16
+ MonitoringConfig,
17
+ ShutdownConfig,
18
+ ServerInfo,
19
+ TunnelInfo,
20
+ FileEntry,
21
+ } from './FileSharingServer.js';
22
+
23
+ export {
24
+ HttpServerProvider,
25
+ HttpServerProviderConfig,
26
+ HttpAuthConfig,
27
+ SslConfig,
28
+ HttpStartResult,
29
+ MiddlewareInfo,
30
+ CustomRouteInfo,
31
+ } from './HttpServerProvider.js';
32
+
33
+ export {
34
+ S3Server,
35
+ S3ServerConfig,
36
+ S3StartResult,
37
+ S3BucketInfo,
38
+ S3ObjectEntry,
39
+ S3AuthResult,
40
+ S3TemporaryCredentials,
41
+ } from './S3Server.js';
42
+
43
+ export {
44
+ DownloadMonitor,
45
+ DownloadRecord,
46
+ DownloadMetadata,
47
+ DownloadStats,
48
+ } from './DownloadMonitor.js';
49
+
50
+ export {
51
+ ShutdownManager,
52
+ ShutdownManagerConfig,
53
+ } from './ShutdownManager.js';
54
+
55
+ export {
56
+ MonitoringDashboard,
57
+ MonitoringDashboardConfig,
58
+ DashboardStats,
59
+ DashboardServerInfo,
60
+ } from './MonitoringDashboard.js';
61
+
62
+ export {
63
+ EventNotifier,
64
+ EventNotifierConfig,
65
+ WebhookOptions,
66
+ WebhookInfo,
67
+ NotificationHistoryEntry,
68
+ } from './EventNotifier.js';
69
+
70
+ // Default export
71
+ export { FileSharingServer as default } from './FileSharingServer.js';
72
+
73
+ /**
74
+ * Create a FileSharingServer with default options
75
+ */
76
+ export function createFileSharingServer(options?: FileSharingServerConfig): FileSharingServer;
77
+
78
+ export interface QuickShareOptions {
79
+ /** HTTP port (default: 3000) */
80
+ port?: number;
81
+ /** Enable tunnel (default: false) */
82
+ tunnel?: boolean;
83
+ /** Tunnel service name (default: 'kadi') */
84
+ tunnelService?: string;
85
+ /** KĀDI auth token */
86
+ kadiToken?: string;
87
+ /** Ngrok auth token */
88
+ ngrokAuthToken?: string;
89
+ /** HTTP auth config */
90
+ auth?: HttpAuthConfig | null;
91
+ /** Extra tunnel options */
92
+ tunnelOptions?: Record<string, any>;
93
+ }
94
+
95
+ export interface QuickShareResult {
96
+ server: FileSharingServer;
97
+ localUrl: string;
98
+ publicUrl?: string;
99
+ }
100
+
101
+ /**
102
+ * Quick share - one-liner to share a directory
103
+ * @param directory - Directory to share
104
+ * @param options - Options
105
+ */
106
+ export function createQuickShare(
107
+ directory: string,
108
+ options?: QuickShareOptions
109
+ ): Promise<QuickShareResult>;
110
+
111
+ // Re-exports from dependencies (convenience)
112
+ // Note: These types come from the respective packages.
113
+ // If those packages don't have types, consumers should install them separately.
114
+ export declare const FileManager: any;
115
+ export declare const createFileManager: (...args: any[]) => any;
116
+ export declare const TunnelManager: any;