jdeploy-peopleinspace 1.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.
Binary file
Binary file
@@ -0,0 +1,649 @@
1
+ #! /usr/bin/env node
2
+
3
+ var path = require('path');
4
+ var os = require('os');
5
+ var jdeployHomeDir = process.env.JDEPLOY_HOME || path.join(os.homedir(), '.jdeploy');
6
+ var jarName = "compose-desktop-1.0-SNAPSHOT-all.jar";
7
+ var mainClass = "{{MAIN_CLASS}}";
8
+ var classPath = "{{CLASSPATH}}";
9
+ var port = "0";
10
+ var warPath = "";
11
+ var javaVersionString = "21";
12
+ var tryJavaHomeFirst = false;
13
+ var javafx = false;
14
+ var bundleType = 'jre';
15
+ if ('{{JAVAFX}}' === 'true') {
16
+ javafx = true;
17
+ }
18
+ if ('{{JDK}}' === 'true') {
19
+ bundleType = 'jdk';
20
+ }
21
+
22
+ var jdk = (bundleType === 'jdk');
23
+ var jdkProvider = 'zulu';
24
+
25
+
26
+ function njreWrap() {
27
+ 'use strict'
28
+
29
+ const fs = require('fs')
30
+ const crypto = require('crypto')
31
+ const fetch = require('node-fetch')
32
+ const yauzl = require('yauzl')
33
+ const tar = require('tar')
34
+
35
+ function createDir (dir) {
36
+ return new Promise((resolve, reject) => {
37
+ fs.access(dir, err => {
38
+ if (err && err.code === 'ENOENT') {
39
+ fs.mkdir(dir, err => {
40
+ if (err) reject(err)
41
+ resolve()
42
+ })
43
+ } else if (!err) resolve()
44
+ else reject(err)
45
+ })
46
+ })
47
+ }
48
+
49
+ function download (dir, url) {
50
+ if (url.indexOf("?") > 0 || jdkProvider === 'zulu') {
51
+ var ext = ".zip";
52
+ switch (process.platform) {
53
+ case 'linux':
54
+ ext = ".tar.gz";
55
+ break;
56
+ }
57
+ var destName = bundleType + ext;
58
+ } else {
59
+ destName = path.basename(url);
60
+ }
61
+
62
+ return new Promise((resolve, reject) => {
63
+ createDir(dir)
64
+ .then(() => fetch(url))
65
+ .then(response => {
66
+ const destFile = path.join(dir, destName)
67
+ const destStream = fs.createWriteStream(destFile)
68
+ response.body.pipe(destStream).on('finish', () => resolve(destFile))
69
+ })
70
+ .catch(err => reject(err))
71
+ })
72
+ }
73
+
74
+ function downloadAll (dir, url) {
75
+ return download(dir, url + '.sha256.txt').then(() => download(dir, url))
76
+ }
77
+
78
+ function genChecksum (file) {
79
+ return new Promise((resolve, reject) => {
80
+ fs.readFile(file, (err, data) => {
81
+ if (err) reject(err)
82
+
83
+ resolve(
84
+ crypto
85
+ .createHash('sha256')
86
+ .update(data)
87
+ .digest('hex')
88
+ )
89
+ })
90
+ })
91
+ }
92
+
93
+ function verify (file) {
94
+ return new Promise((resolve, reject) => {
95
+ fs.readFile(file + '.sha256.txt', 'utf-8', (err, data) => {
96
+ if (err) reject(err)
97
+
98
+ genChecksum(file).then(checksum => {
99
+ checksum === data.split(' ')[0]
100
+ ? resolve(file)
101
+ : reject(new Error('File and checksum don\'t match'))
102
+ })
103
+ })
104
+ })
105
+ }
106
+
107
+ function move (file) {
108
+ return new Promise((resolve, reject) => {
109
+ const jdeployDir = jdeployHomeDir;
110
+ if (!fs.existsSync(jdeployDir)) {
111
+ fs.mkdirSync(jdeployDir);
112
+ }
113
+
114
+ var jreDir = path.join(jdeployDir, bundleType);
115
+ if (!fs.existsSync(jreDir)) {
116
+ fs.mkdirSync(jreDir);
117
+ }
118
+ var vs = javaVersionString;
119
+ if (javafx) {
120
+ vs += 'fx';
121
+ }
122
+ jreDir = path.join(jreDir, vs);
123
+ if (!fs.existsSync(jreDir)) {
124
+ fs.mkdirSync(jreDir);
125
+ }
126
+ const newFile = path.join(jreDir, file.split(path.sep).slice(-1)[0])
127
+ //console.log("Copying file "+file+" to "+newFile);
128
+ fs.copyFile(file, newFile, err => {
129
+ if (err) reject(err)
130
+
131
+ fs.unlink(file, err => {
132
+ if (err) reject(err)
133
+ resolve(newFile)
134
+ })
135
+ })
136
+ })
137
+ }
138
+
139
+ function extractZip (file, dir) {
140
+ //console.log("Extracting "+file+" to "+dir);
141
+ return new Promise((resolve, reject) => {
142
+ yauzl.open(file, { lazyEntries: true }, (err, zipFile) => {
143
+ if (err) reject(err)
144
+
145
+ zipFile.readEntry()
146
+ zipFile.on('entry', entry => {
147
+ const entryPath = path.join(dir, entry.fileName)
148
+
149
+ if (/\/$/.test(entry.fileName)) {
150
+ fs.mkdir(entryPath, { recursive: true }, err => {
151
+ if (err && err.code !== 'EEXIST') reject(err)
152
+
153
+ zipFile.readEntry()
154
+ })
155
+ } else {
156
+ zipFile.openReadStream(entry, (err, readStream) => {
157
+ if (err) reject(err)
158
+
159
+ readStream.on('end', () => {
160
+ zipFile.readEntry()
161
+ })
162
+ readStream.pipe(fs.createWriteStream(entryPath))
163
+ })
164
+ }
165
+ })
166
+ zipFile.once('close', () => {
167
+ fs.unlink(file, err => {
168
+ if (err) reject(err)
169
+ resolve(dir)
170
+ })
171
+ })
172
+ })
173
+ })
174
+ }
175
+
176
+ function extractTarGz (file, dir) {
177
+ return tar.x({ file: file, cwd: dir }).then(() => {
178
+ return new Promise((resolve, reject) => {
179
+ fs.unlink(file, err => {
180
+ if (err) reject(err)
181
+ resolve(dir)
182
+ })
183
+ })
184
+ })
185
+ }
186
+
187
+ function extract (file) {
188
+ var dirString = jdk? 'jdk' : 'jre';
189
+
190
+ const dir = path.join(path.dirname(file), dirString)
191
+ //console.log("About to extract "+file+" to "+dir);
192
+ return createDir(dir).then(() => {
193
+ return path.extname(file) === '.zip'
194
+ ? extractZip(file, dir)
195
+ : extractTarGz(file, dir)
196
+ })
197
+ }
198
+
199
+ /**
200
+ * Installs a JRE copy for the app
201
+ * @param {number} [version = 8] - Java Version (`8`/`9`/`10`/`11`/`12`)
202
+ * @param {object} [options] - Installation Options
203
+ * @param {string} [options.os] - Operating System (defaults to current) (`windows`/`mac`/`linux`/`solaris`/`aix`)
204
+ * @param {string} [options.arch] - Architecture (defaults to current) (`x64`/`x32`/`ppc64`/`s390x`/`ppc64le`/`aarch64`/`sparcv9`)
205
+ * @param {string} [options.openjdk_impl = hotspot] - OpenJDK Implementation (`hotspot`/`openj9`)
206
+ * @param {string} [options.release = latest] - Release
207
+ * @param {string} [options.type = jre] - Binary Type (`jre`/`jdk`)
208
+ * @param {string} [options.heap_size] - Heap Size (`normal`/`large`)
209
+ * @return Promise<string> - Resolves to the installation directory or rejects an error
210
+ * @example
211
+ * const njre = require('njre')
212
+ *
213
+ * // Use default options
214
+ * njre.install()
215
+ * .then(dir => {
216
+ * // Do stuff
217
+ * })
218
+ * .catch(err => {
219
+ * // Handle the error
220
+ * })
221
+ *
222
+ * // or custom ones
223
+ * njre.install(11, { os: 'aix', arch: 'ppc64', openjdk_impl: 'openj9' })
224
+ * .then(dir => {
225
+ * // Do stuff
226
+ * })
227
+ * .catch(err => {
228
+ * // Handle the error
229
+ * })
230
+ */
231
+ function install (version = 11, options = {}) {
232
+ const { openjdk_impl = 'hotspot', release = 'latest', type = 'jre', javafx = false, provider = 'zulu' } = options
233
+ options = { ...options, openjdk_impl, release, type }
234
+
235
+ // Determine the architecture based on the platform and environment
236
+ let arch = process.arch;
237
+ if (arch === 'arm64' || arch === 'aarch64') {
238
+ arch = 'aarch64'; // For ARM-based systems, standardize on aarch64
239
+ } else {
240
+ arch = 'x64'; // Default to x64 for non-ARM systems
241
+ }
242
+
243
+ if (provider === 'zulu') {
244
+ return installZulu(version, options, arch);
245
+ }
246
+
247
+ let url = 'https://api.adoptopenjdk.net/v2/info/releases/openjdk' + version + '?'
248
+
249
+ if (!options.os) {
250
+ switch (process.platform) {
251
+ case 'aix':
252
+ options.os = 'aix'
253
+ break
254
+ case 'darwin':
255
+ options.os = 'mac'
256
+ break
257
+ case 'linux':
258
+ options.os = 'linux'
259
+ break
260
+ case 'sunos':
261
+ options.os = 'solaris'
262
+ break
263
+ case 'win32':
264
+ options.os = 'windows'
265
+ break
266
+ default:
267
+ return Promise.reject(new Error('Unsupported operating system'))
268
+ }
269
+ }
270
+
271
+ if (!options.arch) {
272
+ options.arch = arch; // Use the detected architecture
273
+ }
274
+
275
+ Object.keys(options).forEach(key => { url += key + '=' + options[key] + '&' })
276
+
277
+ const tmpdir = path.join(os.tmpdir(), 'njre')
278
+
279
+ return fetch(url)
280
+ .then(response => response.json())
281
+ .then(json => downloadAll(tmpdir, json.binaries[0]['binary_link']))
282
+ .then(verify)
283
+ .then(move)
284
+ .then(extract)
285
+ }
286
+
287
+ function installZulu(version = 11, options = {}, arch) {
288
+ const { type = 'jre', javafx = false } = options;
289
+
290
+ // Prepare the query parameters for the request
291
+ let q = {
292
+ java_version: version,
293
+ ext: 'zip',
294
+ bundle_type: type,
295
+ javafx: '' + javafx,
296
+ arch: arch, // Use the detected architecture
297
+ hw_bitness: '64',
298
+ };
299
+
300
+ // Base URL for the Azul API
301
+ const zuluBaseURL = "https://api.azul.com/zulu/download/community/v1.0/bundles/latest/binary?";
302
+
303
+ // Determine the OS
304
+ if (!options.os) {
305
+ switch (process.platform) {
306
+ case 'darwin':
307
+ q.os = 'macos';
308
+ break;
309
+ case 'linux':
310
+ q.os = 'linux';
311
+ q.ext = 'tar.gz';
312
+ break;
313
+ case 'win32':
314
+ case 'win64':
315
+ q.os = 'windows';
316
+ break;
317
+ default:
318
+ return Promise.reject(new Error('Unsupported operating system'));
319
+ }
320
+ }
321
+
322
+ // Construct the URL for the download request
323
+ let url = zuluBaseURL;
324
+ Object.keys(q).forEach(key => { url += key + '=' + q[key] + '&' });
325
+
326
+ const tmpdir = path.join(os.tmpdir(), 'njre');
327
+
328
+ // Function to handle the download and extraction
329
+ const attemptDownload = (url) => {
330
+ return download(tmpdir, url)
331
+ .then(move)
332
+ .then(extract);
333
+ };
334
+
335
+ // First, attempt to download the JRE
336
+ return download(tmpdir, url)
337
+ .then(response => {
338
+ // If the JRE is available, proceed with the download and extraction
339
+ if (response.status === 200) {
340
+ return attemptDownload(url);
341
+ } else {
342
+ // If JRE is not available, switch to JDK
343
+ console.log(`JRE not available for version ${version}, falling back to JDK...`);
344
+ // Update the query to request JDK instead of JRE
345
+ q.bundle_type = 'jdk'; // Switch to JDK
346
+ url = zuluBaseURL;
347
+ Object.keys(q).forEach(key => { url += key + '=' + q[key] + '&' });
348
+ return attemptDownload(url); // Try downloading the JDK
349
+ }
350
+ })
351
+ .catch(err => {
352
+ console.error("Download failed: ", err);
353
+ throw err; // Re-throw the error after logging
354
+ });
355
+ }
356
+
357
+
358
+ return {install:install};
359
+ }
360
+
361
+
362
+ var fs = require('fs');
363
+ const njre = njreWrap();
364
+ const targetJavaVersion = parseInt(javaVersionString);
365
+ var shell = require("shelljs/global");
366
+
367
+ function getJavaVersion(binPath) {
368
+
369
+ var oldPath = env['PATH'];
370
+ if (binPath) {
371
+ env['PATH'] = binPath + path.delimiter + env['PATH'];
372
+ }
373
+
374
+ try {
375
+ var javaVersionProc = exec('java -version', {silent:true});
376
+ if (javaVersionProc.code !== 0) {
377
+ return false;
378
+ }
379
+ var stdout = javaVersionProc.stderr;
380
+ var regexp = /version "(.*?)"/;
381
+ var match = regexp.exec(stdout);
382
+ var parts = match[1].split('.');
383
+ var join = '.';
384
+ var versionStr = '';
385
+ parts.forEach(function(v) {
386
+ versionStr += v;
387
+ if (join !== null) {
388
+ versionStr += join;
389
+ join = null;
390
+ }
391
+ });
392
+ versionStr = versionStr.replace('_', '');
393
+ return parseFloat(versionStr);
394
+ } catch (e) {
395
+ return false;
396
+ } finally {
397
+ env['PATH'] = oldPath;
398
+ }
399
+ }
400
+ var getDirectories = dirPath => fs.readdirSync(dirPath).filter(
401
+ file => fs.statSync(path.join(dirPath, file)).isDirectory()
402
+ );
403
+
404
+ function getJavaHomeInPath(basepath) {
405
+
406
+ var dirs = null;
407
+ try {
408
+ dirs = getDirectories(basepath);
409
+ } catch (e) {
410
+ return null;
411
+ }
412
+ if (dirs && dirs.length > 0) {
413
+ basepath = path.join(basepath, dirs[0]);
414
+ if (os.platform() != 'darwin') {
415
+ return basepath;
416
+ }
417
+ if (fs.existsSync(path.join(basepath, 'Contents', 'Home'))) {
418
+ return path.join(basepath, 'Contents', 'Home');
419
+ }
420
+
421
+ var adapterDirectories = getDirectories(basepath).filter(subdir => {
422
+ return subdir.match(/^zulu/) && fs.existsSync(path.join(basepath, subdir, 'Contents', 'Home'));
423
+ });
424
+
425
+ if (adapterDirectories && adapterDirectories.length > 0) {
426
+ return path.join(basepath, adapterDirectories[0], 'Contents', 'Home');
427
+ }
428
+ }
429
+ return null;
430
+ }
431
+
432
+ function findSupportedRuntime(javaVersion, jdk, javafx) {
433
+ var jdeployDir = jdeployHomeDir;
434
+ var JAVA_HOME_OVERRIDE = env['JDEPLOY_JAVA_HOME_OVERRIDE'];
435
+
436
+ if (JAVA_HOME_OVERRIDE && fs.existsSync(JAVA_HOME_OVERRIDE)) {
437
+ return JAVA_HOME_OVERRIDE;
438
+ }
439
+
440
+ // First check for the full-meal deal
441
+ var _javaHomePath = getJavaHomeInPath(path.join(jdeployDir, 'jdk', javaVersion+'fx', 'jdk'));
442
+ if (_javaHomePath && fs.existsSync(_javaHomePath)) {
443
+ return _javaHomePath;
444
+ }
445
+ if (!javafx) {
446
+ var _javaHomePath = getJavaHomeInPath(path.join(jdeployDir, 'jdk', javaVersion, 'jdk'));
447
+ if (_javaHomePath && fs.existsSync(_javaHomePath)) {
448
+ return _javaHomePath;
449
+ }
450
+ }
451
+
452
+ if (!jdk) {
453
+ var _javaHomePath = getJavaHomeInPath(path.join(jdeployDir, 'jre', javaVersion+'fx', 'jre'));
454
+ if (_javaHomePath && fs.existsSync(_javaHomePath)) {
455
+ return _javaHomePath;
456
+ }
457
+ }
458
+
459
+ if (!jdk && !javafx) {
460
+ var _javaHomePath = getJavaHomeInPath(path.join(jdeployDir, 'jre', javaVersion, 'jre'));
461
+ if (_javaHomePath && fs.existsSync(_javaHomePath)) {
462
+ return _javaHomePath;
463
+ }
464
+ }
465
+ return null;
466
+
467
+ }
468
+
469
+ function getEmbeddedJavaHome() {
470
+ var _platform = os.platform();
471
+ var _driver = '';
472
+ switch (_platform) {
473
+ case 'darwin': _platform = 'macosx'; _driver = 'Contents' + path.sep + 'Home'; break;
474
+ case 'win32': _platform = 'windows'; _driver = ''; break;
475
+ case 'linux': _driver = ''; break;
476
+ default:
477
+ fail('unsupported platform: ' + _platform);
478
+ }
479
+ var vs = javaVersionString;
480
+ if (javafx) {
481
+ vs += 'fx';
482
+ }
483
+ var typeDir = jdk ? 'jdk' : 'jre';
484
+
485
+ var jreDir = path.join(jdeployHomeDir, 'jre', vs, 'jre');
486
+ try {
487
+ var out = jreDir + path.sep + getDirectories(jreDir)[0] + (_driver ? (path.sep + _driver) : '');
488
+ return out;
489
+ } catch (e) {
490
+ return null;
491
+ }
492
+ }
493
+
494
+ function javaVersionMatch(v1, v2) {
495
+ if (v1 === 8) v1 = 1.8;
496
+ if (v2 === 8) v2 = 1.8;
497
+ if (Math.floor(v1) !== Math.floor(v2)) {
498
+
499
+ return false;
500
+ }
501
+ if (v1 < 2) {
502
+ // Up to 1.8, the version would be like 1.7, 1.8, etc..
503
+ // So we need to check the minor version for equivalency
504
+ return (Math.floor(v1*10) === Math.floor(v2*10));
505
+ } else {
506
+ // Starting with Java 9, the version is like 9, 10, 11, etc..
507
+ // so we just compare major version.
508
+ return (Math.floor(v1) === Math.floor(v2));
509
+ }
510
+
511
+ }
512
+
513
+ var done = false;
514
+ if (tryJavaHomeFirst) {
515
+ if (env['JAVA_HOME']) {
516
+ var javaHomeVersion = getJavaVersion(path.join(env['JAVA_HOME'], 'bin'));
517
+ if (javaVersionMatch(javaHomeVersion, targetJavaVersion)) {
518
+ done = true;
519
+ env['PATH'] = path.join(env['JAVA_HOME'], 'bin') + path.delimiter + env['PATH'];
520
+ run(env['JAVA_HOME']);
521
+
522
+ }
523
+ }
524
+
525
+ if (!done) {
526
+ var javaVersion = getJavaVersion();
527
+ if (javaVersionMatch(javaVersion, targetJavaVersion)) {
528
+ done = true;
529
+ run();
530
+ }
531
+ }
532
+ }
533
+
534
+
535
+ if (!done) {
536
+
537
+ var _javaHome = findSupportedRuntime(javaVersionString, bundleType === 'jdk', javafx);
538
+ if (_javaHome && fs.existsSync(_javaHome)) {
539
+ var javaVersion = getJavaVersion(path.join(_javaHome, 'bin'));
540
+ if (javaVersionMatch(javaVersion, targetJavaVersion)) {
541
+ env['PATH'] = path.join(_javaHome, 'bin') + path.delimiter + env['PATH'];
542
+ env['JAVA_HOME'] = _javaHome;
543
+ done = true;
544
+ run(_javaHome);
545
+ }
546
+ }
547
+
548
+ }
549
+
550
+ if (!done) {
551
+ console.log("Downloading java runtime environment for version "+targetJavaVersion);
552
+ njre.install(targetJavaVersion, {type: bundleType, javafx: javafx}).then(function(dir) {
553
+ var _javaHome = getJavaHomeInPath(dir);
554
+ if (_javaHome == null)
555
+
556
+ if (!_javaHome || !fs.existsSync(_javaHome)) {
557
+ throw new Error("After install, could not find java home at "+_javaHome);
558
+ }
559
+ env['JAVA_HOME'] = _javaHome;
560
+
561
+ var javaBinary = path.join(_javaHome, 'bin', 'java');
562
+ if (!fs.existsSync(javaBinary)) {
563
+ javaBinary += '.exe';
564
+
565
+ }
566
+ fs.chmodSync(javaBinary, 0o755);
567
+
568
+ env['PATH'] = path.join(env['JAVA_HOME'], 'bin') + path.delimiter + env['PATH'];
569
+
570
+ run(env['JAVA_HOME']);
571
+ }).catch(function(err) {
572
+ console.log("Failed to install JRE", err);
573
+ });
574
+ }
575
+
576
+
577
+
578
+
579
+ function run(_javaHome) {
580
+ var fail = reason => {
581
+ console.error(reason);
582
+ process.exit(1);
583
+ };
584
+
585
+
586
+ classPath = classPath.split(':');
587
+ var classPathStr = '';
588
+ var first = true;
589
+ classPath.forEach(function(part) {
590
+ if (!first) classPathStr += path.delimiter;
591
+ first = false;
592
+ classPathStr += __dirname + '/' + part;
593
+ });
594
+ classPath = classPathStr;
595
+
596
+ var userArgs = process.argv.slice(2);
597
+ var javaArgs = [];
598
+ javaArgs.push('-Djdeploy.base='+__dirname);
599
+ javaArgs.push('-Djdeploy.port='+port);
600
+ javaArgs.push('-Djdeploy.war.path='+warPath);
601
+ var programArgs = [];
602
+ userArgs.forEach(function(arg) {
603
+ if (arg.startsWith('-D') || arg.startsWith('-X')) {
604
+ javaArgs.push(arg);
605
+ } else {
606
+ programArgs.push(arg);
607
+ }
608
+ });
609
+ var cmd = 'java';
610
+
611
+ if (!_javaHome) {
612
+ env['PATH'] = path.join(getEmbeddedJavaHome(), 'bin') + path.delimiter + env['PATH'];
613
+ if (env['JAVA_HOME']) {
614
+ env['PATH'] = env['JAVA_HOME'] + path.sep + 'bin' + path.delimiter + env['PATH'];
615
+ }
616
+
617
+ } else {
618
+ env['JAVA_HOME'] = _javaHome;
619
+ cmd = _javaHome + path.sep + 'bin' + path.sep + 'java';
620
+ }
621
+
622
+ javaArgs.forEach(function(arg) {
623
+ cmd += ' "'+arg+'"';
624
+ });
625
+ if (jarName !== '{'+'{JAR_NAME}}') {
626
+ cmd += ' -jar "'+__dirname+'/'+jarName+'" ';
627
+ } else {
628
+ cmd += ' -cp "'+classPath+'" '+mainClass+' ';
629
+ }
630
+
631
+ programArgs.forEach(function(arg) {
632
+ cmd += ' "'+arg+'"';
633
+ });
634
+ var child = exec(cmd, {async: true});
635
+ process.stdin.setEncoding('utf8');
636
+
637
+ process.stdin.on('readable', function() {
638
+ var chunk = null;
639
+ while (null !== (chunk = process.stdin.read())) {
640
+ try {
641
+ child.stdin.write(chunk);
642
+ } catch(e){}
643
+ }
644
+ });
645
+ child.on('close', function(code) {
646
+ process.exit(code);
647
+ });
648
+
649
+ }
package/package.json ADDED
@@ -0,0 +1 @@
1
+ {"bin":{"peopleinspace":"jdeploy-bundle/jdeploy.js"},"author":"JetBrains Team","description":"People in space demo deployed with jDeploy","main":"index.js","preferGlobal":true,"repository":"","version":"1.0.0","jdeploy":{"jdk":false,"checksums":{"icon.png":"5a0da38d2182d8a5f3f9d592c9f32d3a"},"generateLegacyBundles":false,"buildCommand":["./gradlew",":compose-desktop:buildExecutableJar"],"publishTargets":[{"isDefault":true,"name":"npm: peopleinspace","type":"NPM","url":"peopleinspace"}],"javaVersion":"21","jar":"compose-desktop/build/libs/compose-desktop-1.0-SNAPSHOT-all.jar","javafx":false,"title":"People In Space","downloadPage":{"platforms":["default"]}},"dependencies":{"command-exists-promise":"^2.0.2","node-fetch":"2.6.7","tar":"^4.4.8","yauzl":"^2.10.0","shelljs":"^0.8.4"},"license":"ISC","name":"jdeploy-peopleinspace","files":["jdeploy-bundle"],"scripts":{"test":"echo \"Error: no test specified\" && exit 1"}}