@jetstart/core 2.3.0 → 2.3.2
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 +1 -1
- package/dist/build/gradle.js +10 -7
- package/dist/build/kotlin-compiler.d.ts +7 -0
- package/dist/build/kotlin-compiler.js +77 -16
- package/package.json +3 -3
- package/src/build/gradle.ts +10 -10
- package/src/build/kotlin-compiler.ts +88 -17
package/README.md
CHANGED
|
@@ -4,7 +4,7 @@ Central build server and real-time orchestration layer for JetStart.
|
|
|
4
4
|
|
|
5
5
|
## Overview
|
|
6
6
|
|
|
7
|
-
`@jetstart/core` is the engine that powers `jetstart`. It runs three networked services and orchestrates the complete hot reload pipeline — from detecting a file change to having new code running on a physical Android device in
|
|
7
|
+
`@jetstart/core` is the engine that powers `jetstart`. It runs three networked services and orchestrates the complete hot reload pipeline — from detecting a file change to having new code running on a physical Android device in instantly.
|
|
8
8
|
|
|
9
9
|
```
|
|
10
10
|
src/
|
package/dist/build/gradle.js
CHANGED
|
@@ -42,6 +42,7 @@ const child_process_1 = require("child_process");
|
|
|
42
42
|
const fs = __importStar(require("fs"));
|
|
43
43
|
const path = __importStar(require("path"));
|
|
44
44
|
const os = __importStar(require("os"));
|
|
45
|
+
const shared_1 = require("@jetstart/shared");
|
|
45
46
|
const parser_1 = require("./parser");
|
|
46
47
|
/**
|
|
47
48
|
* ADB Helper for auto-installing APKs
|
|
@@ -288,16 +289,18 @@ class GradleExecutor {
|
|
|
288
289
|
async execute(config) {
|
|
289
290
|
const startTime = Date.now();
|
|
290
291
|
const gradlePath = this.findGradle(config.projectPath);
|
|
291
|
-
// If Gradle not found,
|
|
292
|
+
// If Gradle not found, fail build with clear error
|
|
292
293
|
if (!gradlePath) {
|
|
293
|
-
console.log('[Gradle] No Gradle found, returning mock successful build for testing');
|
|
294
|
-
// Simulate build delay
|
|
295
|
-
await new Promise(resolve => setTimeout(resolve, 2000));
|
|
296
294
|
return {
|
|
297
|
-
success:
|
|
295
|
+
success: false,
|
|
298
296
|
buildTime: Date.now() - startTime,
|
|
299
|
-
|
|
300
|
-
|
|
297
|
+
errors: [{
|
|
298
|
+
file: 'gradle',
|
|
299
|
+
line: 0,
|
|
300
|
+
column: 0,
|
|
301
|
+
message: 'Gradle not found. Please install Gradle 8.0+ or ensure the Gradle wrapper (gradlew) exists in your project project.',
|
|
302
|
+
severity: shared_1.ErrorSeverity.ERROR
|
|
303
|
+
}]
|
|
301
304
|
};
|
|
302
305
|
}
|
|
303
306
|
// Ensure Android SDK is configured
|
|
@@ -22,6 +22,13 @@ export declare class KotlinCompiler {
|
|
|
22
22
|
findComposeCompiler(): Promise<string | null>;
|
|
23
23
|
/**
|
|
24
24
|
* Find kotlinc executable
|
|
25
|
+
*
|
|
26
|
+
* Search order:
|
|
27
|
+
* 1. KOTLIN_HOME env var (set in .env or shell)
|
|
28
|
+
* 2. ANDROID_STUDIO_HOME env var
|
|
29
|
+
* 3. Platform-specific static paths (Scoop, Chocolatey, SDKMAN, snap, …)
|
|
30
|
+
* 4. Versioned IDE directories (IntelliJ IDEA, JetBrains Toolbox, Android Studio)
|
|
31
|
+
* 5. `where` / `which` fallback
|
|
25
32
|
*/
|
|
26
33
|
findKotlinc(): Promise<string | null>;
|
|
27
34
|
/**
|
|
@@ -102,27 +102,88 @@ class KotlinCompiler {
|
|
|
102
102
|
}
|
|
103
103
|
/**
|
|
104
104
|
* Find kotlinc executable
|
|
105
|
+
*
|
|
106
|
+
* Search order:
|
|
107
|
+
* 1. KOTLIN_HOME env var (set in .env or shell)
|
|
108
|
+
* 2. ANDROID_STUDIO_HOME env var
|
|
109
|
+
* 3. Platform-specific static paths (Scoop, Chocolatey, SDKMAN, snap, …)
|
|
110
|
+
* 4. Versioned IDE directories (IntelliJ IDEA, JetBrains Toolbox, Android Studio)
|
|
111
|
+
* 5. `where` / `which` fallback
|
|
105
112
|
*/
|
|
106
113
|
async findKotlinc() {
|
|
107
114
|
if (this.kotlincPath)
|
|
108
115
|
return this.kotlincPath;
|
|
109
|
-
|
|
116
|
+
const win = os.platform() === 'win32';
|
|
117
|
+
const localAppData = process.env.LOCALAPPDATA || path.join(os.homedir(), 'AppData', 'Local');
|
|
118
|
+
const progFiles = process.env.PROGRAMFILES || 'C:\\Program Files';
|
|
119
|
+
/**
|
|
120
|
+
* Scan `parentDir` for subdirectories whose names start with `entryPrefix`
|
|
121
|
+
* (pass '' to accept any entry), then return the first candidate that exists:
|
|
122
|
+
* path.join(parentDir, entry, ...rest)
|
|
123
|
+
* Entries are sorted descending so the latest version is tried first.
|
|
124
|
+
* Returns null (never throws) if the directory is missing or unreadable.
|
|
125
|
+
*/
|
|
126
|
+
const findInVersionedDir = (parentDir, entryPrefix, ...rest) => {
|
|
127
|
+
try {
|
|
128
|
+
if (!fs.existsSync(parentDir))
|
|
129
|
+
return null;
|
|
130
|
+
const entries = fs.readdirSync(parentDir)
|
|
131
|
+
.filter(e => !entryPrefix || e.toLowerCase().startsWith(entryPrefix.toLowerCase()))
|
|
132
|
+
.sort()
|
|
133
|
+
.reverse(); // latest version first
|
|
134
|
+
for (const entry of entries) {
|
|
135
|
+
const candidate = path.join(parentDir, entry, ...rest);
|
|
136
|
+
if (fs.existsSync(candidate))
|
|
137
|
+
return candidate;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
catch { /* permission / access errors — silently skip */ }
|
|
141
|
+
return null;
|
|
142
|
+
};
|
|
110
143
|
const locations = [
|
|
111
|
-
//
|
|
112
|
-
process.env.KOTLIN_HOME
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
//
|
|
119
|
-
'
|
|
120
|
-
'
|
|
121
|
-
//
|
|
122
|
-
'
|
|
123
|
-
|
|
144
|
+
// env overrides
|
|
145
|
+
process.env.KOTLIN_HOME
|
|
146
|
+
? path.join(process.env.KOTLIN_HOME, 'bin', 'kotlinc')
|
|
147
|
+
: null,
|
|
148
|
+
process.env.ANDROID_STUDIO_HOME
|
|
149
|
+
? path.join(process.env.ANDROID_STUDIO_HOME, 'plugins', 'Kotlin', 'kotlinc', 'bin', 'kotlinc')
|
|
150
|
+
: null,
|
|
151
|
+
// Windows static paths
|
|
152
|
+
win ? path.join(progFiles, 'kotlinc', 'bin', 'kotlinc.bat') : null,
|
|
153
|
+
win ? 'C:\\kotlinc\\bin\\kotlinc.bat' : null,
|
|
154
|
+
// Scoop (~\scoop\apps\kotlin\current)
|
|
155
|
+
win ? path.join(os.homedir(), 'scoop', 'apps', 'kotlin', 'current', 'bin', 'kotlinc.bat') : null,
|
|
156
|
+
// Chocolatey
|
|
157
|
+
win ? 'C:\\ProgramData\\chocolatey\\bin\\kotlinc.bat' : null,
|
|
158
|
+
// Android Studio — standard Google installer
|
|
159
|
+
win ? path.join(progFiles, 'Android', 'Android Studio', 'plugins', 'Kotlin', 'kotlinc', 'bin', 'kotlinc.bat') : null,
|
|
160
|
+
win ? path.join(localAppData, 'Programs', 'Android Studio', 'plugins', 'Kotlin', 'kotlinc', 'bin', 'kotlinc.bat') : null,
|
|
161
|
+
// Windows versioned IDE paths (wildcard scan)
|
|
162
|
+
// IntelliJ IDEA — any version under C:\Program Files\JetBrains
|
|
163
|
+
win ? findInVersionedDir(path.join(progFiles, 'JetBrains'), 'IntelliJ IDEA', 'plugins', 'Kotlin', 'kotlinc', 'bin', 'kotlinc.bat') : null,
|
|
164
|
+
// JetBrains Toolbox — IDEA Ultimate
|
|
165
|
+
win ? findInVersionedDir(path.join(localAppData, 'JetBrains', 'Toolbox', 'apps', 'IDEA-U', 'ch-0'), '', 'plugins', 'Kotlin', 'kotlinc', 'bin', 'kotlinc.bat') : null,
|
|
166
|
+
// JetBrains Toolbox — IDEA Community
|
|
167
|
+
win ? findInVersionedDir(path.join(localAppData, 'JetBrains', 'Toolbox', 'apps', 'IDEA-C', 'ch-0'), '', 'plugins', 'Kotlin', 'kotlinc', 'bin', 'kotlinc.bat') : null,
|
|
168
|
+
// JetBrains Toolbox — Android Studio (Jellyfish+)
|
|
169
|
+
win ? findInVersionedDir(path.join(localAppData, 'JetBrains', 'Toolbox', 'apps', 'AndroidStudio', 'ch-0'), '', 'plugins', 'Kotlin', 'kotlinc', 'bin', 'kotlinc.bat') : null,
|
|
170
|
+
// Unix / macOS static paths
|
|
171
|
+
!win ? '/usr/local/bin/kotlinc' : null,
|
|
172
|
+
!win ? '/usr/bin/kotlinc' : null,
|
|
173
|
+
// Homebrew (Apple Silicon + Intel)
|
|
174
|
+
!win ? '/opt/homebrew/bin/kotlinc' : null,
|
|
175
|
+
!win ? '/usr/local/opt/kotlin/bin/kotlinc' : null,
|
|
176
|
+
// SDKMAN (~/.sdkman/candidates/kotlin/current)
|
|
177
|
+
!win ? path.join(os.homedir(), '.sdkman', 'candidates', 'kotlin', 'current', 'bin', 'kotlinc') : null,
|
|
178
|
+
// Snap
|
|
179
|
+
!win ? '/snap/bin/kotlinc' : null,
|
|
180
|
+
// IntelliJ IDEA — Linux Toolbox
|
|
181
|
+
!win ? findInVersionedDir(path.join(os.homedir(), '.local', 'share', 'JetBrains', 'Toolbox', 'apps', 'IDEA-U', 'ch-0'), '', 'plugins', 'Kotlin', 'kotlinc', 'bin', 'kotlinc') : null,
|
|
182
|
+
];
|
|
124
183
|
for (const loc of locations) {
|
|
125
|
-
|
|
184
|
+
if (!loc)
|
|
185
|
+
continue;
|
|
186
|
+
const execPath = win && !loc.endsWith('.bat') ? `${loc}.bat` : loc;
|
|
126
187
|
if (fs.existsSync(execPath)) {
|
|
127
188
|
this.kotlincPath = execPath;
|
|
128
189
|
(0, logger_1.log)(`Found kotlinc at: ${execPath}`);
|
|
@@ -131,7 +192,7 @@ class KotlinCompiler {
|
|
|
131
192
|
}
|
|
132
193
|
// Try to find via 'where' (Windows) or 'which' (Unix)
|
|
133
194
|
try {
|
|
134
|
-
const cmd =
|
|
195
|
+
const cmd = win ? 'where' : 'which';
|
|
135
196
|
const result = await this.runCommand(cmd, ['kotlinc']);
|
|
136
197
|
if (result.success && result.stdout.trim()) {
|
|
137
198
|
this.kotlincPath = result.stdout.trim().split('\n')[0];
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jetstart/core",
|
|
3
|
-
"version": "2.3.
|
|
3
|
+
"version": "2.3.2",
|
|
4
4
|
"description": "Build server and orchestration for JetStart",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -33,8 +33,8 @@
|
|
|
33
33
|
},
|
|
34
34
|
"homepage": "https://github.com/dev-phantom/jetstart#readme",
|
|
35
35
|
"dependencies": {
|
|
36
|
-
"@jetstart/shared": "^2.3.
|
|
37
|
-
"@jetstart/logs": "^2.3.
|
|
36
|
+
"@jetstart/shared": "^2.3.2",
|
|
37
|
+
"@jetstart/logs": "^2.3.2",
|
|
38
38
|
"express": "^4.18.2",
|
|
39
39
|
"ws": "^8.14.2",
|
|
40
40
|
"chokidar": "^3.5.3",
|
package/src/build/gradle.ts
CHANGED
|
@@ -7,7 +7,7 @@ import { spawn, ChildProcess, execSync } from 'child_process';
|
|
|
7
7
|
import * as fs from 'fs';
|
|
8
8
|
import * as path from 'path';
|
|
9
9
|
import * as os from 'os';
|
|
10
|
-
import { BuildConfig, BuildResult } from '@jetstart/shared';
|
|
10
|
+
import { BuildConfig, BuildResult, ErrorSeverity } from '@jetstart/shared';
|
|
11
11
|
import { BuildOutputParser } from './parser';
|
|
12
12
|
|
|
13
13
|
/**
|
|
@@ -289,18 +289,18 @@ export class GradleExecutor {
|
|
|
289
289
|
const startTime = Date.now();
|
|
290
290
|
const gradlePath = this.findGradle(config.projectPath);
|
|
291
291
|
|
|
292
|
-
// If Gradle not found,
|
|
292
|
+
// If Gradle not found, fail build with clear error
|
|
293
293
|
if (!gradlePath) {
|
|
294
|
-
console.log('[Gradle] No Gradle found, returning mock successful build for testing');
|
|
295
|
-
|
|
296
|
-
// Simulate build delay
|
|
297
|
-
await new Promise(resolve => setTimeout(resolve, 2000));
|
|
298
|
-
|
|
299
294
|
return {
|
|
300
|
-
success:
|
|
295
|
+
success: false,
|
|
301
296
|
buildTime: Date.now() - startTime,
|
|
302
|
-
|
|
303
|
-
|
|
297
|
+
errors: [{
|
|
298
|
+
file: 'gradle',
|
|
299
|
+
line: 0,
|
|
300
|
+
column: 0,
|
|
301
|
+
message: 'Gradle not found. Please install Gradle 8.0+ or ensure the Gradle wrapper (gradlew) exists in your project project.',
|
|
302
|
+
severity: ErrorSeverity.ERROR
|
|
303
|
+
}]
|
|
304
304
|
};
|
|
305
305
|
}
|
|
306
306
|
|
|
@@ -82,28 +82,99 @@ export class KotlinCompiler {
|
|
|
82
82
|
|
|
83
83
|
/**
|
|
84
84
|
* Find kotlinc executable
|
|
85
|
+
*
|
|
86
|
+
* Search order:
|
|
87
|
+
* 1. KOTLIN_HOME env var (set in .env or shell)
|
|
88
|
+
* 2. ANDROID_STUDIO_HOME env var
|
|
89
|
+
* 3. Platform-specific static paths (Scoop, Chocolatey, SDKMAN, snap, …)
|
|
90
|
+
* 4. Versioned IDE directories (IntelliJ IDEA, JetBrains Toolbox, Android Studio)
|
|
91
|
+
* 5. `where` / `which` fallback
|
|
85
92
|
*/
|
|
86
93
|
async findKotlinc(): Promise<string | null> {
|
|
87
94
|
if (this.kotlincPath) return this.kotlincPath;
|
|
88
95
|
|
|
89
|
-
|
|
90
|
-
const
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
96
|
+
const win = os.platform() === 'win32';
|
|
97
|
+
const localAppData = process.env.LOCALAPPDATA || path.join(os.homedir(), 'AppData', 'Local');
|
|
98
|
+
const progFiles = process.env.PROGRAMFILES || 'C:\\Program Files';
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Scan `parentDir` for subdirectories whose names start with `entryPrefix`
|
|
102
|
+
* (pass '' to accept any entry), then return the first candidate that exists:
|
|
103
|
+
* path.join(parentDir, entry, ...rest)
|
|
104
|
+
* Entries are sorted descending so the latest version is tried first.
|
|
105
|
+
* Returns null (never throws) if the directory is missing or unreadable.
|
|
106
|
+
*/
|
|
107
|
+
const findInVersionedDir = (
|
|
108
|
+
parentDir: string,
|
|
109
|
+
entryPrefix: string,
|
|
110
|
+
...rest: string[]
|
|
111
|
+
): string | null => {
|
|
112
|
+
try {
|
|
113
|
+
if (!fs.existsSync(parentDir)) return null;
|
|
114
|
+
const entries = fs.readdirSync(parentDir)
|
|
115
|
+
.filter(e => !entryPrefix || e.toLowerCase().startsWith(entryPrefix.toLowerCase()))
|
|
116
|
+
.sort()
|
|
117
|
+
.reverse(); // latest version first
|
|
118
|
+
for (const entry of entries) {
|
|
119
|
+
const candidate = path.join(parentDir, entry, ...rest);
|
|
120
|
+
if (fs.existsSync(candidate)) return candidate;
|
|
121
|
+
}
|
|
122
|
+
} catch { /* permission / access errors — silently skip */ }
|
|
123
|
+
return null;
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
const locations: Array<string | null> = [
|
|
127
|
+
// env overrides
|
|
128
|
+
process.env.KOTLIN_HOME
|
|
129
|
+
? path.join(process.env.KOTLIN_HOME, 'bin', 'kotlinc')
|
|
130
|
+
: null,
|
|
131
|
+
process.env.ANDROID_STUDIO_HOME
|
|
132
|
+
? path.join(process.env.ANDROID_STUDIO_HOME, 'plugins', 'Kotlin', 'kotlinc', 'bin', 'kotlinc')
|
|
133
|
+
: null,
|
|
134
|
+
|
|
135
|
+
// Windows static paths
|
|
136
|
+
win ? path.join(progFiles, 'kotlinc', 'bin', 'kotlinc.bat') : null,
|
|
137
|
+
win ? 'C:\\kotlinc\\bin\\kotlinc.bat' : null,
|
|
138
|
+
// Scoop (~\scoop\apps\kotlin\current)
|
|
139
|
+
win ? path.join(os.homedir(), 'scoop', 'apps', 'kotlin', 'current', 'bin', 'kotlinc.bat') : null,
|
|
140
|
+
// Chocolatey
|
|
141
|
+
win ? 'C:\\ProgramData\\chocolatey\\bin\\kotlinc.bat' : null,
|
|
142
|
+
// Android Studio — standard Google installer
|
|
143
|
+
win ? path.join(progFiles, 'Android', 'Android Studio', 'plugins', 'Kotlin', 'kotlinc', 'bin', 'kotlinc.bat') : null,
|
|
144
|
+
win ? path.join(localAppData,'Programs', 'Android Studio', 'plugins', 'Kotlin', 'kotlinc', 'bin', 'kotlinc.bat') : null,
|
|
145
|
+
|
|
146
|
+
// Windows versioned IDE paths (wildcard scan)
|
|
147
|
+
// IntelliJ IDEA — any version under C:\Program Files\JetBrains
|
|
148
|
+
win ? findInVersionedDir(path.join(progFiles, 'JetBrains'), 'IntelliJ IDEA',
|
|
149
|
+
'plugins', 'Kotlin', 'kotlinc', 'bin', 'kotlinc.bat') : null,
|
|
150
|
+
// JetBrains Toolbox — IDEA Ultimate
|
|
151
|
+
win ? findInVersionedDir(path.join(localAppData, 'JetBrains', 'Toolbox', 'apps', 'IDEA-U', 'ch-0'), '',
|
|
152
|
+
'plugins', 'Kotlin', 'kotlinc', 'bin', 'kotlinc.bat') : null,
|
|
153
|
+
// JetBrains Toolbox — IDEA Community
|
|
154
|
+
win ? findInVersionedDir(path.join(localAppData, 'JetBrains', 'Toolbox', 'apps', 'IDEA-C', 'ch-0'), '',
|
|
155
|
+
'plugins', 'Kotlin', 'kotlinc', 'bin', 'kotlinc.bat') : null,
|
|
156
|
+
// JetBrains Toolbox — Android Studio (Jellyfish+)
|
|
157
|
+
win ? findInVersionedDir(path.join(localAppData, 'JetBrains', 'Toolbox', 'apps', 'AndroidStudio', 'ch-0'), '',
|
|
158
|
+
'plugins', 'Kotlin', 'kotlinc', 'bin', 'kotlinc.bat') : null,
|
|
159
|
+
|
|
160
|
+
// Unix / macOS static paths
|
|
161
|
+
!win ? '/usr/local/bin/kotlinc' : null,
|
|
162
|
+
!win ? '/usr/bin/kotlinc' : null,
|
|
163
|
+
// Homebrew (Apple Silicon + Intel)
|
|
164
|
+
!win ? '/opt/homebrew/bin/kotlinc' : null,
|
|
165
|
+
!win ? '/usr/local/opt/kotlin/bin/kotlinc' : null,
|
|
166
|
+
// SDKMAN (~/.sdkman/candidates/kotlin/current)
|
|
167
|
+
!win ? path.join(os.homedir(), '.sdkman', 'candidates', 'kotlin', 'current', 'bin', 'kotlinc') : null,
|
|
168
|
+
// Snap
|
|
169
|
+
!win ? '/snap/bin/kotlinc' : null,
|
|
170
|
+
// IntelliJ IDEA — Linux Toolbox
|
|
171
|
+
!win ? findInVersionedDir(path.join(os.homedir(), '.local', 'share', 'JetBrains', 'Toolbox', 'apps', 'IDEA-U', 'ch-0'), '',
|
|
172
|
+
'plugins', 'Kotlin', 'kotlinc', 'bin', 'kotlinc') : null,
|
|
173
|
+
];
|
|
104
174
|
|
|
105
175
|
for (const loc of locations) {
|
|
106
|
-
|
|
176
|
+
if (!loc) continue;
|
|
177
|
+
const execPath = win && !loc.endsWith('.bat') ? `${loc}.bat` : loc;
|
|
107
178
|
if (fs.existsSync(execPath)) {
|
|
108
179
|
this.kotlincPath = execPath;
|
|
109
180
|
log(`Found kotlinc at: ${execPath}`);
|
|
@@ -113,7 +184,7 @@ export class KotlinCompiler {
|
|
|
113
184
|
|
|
114
185
|
// Try to find via 'where' (Windows) or 'which' (Unix)
|
|
115
186
|
try {
|
|
116
|
-
const cmd =
|
|
187
|
+
const cmd = win ? 'where' : 'which';
|
|
117
188
|
const result = await this.runCommand(cmd, ['kotlinc']);
|
|
118
189
|
if (result.success && result.stdout.trim()) {
|
|
119
190
|
this.kotlincPath = result.stdout.trim().split('\n')[0];
|