@naesofteak/naeso 0.0.0-stage → 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.
@@ -0,0 +1,691 @@
1
+ const fs = require("fs");
2
+ const path = require("path");
3
+
4
+ const {
5
+ extractArchive,
6
+ findMongoRoot,
7
+ findMongoshRoot,
8
+ findDatabaseToolsRoot,
9
+ findBinary
10
+ } = require("./extractor");
11
+
12
+ const {
13
+ getPackage
14
+ } = require("./registry");
15
+
16
+ const {
17
+ getLatestVersion
18
+ } = require("./compatibility");
19
+
20
+ const {
21
+ configurePath
22
+ } = require("./environment");
23
+
24
+ const NAESO_HOME =
25
+ path.join(
26
+ process.env.HOME,
27
+ ".naeso"
28
+ );
29
+
30
+
31
+ function copyBinary(
32
+ source,
33
+ destination
34
+ ) {
35
+ fs.copyFileSync(
36
+ source,
37
+ destination
38
+ );
39
+
40
+ fs.chmodSync(
41
+ destination,
42
+ 0o755
43
+ );
44
+ }
45
+
46
+
47
+ function ensureEmptyDirectory(
48
+ directory
49
+ ) {
50
+ fs.rmSync(
51
+ directory,
52
+ {
53
+ recursive: true,
54
+ force: true
55
+ }
56
+ );
57
+
58
+ fs.mkdirSync(
59
+ directory,
60
+ {
61
+ recursive: true
62
+ }
63
+ );
64
+ }
65
+
66
+
67
+ async function installPackage(
68
+ packageName,
69
+ version = null,
70
+ downloadedArtifacts
71
+ ) {
72
+ /*
73
+ * ---------------------------------------
74
+ * Load package
75
+ * ---------------------------------------
76
+ */
77
+
78
+ const pkg =
79
+ getPackage(packageName);
80
+
81
+ if (!pkg) {
82
+ throw new Error(
83
+ `Package '${packageName}' not found.`
84
+ );
85
+ }
86
+
87
+
88
+ /*
89
+ * ---------------------------------------
90
+ * Select version
91
+ * ---------------------------------------
92
+ */
93
+
94
+ const selectedVersion =
95
+ version ||
96
+ getLatestVersion(pkg);
97
+
98
+ if (!selectedVersion) {
99
+ throw new Error(
100
+ `No version available for ${packageName}.`
101
+ );
102
+ }
103
+
104
+
105
+ /*
106
+ * ---------------------------------------
107
+ * Validate downloaded artifacts
108
+ * ---------------------------------------
109
+ */
110
+
111
+ if (
112
+ !downloadedArtifacts ||
113
+ Object.keys(downloadedArtifacts).length === 0
114
+ ) {
115
+ throw new Error(
116
+ "No downloaded artifacts were provided."
117
+ );
118
+ }
119
+
120
+
121
+ /*
122
+ * ---------------------------------------
123
+ * Package directories
124
+ * ---------------------------------------
125
+ */
126
+
127
+ const packageRoot =
128
+ path.join(
129
+ NAESO_HOME,
130
+ "packages",
131
+ packageName,
132
+ selectedVersion
133
+ );
134
+
135
+ const extractRoot =
136
+ path.join(
137
+ packageRoot,
138
+ "extract"
139
+ );
140
+
141
+ const installDirectory =
142
+ path.join(
143
+ packageRoot,
144
+ "server"
145
+ );
146
+
147
+ const dataDirectory =
148
+ path.join(
149
+ NAESO_HOME,
150
+ "data",
151
+ packageName
152
+ );
153
+
154
+ const logDirectory =
155
+ path.join(
156
+ NAESO_HOME,
157
+ "logs",
158
+ packageName
159
+ );
160
+
161
+ const configDirectory =
162
+ path.join(
163
+ packageRoot,
164
+ "config"
165
+ );
166
+
167
+
168
+ /*
169
+ * ---------------------------------------
170
+ * Installer header
171
+ * ---------------------------------------
172
+ */
173
+
174
+ console.log("");
175
+ console.log(
176
+ "Naeso Package Installer"
177
+ );
178
+ console.log(
179
+ "-----------------------"
180
+ );
181
+ console.log(
182
+ `Package: ${packageName}`
183
+ );
184
+ console.log(
185
+ `Version: ${selectedVersion}`
186
+ );
187
+ console.log("");
188
+
189
+
190
+ /*
191
+ * ---------------------------------------
192
+ * Prevent duplicate installation
193
+ * ---------------------------------------
194
+ */
195
+
196
+ if (
197
+ fs.existsSync(
198
+ installDirectory
199
+ )
200
+ ) {
201
+ throw new Error(
202
+ `${packageName} ${selectedVersion} is already installed.`
203
+ );
204
+ }
205
+
206
+
207
+ /*
208
+ * ---------------------------------------
209
+ * Create directories
210
+ * ---------------------------------------
211
+ */
212
+
213
+ console.log(
214
+ "Creating directories..."
215
+ );
216
+
217
+ fs.mkdirSync(
218
+ packageRoot,
219
+ {
220
+ recursive: true
221
+ }
222
+ );
223
+
224
+ ensureEmptyDirectory(
225
+ extractRoot
226
+ );
227
+
228
+ fs.mkdirSync(
229
+ installDirectory,
230
+ {
231
+ recursive: true
232
+ }
233
+ );
234
+
235
+ fs.mkdirSync(
236
+ dataDirectory,
237
+ {
238
+ recursive: true
239
+ }
240
+ );
241
+
242
+ fs.mkdirSync(
243
+ logDirectory,
244
+ {
245
+ recursive: true
246
+ }
247
+ );
248
+
249
+ fs.mkdirSync(
250
+ configDirectory,
251
+ {
252
+ recursive: true
253
+ }
254
+ );
255
+
256
+
257
+ /*
258
+ * ---------------------------------------
259
+ * Extract all artifacts
260
+ * ---------------------------------------
261
+ */
262
+
263
+ const extracted = {};
264
+
265
+ for (
266
+ const [artifactName, artifact]
267
+ of Object.entries(
268
+ downloadedArtifacts
269
+ )
270
+ ) {
271
+ const destination =
272
+ path.join(
273
+ extractRoot,
274
+ artifactName
275
+ );
276
+
277
+ console.log(
278
+ `Extracting ${artifactName}...`
279
+ );
280
+
281
+ await extractArchive(
282
+ artifact.archive,
283
+ artifact.type,
284
+ destination
285
+ );
286
+
287
+ extracted[artifactName] =
288
+ destination;
289
+ }
290
+
291
+
292
+ /*
293
+ * ---------------------------------------
294
+ * Locate artifact roots
295
+ * ---------------------------------------
296
+ */
297
+
298
+ const serverRoot =
299
+ findMongoRoot(
300
+ extracted.server
301
+ );
302
+
303
+ const mongoshRoot =
304
+ findMongoshRoot(
305
+ extracted.mongosh
306
+ );
307
+
308
+ const databaseToolsRoot =
309
+ findDatabaseToolsRoot(
310
+ extracted.databaseTools
311
+ );
312
+
313
+ console.log("");
314
+
315
+ console.log(
316
+ `MongoDB server: ${serverRoot}`
317
+ );
318
+
319
+ console.log(
320
+ `MongoDB shell: ${mongoshRoot}`
321
+ );
322
+
323
+ console.log(
324
+ `Database tools: ${databaseToolsRoot}`
325
+ );
326
+
327
+
328
+ /*
329
+ * ---------------------------------------
330
+ * Create final bin directory
331
+ * ---------------------------------------
332
+ */
333
+
334
+ const binDirectory =
335
+ path.join(
336
+ installDirectory,
337
+ "bin"
338
+ );
339
+
340
+ fs.mkdirSync(
341
+ binDirectory,
342
+ {
343
+ recursive: true
344
+ }
345
+ );
346
+
347
+
348
+ /*
349
+ * ---------------------------------------
350
+ * Install MongoDB server
351
+ * ---------------------------------------
352
+ */
353
+
354
+ console.log("");
355
+ console.log(
356
+ "Installing MongoDB server..."
357
+ );
358
+
359
+ copyBinary(
360
+ findBinary(
361
+ serverRoot,
362
+ "mongod"
363
+ ),
364
+ path.join(
365
+ binDirectory,
366
+ "mongod"
367
+ )
368
+ );
369
+
370
+ copyBinary(
371
+ findBinary(
372
+ serverRoot,
373
+ "mongos"
374
+ ),
375
+ path.join(
376
+ binDirectory,
377
+ "mongos"
378
+ )
379
+ );
380
+
381
+
382
+ /*
383
+ * ---------------------------------------
384
+ * Install MongoDB Shell
385
+ * ---------------------------------------
386
+ */
387
+
388
+ console.log(
389
+ "Installing MongoDB Shell..."
390
+ );
391
+
392
+ copyBinary(
393
+ findBinary(
394
+ mongoshRoot,
395
+ "mongosh"
396
+ ),
397
+ path.join(
398
+ binDirectory,
399
+ "mongosh"
400
+ )
401
+ );
402
+
403
+
404
+ /*
405
+ * ---------------------------------------
406
+ * Install MongoDB Database Tools
407
+ * ---------------------------------------
408
+ */
409
+
410
+ console.log(
411
+ "Installing MongoDB Database Tools..."
412
+ );
413
+
414
+ const databaseTools = [
415
+ "mongodump",
416
+ "mongorestore",
417
+ "mongoexport",
418
+ "mongoimport",
419
+ "bsondump",
420
+ "mongostat",
421
+ "mongotop"
422
+ ];
423
+
424
+ for (
425
+ const binary of databaseTools
426
+ ) {
427
+ copyBinary(
428
+ findBinary(
429
+ databaseToolsRoot,
430
+ binary
431
+ ),
432
+ path.join(
433
+ binDirectory,
434
+ binary
435
+ )
436
+ );
437
+ }
438
+
439
+
440
+ /*
441
+ * ---------------------------------------
442
+ * Verify all binaries
443
+ * ---------------------------------------
444
+ */
445
+
446
+ const requiredBinaries = [
447
+ "mongod",
448
+ "mongos",
449
+ "mongosh",
450
+ "mongodump",
451
+ "mongorestore",
452
+ "mongoexport",
453
+ "mongoimport",
454
+ "bsondump",
455
+ "mongostat",
456
+ "mongotop"
457
+ ];
458
+
459
+ console.log("");
460
+ console.log(
461
+ "Verifying MongoDB binaries..."
462
+ );
463
+
464
+ for (
465
+ const binary of requiredBinaries
466
+ ) {
467
+ const binaryPath =
468
+ path.join(
469
+ binDirectory,
470
+ binary
471
+ );
472
+
473
+ if (
474
+ !fs.existsSync(
475
+ binaryPath
476
+ )
477
+ ) {
478
+ throw new Error(
479
+ `Required binary not found: ${binary}`
480
+ );
481
+ }
482
+
483
+ console.log(
484
+ ` ✓ ${binary}`
485
+ );
486
+ }
487
+
488
+
489
+ /*
490
+ * ---------------------------------------
491
+ * Create current symlink
492
+ * ---------------------------------------
493
+ */
494
+
495
+ const packagesDirectory =
496
+ path.join(
497
+ NAESO_HOME,
498
+ "packages",
499
+ packageName
500
+ );
501
+
502
+ const currentLink =
503
+ path.join(
504
+ packagesDirectory,
505
+ "current"
506
+ );
507
+
508
+ const currentStat =
509
+ fs.lstatSync(
510
+ currentLink,
511
+ {
512
+ throwIfNoEntry: false
513
+ }
514
+ );
515
+
516
+ if (
517
+ currentStat
518
+ ) {
519
+ fs.rmSync(
520
+ currentLink,
521
+ {
522
+ recursive: true,
523
+ force: true
524
+ }
525
+ );
526
+ }
527
+
528
+ fs.symlinkSync(
529
+ installDirectory,
530
+ currentLink,
531
+ "dir"
532
+ );
533
+
534
+
535
+ /*
536
+ * ---------------------------------------
537
+ * Configure environment PATH
538
+ * ---------------------------------------
539
+ */
540
+
541
+ const environmentPaths =
542
+ pkg.environment?.path || [];
543
+
544
+ if (
545
+ environmentPaths.length > 0
546
+ ) {
547
+ console.log("");
548
+ console.log(
549
+ "Configuring environment..."
550
+ );
551
+
552
+ const environmentResult =
553
+ configurePath(
554
+ environmentPaths
555
+ );
556
+
557
+ if (
558
+ environmentResult.changed
559
+ ) {
560
+ console.log(
561
+ `PATH updated: ${environmentResult.shellConfig}`
562
+ );
563
+
564
+ console.log(
565
+ "Restart your terminal or reload the shell configuration."
566
+ );
567
+ } else {
568
+ console.log(
569
+ "PATH already configured."
570
+ );
571
+ }
572
+ }
573
+
574
+
575
+ /*
576
+ * ---------------------------------------
577
+ * Installed metadata
578
+ * ---------------------------------------
579
+ */
580
+
581
+ const metadata = {
582
+ name: packageName,
583
+
584
+ version:
585
+ selectedVersion,
586
+
587
+ installedAt:
588
+ new Date().toISOString(),
589
+
590
+ installDirectory,
591
+
592
+ currentDirectory:
593
+ currentLink,
594
+
595
+ binDirectory,
596
+
597
+ dataDirectory,
598
+
599
+ logDirectory,
600
+
601
+ configDirectory,
602
+
603
+ environment: {
604
+ path:
605
+ environmentPaths
606
+ },
607
+
608
+ binaries:
609
+ Object.fromEntries(
610
+ requiredBinaries.map(
611
+ (binary) => [
612
+ binary,
613
+ path.join(
614
+ binDirectory,
615
+ binary
616
+ )
617
+ ]
618
+ )
619
+ )
620
+ };
621
+
622
+
623
+ /*
624
+ * ---------------------------------------
625
+ * Save installed metadata
626
+ * ---------------------------------------
627
+ */
628
+
629
+ const metadataDirectory =
630
+ path.join(
631
+ NAESO_HOME,
632
+ "installed"
633
+ );
634
+
635
+ fs.mkdirSync(
636
+ metadataDirectory,
637
+ {
638
+ recursive: true
639
+ }
640
+ );
641
+
642
+ fs.writeFileSync(
643
+ path.join(
644
+ metadataDirectory,
645
+ `${packageName}.json`
646
+ ),
647
+ JSON.stringify(
648
+ metadata,
649
+ null,
650
+ 2
651
+ )
652
+ );
653
+
654
+
655
+ /*
656
+ * ---------------------------------------
657
+ * Finished
658
+ * ---------------------------------------
659
+ */
660
+
661
+ console.log("");
662
+ console.log(
663
+ `${pkg.displayName || packageName} installation completed.`
664
+ );
665
+ console.log("");
666
+
667
+ console.log(
668
+ `Installed: ${installDirectory}`
669
+ );
670
+
671
+ console.log(
672
+ `Current: ${currentLink}`
673
+ );
674
+
675
+ console.log(
676
+ `Data: ${dataDirectory}`
677
+ );
678
+
679
+ console.log(
680
+ `Logs: ${logDirectory}`
681
+ );
682
+
683
+ console.log("");
684
+
685
+ return metadata;
686
+ }
687
+
688
+
689
+ module.exports = {
690
+ installPackage
691
+ };