@strpc ready
This commit is contained in:
@@ -0,0 +1,27 @@
|
||||
{
|
||||
"name": "@strpc/client_ky",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"main": "dist/index.js",
|
||||
"exports": {
|
||||
".": "./dist/index.js",
|
||||
"./types": "./dist/types.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@strpc/def": "workspace:^"
|
||||
},
|
||||
"devDependencies": {
|
||||
"ky": "^1.0.1",
|
||||
"lodash-es": "^4.17.21"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "tsc --build"
|
||||
},
|
||||
"type": "module",
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"peerDependencies": {
|
||||
"ky": "^1.0.1",
|
||||
"lodash-es": "^4.17.21"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,158 @@
|
||||
import { isArray, isEmpty } from "lodash-es";
|
||||
import ky from "ky";
|
||||
import type { HttpMethod, InvalidResponse, RawArgType, ValidResponse, recoveryMethod } from "@strpc/def";
|
||||
|
||||
|
||||
export type globalRecoveryFunction = (method: HttpMethod, path: string, args: RawArgType, recovery: recoveryMethod, result: InvalidResponse) => Promise<{
|
||||
justRetryAPI?: boolean;
|
||||
} | void>;
|
||||
|
||||
export class APIFailed extends Error {
|
||||
constructor(public readonly reason: string, public readonly detail: unknown, public readonly recovery?: recoveryMethod) {
|
||||
super(reason);
|
||||
}
|
||||
}
|
||||
|
||||
export async function callClientAPI<ResultType extends ValidResponse>(
|
||||
method: HttpMethod,
|
||||
apiRoot: string,
|
||||
path: string | string[],
|
||||
args: RawArgType,
|
||||
globalRecovery: globalRecoveryFunction | undefined
|
||||
): Promise<ResultType>;
|
||||
export async function callClientAPI<ResultType extends ValidResponse>(
|
||||
method: HttpMethod,
|
||||
apiRoot: string,
|
||||
path: string | string[],
|
||||
args: RawArgType,
|
||||
globalRecovery: globalRecoveryFunction | undefined,
|
||||
returnError: undefined
|
||||
): Promise<ResultType>;
|
||||
export async function callClientAPI<ResultType extends ValidResponse>(
|
||||
method: HttpMethod,
|
||||
apiRoot: string,
|
||||
path: string | string[],
|
||||
args: RawArgType,
|
||||
globalRecovery: globalRecoveryFunction | undefined,
|
||||
returnError: false
|
||||
): Promise<ResultType>;
|
||||
export async function callClientAPI<ResultType extends ValidResponse, ErrorType extends InvalidResponse>(
|
||||
method: HttpMethod,
|
||||
apiRoot: string,
|
||||
path: string | string[],
|
||||
args: RawArgType,
|
||||
globalRecovery: globalRecoveryFunction | undefined,
|
||||
returnError: true
|
||||
): Promise<ResultType | ErrorType>;
|
||||
export async function callClientAPI<ResultType extends ValidResponse, ErrorType extends InvalidResponse>(
|
||||
method: HttpMethod,
|
||||
apiRoot: string,
|
||||
path: string | string[],
|
||||
args: RawArgType,
|
||||
globalRecovery: globalRecoveryFunction | undefined,
|
||||
returnError?: boolean
|
||||
): Promise<ResultType | ErrorType> {
|
||||
if (isArray(path)) {
|
||||
path = [apiRoot, ...path].join("/");
|
||||
}
|
||||
else if (path.startsWith("/")) {
|
||||
path = `${apiRoot}${path}`;
|
||||
}
|
||||
else {
|
||||
path = `${apiRoot}/${path}`;
|
||||
}
|
||||
|
||||
if (args && isEmpty(args)) {
|
||||
args = undefined;
|
||||
}
|
||||
|
||||
try {
|
||||
let trialRemain = 3;
|
||||
let lastErr: ErrorType | undefined = undefined;
|
||||
// eslint-disable-next-line no-constant-condition
|
||||
while(trialRemain > 0){
|
||||
const result = (await (() => {
|
||||
if (method == "get") {
|
||||
//TODO: args가 복합 object일 경우의 처리
|
||||
return ky(path, {
|
||||
searchParams: args === undefined ? undefined : {
|
||||
...(args as Record<string, string | number>),
|
||||
},
|
||||
method,
|
||||
headers: {
|
||||
"content-type": "application/json",
|
||||
},
|
||||
timeout: 30000,
|
||||
retry: 0,
|
||||
});
|
||||
}
|
||||
return ky(path, {
|
||||
method,
|
||||
json: args,
|
||||
headers: {
|
||||
"content-type": "application/json",
|
||||
},
|
||||
timeout: 30000,
|
||||
retry: 0,
|
||||
});
|
||||
})().json()) as ErrorType | ResultType;
|
||||
|
||||
if (!result.result) {
|
||||
lastErr = result;
|
||||
if(result.recovery && globalRecovery){
|
||||
const recoveryResult = await globalRecovery(method, path, args, result.recovery, result);
|
||||
if(recoveryResult !== undefined && recoveryResult.justRetryAPI){
|
||||
trialRemain--;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (returnError) {
|
||||
return result;
|
||||
}
|
||||
throw new APIFailed(
|
||||
result.reason,
|
||||
result.detail,
|
||||
result.recovery
|
||||
);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
if(lastErr === undefined){
|
||||
throw new Error('lastErr is undefined');
|
||||
}
|
||||
|
||||
if (returnError) {
|
||||
return lastErr;
|
||||
}
|
||||
throw lastErr.reason;
|
||||
|
||||
}
|
||||
catch(err) {
|
||||
if(!returnError){
|
||||
throw err;
|
||||
}
|
||||
|
||||
let infoText = ''
|
||||
|
||||
if(err instanceof APIFailed){
|
||||
infoText = err.reason;
|
||||
}
|
||||
else if(err instanceof Error){
|
||||
infoText = err.toString();
|
||||
}
|
||||
else if(typeof err == 'string'){
|
||||
infoText = err;
|
||||
}
|
||||
else{
|
||||
infoText = JSON.stringify(err);
|
||||
}
|
||||
|
||||
return {
|
||||
result: false,
|
||||
reason: `failed to fetch(${path}): ${err}`,
|
||||
detail: err,
|
||||
} as ErrorType;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
import { clientAPIPathGen, type APITail, type DefAPINamespace, type RawArgType } from "@strpc/def";
|
||||
import { callClientAPI, type globalRecoveryFunction } from "./callClientAPI.js";
|
||||
export { callClientAPI, type globalRecoveryFunction } from "./callClientAPI.js";
|
||||
|
||||
export function buildClientAPI<T extends DefAPINamespace>(structure: T, apiRoot = '/api', globalRecovery?: globalRecoveryFunction){
|
||||
return clientAPIPathGen(structure, (path: string[], tail: APITail) => {
|
||||
const method = tail.reqType;
|
||||
return (args?: RawArgType, returnError?: boolean) => {
|
||||
if (returnError) {
|
||||
return callClientAPI(method, apiRoot, path.join('/'), args, globalRecovery, returnError);
|
||||
}
|
||||
return callClientAPI(method, apiRoot, path.join('/'), args, globalRecovery);
|
||||
};
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"extends": "../../tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"rootDir": "./src",
|
||||
"outDir": "./dist",
|
||||
},
|
||||
"references": [
|
||||
{
|
||||
"path": "../def"
|
||||
},
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"name": "@strpc/def",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"main": "dist/index.js",
|
||||
"exports": {
|
||||
".": "./dist/index.js",
|
||||
"./types": "./dist/types.js"
|
||||
},
|
||||
"devDependencies": {},
|
||||
"scripts": {
|
||||
"build": "tsc --build"
|
||||
},
|
||||
"type": "module",
|
||||
"author": "",
|
||||
"license": "ISC"
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
export function clientAPIPathGen<T extends object, V>(
|
||||
obj: T,
|
||||
callback: (path: string[], tail: V) => unknown,
|
||||
path: string[] = [],
|
||||
): T {
|
||||
const map = new Map<string, unknown>();
|
||||
return new Proxy(obj, {
|
||||
get(target, key) {
|
||||
if(typeof key === 'symbol'){
|
||||
throw new Error('Symbol is not supported');
|
||||
}
|
||||
|
||||
const cachedResult = map.get(key);
|
||||
if(cachedResult !== undefined){
|
||||
return cachedResult;
|
||||
}
|
||||
|
||||
const nextPath = [...path, key];
|
||||
|
||||
let next;
|
||||
if (key in target) {
|
||||
next = target[key as keyof typeof target];
|
||||
}
|
||||
else {
|
||||
throw `${nextPath} is not exists`;
|
||||
}
|
||||
|
||||
if (typeof (next) === 'function') {
|
||||
const result = callback(nextPath, next as V);
|
||||
map.set(key, result);
|
||||
return result;
|
||||
}
|
||||
const result = clientAPIPathGen<object, V>(next as object, callback, nextPath);
|
||||
map.set(key, result);
|
||||
return result;
|
||||
}
|
||||
}) as T;
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
export type {
|
||||
HttpMethod,
|
||||
RawArgType,
|
||||
DefAPINamespace,
|
||||
APICompatType,
|
||||
ValidResponse,
|
||||
InvalidResponse,
|
||||
recoveryMethod,
|
||||
InferResponse,
|
||||
InferError,
|
||||
InferQuery,
|
||||
} from './types.js';
|
||||
|
||||
export {
|
||||
type APITail,
|
||||
GET,
|
||||
POST,
|
||||
PUT,
|
||||
DELETE,
|
||||
PATCH,
|
||||
HEAD,
|
||||
} from './tail.js';
|
||||
export { clientAPIPathGen } from './clientAPIPathGen.js';
|
||||
@@ -0,0 +1,177 @@
|
||||
import type { ArgDeleteAPI, ArgGetAPI, ArgHeadAPI, ArgPatchAPI, ArgPostAPI, ArgPutAPI, EmptyDeleteAPI, EmptyGetAPI, EmptyHeadAPI, EmptyPatchAPI, EmptyPostAPI, EmptyPutAPI, InvalidResponse, RawArgType, ValidResponse } from "./types.js";
|
||||
|
||||
export type APITail = ReturnType<typeof GET> | ReturnType<typeof POST> | ReturnType<typeof PUT> | ReturnType<typeof DELETE> | ReturnType<typeof PATCH> | ReturnType<typeof HEAD>;
|
||||
|
||||
export function GET(): EmptyGetAPI<ValidResponse, InvalidResponse>;
|
||||
export function GET<
|
||||
ResultType extends ValidResponse = ValidResponse,
|
||||
ErrorType extends InvalidResponse = InvalidResponse,
|
||||
>(): EmptyGetAPI<ResultType, ErrorType>;
|
||||
export function GET<
|
||||
ArgType extends RawArgType,
|
||||
ResultType extends ValidResponse = ValidResponse,
|
||||
ErrorType extends InvalidResponse = InvalidResponse,
|
||||
>(): ArgGetAPI<ArgType, ResultType, ErrorType>;
|
||||
export function GET<
|
||||
ArgType extends RawArgType,
|
||||
ResultType extends ValidResponse = ValidResponse,
|
||||
ErrorType extends InvalidResponse = InvalidResponse,
|
||||
>(): ArgGetAPI<ArgType, ResultType, ErrorType> | EmptyGetAPI<ResultType, ErrorType> {
|
||||
return Object.assign(
|
||||
fakeGET,
|
||||
{ reqType: 'get' } as const
|
||||
)
|
||||
}
|
||||
|
||||
export function POST(): EmptyPostAPI<ValidResponse, InvalidResponse>;
|
||||
export function POST<
|
||||
ResultType extends ValidResponse = ValidResponse,
|
||||
ErrorType extends InvalidResponse = InvalidResponse,
|
||||
>(): EmptyPostAPI<ResultType, ErrorType>;
|
||||
export function POST<
|
||||
ArgType extends RawArgType,
|
||||
ResultType extends ValidResponse = ValidResponse,
|
||||
ErrorType extends InvalidResponse = InvalidResponse,
|
||||
>(): ArgPostAPI<ArgType, ResultType, ErrorType>;
|
||||
export function POST<
|
||||
ArgType extends RawArgType,
|
||||
ResultType extends ValidResponse = ValidResponse,
|
||||
ErrorType extends InvalidResponse = InvalidResponse,
|
||||
>(): ArgPostAPI<ArgType, ResultType, ErrorType> | EmptyPostAPI<ResultType, ErrorType> {
|
||||
return Object.assign(
|
||||
fakePOST,
|
||||
{ reqType: 'post' } as const
|
||||
)
|
||||
}
|
||||
|
||||
export function PUT(): EmptyPutAPI<ValidResponse, InvalidResponse>;
|
||||
export function PUT<
|
||||
ResultType extends ValidResponse = ValidResponse,
|
||||
ErrorType extends InvalidResponse = InvalidResponse,
|
||||
>(): EmptyPutAPI<ResultType, ErrorType>;
|
||||
export function PUT<
|
||||
ArgType extends RawArgType,
|
||||
ResultType extends ValidResponse = ValidResponse,
|
||||
ErrorType extends InvalidResponse = InvalidResponse,
|
||||
>(): ArgPutAPI<ArgType, ResultType, ErrorType>;
|
||||
export function PUT<
|
||||
ArgType extends RawArgType,
|
||||
ResultType extends ValidResponse = ValidResponse,
|
||||
ErrorType extends InvalidResponse = InvalidResponse,
|
||||
>(): ArgPutAPI<ArgType, ResultType, ErrorType> | EmptyPutAPI<ResultType, ErrorType> {
|
||||
return Object.assign(
|
||||
fakePUT,
|
||||
{ reqType: 'put' } as const
|
||||
)
|
||||
}
|
||||
|
||||
export function DELETE(): EmptyDeleteAPI<ValidResponse, InvalidResponse>;
|
||||
export function DELETE<
|
||||
ResultType extends ValidResponse = ValidResponse,
|
||||
ErrorType extends InvalidResponse = InvalidResponse,
|
||||
>(): EmptyDeleteAPI<ResultType, ErrorType>;
|
||||
export function DELETE<
|
||||
ArgType extends RawArgType,
|
||||
ResultType extends ValidResponse = ValidResponse,
|
||||
ErrorType extends InvalidResponse = InvalidResponse,
|
||||
>(): ArgDeleteAPI<ArgType, ResultType, ErrorType>;
|
||||
export function DELETE<
|
||||
ArgType extends RawArgType,
|
||||
ResultType extends ValidResponse = ValidResponse,
|
||||
ErrorType extends InvalidResponse = InvalidResponse,
|
||||
>(): ArgDeleteAPI<ArgType, ResultType, ErrorType> | EmptyDeleteAPI<ResultType, ErrorType> {
|
||||
return Object.assign(
|
||||
fakeDELETE,
|
||||
{ reqType: 'delete' } as const
|
||||
)
|
||||
}
|
||||
|
||||
export function PATCH(): EmptyPatchAPI<ValidResponse, InvalidResponse>;
|
||||
export function PATCH<
|
||||
ResultType extends ValidResponse = ValidResponse,
|
||||
ErrorType extends InvalidResponse = InvalidResponse,
|
||||
>(): EmptyPatchAPI<ResultType, ErrorType>;
|
||||
export function PATCH<
|
||||
ArgType extends RawArgType,
|
||||
ResultType extends ValidResponse = ValidResponse,
|
||||
ErrorType extends InvalidResponse = InvalidResponse,
|
||||
>(): ArgPatchAPI<ArgType, ResultType, ErrorType>;
|
||||
export function PATCH<
|
||||
ArgType extends RawArgType,
|
||||
ResultType extends ValidResponse = ValidResponse,
|
||||
ErrorType extends InvalidResponse = InvalidResponse,
|
||||
>(): ArgPatchAPI<ArgType, ResultType, ErrorType> | EmptyPatchAPI<ResultType, ErrorType> {
|
||||
return Object.assign(
|
||||
fakePATCH,
|
||||
{ reqType: 'patch' } as const
|
||||
)
|
||||
}
|
||||
|
||||
export function HEAD(): EmptyHeadAPI<ValidResponse, InvalidResponse>;
|
||||
export function HEAD<
|
||||
ResultType extends ValidResponse = ValidResponse,
|
||||
ErrorType extends InvalidResponse = InvalidResponse,
|
||||
>(): EmptyHeadAPI<ResultType, ErrorType>;
|
||||
export function HEAD<
|
||||
ArgType extends RawArgType,
|
||||
ResultType extends ValidResponse = ValidResponse,
|
||||
ErrorType extends InvalidResponse = InvalidResponse,
|
||||
>(): ArgHeadAPI<ArgType, ResultType, ErrorType>;
|
||||
export function HEAD<
|
||||
ArgType extends RawArgType,
|
||||
ResultType extends ValidResponse = ValidResponse,
|
||||
ErrorType extends InvalidResponse = InvalidResponse,
|
||||
>(): ArgHeadAPI<ArgType, ResultType, ErrorType> | EmptyHeadAPI<ResultType, ErrorType> {
|
||||
return Object.assign(
|
||||
fakeHEAD,
|
||||
{ reqType: 'head' } as const
|
||||
)
|
||||
}
|
||||
|
||||
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.`
|
||||
}
|
||||
|
||||
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.`
|
||||
}
|
||||
|
||||
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.`;
|
||||
}
|
||||
|
||||
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.`;
|
||||
}
|
||||
|
||||
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.`
|
||||
}
|
||||
|
||||
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.`;
|
||||
}
|
||||
@@ -0,0 +1,191 @@
|
||||
export type HttpMethod = 'get' | 'post' | 'put' | 'delete' | 'patch' | 'head';
|
||||
export type RawArgType = {
|
||||
[key: string]: unknown;
|
||||
} | undefined;
|
||||
|
||||
|
||||
export interface ArgAnyAPI<
|
||||
ArgType extends RawArgType,
|
||||
ResultType extends ValidResponse,
|
||||
ErrorType extends InvalidResponse,
|
||||
Method extends HttpMethod
|
||||
> {
|
||||
(args: ArgType): Promise<ResultType>;
|
||||
(args: ArgType, returnError: false): Promise<ResultType>;
|
||||
(args: ArgType, returnError: true): Promise<ResultType | ErrorType>;
|
||||
readonly reqType: Method;
|
||||
}
|
||||
|
||||
export type ArgGetAPI<
|
||||
ArgType extends RawArgType,
|
||||
ResultType extends ValidResponse,
|
||||
ErrorType extends InvalidResponse
|
||||
> = ArgAnyAPI<ArgType, ResultType, ErrorType, 'get'>;
|
||||
|
||||
export type ArgPostAPI<
|
||||
ArgType extends RawArgType,
|
||||
ResultType extends ValidResponse,
|
||||
ErrorType extends InvalidResponse
|
||||
> = ArgAnyAPI<ArgType, ResultType, ErrorType, 'post'>;
|
||||
|
||||
export type ArgPutAPI<
|
||||
ArgType extends RawArgType,
|
||||
ResultType extends ValidResponse,
|
||||
ErrorType extends InvalidResponse
|
||||
> = ArgAnyAPI<ArgType, ResultType, ErrorType, 'put'>;
|
||||
|
||||
export type ArgDeleteAPI<
|
||||
ArgType extends RawArgType,
|
||||
ResultType extends ValidResponse,
|
||||
ErrorType extends InvalidResponse
|
||||
> = ArgAnyAPI<ArgType, ResultType, ErrorType, 'delete'>;
|
||||
|
||||
export type ArgPatchAPI<
|
||||
ArgType extends RawArgType,
|
||||
ResultType extends ValidResponse,
|
||||
ErrorType extends InvalidResponse
|
||||
> = ArgAnyAPI<ArgType, ResultType, ErrorType, 'patch'>;
|
||||
|
||||
export type ArgHeadAPI<
|
||||
ArgType extends RawArgType,
|
||||
ResultType extends ValidResponse,
|
||||
ErrorType extends InvalidResponse
|
||||
> = ArgAnyAPI<ArgType, ResultType, ErrorType, 'head'>;
|
||||
|
||||
export interface EmptyAnyAPI<ResultType extends ValidResponse, ErrorType extends InvalidResponse, Method extends HttpMethod> {
|
||||
(): Promise<ResultType>;
|
||||
(args?: undefined): Promise<ResultType>;
|
||||
(args: undefined, returnError: false): Promise<ResultType>;
|
||||
(args: undefined, returnError: true): Promise<ResultType | ErrorType>;
|
||||
readonly reqType: Method;
|
||||
}
|
||||
|
||||
export type EmptyGetAPI<
|
||||
ResultType extends ValidResponse,
|
||||
ErrorType extends InvalidResponse
|
||||
> = EmptyAnyAPI<ResultType, ErrorType, 'get'>;
|
||||
|
||||
export type EmptyPostAPI<
|
||||
ResultType extends ValidResponse,
|
||||
ErrorType extends InvalidResponse
|
||||
> = EmptyAnyAPI<ResultType, ErrorType, 'post'>;
|
||||
|
||||
export type EmptyPutAPI<
|
||||
ResultType extends ValidResponse,
|
||||
ErrorType extends InvalidResponse
|
||||
> = EmptyAnyAPI<ResultType, ErrorType, 'put'>;
|
||||
|
||||
export type EmptyDeleteAPI<
|
||||
ResultType extends ValidResponse,
|
||||
ErrorType extends InvalidResponse
|
||||
> = EmptyAnyAPI<ResultType, ErrorType, 'delete'>;
|
||||
|
||||
export type EmptyPatchAPI<
|
||||
ResultType extends ValidResponse,
|
||||
ErrorType extends InvalidResponse
|
||||
> = EmptyAnyAPI<ResultType, ErrorType, 'patch'>;
|
||||
|
||||
export type EmptyHeadAPI<
|
||||
ResultType extends ValidResponse,
|
||||
ErrorType extends InvalidResponse
|
||||
> = EmptyAnyAPI<ResultType, ErrorType, 'head'>;
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
export type ArgTypeOf<T> = T extends AnyAPI<infer A, any, any> ? A : never;
|
||||
|
||||
|
||||
export type AnyAPI<
|
||||
ArgType extends RawArgType,
|
||||
ResultType extends ValidResponse = ValidResponse,
|
||||
ErrorType extends InvalidResponse = InvalidResponse
|
||||
> = ArgType extends undefined ? EmptyAnyAPI<ResultType, ErrorType, HttpMethod> : ArgAnyAPI<ArgType, ResultType, ErrorType, HttpMethod>;
|
||||
|
||||
export type GetAPI<
|
||||
ArgType extends RawArgType,
|
||||
ResultType extends ValidResponse = ValidResponse,
|
||||
ErrorType extends InvalidResponse = InvalidResponse
|
||||
> = ArgType extends undefined ? EmptyGetAPI<ResultType, ErrorType> : ArgGetAPI<ArgType, ResultType, ErrorType>;
|
||||
|
||||
export type PostAPI<
|
||||
ArgType extends RawArgType,
|
||||
ResultType extends ValidResponse = ValidResponse,
|
||||
ErrorType extends InvalidResponse = InvalidResponse
|
||||
> = ArgType extends undefined ? EmptyPostAPI<ResultType, ErrorType> : ArgPostAPI<ArgType, ResultType, ErrorType>;
|
||||
|
||||
export type PutAPI<
|
||||
ArgType extends RawArgType,
|
||||
ResultType extends ValidResponse = ValidResponse,
|
||||
ErrorType extends InvalidResponse = InvalidResponse
|
||||
> = ArgType extends undefined ? EmptyPutAPI<ResultType, ErrorType> : ArgPutAPI<ArgType, ResultType, ErrorType>;
|
||||
|
||||
export type DeleteAPI<
|
||||
ArgType extends RawArgType,
|
||||
ResultType extends ValidResponse = ValidResponse,
|
||||
ErrorType extends InvalidResponse = InvalidResponse
|
||||
> = ArgType extends undefined ? EmptyDeleteAPI<ResultType, ErrorType> : ArgDeleteAPI<ArgType, ResultType, ErrorType>;
|
||||
|
||||
export type PatchAPI<
|
||||
ArgType extends RawArgType,
|
||||
ResultType extends ValidResponse = ValidResponse,
|
||||
ErrorType extends InvalidResponse = InvalidResponse
|
||||
> = ArgType extends undefined ? EmptyPatchAPI<ResultType, ErrorType> : ArgPatchAPI<ArgType, ResultType, ErrorType>;
|
||||
|
||||
export type HeadAPI<
|
||||
ArgType extends RawArgType,
|
||||
ResultType extends ValidResponse = ValidResponse,
|
||||
ErrorType extends InvalidResponse = InvalidResponse
|
||||
> = ArgType extends undefined ? EmptyHeadAPI<ResultType, ErrorType> : ArgHeadAPI<ArgType, ResultType, ErrorType>;
|
||||
|
||||
export interface ValidResponse {
|
||||
result: true;
|
||||
}
|
||||
|
||||
export type recoveryMethod = 'hardRefresh' | 'refreshEntireProcess' | 'retryAPI' | 'login';
|
||||
export interface InvalidResponse {
|
||||
result: false;
|
||||
reason: string;
|
||||
recovery?: recoveryMethod;
|
||||
detail?: string | string[] | Record<string, string | string[]>;
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
export type Callable = (...args: any) => any;
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
export type InferQuery<T extends AnyAPI<any, any, any>> = T extends EmptyAnyAPI<any, any, HttpMethod> ? undefined : T extends ArgAnyAPI<infer Q, any, any, HttpMethod> ? Q : never;
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
export type InferResponse<T extends AnyAPI<any, any, any>> = T extends EmptyAnyAPI<infer R, any, HttpMethod> ? R : T extends ArgAnyAPI<any, infer R, any, HttpMethod> ? R : never;
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
export type InferError<T extends AnyAPI<any, any, any>> = T extends EmptyAnyAPI<any, infer E, HttpMethod> ? E : T extends ArgAnyAPI<any, any, infer E, HttpMethod> ? E : never;
|
||||
|
||||
|
||||
export type DefAPINamespace = {
|
||||
[key: string]: DefAPINamespace
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
| ArgGetAPI<any, any, any>
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
| ArgPostAPI<any, any, any>
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
| ArgPutAPI<any, any, any>
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
| ArgDeleteAPI<any, any, any>
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
| ArgPatchAPI<any, any, any>
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
| ArgHeadAPI<any, any, any>
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
| EmptyGetAPI<any, any>
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
| EmptyPostAPI<any, any>
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
| EmptyPutAPI<any, any>
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
| EmptyDeleteAPI<any, any>
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
| EmptyPatchAPI<any, any>
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
| EmptyHeadAPI<any, any>
|
||||
;
|
||||
}
|
||||
|
||||
export type APICompatType<T extends Callable> = T extends AnyAPI<infer A, infer R, infer E> ? AnyAPI<A, R, E> : never;
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"extends": "../../tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"rootDir": "./src",
|
||||
"outDir": "./dist",
|
||||
},
|
||||
"references": [
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
{
|
||||
"name": "@strpc/express",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"main": "dist/index.js",
|
||||
"scripts": {
|
||||
"build": "tsc --build"
|
||||
},
|
||||
"exports": {
|
||||
".": "./dist/index.js",
|
||||
"./generator": "./dist/generator.js",
|
||||
"./proc_decorator": "./dist/proc_decorator.js"
|
||||
},
|
||||
"type": "module",
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@strpc/def": "workspace:^"
|
||||
},
|
||||
"devDependencies": {
|
||||
"express": "^4.18.2",
|
||||
"express-session": "^1.17.3",
|
||||
"lodash-es": "^4.17.21",
|
||||
"zod": "^3.22.2"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"express": "^4.18.2",
|
||||
"express-session": "^1.17.3",
|
||||
"lodash-es": "^4.17.21",
|
||||
"zod": "^3.22.2"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,213 @@
|
||||
|
||||
import type { Request, Response } from 'express';
|
||||
import type { AnyAPI, Callable, DefAPINamespace, DeleteAPI, GetAPI, HeadAPI, HttpMethod, InferError, InferQuery, InferResponse, InvalidResponse, PatchAPI, PostAPI, PutAPI, recoveryMethod } from '@strpc/def/types';
|
||||
import type { Empty, PostProcDecoratorRunner, ProcDecoratorRunner } from './proc_decorator.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>
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
| iAPI_POST<any, any>
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
| iAPI_PUT<any, any>
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
| iAPI_DELETE<any, any>
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
| iAPI_PATCH<any, any>
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
| iAPI_HEAD<any, any>
|
||||
;
|
||||
}
|
||||
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
export type AnyAPIExecuter = APIExecuter<any, any>;
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
type AnyAnyAPI = AnyAPI<any, any, any>;
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
interface APIExecuter<T extends AnyAnyAPI, CTX extends object> {
|
||||
(query: InferQuery<T>, ctx: CTX, expressReq: Request, expressRes: Response): Promise<InferResponse<T> | InferError<T> | true>;
|
||||
httpMethod: HttpMethod;
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
argValidator?: ZodType<InferQuery<T>>;
|
||||
preDecorator: ProcDecoratorRunner<CTX, Empty>;
|
||||
postDecorator: PostProcDecoratorRunner<CTX>;
|
||||
}
|
||||
|
||||
export interface iAPI_GET<T extends AnyAnyAPI, CTX extends object> extends APIExecuter<T, CTX> {
|
||||
httpMethod: 'get';
|
||||
}
|
||||
|
||||
export interface iAPI_POST<T extends AnyAnyAPI, CTX extends object> extends APIExecuter<T, CTX> {
|
||||
httpMethod: 'post';
|
||||
}
|
||||
|
||||
export interface iAPI_PUT<T extends AnyAnyAPI, CTX extends object> extends APIExecuter<T, CTX> {
|
||||
httpMethod: 'put';
|
||||
}
|
||||
|
||||
export interface iAPI_DELETE<T extends AnyAnyAPI, CTX extends object> extends APIExecuter<T, CTX> {
|
||||
httpMethod: 'delete';
|
||||
}
|
||||
|
||||
export interface iAPI_PATCH<T extends AnyAnyAPI, CTX extends object> extends APIExecuter<T, CTX> {
|
||||
httpMethod: 'patch';
|
||||
}
|
||||
|
||||
export interface iAPI_HEAD<T extends AnyAnyAPI, CTX extends object> extends APIExecuter<T, CTX> {
|
||||
httpMethod: 'head';
|
||||
}
|
||||
|
||||
|
||||
/** API의 반환형. ValidResponse | InvalidResponse | true */
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
export type APIReturnType<T extends AnyAnyAPI> = Promise<InferResponse<T> | InferError<T> | true>;
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
function generateAPI<T extends AnyAnyAPI, CTX extends object>(httpMethod: HttpMethod,
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
argValidator: ZodType<InferQuery<T>> | undefined,
|
||||
preDecorator: ProcDecoratorRunner<CTX, Empty>,
|
||||
postDecorator: PostProcDecoratorRunner<CTX>,
|
||||
callback: (query: InferQuery<T>, ctx: CTX, expressReq: Request, expressRes: Response) => Promise<InferResponse<T> | InferError<T> | true>,
|
||||
): APIExecuter<T, CTX> {
|
||||
return Object.assign(
|
||||
callback,
|
||||
{
|
||||
httpMethod,
|
||||
argValidator,
|
||||
preDecorator,
|
||||
postDecorator,
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
export function GET<T extends GetAPI<any, any, any>>(argValidator?: ZodType<InferQuery<T>>) {
|
||||
return <CTX extends object>([preDecorator, postDecorator]: readonly [ProcDecoratorRunner<CTX, Empty>, PostProcDecoratorRunner<CTX>]) => {
|
||||
return (callback: (query: InferQuery<T>, ctx: CTX, expressReq: Request, expressRes: Response) => Promise<InferResponse<T> | InferError<T> | true>) => {
|
||||
return generateAPI<T, CTX>(
|
||||
'get',
|
||||
argValidator,
|
||||
preDecorator,
|
||||
postDecorator,
|
||||
callback,
|
||||
) as iAPI_GET<T, CTX>;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
export function POST<T extends PostAPI<any, any, any>>(argValidator?: ZodType<InferQuery<T>>) {
|
||||
return <CTX extends object>([preDecorator, postDecorator]: readonly [ProcDecoratorRunner<CTX, Empty>, PostProcDecoratorRunner<CTX>]) => {
|
||||
return (callback: (query: InferQuery<T>, ctx: CTX, expressReq: Request, expressRes: Response) => Promise<InferResponse<T> | InferError<T> | true>) => {
|
||||
return generateAPI<T, CTX>(
|
||||
'post',
|
||||
argValidator,
|
||||
preDecorator,
|
||||
postDecorator,
|
||||
callback,
|
||||
) as iAPI_POST<T, CTX>;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
export function PUT<T extends PutAPI<any, any, any>>(argValidator?: ZodType<InferQuery<T>>) {
|
||||
return <CTX extends object>([preDecorator, postDecorator]: readonly [ProcDecoratorRunner<CTX, Empty>, PostProcDecoratorRunner<CTX>]) => {
|
||||
return (callback: (query: InferQuery<T>, ctx: CTX, expressReq: Request, expressRes: Response) => Promise<InferResponse<T> | InferError<T> | true>) => {
|
||||
return generateAPI<T, CTX>(
|
||||
'put',
|
||||
argValidator,
|
||||
preDecorator,
|
||||
postDecorator,
|
||||
callback,
|
||||
) as iAPI_PUT<T, CTX>;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
export function DELETE<T extends DeleteAPI<any, any, any>, Z extends ZodType<InferQuery<T>>>(argValidator?: Z) {
|
||||
return <CTX extends object>([preDecorator, postDecorator]: readonly [ProcDecoratorRunner<CTX, Empty>, PostProcDecoratorRunner<CTX>]) => {
|
||||
return (callback: (query: InferQuery<T>, ctx: CTX, expressReq: Request, expressRes: Response) => Promise<InferResponse<T> | InferError<T> | true>) => {
|
||||
return generateAPI<T, CTX>(
|
||||
'delete',
|
||||
argValidator,
|
||||
preDecorator,
|
||||
postDecorator,
|
||||
callback,
|
||||
) as iAPI_DELETE<T, CTX>;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
export function PATCH<T extends PatchAPI<any, any, any>>(argValidator?: ZodType<InferQuery<T>>) {
|
||||
return <CTX extends object>([preDecorator, postDecorator]: readonly [ProcDecoratorRunner<CTX, Empty>, PostProcDecoratorRunner<CTX>]) => {
|
||||
return (callback: (query: InferQuery<T>, ctx: CTX, expressReq: Request, expressRes: Response) => Promise<InferResponse<T> | InferError<T> | true>) => {
|
||||
return generateAPI<T, CTX>(
|
||||
'patch',
|
||||
argValidator,
|
||||
preDecorator,
|
||||
postDecorator,
|
||||
callback,
|
||||
) as iAPI_PATCH<T, CTX>;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
export function HEAD<T extends HeadAPI<any, any, any>>(argValidator?: ZodType<InferQuery<T>>) {
|
||||
return <CTX extends object>([preDecorator, postDecorator]: readonly [ProcDecoratorRunner<CTX, Empty>, PostProcDecoratorRunner<CTX>]) => {
|
||||
return (callback: (query: InferQuery<T>, ctx: CTX, expressReq: Request, expressRes: Response) => Promise<InferResponse<T> | InferError<T> | true>) => {
|
||||
return generateAPI<T, CTX>(
|
||||
'head',
|
||||
argValidator,
|
||||
preDecorator,
|
||||
postDecorator,
|
||||
callback,
|
||||
) as iAPI_HEAD<T, CTX>;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function raiseError(reason: string, recovery?: recoveryMethod): InvalidResponse {
|
||||
if (recovery) {
|
||||
return {
|
||||
result: false,
|
||||
reason,
|
||||
recovery,
|
||||
};
|
||||
}
|
||||
return {
|
||||
result: false,
|
||||
reason,
|
||||
};
|
||||
}
|
||||
|
||||
export type APIServerType<T extends Callable> =
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
T extends GetAPI<infer Q, infer R, infer E> ? iAPI_GET<GetAPI<Q, R, E>, any> :
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
T extends PostAPI<infer Q, infer R, infer E> ? iAPI_POST<PostAPI<Q, R, E>, any> :
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
T extends PutAPI<infer Q, infer R, infer E> ? iAPI_PUT<PutAPI<Q, R, E>, any> :
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
T extends DeleteAPI<infer Q, infer R, infer E> ? iAPI_DELETE<DeleteAPI<Q, R, E>, any> :
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
T extends PatchAPI<infer Q, infer R, infer E> ? iAPI_PATCH<PatchAPI<Q, R, E>, any> :
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
T extends HeadAPI<infer Q, infer R, infer E> ? iAPI_HEAD<HeadAPI<Q, R, E>, 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;
|
||||
};
|
||||
@@ -0,0 +1,161 @@
|
||||
import { Router, type Request, type Response } from 'express';
|
||||
import type { AnyAPIExecuter, APINamespace } from './defs.js';
|
||||
import type { RawArgType } from '@strpc/def';
|
||||
import type { SafeParseReturnType, ZodType, z } from 'zod';
|
||||
import { flatten } from 'lodash-es';
|
||||
|
||||
const PRINT_API_CALL = true;
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
async function parseParam<Q extends RawArgType>(req: Request, argValidator?: ZodType<Q>): Promise<SafeParseReturnType<Q, Q>> {
|
||||
if (!argValidator) {
|
||||
return {
|
||||
success: true,
|
||||
data: req.query as Q
|
||||
}
|
||||
}
|
||||
|
||||
const query = req.query;
|
||||
return await argValidator.safeParseAsync(query);
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
async function parseBody<Q extends RawArgType>(req: Request, argValidator?: ZodType<Q>): Promise<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<Q extends RawArgType>(query: Q, 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) {
|
||||
//회수조차 불가능?
|
||||
if (PRINT_API_CALL) {
|
||||
console.log(JSON.stringify([(new Date).toISOString(), req.ip, req.path, false, 'preDecorator', lastErr.type, lastErr.info]));
|
||||
}
|
||||
res.json({
|
||||
result: false,
|
||||
path: req.path,
|
||||
reason: lastErr.info,
|
||||
recovery: lastErr.recovery,
|
||||
detail: {
|
||||
type: 'decorator',
|
||||
preDecorator: [lastErr.type, lastErr.info],
|
||||
postDecorator: flatten(postErrors.map((obj) => [obj.type, obj.info])),
|
||||
},
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if (PRINT_API_CALL) {
|
||||
console.log(JSON.stringify([(new Date).toISOString(), req.ip, req.path, false, 'preDecorator', lastErr.type, lastErr.info]));
|
||||
}
|
||||
res.json({
|
||||
result: false,
|
||||
path: req.path,
|
||||
reason: lastErr.info,
|
||||
recovery: lastErr.recovery,
|
||||
detail: {
|
||||
type: 'decorator',
|
||||
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) {
|
||||
const lastErr = postErrors.pop() as typeof postErrors[0];
|
||||
if (PRINT_API_CALL) {
|
||||
console.log(JSON.stringify([(new Date).toISOString(), req.ip, req.path, false, 'postDecorator', lastErr.type, lastErr.info]));
|
||||
}
|
||||
if (result === true) {
|
||||
//NOTE: 이미 api에서 response를 보낸 특이 케이스.
|
||||
return;
|
||||
}
|
||||
res.json({
|
||||
result: false,
|
||||
path: req.path,
|
||||
reason: lastErr?.info,
|
||||
recovery: lastErr?.recovery,
|
||||
detail: {
|
||||
type: 'decorator',
|
||||
preDecorator: flatten(postErrors.map((obj) => [obj.type, obj.info])),
|
||||
},
|
||||
originalResult: result,
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if (PRINT_API_CALL) {
|
||||
if(result === true){
|
||||
console.log(JSON.stringify([(new Date).toISOString(), req.ip, req.path, true, 'passThrough']));
|
||||
}
|
||||
else{
|
||||
let tmp_result = true;
|
||||
let tmp_reason = undefined;
|
||||
if('result' in result){
|
||||
tmp_result = result.result;
|
||||
}
|
||||
if('reason' in result){
|
||||
tmp_reason = result.reason;
|
||||
}
|
||||
console.log(JSON.stringify([(new Date).toISOString(), req.ip, req.path, tmp_result, tmp_reason]));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
export * from './defs.js';
|
||||
export * as generator from './generator.js';
|
||||
export * as proc_decorator from './proc_decorator.js';
|
||||
@@ -0,0 +1,187 @@
|
||||
import type { recoveryMethod } from "@strpc/def";
|
||||
import type { Request, Response } from "express";
|
||||
|
||||
type MayBePromise<T> = T | Promise<T>;
|
||||
|
||||
export type Empty = Record<string, never>;
|
||||
export type DecoratorResultTrue = {
|
||||
result: true;
|
||||
type?: string;
|
||||
info?: string;
|
||||
recovery?: recoveryMethod;
|
||||
};
|
||||
export type DecoratorResultFalse = {
|
||||
result: false;
|
||||
type: string;
|
||||
info: string;
|
||||
recovery?: recoveryMethod;
|
||||
}
|
||||
export type DecoratorResult = DecoratorResultTrue | DecoratorResultFalse;
|
||||
export type DecoratorStack = DecoratorResult[];
|
||||
|
||||
export interface ProcDecorator<Out extends object, In extends object = Empty> {
|
||||
(inCtx: In & Partial<Out>, req: Request, res: Response)
|
||||
: MayBePromise<[DecoratorResultTrue, Out]>
|
||||
| MayBePromise<[DecoratorResultFalse, In & Partial<Out>]>;
|
||||
}
|
||||
|
||||
export interface PostProcDecorator<T extends object> {
|
||||
(ctx: T, preResult: DecoratorResult, req: Request, res: Response, isValidRoute: boolean): MayBePromise<[DecoratorResult, T]>;
|
||||
}
|
||||
|
||||
export interface ProcDecoratorRunner<Out extends object, In extends object> {
|
||||
(inCtx: In & Partial<Out>, req: Request, res: Response): MayBePromise<[DecoratorStack, Out]>;
|
||||
}
|
||||
|
||||
export interface PostProcDecoratorRunner<T extends object> {
|
||||
(ctx: T, preResult: DecoratorStack, req: Request, res: Response, isValidRoute: boolean): MayBePromise<[DecoratorStack, T]>;
|
||||
}
|
||||
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
type PlainDecorator = ProcDecorator<any, any>;
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
type PlainPostDecorator = PostProcDecorator<any>;
|
||||
|
||||
|
||||
export type ProcDecoratorGenerator<B extends object, A extends object> = ProcDecorator<B & A, A>;
|
||||
export type ProcDecoratorPrePostGenerator<B extends object, A extends object> = [ProcDecorator<B & A, A>, PostProcDecorator<B & A>];
|
||||
|
||||
export type ProcDecoratorChain = readonly ((() => PlainDecorator) | (() => [PlainDecorator, PlainPostDecorator]))[];
|
||||
|
||||
export type ResolveChain<T> = T extends undefined ? Empty : T extends ProcDecoratorChain ? Resolve<PackChain<T>> : never;
|
||||
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
export type ParseInType<T> = T extends ProcDecorator<any, infer A> ? object extends A ? A : never : never;
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
export type ParseOutType<T> = T extends ProcDecorator<infer B, object> ? B : never;
|
||||
|
||||
export const EmptyProcDecorator: readonly [ProcDecoratorRunner<Empty, Empty>, PostProcDecoratorRunner<Empty>] = [
|
||||
async (ctx) => [[], ctx], async (ctx, stack) => [stack, ctx]
|
||||
];
|
||||
|
||||
export function declProcDecorators<T extends ProcDecoratorChain>(...decorators: T) {
|
||||
type OutType = ParseOutType<PackChain<T>>;
|
||||
|
||||
const preDecorator: PlainDecorator[] = [];
|
||||
const postDecorator: (PlainPostDecorator | undefined)[] = [];
|
||||
if (decorators) {
|
||||
for (const procGen of decorators) {
|
||||
const proc = procGen();
|
||||
if (Array.isArray(proc)) {
|
||||
preDecorator.push(proc[0]);
|
||||
postDecorator.push(proc[1]);
|
||||
}
|
||||
else {
|
||||
preDecorator.push(proc);
|
||||
postDecorator.push(undefined);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const packedDecorators: readonly [ProcDecoratorRunner<OutType, Empty>, PostProcDecoratorRunner<OutType>] = [
|
||||
async (ctx, req, res) => {
|
||||
let rctx = ctx as unknown as OutType;
|
||||
const decoratorStack: DecoratorStack = [];
|
||||
if (!preDecorator) {
|
||||
return [decoratorStack, rctx];
|
||||
}
|
||||
|
||||
for (const [idx, proc] of preDecorator.entries()) {
|
||||
try {
|
||||
const [stackResult, newCtx] = await proc(rctx, req, res);
|
||||
decoratorStack.push(stackResult);
|
||||
|
||||
if (stackResult.result) {
|
||||
rctx = newCtx;
|
||||
continue;
|
||||
}
|
||||
|
||||
return [decoratorStack, newCtx];
|
||||
}
|
||||
catch (e) {
|
||||
while (decoratorStack.length > idx) {
|
||||
decoratorStack.pop();
|
||||
}
|
||||
decoratorStack.push({
|
||||
result: false,
|
||||
type: 'PreThrow',
|
||||
info: `internal error: ${e}`,
|
||||
});
|
||||
|
||||
return [decoratorStack, rctx];
|
||||
}
|
||||
}
|
||||
|
||||
return [decoratorStack, rctx];
|
||||
},
|
||||
async (ctx, stack, req, res) => {
|
||||
if (!postDecorator.length) {
|
||||
return [stack, ctx];
|
||||
}
|
||||
let isValidRoute = stack.length === postDecorator.length && stack.every(v => v.result);
|
||||
for (let idx = stack.length - 1; idx >= 0; idx--) {
|
||||
const preStackResult = stack[idx] as DecoratorResult;
|
||||
if (!preStackResult.result) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const proc = postDecorator[idx];
|
||||
|
||||
if (!proc) {
|
||||
if (isValidRoute) {
|
||||
stack.pop();
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
const [postStackResult, nextCtx] = await proc(ctx, preStackResult, req, res, isValidRoute);
|
||||
if (postStackResult.result) {
|
||||
if (isValidRoute) {
|
||||
stack.pop();
|
||||
}
|
||||
ctx = nextCtx;
|
||||
continue;
|
||||
}
|
||||
|
||||
isValidRoute = false;
|
||||
stack[idx] = postStackResult;
|
||||
|
||||
ctx = nextCtx;
|
||||
}
|
||||
catch (e) {
|
||||
isValidRoute = false;
|
||||
stack[idx] = {
|
||||
result: false,
|
||||
type: 'PostThrow',
|
||||
info: `internal error: ${e}`,
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
return [stack, ctx];
|
||||
},
|
||||
] as const;
|
||||
|
||||
return packedDecorators;
|
||||
}
|
||||
|
||||
type Compose2<B extends object, A extends object, D extends object, C> = B extends C ? ProcDecorator<D & B, A> : never;
|
||||
|
||||
type PD1<B extends object, A extends object> = () => ProcDecorator<B, A>;
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
type PD2<B extends object, A extends object> = () => [ProcDecorator<B, A>, PostProcDecorator<any>];
|
||||
|
||||
export type PackChain<T> =
|
||||
T extends readonly [] ? ProcDecorator<Empty, Empty> :
|
||||
T extends readonly [PD1<infer B, infer A>] ? ProcDecorator<B, A> :
|
||||
T extends readonly [PD2<infer B, infer A>] ? ProcDecorator<B, A> :
|
||||
T extends readonly [PD1<infer B, infer A>, PD1<infer D, infer C>, ... infer R] ? PackChain<[() => Compose2<B, A, D, C>, ...R]> :
|
||||
T extends readonly [PD2<infer B, infer A>, PD1<infer D, infer C>, ... infer R] ? PackChain<[() => Compose2<B, A, D, C>, ...R]> :
|
||||
T extends readonly [PD1<infer B, infer A>, PD2<infer D, infer C>, ... infer R] ? PackChain<[() => Compose2<B, A, D, C>, ...R]> :
|
||||
T extends readonly [PD2<infer B, infer A>, PD2<infer D, infer C>, ... infer R] ? PackChain<[() => Compose2<B, A, D, C>, ...R]> :
|
||||
never;
|
||||
|
||||
type Resolve<T> = T extends ProcDecorator<infer B, infer A> ? Empty extends A ? B : never : never;
|
||||
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"extends": "../../tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"rootDir": "./src",
|
||||
"outDir": "./dist",
|
||||
},
|
||||
"references": [
|
||||
{
|
||||
"path": "../def"
|
||||
},
|
||||
]
|
||||
}
|
||||
Generated
+176
-186
@@ -4,138 +4,174 @@ settings:
|
||||
autoInstallPeers: true
|
||||
excludeLinksFromLockfile: false
|
||||
|
||||
dependencies:
|
||||
'@esfx/async-readerwriterlock':
|
||||
specifier: ^1.0.0
|
||||
version: 1.0.0
|
||||
'@popperjs/core':
|
||||
specifier: ^2.11.8
|
||||
version: 2.11.8
|
||||
async-lock:
|
||||
specifier: ^1.4.0
|
||||
version: 1.4.0
|
||||
bootstrap:
|
||||
specifier: ^5.3.1
|
||||
version: 5.3.1(@popperjs/core@2.11.8)
|
||||
bootstrap-vue-next:
|
||||
specifier: ^0.9.26
|
||||
version: 0.9.26(vue@3.3.4)
|
||||
bson:
|
||||
specifier: ^5.4.0
|
||||
version: 5.4.0
|
||||
buffer:
|
||||
specifier: ^6.0.3
|
||||
version: 6.0.3
|
||||
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: ^0.33.3
|
||||
version: 0.33.3
|
||||
lodash-es:
|
||||
specifier: ^4.17.21
|
||||
version: 4.17.21
|
||||
mongoose:
|
||||
specifier: ^7.4.3
|
||||
version: 7.4.3
|
||||
pinia:
|
||||
specifier: ^2.1.4
|
||||
version: 2.1.4(typescript@5.1.6)(vue@3.3.4)
|
||||
reflect-metadata:
|
||||
specifier: ^0.1.13
|
||||
version: 0.1.13
|
||||
tslib:
|
||||
specifier: ^2.6.1
|
||||
version: 2.6.1
|
||||
vue:
|
||||
specifier: ^3.3.4
|
||||
version: 3.3.4
|
||||
vue-router:
|
||||
specifier: ^4.2.4
|
||||
version: 4.2.4(vue@3.3.4)
|
||||
zod:
|
||||
specifier: ^3.22.1
|
||||
version: 3.22.1
|
||||
importers:
|
||||
|
||||
devDependencies:
|
||||
'@rushstack/eslint-patch':
|
||||
specifier: ^1.3.2
|
||||
version: 1.3.2
|
||||
'@tsconfig/node18':
|
||||
specifier: ^18.2.0
|
||||
version: 18.2.0
|
||||
'@types/async-lock':
|
||||
specifier: ^1.4.0
|
||||
version: 1.4.0
|
||||
'@types/bootstrap':
|
||||
specifier: ^5.2.6
|
||||
version: 5.2.6
|
||||
'@types/express':
|
||||
specifier: ^4.17.17
|
||||
version: 4.17.17
|
||||
'@types/express-session':
|
||||
specifier: ^1.17.7
|
||||
version: 1.17.7
|
||||
'@types/lodash-es':
|
||||
specifier: ^4.17.8
|
||||
version: 4.17.8
|
||||
'@types/node':
|
||||
specifier: ^18.17.0
|
||||
version: 18.17.0
|
||||
'@vitejs/plugin-vue':
|
||||
specifier: ^4.2.3
|
||||
version: 4.2.3(vite@4.4.6)(vue@3.3.4)
|
||||
'@vue/eslint-config-prettier':
|
||||
specifier: ^8.0.0
|
||||
version: 8.0.0(eslint@8.45.0)(prettier@3.0.0)
|
||||
'@vue/eslint-config-typescript':
|
||||
specifier: ^11.0.3
|
||||
version: 11.0.3(eslint-plugin-vue@9.15.1)(eslint@8.45.0)(typescript@5.1.6)
|
||||
'@vue/tsconfig':
|
||||
specifier: ^0.4.0
|
||||
version: 0.4.0
|
||||
concurrently:
|
||||
specifier: ^8.2.0
|
||||
version: 8.2.0
|
||||
eslint:
|
||||
specifier: ^8.45.0
|
||||
version: 8.45.0
|
||||
eslint-plugin-vue:
|
||||
specifier: ^9.15.1
|
||||
version: 9.15.1(eslint@8.45.0)
|
||||
npm-run-all:
|
||||
specifier: ^4.1.5
|
||||
version: 4.1.5
|
||||
prettier:
|
||||
specifier: ^3.0.0
|
||||
version: 3.0.0
|
||||
ts-node:
|
||||
specifier: ^10.9.1
|
||||
version: 10.9.1(@types/node@18.17.0)(typescript@5.1.6)
|
||||
tsc-watch:
|
||||
specifier: ^6.0.4
|
||||
version: 6.0.4(typescript@5.1.6)
|
||||
typescript:
|
||||
specifier: ~5.1.6
|
||||
version: 5.1.6
|
||||
vite:
|
||||
specifier: ^4.4.6
|
||||
version: 4.4.6(@types/node@18.17.0)
|
||||
vue-tsc:
|
||||
specifier: ^1.8.6
|
||||
version: 1.8.6(typescript@5.1.6)
|
||||
.:
|
||||
dependencies:
|
||||
'@esfx/async-readerwriterlock':
|
||||
specifier: ^1.0.0
|
||||
version: 1.0.0
|
||||
'@popperjs/core':
|
||||
specifier: ^2.11.8
|
||||
version: 2.11.8
|
||||
async-lock:
|
||||
specifier: ^1.4.0
|
||||
version: 1.4.0
|
||||
bootstrap:
|
||||
specifier: ^5.3.1
|
||||
version: 5.3.1(@popperjs/core@2.11.8)
|
||||
bootstrap-vue-next:
|
||||
specifier: ^0.9.26
|
||||
version: 0.9.26(vue@3.3.4)
|
||||
bson:
|
||||
specifier: ^5.4.0
|
||||
version: 5.4.0
|
||||
buffer:
|
||||
specifier: ^6.0.3
|
||||
version: 6.0.3
|
||||
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: ^0.33.3
|
||||
version: 0.33.3
|
||||
lodash-es:
|
||||
specifier: ^4.17.21
|
||||
version: 4.17.21
|
||||
mongoose:
|
||||
specifier: ^7.4.3
|
||||
version: 7.4.3
|
||||
pinia:
|
||||
specifier: ^2.1.4
|
||||
version: 2.1.4(typescript@5.1.6)(vue@3.3.4)
|
||||
reflect-metadata:
|
||||
specifier: ^0.1.13
|
||||
version: 0.1.13
|
||||
tslib:
|
||||
specifier: ^2.6.1
|
||||
version: 2.6.1
|
||||
vue:
|
||||
specifier: ^3.3.4
|
||||
version: 3.3.4
|
||||
vue-router:
|
||||
specifier: ^4.2.4
|
||||
version: 4.2.4(vue@3.3.4)
|
||||
zod:
|
||||
specifier: ^3.22.1
|
||||
version: 3.22.1
|
||||
devDependencies:
|
||||
'@rushstack/eslint-patch':
|
||||
specifier: ^1.3.2
|
||||
version: 1.3.2
|
||||
'@tsconfig/node18':
|
||||
specifier: ^18.2.0
|
||||
version: 18.2.0
|
||||
'@types/async-lock':
|
||||
specifier: ^1.4.0
|
||||
version: 1.4.0
|
||||
'@types/bootstrap':
|
||||
specifier: ^5.2.6
|
||||
version: 5.2.6
|
||||
'@types/express':
|
||||
specifier: ^4.17.17
|
||||
version: 4.17.17
|
||||
'@types/express-session':
|
||||
specifier: ^1.17.7
|
||||
version: 1.17.7
|
||||
'@types/lodash-es':
|
||||
specifier: ^4.17.8
|
||||
version: 4.17.8
|
||||
'@types/node':
|
||||
specifier: ^18.17.0
|
||||
version: 18.17.0
|
||||
'@vitejs/plugin-vue':
|
||||
specifier: ^4.2.3
|
||||
version: 4.2.3(vite@4.4.6)(vue@3.3.4)
|
||||
'@vue/eslint-config-prettier':
|
||||
specifier: ^8.0.0
|
||||
version: 8.0.0(eslint@8.45.0)(prettier@3.0.0)
|
||||
'@vue/eslint-config-typescript':
|
||||
specifier: ^11.0.3
|
||||
version: 11.0.3(eslint-plugin-vue@9.15.1)(eslint@8.45.0)(typescript@5.1.6)
|
||||
'@vue/tsconfig':
|
||||
specifier: ^0.4.0
|
||||
version: 0.4.0
|
||||
concurrently:
|
||||
specifier: ^8.2.0
|
||||
version: 8.2.0
|
||||
eslint:
|
||||
specifier: ^8.45.0
|
||||
version: 8.45.0
|
||||
eslint-plugin-vue:
|
||||
specifier: ^9.15.1
|
||||
version: 9.15.1(eslint@8.45.0)
|
||||
npm-run-all:
|
||||
specifier: ^4.1.5
|
||||
version: 4.1.5
|
||||
prettier:
|
||||
specifier: ^3.0.0
|
||||
version: 3.0.0
|
||||
ts-node:
|
||||
specifier: ^10.9.1
|
||||
version: 10.9.1(@types/node@18.17.0)(typescript@5.1.6)
|
||||
tsc-watch:
|
||||
specifier: ^6.0.4
|
||||
version: 6.0.4(typescript@5.1.6)
|
||||
typescript:
|
||||
specifier: ~5.1.6
|
||||
version: 5.1.6
|
||||
vite:
|
||||
specifier: ^4.4.6
|
||||
version: 4.4.6(@types/node@18.17.0)
|
||||
vue-tsc:
|
||||
specifier: ^1.8.6
|
||||
version: 1.8.6(typescript@5.1.6)
|
||||
|
||||
'@strpc/client_ky':
|
||||
dependencies:
|
||||
'@strpc/def':
|
||||
specifier: workspace:^
|
||||
version: link:../def
|
||||
devDependencies:
|
||||
ky:
|
||||
specifier: ^1.0.1
|
||||
version: 1.0.1
|
||||
lodash-es:
|
||||
specifier: ^4.17.21
|
||||
version: 4.17.21
|
||||
|
||||
'@strpc/def': {}
|
||||
|
||||
'@strpc/express':
|
||||
dependencies:
|
||||
'@strpc/def':
|
||||
specifier: workspace:^
|
||||
version: link:../def
|
||||
devDependencies:
|
||||
express:
|
||||
specifier: ^4.18.2
|
||||
version: 4.18.2
|
||||
express-session:
|
||||
specifier: ^1.17.3
|
||||
version: 1.17.3
|
||||
lodash-es:
|
||||
specifier: ^4.17.21
|
||||
version: 4.17.21
|
||||
zod:
|
||||
specifier: ^3.22.2
|
||||
version: 3.22.2
|
||||
|
||||
packages:
|
||||
|
||||
@@ -1021,7 +1057,6 @@ packages:
|
||||
dependencies:
|
||||
mime-types: 2.1.35
|
||||
negotiator: 0.6.3
|
||||
dev: false
|
||||
|
||||
/acorn-jsx@5.3.2(acorn@8.10.0):
|
||||
resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==}
|
||||
@@ -1087,7 +1122,6 @@ packages:
|
||||
|
||||
/array-flatten@1.1.1:
|
||||
resolution: {integrity: sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==}
|
||||
dev: false
|
||||
|
||||
/array-union@2.1.0:
|
||||
resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==}
|
||||
@@ -1146,7 +1180,6 @@ packages:
|
||||
unpipe: 1.0.0
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
dev: false
|
||||
|
||||
/boolbase@1.0.0:
|
||||
resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==}
|
||||
@@ -1221,7 +1254,6 @@ packages:
|
||||
/bytes@3.1.2:
|
||||
resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==}
|
||||
engines: {node: '>= 0.8'}
|
||||
dev: false
|
||||
|
||||
/call-bind@1.0.2:
|
||||
resolution: {integrity: sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==}
|
||||
@@ -1306,26 +1338,21 @@ packages:
|
||||
engines: {node: '>= 0.6'}
|
||||
dependencies:
|
||||
safe-buffer: 5.2.1
|
||||
dev: false
|
||||
|
||||
/content-type@1.0.5:
|
||||
resolution: {integrity: sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==}
|
||||
engines: {node: '>= 0.6'}
|
||||
dev: false
|
||||
|
||||
/cookie-signature@1.0.6:
|
||||
resolution: {integrity: sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==}
|
||||
dev: false
|
||||
|
||||
/cookie@0.4.2:
|
||||
resolution: {integrity: sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==}
|
||||
engines: {node: '>= 0.6'}
|
||||
dev: false
|
||||
|
||||
/cookie@0.5.0:
|
||||
resolution: {integrity: sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==}
|
||||
engines: {node: '>= 0.6'}
|
||||
dev: false
|
||||
|
||||
/create-require@1.1.1:
|
||||
resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==}
|
||||
@@ -1379,7 +1406,6 @@ packages:
|
||||
optional: true
|
||||
dependencies:
|
||||
ms: 2.0.0
|
||||
dev: false
|
||||
|
||||
/debug@4.3.4:
|
||||
resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==}
|
||||
@@ -1430,12 +1456,10 @@ packages:
|
||||
/depd@2.0.0:
|
||||
resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==}
|
||||
engines: {node: '>= 0.8'}
|
||||
dev: false
|
||||
|
||||
/destroy@1.2.0:
|
||||
resolution: {integrity: sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==}
|
||||
engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16}
|
||||
dev: false
|
||||
|
||||
/diff@4.0.2:
|
||||
resolution: {integrity: sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==}
|
||||
@@ -1467,7 +1491,6 @@ packages:
|
||||
|
||||
/ee-first@1.1.1:
|
||||
resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==}
|
||||
dev: false
|
||||
|
||||
/emoji-regex@8.0.0:
|
||||
resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==}
|
||||
@@ -1476,7 +1499,6 @@ packages:
|
||||
/encodeurl@1.0.2:
|
||||
resolution: {integrity: sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==}
|
||||
engines: {node: '>= 0.8'}
|
||||
dev: false
|
||||
|
||||
/error-ex@1.3.2:
|
||||
resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==}
|
||||
@@ -1584,7 +1606,6 @@ packages:
|
||||
|
||||
/escape-html@1.0.3:
|
||||
resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==}
|
||||
dev: false
|
||||
|
||||
/escape-string-regexp@1.0.5:
|
||||
resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==}
|
||||
@@ -1755,7 +1776,6 @@ packages:
|
||||
/etag@1.8.1:
|
||||
resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==}
|
||||
engines: {node: '>= 0.6'}
|
||||
dev: false
|
||||
|
||||
/event-stream@3.3.4:
|
||||
resolution: {integrity: sha512-QHpkERcGsR0T7Qm3HNJSyXKEEj8AHNxkY3PK8TS2KJvQ7NiSHe3DDpwVKKtoYprL/AreyzFBeIkBIWChAqn60g==}
|
||||
@@ -1817,7 +1837,6 @@ packages:
|
||||
uid-safe: 2.1.5
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
dev: false
|
||||
|
||||
/express@4.18.2:
|
||||
resolution: {integrity: sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==}
|
||||
@@ -1856,7 +1875,6 @@ packages:
|
||||
vary: 1.1.2
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
dev: false
|
||||
|
||||
/fast-deep-equal@3.1.3:
|
||||
resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==}
|
||||
@@ -1918,7 +1936,6 @@ packages:
|
||||
unpipe: 1.0.0
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
dev: false
|
||||
|
||||
/find-up@5.0.0:
|
||||
resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==}
|
||||
@@ -1949,12 +1966,10 @@ packages:
|
||||
/forwarded@0.2.0:
|
||||
resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==}
|
||||
engines: {node: '>= 0.6'}
|
||||
dev: false
|
||||
|
||||
/fresh@0.5.2:
|
||||
resolution: {integrity: sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==}
|
||||
engines: {node: '>= 0.6'}
|
||||
dev: false
|
||||
|
||||
/from@0.1.7:
|
||||
resolution: {integrity: sha512-twe20eF1OxVxp/ML/kq2p1uc6KvFK/+vs8WjEbeKmV2He22MKm7YF2ANIt+EOqhJ5L3K/SuuPhk0hWQDjOM23g==}
|
||||
@@ -2139,7 +2154,6 @@ packages:
|
||||
setprototypeof: 1.2.0
|
||||
statuses: 2.0.1
|
||||
toidentifier: 1.0.1
|
||||
dev: false
|
||||
|
||||
/human-signals@2.1.0:
|
||||
resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==}
|
||||
@@ -2156,7 +2170,6 @@ packages:
|
||||
engines: {node: '>=0.10.0'}
|
||||
dependencies:
|
||||
safer-buffer: 2.1.2
|
||||
dev: false
|
||||
|
||||
/ieee754@1.2.1:
|
||||
resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==}
|
||||
@@ -2206,7 +2219,6 @@ packages:
|
||||
/ipaddr.js@1.9.1:
|
||||
resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==}
|
||||
engines: {node: '>= 0.10'}
|
||||
dev: false
|
||||
|
||||
/is-array-buffer@3.0.2:
|
||||
resolution: {integrity: sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==}
|
||||
@@ -2406,6 +2418,11 @@ packages:
|
||||
engines: {node: '>=14.16'}
|
||||
dev: false
|
||||
|
||||
/ky@1.0.1:
|
||||
resolution: {integrity: sha512-UvcwpQO0LOuZwG0Ti3VDo6w57KYt+r4bWEYlNaMt82hgyFtse86QtOGum1RzsZni31FndXQl6NvtDArfunt2JQ==}
|
||||
engines: {node: '>=18'}
|
||||
dev: true
|
||||
|
||||
/levn@0.4.1:
|
||||
resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==}
|
||||
engines: {node: '>= 0.8.0'}
|
||||
@@ -2433,7 +2450,6 @@ packages:
|
||||
|
||||
/lodash-es@4.17.21:
|
||||
resolution: {integrity: sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==}
|
||||
dev: false
|
||||
|
||||
/lodash.merge@4.6.2:
|
||||
resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==}
|
||||
@@ -2467,7 +2483,6 @@ packages:
|
||||
/media-typer@0.3.0:
|
||||
resolution: {integrity: sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==}
|
||||
engines: {node: '>= 0.6'}
|
||||
dev: false
|
||||
|
||||
/memory-pager@1.5.0:
|
||||
resolution: {integrity: sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==}
|
||||
@@ -2482,7 +2497,6 @@ packages:
|
||||
|
||||
/merge-descriptors@1.0.1:
|
||||
resolution: {integrity: sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==}
|
||||
dev: false
|
||||
|
||||
/merge-stream@2.0.0:
|
||||
resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==}
|
||||
@@ -2496,7 +2510,6 @@ packages:
|
||||
/methods@1.1.2:
|
||||
resolution: {integrity: sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==}
|
||||
engines: {node: '>= 0.6'}
|
||||
dev: false
|
||||
|
||||
/micromatch@4.0.5:
|
||||
resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==}
|
||||
@@ -2509,20 +2522,17 @@ packages:
|
||||
/mime-db@1.52.0:
|
||||
resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==}
|
||||
engines: {node: '>= 0.6'}
|
||||
dev: false
|
||||
|
||||
/mime-types@2.1.35:
|
||||
resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==}
|
||||
engines: {node: '>= 0.6'}
|
||||
dependencies:
|
||||
mime-db: 1.52.0
|
||||
dev: false
|
||||
|
||||
/mime@1.6.0:
|
||||
resolution: {integrity: sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==}
|
||||
engines: {node: '>=4'}
|
||||
hasBin: true
|
||||
dev: false
|
||||
|
||||
/mimic-fn@2.1.0:
|
||||
resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==}
|
||||
@@ -2618,14 +2628,12 @@ packages:
|
||||
|
||||
/ms@2.0.0:
|
||||
resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==}
|
||||
dev: false
|
||||
|
||||
/ms@2.1.2:
|
||||
resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==}
|
||||
|
||||
/ms@2.1.3:
|
||||
resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
|
||||
dev: false
|
||||
|
||||
/muggle-string@0.3.1:
|
||||
resolution: {integrity: sha512-ckmWDJjphvd/FvZawgygcUeQCxzvohjFO5RxTjj4eq8kw359gFF3E1brjfI+viLMxss5JrHTDRHZvu2/tuy0Qg==}
|
||||
@@ -2647,7 +2655,6 @@ packages:
|
||||
/negotiator@0.6.3:
|
||||
resolution: {integrity: sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==}
|
||||
engines: {node: '>= 0.6'}
|
||||
dev: false
|
||||
|
||||
/nice-try@1.0.5:
|
||||
resolution: {integrity: sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==}
|
||||
@@ -2725,12 +2732,10 @@ packages:
|
||||
engines: {node: '>= 0.8'}
|
||||
dependencies:
|
||||
ee-first: 1.1.1
|
||||
dev: false
|
||||
|
||||
/on-headers@1.0.2:
|
||||
resolution: {integrity: sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==}
|
||||
engines: {node: '>= 0.8'}
|
||||
dev: false
|
||||
|
||||
/once@1.4.0:
|
||||
resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==}
|
||||
@@ -2806,7 +2811,6 @@ packages:
|
||||
/parseurl@1.3.3:
|
||||
resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==}
|
||||
engines: {node: '>= 0.8'}
|
||||
dev: false
|
||||
|
||||
/path-exists@4.0.0:
|
||||
resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==}
|
||||
@@ -2839,7 +2843,6 @@ packages:
|
||||
|
||||
/path-to-regexp@0.1.7:
|
||||
resolution: {integrity: sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==}
|
||||
dev: false
|
||||
|
||||
/path-type@3.0.0:
|
||||
resolution: {integrity: sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==}
|
||||
@@ -2936,7 +2939,6 @@ packages:
|
||||
dependencies:
|
||||
forwarded: 0.2.0
|
||||
ipaddr.js: 1.9.1
|
||||
dev: false
|
||||
|
||||
/ps-tree@1.2.0:
|
||||
resolution: {integrity: sha512-0VnamPPYHl4uaU/nSFeZZpR21QAWRz+sRv4iW9+v/GS/J5U5iZB5BNN6J0RMoOvdx2gWM2+ZFMIm58q24e4UYA==}
|
||||
@@ -2955,7 +2957,6 @@ packages:
|
||||
engines: {node: '>=0.6'}
|
||||
dependencies:
|
||||
side-channel: 1.0.4
|
||||
dev: false
|
||||
|
||||
/queue-microtask@1.2.3:
|
||||
resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==}
|
||||
@@ -2964,12 +2965,10 @@ packages:
|
||||
/random-bytes@1.0.0:
|
||||
resolution: {integrity: sha512-iv7LhNVO047HzYR3InF6pUcUsPQiHTM1Qal51DcGSuZFBil1aBBWG5eHPNek7bvILMaYJ/8RU1e8w1AMdHmLQQ==}
|
||||
engines: {node: '>= 0.8'}
|
||||
dev: false
|
||||
|
||||
/range-parser@1.2.1:
|
||||
resolution: {integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==}
|
||||
engines: {node: '>= 0.6'}
|
||||
dev: false
|
||||
|
||||
/raw-body@2.5.1:
|
||||
resolution: {integrity: sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==}
|
||||
@@ -2979,7 +2978,6 @@ packages:
|
||||
http-errors: 2.0.0
|
||||
iconv-lite: 0.4.24
|
||||
unpipe: 1.0.0
|
||||
dev: false
|
||||
|
||||
/read-pkg@3.0.0:
|
||||
resolution: {integrity: sha512-BLq/cCO9two+lBgiTYNqD6GdtK8s4NpaWrl6/rCO9w0TUS8oJl7cmToOZfRYllKTISY6nt1U7jQ53brmKqY6BA==}
|
||||
@@ -3076,7 +3074,6 @@ packages:
|
||||
|
||||
/safe-buffer@5.2.1:
|
||||
resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==}
|
||||
dev: false
|
||||
|
||||
/safe-regex-test@1.0.0:
|
||||
resolution: {integrity: sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==}
|
||||
@@ -3088,7 +3085,6 @@ packages:
|
||||
|
||||
/safer-buffer@2.1.2:
|
||||
resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==}
|
||||
dev: false
|
||||
|
||||
/saslprep@1.0.3:
|
||||
resolution: {integrity: sha512-/MY/PEMbk2SuY5sScONwhUDsV2p77Znkb/q3nSVstq/yQzYJOH/Azh29p9oJLsl3LnQwSvZDKagDGBsBwSooag==}
|
||||
@@ -3131,7 +3127,6 @@ packages:
|
||||
statuses: 2.0.1
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
dev: false
|
||||
|
||||
/serve-static@1.15.0:
|
||||
resolution: {integrity: sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==}
|
||||
@@ -3143,11 +3138,9 @@ packages:
|
||||
send: 0.18.0
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
dev: false
|
||||
|
||||
/setprototypeof@1.2.0:
|
||||
resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==}
|
||||
dev: false
|
||||
|
||||
/shebang-command@1.2.0:
|
||||
resolution: {integrity: sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==}
|
||||
@@ -3257,7 +3250,6 @@ packages:
|
||||
/statuses@2.0.1:
|
||||
resolution: {integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==}
|
||||
engines: {node: '>= 0.8'}
|
||||
dev: false
|
||||
|
||||
/stream-combiner@0.0.4:
|
||||
resolution: {integrity: sha512-rT00SPnTVyRsaSz5zgSPma/aHSOic5U1prhYdRy5HS2kTZviFpmDgzilbtsJsxiroqACmayynDN/9VzIbX5DOw==}
|
||||
@@ -3401,7 +3393,6 @@ packages:
|
||||
/toidentifier@1.0.1:
|
||||
resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==}
|
||||
engines: {node: '>=0.6'}
|
||||
dev: false
|
||||
|
||||
/tr46@3.0.0:
|
||||
resolution: {integrity: sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA==}
|
||||
@@ -3495,7 +3486,6 @@ packages:
|
||||
dependencies:
|
||||
media-typer: 0.3.0
|
||||
mime-types: 2.1.35
|
||||
dev: false
|
||||
|
||||
/typed-array-buffer@1.0.0:
|
||||
resolution: {integrity: sha512-Y8KTSIglk9OZEr8zywiIHG/kmQ7KWyjseXs1CbSo8vC42w7hg2HgYTxSWwP0+is7bWDc1H+Fo026CpHFwm8tkw==}
|
||||
@@ -3545,7 +3535,6 @@ packages:
|
||||
engines: {node: '>= 0.8'}
|
||||
dependencies:
|
||||
random-bytes: 1.0.0
|
||||
dev: false
|
||||
|
||||
/unbox-primitive@1.0.2:
|
||||
resolution: {integrity: sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==}
|
||||
@@ -3559,7 +3548,6 @@ packages:
|
||||
/unpipe@1.0.0:
|
||||
resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==}
|
||||
engines: {node: '>= 0.8'}
|
||||
dev: false
|
||||
|
||||
/untildify@4.0.0:
|
||||
resolution: {integrity: sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==}
|
||||
@@ -3579,7 +3567,6 @@ packages:
|
||||
/utils-merge@1.0.1:
|
||||
resolution: {integrity: sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==}
|
||||
engines: {node: '>= 0.4.0'}
|
||||
dev: false
|
||||
|
||||
/v8-compile-cache-lib@3.0.1:
|
||||
resolution: {integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==}
|
||||
@@ -3595,7 +3582,6 @@ packages:
|
||||
/vary@1.1.2:
|
||||
resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==}
|
||||
engines: {node: '>= 0.8'}
|
||||
dev: false
|
||||
|
||||
/vite@4.4.6(@types/node@18.17.0):
|
||||
resolution: {integrity: sha512-EY6Mm8vJ++S3D4tNAckaZfw3JwG3wa794Vt70M6cNJ6NxT87yhq7EC8Rcap3ahyHdo8AhCmV9PTk+vG1HiYn1A==}
|
||||
@@ -3810,3 +3796,7 @@ packages:
|
||||
/zod@3.22.1:
|
||||
resolution: {integrity: sha512-+qUhAMl414+Elh+fRNtpU+byrwjDFOS1N7NioLY+tSlcADTx4TkCUua/hxJvxwDXcV4397/nZ420jy4n4+3WUg==}
|
||||
dev: false
|
||||
|
||||
/zod@3.22.2:
|
||||
resolution: {integrity: sha512-wvWkphh5WQsJbVk1tbx1l1Ly4yg+XecD+Mq280uBGt9wa5BKSWf4Mhp6GmrkPixhMxmabYY7RbzlwVP32pbGCg==}
|
||||
dev: true
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
packages:
|
||||
- '@sammo/*'
|
||||
- '@strpc/*'
|
||||
- '!**/test/**'
|
||||
@@ -0,0 +1,30 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ESNext",
|
||||
"module": "node16",
|
||||
"moduleResolution": "node16",
|
||||
"resolveJsonModule": true,
|
||||
"declaration": true,
|
||||
"declarationMap": true,
|
||||
"importHelpers": true,
|
||||
"isolatedModules": true,
|
||||
"verbatimModuleSyntax": true,
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"esModuleInterop": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"removeComments": false,
|
||||
"strict": true,
|
||||
"noImplicitReturns": true,
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"noImplicitOverride": true,
|
||||
"skipLibCheck": true,
|
||||
"incremental": true,
|
||||
"sourceMap": true,
|
||||
"composite": true
|
||||
},
|
||||
"ts-node": {
|
||||
"esm": true,
|
||||
"experimentalSpecifierResolution": "node"
|
||||
},
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user