mirror of
https://github.com/blitzkit/blitzkit.git
synced 2026-10-24 12:09:51 +02:00
feat: remote catalog
This commit is contained in:
1 parent
e7386ff766
commit
5e9aa99755
17 files changed
+109
-67
No files matched your search
+1
-1
@@ -1,7 +1,7 @@
|
|||||||
node_modules
|
node_modules
|
||||||
_node_modules
|
_node_modules
|
||||||
package-lock.json
|
package-lock.json
|
||||||
.env
|
*.env
|
||||||
/test-results/
|
/test-results/
|
||||||
/playwright-report/
|
/playwright-report/
|
||||||
/playwright/.cache/
|
/playwright/.cache/
|
||||||
|
|||||||
@@ -95,13 +95,11 @@
|
|||||||
"urlon": "^3.1.0",
|
"urlon": "^3.1.0",
|
||||||
"zustand": "^4.5.5",
|
"zustand": "^4.5.5",
|
||||||
"@types/bun": "latest",
|
"@types/bun": "latest",
|
||||||
"@types/lodash-es": "^4.17.12",
|
|
||||||
"@types/node": "^22.14.1",
|
"@types/node": "^22.14.1",
|
||||||
"prettier": "^3.5.3",
|
"prettier": "^3.5.3",
|
||||||
"prisma": "^6.6.0",
|
"prisma": "^6.6.0",
|
||||||
"typescript": "^5.8.3",
|
"typescript": "^5.8.3",
|
||||||
"googleapis": "^144.0.0",
|
"googleapis": "^144.0.0",
|
||||||
"lodash-es": "^4.17.21",
|
|
||||||
"protobufjs": "^7.5.2",
|
"protobufjs": "^7.5.2",
|
||||||
"quicklime": "^1.2.0",
|
"quicklime": "^1.2.0",
|
||||||
"sharp": "^0.33.5"
|
"sharp": "^0.33.5"
|
||||||
|
|||||||
+18
-30
@@ -1,15 +1,14 @@
|
|||||||
import { CatalogItem } from '@protos/blitz_items';
|
import { CatalogItem } from '@protos/blitz_items';
|
||||||
import { Metadata } from '@protos/blitz_metadata';
|
|
||||||
import { CatalogItemsComponent } from '@protos/blitz_static_catalog_items_group_component';
|
import { CatalogItemsComponent } from '@protos/blitz_static_catalog_items_group_component';
|
||||||
import { BlitzKitAllTankEntities } from '@protos/blitzkit_static_all_tank_entities';
|
import { BlitzkitAllTanksComponent } from '@protos/blitzkit_static_all_tanks_component';
|
||||||
import { BlitzKitTankCatalogComponent } from '@protos/blitzkit_static_tank_component';
|
import { BlitzKitTankCatalogComponent } from '@protos/blitzkit_static_tank_component';
|
||||||
import { CatalogItemAccessor } from './catalogItemAccessor';
|
import { CatalogItemAccessor } from './catalogItemAccessor';
|
||||||
|
|
||||||
export class UnpackedMetadataAccessor {
|
export class CatalogAccessor {
|
||||||
items: Record<string, CatalogItemAccessor> = {};
|
items: Record<string, CatalogItemAccessor> = {};
|
||||||
|
|
||||||
constructor(metadata: Metadata) {
|
constructor(catalogItems: CatalogItem[]) {
|
||||||
for (const item of metadata.catalog_items) {
|
for (const item of catalogItems) {
|
||||||
if (item.catalog_id in this.items) {
|
if (item.catalog_id in this.items) {
|
||||||
throw new Error(`Duplicate catalog ID: ${item.catalog_id}`);
|
throw new Error(`Duplicate catalog ID: ${item.catalog_id}`);
|
||||||
}
|
}
|
||||||
@@ -20,29 +19,14 @@ export class UnpackedMetadataAccessor {
|
|||||||
|
|
||||||
get(item: string) {
|
get(item: string) {
|
||||||
if (item in this.items) return this.items[item];
|
if (item in this.items) return this.items[item];
|
||||||
|
|
||||||
throw new Error(`Unknown catalog ID: ${item}`);
|
throw new Error(`Unknown catalog ID: ${item}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
addCatalogItem(item: CatalogItemAccessor) {
|
add(item: CatalogItemAccessor) {
|
||||||
this.items[item.id] = item;
|
this.items[item.id] = item;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
addCatalogItemWithComponent(
|
|
||||||
catalogId: string,
|
|
||||||
componentId: string,
|
|
||||||
url: string,
|
|
||||||
value: Uint8Array,
|
|
||||||
) {
|
|
||||||
this.addCatalogItem(
|
|
||||||
new CatalogItemAccessor({
|
|
||||||
catalog_id: catalogId,
|
|
||||||
components: [],
|
|
||||||
}).addComponent(componentId, { type_url: url, value }),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
getAllTanks() {
|
getAllTanks() {
|
||||||
return this.get('CatalogItemsGroupEntity.all_tanks').get(
|
return this.get('CatalogItemsGroupEntity.all_tanks').get(
|
||||||
CatalogItemsComponent,
|
CatalogItemsComponent,
|
||||||
@@ -52,7 +36,7 @@ export class UnpackedMetadataAccessor {
|
|||||||
|
|
||||||
injectBlitzkit() {
|
injectBlitzkit() {
|
||||||
this.injectBlitzKitTankComponents();
|
this.injectBlitzKitTankComponents();
|
||||||
this.injectBlitzKitAllTankEntities();
|
this.injectBlitzKitAllTanksEntity();
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
@@ -73,23 +57,27 @@ export class UnpackedMetadataAccessor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
injectBlitzKitAllTankEntities() {
|
injectBlitzKitAllTanksEntity() {
|
||||||
const allTanksEntities: BlitzKitAllTankEntities = { tanks: [] };
|
const allTanksEntities: BlitzkitAllTanksComponent = { tanks: [] };
|
||||||
|
|
||||||
for (const item of this.getAllTanks().catalog_items) {
|
for (const item of this.getAllTanks().catalog_items) {
|
||||||
allTanksEntities.tanks.push(this.get(item).pack());
|
allTanksEntities.tanks.push(this.get(item).pack());
|
||||||
}
|
}
|
||||||
|
|
||||||
this.addCatalogItemWithComponent(
|
this.add(
|
||||||
'BlitzKitAllTankEntities.all_tanks',
|
CatalogItemAccessor.fromComponent(
|
||||||
'blitzkitAllTankEntitiesComponent',
|
'BlitzKitAllTanksEntity.blitzkit_all_tanks',
|
||||||
'./blitzkit_static_all_tank_entities.BlitzKitAllTankEntities',
|
{
|
||||||
BlitzKitAllTankEntities.encode(allTanksEntities).finish(),
|
type_url:
|
||||||
|
'./blitzkit_static_all_tanks_component.BlitzkitAllTanksComponent',
|
||||||
|
value: BlitzkitAllTanksComponent.encode(allTanksEntities).finish(),
|
||||||
|
},
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class DiscreteMetadataAccessor {
|
export class RemoteCatalogAccessor {
|
||||||
constructor(private base: string) {}
|
constructor(private base: string) {}
|
||||||
|
|
||||||
async get(item: string) {
|
async get(item: string) {
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
import { CatalogItem } from '@protos/blitz_items';
|
import { CatalogItem } from '@protos/blitz_items';
|
||||||
import { Any } from '@protos/google/protobuf/any';
|
import { Any } from '@protos/google/protobuf/any';
|
||||||
|
import { lowerFirst } from 'lodash-es';
|
||||||
import { MessageFns } from '../protos';
|
import { MessageFns } from '../protos';
|
||||||
|
|
||||||
export class CatalogItemAccessor {
|
export class CatalogItemAccessor {
|
||||||
@@ -21,6 +22,22 @@ export class CatalogItemAccessor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static fromComponent(id: string, component: Any) {
|
||||||
|
return this.fromComponents(id, [component]);
|
||||||
|
}
|
||||||
|
|
||||||
|
static fromComponents(id: string, components: Any[]) {
|
||||||
|
return new CatalogItemAccessor({
|
||||||
|
catalog_id: id,
|
||||||
|
components: components.map((component) => ({
|
||||||
|
key: lowerFirst(
|
||||||
|
component.type_url.slice(2).split('.').slice(1).join('.'),
|
||||||
|
),
|
||||||
|
value: { type_url: component.type_url, component },
|
||||||
|
})),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
addComponent(key: string, value: Any) {
|
addComponent(key: string, value: Any) {
|
||||||
this.components[key] = value;
|
this.components[key] = value;
|
||||||
return this;
|
return this;
|
||||||
@@ -48,4 +65,8 @@ export class CatalogItemAccessor {
|
|||||||
|
|
||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
encode() {
|
||||||
|
return CatalogItem.encode(this.pack()).finish();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
export * from './canSplash';
|
export * from './canSplash';
|
||||||
export * from './catalogItemAccessor';
|
export * from './catalogAccessor';
|
||||||
export * from './clans';
|
export * from './clans';
|
||||||
export * from './classes';
|
export * from './classes';
|
||||||
export * from './constants';
|
export * from './constants';
|
||||||
@@ -19,7 +19,6 @@ export * from './getTankStats';
|
|||||||
export * from './idToRegion';
|
export * from './idToRegion';
|
||||||
export * from './isOnGoingRatingSeason';
|
export * from './isOnGoingRatingSeason';
|
||||||
export * from './isValidBlitzId';
|
export * from './isValidBlitzId';
|
||||||
export * from './metadataAccessor';
|
|
||||||
export * from './nations';
|
export * from './nations';
|
||||||
export * from './normalizeExtra';
|
export * from './normalizeExtra';
|
||||||
export * from './normalizeIds';
|
export * from './normalizeIds';
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"extends": "../../tsconfig.json",
|
"extends": "../../tsconfig.json",
|
||||||
"include": ["src/**/*", "../i18n/src/strings.ts"],
|
"include": ["src/**/*"],
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"baseUrl": "../../"
|
"baseUrl": "../../"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,4 +7,5 @@ import react from '@astrojs/react';
|
|||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
integrations: [react()],
|
integrations: [react()],
|
||||||
devToolbar: { enabled: false },
|
devToolbar: { enabled: false },
|
||||||
|
site: 'https://blitzkit.app',
|
||||||
});
|
});
|
||||||
@@ -19,6 +19,8 @@
|
|||||||
"@types/react-dom": "^19.1.5",
|
"@types/react-dom": "^19.1.5",
|
||||||
"astro": "^5.8.0",
|
"astro": "^5.8.0",
|
||||||
"react": "^19.1.0",
|
"react": "^19.1.0",
|
||||||
"react-dom": "^19.1.0"
|
"react-dom": "^19.1.0",
|
||||||
|
"@types/lodash-es": "^4.17.12",
|
||||||
|
"lodash-es": "^4.17.21"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
import { fetchMetadata } from '@blitzkit/closed';
|
||||||
|
import { CatalogAccessor } from 'packages/core/src';
|
||||||
|
|
||||||
|
export const catalog = new CatalogAccessor(
|
||||||
|
await fetchMetadata().then((data) => data.catalog_items),
|
||||||
|
).injectBlitzkit();
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
import { DiscreteMetadataAccessor } from 'packages/core/src';
|
|
||||||
|
|
||||||
export const discreteMetadata = new DiscreteMetadataAccessor('/api/catalog');
|
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
import { RemoteCatalogAccessor } from 'packages/core/src';
|
||||||
|
import { api } from '../blitzkit/api';
|
||||||
|
|
||||||
|
export const remoteCatalog = new RemoteCatalogAccessor(api('catalog'));
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
import { requestAutoProxyClient, unpackMetadata } from '@blitzkit/closed';
|
|
||||||
import type { GetPackedMetadataAsyncResponse } from '@blitzkit/closed/src/unreal/protos/auto_legacy_proxy_client';
|
|
||||||
import { UnpackedMetadataAccessor } from 'packages/core/src';
|
|
||||||
|
|
||||||
export const unpackedMetadata = new UnpackedMetadataAccessor(
|
|
||||||
await requestAutoProxyClient<GetPackedMetadataAsyncResponse>(
|
|
||||||
'GetPackedMetadataAsyncRequest',
|
|
||||||
).then(unpackMetadata),
|
|
||||||
).injectBlitzkit();
|
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
let base: string;
|
||||||
|
|
||||||
|
if (import.meta.env.DEV) {
|
||||||
|
base = 'http://localhost:4321';
|
||||||
|
} else {
|
||||||
|
base = import.meta.env.SITE;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function api(path: string) {
|
||||||
|
return `${base}/api/${path}`;
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
import { TankCatalogComponent } from '@protos/blitz_static_tank_component';
|
||||||
|
import { BlitzkitAllTanksComponent } from '@protos/blitzkit_static_all_tanks_component';
|
||||||
|
import { CatalogAccessor } from 'packages/core/src';
|
||||||
|
import { remoteCatalog } from 'packages/website-ue/src/core/blitz/remoteCatalog';
|
||||||
|
|
||||||
|
const data = await remoteCatalog
|
||||||
|
.get('BlitzKitAllTanksEntity.blitzkit_all_tanks')
|
||||||
|
.then((components) =>
|
||||||
|
components.get(BlitzkitAllTanksComponent, 'blitzkitAllTanksComponent'),
|
||||||
|
);
|
||||||
|
|
||||||
|
export function Page() {
|
||||||
|
const tankCatalog = new CatalogAccessor(data.tanks);
|
||||||
|
|
||||||
|
const content = tankCatalog
|
||||||
|
.get('TankEntity.A92_M60')
|
||||||
|
.get(TankCatalogComponent, 'tankCatalogComponent');
|
||||||
|
|
||||||
|
return <pre children={JSON.stringify(content, null, 2)} />;
|
||||||
|
}
|
||||||
@@ -1,23 +1,9 @@
|
|||||||
---
|
---
|
||||||
import { CatalogItemsComponent } from '@protos/blitz_static_catalog_items_group_component';
|
import { Page } from './_index';
|
||||||
import { BlitzKitAllTankEntities } from '@protos/blitzkit_static_all_tank_entities';
|
|
||||||
import { unpackedMetadata } from '../../../core/blitz/unpackedMetadata';
|
|
||||||
export { getStaticPaths } from '../index.astro';
|
export { getStaticPaths } from '../index.astro';
|
||||||
|
|
||||||
const { locale } = Astro.props;
|
const { locale } = Astro.props;
|
||||||
|
|
||||||
const allTanks = unpackedMetadata
|
|
||||||
.get('CatalogItemsGroupEntity.all_tanks')
|
|
||||||
.get(CatalogItemsComponent, 'catalogItemsGroupComponent');
|
|
||||||
|
|
||||||
const allTankEntities = unpackedMetadata
|
|
||||||
.get('BlitzKitAllTankEntities.all_tanks')
|
|
||||||
.get(BlitzKitAllTankEntities, 'blitzkitAllTankEntitiesComponent');
|
|
||||||
---
|
---
|
||||||
|
|
||||||
<pre>
|
<Page client:load />
|
||||||
{JSON.stringify(allTankEntities.tanks.map(tank=>({
|
|
||||||
tank: tank.catalog_id,
|
|
||||||
components: tank.components.map(component=>component.key)
|
|
||||||
})), null, 2)}
|
|
||||||
</pre>
|
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
import type { APIRoute, GetStaticPaths, GetStaticPathsItem } from 'astro';
|
||||||
|
import { catalog } from 'packages/website-ue/src/core/blitz/catalog';
|
||||||
|
|
||||||
|
export const getStaticPaths: GetStaticPaths = () => {
|
||||||
|
const paths: GetStaticPathsItem[] = [];
|
||||||
|
|
||||||
|
for (const item in catalog.items) {
|
||||||
|
paths.push({ params: { item } });
|
||||||
|
}
|
||||||
|
|
||||||
|
return paths;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const GET: APIRoute<{}, { item: string }> = ({ params }) => {
|
||||||
|
return new Response(catalog.get(params.item).encode(), {
|
||||||
|
headers: { 'Content-Type': 'application/octet-stream' },
|
||||||
|
});
|
||||||
|
};
|
||||||
Submodule submodules/blitzkit-closed updated: 0ce4f61818...add1ddf247.
Reference in new issue
Block a user