@zthun/romulator-api 1.6.0 → 1.7.1

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.
@@ -1,2 +1,7 @@
1
+ import { IZRomulatorFilesService } from './files-service.mjs';
1
2
  export declare class ZRomulatorFilesModule {
3
+ private readonly _files;
4
+ constructor(_files: IZRomulatorFilesService);
5
+ onModuleInit(): Promise<void>;
6
+ onModuleDestroy(): Promise<void>;
2
7
  }
@@ -1,20 +1,106 @@
1
- import { IZFileSystemNode } from '@zthun/crumbtrail-fs';
1
+ import { IZFileRepository, IZFileSystemNode, IZFileSystemService } from '@zthun/crumbtrail-fs';
2
2
  import { IZRomulatorConfigsService } from '../config/configs-service.mjs';
3
3
  export declare const ZRomulatorFilesToken: unique symbol;
4
+ /**
5
+ * Represents the service that you can use to
6
+ * scan the games folder for media, info, games, and systems.
7
+ */
4
8
  export interface IZRomulatorFilesService {
9
+ /**
10
+ * Retrieves all media found in the games .media folder.
11
+ *
12
+ * @returns
13
+ * A list of all media found in the game media folder.
14
+ */
5
15
  media(): Promise<IZFileSystemNode[]>;
16
+ /**
17
+ * Retrieves a single media node found in the .media folder.
18
+ *
19
+ * @param path -
20
+ * The path of the media node to retrieve. This will
21
+ * be relative to the configured games directory. If this
22
+ * starts with a root OS folder, then the path by itself
23
+ * is used.
24
+ *
25
+ * @returns
26
+ * The node with the given path or null if no such
27
+ * file exists.
28
+ */
29
+ media(path: string): Promise<IZFileSystemNode | null>;
30
+ /**
31
+ * Retrieves all systems found in the games folder.
32
+ *
33
+ * A system is a root folder that is a slug of a supported
34
+ * system.
35
+ *
36
+ * @returns
37
+ * A list of all systems found in the games folder.
38
+ */
39
+ systems(): Promise<IZFileSystemNode[]>;
40
+ /**
41
+ * Retrieves a single system found in the games folder.
42
+ *
43
+ * @param path -
44
+ * The id of the system, which is also the name of the folder.
45
+ *
46
+ * @returns
47
+ * The node that represents the system slug. Returns null if
48
+ * the folder does not exist or is not supported. Note
49
+ * that the path is relative to the configured games folder. If you
50
+ * want to supply a fully qualified absolute path, then this string
51
+ * should start with the root of an OS drive (not recommended).
52
+ */
53
+ systems(path: string): Promise<IZFileSystemNode | null>;
54
+ /**
55
+ * Retrieves all info found in the games .info folder.
56
+ *
57
+ * Info is the metadata scraped from a scraper service.
58
+ * The data format is stored in json.
59
+ *
60
+ * @returns
61
+ * A list of all info found in the games folder.
62
+ */
63
+ info(): Promise<IZFileSystemNode[]>;
64
+ /**
65
+ * Retrieves specific information found in the games .info folder.
66
+ *
67
+ * @param path -
68
+ * The path of the info node to retrieve.
69
+ *
70
+ * @returns
71
+ * The node with the given path or null if no such file exists.
72
+ */
73
+ info(path: string): Promise<IZFileSystemNode | null>;
74
+ /**
75
+ * Initializes the file repository.
76
+ */
77
+ init(): Promise<void>;
78
+ /**
79
+ * Cleans up internal resources.
80
+ */
81
+ dispose(): Promise<void>;
6
82
  }
7
83
  export declare class ZRomulatorFilesService implements IZRomulatorFilesService {
8
84
  private readonly _configs;
85
+ private readonly _fileSystem;
9
86
  private static readonly MediaFolderName;
10
87
  private static readonly InfoFolderName;
11
88
  private _repository;
12
- private _folderWriter;
89
+ private _folderStream;
13
90
  private _globs;
14
- constructor(_configs: IZRomulatorConfigsService);
91
+ private _systems;
92
+ constructor(_configs: IZRomulatorConfigsService, _fileSystem: IZFileSystemService);
15
93
  private gamesFolder;
16
94
  private mediaFolder;
17
95
  private infoFolder;
18
- private repository;
96
+ private contents;
97
+ init(): Promise<void>;
98
+ dispose(): Promise<void>;
99
+ seed(): Promise<IZFileRepository>;
19
100
  media(): Promise<IZFileSystemNode[]>;
101
+ media(path: string): Promise<IZFileSystemNode | null>;
102
+ systems(): Promise<IZFileSystemNode[]>;
103
+ systems(path: string): Promise<IZFileSystemNode | null>;
104
+ info(): Promise<IZFileSystemNode[]>;
105
+ info(path: string): Promise<IZFileSystemNode | null>;
20
106
  }
