@simeonradivoev/gameflow-sdk 1.5.1 → 1.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/shared.ts ADDED
@@ -0,0 +1,631 @@
1
+ import * as z from "zod";
2
+
3
+ export const settingRegistry = z.registry<{
4
+ dev?: boolean;
5
+ }>();
6
+
7
+ export const SettingsSchema = z.object({
8
+ rommAddress: z.url().optional(),
9
+ rommUser: z.string().default('admin').optional(),
10
+ windowSize: z.object({ width: z.number(), height: z.number() }).optional(),
11
+ windowPosition: z.object({ x: z.number(), y: z.number() }).optional(),
12
+ downloadPath: z.string(),
13
+ launchInFullscreen: z.boolean().default(true),
14
+ disabledPlugins: z.array(z.string()).default([]),
15
+ emulatorResolution: z.enum(['720p', '1080p', '1440p', '4k']).default('720p'),
16
+ emulatorWidescreen: z.boolean().default(true)
17
+ }); export const LocalSettingsSchema = z.object({
18
+ backgroundBlur: z.boolean().default(true).meta({ title: "Background Blur" }),
19
+ backgroundAnimation: z.boolean().default(true).meta({ title: "Background Animation" }),
20
+ theme: z.enum(['dark', 'light', 'auto']).default('auto').meta({ title: "Theme" }),
21
+ soundEffects: z.boolean().default(true).meta({ title: "Sounds" }),
22
+ soundEffectsVolume: z.number().min(0).max(100).default(50).meta({ title: "Sound Volume" }),
23
+ hapticsEffects: z.boolean().default(true).meta({ title: "Haptics" }),
24
+ showRouterDevOptions: z.boolean().default(false).meta({ title: "Show Router Options" }).register(settingRegistry, { dev: true }),
25
+ showQueryDevOptions: z.boolean().default(false).meta({ title: "Show Query Options" }).register(settingRegistry, { dev: true }),
26
+ useGameflowKeyboard: z.boolean().default(true).describe("Show the gameflow on screen keyboard when using a controller").meta({ title: "Use Gameflow Keyboard" }),
27
+ autoKeybaord: z.boolean().default(true).describe("Open on screen keybaord automatically").meta({ title: "Auto Keyboard" })
28
+ });
29
+ export const GameListFilterSchema = z.object({
30
+ platform_source: z.string().optional(),
31
+ platform_slug: z.string().optional(),
32
+ platform_id: z.coerce.number().optional(),
33
+ collection_id: z.coerce.number().optional(),
34
+ collection_source: z.string().optional(),
35
+ limit: z.coerce.number().optional(),
36
+ search: z.string().optional(),
37
+ offset: z.coerce.number().optional(),
38
+ source: z.string().optional(),
39
+ localOnly: z.coerce.boolean().optional(),
40
+ orderBy: z.literal(['added', 'activity', 'name', 'release']).optional(),
41
+ age_ratings: z.union([z.string().array(), z.string().transform(v => [v])]).optional(),
42
+ genres: z.union([z.string().array(), z.string().transform(v => [v])]).optional(),
43
+ keywords: z.union([z.string().array(), z.string().transform(v => [v])]).optional(),
44
+ });
45
+ export const DownloadSourceSchema = z.object({
46
+ id: z.string(),
47
+ name: z.string()
48
+ });
49
+ export const RommLoginDataSchema = z.object({ hostname: z.url(), username: z.string(), password: z.string() });
50
+ export type GameListFilterType = z.infer<typeof GameListFilterSchema>;
51
+ export const DirSchema = z.object({ name: z.string(), parentPath: z.string(), isDirectory: z.boolean() });
52
+ export type DirType = z.infer<typeof DirSchema>;
53
+ export const CustomEmulatorSchema = z.record(z.string(), z.string());
54
+ export const GithubManifestSchema = z.object({
55
+ sha: z.hash('sha1'),
56
+ url: z.url(),
57
+ tree: z.array(z.object({
58
+ path: z.string(),
59
+ mode: z.string(),
60
+ type: z.enum(['blob', 'tree']),
61
+ sha: z.hash('sha1'),
62
+ url: z.url()
63
+ }))
64
+ });
65
+ export const StoreGameSaveSchema = z.object({
66
+ cwd: z.string(),
67
+ globs: z.string().array()
68
+ });
69
+ export const StoreDownloadSchema = z.discriminatedUnion('type', [
70
+ z.object({
71
+ type: z.literal('direct'),
72
+ url: z.url(),
73
+ name: z.string().optional(),
74
+ system: z.string(),
75
+ main: z.string().optional(),
76
+ saves: z.record(z.string(), StoreGameSaveSchema).optional()
77
+ }),
78
+ z.object({
79
+ type: z.literal("itch"),
80
+ path: z.string(),
81
+ name: z.string().optional(),
82
+ system: z.string(),
83
+ saves: z.record(z.string(), StoreGameSaveSchema).optional()
84
+ })
85
+ ]);
86
+ export const NewGameSchema = z.object({
87
+ name: z.string(),
88
+ summary: z.string(),
89
+ genres: z.string().regex(/^$|^(\s*\S[^,]*)(\s*,\s*\S[^,]*)*\s*$/, {
90
+ message: "Must be a comma-separated list",
91
+ })
92
+ });
93
+ export const StoreGameSchema = z.object({
94
+ name: z.string(),
95
+ description: z.string(),
96
+ version: z.string(),
97
+ homepage: z.string().optional(),
98
+ keywords: z.string().array().optional(),
99
+ genres: z.string().array().optional(),
100
+ companies: z.string().array().optional(),
101
+ screenshots: z.string().array().optional(),
102
+ covers: z.string().array().optional(),
103
+ igdb_id: z.number().optional(),
104
+ ra_id: z.number().optional(),
105
+ sgdb_id: z.number().optional(),
106
+ first_release_date: z.union([z.number(), z.date()]).optional(),
107
+ player_count: z.string().optional(),
108
+ saves: z.record(z.string(), z.record(z.string(), StoreGameSaveSchema)).optional(),
109
+ downloads: z.record(z.string(), StoreDownloadSchema)
110
+ });
111
+ export const EmulatorPackageSchema = z.object({
112
+ name: z.string(),
113
+ description: z.string(),
114
+ homepage: z.url(),
115
+ logo: z.url(),
116
+ type: z.enum(['emulator']),
117
+ os: z.array(z.enum(['darwin', 'linux', 'win32', 'android'])),
118
+ keywords: z.array(z.string()).optional(),
119
+ downloads: z.record(z.string(), z.array(z.discriminatedUnion('type', [
120
+ z.object({
121
+ type: z.literal(['github', 'gitlab']),
122
+ pattern: z.string(),
123
+ path: z.string(),
124
+ bin: z.string().optional()
125
+ }),
126
+ z.object({
127
+ type: z.literal('direct'),
128
+ url: z.url(),
129
+ bin: z.string().optional()
130
+ }),
131
+ z.object({
132
+ type: z.literal('scoop'),
133
+ url: z.url(),
134
+ bin: z.string().optional()
135
+ })
136
+ ]))).optional(),
137
+ systems: z.array(z.string()),
138
+ bios: z.literal(["required", "optional"]).optional()
139
+ });
140
+ export const ScoopPackageSchema = z.object({
141
+ version: z.string(),
142
+ url: z.url().optional(),
143
+ description: z.string(),
144
+ bin: z.string().optional(),
145
+ architecture: z.record(z.string(), z.object({
146
+ url: z.url(),
147
+ hash: z.string().optional(),
148
+ extract_dir: z.string().optional()
149
+ })).optional()
150
+ });
151
+ export const SystemInfoSchema = z.object({
152
+ battery: z.object({
153
+ percent: z.number(),
154
+ isCharging: z.boolean(),
155
+ acConnected: z.boolean(),
156
+ hasBattery: z.boolean()
157
+ }),
158
+ wifiConnections: z.array(z.object({ signalLevel: z.number() })),
159
+ bluetoothDevices: z.array(z.object({ connected: z.boolean() }))
160
+ });
161
+ export const GithubReleaseSchema = z.object({
162
+ id: z.number(),
163
+ tag_name: z.string().optional(),
164
+ url: z.url(),
165
+ body: z.string(),
166
+ assets: z.array(z.object({
167
+ name: z.string(),
168
+ browser_download_url: z.url(),
169
+ content_type: z.string().optional()
170
+ }))
171
+ });
172
+ export const EmulatorDownloadInfoSchema = z.object({
173
+ id: z.string(),
174
+ version: z.string().optional(),
175
+ url: z.url().optional(),
176
+ description: z.string().optional(),
177
+ downloadDate: z.coerce.date(),
178
+ type: z.string()
179
+ });
180
+ export const PluginEntrySchema = z.object({
181
+ downloads: z.object({
182
+ monthly: z.number(),
183
+ weekly: z.number()
184
+ }),
185
+ searchScore: z.number(),
186
+ installed: z.boolean(),
187
+ update: z.object({ from: z.string() }).optional(),
188
+ package: z.object({
189
+ name: z.string(),
190
+ keywords: z.string().array(),
191
+ version: z.string(),
192
+ description: z.string().optional(),
193
+ sanitized_name: z.string(),
194
+ license: z.string().optional(),
195
+ publisher: z.object({
196
+ email: z.string(),
197
+ username: z.string(),
198
+ trustedPublisher: z.object({
199
+ id: z.string(),
200
+ oidcConfigId: z.string()
201
+ }).optional()
202
+ }),
203
+ date: z.coerce.date(),
204
+ links: z.object({
205
+ homepage: z.string().optional(),
206
+ repository: z.string().optional(),
207
+ bugs: z.string().optional(),
208
+ npm: z.url()
209
+ })
210
+ })
211
+ });
212
+ export const PluginBunDetailsSchema = z.object({
213
+ name: z.string(),
214
+ keywords: z.string().array(),
215
+ version: z.string(),
216
+ author: z.object({ name: z.string().optional() }).optional(),
217
+ license: z.string().optional(),
218
+ devDependencies: z.record(z.string(), z.string()).optional(),
219
+ dependencies: z.record(z.string(), z.string()).optional(),
220
+ maintainers: z.object({ name: z.string() }).array().optional(),
221
+ dist: z.object({ unpackedSize: z.number() }),
222
+ description: z.string().optional(),
223
+ _npmUser: z.object({ name: z.string() }).optional()
224
+ });
225
+ export type EmulatorPackageType = z.infer<typeof EmulatorPackageSchema>;
226
+ export type StoreGameType = z.infer<typeof StoreGameSchema>;
227
+ export type StoreDownloadType = z.infer<typeof StoreDownloadSchema>;
228
+ export type SettingsType = z.infer<typeof SettingsSchema>;
229
+ export type LocalSettingsType = z.infer<typeof LocalSettingsSchema>;
230
+ export const PlatformSchema = z.object({ slug: z.string() });
231
+ export type SystemInfoType = z.infer<typeof SystemInfoSchema>;
232
+ export type EmulatorDownloadInfoType = z.infer<typeof EmulatorDownloadInfoSchema>;
233
+ export type DownloadSourceType = z.infer<typeof DownloadSourceSchema>;
234
+ export type PluginEntryType = z.infer<typeof PluginEntrySchema>;
235
+ export type PluginBunDetailsType = z.infer<typeof PluginBunDetailsSchema>;
236
+
237
+ export interface SaveFileChange
238
+ {
239
+ subPath: string | string[];
240
+ isGlob?: true;
241
+ cwd: string;
242
+ shared: boolean;
243
+ fixedSize?: boolean;
244
+ }
245
+
246
+ export type EmulatorSourceType = 'custom' | 'store' | 'registry' | 'system' | 'static' | 'embedded';
247
+
248
+ export interface EmulatorSourceEntryType
249
+ {
250
+ binPath: string;
251
+ rootPath?: string;
252
+ type: EmulatorSourceType;
253
+ exists: boolean;
254
+ }
255
+
256
+ export interface FrontEndEmulator
257
+ {
258
+ name: string;
259
+ source: string;
260
+ logo: string;
261
+ systems: EmulatorSystem[];
262
+ description?: string;
263
+ gameCount: number;
264
+ validSources: EmulatorSourceEntryType[];
265
+ integrations: EmulatorSupport[];
266
+ }
267
+
268
+ export interface EmulatorSystem { id: string, romm_slug?: string, name: string, iconUrl: string; }
269
+
270
+ export interface FrontEndEmulatorDetailedDownload
271
+ {
272
+ name: string;
273
+ type: string | undefined;
274
+ version?: string;
275
+ }
276
+
277
+ export interface FrontEndEmulatorDetailed extends FrontEndEmulator
278
+ {
279
+ homepage: string;
280
+ description: string;
281
+ downloads: FrontEndEmulatorDetailedDownload[];
282
+ keywords?: string[];
283
+ screenshots: string[];
284
+ biosRequirement?: "required" | "optional";
285
+ bios?: string[];
286
+ storeDownloadInfo?: { hasUpdate: boolean; version?: string, type: string; description?: string; };
287
+ }
288
+
289
+ export interface FrontEndGameTypeDetailedAchievement
290
+ {
291
+ id: string;
292
+ title: string;
293
+ description?: string;
294
+ date?: Date;
295
+ date_hardcode?: Date;
296
+ badge_url?: string;
297
+ display_order: number;
298
+ type?: string;
299
+ }
300
+
301
+ export interface FrontEndGameTypeDetailedEmulator extends FrontEndEmulator
302
+ {
303
+
304
+ }
305
+
306
+ export interface FrontEndGameTypeDetailed extends Exclude<FrontEndGameTypeWithIds, "metadata">
307
+ {
308
+ summary: string | null;
309
+ fs_size_bytes: number | null;
310
+ missing: boolean;
311
+ local: boolean;
312
+ version?: string | null;
313
+ version_system?: string | null;
314
+ version_source?: string | null;
315
+ metadata: FrontEndGameMetadataDetailed,
316
+ emulators?: FrontEndGameTypeDetailedEmulator[],
317
+ achievements?: {
318
+ unlocked: number;
319
+ total: number;
320
+ entires: FrontEndGameTypeDetailedAchievement[];
321
+ };
322
+ };
323
+
324
+ export interface Drive
325
+ {
326
+ parent: string | null;
327
+ device: string;
328
+ label: string;
329
+ mountPoint: string | null;
330
+ type: string;
331
+ size: number;
332
+ used: number;
333
+ isRemovable: boolean;
334
+ interfaceType: string | null;
335
+ hasWriteAccess: boolean;
336
+ hasReadAccess: boolean;
337
+ }
338
+
339
+ export interface DownloadsDrive
340
+ {
341
+ device: string;
342
+ label: string;
343
+ mountPoint: string | null;
344
+ isRemovable: boolean;
345
+ size: number;
346
+ used: number;
347
+ isCurrentlyUsed: boolean;
348
+ unusableReason: 'not_enough_space' | 'already_used' | null;
349
+ }
350
+
351
+ export interface FrontendNotification
352
+ {
353
+ title?: string;
354
+ message: string;
355
+ type: 'success' | 'error' | 'info' | 'custom';
356
+ icon?: "save" | "upload" | "clock";
357
+ duration?: number;
358
+ }
359
+
360
+ export interface CommandEntry
361
+ {
362
+ /** The ID of the command. Could be just an index or a string */
363
+ id: string | number;
364
+ /** The front end label for the command. Mainly gotten from ES-DE list */
365
+ label?: string;
366
+ /** Compiled command to be executed */
367
+ command: string | string[];
368
+ /** Environment variables */
369
+ env?: Record<string, string>,
370
+ /** The path the spawned process will start at */
371
+ startDir?: string;
372
+ /** Is the command valid, for example does the executable exists */
373
+ valid: boolean;
374
+ /** Run the command as shell. Defaults is true */
375
+ shell?: boolean;
376
+ /** For what emulator is the command */
377
+ emulator?: string;
378
+ /** Where the emulator came from */
379
+ emulatorSource?: EmulatorSourceType;
380
+ /** Metadata for the command */
381
+ metadata: {
382
+ romPath?: string;
383
+ emulatorBin?: string;
384
+ /** The root directory of the emulator */
385
+ emulatorDir?: string;
386
+ };
387
+ }
388
+
389
+ export interface FrontEndId
390
+ {
391
+ id: string;
392
+ source: string;
393
+ }
394
+
395
+ // Stuff stored in the local sqlite metadata field
396
+ export interface LocalGameMetadata
397
+ {
398
+ genres?: string[],
399
+ companies?: string[],
400
+ game_modes?: string[],
401
+ age_ratings?: string[];
402
+ player_count?: string;
403
+ first_release_date?: number;
404
+ average_rating?: number;
405
+ }
406
+
407
+ export interface FrontEndPlatformType
408
+ {
409
+ id: FrontEndId;
410
+ slug: string;
411
+ name: string;
412
+ family_name?: string | null;
413
+ path_cover: string | null;
414
+ game_count: number;
415
+ updated_at: Date;
416
+ hasLocal: boolean;
417
+ paths_screenshots: string[];
418
+ }
419
+
420
+ export interface FrontEndGameTypeWithIds extends FrontEndGameType
421
+ {
422
+ igdb_id: number | null;
423
+ ra_id: number | null;
424
+ }
425
+
426
+ export interface FrontEndFilterSets
427
+ {
428
+ age_ratings: Set<string>,
429
+ player_counts: Set<string>,
430
+ languages: Set<string>,
431
+ companies: Set<string>,
432
+ genres: Set<string>;
433
+ }
434
+
435
+ export interface FrontEndFilterLists
436
+ {
437
+ age_ratings: string[],
438
+ player_counts: string[],
439
+ languages: string[],
440
+ companies: string[],
441
+ genres: string[];
442
+ }
443
+
444
+ export interface FrontEndGameMetadata
445
+ {
446
+ first_release_date: Date | null;
447
+ }
448
+
449
+ export interface FrontEndGameMetadataDetailed extends FrontEndGameMetadata
450
+ {
451
+ genres: string[],
452
+ companies: string[],
453
+ game_modes: string[],
454
+ age_ratings: string[];
455
+ player_count: string | null;
456
+ average_rating: number | null;
457
+ }
458
+
459
+ export interface FrontEndGameType
460
+ {
461
+ platform_display_name: string | null,
462
+ path_platform_cover: string | null;
463
+ id: FrontEndId,
464
+ source: string | null,
465
+ source_id: string | null,
466
+ path_fs: string | null,
467
+ path_covers: string[],
468
+ last_played: Date | null,
469
+ updated_at: Date,
470
+ metadata: FrontEndGameMetadata,
471
+ slug: string | null,
472
+ name: string | null,
473
+ platform_id: number | null,
474
+ platform_slug: string | null,
475
+ paths_screenshots: string[];
476
+ };
477
+
478
+ export type GameStatusType = 'installed' | 'missing-emulator' | 'error' | 'install' | 'download' | 'extract' | 'playing' | 'queued';
479
+
480
+ export interface GameInstallProgress
481
+ {
482
+ progress?: number;
483
+ status?: GameStatusType;
484
+ details?: string;
485
+ commands?: CommandEntry[];
486
+ error?: any;
487
+ }
488
+
489
+ export type JobStatus = 'completed' | 'error' | 'running' | 'queued' | 'aborted';
490
+ export type GameInstallProgressEvent = 'refresh';
491
+
492
+ export interface FrontendPlugin
493
+ {
494
+ name: string;
495
+ displayName?: string;
496
+ description?: string;
497
+ category: string;
498
+ enabled: boolean;
499
+ canDisable: boolean;
500
+ canUninstall: boolean;
501
+ source: PluginSourceType;
502
+ hasSettings: boolean;
503
+ version: string;
504
+ icon?: string;
505
+ update?: PluginUpdateCheck;
506
+ }
507
+
508
+ export interface PluginUpdateCheck
509
+ {
510
+ current: string;
511
+ new: string;
512
+ }
513
+
514
+ export type PluginSourceType = "builtin" | "store";
515
+
516
+ export type KeysWithValueAssignableTo<T, Value> = {
517
+ [K in keyof T]: Exclude<T[K], undefined> extends Value ? K : never;
518
+ }[keyof T];
519
+
520
+ export interface DownloadInfo
521
+ {
522
+ id: string;
523
+ screenshotUrls: string[];
524
+ coverUrl: string;
525
+ platform?: DownloadPlatform;
526
+ slug?: string;
527
+ path_fs?: string;
528
+ main_glob?: string;
529
+ summary?: string;
530
+ name: string;
531
+ last_played?: Date;
532
+ igdb_id?: number;
533
+ ra_id?: number;
534
+ source_id: string;
535
+ system_slug: string;
536
+ extract_path?: string;
537
+ metadata?: any;
538
+ files: DownloadFileEntry[];
539
+ auth?: string;
540
+ version?: string;
541
+ version_source?: string;
542
+ version_system?: string;
543
+ }
544
+
545
+ export interface DownloadPlatform
546
+ {
547
+ id: string;
548
+ source: string;
549
+ igdb_id?: number;
550
+ igdb_slug?: string;
551
+ ra_id?: number;
552
+ moby_id?: number;
553
+ slug: string;
554
+ name: string;
555
+ /** Like Sony or Nintendo */
556
+ family_name?: string;
557
+ }
558
+
559
+ export interface DownloadFileEntry
560
+ {
561
+ url: URL;
562
+ /** The path of the file, excluding the name */
563
+ file_path: string;
564
+ /** Just the name of the file including the extension */
565
+ file_name: string;
566
+ /** Checksum of the file */
567
+ sha1?: string;
568
+ /** Size in bytes */
569
+ size?: number;
570
+ }
571
+
572
+ export interface LocalDownloadFileEntry extends DownloadFileEntry
573
+ {
574
+ /** Exists on the file system */
575
+ exists: boolean;
576
+ /** Matches the checksum */
577
+ matches: boolean;
578
+ }
579
+
580
+ export interface FrontEndCollection
581
+ {
582
+ id: FrontEndId;
583
+ name: string;
584
+ description: string;
585
+ path_platform_cover: string | null;
586
+ game_count: number;
587
+ }
588
+
589
+ export type EmulatorCapabilities = "saves" | "fullscreen" | "resolution" | "batch" | "states" | "config";
590
+
591
+ export interface EmulatorSupport
592
+ {
593
+ id: string;
594
+ source?: EmulatorSourceEntryType;
595
+ supportLevel?: "partial" | "full";
596
+ capabilities?: EmulatorCapabilities[];
597
+ }
598
+
599
+ export interface GameLookup
600
+ {
601
+ source: string;
602
+ id: string;
603
+ coverUrl: string | null | undefined;
604
+ slug: string | null | undefined;
605
+ screenshotUrls: string[];
606
+ name: string;
607
+ summary: string | null | undefined;
608
+ genres: string[];
609
+ companies: string[];
610
+ game_modes: string[];
611
+ age_ratings: string[];
612
+ player_count: string | undefined;
613
+ first_release_date: number | undefined;
614
+ average_rating: number | undefined;
615
+ keywords: string[];
616
+ igdb_id: number | undefined;
617
+ platforms: {
618
+ id: number;
619
+ name?: string | null;
620
+ displayName: string;
621
+ slug: string;
622
+ }[];
623
+ }
624
+
625
+ export interface AutoSaveChange
626
+ {
627
+ subPath: string;
628
+ cwd: string;
629
+ }
630
+
631
+ export type SaveSlots = Record<string, { cwd: string; }>;