feat: start of monorepo

This commit is contained in:
TrèsAbhi committed 2024-09-06 21:45:58 -05:00
1 parent 14f39d71ac
commit 73c7bdf0c0
260 files changed
+1236 -1235

No files matched your search

+31
View File
@@ -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`);
}
}
+1
View File
@@ -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'),
);
+4
View File
@@ -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;
}
+50
View File
@@ -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}`;
}
+1
View File
@@ -0,0 +1 @@
export * from './imgur';
+5
View File
@@ -0,0 +1,5 @@
export * from './blitz';
export * from './blitzkit';
export * from './imgur';
export * from './patreon';
export * from './zustand';
+1
View File
@@ -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 };
}
+1
View File
@@ -0,0 +1 @@
export * from './createNextSafeStore';