mirror of
https://github.com/blitzkit/blitzkit.git
synced 2026-10-23 11:39:50 +02:00
feat: start of monorepo
This commit is contained in:
1 parent
14f39d71ac
commit
73c7bdf0c0
260 files changed
+1236
-1235
No files matched your search
@@ -0,0 +1,31 @@
|
||||
import { Region } from '../../constants/regions';
|
||||
|
||||
export const MIN_REGION_IDS: Record<Region, number> = {
|
||||
asia: 20e8,
|
||||
com: 10e8,
|
||||
eu: 5e8,
|
||||
};
|
||||
|
||||
export const MAX_REGION_IDS: Record<Region, number> = {
|
||||
asia: 31e8 - 1,
|
||||
com: MIN_REGION_IDS.asia - 1,
|
||||
eu: MIN_REGION_IDS.com - 1,
|
||||
};
|
||||
|
||||
export function idToRegion(id: number): Region {
|
||||
if (id >= 42e8) {
|
||||
throw new Error('bot id');
|
||||
} else if (id >= 31e8) {
|
||||
throw new Error('china id');
|
||||
} else if (id >= 20e8) {
|
||||
return 'asia';
|
||||
} else if (id >= 10e8) {
|
||||
return 'com';
|
||||
} else if (id >= 5e8) {
|
||||
return 'eu';
|
||||
} else if (id >= 0) {
|
||||
throw new Error('ru id');
|
||||
} else {
|
||||
throw new Error(`id ${id} is out of range`);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
export * from './idToRegion';
|
||||
@@ -0,0 +1,4 @@
|
||||
export function assertSecret(secret?: string) {
|
||||
if (secret === undefined) throw new Error('Missing secret');
|
||||
return secret;
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
import { asset } from '../../../../src/core/blitzkit/asset';
|
||||
import { fetchCdonLz4 } from '../../../../src/core/blitzkit/fetchCdonLz4';
|
||||
|
||||
interface GameMode {
|
||||
name: string;
|
||||
}
|
||||
|
||||
export interface GameDefinitions {
|
||||
version: string;
|
||||
nations: string[];
|
||||
gameModes: Record<number, GameMode>;
|
||||
roles: Record<
|
||||
number,
|
||||
{
|
||||
provisions: number[];
|
||||
consumables: number[];
|
||||
}
|
||||
>;
|
||||
}
|
||||
|
||||
export const gameDefinitions = fetchCdonLz4<GameDefinitions>(
|
||||
asset('definitions/game.cdon.lz4'),
|
||||
);
|
||||
@@ -0,0 +1,4 @@
|
||||
export * from './assertSecret';
|
||||
export * from './gameDefinitions';
|
||||
export * from './superCompress';
|
||||
export * from './superDecompress';
|
||||
@@ -0,0 +1,8 @@
|
||||
import { compress } from 'lz4js';
|
||||
import { CdonWriteStream } from '../../../../src/core/streams/cdon';
|
||||
|
||||
export function superCompress(object: any) {
|
||||
const write = new CdonWriteStream().cdon(object);
|
||||
const compressed = compress(write.uint8Array);
|
||||
return Buffer.from(compressed).toString('base64');
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
import { decompress } from 'lz4js';
|
||||
import { CdonReadStream } from '../../../../src/core/streams/cdon';
|
||||
|
||||
export function superDecompress<Type>(buffer: ArrayBuffer) {
|
||||
const decompressed = decompress(new Uint8Array(buffer)).buffer as ArrayBuffer;
|
||||
const read = new CdonReadStream(decompressed);
|
||||
return read.cdon() as Type;
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
export enum ImgurSize {
|
||||
/**
|
||||
* The default size
|
||||
*/
|
||||
Default = '',
|
||||
/**
|
||||
* Unknown size but really really small
|
||||
*/
|
||||
UltraSmall = 'ss',
|
||||
/**
|
||||
* 90x90
|
||||
*/
|
||||
SmallSquare = 's',
|
||||
/**
|
||||
* 160x160
|
||||
*/
|
||||
BigSquare = 'b',
|
||||
/**
|
||||
* 160x160
|
||||
*/
|
||||
SmallThumbnail = 't',
|
||||
/**
|
||||
* 320x320
|
||||
*/
|
||||
MediumThumbnail = 'm',
|
||||
/**
|
||||
* 640x640
|
||||
*/
|
||||
LargeThumbnail = 'l',
|
||||
/**
|
||||
* 1024x1024
|
||||
*/
|
||||
HugeThumbnail = 'h',
|
||||
}
|
||||
|
||||
interface ImgurOptions {
|
||||
format: 'jpeg' | 'png';
|
||||
size: ImgurSize;
|
||||
}
|
||||
|
||||
const defaultImgurOptions: ImgurOptions = {
|
||||
format: 'png',
|
||||
size: ImgurSize.Default,
|
||||
};
|
||||
|
||||
export function imgur(id: string, imgurOptions?: Partial<ImgurOptions>) {
|
||||
const options = { ...defaultImgurOptions, ...imgurOptions };
|
||||
|
||||
return `https://i.imgur.com/${id}${options.size}.${options.format}`;
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
export * from './imgur';
|
||||
@@ -0,0 +1,5 @@
|
||||
export * from './blitz';
|
||||
export * from './blitzkit';
|
||||
export * from './imgur';
|
||||
export * from './patreon';
|
||||
export * from './zustand';
|
||||
@@ -0,0 +1 @@
|
||||
export * from './patreonLoginUrl';
|
||||
@@ -0,0 +1,12 @@
|
||||
import { assertSecret } from '../blitzkit/assertSecret';
|
||||
|
||||
export function patreonLoginUrl() {
|
||||
const params = new URLSearchParams({
|
||||
response_type: 'code',
|
||||
client_id: assertSecret(process.env.NEXT_PUBLIC_PATREON_CLIENT_ID),
|
||||
redirect_uri: assertSecret(process.env.NEXT_PUBLIC_PATREON_REDIRECT_URI),
|
||||
scope: 'identity',
|
||||
});
|
||||
|
||||
return `https://www.patreon.com/oauth2/authorize?${params}`;
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
import { Draft, produce } from 'immer';
|
||||
import {
|
||||
createContext,
|
||||
ReactNode,
|
||||
useContext,
|
||||
useEffect,
|
||||
useRef,
|
||||
useState,
|
||||
} from 'react';
|
||||
import { StoreApi, useStore as useStoreZustand } from 'zustand';
|
||||
|
||||
type StoreProviderProps<InitData> = {
|
||||
children: ReactNode;
|
||||
} & (InitData extends unknown ? { data?: InitData } : { data: InitData });
|
||||
|
||||
// idk why zustand doesn't export this
|
||||
type ExtractState<S> = S extends {
|
||||
getState: () => infer T;
|
||||
}
|
||||
? T
|
||||
: never;
|
||||
|
||||
export function createNextSafeStore<Store extends StoreApi<unknown>, InitData>(
|
||||
initialize: (data: InitData) => Store,
|
||||
) {
|
||||
type Type = Store extends StoreApi<infer T> ? T : never;
|
||||
|
||||
const Context = createContext<Store | undefined>(undefined);
|
||||
|
||||
function Provider(props: StoreProviderProps<InitData>) {
|
||||
const storeRef = useRef<Store>();
|
||||
if (!storeRef.current) {
|
||||
storeRef.current = initialize((props as { data: InitData }).data);
|
||||
}
|
||||
|
||||
return (
|
||||
<Context.Provider value={storeRef.current}>
|
||||
{props.children}
|
||||
</Context.Provider>
|
||||
);
|
||||
}
|
||||
|
||||
function useStore() {
|
||||
const store = useContext(Context);
|
||||
if (!store) throw new Error('useStore must be used within Provider');
|
||||
return store as Store;
|
||||
}
|
||||
|
||||
function use<Slice = Type>(
|
||||
selector: (store: Type) => Slice = (state) => state as Slice,
|
||||
) {
|
||||
const store = useStore();
|
||||
return useStoreZustand(
|
||||
store,
|
||||
selector as (state: ExtractState<Store>) => Slice,
|
||||
);
|
||||
}
|
||||
|
||||
function useDeferred<Slice = Type>(
|
||||
initial: Slice,
|
||||
selector: (store: Type) => Slice = (state) => state as Slice,
|
||||
) {
|
||||
const [state, setState] = useState(initial);
|
||||
const trueState = use(selector);
|
||||
|
||||
useEffect(() => {
|
||||
setState(trueState);
|
||||
}, [trueState]);
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
function useMutation() {
|
||||
const counterStoreContext = useStore();
|
||||
|
||||
return function (recipe: (draft: Draft<Type>) => void) {
|
||||
counterStoreContext.setState(
|
||||
produce<Type>((draft) => {
|
||||
recipe(draft);
|
||||
}),
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
return { Provider, use, useMutation, useStore, useDeferred };
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
export * from './createNextSafeStore';
|
||||
Reference in new issue
Block a user