sloss-cli 1.2.1 → 1.3.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/bin/sloss.js +4 -4
- package/package.json +1 -1
- package/src/commands/build.js +28 -103
- package/src/commands/login.js +6 -10
package/bin/sloss.js
CHANGED
|
@@ -120,15 +120,15 @@ program
|
|
|
120
120
|
// Build command
|
|
121
121
|
program
|
|
122
122
|
.command('build')
|
|
123
|
-
.description('
|
|
123
|
+
.description('Run a local EAS build and upload to Sloss')
|
|
124
124
|
.option('--platform <platform>', 'Platform (ios or android)', 'ios')
|
|
125
125
|
.option('--profile <profile>', 'Build profile (development, preview, production)', 'development')
|
|
126
126
|
.option('--bump <type>', 'Version bump type for production (patch, minor, major)', 'patch')
|
|
127
|
-
.option('--dir <path>', 'Project directory (default: current directory)'
|
|
127
|
+
.option('--dir <path>', 'Project directory (default: current directory)')
|
|
128
|
+
.option('--yes', 'Skip confirmation prompt')
|
|
128
129
|
.action(async (options) => {
|
|
129
130
|
try {
|
|
130
|
-
|
|
131
|
-
await buildCommand(options, config);
|
|
131
|
+
await buildCommand(options);
|
|
132
132
|
} catch (error) {
|
|
133
133
|
console.error(`Error: ${error.message}`);
|
|
134
134
|
process.exit(1);
|
package/package.json
CHANGED
package/src/commands/build.js
CHANGED
|
@@ -1,115 +1,40 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Build command
|
|
2
|
+
* Build command — thin wrapper that execs cli/build.sh with CLI flags passed through.
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import { execSync } from 'child_process';
|
|
9
|
-
import { tmpdir } from 'os';
|
|
10
|
-
import { join } from 'path';
|
|
11
|
-
import { formatBuild } from '../format.js';
|
|
5
|
+
import { resolve, dirname, join } from 'path';
|
|
6
|
+
import { fileURLToPath } from 'url';
|
|
7
|
+
import { execFileSync } from 'child_process';
|
|
12
8
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
const profile = (options.profile || 'development').toLowerCase();
|
|
16
|
-
const bump = options.bump || 'patch';
|
|
17
|
-
const projectDir = resolve(options.dir || '.');
|
|
9
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
10
|
+
const BUILD_SCRIPT = resolve(__dirname, '../../build.sh');
|
|
18
11
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
throw new Error('Platform must be "ios" or "android"');
|
|
22
|
-
}
|
|
12
|
+
export async function buildCommand(options) {
|
|
13
|
+
const args = [];
|
|
23
14
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
throw new Error('Profile must be "development", "preview", or "production"');
|
|
15
|
+
if (options.platform) {
|
|
16
|
+
args.push('--platform', options.platform);
|
|
27
17
|
}
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
const slossConfigPath = join(projectDir, '.sloss.json');
|
|
31
|
-
if (!existsSync(slossConfigPath)) {
|
|
32
|
-
throw new Error(
|
|
33
|
-
`.sloss.json not found in ${projectDir}\n` +
|
|
34
|
-
' Create a .sloss.json config file in your project root.\n' +
|
|
35
|
-
' See: https://github.com/aualdrich/sloss#build-agent'
|
|
36
|
-
);
|
|
18
|
+
if (options.profile) {
|
|
19
|
+
args.push('--profile', options.profile);
|
|
37
20
|
}
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
const slossConfig = JSON.parse(readFileSync(slossConfigPath, 'utf8'));
|
|
41
|
-
|
|
42
|
-
console.log('╔══════════════════════════════════════════╗');
|
|
43
|
-
console.log('║ SLOSS BUILD ║');
|
|
44
|
-
console.log('╠══════════════════════════════════════════╣');
|
|
45
|
-
console.log(`║ app : ${(slossConfig.app_name || '—').padEnd(27)} ║`);
|
|
46
|
-
console.log(`║ platform : ${platform.padEnd(27)} ║`);
|
|
47
|
-
console.log(`║ profile : ${profile.padEnd(27)} ║`);
|
|
48
|
-
console.log(`║ bump : ${bump.padEnd(27)} ║`);
|
|
49
|
-
console.log(`║ server : ${config.baseUrl.padEnd(27)} ║`);
|
|
50
|
-
console.log('╚══════════════════════════════════════════╝');
|
|
51
|
-
console.log('');
|
|
52
|
-
|
|
53
|
-
// Create tarball
|
|
54
|
-
console.log('📦 Packaging project...');
|
|
55
|
-
const tarballPath = join(tmpdir(), `sloss-build-${Date.now()}.tar.gz`);
|
|
56
|
-
|
|
57
|
-
// Use git archive if in a git repo (respects .gitignore), otherwise tar with excludes
|
|
58
|
-
let tarCmd;
|
|
59
|
-
try {
|
|
60
|
-
execSync('git rev-parse --git-dir', { cwd: projectDir, stdio: 'pipe' });
|
|
61
|
-
// git archive from the repo root, only including the project subdir if needed
|
|
62
|
-
const gitRoot = execSync('git rev-parse --show-toplevel', { cwd: projectDir, encoding: 'utf8' }).trim();
|
|
63
|
-
const relPath = projectDir.replace(gitRoot, '').replace(/^\//, '');
|
|
64
|
-
|
|
65
|
-
if (relPath) {
|
|
66
|
-
// Project is in a subdirectory — include only that dir
|
|
67
|
-
tarCmd = `cd "${gitRoot}" && git archive --format=tar HEAD -- "${relPath}" | gzip > "${tarballPath}"`;
|
|
68
|
-
} else {
|
|
69
|
-
tarCmd = `cd "${projectDir}" && git archive --format=tar.gz HEAD > "${tarballPath}"`;
|
|
70
|
-
}
|
|
71
|
-
} catch {
|
|
72
|
-
// Not a git repo — fall back to tar with common excludes
|
|
73
|
-
tarCmd = `cd "${projectDir}" && tar czf "${tarballPath}" --exclude=node_modules --exclude=.git --exclude=ios/build --exclude=android/build .`;
|
|
21
|
+
if (options.bump) {
|
|
22
|
+
args.push('--bump', options.bump);
|
|
74
23
|
}
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
const tarSize = statSync(tarballPath).size;
|
|
81
|
-
const sizeMB = (tarSize / (1024 * 1024)).toFixed(1);
|
|
82
|
-
console.log(` → ${sizeMB} MB`);
|
|
83
|
-
|
|
84
|
-
// Read version info from .sloss.json's version_file
|
|
85
|
-
let version = '';
|
|
86
|
-
let buildNumber = '';
|
|
87
|
-
if (slossConfig.version_file) {
|
|
88
|
-
const versionFilePath = join(projectDir, slossConfig.version_file);
|
|
89
|
-
if (existsSync(versionFilePath)) {
|
|
90
|
-
const versionData = JSON.parse(readFileSync(versionFilePath, 'utf8'));
|
|
91
|
-
version = versionData.version || '';
|
|
92
|
-
buildNumber = versionData.buildNumber || '';
|
|
93
|
-
}
|
|
24
|
+
if (options.dir) {
|
|
25
|
+
args.push('--dir', resolve(options.dir));
|
|
26
|
+
}
|
|
27
|
+
if (options.yes) {
|
|
28
|
+
args.push('--yes');
|
|
94
29
|
}
|
|
95
30
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
version,
|
|
106
|
-
buildNumber,
|
|
107
|
-
});
|
|
108
|
-
|
|
109
|
-
// Clean up tarball
|
|
110
|
-
const { unlinkSync } = await import('fs');
|
|
111
|
-
try { unlinkSync(tarballPath); } catch { /* ignore */ }
|
|
112
|
-
|
|
113
|
-
console.log('');
|
|
114
|
-
console.log(formatBuild(result, config.jsonMode));
|
|
31
|
+
try {
|
|
32
|
+
execFileSync('bash', [BUILD_SCRIPT, ...args], {
|
|
33
|
+
stdio: 'inherit',
|
|
34
|
+
env: process.env,
|
|
35
|
+
});
|
|
36
|
+
} catch (error) {
|
|
37
|
+
// build.sh handles its own error messages; just exit with the same code
|
|
38
|
+
process.exit(error.status || 1);
|
|
39
|
+
}
|
|
115
40
|
}
|
package/src/commands/login.js
CHANGED
|
@@ -20,13 +20,8 @@ const CREDENTIALS_PATH = join(homedir(), '.config', 'sloss', 'credentials.json')
|
|
|
20
20
|
*/
|
|
21
21
|
function prompt(question, hidden = false) {
|
|
22
22
|
return new Promise((resolve) => {
|
|
23
|
-
const rl = createInterface({
|
|
24
|
-
input: process.stdin,
|
|
25
|
-
output: process.stdout,
|
|
26
|
-
});
|
|
27
|
-
|
|
28
23
|
if (hidden) {
|
|
29
|
-
//
|
|
24
|
+
// Raw mode password input — no readline (avoids echo)
|
|
30
25
|
process.stdout.write(question);
|
|
31
26
|
|
|
32
27
|
let value = '';
|
|
@@ -34,19 +29,16 @@ function prompt(question, hidden = false) {
|
|
|
34
29
|
const onData = (char) => {
|
|
35
30
|
char = char.toString();
|
|
36
31
|
if (char === '\n' || char === '\r' || char === '\u0004') {
|
|
37
|
-
// Enter pressed
|
|
38
32
|
process.stdin.setRawMode(false);
|
|
39
33
|
process.stdin.pause();
|
|
40
34
|
process.stdin.removeListener('data', onData);
|
|
41
35
|
process.stdout.write('\n');
|
|
42
|
-
rl.close();
|
|
43
36
|
resolve(value);
|
|
44
37
|
} else if (char === '\u0003') {
|
|
45
|
-
|
|
38
|
+
process.stdin.setRawMode(false);
|
|
46
39
|
process.stdout.write('\n');
|
|
47
40
|
process.exit(0);
|
|
48
41
|
} else if (char === '\u007f' || char === '\b') {
|
|
49
|
-
// Backspace
|
|
50
42
|
if (value.length > 0) {
|
|
51
43
|
value = value.slice(0, -1);
|
|
52
44
|
}
|
|
@@ -60,6 +52,10 @@ function prompt(question, hidden = false) {
|
|
|
60
52
|
process.stdin.setEncoding('utf8');
|
|
61
53
|
process.stdin.on('data', onData);
|
|
62
54
|
} else {
|
|
55
|
+
const rl = createInterface({
|
|
56
|
+
input: process.stdin,
|
|
57
|
+
output: process.stdout,
|
|
58
|
+
});
|
|
63
59
|
rl.question(question, (answer) => {
|
|
64
60
|
rl.close();
|
|
65
61
|
resolve(answer);
|