feat: api

This commit is contained in:
TrèsAbhi committed 2025-06-03 20:31:53 -05:00
1 parent 2dc4f12246
commit 7e11c1e5ce
26 files changed
+149 -866

No files matched your search

+2 -1
View File
@@ -6,6 +6,7 @@
"dependencies": {
"@types/js-yaml": "^4.0.9",
"js-yaml": "^4.1.0",
"ts-proto": "^2.2.2"
"ts-proto": "^2.2.2",
"@blitzkit/closed": "workspace:*"
}
}
@@ -1,9 +1,7 @@
import { CatalogItem } from '@protos/blitz_items';
import { Metadata } from '@protos/blitz_metadata';
import { LocalizationResourcesComponent } from '@protos/blitz_static_localization_resources_component';
import { ProfileAvatarComponent } from '@protos/blitz_static_profile_avatar_component';
import { RemoteStorageComponent } from '@protos/blitz_static_remote_storage_component';
import { SellableComponent } from '@protos/blitz_static_sellable_component';
import { StuffUIComponent } from '@protos/blitz_static_stuff_ui_component';
import { BlitzkitAllAvatarsComponent } from '@protos/blitzkit_static_all_avatars_component';
import { load } from 'js-yaml';
import { minimatch } from 'minimatch';
import { CatalogItemAccessor } from 'packages/core/src/blitz/catalogItemAccessor';
@@ -12,12 +10,35 @@ interface LocalizationConfig {
namespaces: string[];
}
export abstract class MetadataAccessor {
abstract get(item: string): Promise<CatalogItemAccessor>;
export class MetadataAccessor {
items: Record<string, CatalogItem> = {};
abstract add(item: CatalogItemAccessor): void;
constructor(metadata: Metadata) {
for (const item of metadata.catalog_items) {
this.items[item.catalog_id] = item;
}
}
abstract filter(predicate: (item: string) => boolean): CatalogItemAccessor[];
get(item: string) {
if (item in this.items) return new CatalogItemAccessor(this.items[item]);
throw new Error(`Item ${item} does not exist in socket metadata`);
}
add(item: CatalogItemAccessor) {
this.items[item.id] = item.pack();
}
filter(predicate: (item: string) => boolean) {
const items: CatalogItemAccessor[] = [];
for (const item in this.items) {
if (predicate(item)) {
items.push(new CatalogItemAccessor(this.items[item]));
}
}
return items;
}
async strings(locale: string) {
const clientConfig = await this.get(
@@ -97,44 +118,4 @@ export abstract class MetadataAccessor {
return filtered;
}
injectBlitzkit() {
this.injectBlitzkitProfileAvatars();
return this;
}
injectBlitzkitProfileAvatars() {
const allAvatars: BlitzkitAllAvatarsComponent = { avatars: [] };
for (const item of this.filter((item) =>
item.startsWith('ProfileAvatarEntity.'),
)) {
const stuff = item.get(StuffUIComponent, 'UIComponent');
const avatar = item.get(ProfileAvatarComponent, 'profileAvatarComponent');
const sellable = item.getOptional(SellableComponent, 'sellableComponent');
allAvatars.avatars.push({
id: item.undiscriminatedId(),
name: stuff.display_name,
obtaining: stuff.obtaining_methods,
description: stuff.description,
grade: stuff.grade,
category: avatar.category,
hidden_if_not_obtained: avatar.hidden_if_not_obtained,
sale: sellable?.reward,
});
}
this.add(
CatalogItemAccessor.fromComponent(
'BlitzkitAllAvatarsEntity.blitzkit_all_avatars',
{
type_url:
'./blitzkit_static_all_avatars_component.BlitzkitAllAvatarsComponent',
value: BlitzkitAllAvatarsComponent.encode(allAvatars).finish(),
},
),
);
}
}
@@ -1,3 +0,0 @@
export * from './abstract';
export * from './remote';
export * from './socket';
@@ -1,30 +0,0 @@
import { CatalogItem } from '@protos/blitz_items';
import { CatalogItemAccessor } from '../catalogItemAccessor';
import { MetadataAccessor } from './abstract';
export class RemoteMetadataAccessor extends MetadataAccessor {
constructor(private base: string) {
super();
}
async get(item: string) {
const response = await fetch(`${this.base}/${item}.pb`);
if (!response.ok) {
throw new Error(`Item ${item} does not exist in remote metadata`);
}
const buffer = new Uint8Array(await response.arrayBuffer());
const catalogItem = CatalogItem.decode(buffer);
return new CatalogItemAccessor(catalogItem);
}
add() {
throw new Error('Cannot add items to remote metadata');
}
filter(): CatalogItemAccessor[] {
throw new Error('Cannot filter remote metadata');
}
}
@@ -1,37 +0,0 @@
import { CatalogItem } from '@protos/blitz_items';
import { Metadata } from '@protos/blitz_metadata';
import { CatalogItemAccessor } from '../catalogItemAccessor';
import { MetadataAccessor } from './abstract';
export class SocketMetadataAccessor extends MetadataAccessor {
items: Record<string, CatalogItem> = {};
constructor(metadata: Metadata) {
super();
for (const item of metadata.catalog_items) {
this.items[item.catalog_id] = item;
}
}
async get(item: string) {
if (item in this.items) return new CatalogItemAccessor(this.items[item]);
throw new Error(`Item ${item} does not exist in socket metadata`);
}
add(item: CatalogItemAccessor) {
this.items[item.id] = item.pack();
}
filter(predicate: (item: string) => boolean) {
const items: CatalogItemAccessor[] = [];
for (const item in this.items) {
if (predicate(item)) {
items.push(new CatalogItemAccessor(this.items[item]));
}
}
return items;
}
}
@@ -0,0 +1,8 @@
import { BlitzKitAvatars } from '@protos/blitzkit';
import { MetadataAccessor } from '../../blitz/metadata';
export abstract class BlitzkitAPI {
abstract metadata: MetadataAccessor;
abstract avatars(): Promise<BlitzKitAvatars>;
}
+15
View File
@@ -0,0 +1,15 @@
import { BlitzKitAvatars } from '@protos/blitzkit';
import { MetadataAccessor } from '../../blitz/metadata';
import { BlitzkitAPI } from './abstract';
export class BlitzkitClientAPI extends BlitzkitAPI {
get metadata(): MetadataAccessor {
throw new Error('Cannot access metadata from client');
}
async avatars() {
const response = await fetch('/api/internal/avatars.pb');
const buffer = await response.arrayBuffer();
return BlitzKitAvatars.decode(new Uint8Array(buffer));
}
}
+3
View File
@@ -0,0 +1,3 @@
export * from './abstract';
export * from './client';
export * from './server';
+37
View File
@@ -0,0 +1,37 @@
import { ProfileAvatarComponent } from '@protos/blitz_static_profile_avatar_component';
import { SellableComponent } from '@protos/blitz_static_sellable_component';
import { StuffUIComponent } from '@protos/blitz_static_stuff_ui_component';
import { BlitzKitAvatars } from '@protos/blitzkit';
import { BlitzkitAPI } from '.';
import { MetadataAccessor } from '../../blitz/metadata';
export class BlitzkitServerAPI extends BlitzkitAPI {
constructor(public metadata: MetadataAccessor) {
super();
}
async avatars() {
const avatars: BlitzKitAvatars = { avatars: [] };
for (const item of this.metadata.filter((item) =>
item.startsWith('ProfileAvatarEntity.'),
)) {
const stuff = item.get(StuffUIComponent, 'UIComponent');
const avatar = item.get(ProfileAvatarComponent, 'profileAvatarComponent');
const sellable = item.getOptional(SellableComponent, 'sellableComponent');
avatars.avatars.push({
id: item.undiscriminatedId(),
name: stuff.display_name,
obtaining: stuff.obtaining_methods,
description: stuff.description,
grade: stuff.grade,
category: avatar.category,
hidden_if_not_obtained: avatar.hidden_if_not_obtained,
sale: sellable?.reward,
});
}
return avatars;
}
}
+1
View File
@@ -41,6 +41,7 @@ export * from './uniqueGuns';
export * from './unwrapBlitzkitResponse';
export * from './votes';
// export * from './withCORSProxy';
export * from './api';
export * from './createDefaultProvisions';
export * from './gallery';
export * from './metaSortTank';