@ovipakla/gm-cli 2.1.0 → 2.1.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/app.js +871 -865
- package/package.json +1 -1
package/app.js
CHANGED
|
@@ -1,865 +1,871 @@
|
|
|
1
|
-
#! /usr/bin/env node
|
|
2
|
-
|
|
3
|
-
import { watch, sync } from './GMFileWatcher.js';
|
|
4
|
-
import path from 'node:path';
|
|
5
|
-
import { Command } from 'commander';
|
|
6
|
-
import { spawn, execSync } from 'child_process';
|
|
7
|
-
import fs from 'fs';
|
|
8
|
-
import readline from 'readline';
|
|
9
|
-
import { fileURLToPath } from "node:url";
|
|
10
|
-
|
|
11
|
-
function findFileUpwardsSync(filename, maxLevels = 99) {
|
|
12
|
-
let currentDir = process.cwd();
|
|
13
|
-
for (let i = 0; i < maxLevels; i++) {
|
|
14
|
-
const candidate = path.join(currentDir, filename);
|
|
15
|
-
if (fs.existsSync(candidate)) {
|
|
16
|
-
return candidate;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
const parentDir = path.dirname(currentDir);
|
|
20
|
-
if (parentDir === currentDir) {
|
|
21
|
-
break;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
currentDir = parentDir;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
return null;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
function getPackageGM() {
|
|
31
|
-
const file = findFileUpwardsSync("package-gm.json");
|
|
32
|
-
if (file === null) {
|
|
33
|
-
throw new Error('❌ package-gm.json was not found')
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
return {
|
|
37
|
-
file: file,
|
|
38
|
-
data: JSON.parse(fs.readFileSync(file, "utf8")),
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
function getYYPPathFromPackageGM(packageGM) {
|
|
43
|
-
return path.join(path.dirname(packageGM.file), packageGM.data.main).replaceAll("\\", "/");
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
function backupPackageGM(packageGM) {
|
|
47
|
-
console.log(`📝 Backup package-gm.json: ${packageGM.file}.old`);
|
|
48
|
-
fs.copyFileSync(packageGM.file, `${packageGM.file}.old`);
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
function savePackageGM(packageGM) {
|
|
52
|
-
fs.writeFileSync(packageGM.file, JSON.stringify(packageGM.data, null, 2), "utf8");
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
function clamp(value, min, max) {
|
|
56
|
-
return Math.min(Math.max(value, min), max);
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
function getPSMonitorRAMCommand(processName, interval, name) {
|
|
60
|
-
const psCommand = `
|
|
61
|
-
\$processName = "${processName}"
|
|
62
|
-
\$interval = ${interval}
|
|
63
|
-
\$reportFile = "${name}"
|
|
64
|
-
\$timestamp = Get-Date -Format "yyyy-MM-dd_hh-mm"
|
|
65
|
-
if (\$reportFile -eq "") {
|
|
66
|
-
\$reportFile = "\$processName_\$timestamp-ram-report.csv"
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
if (-not (Test-Path \$reportFile)) {
|
|
70
|
-
"date,RAM_MB" | Out-File -FilePath \$reportFile -Encoding UTF8
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
echo "Monitoring RAM usage..."
|
|
74
|
-
|
|
75
|
-
while (\$true) {
|
|
76
|
-
\$date = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
|
|
77
|
-
try {
|
|
78
|
-
\$process = Get-Process -Name \$processName -ErrorAction Stop
|
|
79
|
-
\$ramMB = [math]::Round(\$process.WorkingSet64 / 1MB, 2)
|
|
80
|
-
"\$date,\$ramMB" | Out-File -Append -Encoding utf8 -FilePath \$reportFile
|
|
81
|
-
echo "\$date TEST [${processName}::monitor-ram]: \$ramMB"
|
|
82
|
-
} catch {
|
|
83
|
-
#"\$date,PROCESS_NOT_RUNNING" | Out-File -Append -Encoding utf8 -FilePath \$reportFile
|
|
84
|
-
echo "\$date TEST [${processName}::monitor-ram]: PROCESS_NOT_RUNNING"
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
Start-Sleep -Milliseconds \$interval
|
|
88
|
-
}
|
|
89
|
-
`
|
|
90
|
-
|
|
91
|
-
return psCommand
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
function runShellScript(scriptData) {
|
|
95
|
-
const bashProcess = spawn("bash", ["-s"], { stdio: ["pipe", "inherit", "inherit"] });
|
|
96
|
-
bashProcess.stdin.write(`#!/bin/bash\nset -Eeuo pipefail\n${scriptData}`);
|
|
97
|
-
bashProcess.stdin.end();
|
|
98
|
-
bashProcess.on("close", (code) => {
|
|
99
|
-
console.log(`Exited with code ${code}`);
|
|
100
|
-
process.exit(code);
|
|
101
|
-
});
|
|
102
|
-
return bashProcess
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
const packageJson = JSON.parse(fs.readFileSync(path.join(path.dirname(fileURLToPath(import.meta.url)), "package.json"), "utf-8"));
|
|
107
|
-
|
|
108
|
-
const program = new Command()
|
|
109
|
-
.version(packageJson.version, '-v, --version, ', 'output the current version');
|
|
110
|
-
|
|
111
|
-
const config = program
|
|
112
|
-
.command('config')
|
|
113
|
-
.description('Manage configuration');
|
|
114
|
-
|
|
115
|
-
const configSet = config
|
|
116
|
-
.command('set')
|
|
117
|
-
.description('Set config values');
|
|
118
|
-
|
|
119
|
-
const configUnset = config
|
|
120
|
-
.command('unset')
|
|
121
|
-
.description('Unset config values');
|
|
122
|
-
|
|
123
|
-
const resource = program
|
|
124
|
-
.command("resource")
|
|
125
|
-
.description("Manage resources");
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
program
|
|
129
|
-
.command('init')
|
|
130
|
-
.description('CLI creator for package-gm.json')
|
|
131
|
-
.action(async () => {
|
|
132
|
-
const rl = readline.createInterface({
|
|
133
|
-
input: process.stdin,
|
|
134
|
-
output: process.stdout
|
|
135
|
-
});
|
|
136
|
-
const askQuestion = (query) => new Promise(resolve => rl.question(query, resolve));
|
|
137
|
-
|
|
138
|
-
try {
|
|
139
|
-
console.log("This utility will walk you through creating a package-gm.json file.");
|
|
140
|
-
console.log("It only covers the most common items, and tries to guess sensible defaults.");
|
|
141
|
-
|
|
142
|
-
const projectPath = process.cwd();
|
|
143
|
-
const basename = path.basename(projectPath);
|
|
144
|
-
const version = "0.0.1";
|
|
145
|
-
const propertyPackage = await askQuestion(`package name: (${basename}) `);
|
|
146
|
-
const propertyVersion = await askQuestion(`version: (${version}) `);
|
|
147
|
-
const propertyDescription = await askQuestion('description: ');
|
|
148
|
-
const propertyYYP = await askQuestion('gamemaker project file (.yyp): ');
|
|
149
|
-
const propertyTest = await askQuestion('test command: ');
|
|
150
|
-
const propertyGit = await askQuestion('git repository: ');
|
|
151
|
-
const propertyKeywords = await askQuestion('keywords: ');
|
|
152
|
-
const propertyAuthor = await askQuestion('author: ');
|
|
153
|
-
const propertyLicense = await askQuestion('license: (ISC) ');
|
|
154
|
-
const data = {
|
|
155
|
-
name: propertyPackage === null || propertyPackage === ''
|
|
156
|
-
? basename
|
|
157
|
-
: propertyPackage,
|
|
158
|
-
version: propertyVersion === null || propertyVersion === ''
|
|
159
|
-
? version
|
|
160
|
-
: propertyVersion,
|
|
161
|
-
description: propertyDescription,
|
|
162
|
-
main: propertyYYP,
|
|
163
|
-
git: propertyGit,
|
|
164
|
-
keywords: propertyKeywords,
|
|
165
|
-
author: propertyAuthor,
|
|
166
|
-
license: propertyLicense,
|
|
167
|
-
scripts: {
|
|
168
|
-
test: propertyTest
|
|
169
|
-
},
|
|
170
|
-
dependencies: {},
|
|
171
|
-
runtimes: {},
|
|
172
|
-
};
|
|
173
|
-
|
|
174
|
-
const filePath = path.join(projectPath, 'package-gm.json');
|
|
175
|
-
const dataString = JSON.stringify(data, null, 2);
|
|
176
|
-
|
|
177
|
-
console.log(`About to write to ${filePath}:\n\n${dataString}\n\n`);
|
|
178
|
-
const response = await askQuestion(`Is this OK? (yes) `)
|
|
179
|
-
if (typeof response === 'string' && (response.includes('y') || response.includes('Y'))) {
|
|
180
|
-
fs.writeFileSync(filePath, dataString, 'utf8');
|
|
181
|
-
} else {
|
|
182
|
-
console.log('Aborted.\n');
|
|
183
|
-
}
|
|
184
|
-
} catch (error) {
|
|
185
|
-
console.error('An error occurred:', error);
|
|
186
|
-
} finally {
|
|
187
|
-
rl.close();
|
|
188
|
-
process.exit(0);
|
|
189
|
-
}
|
|
190
|
-
});
|
|
191
|
-
|
|
192
|
-
program
|
|
193
|
-
.command('watch')
|
|
194
|
-
.description('Watch modules dir and copy code to gamemaker project')
|
|
195
|
-
.action(() => {
|
|
196
|
-
watch(path.normalize(path.join(process.cwd(), 'package-gm.json')))
|
|
197
|
-
});
|
|
198
|
-
|
|
199
|
-
program
|
|
200
|
-
.command('sync')
|
|
201
|
-
.description('Copy code from modules dir to gamemaker project')
|
|
202
|
-
.action(() => {
|
|
203
|
-
sync(path.normalize(path.join(process.cwd(), 'package-gm.json')))
|
|
204
|
-
});
|
|
205
|
-
|
|
206
|
-
program
|
|
207
|
-
.command('install')
|
|
208
|
-
.description('Install dependencies listed in package-gm.json to gm_modules folder')
|
|
209
|
-
.option('-c, --clean', 'remove existing gm_modules')
|
|
210
|
-
.option('-s, --shallow', 'git clone will use depth=1 branch=REVISION')
|
|
211
|
-
.action(function() {
|
|
212
|
-
const options = this.opts();
|
|
213
|
-
const clean = options.clean !== undefined;
|
|
214
|
-
const shallow = options.shallow !== undefined;
|
|
215
|
-
const modulesDir = 'gm_modules';
|
|
216
|
-
|
|
217
|
-
if (!fs.existsSync(modulesDir)) {
|
|
218
|
-
fs.mkdirSync(modulesDir);
|
|
219
|
-
} else if (clean) {
|
|
220
|
-
fs.rmdirSync(modulesDir, { recursive: true });
|
|
221
|
-
fs.mkdirSync(modulesDir);
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
const packageGM = getPackageGM()
|
|
225
|
-
const dependencies = packageGM.data.dependencies;
|
|
226
|
-
Object.entries(dependencies).forEach(([key, dependency]) => {
|
|
227
|
-
console.log(`\n📦️ Install ${key}\n===========${"=".repeat(key.length)}`)
|
|
228
|
-
const modulePath = path.join(modulesDir, key);
|
|
229
|
-
const cloneOptions = shallow ? `--depth 1 --branch ${dependency.revision}` : ''
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
if (
|
|
307
|
-
|
|
308
|
-
}
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
const
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
const
|
|
352
|
-
const
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
.
|
|
367
|
-
.
|
|
368
|
-
.option('-
|
|
369
|
-
.
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
config.
|
|
392
|
-
}
|
|
393
|
-
|
|
394
|
-
if (options.
|
|
395
|
-
config.
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
function
|
|
417
|
-
local timestamp=$(date +"%Y-%m-%d %H:%M:%S")
|
|
418
|
-
echo -e "\\\e[90m$timestamp\\\e[0m \\\e[
|
|
419
|
-
}
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
runtime_path=$
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
igor_path
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
project_path=$
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
user_path=$
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
--
|
|
527
|
-
--
|
|
528
|
-
--
|
|
529
|
-
--
|
|
530
|
-
--
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
const
|
|
558
|
-
const
|
|
559
|
-
|
|
560
|
-
const
|
|
561
|
-
const
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
.
|
|
573
|
-
.
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
const
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
}
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
ps
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
const
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
${
|
|
683
|
-
|
|
684
|
-
${
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
};
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
1
|
+
#! /usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { watch, sync } from './GMFileWatcher.js';
|
|
4
|
+
import path from 'node:path';
|
|
5
|
+
import { Command } from 'commander';
|
|
6
|
+
import { spawn, execSync } from 'child_process';
|
|
7
|
+
import fs from 'fs';
|
|
8
|
+
import readline from 'readline';
|
|
9
|
+
import { fileURLToPath } from "node:url";
|
|
10
|
+
|
|
11
|
+
function findFileUpwardsSync(filename, maxLevels = 99) {
|
|
12
|
+
let currentDir = process.cwd();
|
|
13
|
+
for (let i = 0; i < maxLevels; i++) {
|
|
14
|
+
const candidate = path.join(currentDir, filename);
|
|
15
|
+
if (fs.existsSync(candidate)) {
|
|
16
|
+
return candidate;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const parentDir = path.dirname(currentDir);
|
|
20
|
+
if (parentDir === currentDir) {
|
|
21
|
+
break;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
currentDir = parentDir;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
return null;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function getPackageGM() {
|
|
31
|
+
const file = findFileUpwardsSync("package-gm.json");
|
|
32
|
+
if (file === null) {
|
|
33
|
+
throw new Error('❌ package-gm.json was not found')
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return {
|
|
37
|
+
file: file,
|
|
38
|
+
data: JSON.parse(fs.readFileSync(file, "utf8")),
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function getYYPPathFromPackageGM(packageGM) {
|
|
43
|
+
return path.join(path.dirname(packageGM.file), packageGM.data.main).replaceAll("\\", "/");
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function backupPackageGM(packageGM) {
|
|
47
|
+
console.log(`📝 Backup package-gm.json: ${packageGM.file}.old`);
|
|
48
|
+
fs.copyFileSync(packageGM.file, `${packageGM.file}.old`);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function savePackageGM(packageGM) {
|
|
52
|
+
fs.writeFileSync(packageGM.file, JSON.stringify(packageGM.data, null, 2), "utf8");
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function clamp(value, min, max) {
|
|
56
|
+
return Math.min(Math.max(value, min), max);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function getPSMonitorRAMCommand(processName, interval, name) {
|
|
60
|
+
const psCommand = `
|
|
61
|
+
\$processName = "${processName}"
|
|
62
|
+
\$interval = ${interval}
|
|
63
|
+
\$reportFile = "${name}"
|
|
64
|
+
\$timestamp = Get-Date -Format "yyyy-MM-dd_hh-mm"
|
|
65
|
+
if (\$reportFile -eq "") {
|
|
66
|
+
\$reportFile = "\$processName_\$timestamp-ram-report.csv"
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
if (-not (Test-Path \$reportFile)) {
|
|
70
|
+
"date,RAM_MB" | Out-File -FilePath \$reportFile -Encoding UTF8
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
echo "Monitoring RAM usage..."
|
|
74
|
+
|
|
75
|
+
while (\$true) {
|
|
76
|
+
\$date = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
|
|
77
|
+
try {
|
|
78
|
+
\$process = Get-Process -Name \$processName -ErrorAction Stop
|
|
79
|
+
\$ramMB = [math]::Round(\$process.WorkingSet64 / 1MB, 2)
|
|
80
|
+
"\$date,\$ramMB" | Out-File -Append -Encoding utf8 -FilePath \$reportFile
|
|
81
|
+
echo "\$date TEST [${processName}::monitor-ram]: \$ramMB"
|
|
82
|
+
} catch {
|
|
83
|
+
#"\$date,PROCESS_NOT_RUNNING" | Out-File -Append -Encoding utf8 -FilePath \$reportFile
|
|
84
|
+
echo "\$date TEST [${processName}::monitor-ram]: PROCESS_NOT_RUNNING"
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
Start-Sleep -Milliseconds \$interval
|
|
88
|
+
}
|
|
89
|
+
`
|
|
90
|
+
|
|
91
|
+
return psCommand
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function runShellScript(scriptData) {
|
|
95
|
+
const bashProcess = spawn("bash", ["-s"], { stdio: ["pipe", "inherit", "inherit"] });
|
|
96
|
+
bashProcess.stdin.write(`#!/bin/bash\nset -Eeuo pipefail\n${scriptData}`);
|
|
97
|
+
bashProcess.stdin.end();
|
|
98
|
+
bashProcess.on("close", (code) => {
|
|
99
|
+
console.log(`Exited with code ${code}`);
|
|
100
|
+
process.exit(code);
|
|
101
|
+
});
|
|
102
|
+
return bashProcess
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
const packageJson = JSON.parse(fs.readFileSync(path.join(path.dirname(fileURLToPath(import.meta.url)), "package.json"), "utf-8"));
|
|
107
|
+
|
|
108
|
+
const program = new Command()
|
|
109
|
+
.version(packageJson.version, '-v, --version, ', 'output the current version');
|
|
110
|
+
|
|
111
|
+
const config = program
|
|
112
|
+
.command('config')
|
|
113
|
+
.description('Manage configuration');
|
|
114
|
+
|
|
115
|
+
const configSet = config
|
|
116
|
+
.command('set')
|
|
117
|
+
.description('Set config values');
|
|
118
|
+
|
|
119
|
+
const configUnset = config
|
|
120
|
+
.command('unset')
|
|
121
|
+
.description('Unset config values');
|
|
122
|
+
|
|
123
|
+
const resource = program
|
|
124
|
+
.command("resource")
|
|
125
|
+
.description("Manage resources");
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
program
|
|
129
|
+
.command('init')
|
|
130
|
+
.description('CLI creator for package-gm.json')
|
|
131
|
+
.action(async () => {
|
|
132
|
+
const rl = readline.createInterface({
|
|
133
|
+
input: process.stdin,
|
|
134
|
+
output: process.stdout
|
|
135
|
+
});
|
|
136
|
+
const askQuestion = (query) => new Promise(resolve => rl.question(query, resolve));
|
|
137
|
+
|
|
138
|
+
try {
|
|
139
|
+
console.log("This utility will walk you through creating a package-gm.json file.");
|
|
140
|
+
console.log("It only covers the most common items, and tries to guess sensible defaults.");
|
|
141
|
+
|
|
142
|
+
const projectPath = process.cwd();
|
|
143
|
+
const basename = path.basename(projectPath);
|
|
144
|
+
const version = "0.0.1";
|
|
145
|
+
const propertyPackage = await askQuestion(`package name: (${basename}) `);
|
|
146
|
+
const propertyVersion = await askQuestion(`version: (${version}) `);
|
|
147
|
+
const propertyDescription = await askQuestion('description: ');
|
|
148
|
+
const propertyYYP = await askQuestion('gamemaker project file (.yyp): ');
|
|
149
|
+
const propertyTest = await askQuestion('test command: ');
|
|
150
|
+
const propertyGit = await askQuestion('git repository: ');
|
|
151
|
+
const propertyKeywords = await askQuestion('keywords: ');
|
|
152
|
+
const propertyAuthor = await askQuestion('author: ');
|
|
153
|
+
const propertyLicense = await askQuestion('license: (ISC) ');
|
|
154
|
+
const data = {
|
|
155
|
+
name: propertyPackage === null || propertyPackage === ''
|
|
156
|
+
? basename
|
|
157
|
+
: propertyPackage,
|
|
158
|
+
version: propertyVersion === null || propertyVersion === ''
|
|
159
|
+
? version
|
|
160
|
+
: propertyVersion,
|
|
161
|
+
description: propertyDescription,
|
|
162
|
+
main: propertyYYP,
|
|
163
|
+
git: propertyGit,
|
|
164
|
+
keywords: propertyKeywords,
|
|
165
|
+
author: propertyAuthor,
|
|
166
|
+
license: propertyLicense,
|
|
167
|
+
scripts: {
|
|
168
|
+
test: propertyTest
|
|
169
|
+
},
|
|
170
|
+
dependencies: {},
|
|
171
|
+
runtimes: {},
|
|
172
|
+
};
|
|
173
|
+
|
|
174
|
+
const filePath = path.join(projectPath, 'package-gm.json');
|
|
175
|
+
const dataString = JSON.stringify(data, null, 2);
|
|
176
|
+
|
|
177
|
+
console.log(`About to write to ${filePath}:\n\n${dataString}\n\n`);
|
|
178
|
+
const response = await askQuestion(`Is this OK? (yes) `)
|
|
179
|
+
if (typeof response === 'string' && (response.includes('y') || response.includes('Y'))) {
|
|
180
|
+
fs.writeFileSync(filePath, dataString, 'utf8');
|
|
181
|
+
} else {
|
|
182
|
+
console.log('Aborted.\n');
|
|
183
|
+
}
|
|
184
|
+
} catch (error) {
|
|
185
|
+
console.error('An error occurred:', error);
|
|
186
|
+
} finally {
|
|
187
|
+
rl.close();
|
|
188
|
+
process.exit(0);
|
|
189
|
+
}
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
program
|
|
193
|
+
.command('watch')
|
|
194
|
+
.description('Watch modules dir and copy code to gamemaker project')
|
|
195
|
+
.action(() => {
|
|
196
|
+
watch(path.normalize(path.join(process.cwd(), 'package-gm.json')))
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
program
|
|
200
|
+
.command('sync')
|
|
201
|
+
.description('Copy code from modules dir to gamemaker project')
|
|
202
|
+
.action(() => {
|
|
203
|
+
sync(path.normalize(path.join(process.cwd(), 'package-gm.json')))
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
program
|
|
207
|
+
.command('install')
|
|
208
|
+
.description('Install dependencies listed in package-gm.json to gm_modules folder')
|
|
209
|
+
.option('-c, --clean', 'remove existing gm_modules')
|
|
210
|
+
.option('-s, --shallow', 'git clone will use depth=1 branch=REVISION')
|
|
211
|
+
.action(function() {
|
|
212
|
+
const options = this.opts();
|
|
213
|
+
const clean = options.clean !== undefined;
|
|
214
|
+
const shallow = options.shallow !== undefined;
|
|
215
|
+
const modulesDir = 'gm_modules';
|
|
216
|
+
|
|
217
|
+
if (!fs.existsSync(modulesDir)) {
|
|
218
|
+
fs.mkdirSync(modulesDir);
|
|
219
|
+
} else if (clean) {
|
|
220
|
+
fs.rmdirSync(modulesDir, { recursive: true });
|
|
221
|
+
fs.mkdirSync(modulesDir);
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
const packageGM = getPackageGM()
|
|
225
|
+
const dependencies = packageGM.data.dependencies;
|
|
226
|
+
Object.entries(dependencies).forEach(([key, dependency]) => {
|
|
227
|
+
console.log(`\n📦️ Install ${key}\n===========${"=".repeat(key.length)}`)
|
|
228
|
+
const modulePath = path.join(modulesDir, key).replaceAll("\\", "/");
|
|
229
|
+
const cloneOptions = shallow ? `--depth 1 --branch ${dependency.revision}` : ''
|
|
230
|
+
const fetchOptions = shallow ? `origin "${dependency.revision}"` : `--all --tags`
|
|
231
|
+
const commit = `
|
|
232
|
+
COMMIT="${dependencies.revision}"
|
|
233
|
+
if git rev-parse --verify "${dependency.revision}^{commit}" >/dev/null 2>&1; then
|
|
234
|
+
COMMIT=\$(git rev-parse "${dependency.revision}^{commit}")
|
|
235
|
+
elif git rev-parse --verify "origin/${dependency.revision}^{commit}" >/dev/null 2>&1; then
|
|
236
|
+
COMMIT=\$(git rev-parse "origin/${dependency.revision}^{commit}")
|
|
237
|
+
else
|
|
238
|
+
echo "Cannot resolve revision ${dependency.revision}"
|
|
239
|
+
exit 1
|
|
240
|
+
fi
|
|
241
|
+
|
|
242
|
+
`
|
|
243
|
+
if (fs.existsSync(modulePath)) {
|
|
244
|
+
try {
|
|
245
|
+
execSync('git rev-parse --is-inside-work-tree', { shell: "bash", cwd: modulePath, stdio: 'ignore' });
|
|
246
|
+
console.log(`🌐 Syncing ${modulePath} to revision ${dependency.revision}`);
|
|
247
|
+
execSync(`git fetch ${fetchOptions}`, { shell: "bash", cwd: modulePath, stdio: 'inherit' });
|
|
248
|
+
execSync(`${commit}git checkout --detach --force \$COMMIT`, { shell: "bash", cwd: modulePath, stdio: 'inherit' });
|
|
249
|
+
execSync(`${commit}git reset --hard \$COMMIT`, { shell: "bash", cwd: modulePath, stdio: 'ignore' });
|
|
250
|
+
execSync(`git clean -fdx`, { shell: "bash", cwd: modulePath, stdio: 'inherit' });
|
|
251
|
+
} catch (error) {
|
|
252
|
+
console.log(`🗑️ Removing ${modulePath} because it's not a git repository`);
|
|
253
|
+
fs.rmSync(modulePath, { recursive: true, force: true });
|
|
254
|
+
console.log(`🔧 Initializing ${modulePath} to revision ${dependency.revision}`);
|
|
255
|
+
execSync(`git clone ${cloneOptions} ${dependency.remote} ${modulePath}`, { shell: "bash", stdio: 'inherit' });
|
|
256
|
+
execSync(`git fetch ${fetchOptions}`, { shell: "bash", cwd: modulePath, stdio: 'inherit' });
|
|
257
|
+
execSync(`${commit}git checkout --detach --force \$COMMIT`, { shell: "bash", cwd: modulePath, stdio: 'inherit' });
|
|
258
|
+
}
|
|
259
|
+
} else {
|
|
260
|
+
console.log(`🔧 Initializing ${modulePath} to revision ${dependency.revision}`);
|
|
261
|
+
execSync(`git clone ${cloneOptions} ${dependency.remote} ${modulePath}`, { shell: "bash", stdio: 'inherit' });
|
|
262
|
+
execSync(`git fetch ${fetchOptions}`, { shell: "bash", cwd: modulePath, stdio: 'inherit' });
|
|
263
|
+
execSync(`${commit}git checkout --detach --force \$COMMIT`, { shell: "bash", cwd: modulePath, stdio: 'inherit' });
|
|
264
|
+
}
|
|
265
|
+
});
|
|
266
|
+
|
|
267
|
+
console.log('\n\n✅ All dependencies processed.');
|
|
268
|
+
process.exit(0);
|
|
269
|
+
})
|
|
270
|
+
|
|
271
|
+
program
|
|
272
|
+
.command('run')
|
|
273
|
+
.description('Run the script named <foo>')
|
|
274
|
+
.argument('<foo>', 'script name')
|
|
275
|
+
.action((foo) => {
|
|
276
|
+
if (typeof foo !== 'string') {
|
|
277
|
+
console.log(`missing argument`);
|
|
278
|
+
console.log(`Exited with code 1`);
|
|
279
|
+
return process.exit(1);
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
const packageGM = getPackageGM()
|
|
283
|
+
const scriptData = packageGM.data.scripts[foo]
|
|
284
|
+
if (typeof scriptData !== 'string') {
|
|
285
|
+
console.log(`script ${foo} wasn't found`);
|
|
286
|
+
console.log(`Exited with code 1`);
|
|
287
|
+
return process.exit(1);
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
const shellScript = `#!/bin/bash
|
|
291
|
+
cd ${path.dirname(packageGM.file).replaceAll("\\", "/")}
|
|
292
|
+
|
|
293
|
+
${scriptData}
|
|
294
|
+
`;
|
|
295
|
+
runShellScript(shellScript)
|
|
296
|
+
});
|
|
297
|
+
|
|
298
|
+
program
|
|
299
|
+
.command('generate')
|
|
300
|
+
.description('Generate *.yyp IncludedFiles section')
|
|
301
|
+
.action(function() {
|
|
302
|
+
function getFilesRecursively(dir, root) {
|
|
303
|
+
let files = [];
|
|
304
|
+
for (const entry of fs.readdirSync(dir)) {
|
|
305
|
+
const fullPath = path.join(dir, entry).replaceAll("\\", "/");
|
|
306
|
+
if (fs.statSync(fullPath).isDirectory()) {
|
|
307
|
+
files = files.concat(getFilesRecursively(fullPath, root));
|
|
308
|
+
} else {
|
|
309
|
+
const filePath = `datafiles${(fullPath.startsWith(root) ? fullPath.slice(root.length) : fullPath)}`.replaceAll(`/${entry}`, '');
|
|
310
|
+
const line = `{"$GMIncludedFile":"","%Name":"${entry}","CopyToMask":-1,"filePath":"${filePath}","name":"${entry}","resourceType":"GMIncludedFile","resourceVersion":"2.0",},`;
|
|
311
|
+
files.push(line);
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
return files;
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
function parseEnvFile(filePath) {
|
|
318
|
+
const content = fs.readFileSync(filePath, "utf8");
|
|
319
|
+
const result = new Map();
|
|
320
|
+
content.split(/\r?\n/).forEach(line => {
|
|
321
|
+
line = line.trim();
|
|
322
|
+
if (!line || line.startsWith("#")) {
|
|
323
|
+
return;
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
const match = line.match(/^([^=]+)="(.*)"$/);
|
|
327
|
+
if (match) {
|
|
328
|
+
const [, key, value] = match;
|
|
329
|
+
result.set(key.trim(), value);
|
|
330
|
+
}
|
|
331
|
+
});
|
|
332
|
+
|
|
333
|
+
return result;
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
const envFile = findFileUpwardsSync(".gm-cli.env");
|
|
337
|
+
if (envFile === null) {
|
|
338
|
+
console.error('.gm-cli.env was not found')
|
|
339
|
+
return
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
const packageGM = getPackageGM()
|
|
343
|
+
if (packageGM === null) {
|
|
344
|
+
return null
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
const envPath = path.dirname(envFile).replaceAll("\\", "/");
|
|
348
|
+
const envMap = parseEnvFile(envFile);
|
|
349
|
+
const projectPath = path.dirname(path.join(path.dirname(packageGM.file), packageGM.data.main.replaceAll("\\", "/")));
|
|
350
|
+
const yypPath = getYYPPathFromPackageGM(packageGM)
|
|
351
|
+
const yypOldPath = `${yypPath}.old`
|
|
352
|
+
const yyp = fs.readFileSync(yypPath, "utf8");
|
|
353
|
+
console.log(`📝 Backup yyp:`, yypOldPath);
|
|
354
|
+
fs.copyFileSync(yypPath, yypOldPath);
|
|
355
|
+
|
|
356
|
+
const datafilesPath = path.join(projectPath, "datafiles").replaceAll("\\", "/")
|
|
357
|
+
const datafiles = getFilesRecursively(datafilesPath, datafilesPath)
|
|
358
|
+
const replaced = yyp.replace(/"IncludedFiles"\s*:\s*\[(.*?)\]/s, `"IncludedFiles":[
|
|
359
|
+
${datafiles.join("\n ")}
|
|
360
|
+
]`);
|
|
361
|
+
console.log(`📝 Save yyp:`, yypPath);
|
|
362
|
+
fs.writeFileSync(yypPath, replaced, "utf8");
|
|
363
|
+
});
|
|
364
|
+
|
|
365
|
+
program
|
|
366
|
+
.command('make')
|
|
367
|
+
.description('Build and run gamemaker project')
|
|
368
|
+
.option('-t, --target <target>', 'available targets: windows')
|
|
369
|
+
.option('-r, --runtime <type>', 'use VM or YYC runtime')
|
|
370
|
+
.option('-n, --name <name>', 'The actual file name of the ZIP file that is created')
|
|
371
|
+
.option('-l, --launch', 'launch the executable after building')
|
|
372
|
+
.option('-c, --clean', 'make clean build')
|
|
373
|
+
.option('-p, --projectool', 'Path to ProjectTool.exe')
|
|
374
|
+
.action(function() {
|
|
375
|
+
const packageGM = getPackageGM()
|
|
376
|
+
const targetMap = new Map([ [ 'windows', 'win' ] ])
|
|
377
|
+
const options = this.opts();
|
|
378
|
+
const config = {
|
|
379
|
+
runtime: '$GM_CLI_DEFAULT_RUNTIME',
|
|
380
|
+
target: '$GM_CLI_DEFAULT_TARGET',
|
|
381
|
+
projectool: '$GM_CLI_PROJECT_TOOL_PATH',
|
|
382
|
+
clean: 'false',
|
|
383
|
+
launch: 'PackageZip',
|
|
384
|
+
name: packageGM.data.name,
|
|
385
|
+
zip: packageGM.data.name,
|
|
386
|
+
yyp: path.basename(packageGM.data.main).replaceAll("\\", "/"),
|
|
387
|
+
path: path.join(path.dirname(packageGM.file), path.dirname(packageGM.data.main)).replaceAll("\\", "/"),
|
|
388
|
+
};
|
|
389
|
+
|
|
390
|
+
if (options.runtime !== undefined) {
|
|
391
|
+
config.runtime = options.runtime;
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
if (options.target !== undefined && targetMap.has(options.target)) {
|
|
395
|
+
config.target = options.target;
|
|
396
|
+
config.targetExt = targetMap.get(config.target);
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
if (options.projectool !== undefined) {
|
|
400
|
+
config.projectool = options.projectool;
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
if (options.clean !== undefined) {
|
|
404
|
+
config.clean = 'true';
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
if (options.launch !== undefined) {
|
|
408
|
+
config.launch = 'Run';
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
if (options.name !== undefined && typeof options.name === 'string' && options.name.trim() !== '') {
|
|
412
|
+
config.zip = options.name;
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
const shellScript = `#!/bin/bash
|
|
416
|
+
function log_info {
|
|
417
|
+
local timestamp=$(date +"%Y-%m-%d %H:%M:%S")
|
|
418
|
+
echo -e "\\\e[90m$timestamp\\\e[0m \\\e[32mINFO\\\e[0m \\\e[35m[gm-cli::make]\\\e[0m $1"
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
function log_error {
|
|
422
|
+
local timestamp=$(date +"%Y-%m-%d %H:%M:%S")
|
|
423
|
+
echo -e "\\\e[90m$timestamp\\\e[0m \\\e[31mERROR\\\e[0m \\\e[35m[gm-cli::make]\\\e[0m $1"
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
gm_cli_env_path=""
|
|
427
|
+
dir=$(realpath "$PWD")
|
|
428
|
+
while [ "$dir" != "/" ]; do
|
|
429
|
+
if [ -f "$dir/.gm-cli.env" ]; then
|
|
430
|
+
gm_cli_env_path="$dir/.gm-cli.env"
|
|
431
|
+
log_info "Load configuration '$gm_cli_env_path'"
|
|
432
|
+
set -a
|
|
433
|
+
. "$gm_cli_env_path"
|
|
434
|
+
set +a
|
|
435
|
+
break
|
|
436
|
+
fi
|
|
437
|
+
dir=$(dirname "$dir")
|
|
438
|
+
done
|
|
439
|
+
|
|
440
|
+
runtime_path=$GM_CLI_RUNTIME_PATH
|
|
441
|
+
if [ -z "$runtime_path" ]; then
|
|
442
|
+
log_error "GM_CLI_RUNTIME_PATH must be defined! exit 1"
|
|
443
|
+
exit 1
|
|
444
|
+
fi
|
|
445
|
+
runtime_path=$(realpath $runtime_path)
|
|
446
|
+
|
|
447
|
+
igor_path="$\{GM_CLI_RUNTIME_PATH%/\}/bin/igor/windows/x64/Igor.exe"
|
|
448
|
+
if [ -z "$igor_path" ]; then
|
|
449
|
+
log_error "GM_CLI_RUNTIME_PATH must be defined! exit 1"
|
|
450
|
+
exit 1
|
|
451
|
+
fi
|
|
452
|
+
igor_path=$(realpath $igor_path)
|
|
453
|
+
|
|
454
|
+
project_name=${config.name}
|
|
455
|
+
if [ -z "$project_name" ]; then
|
|
456
|
+
log_error "package-gm.json name field must be defined! exit 1"
|
|
457
|
+
exit 1
|
|
458
|
+
fi
|
|
459
|
+
|
|
460
|
+
project_yyp=${config.yyp}
|
|
461
|
+
if [ -z "$project_yyp" ]; then
|
|
462
|
+
log_error "package-gm.json yyp field must be defined! exit 1"
|
|
463
|
+
exit 1
|
|
464
|
+
fi
|
|
465
|
+
|
|
466
|
+
project_path=${config.path}
|
|
467
|
+
if [ -z "$project_path" ]; then
|
|
468
|
+
log_error "package-gm.json yyp field must be defined! exit 1"
|
|
469
|
+
exit 1
|
|
470
|
+
fi
|
|
471
|
+
project_path=$(realpath $project_path)
|
|
472
|
+
|
|
473
|
+
user_path=$GM_CLI_USER_PATH
|
|
474
|
+
if [ -z "$user_path" ]; then
|
|
475
|
+
log_error "GM_CLI_USER_PATH must be defined! exit 1"
|
|
476
|
+
exit 1
|
|
477
|
+
fi
|
|
478
|
+
user_path=$(realpath $user_path)
|
|
479
|
+
|
|
480
|
+
runtime=${config.runtime}
|
|
481
|
+
if [ -z "$runtime" ]; then
|
|
482
|
+
log_error "GM_CLI_DEFAULT_RUNTIME must be defined! exit 1"
|
|
483
|
+
exit 1
|
|
484
|
+
fi
|
|
485
|
+
|
|
486
|
+
target=${config.target}
|
|
487
|
+
if [ -z "$target" ]; then
|
|
488
|
+
log_error "GM_CLI_DEFAULT_TARGET must be defined! exit 1"
|
|
489
|
+
exit 1
|
|
490
|
+
fi
|
|
491
|
+
|
|
492
|
+
zip_name=${config.zip}
|
|
493
|
+
echo $zip_name
|
|
494
|
+
if [ -z "$zip_name" ]; then
|
|
495
|
+
log_error "--name must be defined! exit 1"
|
|
496
|
+
exit 1
|
|
497
|
+
fi
|
|
498
|
+
|
|
499
|
+
project_tool=${config.projectool}
|
|
500
|
+
echo $project_tool
|
|
501
|
+
if [ -z "$project_tool" ]; then
|
|
502
|
+
log_error "--projectool must be defined! exit 1"
|
|
503
|
+
exit 1
|
|
504
|
+
fi
|
|
505
|
+
|
|
506
|
+
clean=${config.clean}
|
|
507
|
+
if [ "$clean" = "true" ]; then
|
|
508
|
+
log_info "Clean '$project_path/tmp/igor'"
|
|
509
|
+
rm -rf $project_path/tmp/igor
|
|
510
|
+
|
|
511
|
+
log_info "Execute shell command:\n\\\e[33m$igor_path \\ \n --runtimePath="$runtime_path" \\ \n --runtime=$runtime \\ \n --project="$\{project_path\}/$\{project_yyp\}" \\ \n --projectool="$\{project_tool\}" \\ \n --uf="$user_path" \\ \n -- $target Clean\n\\\e[0m"
|
|
512
|
+
$igor_path \
|
|
513
|
+
--runtimePath="$runtime_path" \
|
|
514
|
+
--runtime=$runtime \
|
|
515
|
+
--project="$\{project_path\}/$\{project_yyp\}" \
|
|
516
|
+
--projectool="$\{project_tool\}" \
|
|
517
|
+
--uf="$user_path" \
|
|
518
|
+
-- $target Clean | GREP_COLORS='mt=01;31' grep --color=always -E 'Error : |$'
|
|
519
|
+
fi
|
|
520
|
+
|
|
521
|
+
log_info "Clean '$\{project_path\}/tmp/igor/out'"
|
|
522
|
+
rm -rf $\{project_path\}/tmp/igor/out
|
|
523
|
+
|
|
524
|
+
log_info "Execute shell command:\n\\\e[33m$igor_path \\ \n --project="$\{project_path\}/$\{project_yyp\}" \\ \n --user="$user_path" \\ \n --runtimePath="$runtime_path" \\ \n --runtime=$runtime \\ \n --cache="$\{project_path\}/tmp/igor/cache" \\ \n --temp="$\{project_path\}/tmp/igor/temp" \\ \n --of="$\{project_path\}/tmp/igor/out/$\{project_name\}.win" \\ \n --tf="$\{zip_name\}.zip" \\ \n --projectool="$\{project_tool\}" \\ \n --uf="$user_path" \\ \n -- $target ${config.launch}\\\e[0m"
|
|
525
|
+
$igor_path \
|
|
526
|
+
--project="$\{project_path\}/$\{project_yyp\}" \
|
|
527
|
+
--user="$user_path" \
|
|
528
|
+
--runtimePath="$runtime_path" \
|
|
529
|
+
--runtime=$runtime \
|
|
530
|
+
--cache="$\{project_path\}/tmp/igor/cache" \
|
|
531
|
+
--temp="$\{project_path\}/tmp/igor/temp" \
|
|
532
|
+
--of="$\{project_path\}/tmp/igor/out/$\{project_name\}.win" \
|
|
533
|
+
--tf="$\{zip_name\}.zip" \
|
|
534
|
+
--projectool="$\{project_tool\}" \
|
|
535
|
+
--uf="$user_path" \
|
|
536
|
+
-- $target ${config.launch} | GREP_COLORS='mt=01;31' grep --color=always -E 'Error : |$'
|
|
537
|
+
|
|
538
|
+
exit 0
|
|
539
|
+
`;
|
|
540
|
+
|
|
541
|
+
runShellScript(shellScript)
|
|
542
|
+
});
|
|
543
|
+
|
|
544
|
+
program
|
|
545
|
+
.command('env')
|
|
546
|
+
.description('CLI creator for .gm-cli.env')
|
|
547
|
+
.action(async () => {
|
|
548
|
+
const rl = readline.createInterface({
|
|
549
|
+
input: process.stdin,
|
|
550
|
+
output: process.stdout
|
|
551
|
+
});
|
|
552
|
+
const askQuestion = (query) => new Promise(resolve => rl.question(query, resolve));
|
|
553
|
+
|
|
554
|
+
try {
|
|
555
|
+
console.log("This utility will walk you through creating a .gm-cli.env file.");
|
|
556
|
+
|
|
557
|
+
const runtimes = [ "VM", "YYC" ]
|
|
558
|
+
const targets = [ "windows" ]
|
|
559
|
+
|
|
560
|
+
const projectPath = process.cwd();
|
|
561
|
+
const propertyDefaultRuntime = await askQuestion('Default runtime [ VM, YYC ]: ');
|
|
562
|
+
const propertyDefaultTarget = await askQuestion('Default target [ windows ]: ');
|
|
563
|
+
const propertyProjectoolPath = await askQuestion('Path to ProjectTool.exe: ');
|
|
564
|
+
const propertyRuntimePath = await askQuestion('Path to gamemaker runtime: ');
|
|
565
|
+
const propertyUserPath = await askQuestion('Path to gamemaker user: ');
|
|
566
|
+
const propertyVsDevCmdPath = await askQuestion('Path to VsDevCmd.bat: ');
|
|
567
|
+
const data = {
|
|
568
|
+
GM_CLI_DEFAULT_RUNTIME: runtimes.includes(propertyDefaultRuntime) ? propertyDefaultRuntime : runtimes[0],
|
|
569
|
+
GM_CLI_DEFAULT_TARGET: runtimes.includes(propertyDefaultTarget) ? propertyDefaultTarget : targets[0],
|
|
570
|
+
GM_CLI_PROJECT_TOOL_PATH: path.normalize(propertyProjectoolPath),
|
|
571
|
+
GM_CLI_RUNTIME_PATH: path.normalize(propertyRuntimePath),
|
|
572
|
+
GM_CLI_USER_PATH: path.normalize(propertyUserPath),
|
|
573
|
+
GM_CLI_VS_DEV_CMD_PATH: path.normalize(propertyVsDevCmdPath),
|
|
574
|
+
};
|
|
575
|
+
|
|
576
|
+
const filePath = path.join(projectPath, '.gm-cli.env');
|
|
577
|
+
const dataString = Object.entries(data)
|
|
578
|
+
.map(([key, value]) => `${key}="${value}"`)
|
|
579
|
+
.join("\n");
|
|
580
|
+
|
|
581
|
+
console.log(`About to write to ${filePath}:\n\n${dataString}\n\n`);
|
|
582
|
+
const response = await askQuestion(`Is this OK? (yes) `)
|
|
583
|
+
if (typeof response === 'string' && (response.includes('y') || response.includes('Y'))) {
|
|
584
|
+
fs.writeFileSync(filePath, dataString, 'utf8');
|
|
585
|
+
} else {
|
|
586
|
+
console.log('Aborted.\n');
|
|
587
|
+
}
|
|
588
|
+
} catch (error) {
|
|
589
|
+
console.error('An error occurred:', error);
|
|
590
|
+
} finally {
|
|
591
|
+
rl.close();
|
|
592
|
+
process.exit(0);
|
|
593
|
+
}
|
|
594
|
+
});
|
|
595
|
+
|
|
596
|
+
program
|
|
597
|
+
.command('monitor-ram')
|
|
598
|
+
.description('Monitor RAM usage and save it to csv file')
|
|
599
|
+
.option('-i, --interval <interval>', 'step value in seconds (default = 15)')
|
|
600
|
+
.option('-n, --name <name>', 'name of binary')
|
|
601
|
+
.option('-r, --report <report>', 'name of CSV report file')
|
|
602
|
+
.action((options) => {
|
|
603
|
+
const packageGM = getPackageGM()
|
|
604
|
+
const interval = clamp((Number.isNaN(Number(options.interval)) ? 15.0 : Number(options.interval)), 1.0 / 60.0, 999.0)
|
|
605
|
+
const name = options.name === undefined ? packageGM.data.name : options.name
|
|
606
|
+
const report = options.report === undefined ? '' : options.report
|
|
607
|
+
const psCommand = getPSMonitorRAMCommand(name, 1000.0 * interval, report)
|
|
608
|
+
const ps = spawn('powershell.exe', [
|
|
609
|
+
'-NoProfile',
|
|
610
|
+
'-Command',
|
|
611
|
+
psCommand
|
|
612
|
+
]);
|
|
613
|
+
|
|
614
|
+
ps.stdout.on('data', data => {
|
|
615
|
+
console.log(data.toString().replace(/\r?\n$/, ''));
|
|
616
|
+
});
|
|
617
|
+
|
|
618
|
+
ps.stderr.on('data', data => {
|
|
619
|
+
console.error(data.toString().replace(/\r?\n$/, ''));
|
|
620
|
+
});
|
|
621
|
+
|
|
622
|
+
ps.on('close', code => {
|
|
623
|
+
console.log(`Exited with code ${code}`);
|
|
624
|
+
});
|
|
625
|
+
})
|
|
626
|
+
|
|
627
|
+
program
|
|
628
|
+
.command('test')
|
|
629
|
+
.description('Run tests')
|
|
630
|
+
.option('-t, --tests <tests>', 'List of paths to json test cases')
|
|
631
|
+
.option('-b, --build <build>', 'Path to executable')
|
|
632
|
+
.option('-m, --monitorRAM', 'Monitor RAM while testing')
|
|
633
|
+
.action((options) => {
|
|
634
|
+
const packageGM = getPackageGM()
|
|
635
|
+
|
|
636
|
+
const shellMonitorRAMScript = options.monitorRAM === undefined ? `` : `
|
|
637
|
+
set -m
|
|
638
|
+
gm-cli monitor-ram --name \$\{EXE_FILE%.exe\} &
|
|
639
|
+
pid=\$!
|
|
640
|
+
trap "kill -- -\$pid 2>/dev/null" EXIT INT TERM
|
|
641
|
+
`;
|
|
642
|
+
|
|
643
|
+
const shellBuildScript = options.build !== undefined ? `
|
|
644
|
+
cd ${path.dirname(options.build).replaceAll("\\", "/")}
|
|
645
|
+
build_name="\$\{PWD##*/\}"
|
|
646
|
+
|
|
647
|
+
EXE_FILE="${path.basename(options.build)}"
|
|
648
|
+
EXE_COUNT=1
|
|
649
|
+
` : `
|
|
650
|
+
build_name="${packageGM.data.name}_test"
|
|
651
|
+
rm -rf \$build_name.zip
|
|
652
|
+
rm -rf \$build_name
|
|
653
|
+
gm-cli make --name \$build_name
|
|
654
|
+
unzip \$build_name.zip -d \$build_name
|
|
655
|
+
cd \$build_name
|
|
656
|
+
|
|
657
|
+
EXE_FILE=\$(find . -maxdepth 1 -type f -name "*.exe" -printf "%f\n" 2>/dev/null)
|
|
658
|
+
EXE_COUNT=\$(printf "%s\n" "\$EXE_FILE" | grep -c .)
|
|
659
|
+
`;
|
|
660
|
+
|
|
661
|
+
const shellTestScript = options.tests === undefined ? `
|
|
662
|
+
TESTS=\$(find . -type f -name "*test.json" -print0 | xargs -0 echo | sed 's/ /, /g')
|
|
663
|
+
` : `
|
|
664
|
+
TESTS=\"${options.tests}\"
|
|
665
|
+
`
|
|
666
|
+
|
|
667
|
+
const shellCommandScript = `
|
|
668
|
+
TIMESTAMP=\$(date +"%Y-%m-%d_%H-%M")
|
|
669
|
+
OUTPUT_FILE="\$\{TIMESTAMP\}_\$\{EXE_FILE%.exe\}_run-test.log"
|
|
670
|
+
COMMAND="./\$EXE_FILE -output \"\$OUTPUT_FILE\" --tests \\\"\$TESTS\\\""
|
|
671
|
+
|
|
672
|
+
if [ "\$EXE_COUNT" -eq 0 ]; then
|
|
673
|
+
echo "ERROR 1: binary was not found"
|
|
674
|
+
exit 1
|
|
675
|
+
elif [ "\$EXE_COUNT" -gt 1 ]; then
|
|
676
|
+
echo "ERROR 2: found more executables: \$EXE_FILE"
|
|
677
|
+
exit 2
|
|
678
|
+
fi
|
|
679
|
+
`;
|
|
680
|
+
|
|
681
|
+
const shellScript = `#!/bin/bash
|
|
682
|
+
cd ${path.dirname(packageGM.file).replaceAll("\\", "/")}
|
|
683
|
+
|
|
684
|
+
${shellBuildScript}
|
|
685
|
+
|
|
686
|
+
${shellTestScript}
|
|
687
|
+
|
|
688
|
+
${shellCommandScript}
|
|
689
|
+
|
|
690
|
+
${shellMonitorRAMScript}
|
|
691
|
+
|
|
692
|
+
eval "\$COMMAND" | cat
|
|
693
|
+
`
|
|
694
|
+
|
|
695
|
+
runShellScript(shellScript)
|
|
696
|
+
})
|
|
697
|
+
|
|
698
|
+
configSet
|
|
699
|
+
.command('dependency <name> <revision>')
|
|
700
|
+
.description('Manage dependencies in package-gm.json')
|
|
701
|
+
.option('--remote <remote>')
|
|
702
|
+
.action((name, revision, options) => {
|
|
703
|
+
const resolve = () => {
|
|
704
|
+
const current = packageGM.data.dependencies[name] ?? {};
|
|
705
|
+
|
|
706
|
+
packageGM.data.dependencies[name] = {
|
|
707
|
+
...current,
|
|
708
|
+
...(options.remote !== undefined && { remote: options.remote }),
|
|
709
|
+
...(revision !== undefined && { revision }),
|
|
710
|
+
};
|
|
711
|
+
|
|
712
|
+
console.log("🔨 Set dependency", name, "as", packageGM.data.dependencies[name])
|
|
713
|
+
};
|
|
714
|
+
|
|
715
|
+
const packageGM = getPackageGM()
|
|
716
|
+
|
|
717
|
+
backupPackageGM(packageGM)
|
|
718
|
+
resolve()
|
|
719
|
+
savePackageGM(packageGM)
|
|
720
|
+
});
|
|
721
|
+
|
|
722
|
+
configSet
|
|
723
|
+
.command('script <name> [command]')
|
|
724
|
+
.description('Manage scripts in package-gm.json')
|
|
725
|
+
.action((name, command = '') => {
|
|
726
|
+
const resolve = () => {
|
|
727
|
+
packageGM.data.scripts[name] = command !== undefined ? command : ''
|
|
728
|
+
console.log("🔨 Set script", name, "as", packageGM.data.scripts[name])
|
|
729
|
+
}
|
|
730
|
+
|
|
731
|
+
const packageGM = getPackageGM()
|
|
732
|
+
|
|
733
|
+
backupPackageGM(packageGM)
|
|
734
|
+
resolve()
|
|
735
|
+
savePackageGM(packageGM)
|
|
736
|
+
});
|
|
737
|
+
|
|
738
|
+
configSet
|
|
739
|
+
.command('runtime <name> [supported]')
|
|
740
|
+
.description('Manage runtimes in package-gm.json')
|
|
741
|
+
.action((name, supported = 'true') => {
|
|
742
|
+
const resolve = () => {
|
|
743
|
+
packageGM.data.runtimes[name] = supported === "false" ? supported : "true"
|
|
744
|
+
console.log("🔨 Set runtime", name, "as", supported === "false" ? "false" : "true")
|
|
745
|
+
}
|
|
746
|
+
|
|
747
|
+
const packageGM = getPackageGM()
|
|
748
|
+
|
|
749
|
+
backupPackageGM(packageGM)
|
|
750
|
+
resolve()
|
|
751
|
+
savePackageGM(packageGM)
|
|
752
|
+
});
|
|
753
|
+
|
|
754
|
+
configUnset
|
|
755
|
+
.command('dependency <name>')
|
|
756
|
+
.description('Remove dependencies from package-gm.json')
|
|
757
|
+
.action((name) => {
|
|
758
|
+
const resolve = () => {
|
|
759
|
+
if (name in packageGM.data.dependencies) {
|
|
760
|
+
console.log("🗑️ Unset dependency", name)
|
|
761
|
+
delete packageGM.data.dependencies[name]
|
|
762
|
+
}
|
|
763
|
+
}
|
|
764
|
+
|
|
765
|
+
const packageGM = getPackageGM()
|
|
766
|
+
|
|
767
|
+
backupPackageGM(packageGM)
|
|
768
|
+
resolve()
|
|
769
|
+
savePackageGM(packageGM)
|
|
770
|
+
});
|
|
771
|
+
|
|
772
|
+
configUnset
|
|
773
|
+
.command('script <name>')
|
|
774
|
+
.description('Remove scripts from package-gm.json')
|
|
775
|
+
.action((name) => {
|
|
776
|
+
const resolve = () => {
|
|
777
|
+
if (name in packageGM.data.scripts) {
|
|
778
|
+
console.log("🗑️ Unset script", name)
|
|
779
|
+
delete packageGM.data.scripts[name]
|
|
780
|
+
}
|
|
781
|
+
}
|
|
782
|
+
|
|
783
|
+
const packageGM = getPackageGM()
|
|
784
|
+
|
|
785
|
+
backupPackageGM(packageGM)
|
|
786
|
+
resolve()
|
|
787
|
+
savePackageGM(packageGM)
|
|
788
|
+
});
|
|
789
|
+
|
|
790
|
+
configUnset
|
|
791
|
+
.command('runtime <name>')
|
|
792
|
+
.description('Remove runtimes from package-gm.json')
|
|
793
|
+
.action((name) => {
|
|
794
|
+
const resolve = () => {
|
|
795
|
+
if (name in packageGM.data.scripts) {
|
|
796
|
+
console.log("🗑️ Unset runtime", name)
|
|
797
|
+
delete packageGM.data.runtimes[name]
|
|
798
|
+
}
|
|
799
|
+
}
|
|
800
|
+
|
|
801
|
+
const packageGM = getPackageGM()
|
|
802
|
+
|
|
803
|
+
backupPackageGM(packageGM)
|
|
804
|
+
resolve()
|
|
805
|
+
savePackageGM(packageGM)
|
|
806
|
+
});
|
|
807
|
+
|
|
808
|
+
resource
|
|
809
|
+
.command("create")
|
|
810
|
+
.description("Create a resource")
|
|
811
|
+
.requiredOption("-t, --type <type>", "Resource type")
|
|
812
|
+
.requiredOption("-n, --name <name>", "Resource name")
|
|
813
|
+
.option("-f, --folder <folder>", "Resource folder")
|
|
814
|
+
.action((options) => {
|
|
815
|
+
const packageGM = getPackageGM()
|
|
816
|
+
const yypPath = getYYPPathFromPackageGM(packageGM)
|
|
817
|
+
const folderOption = options.folder !== undefined ? `folder=${options.folder}` : ``
|
|
818
|
+
const shellScript = `yy-gm-cli resourcetool eval "resource create type=${options.type} name=${options.name} ${folderOption}" ${yypPath}`
|
|
819
|
+
runShellScript(shellScript)
|
|
820
|
+
});
|
|
821
|
+
|
|
822
|
+
resource
|
|
823
|
+
.command("update")
|
|
824
|
+
.description("Update a resource property")
|
|
825
|
+
.requiredOption("-e, --expr <expr>", "Resource expression")
|
|
826
|
+
.requiredOption("-v, --value <value>", "New value")
|
|
827
|
+
.action((options) => {
|
|
828
|
+
const packageGM = getPackageGM()
|
|
829
|
+
const yypPath = getYYPPathFromPackageGM(packageGM)
|
|
830
|
+
const shellScript = `yy-gm-cli resourcetool eval "resource set expr=${options.expr} value=${options.value}" ${yypPath}`
|
|
831
|
+
runShellScript(shellScript)
|
|
832
|
+
});
|
|
833
|
+
|
|
834
|
+
resource
|
|
835
|
+
.command("get")
|
|
836
|
+
.description(" a resource")
|
|
837
|
+
.requiredOption("-e, --expr <expr>", "Resource expression")
|
|
838
|
+
.action((options) => {
|
|
839
|
+
const packageGM = getPackageGM()
|
|
840
|
+
const yypPath = getYYPPathFromPackageGM(packageGM)
|
|
841
|
+
const shellScript = `yy-gm-cli resourcetool eval "resource info expr=${options.expr}" ${yypPath}`
|
|
842
|
+
runShellScript(shellScript)
|
|
843
|
+
});
|
|
844
|
+
|
|
845
|
+
resource
|
|
846
|
+
.command("delete")
|
|
847
|
+
.description("Delete a resource")
|
|
848
|
+
.requiredOption("-n, --name <name>", "Resource name")
|
|
849
|
+
.option("--type <type>", "Resource type")
|
|
850
|
+
.action((options) => {
|
|
851
|
+
const packageGM = getPackageGM()
|
|
852
|
+
const yypPath = getYYPPathFromPackageGM(packageGM)
|
|
853
|
+
const typeOptions = options.type !== undefined ? `type=${options.type}` : ``
|
|
854
|
+
const shellScript = `yy-gm-cli resourcetool eval "resource delete name=${options.name} ${typeOptions}" ${yypPath}`
|
|
855
|
+
runShellScript(shellScript)
|
|
856
|
+
});
|
|
857
|
+
|
|
858
|
+
resource
|
|
859
|
+
.command("list")
|
|
860
|
+
.description("List resources")
|
|
861
|
+
.option("--type <type>", "Resource type")
|
|
862
|
+
.action((options) => {
|
|
863
|
+
const packageGM = getPackageGM()
|
|
864
|
+
const yypPath = getYYPPathFromPackageGM(packageGM)
|
|
865
|
+
const typeOptions = options.type !== undefined ? `type=${options.type}` : ``
|
|
866
|
+
const shellScript = `yy-gm-cli resourcetool eval "resource list ${typeOptions}" ${yypPath}`
|
|
867
|
+
runShellScript(shellScript)
|
|
868
|
+
});
|
|
869
|
+
|
|
870
|
+
|
|
871
|
+
program.parse(process.argv);
|