package/dist/main.cjs CHANGED
@@ -29,7 +29,7 @@ function _ts_decorate$g(decorators, target, key, desc) {
29
29
  else for(var i = decorators.length - 1; i >= 0; i--)if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
30
30
  return c > 3 && r && Object.defineProperty(target, key, r), r;
31
31
  }
32
- function _ts_metadata$a(k, v) {
32
+ function _ts_metadata$b(k, v) {
33
33
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
34
34
  }
35
35
  class ZRomulatorConfigUpdateDto {
@@ -47,7 +47,7 @@ _ts_decorate$g([
47
47
  message: "The contents of the config must be an object "
48
48
  }),
49
49
  classValidator.IsNotEmptyObject(),
50
- _ts_metadata$a("design:type", typeof T === "undefined" ? Object : T)
50
+ _ts_metadata$b("design:type", typeof T === "undefined" ? Object : T)
51
51
  ], ZRomulatorConfigUpdateDto.prototype, "contents", void 0);
52
52
 
53
53
  class ZDir {
@@ -80,10 +80,10 @@ function _ts_decorate$f(decorators, target, key, desc) {
80
80
  else for(var i = decorators.length - 1; i >= 0; i--)if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
81
81
  return c > 3 && r && Object.defineProperty(target, key, r), r;
82
82
  }
83
- function _ts_metadata$9(k, v) {
83
+ function _ts_metadata$a(k, v) {
84
84
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
85
85
  }
86
- function _ts_param$8(paramIndex, decorator) {
86
+ function _ts_param$9(paramIndex, decorator) {
87
87
  return function(target, key) {
88
88
  decorator(target, key, paramIndex);
89
89
  };
@@ -167,9 +167,9 @@ class ZRomulatorConfigsService {
167
167
  }
168
168
  ZRomulatorConfigsService = _ts_decorate$f([
169
169
  common.Injectable(),
170
- _ts_param$8(0, common.Inject(lumberjackyNest.ZLoggerToken)),
171
- _ts_metadata$9("design:type", Function),
172
- _ts_metadata$9("design:paramtypes", [
170
+ _ts_param$9(0, common.Inject(lumberjackyNest.ZLoggerToken)),
171
+ _ts_metadata$a("design:type", Function),
172
+ _ts_metadata$a("design:paramtypes", [
173
173
  typeof IZLogger === "undefined" ? Object : IZLogger
174
174
  ])
175
175
  ], ZRomulatorConfigsService);
@@ -180,10 +180,10 @@ function _ts_decorate$e(decorators, target, key, desc) {
180
180
  else for(var i = decorators.length - 1; i >= 0; i--)if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
181
181
  return c > 3 && r && Object.defineProperty(target, key, r), r;
182
182
  }
183
- function _ts_metadata$8(k, v) {
183
+ function _ts_metadata$9(k, v) {
184
184
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
185
185
  }
186
- function _ts_param$7(paramIndex, decorator) {
186
+ function _ts_param$8(paramIndex, decorator) {
187
187
  return function(target, key) {
188
188
  decorator(target, key, paramIndex);
189
189
  };
@@ -206,12 +206,12 @@ class ZRomulatorConfigsController {
206
206
  }
207
207
  _ts_decorate$e([
208
208
  common.Get(),
209
- _ts_param$7(0, common.Query()),
210
- _ts_metadata$8("design:type", Function),
211
- _ts_metadata$8("design:paramtypes", [
209
+ _ts_param$8(0, common.Query()),
210
+ _ts_metadata$9("design:type", Function),
211
+ _ts_metadata$9("design:paramtypes", [
212
212
  typeof IZDataRequestQuery === "undefined" ? Object : IZDataRequestQuery
213
213
  ]),
214
- _ts_metadata$8("design:returntype", Promise)
214
+ _ts_metadata$9("design:returntype", Promise)
215
215
  ], ZRomulatorConfigsController.prototype, "list", null);
216
216
  _ts_decorate$e([
217
217
  swagger.ApiParam({
@@ -230,14 +230,14 @@ _ts_decorate$e([
230
230
  skipNullProperties: false,
231
231
  skipUndefinedProperties: false
232
232
  })),
233
- _ts_param$7(0, common.Param("identification")),
234
- _ts_param$7(1, common.Body()),
235
- _ts_metadata$8("design:type", Function),
236
- _ts_metadata$8("design:paramtypes", [
233
+ _ts_param$8(0, common.Param("identification")),
234
+ _ts_param$8(1, common.Body()),
235
+ _ts_metadata$9("design:type", Function),
236
+ _ts_metadata$9("design:paramtypes", [
237
237
  typeof ZRomulatorConfigId === "undefined" ? Object : ZRomulatorConfigId,
238
238
  typeof ZRomulatorConfigUpdateDto === "undefined" ? Object : ZRomulatorConfigUpdateDto
239
239
  ]),
240
- _ts_metadata$8("design:returntype", Promise)
240
+ _ts_metadata$9("design:returntype", Promise)
241
241
  ], ZRomulatorConfigsController.prototype, "update", null);
242
242
  _ts_decorate$e([
243
243
  swagger.ApiParam({
@@ -246,18 +246,18 @@ _ts_decorate$e([
246
246
  description: "The id of the config"
247
247
  }),
248
248
  common.Get(":identification"),
249
- _ts_param$7(0, common.Param("identification")),
250
- _ts_metadata$8("design:type", Function),
251
- _ts_metadata$8("design:paramtypes", [
249
+ _ts_param$8(0, common.Param("identification")),
250
+ _ts_metadata$9("design:type", Function),
251
+ _ts_metadata$9("design:paramtypes", [
252
252
  typeof ZRomulatorConfigId === "undefined" ? Object : ZRomulatorConfigId
253
253
  ]),
254
- _ts_metadata$8("design:returntype", Promise)
254
+ _ts_metadata$9("design:returntype", Promise)
255
255
  ], ZRomulatorConfigsController.prototype, "get", null);
256
256
  ZRomulatorConfigsController = _ts_decorate$e([
257
257
  common.Controller("configs"),
258
- _ts_param$7(0, common.Inject(ZRomulatorConfigsToken)),
259
- _ts_metadata$8("design:type", Function),
260
- _ts_metadata$8("design:paramtypes", [
258
+ _ts_param$8(0, common.Inject(ZRomulatorConfigsToken)),
259
+ _ts_metadata$9("design:type", Function),
260
+ _ts_metadata$9("design:paramtypes", [
261
261
  typeof IZRomulatorConfigsService === "undefined" ? Object : IZRomulatorConfigsService
262
262
  ])
263
263
  ], ZRomulatorConfigsController);
@@ -297,7 +297,7 @@ function _ts_decorate$c(decorators, target, key, desc) {
297
297
  else for(var i = decorators.length - 1; i >= 0; i--)if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
298
298
  return c > 3 && r && Object.defineProperty(target, key, r), r;
299
299
  }
300
- function _ts_metadata$7(k, v) {
300
+ function _ts_metadata$8(k, v) {
301
301
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
302
302
  }
303
303
  const KnownSystem = "@zthunworks/romulator/known-system";
@@ -395,45 +395,45 @@ const KnownSystem = "@zthunworks/romulator/known-system";
395
395
  }
396
396
  _ts_decorate$c([
397
397
  helpfulReflection.ZTag(KnownSystem),
398
- _ts_metadata$7("design:type", Function),
399
- _ts_metadata$7("design:paramtypes", []),
400
- _ts_metadata$7("design:returntype", void 0)
398
+ _ts_metadata$8("design:type", Function),
399
+ _ts_metadata$8("design:paramtypes", []),
400
+ _ts_metadata$8("design:returntype", void 0)
401
401
  ], ZRomulatorSystemKnown, "nes", null);
402
402
  _ts_decorate$c([
403
403
  helpfulReflection.ZTag(KnownSystem),
404
- _ts_metadata$7("design:type", Function),
405
- _ts_metadata$7("design:paramtypes", []),
406
- _ts_metadata$7("design:returntype", void 0)
404
+ _ts_metadata$8("design:type", Function),
405
+ _ts_metadata$8("design:paramtypes", []),
406
+ _ts_metadata$8("design:returntype", void 0)
407
407
  ], ZRomulatorSystemKnown, "snes", null);
408
408
  _ts_decorate$c([
409
409
  helpfulReflection.ZTag(KnownSystem),
410
- _ts_metadata$7("design:type", Function),
411
- _ts_metadata$7("design:paramtypes", []),
412
- _ts_metadata$7("design:returntype", void 0)
410
+ _ts_metadata$8("design:type", Function),
411
+ _ts_metadata$8("design:paramtypes", []),
412
+ _ts_metadata$8("design:returntype", void 0)
413
413
  ], ZRomulatorSystemKnown, "n64", null);
414
414
  _ts_decorate$c([
415
415
  helpfulReflection.ZTag(KnownSystem),
416
- _ts_metadata$7("design:type", Function),
417
- _ts_metadata$7("design:paramtypes", []),
418
- _ts_metadata$7("design:returntype", void 0)
416
+ _ts_metadata$8("design:type", Function),
417
+ _ts_metadata$8("design:paramtypes", []),
418
+ _ts_metadata$8("design:returntype", void 0)
419
419
  ], ZRomulatorSystemKnown, "gc", null);
420
420
  _ts_decorate$c([
421
421
  helpfulReflection.ZTag(KnownSystem),
422
- _ts_metadata$7("design:type", Function),
423
- _ts_metadata$7("design:paramtypes", []),
424
- _ts_metadata$7("design:returntype", void 0)
422
+ _ts_metadata$8("design:type", Function),
423
+ _ts_metadata$8("design:paramtypes", []),
424
+ _ts_metadata$8("design:returntype", void 0)
425
425
  ], ZRomulatorSystemKnown, "wii", null);
426
426
  _ts_decorate$c([
427
427
  helpfulReflection.ZTag(KnownSystem),
428
- _ts_metadata$7("design:type", Function),
429
- _ts_metadata$7("design:paramtypes", []),
430
- _ts_metadata$7("design:returntype", void 0)
428
+ _ts_metadata$8("design:type", Function),
429
+ _ts_metadata$8("design:paramtypes", []),
430
+ _ts_metadata$8("design:returntype", void 0)
431
431
  ], ZRomulatorSystemKnown, "wiiu", null);
432
432
  _ts_decorate$c([
433
433
  helpfulReflection.ZTag(KnownSystem),
434
- _ts_metadata$7("design:type", Function),
435
- _ts_metadata$7("design:paramtypes", []),
436
- _ts_metadata$7("design:returntype", void 0)
434
+ _ts_metadata$8("design:type", Function),
435
+ _ts_metadata$8("design:paramtypes", []),
436
+ _ts_metadata$8("design:returntype", void 0)
437
437
  ], ZRomulatorSystemKnown, "switch", null);
438
438
 
439
439
  /**
@@ -462,10 +462,10 @@ function _ts_decorate$b(decorators, target, key, desc) {
462
462
  else for(var i = decorators.length - 1; i >= 0; i--)if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
463
463
  return c > 3 && r && Object.defineProperty(target, key, r), r;
464
464
  }
465
- function _ts_metadata$6(k, v) {
465
+ function _ts_metadata$7(k, v) {
466
466
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
467
467
  }
468
- function _ts_param$6(paramIndex, decorator) {
468
+ function _ts_param$7(paramIndex, decorator) {
469
469
  return function(target, key) {
470
470
  decorator(target, key, paramIndex);
471
471
  };
@@ -523,11 +523,11 @@ class ZRomulatorGamesService {
523
523
  }
524
524
  ZRomulatorGamesService = _ts_decorate$b([
525
525
  common.Injectable(),
526
- _ts_param$6(0, common.Inject(crumbtrailNest.ZFileSystemToken)),
527
- _ts_param$6(1, common.Inject(ZRomulatorConfigsToken)),
528
- _ts_param$6(2, common.Inject(lumberjackyNest.ZLoggerToken)),
529
- _ts_metadata$6("design:type", Function),
530
- _ts_metadata$6("design:paramtypes", [
526
+ _ts_param$7(0, common.Inject(crumbtrailNest.ZFileSystemToken)),
527
+ _ts_param$7(1, common.Inject(ZRomulatorConfigsToken)),
528
+ _ts_param$7(2, common.Inject(lumberjackyNest.ZLoggerToken)),
529
+ _ts_metadata$7("design:type", Function),
530
+ _ts_metadata$7("design:paramtypes", [
531
531
  typeof IZFileSystemService === "undefined" ? Object : IZFileSystemService,
532
532
  typeof IZRomulatorConfigsService === "undefined" ? Object : IZRomulatorConfigsService,
533
533
  typeof IZLogger === "undefined" ? Object : IZLogger
@@ -540,10 +540,10 @@ function _ts_decorate$a(decorators, target, key, desc) {
540
540
  else for(var i = decorators.length - 1; i >= 0; i--)if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
541
541
  return c > 3 && r && Object.defineProperty(target, key, r), r;
542
542
  }
543
- function _ts_metadata$5(k, v) {
543
+ function _ts_metadata$6(k, v) {
544
544
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
545
545
  }
546
- function _ts_param$5(paramIndex, decorator) {
546
+ function _ts_param$6(paramIndex, decorator) {
547
547
  return function(target, key) {
548
548
  decorator(target, key, paramIndex);
549
549
  };
@@ -562,27 +562,27 @@ class ZRomulatorGamesController {
562
562
  }
563
563
  _ts_decorate$a([
564
564
  common.Get(),
565
- _ts_param$5(0, common.Query()),
566
- _ts_metadata$5("design:type", Function),
567
- _ts_metadata$5("design:paramtypes", [
565
+ _ts_param$6(0, common.Query()),
566
+ _ts_metadata$6("design:type", Function),
567
+ _ts_metadata$6("design:paramtypes", [
568
568
  typeof IZDataRequestQuery === "undefined" ? Object : IZDataRequestQuery
569
569
  ]),
570
- _ts_metadata$5("design:returntype", typeof Promise === "undefined" ? Object : Promise)
570
+ _ts_metadata$6("design:returntype", typeof Promise === "undefined" ? Object : Promise)
571
571
  ], ZRomulatorGamesController.prototype, "list", null);
572
572
  _ts_decorate$a([
573
573
  common.Get(":identification"),
574
- _ts_param$5(0, common.Param("identification")),
575
- _ts_metadata$5("design:type", Function),
576
- _ts_metadata$5("design:paramtypes", [
574
+ _ts_param$6(0, common.Param("identification")),
575
+ _ts_metadata$6("design:type", Function),
576
+ _ts_metadata$6("design:paramtypes", [
577
577
  String
578
578
  ]),
579
- _ts_metadata$5("design:returntype", void 0)
579
+ _ts_metadata$6("design:returntype", void 0)
580
580
  ], ZRomulatorGamesController.prototype, "get", null);
581
581
  ZRomulatorGamesController = _ts_decorate$a([
582
582
  common.Controller("games"),
583
- _ts_param$5(0, common.Inject(ZRomulatorGamesToken)),
584
- _ts_metadata$5("design:type", Function),
585
- _ts_metadata$5("design:paramtypes", [
583
+ _ts_param$6(0, common.Inject(ZRomulatorGamesToken)),
584
+ _ts_metadata$6("design:type", Function),
585
+ _ts_metadata$6("design:paramtypes", [
586
586
  typeof IZRomulatorGamesService === "undefined" ? Object : IZRomulatorGamesService
587
587
  ])
588
588
  ], ZRomulatorGamesController);
@@ -620,10 +620,10 @@ function _ts_decorate$8(decorators, target, key, desc) {
620
620
  else for(var i = decorators.length - 1; i >= 0; i--)if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
621
621
  return c > 3 && r && Object.defineProperty(target, key, r), r;
622
622
  }
623
- function _ts_metadata$4(k, v) {
623
+ function _ts_metadata$5(k, v) {
624
624
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
625
625
  }
626
- function _ts_param$4(paramIndex, decorator) {
626
+ function _ts_param$5(paramIndex, decorator) {
627
627
  return function(target, key) {
628
628
  decorator(target, key, paramIndex);
629
629
  };
@@ -631,19 +631,23 @@ function _ts_param$4(paramIndex, decorator) {
631
631
  const ZRomulatorFilesToken = Symbol("files");
632
632
  class ZRomulatorFilesService {
633
633
  _configs;
634
+ _fileSystem;
634
635
  static MediaFolderName = ".media";
635
636
  static InfoFolderName = ".info";
636
637
  _repository = new crumbtrailFs.ZFileRepository();
637
- _folderWriter = new crumbtrailFs.ZStreamFolder();
638
+ _folderStream = new crumbtrailFs.ZStreamFolder();
638
639
  _globs;
639
- constructor(_configs){
640
+ _systems;
641
+ constructor(_configs, _fileSystem){
640
642
  this._configs = _configs;
643
+ this._fileSystem = _fileSystem;
641
644
  const slugs = Object.values(romulatorClient.ZRomulatorSystemId);
642
645
  this._globs = [
643
646
  ".media/**",
644
647
  ".info/**",
645
648
  ...slugs.map((s)=>`${s}/*.*`)
646
649
  ];
650
+ this._systems = Object.values(romulatorClient.ZRomulatorSystemId);
647
651
  }
648
652
  async gamesFolder() {
649
653
  const config = await this._configs.get(romulatorClient.ZRomulatorConfigId.Games);
@@ -660,31 +664,61 @@ class ZRomulatorFilesService {
660
664
  const gamesFolder = await this.gamesFolder();
661
665
  return node_path.resolve(gamesFolder, ZRomulatorFilesService.InfoFolderName);
662
666
  }
663
- async repository() {
667
+ async contents(root, path) {
668
+ const repository = await this.seed();
669
+ const prefix = lodashEs.trimEnd(root, "/");
670
+ const folder = `${prefix}${node_path.sep}`;
671
+ let filter = new helpfulQuery.ZFilterBinaryBuilder().subject("path");
672
+ filter = path == null ? filter.startsWith().value(folder) : filter.equal().value(node_path.resolve(folder, path));
673
+ const sort = new helpfulQuery.ZSortBuilder().ascending("path").build();
674
+ const request = new helpfulQuery.ZDataRequestBuilder().filter(filter.build()).sort(sort).build();
675
+ const nodes = await repository.retrieve(request);
676
+ return path == null ? nodes : helpfulFn.firstDefined(null, lodashEs.first(nodes));
677
+ }
678
+ async init() {
679
+ await this.seed();
680
+ }
681
+ async dispose() {
682
+ await this._repository.reset();
683
+ }
684
+ async seed() {
664
685
  const path = await this.gamesFolder();
665
686
  if (this._repository.path !== path) {
666
- await this._folderWriter.write(await this.mediaFolder());
667
- await this._folderWriter.write(await this.infoFolder());
687
+ await this._folderStream.write(await this.mediaFolder());
688
+ await this._folderStream.write(await this.infoFolder());
668
689
  await this._repository.initialize(path, this._globs);
669
690
  }
670
691
  return this._repository;
671
692
  }
672
- async media() {
673
- const repository = await this.repository();
674
- const prefix = lodashEs.trimEnd(await this.mediaFolder(), "/");
675
- const folder = `${prefix}${node_path.sep}`;
676
- const filter = new helpfulQuery.ZFilterBinaryBuilder().subject("path").startsWith().value(folder).build();
677
- const sort = new helpfulQuery.ZSortBuilder().ascending("path").build();
678
- const request = new helpfulQuery.ZDataRequestBuilder().filter(filter).sort(sort).build();
679
- return repository.retrieve(request);
693
+ async media(path) {
694
+ return this.contents(await this.mediaFolder(), path);
695
+ }
696
+ async systems(path) {
697
+ // Systems use directories. There's a maximum limit of about 200 systems.
698
+ // Since we don't actually need to read any metadata or scan through thousands
699
+ // of unknown folders, we can use the supported system ids to just grab the
700
+ // systems that we need. Since the file repository does a stat anyway, we can just
701
+ // grab the systems from the file system and it should be fast enough. These are all
702
+ // folders, so we don't even need the stats for them and we can assume folders.
703
+ const games = await this.gamesFolder();
704
+ const folders = path == null ? this._systems.map((s)=>`${s}/`) : node_path.resolve(games, path);
705
+ const items = await this._fileSystem.search(folders, {
706
+ cwd: games
707
+ });
708
+ return path == null ? items : helpfulFn.firstDefined(null, lodashEs.first(items));
709
+ }
710
+ async info(path) {
711
+ return this.contents(await this.infoFolder(), path);
680
712
  }
681
713
  }
682
714
  ZRomulatorFilesService = _ts_decorate$8([
683
715
  common.Injectable(),
684
- _ts_param$4(0, common.Inject(ZRomulatorConfigsToken)),
685
- _ts_metadata$4("design:type", Function),
686
- _ts_metadata$4("design:paramtypes", [
687
- typeof IZRomulatorConfigsService === "undefined" ? Object : IZRomulatorConfigsService
716
+ _ts_param$5(0, common.Inject(ZRomulatorConfigsToken)),
717
+ _ts_param$5(1, common.Inject(crumbtrailNest.ZFileSystemToken)),
718
+ _ts_metadata$5("design:type", Function),
719
+ _ts_metadata$5("design:paramtypes", [
720
+ typeof IZRomulatorConfigsService === "undefined" ? Object : IZRomulatorConfigsService,
721
+ typeof IZFileSystemService === "undefined" ? Object : IZFileSystemService
688
722
  ])
689
723
  ], ZRomulatorFilesService);
690
724
 
@@ -694,11 +728,30 @@ function _ts_decorate$7(decorators, target, key, desc) {
694
728
  else for(var i = decorators.length - 1; i >= 0; i--)if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
695
729
  return c > 3 && r && Object.defineProperty(target, key, r), r;
696
730
  }
731
+ function _ts_metadata$4(k, v) {
732
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
733
+ }
734
+ function _ts_param$4(paramIndex, decorator) {
735
+ return function(target, key) {
736
+ decorator(target, key, paramIndex);
737
+ };
738
+ }
697
739
  class ZRomulatorFilesModule {
740
+ _files;
741
+ constructor(_files){
742
+ this._files = _files;
743
+ }
744
+ async onModuleInit() {
745
+ await this._files.init();
746
+ }
747
+ async onModuleDestroy() {
748
+ await this._files.dispose();
749
+ }
698
750
  }
699
751
  ZRomulatorFilesModule = _ts_decorate$7([
700
752
  common.Module({
701
753
  imports: [
754
+ crumbtrailNest.ZFileSystemModule,
702
755
  ZRomulatorConfigsModule
703
756
  ],
704
757
  providers: [
@@ -710,7 +763,12 @@ ZRomulatorFilesModule = _ts_decorate$7([
710
763
  exports: [
711
764
  ZRomulatorFilesToken
712
765
  ]
713
- })
766
+ }),
767
+ _ts_param$4(0, common.Inject(ZRomulatorFilesToken)),
768
+ _ts_metadata$4("design:type", Function),
769
+ _ts_metadata$4("design:paramtypes", [
770
+ typeof IZRomulatorFilesService === "undefined" ? Object : IZRomulatorFilesService
771
+ ])
714
772
  ], ZRomulatorFilesModule);
715
773
 
716
774
  function _ts_decorate$6(decorators, target, key, desc) {
@@ -1005,13 +1063,16 @@ function _ts_param$1(paramIndex, decorator) {
1005
1063
  }
1006
1064
  const ZRomulatorSystemsToken = Symbol("romulator-systems-service");
1007
1065
  class ZRomulatorSystemsService {
1008
- _file;
1009
- _configs;
1066
+ _files;
1010
1067
  logger;
1011
1068
  _logger;
1012
- constructor(_file, _configs, logger){
1013
- this._file = _file;
1014
- this._configs = _configs;
1069
+ _fileStream = new crumbtrailFs.ZStreamFile({
1070
+ cache: {
1071
+ maxFiles: Object.keys(romulatorClient.ZRomulatorSystemId).length + 1
1072
+ }
1073
+ });
1074
+ constructor(_files, logger){
1075
+ this._files = _files;
1015
1076
  this.logger = logger;
1016
1077
  this._logger = new lumberjackyLog.ZLoggerContext("ZRomulatorSystemsService", logger);
1017
1078
  }
@@ -1020,18 +1081,8 @@ class ZRomulatorSystemsService {
1020
1081
  const size = helpfulFn.firstDefined(Infinity, req.size);
1021
1082
  let msg = `Retrieving systems page, ${page}, with size, ${size}.`;
1022
1083
  this._logger.log(new lumberjackyLog.ZLogEntryBuilder().info().message(msg).build());
1023
- const { contents } = await this._configs.get(romulatorClient.ZRomulatorConfigId.Games);
1024
- const { gamesFolder } = contents;
1025
- const { fallback } = romulatorClient.ZRomulatorConfigGamesMetadata.gamesFolder();
1026
- const _folder = helpfulFn.firstDefined(fallback, gamesFolder);
1027
- const cwd = helpfulFn.detokenize(_folder, process.env);
1028
- msg = `Looking for systems in ${cwd}`;
1029
- this._logger.log(new lumberjackyLog.ZLogEntryBuilder().info().message(msg).build());
1030
- const searchOptions = {
1031
- cwd
1032
- };
1033
- const folders = await this._file.search("*/", searchOptions);
1034
- const systems = folders.map((folder)=>folder.path).map((path)=>node_path.basename(path)).map((slug)=>this._createSystemFromSlug(slug)).filter((system)=>system != null);
1084
+ const folders = await this._files.systems();
1085
+ const systems = await Promise.all(folders.map((folder)=>folder.path).map((path)=>node_path.basename(path)).filter((slug)=>romulatorClient.isSystemId(slug)).map((slug)=>this._createSystemFromSlug(slug)));
1035
1086
  msg = `Found ${systems.length} systems`;
1036
1087
  this._logger.log(new lumberjackyLog.ZLogEntryBuilder().info().message(msg).build());
1037
1088
  const sourceOptions = new helpfulQuery.ZDataSourceStaticOptionsBuilder().search(new helpfulQuery.ZDataSearchFields([
@@ -1045,27 +1096,46 @@ class ZRomulatorSystemsService {
1045
1096
  return new helpfulQuery.ZPageBuilder().data(data).count(count).build();
1046
1097
  }
1047
1098
  async get(id) {
1048
- const all = await this.list(new helpfulQuery.ZDataRequestBuilder().build());
1049
- const system = lodashEs.find(all.data, (system)=>system.id === id);
1050
- if (!system) {
1051
- throw new common.NotFoundException(`Unable to find system with id, ${id}.`);
1099
+ // The system path should be the slug itself.
1100
+ if (!romulatorClient.isSystemId(id)) {
1101
+ const message = `The specified system slug, ${id}, is not supported.`;
1102
+ throw new common.NotFoundException(message);
1052
1103
  }
1053
- return system;
1104
+ const node = await this._files.systems(id);
1105
+ if (node == null) {
1106
+ const message = `System with slug, ${id}, was not found.`;
1107
+ throw new common.NotFoundException(message);
1108
+ }
1109
+ return this._createSystemFromSlug(id);
1054
1110
  }
1055
- _createSystemFromSlug(slug) {
1056
- // A romulator system's slug should read the metadata.json file from the root
1057
- return ZRomulatorSystemKnown.from(slug);
1111
+ async _createSystemFromSlug(slug) {
1112
+ const system = new romulatorClient.ZRomulatorSystemBuilder().id(slug);
1113
+ const path = `${slug}/info.json`;
1114
+ const info = await this._files.info(path);
1115
+ if (info == null) {
1116
+ // Best we can do right now.
1117
+ return system.build();
1118
+ }
1119
+ try {
1120
+ const contents = await this._fileStream.read(info.path);
1121
+ const json = JSON.parse(contents.toString());
1122
+ return system.assign(json).redact().build();
1123
+ } catch (e) {
1124
+ // Best we can do
1125
+ const err = helpfulFn.createError(e);
1126
+ const msg = `Cannot read system metadata, ${err.message}`;
1127
+ this._logger.log(new lumberjackyLog.ZLogEntryBuilder().error().message(msg).build());
1128
+ return system.build();
1129
+ }
1058
1130
  }
1059
1131
  }
1060
1132
  ZRomulatorSystemsService = _ts_decorate$3([
1061
1133
  common.Injectable(),
1062
- _ts_param$1(0, common.Inject(crumbtrailNest.ZFileSystemToken)),
1063
- _ts_param$1(1, common.Inject(ZRomulatorConfigsToken)),
1064
- _ts_param$1(2, common.Inject(lumberjackyNest.ZLoggerToken)),
1134
+ _ts_param$1(0, common.Inject(ZRomulatorFilesToken)),
1135
+ _ts_param$1(1, common.Inject(lumberjackyNest.ZLoggerToken)),
1065
1136
  _ts_metadata$1("design:type", Function),
1066
1137
  _ts_metadata$1("design:paramtypes", [
1067
- typeof IZFileSystemService === "undefined" ? Object : IZFileSystemService,
1068
- typeof IZRomulatorConfigsService === "undefined" ? Object : IZRomulatorConfigsService,
1138
+ typeof IZRomulatorFilesService === "undefined" ? Object : IZRomulatorFilesService,
1069
1139
  typeof IZLogger === "undefined" ? Object : IZLogger
1070
1140
  ])
1071
1141
  ], ZRomulatorSystemsService);
@@ -1139,8 +1209,7 @@ class ZRomulatorSystemsModule {
1139
1209
  ZRomulatorSystemsModule = _ts_decorate$1([
1140
1210
  common.Module({
1141
1211
  imports: [
1142
- ZRomulatorConfigsModule,
1143
- crumbtrailNest.ZFileSystemModule,
1212
+ ZRomulatorFilesModule,
1144
1213
  lumberjackyNest.ZLoggerModule
1145
1214
  ],
1146
1215
  controllers: [