@jetstart/shared 1.6.0 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +223 -70
- package/dist/protocols/websocket.d.ts +20 -1
- package/package.json +1 -1
- package/src/protocols/websocket.ts +22 -0
package/README.md
CHANGED
|
@@ -1,108 +1,261 @@
|
|
|
1
|
-
# @jetstart/shared
|
|
1
|
+
# @jetstart/shared
|
|
2
2
|
|
|
3
|
-
Shared types,
|
|
3
|
+
Shared TypeScript types, WebSocket protocol definitions, validation utilities, and constants used across every JetStart package.
|
|
4
4
|
|
|
5
5
|
## Overview
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
`@jetstart/shared` is the single source of truth for the JetStart communication contract. All other packages — `core`, `cli`, `web`, `logs` — import types and constants from here. Nothing about the protocol is duplicated across packages.
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
9
|
+
```
|
|
10
|
+
src/
|
|
11
|
+
├── types/
|
|
12
|
+
│ ├── session.ts # Session, SessionStatus, SessionToken, QRCodeData
|
|
13
|
+
│ ├── build.ts # BuildConfig, BuildResult, BuildStatus, APKInfo, BuildError
|
|
14
|
+
│ ├── device.ts # DeviceInfo, Platform, Architecture
|
|
15
|
+
│ └── log.ts # LogEntry, LogLevel, LogSource, LogFilter, LogStats
|
|
16
|
+
├── protocols/
|
|
17
|
+
│ ├── websocket.ts # All WebSocket message interfaces + WSMessage union type
|
|
18
|
+
│ ├── events.ts # EventEmitter-style event definitions
|
|
19
|
+
│ └── index.ts
|
|
20
|
+
└── utils/
|
|
21
|
+
├── constants.ts # Ports, timeouts, size limits, version, error codes
|
|
22
|
+
├── validation.ts # isValidProjectName, isValidPackageName, isValidSessionId
|
|
23
|
+
├── version-compare.ts # Semantic version comparison
|
|
24
|
+
├── colors.ts # Log level color helpers
|
|
25
|
+
└── index.ts
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
## Installation
|
|
31
|
+
|
|
32
|
+
`@jetstart/shared` is an internal monorepo package. Import it from any workspace:
|
|
12
33
|
|
|
13
|
-
## Usage
|
|
14
34
|
```typescript
|
|
15
35
|
import {
|
|
16
36
|
Session,
|
|
17
|
-
SessionStatus,
|
|
18
37
|
BuildConfig,
|
|
19
|
-
|
|
20
|
-
ClientMessage,
|
|
21
|
-
CoreMessage,
|
|
22
|
-
isValidSessionId,
|
|
38
|
+
WSMessage,
|
|
23
39
|
DEFAULT_CORE_PORT,
|
|
40
|
+
isValidProjectName,
|
|
24
41
|
} from '@jetstart/shared';
|
|
25
42
|
```
|
|
26
43
|
|
|
27
|
-
|
|
28
|
-
```
|
|
29
|
-
src/
|
|
30
|
-
├── types/ # Type definitions
|
|
31
|
-
│ ├── session.ts # Session management types
|
|
32
|
-
│ ├── build.ts # Build system types
|
|
33
|
-
│ ├── device.ts # Device information types
|
|
34
|
-
│ └── log.ts # Logging types
|
|
35
|
-
├── protocols/ # Communication protocols
|
|
36
|
-
│ ├── websocket.ts # WebSocket messages
|
|
37
|
-
│ └── events.ts # Event system
|
|
38
|
-
└── utils/ # Utilities
|
|
39
|
-
├── validation.ts # Validation functions
|
|
40
|
-
└── constants.ts # Shared constants
|
|
41
|
-
```
|
|
44
|
+
---
|
|
42
45
|
|
|
43
|
-
##
|
|
46
|
+
## Types
|
|
44
47
|
|
|
45
|
-
### Session
|
|
46
|
-
- `Session` - Development session state
|
|
47
|
-
- `SessionStatus` - Connection status enum
|
|
48
|
-
- `SessionToken` - Authentication token
|
|
49
|
-
- `QRCodeData` - QR code payload
|
|
48
|
+
### Session
|
|
50
49
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
50
|
+
```typescript
|
|
51
|
+
interface Session {
|
|
52
|
+
id: string;
|
|
53
|
+
token: string;
|
|
54
|
+
projectName: string;
|
|
55
|
+
projectPath: string;
|
|
56
|
+
createdAt: number;
|
|
57
|
+
lastActivity: number;
|
|
58
|
+
}
|
|
56
59
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
60
|
+
enum SessionStatus {
|
|
61
|
+
CONNECTING = 'connecting',
|
|
62
|
+
CONNECTED = 'connected',
|
|
63
|
+
IDLE = 'idle',
|
|
64
|
+
DISCONNECTED = 'disconnected',
|
|
65
|
+
ERROR = 'error',
|
|
66
|
+
}
|
|
67
|
+
```
|
|
61
68
|
|
|
62
|
-
###
|
|
63
|
-
- `LogEntry` - Log message structure
|
|
64
|
-
- `LogLevel` - Log severity levels
|
|
65
|
-
- `LogSource` - Log origin
|
|
69
|
+
### Build
|
|
66
70
|
|
|
67
|
-
|
|
71
|
+
```typescript
|
|
72
|
+
interface BuildConfig {
|
|
73
|
+
projectPath: string;
|
|
74
|
+
outputPath?: string;
|
|
75
|
+
buildType: 'debug' | 'release';
|
|
76
|
+
debuggable?: boolean;
|
|
77
|
+
minifyEnabled?: boolean;
|
|
78
|
+
versionCode?: number;
|
|
79
|
+
versionName?: string;
|
|
80
|
+
applicationId?: string;
|
|
81
|
+
}
|
|
68
82
|
|
|
69
|
-
|
|
83
|
+
interface BuildResult {
|
|
84
|
+
success: boolean;
|
|
85
|
+
buildTime: number;
|
|
86
|
+
apkPath?: string;
|
|
87
|
+
apkSize?: number;
|
|
88
|
+
errors?: BuildError[];
|
|
89
|
+
}
|
|
70
90
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
91
|
+
interface APKInfo {
|
|
92
|
+
path: string;
|
|
93
|
+
size: number;
|
|
94
|
+
hash: string;
|
|
95
|
+
versionCode: number;
|
|
96
|
+
versionName: string;
|
|
97
|
+
minSdkVersion: number; // minimum: 24 (Android 7.0)
|
|
98
|
+
targetSdkVersion: number; // current target: 34 (Android 14)
|
|
99
|
+
applicationId: string;
|
|
100
|
+
}
|
|
101
|
+
```
|
|
76
102
|
|
|
77
|
-
|
|
78
|
-
- `core:connected` - Connection confirmed
|
|
79
|
-
- `core:build-start` - Build started
|
|
80
|
-
- `core:build-status` - Build progress
|
|
81
|
-
- `core:build-complete` - Build finished
|
|
82
|
-
- `core:build-error` - Build failed
|
|
83
|
-
- `core:reload` - Trigger reload
|
|
103
|
+
### Device
|
|
84
104
|
|
|
85
|
-
## Validation
|
|
86
105
|
```typescript
|
|
87
|
-
|
|
106
|
+
interface DeviceInfo {
|
|
107
|
+
id: string;
|
|
108
|
+
model: string;
|
|
109
|
+
platform: Platform;
|
|
110
|
+
architecture: Architecture;
|
|
111
|
+
androidVersion?: string;
|
|
112
|
+
apiLevel?: number;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
enum Platform { ANDROID = 'android', WEB = 'web' }
|
|
116
|
+
enum Architecture { ARM64 = 'arm64', X86_64 = 'x86_64', X86 = 'x86' }
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
### Logging
|
|
88
120
|
|
|
89
|
-
|
|
90
|
-
|
|
121
|
+
```typescript
|
|
122
|
+
interface LogEntry {
|
|
123
|
+
id: string;
|
|
124
|
+
timestamp: number;
|
|
125
|
+
level: LogLevel;
|
|
126
|
+
tag: string;
|
|
127
|
+
message: string;
|
|
128
|
+
source: LogSource;
|
|
129
|
+
metadata?: Record<string, unknown>;
|
|
91
130
|
}
|
|
92
131
|
|
|
93
|
-
|
|
94
|
-
|
|
132
|
+
enum LogLevel { VERBOSE, DEBUG, INFO, WARN, ERROR, FATAL }
|
|
133
|
+
enum LogSource { CLI, CORE, CLIENT, BUILD, NETWORK, SYSTEM }
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
---
|
|
137
|
+
|
|
138
|
+
## WebSocket Protocol
|
|
139
|
+
|
|
140
|
+
All messages extend `BaseMessage`:
|
|
141
|
+
|
|
142
|
+
```typescript
|
|
143
|
+
interface BaseMessage {
|
|
144
|
+
type: string;
|
|
145
|
+
timestamp: number;
|
|
146
|
+
sessionId?: string;
|
|
95
147
|
}
|
|
148
|
+
|
|
149
|
+
type WSMessage = ClientMessage | CoreMessage;
|
|
96
150
|
```
|
|
97
151
|
|
|
152
|
+
### Device / Browser → Core
|
|
153
|
+
|
|
154
|
+
| `type` | Key fields | Description |
|
|
155
|
+
|---|---|---|
|
|
156
|
+
| `client:connect` | `sessionId`, `token`, `deviceInfo` | Authenticate with session credentials |
|
|
157
|
+
| `client:status` | `status: SessionStatus` | Send a status update |
|
|
158
|
+
| `client:log` | `log: LogEntry` | Forward a device log to the server |
|
|
159
|
+
| `client:heartbeat` | — | Keep-alive ping |
|
|
160
|
+
| `client:disconnect` | `reason?` | Graceful disconnect |
|
|
161
|
+
| `client:click` | `action`, `elementType`, `elementText?` | UI interaction event from web emulator |
|
|
162
|
+
|
|
163
|
+
### Core → Device / Browser
|
|
164
|
+
|
|
165
|
+
| `type` | Key fields | Description |
|
|
166
|
+
|---|---|---|
|
|
167
|
+
| `core:connected` | `projectName` | Authentication accepted |
|
|
168
|
+
| `core:build-start` | — | Gradle build has started |
|
|
169
|
+
| `core:build-status` | `status: BuildStatus` | Mid-build progress update |
|
|
170
|
+
| `core:build-complete` | `apkInfo: APKInfo`, `downloadUrl` | APK is ready |
|
|
171
|
+
| `core:build-error` | `error`, `details?` | Build failed |
|
|
172
|
+
| `core:reload` | `reloadType: 'full' \| 'hot'` | Request an app reload |
|
|
173
|
+
| `core:dex-reload` | `dexBase64`, `classNames: string[]` | Hot reload DEX patch for Android |
|
|
174
|
+
| `core:js-update` | `jsBase64`, `sourceFile`, `byteSize` | ES module update for the web emulator |
|
|
175
|
+
| `core:log` | `log: LogEntry` | Broadcast a device log to dashboard clients |
|
|
176
|
+
| `core:disconnect` | `reason` | Server is shutting down |
|
|
177
|
+
|
|
178
|
+
---
|
|
179
|
+
|
|
98
180
|
## Constants
|
|
181
|
+
|
|
99
182
|
```typescript
|
|
100
|
-
|
|
183
|
+
// Default ports
|
|
184
|
+
DEFAULT_CORE_PORT = 8765 // HTTP server
|
|
185
|
+
DEFAULT_WS_PORT = 8766 // WebSocket server
|
|
186
|
+
DEFAULT_LOGS_PORT = 8767 // Logs server
|
|
187
|
+
|
|
188
|
+
// WebSocket behaviour
|
|
189
|
+
WS_HEARTBEAT_INTERVAL = 30_000 // ms between heartbeat pings
|
|
190
|
+
WS_RECONNECT_DELAY = 5_000 // ms before reconnect attempt
|
|
191
|
+
WS_MAX_RECONNECT_ATTEMPTS = 5
|
|
101
192
|
|
|
102
|
-
|
|
103
|
-
|
|
193
|
+
// Session lifecycle
|
|
194
|
+
SESSION_TOKEN_EXPIRY = 3_600_000 // 1 hour
|
|
195
|
+
SESSION_CLEANUP_INTERVAL = 60_000 // 1 minute
|
|
196
|
+
SESSION_IDLE_TIMEOUT = 1_800_000 // 30 minutes
|
|
197
|
+
|
|
198
|
+
// Build limits
|
|
199
|
+
BUILD_CACHE_SIZE_LIMIT = 1_073_741_824 // 1 GB
|
|
200
|
+
BUILD_TIMEOUT = 300_000 // 5 minutes
|
|
201
|
+
MAX_CONCURRENT_BUILDS = 3
|
|
202
|
+
|
|
203
|
+
// File limits
|
|
204
|
+
MAX_APK_SIZE = 104_857_600 // 100 MB
|
|
205
|
+
MAX_LOG_ENTRIES = 10_000
|
|
206
|
+
|
|
207
|
+
// Android targets
|
|
208
|
+
MIN_ANDROID_API_LEVEL = 24 // Android 7.0
|
|
209
|
+
TARGET_ANDROID_API_LEVEL = 34 // Android 14
|
|
210
|
+
|
|
211
|
+
// Version
|
|
212
|
+
JETSTART_VERSION = '0.1.0'
|
|
104
213
|
```
|
|
105
214
|
|
|
215
|
+
---
|
|
216
|
+
|
|
217
|
+
## Validation
|
|
218
|
+
|
|
219
|
+
```typescript
|
|
220
|
+
import { isValidProjectName, isValidPackageName, isValidSessionId } from '@jetstart/shared';
|
|
221
|
+
|
|
222
|
+
// Letters, numbers, hyphens, underscores; must start with a letter; 1–64 chars
|
|
223
|
+
isValidProjectName('my-app') // true
|
|
224
|
+
isValidProjectName('123bad') // false
|
|
225
|
+
|
|
226
|
+
// Reverse-domain format, at least two segments
|
|
227
|
+
isValidPackageName('com.example.app') // true
|
|
228
|
+
isValidPackageName('example') // false
|
|
229
|
+
|
|
230
|
+
isValidSessionId(sessionId) // validates generated session ID format
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
---
|
|
234
|
+
|
|
235
|
+
## WebSocket State & Error Types
|
|
236
|
+
|
|
237
|
+
```typescript
|
|
238
|
+
enum WSState {
|
|
239
|
+
CONNECTING = 'connecting',
|
|
240
|
+
CONNECTED = 'connected',
|
|
241
|
+
DISCONNECTING = 'disconnecting',
|
|
242
|
+
DISCONNECTED = 'disconnected',
|
|
243
|
+
ERROR = 'error',
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
enum WSErrorCode {
|
|
247
|
+
CONNECTION_FAILED = 'connection_failed',
|
|
248
|
+
AUTHENTICATION_FAILED = 'authentication_failed',
|
|
249
|
+
TIMEOUT = 'timeout',
|
|
250
|
+
INVALID_MESSAGE = 'invalid_message',
|
|
251
|
+
SESSION_EXPIRED = 'session_expired',
|
|
252
|
+
UNKNOWN = 'unknown',
|
|
253
|
+
}
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
---
|
|
257
|
+
|
|
106
258
|
## License
|
|
107
259
|
|
|
108
|
-
|
|
260
|
+
MIT
|
|
261
|
+
|
|
@@ -46,7 +46,7 @@ export interface ClientClickEventMessage extends BaseMessage {
|
|
|
46
46
|
/**
|
|
47
47
|
* Messages from Core to Client
|
|
48
48
|
*/
|
|
49
|
-
export type CoreMessage = CoreConnectedMessage | CoreBuildStartMessage | CoreBuildStatusMessage | CoreBuildCompleteMessage | CoreBuildErrorMessage | CoreReloadMessage | CoreUIUpdateMessage | CoreDisconnectMessage | CoreLogMessage;
|
|
49
|
+
export type CoreMessage = CoreConnectedMessage | CoreBuildStartMessage | CoreBuildStatusMessage | CoreBuildCompleteMessage | CoreBuildErrorMessage | CoreReloadMessage | CoreUIUpdateMessage | CoreDexReloadMessage | CoreDisconnectMessage | CoreLogMessage;
|
|
50
50
|
export interface CoreConnectedMessage extends BaseMessage {
|
|
51
51
|
type: 'core:connected';
|
|
52
52
|
sessionId: string;
|
|
@@ -79,6 +79,25 @@ export interface CoreUIUpdateMessage extends BaseMessage {
|
|
|
79
79
|
screens?: string[];
|
|
80
80
|
hash?: string;
|
|
81
81
|
}
|
|
82
|
+
export interface CoreDexReloadMessage extends BaseMessage {
|
|
83
|
+
type: 'core:dex-reload';
|
|
84
|
+
dexBase64: string;
|
|
85
|
+
classNames: string[];
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Compiled Kotlin→JS module for web emulator preview.
|
|
89
|
+
* The browser imports this as an ES module, executes renderScreen(),
|
|
90
|
+
* and gets back a component tree it renders as Material You HTML.
|
|
91
|
+
*/
|
|
92
|
+
export interface CoreJsUpdateMessage extends BaseMessage {
|
|
93
|
+
type: 'core:js-update';
|
|
94
|
+
/** Base64-encoded ES module (.mjs) compiled by kotlinc-js */
|
|
95
|
+
jsBase64: string;
|
|
96
|
+
/** Source file that triggered this update */
|
|
97
|
+
sourceFile: string;
|
|
98
|
+
/** Size in bytes for display */
|
|
99
|
+
byteSize: number;
|
|
100
|
+
}
|
|
82
101
|
export interface CoreDisconnectMessage extends BaseMessage {
|
|
83
102
|
type: 'core:disconnect';
|
|
84
103
|
reason: string;
|
package/package.json
CHANGED
|
@@ -76,6 +76,7 @@ export type CoreMessage =
|
|
|
76
76
|
| CoreBuildErrorMessage
|
|
77
77
|
| CoreReloadMessage
|
|
78
78
|
| CoreUIUpdateMessage
|
|
79
|
+
| CoreDexReloadMessage
|
|
79
80
|
| CoreDisconnectMessage
|
|
80
81
|
| CoreLogMessage;
|
|
81
82
|
|
|
@@ -118,6 +119,27 @@ export interface CoreUIUpdateMessage extends BaseMessage {
|
|
|
118
119
|
hash?: string;
|
|
119
120
|
}
|
|
120
121
|
|
|
122
|
+
export interface CoreDexReloadMessage extends BaseMessage {
|
|
123
|
+
type: 'core:dex-reload';
|
|
124
|
+
dexBase64: string;
|
|
125
|
+
classNames: string[];
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Compiled Kotlin→JS module for web emulator preview.
|
|
130
|
+
* The browser imports this as an ES module, executes renderScreen(),
|
|
131
|
+
* and gets back a component tree it renders as Material You HTML.
|
|
132
|
+
*/
|
|
133
|
+
export interface CoreJsUpdateMessage extends BaseMessage {
|
|
134
|
+
type: 'core:js-update';
|
|
135
|
+
/** Base64-encoded ES module (.mjs) compiled by kotlinc-js */
|
|
136
|
+
jsBase64: string;
|
|
137
|
+
/** Source file that triggered this update */
|
|
138
|
+
sourceFile: string;
|
|
139
|
+
/** Size in bytes for display */
|
|
140
|
+
byteSize: number;
|
|
141
|
+
}
|
|
142
|
+
|
|
121
143
|
export interface CoreDisconnectMessage extends BaseMessage {
|
|
122
144
|
type: 'core:disconnect';
|
|
123
145
|
reason: string;
|