파일 위치 이동
This commit is contained in:
@@ -0,0 +1,27 @@
|
|||||||
|
{
|
||||||
|
"name": "@sammo/api_def",
|
||||||
|
"version": "1.0.1",
|
||||||
|
"description": "",
|
||||||
|
"main": "dist/index.js",
|
||||||
|
"exports": {
|
||||||
|
".": "./dist/index.js",
|
||||||
|
"./gateway": "./dist/gateway.js",
|
||||||
|
"./def": "./dist/def/index.js"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"build": "tsc --build"
|
||||||
|
},
|
||||||
|
"author": "",
|
||||||
|
"type": "module",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@sammo/util": "workspace:^",
|
||||||
|
"@strpc/def": "workspace:^"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"zod": "^3.22.2"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"zod": "^3.22.2"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 4.2 KiB |
|
Before Width: | Height: | Size: 276 B After Width: | Height: | Size: 276 B |
@@ -4,7 +4,7 @@ import { createApp } from 'vue'
|
|||||||
import { createPinia } from 'pinia'
|
import { createPinia } from 'pinia'
|
||||||
|
|
||||||
import App from './App.vue'
|
import App from './App.vue'
|
||||||
import router from './router'
|
import router from './router/index.js'
|
||||||
|
|
||||||
const app = createApp(App)
|
const app = createApp(App)
|
||||||
|
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
{
|
||||||
|
"extends": "../../tsconfig.base.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"rootDir": "./src",
|
||||||
|
"outDir": "./dist",
|
||||||
|
},
|
||||||
|
"references": [
|
||||||
|
{
|
||||||
|
|
||||||
|
"path": "../util"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "../secure_token"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "../../@strpc/def"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
{
|
||||||
|
"name": "@sammo/game_logic",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "",
|
||||||
|
"main": "dist/index.js",
|
||||||
|
"scripts": {
|
||||||
|
"build": "tsc --build"
|
||||||
|
},
|
||||||
|
"author": "",
|
||||||
|
"type": "module",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@sammo/api_def": "workspace:^",
|
||||||
|
"@sammo/server_util": "workspace:^",
|
||||||
|
"@sammo/util": "workspace:^",
|
||||||
|
"@strpc/express": "workspace:^",
|
||||||
|
"dotenv": "^16.3.1",
|
||||||
|
"mongoose": "^7.4.3"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@types/node": "^20.6.3"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
export * from "./generalStats.js";
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
{
|
||||||
|
"extends": "../../tsconfig.base.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"rootDir": "./src",
|
||||||
|
"outDir": "./dist",
|
||||||
|
},
|
||||||
|
"references": [
|
||||||
|
{
|
||||||
|
"path": "../../@strpc/express"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "../util"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "../crypto"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "../server_util"
|
||||||
|
},
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -10,14 +10,26 @@
|
|||||||
"type": "module",
|
"type": "module",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@esfx/async-readerwriterlock": "^1.0.0",
|
||||||
"@sammo/api_def": "workspace:^",
|
"@sammo/api_def": "workspace:^",
|
||||||
|
"@sammo/game_logic": "workspace:^",
|
||||||
"@sammo/server_util": "workspace:^",
|
"@sammo/server_util": "workspace:^",
|
||||||
"@sammo/util": "workspace:^",
|
"@sammo/util": "workspace:^",
|
||||||
"@strpc/express": "workspace:^",
|
"@strpc/express": "workspace:^",
|
||||||
|
"date-fns": "^2.30.0",
|
||||||
"dotenv": "^16.3.1",
|
"dotenv": "^16.3.1",
|
||||||
"mongoose": "^7.4.3"
|
"eventemitter3": "^5.0.1",
|
||||||
|
"express": "^4.18.2",
|
||||||
|
"express-session": "^1.17.3",
|
||||||
|
"ky": "^1.0.1",
|
||||||
|
"lodash-es": "^4.17.21",
|
||||||
|
"mongoose": "^7.4.3",
|
||||||
|
"reflect-metadata": "^0.1.13",
|
||||||
|
"tslib": "^2.6.2",
|
||||||
|
"zod": "^3.22.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@sammo/gateway": "workspace:^",
|
||||||
"@types/node": "^20.6.3"
|
"@types/node": "^20.6.3"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
import type { structure } from "@sammo/api_def";
|
||||||
|
import type { APINamespaceType } from "@strpc/express";
|
||||||
|
|
||||||
|
export const sammoAPI = {
|
||||||
|
} satisfies APINamespaceType<typeof structure>;
|
||||||
@@ -1,21 +1,19 @@
|
|||||||
|
import './dotenv.js'
|
||||||
import 'reflect-metadata';
|
import 'reflect-metadata';
|
||||||
import connectDB from './connectDB.js';
|
import connectDB from './connectDB.js';
|
||||||
import express, { type Request, type Response } from "express"
|
import express, { type Request, type Response } from "express"
|
||||||
import session from "express-session";
|
import session from "express-session";
|
||||||
import path from 'node:path';
|
import { buildAPISystem } from '@strpc/express/generator';
|
||||||
import { LiteHashDRBG } from './util/LiteHashDRBG.js';
|
import { sammoAPI } from './api/index.js';
|
||||||
import { simpleSerialize } from './util/simpleSerialize.js';
|
import { unwrap } from '@sammo/util';;
|
||||||
import { buildAPISystem } from './api/generator.js';
|
import { serverConfig } from './serverConfig.js';
|
||||||
import { unwrap } from './util/unwrap.js';
|
|
||||||
import { sammoAPI } from './api/api.js';
|
|
||||||
import { ownConfig } from './serverConfig.js';
|
|
||||||
|
|
||||||
connectDB.then(async (db) => {
|
connectDB.then(async (db) => {
|
||||||
// create express app
|
// create express app
|
||||||
const app = express()
|
const app = express()
|
||||||
app.use(express.json());
|
app.use(express.json());
|
||||||
app.use(session({
|
app.use(session({
|
||||||
secret: unwrap(ownConfig.sessionSecret),
|
secret: unwrap(serverConfig.sessionSecret),
|
||||||
resave: false,
|
resave: false,
|
||||||
saveUninitialized: false,
|
saveUninitialized: false,
|
||||||
}))
|
}))
|
||||||
@@ -24,9 +22,9 @@ connectDB.then(async (db) => {
|
|||||||
app.use('/api', buildAPISystem(sammoAPI));
|
app.use('/api', buildAPISystem(sammoAPI));
|
||||||
|
|
||||||
// start express server
|
// start express server
|
||||||
app.listen(ownConfig.port)
|
app.listen(serverConfig.port)
|
||||||
|
|
||||||
console.log(`Express server has started on port ${ownConfig.port}`)
|
console.log(`Express server has started on port ${serverConfig.port}`)
|
||||||
|
|
||||||
}).catch(error => console.log(error));
|
}).catch(error => console.log(error));
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import 'dotenv/config';
|
import 'dotenv/config';
|
||||||
import { unwrap } from './util/unwrap.js';
|
import { unwrap } from '@sammo/util';
|
||||||
|
|
||||||
export const ownConfig = {
|
export const serverConfig = {
|
||||||
sessionSecret: unwrap(process.env.SESSION_SECRET),
|
sessionSecret: unwrap(process.env.SESSION_SECRET),
|
||||||
port: Number(unwrap(process.env.SERVER_PORT)),
|
port: Number(unwrap(process.env.SERVER_PORT)),
|
||||||
gatewayHost: unwrap(process.env.GATEWAY_HOST),
|
gatewayHost: unwrap(process.env.GATEWAY_HOST),
|
||||||
|
|||||||
Generated
+86
-3
@@ -210,6 +210,31 @@ importers:
|
|||||||
specifier: ^5.2.2
|
specifier: ^5.2.2
|
||||||
version: 5.2.2
|
version: 5.2.2
|
||||||
|
|
||||||
|
'@sammo/game_logic':
|
||||||
|
dependencies:
|
||||||
|
'@sammo/api_def':
|
||||||
|
specifier: workspace:^
|
||||||
|
version: link:../api_def
|
||||||
|
'@sammo/server_util':
|
||||||
|
specifier: workspace:^
|
||||||
|
version: link:../server_util
|
||||||
|
'@sammo/util':
|
||||||
|
specifier: workspace:^
|
||||||
|
version: link:../util
|
||||||
|
'@strpc/express':
|
||||||
|
specifier: workspace:^
|
||||||
|
version: link:../../@strpc/express
|
||||||
|
dotenv:
|
||||||
|
specifier: ^16.3.1
|
||||||
|
version: 16.3.1
|
||||||
|
mongoose:
|
||||||
|
specifier: ^7.4.3
|
||||||
|
version: 7.4.3
|
||||||
|
devDependencies:
|
||||||
|
'@types/node':
|
||||||
|
specifier: ^20.6.3
|
||||||
|
version: 20.6.3
|
||||||
|
|
||||||
'@sammo/gateway':
|
'@sammo/gateway':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@sammo/api_def':
|
'@sammo/api_def':
|
||||||
@@ -254,6 +279,67 @@ importers:
|
|||||||
specifier: ^3.22.2
|
specifier: ^3.22.2
|
||||||
version: 3.22.2
|
version: 3.22.2
|
||||||
|
|
||||||
|
'@sammo/server':
|
||||||
|
dependencies:
|
||||||
|
'@esfx/async-readerwriterlock':
|
||||||
|
specifier: ^1.0.0
|
||||||
|
version: 1.0.0
|
||||||
|
'@sammo/api_def':
|
||||||
|
specifier: workspace:^
|
||||||
|
version: link:../api_def
|
||||||
|
'@sammo/game_logic':
|
||||||
|
specifier: workspace:^
|
||||||
|
version: link:../game_logic
|
||||||
|
'@sammo/server_util':
|
||||||
|
specifier: workspace:^
|
||||||
|
version: link:../server_util
|
||||||
|
'@sammo/util':
|
||||||
|
specifier: workspace:^
|
||||||
|
version: link:../util
|
||||||
|
'@strpc/express':
|
||||||
|
specifier: workspace:^
|
||||||
|
version: link:../../@strpc/express
|
||||||
|
date-fns:
|
||||||
|
specifier: ^2.30.0
|
||||||
|
version: 2.30.0
|
||||||
|
dotenv:
|
||||||
|
specifier: ^16.3.1
|
||||||
|
version: 16.3.1
|
||||||
|
eventemitter3:
|
||||||
|
specifier: ^5.0.1
|
||||||
|
version: 5.0.1
|
||||||
|
express:
|
||||||
|
specifier: ^4.18.2
|
||||||
|
version: 4.18.2
|
||||||
|
express-session:
|
||||||
|
specifier: ^1.17.3
|
||||||
|
version: 1.17.3
|
||||||
|
ky:
|
||||||
|
specifier: ^1.0.1
|
||||||
|
version: 1.0.1
|
||||||
|
lodash-es:
|
||||||
|
specifier: ^4.17.21
|
||||||
|
version: 4.17.21
|
||||||
|
mongoose:
|
||||||
|
specifier: ^7.4.3
|
||||||
|
version: 7.4.3
|
||||||
|
reflect-metadata:
|
||||||
|
specifier: ^0.1.13
|
||||||
|
version: 0.1.13
|
||||||
|
tslib:
|
||||||
|
specifier: ^2.6.2
|
||||||
|
version: 2.6.2
|
||||||
|
zod:
|
||||||
|
specifier: ^3.22.2
|
||||||
|
version: 3.22.2
|
||||||
|
devDependencies:
|
||||||
|
'@sammo/gateway':
|
||||||
|
specifier: workspace:^
|
||||||
|
version: link:../gateway
|
||||||
|
'@types/node':
|
||||||
|
specifier: ^20.6.3
|
||||||
|
version: 20.6.3
|
||||||
|
|
||||||
'@sammo/server_util':
|
'@sammo/server_util':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@sammo/api_def':
|
'@sammo/api_def':
|
||||||
@@ -4267,7 +4353,6 @@ packages:
|
|||||||
/ky@1.0.1:
|
/ky@1.0.1:
|
||||||
resolution: {integrity: sha512-UvcwpQO0LOuZwG0Ti3VDo6w57KYt+r4bWEYlNaMt82hgyFtse86QtOGum1RzsZni31FndXQl6NvtDArfunt2JQ==}
|
resolution: {integrity: sha512-UvcwpQO0LOuZwG0Ti3VDo6w57KYt+r4bWEYlNaMt82hgyFtse86QtOGum1RzsZni31FndXQl6NvtDArfunt2JQ==}
|
||||||
engines: {node: '>=18'}
|
engines: {node: '>=18'}
|
||||||
dev: true
|
|
||||||
|
|
||||||
/leven@3.1.0:
|
/leven@3.1.0:
|
||||||
resolution: {integrity: sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==}
|
resolution: {integrity: sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==}
|
||||||
@@ -5543,7 +5628,6 @@ packages:
|
|||||||
|
|
||||||
/tslib@2.6.2:
|
/tslib@2.6.2:
|
||||||
resolution: {integrity: sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==}
|
resolution: {integrity: sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==}
|
||||||
dev: true
|
|
||||||
|
|
||||||
/tsutils@3.21.0(typescript@5.1.6):
|
/tsutils@3.21.0(typescript@5.1.6):
|
||||||
resolution: {integrity: sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==}
|
resolution: {integrity: sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==}
|
||||||
@@ -5940,4 +6024,3 @@ packages:
|
|||||||
|
|
||||||
/zod@3.22.2:
|
/zod@3.22.2:
|
||||||
resolution: {integrity: sha512-wvWkphh5WQsJbVk1tbx1l1Ly4yg+XecD+Mq280uBGt9wa5BKSWf4Mhp6GmrkPixhMxmabYY7RbzlwVP32pbGCg==}
|
resolution: {integrity: sha512-wvWkphh5WQsJbVk1tbx1l1Ly4yg+XecD+Mq280uBGt9wa5BKSWf4Mhp6GmrkPixhMxmabYY7RbzlwVP32pbGCg==}
|
||||||
dev: true
|
|
||||||
|
|||||||
@@ -1,5 +0,0 @@
|
|||||||
import type { structure } from "../apiStructure/sammoAPI.js";
|
|
||||||
import type { APINamespaceType } from "./defs.js";
|
|
||||||
|
|
||||||
export const sammoAPI = {
|
|
||||||
} satisfies APINamespaceType<typeof structure>;
|
|
||||||
@@ -1,199 +0,0 @@
|
|||||||
|
|
||||||
import type { Request, Response } from 'express';
|
|
||||||
import type { Callable, DefAPINamespace, DeleteAPICallT, GetAPICallT, HeadAPICallT, HttpMethod, InvalidResponse, PatchAPICallT, PostAPICallT, PutAPICallT, RawArgType, ValidResponse, recoveryMethod } from '../apiStructure/defs.js';
|
|
||||||
import type { Empty, PostProcDecoratorRunner, ProcDecoratorRunner } from '../ProcDecorator/base.js';
|
|
||||||
import type { ZodType } from 'zod';
|
|
||||||
|
|
||||||
export type APINamespace = {
|
|
||||||
[key: string]: APINamespace
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
||||||
| iAPI_GET<any, any, any, any>
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
||||||
| iAPI_POST<any, any, any, any>
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
||||||
| iAPI_PUT<any, any, any, any>
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
||||||
| iAPI_DELETE<any, any, any, any>
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
||||||
| iAPI_PATCH<any, any, any, any>
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
||||||
| iAPI_HEAD<any, any, any, any>
|
|
||||||
;
|
|
||||||
}
|
|
||||||
|
|
||||||
type ValidatorType<T> = T extends undefined ? undefined : ZodType<T>;
|
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
||||||
export type AnyAPIExecuter = APIExecuter<any, any, any, any>;
|
|
||||||
|
|
||||||
interface APIExecuter<R extends ValidResponse, E extends InvalidResponse, Q extends RawArgType, CTX extends object> {
|
|
||||||
(query: Q, ctx: CTX, expressReq: Request, expressRes: Response): Promise<R | E | true>;
|
|
||||||
httpMethod: HttpMethod;
|
|
||||||
argValidator?: ValidatorType<Q>;
|
|
||||||
preDecorator: ProcDecoratorRunner<CTX, Empty>;
|
|
||||||
postDecorator: PostProcDecoratorRunner<CTX>;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface iAPI_GET<R extends ValidResponse, E extends InvalidResponse, Q extends RawArgType, CTX extends object> extends APIExecuter<R, E, Q, CTX> {
|
|
||||||
httpMethod: 'get';
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface iAPI_POST<R extends ValidResponse, E extends InvalidResponse, Q extends RawArgType, CTX extends object> extends APIExecuter<R, E, Q, CTX> {
|
|
||||||
httpMethod: 'post';
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface iAPI_PUT<R extends ValidResponse, E extends InvalidResponse, Q extends RawArgType, CTX extends object> extends APIExecuter<R, E, Q, CTX> {
|
|
||||||
httpMethod: 'put';
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface iAPI_DELETE<R extends ValidResponse, E extends InvalidResponse, Q extends RawArgType, CTX extends object> extends APIExecuter<R, E, Q, CTX> {
|
|
||||||
httpMethod: 'delete';
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface iAPI_PATCH<R extends ValidResponse, E extends InvalidResponse, Q extends RawArgType, CTX extends object> extends APIExecuter<R, E, Q, CTX> {
|
|
||||||
httpMethod: 'patch';
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface iAPI_HEAD<R extends ValidResponse, E extends InvalidResponse, Q extends RawArgType, CTX extends object> extends APIExecuter<R, E, Q, CTX> {
|
|
||||||
httpMethod: 'head';
|
|
||||||
}
|
|
||||||
|
|
||||||
function generateAPI<R extends ValidResponse, E extends InvalidResponse, Q extends RawArgType, CTX extends object>(httpMethod: HttpMethod,
|
|
||||||
argValidator: ValidatorType<Q> | undefined,
|
|
||||||
preDecorator: ProcDecoratorRunner<CTX, Empty>,
|
|
||||||
postDecorator: PostProcDecoratorRunner<CTX>,
|
|
||||||
callback: (query: Q, ctx: CTX, expressReq: Request, expressRes: Response) => Promise<R | E | true>,
|
|
||||||
): APIExecuter<R, E, Q, CTX> {
|
|
||||||
return Object.assign(
|
|
||||||
callback,
|
|
||||||
{
|
|
||||||
httpMethod,
|
|
||||||
argValidator,
|
|
||||||
preDecorator,
|
|
||||||
postDecorator,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function GET<R extends ValidResponse, E extends InvalidResponse, Q extends RawArgType>(argValidator?: ValidatorType<Q>) {
|
|
||||||
return <CTX extends object>([preDecorator, postDecorator]: readonly [ProcDecoratorRunner<CTX, Empty>, PostProcDecoratorRunner<CTX>]) => {
|
|
||||||
return (callback: (query: Q, ctx: CTX, expressReq: Request, expressRes: Response) => Promise<R | E | true>) => {
|
|
||||||
return generateAPI<R, E, Q, CTX>(
|
|
||||||
'get',
|
|
||||||
argValidator,
|
|
||||||
preDecorator,
|
|
||||||
postDecorator,
|
|
||||||
callback,
|
|
||||||
) as iAPI_GET<R, E, Q, CTX>;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export function POST<R extends ValidResponse, E extends InvalidResponse, Q extends RawArgType>(argValidator?: ValidatorType<Q>) {
|
|
||||||
return <CTX extends object>([preDecorator, postDecorator]: readonly [ProcDecoratorRunner<CTX, Empty>, PostProcDecoratorRunner<CTX>]) => {
|
|
||||||
return (callback: (query: Q, ctx: CTX, expressReq: Request, expressRes: Response) => Promise<R | E | true>) => {
|
|
||||||
return generateAPI<R, E, Q, CTX>(
|
|
||||||
'post',
|
|
||||||
argValidator,
|
|
||||||
preDecorator,
|
|
||||||
postDecorator,
|
|
||||||
callback,
|
|
||||||
) as iAPI_POST<R, E, Q, CTX>;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export function PUT<R extends ValidResponse, E extends InvalidResponse, Q extends RawArgType>(argValidator?: ValidatorType<Q>) {
|
|
||||||
return <CTX extends object>([preDecorator, postDecorator]: readonly [ProcDecoratorRunner<CTX, Empty>, PostProcDecoratorRunner<CTX>]) => {
|
|
||||||
return (callback: (query: Q, ctx: CTX, expressReq: Request, expressRes: Response) => Promise<R | E | true>) => {
|
|
||||||
return generateAPI<R, E, Q, CTX>(
|
|
||||||
'put',
|
|
||||||
argValidator,
|
|
||||||
preDecorator,
|
|
||||||
postDecorator,
|
|
||||||
callback,
|
|
||||||
) as iAPI_PUT<R, E, Q, CTX>;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export function DELETE<R extends ValidResponse, E extends InvalidResponse, Q extends RawArgType>(argValidator?: ValidatorType<Q>) {
|
|
||||||
return <CTX extends object>([preDecorator, postDecorator]: readonly [ProcDecoratorRunner<CTX, Empty>, PostProcDecoratorRunner<CTX>]) => {
|
|
||||||
return (callback: (query: Q, ctx: CTX, expressReq: Request, expressRes: Response) => Promise<R | E | true>) => {
|
|
||||||
return generateAPI<R, E, Q, CTX>(
|
|
||||||
'delete',
|
|
||||||
argValidator,
|
|
||||||
preDecorator,
|
|
||||||
postDecorator,
|
|
||||||
callback,
|
|
||||||
) as iAPI_DELETE<R, E, Q, CTX>;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export function PATCH<R extends ValidResponse, E extends InvalidResponse, Q extends RawArgType>(argValidator?: ValidatorType<Q>) {
|
|
||||||
return <CTX extends object>([preDecorator, postDecorator]: readonly [ProcDecoratorRunner<CTX, Empty>, PostProcDecoratorRunner<CTX>]) => {
|
|
||||||
return (callback: (query: Q, ctx: CTX, expressReq: Request, expressRes: Response) => Promise<R | E | true>) => {
|
|
||||||
return generateAPI<R, E, Q, CTX>(
|
|
||||||
'patch',
|
|
||||||
argValidator,
|
|
||||||
preDecorator,
|
|
||||||
postDecorator,
|
|
||||||
callback,
|
|
||||||
) as iAPI_PATCH<R, E, Q, CTX>;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export function HEAD<R extends ValidResponse, E extends InvalidResponse, Q extends RawArgType>(argValidator?: ValidatorType<Q>) {
|
|
||||||
return <CTX extends object>([preDecorator, postDecorator]: readonly [ProcDecoratorRunner<CTX, Empty>, PostProcDecoratorRunner<CTX>]) => {
|
|
||||||
return (callback: (query: Q, ctx: CTX, expressReq: Request, expressRes: Response) => Promise<R | E | true>) => {
|
|
||||||
return generateAPI<R, E, Q, CTX>(
|
|
||||||
'head',
|
|
||||||
argValidator,
|
|
||||||
preDecorator,
|
|
||||||
postDecorator,
|
|
||||||
callback,
|
|
||||||
) as iAPI_HEAD<R, E, Q, CTX>;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export function raiseError(reason: string, recovery?: recoveryMethod): InvalidResponse {
|
|
||||||
if (recovery) {
|
|
||||||
return {
|
|
||||||
result: false,
|
|
||||||
reason,
|
|
||||||
recovery,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
result: false,
|
|
||||||
reason,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
||||||
export type ClassType<T> = new (...args: any[]) => T;
|
|
||||||
|
|
||||||
export type APIServerType<T extends Callable> =
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
||||||
T extends GetAPICallT<infer Q, infer R, infer E> ? iAPI_GET<R, E, Q, any> :
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
||||||
T extends PostAPICallT<infer Q, infer R, infer E> ? iAPI_POST<R, E, Q, any> :
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
||||||
T extends PutAPICallT<infer Q, infer R, infer E> ? iAPI_PUT<R, E, Q, any> :
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
||||||
T extends DeleteAPICallT<infer Q, infer R, infer E> ? iAPI_DELETE<R, E, Q, any> :
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
||||||
T extends PatchAPICallT<infer Q, infer R, infer E> ? iAPI_PATCH<R, E, Q, any> :
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
||||||
T extends HeadAPICallT<infer Q, infer R, infer E> ? iAPI_HEAD<R, E, Q, any> :
|
|
||||||
never;
|
|
||||||
export type APINamespaceType<T extends DefAPINamespace> = {
|
|
||||||
[K in keyof T]:
|
|
||||||
T[K] extends Callable ? APIServerType<T[K]> :
|
|
||||||
T[K] extends DefAPINamespace ? APINamespaceType<T[K]> :
|
|
||||||
never;
|
|
||||||
};
|
|
||||||
@@ -1,118 +0,0 @@
|
|||||||
import { Router, type Request, type Response } from 'express';
|
|
||||||
import type { AnyAPIExecuter, APINamespace } from './defs.js';
|
|
||||||
import type { RawArgType } from '../apiStructure/defs.js';
|
|
||||||
import { z } from 'zod';
|
|
||||||
|
|
||||||
async function parseParam<Q extends Exclude<RawArgType, undefined>>(req: Request, argValidator?: z.ZodType<Q>): Promise<z.SafeParseReturnType<Q, Q>> {
|
|
||||||
if (!argValidator) {
|
|
||||||
return {
|
|
||||||
success: true,
|
|
||||||
data: req.query as Q
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const query = req.query;
|
|
||||||
return await argValidator.safeParseAsync(query);
|
|
||||||
}
|
|
||||||
|
|
||||||
async function parseBody<Q extends Exclude<RawArgType, undefined>>(req: Request, argValidator?: z.ZodType<Q>): Promise<z.SafeParseReturnType<Q, Q>> {
|
|
||||||
if (!argValidator) {
|
|
||||||
return {
|
|
||||||
success: true,
|
|
||||||
data: req.body as Q
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const query = req.body;
|
|
||||||
return await argValidator.safeParseAsync(query);
|
|
||||||
}
|
|
||||||
|
|
||||||
async function apiRun(query: object, req: Request, res: Response, api: AnyAPIExecuter): Promise<void> {
|
|
||||||
const [preResult, ctx] = await api.preDecorator({}, req, res);
|
|
||||||
if (!preResult.every((v) => v.result)) {
|
|
||||||
const lastErr = preResult.pop() as typeof preResult[0];
|
|
||||||
|
|
||||||
const [postResult,] = await api.postDecorator(ctx, preResult, req, res, false);
|
|
||||||
const postErrors = postResult.filter((obj)=>!obj.result);
|
|
||||||
if (postErrors.length) {
|
|
||||||
//회수조차 불가능?
|
|
||||||
const postErrorsStr = postErrors.map((obj)=>{
|
|
||||||
return `(${obj.type})${obj.info}`
|
|
||||||
}).join(', ');
|
|
||||||
res.json({
|
|
||||||
result: false,
|
|
||||||
path: req.path,
|
|
||||||
reason: `preDecorator: (${lastErr.type})${lastErr.info}, postDecorator: ${postErrorsStr}`,
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
res.json({
|
|
||||||
result: false,
|
|
||||||
path: req.path,
|
|
||||||
reason: `preDecorator: (${lastErr.type})${lastErr.info}`,
|
|
||||||
})
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const result = await api(query, ctx, req, res);
|
|
||||||
const [postResult,] = await api.postDecorator(ctx, preResult, req, res, true);
|
|
||||||
const postErrors = postResult.filter((obj)=>!obj.result);
|
|
||||||
if(postErrors.length) {
|
|
||||||
if(result === true) {
|
|
||||||
//NOTE: 이미 api에서 response를 보낸 특이 케이스.
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const postErrorsStr = postErrors.map((obj)=>{
|
|
||||||
return `(${obj.type})${obj.info}`
|
|
||||||
}).join(', ');
|
|
||||||
res.json({
|
|
||||||
result: false,
|
|
||||||
path: req.path,
|
|
||||||
reason: `postDecorator: ${postErrorsStr}`,
|
|
||||||
originalResult: result,
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (result !== true) {
|
|
||||||
res.json(result);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export function buildAPISystem<N extends APINamespace, Q extends AnyAPIExecuter>(api: N | Q): Router {
|
|
||||||
const router = Router();
|
|
||||||
|
|
||||||
if(typeof api === 'function') {
|
|
||||||
throw 'root api cannot be function';
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const [key, value] of Object.entries(api)) {
|
|
||||||
const rkey = `/${key}`;
|
|
||||||
if (typeof value !== 'function') {
|
|
||||||
router.use(rkey, buildAPISystem(value));
|
|
||||||
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
const executer = value;
|
|
||||||
|
|
||||||
if (!executer.httpMethod) {
|
|
||||||
throw new Error('APIExecuter.reqType is not defined');
|
|
||||||
}
|
|
||||||
|
|
||||||
const parser = executer.httpMethod === 'get' ? parseParam : parseBody;
|
|
||||||
router[executer.httpMethod](rkey, async (req, res) => {
|
|
||||||
const queryResult = await parser(req, executer.argValidator);
|
|
||||||
if(!queryResult.success){
|
|
||||||
res.json({
|
|
||||||
result: false,
|
|
||||||
reason: `invalid parameter: ${queryResult.error.message}`,
|
|
||||||
error: queryResult.error
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
await apiRun(queryResult.data, req, res, executer);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return router;
|
|
||||||
}
|
|
||||||
@@ -1,358 +0,0 @@
|
|||||||
export type HttpMethod = 'get' | 'post' | 'put' | 'delete' | 'patch' | 'head';
|
|
||||||
export type RawArgType = {
|
|
||||||
[key: string]: unknown;
|
|
||||||
} | undefined;
|
|
||||||
|
|
||||||
|
|
||||||
export interface BasicAPICallT<
|
|
||||||
ArgType extends RawArgType,
|
|
||||||
ResultType extends ValidResponse,
|
|
||||||
ErrorType extends InvalidResponse
|
|
||||||
> {
|
|
||||||
(args: ArgType): Promise<ResultType>;
|
|
||||||
(args: ArgType, returnError: false): Promise<ResultType>;
|
|
||||||
(args: ArgType, returnError: true): Promise<ResultType | ErrorType>;
|
|
||||||
readonly reqType: HttpMethod;
|
|
||||||
}
|
|
||||||
|
|
||||||
export type BasicGetAPICallT<
|
|
||||||
ArgType extends RawArgType,
|
|
||||||
ResultType extends ValidResponse,
|
|
||||||
ErrorType extends InvalidResponse
|
|
||||||
> = BasicAPICallT<ArgType, ResultType, ErrorType> & { readonly reqType: 'get' };
|
|
||||||
|
|
||||||
export type BasicPostAPICallT<
|
|
||||||
ArgType extends RawArgType,
|
|
||||||
ResultType extends ValidResponse,
|
|
||||||
ErrorType extends InvalidResponse
|
|
||||||
> = BasicAPICallT<ArgType, ResultType, ErrorType> & { readonly reqType: 'post' };
|
|
||||||
|
|
||||||
export type BasicPutAPICallT<
|
|
||||||
ArgType extends RawArgType,
|
|
||||||
ResultType extends ValidResponse,
|
|
||||||
ErrorType extends InvalidResponse
|
|
||||||
> = BasicAPICallT<ArgType, ResultType, ErrorType> & { readonly reqType: 'put' };
|
|
||||||
|
|
||||||
export type BasicDeleteAPICallT<
|
|
||||||
ArgType extends RawArgType,
|
|
||||||
ResultType extends ValidResponse,
|
|
||||||
ErrorType extends InvalidResponse
|
|
||||||
> = BasicAPICallT<ArgType, ResultType, ErrorType> & { readonly reqType: 'delete' };
|
|
||||||
|
|
||||||
export type BasicPatchAPICallT<
|
|
||||||
ArgType extends RawArgType,
|
|
||||||
ResultType extends ValidResponse,
|
|
||||||
ErrorType extends InvalidResponse
|
|
||||||
> = BasicAPICallT<ArgType, ResultType, ErrorType> & { readonly reqType: 'patch' };
|
|
||||||
|
|
||||||
export type BasicHeadAPICallT<
|
|
||||||
ArgType extends RawArgType,
|
|
||||||
ResultType extends ValidResponse,
|
|
||||||
ErrorType extends InvalidResponse
|
|
||||||
> = BasicAPICallT<ArgType, ResultType, ErrorType> & { readonly reqType: 'head' };
|
|
||||||
|
|
||||||
export interface EmptyAPICallT<ResultType extends ValidResponse, ErrorType extends InvalidResponse> {
|
|
||||||
(): Promise<ResultType>;
|
|
||||||
(args?: undefined): Promise<ResultType>;
|
|
||||||
(args: undefined, returnError: false): Promise<ResultType>;
|
|
||||||
(args: undefined, returnError: true): Promise<ResultType | ErrorType>;
|
|
||||||
readonly reqType: HttpMethod;
|
|
||||||
}
|
|
||||||
|
|
||||||
export type EmptyGetAPICallT<
|
|
||||||
ResultType extends ValidResponse,
|
|
||||||
ErrorType extends InvalidResponse
|
|
||||||
> = EmptyAPICallT<ResultType, ErrorType> & { readonly reqType: 'get' };
|
|
||||||
|
|
||||||
export type EmptyPostAPICallT<
|
|
||||||
ResultType extends ValidResponse,
|
|
||||||
ErrorType extends InvalidResponse
|
|
||||||
> = EmptyAPICallT<ResultType, ErrorType> & { readonly reqType: 'post' };
|
|
||||||
|
|
||||||
export type EmptyPutAPICallT<
|
|
||||||
ResultType extends ValidResponse,
|
|
||||||
ErrorType extends InvalidResponse
|
|
||||||
> = EmptyAPICallT<ResultType, ErrorType> & { readonly reqType: 'put' };
|
|
||||||
|
|
||||||
export type EmptyDeleteAPICallT<
|
|
||||||
ResultType extends ValidResponse,
|
|
||||||
ErrorType extends InvalidResponse
|
|
||||||
> = EmptyAPICallT<ResultType, ErrorType> & { readonly reqType: 'delete' };
|
|
||||||
|
|
||||||
export type EmptyPatchAPICallT<
|
|
||||||
ResultType extends ValidResponse,
|
|
||||||
ErrorType extends InvalidResponse
|
|
||||||
> = EmptyAPICallT<ResultType, ErrorType> & { readonly reqType: 'patch' };
|
|
||||||
|
|
||||||
export type EmptyHeadAPICallT<
|
|
||||||
ResultType extends ValidResponse,
|
|
||||||
ErrorType extends InvalidResponse
|
|
||||||
> = EmptyAPICallT<ResultType, ErrorType> & { readonly reqType: 'head' };
|
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
||||||
export type ArgTypeOf<T> = T extends APICallT<infer A, any, any> ? A : never;
|
|
||||||
|
|
||||||
|
|
||||||
export type APICallT<
|
|
||||||
ArgType extends RawArgType,
|
|
||||||
ResultType extends ValidResponse = ValidResponse,
|
|
||||||
ErrorType extends InvalidResponse = InvalidResponse
|
|
||||||
> = ArgType extends undefined ? EmptyAPICallT<ResultType, ErrorType> : BasicAPICallT<ArgType, ResultType, ErrorType>;
|
|
||||||
|
|
||||||
export type GetAPICallT<
|
|
||||||
ArgType extends RawArgType,
|
|
||||||
ResultType extends ValidResponse = ValidResponse,
|
|
||||||
ErrorType extends InvalidResponse = InvalidResponse
|
|
||||||
> = ArgType extends undefined ? EmptyGetAPICallT<ResultType, ErrorType> : BasicGetAPICallT<ArgType, ResultType, ErrorType>;
|
|
||||||
|
|
||||||
export type PostAPICallT<
|
|
||||||
ArgType extends RawArgType,
|
|
||||||
ResultType extends ValidResponse = ValidResponse,
|
|
||||||
ErrorType extends InvalidResponse = InvalidResponse
|
|
||||||
> = ArgType extends undefined ? EmptyPostAPICallT<ResultType, ErrorType> : BasicPostAPICallT<ArgType, ResultType, ErrorType>;
|
|
||||||
|
|
||||||
export type PutAPICallT<
|
|
||||||
ArgType extends RawArgType,
|
|
||||||
ResultType extends ValidResponse = ValidResponse,
|
|
||||||
ErrorType extends InvalidResponse = InvalidResponse
|
|
||||||
> = ArgType extends undefined ? EmptyPutAPICallT<ResultType, ErrorType> : BasicPutAPICallT<ArgType, ResultType, ErrorType>;
|
|
||||||
|
|
||||||
export type DeleteAPICallT<
|
|
||||||
ArgType extends RawArgType,
|
|
||||||
ResultType extends ValidResponse = ValidResponse,
|
|
||||||
ErrorType extends InvalidResponse = InvalidResponse
|
|
||||||
> = ArgType extends undefined ? EmptyDeleteAPICallT<ResultType, ErrorType> : BasicDeleteAPICallT<ArgType, ResultType, ErrorType>;
|
|
||||||
|
|
||||||
export type PatchAPICallT<
|
|
||||||
ArgType extends RawArgType,
|
|
||||||
ResultType extends ValidResponse = ValidResponse,
|
|
||||||
ErrorType extends InvalidResponse = InvalidResponse
|
|
||||||
> = ArgType extends undefined ? EmptyPatchAPICallT<ResultType, ErrorType> : BasicPatchAPICallT<ArgType, ResultType, ErrorType>;
|
|
||||||
|
|
||||||
export type HeadAPICallT<
|
|
||||||
ArgType extends RawArgType,
|
|
||||||
ResultType extends ValidResponse = ValidResponse,
|
|
||||||
ErrorType extends InvalidResponse = InvalidResponse
|
|
||||||
> = ArgType extends undefined ? EmptyHeadAPICallT<ResultType, ErrorType> : BasicHeadAPICallT<ArgType, ResultType, ErrorType>;
|
|
||||||
|
|
||||||
export type APITail = ReturnType<typeof GET> | ReturnType<typeof POST> | ReturnType<typeof PUT> | ReturnType<typeof DELETE> | ReturnType<typeof PATCH> | ReturnType<typeof HEAD>;
|
|
||||||
|
|
||||||
export function GET<
|
|
||||||
ResultType extends ValidResponse = ValidResponse,
|
|
||||||
ErrorType extends InvalidResponse = InvalidResponse,
|
|
||||||
>(): EmptyGetAPICallT<ResultType, ErrorType>
|
|
||||||
export function GET<
|
|
||||||
ArgType extends RawArgType,
|
|
||||||
ResultType extends ValidResponse = ValidResponse,
|
|
||||||
ErrorType extends InvalidResponse = InvalidResponse,
|
|
||||||
>(): BasicGetAPICallT<ArgType, ResultType, ErrorType>;
|
|
||||||
export function GET<
|
|
||||||
ArgType extends RawArgType,
|
|
||||||
ResultType extends ValidResponse = ValidResponse,
|
|
||||||
ErrorType extends InvalidResponse = InvalidResponse,
|
|
||||||
>(): BasicGetAPICallT<ArgType, ResultType, ErrorType> | EmptyGetAPICallT<ResultType, ErrorType> {
|
|
||||||
return Object.assign(
|
|
||||||
fakeGET,
|
|
||||||
{ reqType: 'get' } as const
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
export function POST<
|
|
||||||
ResultType extends ValidResponse = ValidResponse,
|
|
||||||
ErrorType extends InvalidResponse = InvalidResponse,
|
|
||||||
>(): EmptyPostAPICallT<ResultType, ErrorType>
|
|
||||||
export function POST<
|
|
||||||
ArgType extends RawArgType,
|
|
||||||
ResultType extends ValidResponse = ValidResponse,
|
|
||||||
ErrorType extends InvalidResponse = InvalidResponse,
|
|
||||||
>(): BasicPostAPICallT<ArgType, ResultType, ErrorType>;
|
|
||||||
export function POST<
|
|
||||||
ArgType extends RawArgType,
|
|
||||||
ResultType extends ValidResponse = ValidResponse,
|
|
||||||
ErrorType extends InvalidResponse = InvalidResponse,
|
|
||||||
>(): BasicPostAPICallT<ArgType, ResultType, ErrorType> | EmptyPostAPICallT<ResultType, ErrorType> {
|
|
||||||
return Object.assign(
|
|
||||||
fakePOST,
|
|
||||||
{ reqType: 'post' } as const
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
export function PUT<
|
|
||||||
ResultType extends ValidResponse = ValidResponse,
|
|
||||||
ErrorType extends InvalidResponse = InvalidResponse,
|
|
||||||
>(): EmptyPutAPICallT<ResultType, ErrorType>
|
|
||||||
export function PUT<
|
|
||||||
ArgType extends RawArgType,
|
|
||||||
ResultType extends ValidResponse = ValidResponse,
|
|
||||||
ErrorType extends InvalidResponse = InvalidResponse,
|
|
||||||
>(): BasicPutAPICallT<ArgType, ResultType, ErrorType>;
|
|
||||||
export function PUT<
|
|
||||||
ArgType extends RawArgType,
|
|
||||||
ResultType extends ValidResponse = ValidResponse,
|
|
||||||
ErrorType extends InvalidResponse = InvalidResponse,
|
|
||||||
>(): BasicPutAPICallT<ArgType, ResultType, ErrorType> | EmptyPutAPICallT<ResultType, ErrorType> {
|
|
||||||
return Object.assign(
|
|
||||||
fakePUT,
|
|
||||||
{ reqType: 'put' } as const
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
export function DELETE<
|
|
||||||
ResultType extends ValidResponse = ValidResponse,
|
|
||||||
ErrorType extends InvalidResponse = InvalidResponse,
|
|
||||||
>(): EmptyDeleteAPICallT<ResultType, ErrorType>
|
|
||||||
export function DELETE<
|
|
||||||
ArgType extends RawArgType,
|
|
||||||
ResultType extends ValidResponse = ValidResponse,
|
|
||||||
ErrorType extends InvalidResponse = InvalidResponse,
|
|
||||||
>(): BasicDeleteAPICallT<ArgType, ResultType, ErrorType>;
|
|
||||||
export function DELETE<
|
|
||||||
ArgType extends RawArgType,
|
|
||||||
ResultType extends ValidResponse = ValidResponse,
|
|
||||||
ErrorType extends InvalidResponse = InvalidResponse,
|
|
||||||
>(): BasicDeleteAPICallT<ArgType, ResultType, ErrorType> | EmptyDeleteAPICallT<ResultType, ErrorType> {
|
|
||||||
return Object.assign(
|
|
||||||
fakeDELETE,
|
|
||||||
{ reqType: 'delete' } as const
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
export function PATCH<
|
|
||||||
ResultType extends ValidResponse = ValidResponse,
|
|
||||||
ErrorType extends InvalidResponse = InvalidResponse,
|
|
||||||
>(): EmptyPatchAPICallT<ResultType, ErrorType>
|
|
||||||
export function PATCH<
|
|
||||||
ArgType extends RawArgType,
|
|
||||||
ResultType extends ValidResponse = ValidResponse,
|
|
||||||
ErrorType extends InvalidResponse = InvalidResponse,
|
|
||||||
>(): BasicPatchAPICallT<ArgType, ResultType, ErrorType>;
|
|
||||||
export function PATCH<
|
|
||||||
ArgType extends RawArgType,
|
|
||||||
ResultType extends ValidResponse = ValidResponse,
|
|
||||||
ErrorType extends InvalidResponse = InvalidResponse,
|
|
||||||
>(): BasicPatchAPICallT<ArgType, ResultType, ErrorType> | EmptyPatchAPICallT<ResultType, ErrorType> {
|
|
||||||
return Object.assign(
|
|
||||||
fakePATCH,
|
|
||||||
{ reqType: 'patch' } as const
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
export function HEAD<
|
|
||||||
ResultType extends ValidResponse = ValidResponse,
|
|
||||||
ErrorType extends InvalidResponse = InvalidResponse,
|
|
||||||
>(): EmptyHeadAPICallT<ResultType, ErrorType>
|
|
||||||
export function HEAD<
|
|
||||||
ArgType extends RawArgType,
|
|
||||||
ResultType extends ValidResponse = ValidResponse,
|
|
||||||
ErrorType extends InvalidResponse = InvalidResponse,
|
|
||||||
>(): BasicHeadAPICallT<ArgType, ResultType, ErrorType>;
|
|
||||||
export function HEAD<
|
|
||||||
ArgType extends RawArgType,
|
|
||||||
ResultType extends ValidResponse = ValidResponse,
|
|
||||||
ErrorType extends InvalidResponse = InvalidResponse,
|
|
||||||
>(): BasicHeadAPICallT<ArgType, ResultType, ErrorType> | EmptyHeadAPICallT<ResultType, ErrorType> {
|
|
||||||
return Object.assign(
|
|
||||||
fakeHEAD,
|
|
||||||
{ reqType: 'head' } as const
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function fakeGET<
|
|
||||||
ResultType extends ValidResponse,
|
|
||||||
ErrorType extends InvalidResponse,
|
|
||||||
ArgType extends undefined = undefined
|
|
||||||
>(args?: ArgType, returnError = false): Promise<ResultType | ErrorType> {
|
|
||||||
throw `Can't directly call GET. ${args}, ${returnError}. Use auto-generated path API.`
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function fakePOST<
|
|
||||||
ResultType extends ValidResponse,
|
|
||||||
ErrorType extends InvalidResponse,
|
|
||||||
ArgType extends RawArgType = undefined
|
|
||||||
>(args: ArgType, returnError = false): Promise<ResultType | ErrorType> {
|
|
||||||
throw `Can't directly call POST. ${args}, ${returnError}. Use auto-generated path API.`
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function fakePUT<
|
|
||||||
ResultType extends ValidResponse,
|
|
||||||
ErrorType extends InvalidResponse,
|
|
||||||
ArgType extends RawArgType = undefined
|
|
||||||
>(args: ArgType, returnError = false): Promise<ResultType | ErrorType> {
|
|
||||||
throw `Can't directly call PUT. ${args}, ${returnError}. Use auto-generated path API.`;
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function fakeDELETE<
|
|
||||||
ResultType extends ValidResponse,
|
|
||||||
ErrorType extends InvalidResponse,
|
|
||||||
ArgType extends RawArgType = undefined
|
|
||||||
>(args: ArgType, returnError = false): Promise<ResultType | ErrorType> {
|
|
||||||
throw `Can't directly call DELETE. ${args}, ${returnError}. Use auto-generated path API.`;
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function fakePATCH<
|
|
||||||
ResultType extends ValidResponse,
|
|
||||||
ErrorType extends InvalidResponse,
|
|
||||||
ArgType extends RawArgType = undefined
|
|
||||||
>(args: ArgType, returnError = false): Promise<ResultType | ErrorType> {
|
|
||||||
throw `Can't directly call PATCH. ${args}, ${returnError}. Use auto-generated path API.`
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function fakeHEAD<
|
|
||||||
ResultType extends ValidResponse,
|
|
||||||
ErrorType extends InvalidResponse,
|
|
||||||
ArgType extends RawArgType = undefined
|
|
||||||
>(args?: ArgType, returnError = false): Promise<ResultType | ErrorType> {
|
|
||||||
throw `Can't directly call HEAD. ${args}, ${returnError}. Use auto-generated path API.`;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface ValidResponse {
|
|
||||||
result: true;
|
|
||||||
}
|
|
||||||
|
|
||||||
export type recoveryMethod = 'refreshEntirePage' | 'retryAPI' | 'gameLogin' | 'gatewayLogin' | 'gateway2FA' | 'gameQuota';
|
|
||||||
export interface InvalidResponse {
|
|
||||||
result: false;
|
|
||||||
reason: string;
|
|
||||||
recovery?: recoveryMethod;
|
|
||||||
}
|
|
||||||
|
|
||||||
type ExtractValid<T> = T extends ValidResponse ? T : never;
|
|
||||||
type ExtractInvalid<T> = T extends InvalidResponse ? T : never;
|
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
||||||
export type Callable = (...args: any) => any;
|
|
||||||
|
|
||||||
export type ExtractResponse<T extends Callable> = ExtractValid<Awaited<ReturnType<T>>>;
|
|
||||||
export type ExtractError<T extends Callable> = ExtractInvalid<Awaited<ReturnType<T>>>;
|
|
||||||
export type ExtractQuery<T extends Callable> = Parameters<T>[0];
|
|
||||||
|
|
||||||
export type DefAPINamespace = {
|
|
||||||
[key: string]: DefAPINamespace
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
||||||
| BasicGetAPICallT<any, any, any>
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
||||||
| BasicPostAPICallT<any, any, any>
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
||||||
| BasicPutAPICallT<any, any, any>
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
||||||
| BasicDeleteAPICallT<any, any, any>
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
||||||
| BasicPatchAPICallT<any, any, any>
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
||||||
| BasicHeadAPICallT<any, any, any>
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
||||||
| EmptyGetAPICallT<any, any>
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
||||||
| EmptyPostAPICallT<any, any>
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
||||||
| EmptyPutAPICallT<any, any>
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
||||||
| EmptyDeleteAPICallT<any, any>
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
||||||
| EmptyPatchAPICallT<any, any>
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
||||||
| EmptyHeadAPICallT<any, any>
|
|
||||||
;
|
|
||||||
}
|
|
||||||
|
|
||||||
export type APICompatType<T extends Callable> = T extends APICallT<infer A, infer R, infer E> ? APICallT<A, R, E> : never;
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
import { type DefAPINamespace, GET, POST } from "./defs.js";
|
|
||||||
|
|
||||||
/** @internal */
|
|
||||||
export const structure = {
|
|
||||||
|
|
||||||
} satisfies DefAPINamespace;
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
import 'dotenv/config';
|
|
||||||
import { connect, Mongoose } from "mongoose";
|
|
||||||
import { unwrap } from './util/unwrap.js';
|
|
||||||
|
|
||||||
const dbConfig = {
|
|
||||||
host: unwrap(process.env.GATEWAY_DB_HOST),
|
|
||||||
port: Number(unwrap(process.env.GATEWAY_DB_PORT)),
|
|
||||||
user: unwrap(process.env.GATEWAY_DB_USER),
|
|
||||||
password: unwrap(process.env.GATEWAY_DB_PASSWORD),
|
|
||||||
database: unwrap(process.env.GATEWAY_DB_DATABASE),
|
|
||||||
}
|
|
||||||
|
|
||||||
const gatewayDB: Promise<Mongoose> = (async () => {
|
|
||||||
return await connect(`mongodb://${dbConfig.host}:${dbConfig.port}/${dbConfig.database}`, {
|
|
||||||
auth:{
|
|
||||||
username: dbConfig.user,
|
|
||||||
password: dbConfig.password,
|
|
||||||
}
|
|
||||||
});
|
|
||||||
})();
|
|
||||||
|
|
||||||
export default gatewayDB;
|
|
||||||
@@ -1,37 +0,0 @@
|
|||||||
import 'reflect-metadata';
|
|
||||||
import gatewayDB from './connectGatewayDB.js';
|
|
||||||
import express, { type Request, type Response } from "express"
|
|
||||||
import session from "express-session";
|
|
||||||
import path from 'node:path';
|
|
||||||
import { LiteHashDRBG } from './util/LiteHashDRBG.js';
|
|
||||||
import { simpleSerialize } from './util/simpleSerialize.js';
|
|
||||||
import { SammoGatewayAPI } from './clientAPI/sammoGatewayAPI.js';
|
|
||||||
import { buildAPISystem } from './api/generator.js';
|
|
||||||
import { sammoGatewayAPI } from './api/gatewayAPI.js';
|
|
||||||
import { unwrap } from './util/unwrap.js';
|
|
||||||
import { gatewayConfig } from './gatewayConfig.js';
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
gatewayDB.then(async (gatewayDB) => {
|
|
||||||
// create express app
|
|
||||||
const app = express()
|
|
||||||
app.use(express.json());
|
|
||||||
app.use(session({
|
|
||||||
secret: unwrap(gatewayConfig.sessionSecret),
|
|
||||||
resave: false,
|
|
||||||
saveUninitialized: false,
|
|
||||||
}))
|
|
||||||
//app.set('etag', false);
|
|
||||||
|
|
||||||
app.use('/gateway_api', buildAPISystem(sammoGatewayAPI));
|
|
||||||
|
|
||||||
// start express server
|
|
||||||
app.listen(gatewayConfig.port)
|
|
||||||
|
|
||||||
console.log(`Gateway server has started on port ${gatewayConfig.port}`)
|
|
||||||
|
|
||||||
}).catch(error => console.log(error));
|
|
||||||
|
|
||||||
export default {};
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
import 'dotenv/config';
|
|
||||||
import { unwrap } from './util/unwrap.js';
|
|
||||||
|
|
||||||
export const gatewayConfig = {
|
|
||||||
sessionSecret: unwrap(process.env.GATEWAY_SESSION_SECRET),
|
|
||||||
port: Number(unwrap(process.env.GATEWAY_PORT)),
|
|
||||||
};
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
{
|
|
||||||
"extends": "@vue/tsconfig/tsconfig.dom.json",
|
|
||||||
"include": ["env.d.ts", "src/**/*", "src/**/*.vue"],
|
|
||||||
"exclude": ["src/**/__tests__/*"],
|
|
||||||
"compilerOptions": {
|
|
||||||
"composite": true,
|
|
||||||
"baseUrl": ".",
|
|
||||||
"paths": {
|
|
||||||
"@/*": ["./src/*"]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user