@simeonradivoev/gameflow-sdk 1.5.1 → 1.5.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/shared.ts ADDED
@@ -0,0 +1,623 @@
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
+ package: z.object({
188
+ name: z.string(),
189
+ keywords: z.string().array(),
190
+ version: z.string(),
191
+ description: z.string().optional(),
192
+ sanitized_name: z.string(),
193
+ license: z.string().optional(),
194
+ publisher: z.object({
195
+ email: z.string(),
196
+ username: z.string(),
197
+ trustedPublisher: z.object({
198
+ id: z.string(),
199
+ oidcConfigId: z.string()
200
+ }).optional()
201
+ }),
202
+ date: z.coerce.date(),
203
+ links: z.object({
204
+ homepage: z.string().optional(),
205
+ repository: z.string().optional(),
206
+ bugs: z.string().optional(),
207
+ npm: z.url()
208
+ })
209
+ })
210
+ });
211
+ export const PluginBunDetailsSchema = z.object({
212
+ name: z.string(),
213
+ keywords: z.string().array(),
214
+ version: z.string(),
215
+ author: z.object({ name: z.string().optional() }).optional(),
216
+ license: z.string().optional(),
217
+ devDependencies: z.record(z.string(), z.string()).optional(),
218
+ dependencies: z.record(z.string(), z.string()).optional(),
219
+ maintainers: z.object({ name: z.string() }).array().optional(),
220
+ dist: z.object({ unpackedSize: z.number() }),
221
+ description: z.string().optional(),
222
+ _npmUser: z.object({ name: z.string() }).optional()
223
+ });
224
+ export type EmulatorPackageType = z.infer<typeof EmulatorPackageSchema>;
225
+ export type StoreGameType = z.infer<typeof StoreGameSchema>;
226
+ export type StoreDownloadType = z.infer<typeof StoreDownloadSchema>;
227
+ export type SettingsType = z.infer<typeof SettingsSchema>;
228
+ export type LocalSettingsType = z.infer<typeof LocalSettingsSchema>;
229
+ export const PlatformSchema = z.object({ slug: z.string() });
230
+ export type SystemInfoType = z.infer<typeof SystemInfoSchema>;
231
+ export type EmulatorDownloadInfoType = z.infer<typeof EmulatorDownloadInfoSchema>;
232
+ export type DownloadSourceType = z.infer<typeof DownloadSourceSchema>;
233
+ export type PluginEntryType = z.infer<typeof PluginEntrySchema>;
234
+ export type PluginBunDetailsType = z.infer<typeof PluginBunDetailsSchema>;
235
+
236
+ export interface SaveFileChange
237
+ {
238
+ subPath: string | string[];
239
+ isGlob?: true;
240
+ cwd: string;
241
+ shared: boolean;
242
+ fixedSize?: boolean;
243
+ }
244
+
245
+ export type EmulatorSourceType = 'custom' | 'store' | 'registry' | 'system' | 'static' | 'embedded';
246
+
247
+ export interface EmulatorSourceEntryType
248
+ {
249
+ binPath: string;
250
+ rootPath?: string;
251
+ type: EmulatorSourceType;
252
+ exists: boolean;
253
+ }
254
+
255
+ export interface FrontEndEmulator
256
+ {
257
+ name: string;
258
+ source: string;
259
+ logo: string;
260
+ systems: EmulatorSystem[];
261
+ description?: string;
262
+ gameCount: number;
263
+ validSources: EmulatorSourceEntryType[];
264
+ integrations: EmulatorSupport[];
265
+ }
266
+
267
+ export interface EmulatorSystem { id: string, romm_slug?: string, name: string, iconUrl: string; }
268
+
269
+ export interface FrontEndEmulatorDetailedDownload
270
+ {
271
+ name: string;
272
+ type: string | undefined;
273
+ version?: string;
274
+ }
275
+
276
+ export interface FrontEndEmulatorDetailed extends FrontEndEmulator
277
+ {
278
+ homepage: string;
279
+ description: string;
280
+ downloads: FrontEndEmulatorDetailedDownload[];
281
+ keywords?: string[];
282
+ screenshots: string[];
283
+ biosRequirement?: "required" | "optional";
284
+ bios?: string[];
285
+ storeDownloadInfo?: { hasUpdate: boolean; version?: string, type: string; description?: string; };
286
+ }
287
+
288
+ export interface FrontEndGameTypeDetailedAchievement
289
+ {
290
+ id: string;
291
+ title: string;
292
+ description?: string;
293
+ date?: Date;
294
+ date_hardcode?: Date;
295
+ badge_url?: string;
296
+ display_order: number;
297
+ type?: string;
298
+ }
299
+
300
+ export interface FrontEndGameTypeDetailedEmulator extends FrontEndEmulator
301
+ {
302
+
303
+ }
304
+
305
+ export interface FrontEndGameTypeDetailed extends Exclude<FrontEndGameTypeWithIds, "metadata">
306
+ {
307
+ summary: string | null;
308
+ fs_size_bytes: number | null;
309
+ missing: boolean;
310
+ local: boolean;
311
+ version?: string | null;
312
+ version_system?: string | null;
313
+ version_source?: string | null;
314
+ metadata: FrontEndGameMetadataDetailed,
315
+ emulators?: FrontEndGameTypeDetailedEmulator[],
316
+ achievements?: {
317
+ unlocked: number;
318
+ total: number;
319
+ entires: FrontEndGameTypeDetailedAchievement[];
320
+ };
321
+ };
322
+
323
+ export interface Drive
324
+ {
325
+ parent: string | null;
326
+ device: string;
327
+ label: string;
328
+ mountPoint: string | null;
329
+ type: string;
330
+ size: number;
331
+ used: number;
332
+ isRemovable: boolean;
333
+ interfaceType: string | null;
334
+ hasWriteAccess: boolean;
335
+ hasReadAccess: boolean;
336
+ }
337
+
338
+ export interface DownloadsDrive
339
+ {
340
+ device: string;
341
+ label: string;
342
+ mountPoint: string | null;
343
+ isRemovable: boolean;
344
+ size: number;
345
+ used: number;
346
+ isCurrentlyUsed: boolean;
347
+ unusableReason: 'not_enough_space' | 'already_used' | null;
348
+ }
349
+
350
+ export interface FrontendNotification
351
+ {
352
+ title?: string;
353
+ message: string;
354
+ type: 'success' | 'error' | 'info' | 'custom';
355
+ icon?: "save" | "upload" | "clock";
356
+ duration?: number;
357
+ }
358
+
359
+ export interface CommandEntry
360
+ {
361
+ /** The ID of the command. Could be just an index or a string */
362
+ id: string | number;
363
+ /** The front end label for the command. Mainly gotten from ES-DE list */
364
+ label?: string;
365
+ /** Compiled command to be executed */
366
+ command: string | string[];
367
+ /** Environment variables */
368
+ env?: Record<string, string>,
369
+ /** The path the spawned process will start at */
370
+ startDir?: string;
371
+ /** Is the command valid, for example does the executable exists */
372
+ valid: boolean;
373
+ /** Run the command as shell. Defaults is true */
374
+ shell?: boolean;
375
+ /** For what emulator is the command */
376
+ emulator?: string;
377
+ /** Where the emulator came from */
378
+ emulatorSource?: EmulatorSourceType;
379
+ /** Metadata for the command */
380
+ metadata: {
381
+ romPath?: string;
382
+ emulatorBin?: string;
383
+ /** The root directory of the emulator */
384
+ emulatorDir?: string;
385
+ };
386
+ }
387
+
388
+ export interface FrontEndId
389
+ {
390
+ id: string;
391
+ source: string;
392
+ }
393
+
394
+ // Stuff stored in the local sqlite metadata field
395
+ export interface LocalGameMetadata
396
+ {
397
+ genres?: string[],
398
+ companies?: string[],
399
+ game_modes?: string[],
400
+ age_ratings?: string[];
401
+ player_count?: string;
402
+ first_release_date?: number;
403
+ average_rating?: number;
404
+ }
405
+
406
+ export interface FrontEndPlatformType
407
+ {
408
+ id: FrontEndId;
409
+ slug: string;
410
+ name: string;
411
+ family_name?: string | null;
412
+ path_cover: string | null;
413
+ game_count: number;
414
+ updated_at: Date;
415
+ hasLocal: boolean;
416
+ paths_screenshots: string[];
417
+ }
418
+
419
+ export interface FrontEndGameTypeWithIds extends FrontEndGameType
420
+ {
421
+ igdb_id: number | null;
422
+ ra_id: number | null;
423
+ }
424
+
425
+ export interface FrontEndFilterSets
426
+ {
427
+ age_ratings: Set<string>,
428
+ player_counts: Set<string>,
429
+ languages: Set<string>,
430
+ companies: Set<string>,
431
+ genres: Set<string>;
432
+ }
433
+
434
+ export interface FrontEndFilterLists
435
+ {
436
+ age_ratings: string[],
437
+ player_counts: string[],
438
+ languages: string[],
439
+ companies: string[],
440
+ genres: string[];
441
+ }
442
+
443
+ export interface FrontEndGameMetadata
444
+ {
445
+ first_release_date: Date | null;
446
+ }
447
+
448
+ export interface FrontEndGameMetadataDetailed extends FrontEndGameMetadata
449
+ {
450
+ genres: string[],
451
+ companies: string[],
452
+ game_modes: string[],
453
+ age_ratings: string[];
454
+ player_count: string | null;
455
+ average_rating: number | null;
456
+ }
457
+
458
+ export interface FrontEndGameType
459
+ {
460
+ platform_display_name: string | null,
461
+ path_platform_cover: string | null;
462
+ id: FrontEndId,
463
+ source: string | null,
464
+ source_id: string | null,
465
+ path_fs: string | null,
466
+ path_covers: string[],
467
+ last_played: Date | null,
468
+ updated_at: Date,
469
+ metadata: FrontEndGameMetadata,
470
+ slug: string | null,
471
+ name: string | null,
472
+ platform_id: number | null,
473
+ platform_slug: string | null,
474
+ paths_screenshots: string[];
475
+ };
476
+
477
+ export type GameStatusType = 'installed' | 'missing-emulator' | 'error' | 'install' | 'download' | 'extract' | 'playing' | 'queued';
478
+
479
+ export interface GameInstallProgress
480
+ {
481
+ progress?: number;
482
+ status?: GameStatusType;
483
+ details?: string;
484
+ commands?: CommandEntry[];
485
+ error?: any;
486
+ }
487
+
488
+ export type JobStatus = 'completed' | 'error' | 'running' | 'queued' | 'aborted';
489
+ export type GameInstallProgressEvent = 'refresh';
490
+
491
+ export interface FrontendPlugin
492
+ {
493
+ name: string;
494
+ displayName?: string;
495
+ description?: string;
496
+ category: string;
497
+ enabled: boolean;
498
+ canDisable: boolean;
499
+ canUninstall: boolean;
500
+ source: PluginSourceType;
501
+ hasSettings: boolean;
502
+ version: string;
503
+ icon?: string;
504
+ }
505
+
506
+ export type PluginSourceType = "builtin" | "store";
507
+
508
+ export type KeysWithValueAssignableTo<T, Value> = {
509
+ [K in keyof T]: Exclude<T[K], undefined> extends Value ? K : never;
510
+ }[keyof T];
511
+
512
+ export interface DownloadInfo
513
+ {
514
+ id: string;
515
+ screenshotUrls: string[];
516
+ coverUrl: string;
517
+ platform?: DownloadPlatform;
518
+ slug?: string;
519
+ path_fs?: string;
520
+ main_glob?: string;
521
+ summary?: string;
522
+ name: string;
523
+ last_played?: Date;
524
+ igdb_id?: number;
525
+ ra_id?: number;
526
+ source_id: string;
527
+ system_slug: string;
528
+ extract_path?: string;
529
+ metadata?: any;
530
+ files: DownloadFileEntry[];
531
+ auth?: string;
532
+ version?: string;
533
+ version_source?: string;
534
+ version_system?: string;
535
+ }
536
+
537
+ export interface DownloadPlatform
538
+ {
539
+ id: string;
540
+ source: string;
541
+ igdb_id?: number;
542
+ igdb_slug?: string;
543
+ ra_id?: number;
544
+ moby_id?: number;
545
+ slug: string;
546
+ name: string;
547
+ /** Like Sony or Nintendo */
548
+ family_name?: string;
549
+ }
550
+
551
+ export interface DownloadFileEntry
552
+ {
553
+ url: URL;
554
+ /** The path of the file, excluding the name */
555
+ file_path: string;
556
+ /** Just the name of the file including the extension */
557
+ file_name: string;
558
+ /** Checksum of the file */
559
+ sha1?: string;
560
+ /** Size in bytes */
561
+ size?: number;
562
+ }
563
+
564
+ export interface LocalDownloadFileEntry extends DownloadFileEntry
565
+ {
566
+ /** Exists on the file system */
567
+ exists: boolean;
568
+ /** Matches the checksum */
569
+ matches: boolean;
570
+ }
571
+
572
+ export interface FrontEndCollection
573
+ {
574
+ id: FrontEndId;
575
+ name: string;
576
+ description: string;
577
+ path_platform_cover: string | null;
578
+ game_count: number;
579
+ }
580
+
581
+ export type EmulatorCapabilities = "saves" | "fullscreen" | "resolution" | "batch" | "states" | "config";
582
+
583
+ export interface EmulatorSupport
584
+ {
585
+ id: string;
586
+ source?: EmulatorSourceEntryType;
587
+ supportLevel?: "partial" | "full";
588
+ capabilities?: EmulatorCapabilities[];
589
+ }
590
+
591
+ export interface GameLookup
592
+ {
593
+ source: string;
594
+ id: string;
595
+ coverUrl: string | null | undefined;
596
+ slug: string | null | undefined;
597
+ screenshotUrls: string[];
598
+ name: string;
599
+ summary: string | null | undefined;
600
+ genres: string[];
601
+ companies: string[];
602
+ game_modes: string[];
603
+ age_ratings: string[];
604
+ player_count: string | undefined;
605
+ first_release_date: number | undefined;
606
+ average_rating: number | undefined;
607
+ keywords: string[];
608
+ igdb_id: number | undefined;
609
+ platforms: {
610
+ id: number;
611
+ name?: string | null;
612
+ displayName: string;
613
+ slug: string;
614
+ }[];
615
+ }
616
+
617
+ export interface AutoSaveChange
618
+ {
619
+ subPath: string;
620
+ cwd: string;
621
+ }
622
+
623
+ export type SaveSlots = Record<string, { cwd: string; }>;