mirror of
https://github.com/monkeytypegame/monkeytype.git
synced 2024-09-20 07:16:17 +08:00
extract shared contracts
This commit is contained in:
parent
1fcb8748c0
commit
093c176530
|
@ -24,6 +24,6 @@
|
|||
"./**/*.ts",
|
||||
"./**/*.spec.ts",
|
||||
"./setup-tests.ts",
|
||||
"../../shared-types/**/*.d.ts"
|
||||
"../../shared/types/**/*.d.ts"
|
||||
]
|
||||
}
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
import * as ConfigDAL from "../../dal/config";
|
||||
import { MonkeyTypes } from "../../types/types";
|
||||
import { MonkeyResponse, MonkeyResponse2 } from "../../utils/monkey-response";
|
||||
import {
|
||||
ConfigType,
|
||||
GetConfig,
|
||||
GetTestConfigParams,
|
||||
GetTestConfigQuery,
|
||||
} from "../schemas/config.contract";
|
||||
} from "@shared/contract/config.contract";
|
||||
|
||||
export async function getConfig(
|
||||
req: MonkeyTypes.Request
|
||||
|
@ -18,7 +17,7 @@ export async function getConfig(
|
|||
|
||||
export async function getConfigV2(
|
||||
req: MonkeyTypes.Request2
|
||||
): Promise<MonkeyResponse2<ConfigType>> {
|
||||
): Promise<MonkeyResponse2<GetConfig>> {
|
||||
const { uid } = req.ctx.decodedToken;
|
||||
|
||||
const data = await ConfigDAL.getConfig(uid);
|
||||
|
@ -27,7 +26,7 @@ export async function getConfigV2(
|
|||
|
||||
export async function getTestConfigV2(
|
||||
req: MonkeyTypes.Request2<never, GetTestConfigQuery, GetTestConfigParams>
|
||||
): Promise<MonkeyResponse2<ConfigType>> {
|
||||
): Promise<MonkeyResponse2<GetConfig>> {
|
||||
const { noCache, includes } = req.query;
|
||||
const { id } = req.params;
|
||||
const { uid } = req.ctx.decodedToken;
|
||||
|
|
|
@ -2,11 +2,7 @@ import _ from "lodash";
|
|||
import * as UserDAL from "../../dal/user";
|
||||
import MonkeyError from "../../utils/error";
|
||||
import Logger from "../../utils/logger";
|
||||
import {
|
||||
EmptyMonkeyResponse2,
|
||||
MonkeyResponse,
|
||||
MonkeyResponse2,
|
||||
} from "../../utils/monkey-response";
|
||||
import { MonkeyResponse, MonkeyResponse2 } from "../../utils/monkey-response";
|
||||
import * as DiscordUtils from "../../utils/discord";
|
||||
import {
|
||||
MILLISECONDS_IN_DAY,
|
||||
|
@ -33,8 +29,7 @@ import * as AuthUtil from "../../utils/auth";
|
|||
import * as Dates from "date-fns";
|
||||
import { UTCDateMini } from "@date-fns/utc";
|
||||
import * as BlocklistDal from "../../dal/blocklist";
|
||||
import { UserCreateType, UserType } from "../schemas/user.contract";
|
||||
import { MonkeyTypes } from "../../types/types";
|
||||
import { UserCreateType, UserType } from "@shared/contract/user.contract";
|
||||
|
||||
async function verifyCaptcha(captcha: string): Promise<void> {
|
||||
if (!(await verify(captcha))) {
|
||||
|
|
|
@ -5,11 +5,11 @@ import {
|
|||
} from "../../middlewares/auth";
|
||||
import * as RateLimit from "../../middlewares/rate-limit";
|
||||
import * as ConfigController from "../controllers/config";
|
||||
import { configContract as configsContract } from "../schemas/config.contract";
|
||||
import { configContract } from "./../../../../shared/contract/config.contract";
|
||||
import { callHandler } from "./index2";
|
||||
|
||||
const s = initServer();
|
||||
export const configRoutes = s.router(configsContract, {
|
||||
export const configRoutes = s.router(configContract, {
|
||||
get: {
|
||||
middleware: [authenticateRequest(), RateLimit.configGet],
|
||||
handler: (r) => callHandler(ConfigController.getConfigV2)(r),
|
||||
|
|
|
@ -1,20 +1,15 @@
|
|||
import { AppRoute, AppRouter } from "@ts-rest/core";
|
||||
import {
|
||||
TsRestRequest,
|
||||
TsRestRequestHandler,
|
||||
createExpressEndpoints,
|
||||
initServer,
|
||||
} from "@ts-rest/express";
|
||||
import { IRouter, NextFunction } from "express";
|
||||
import {
|
||||
MonkeyResponse2,
|
||||
MonkeyStatusAware,
|
||||
} from "../../utils/monkey-response";
|
||||
import { contract } from "../schemas/index.contract";
|
||||
import { RateLimitRequestHandler } from "express-rate-limit";
|
||||
import { MonkeyResponse2 } from "../../utils/monkey-response";
|
||||
import { configRoutes } from "./configsV2";
|
||||
import { userRoutes } from "./usersV2";
|
||||
import { MonkeyTypes } from "../../types/types";
|
||||
import { RateLimitRequestHandler } from "express-rate-limit";
|
||||
import { AppRoute, AppRouter } from "@ts-rest/core";
|
||||
import { contract } from "./../../../../shared/contract/index.contract";
|
||||
|
||||
const s = initServer();
|
||||
const router = s.router(contract, {
|
||||
|
|
|
@ -5,7 +5,7 @@ import { authenticateRequest } from "../../middlewares/auth";
|
|||
import * as RateLimit from "../../middlewares/rate-limit";
|
||||
|
||||
import * as UserController from "../controllers/user";
|
||||
import { userContract } from "../schemas/user.contract";
|
||||
import { userContract } from "./../../../../shared/contract/user.contract";
|
||||
import { callHandler } from "./index2";
|
||||
|
||||
const s = initServer();
|
||||
|
|
|
@ -15,7 +15,6 @@ import crypto from "crypto";
|
|||
import { performance } from "perf_hooks";
|
||||
import { TsRestRequest, TsRestRequestHandler } from "@ts-rest/express";
|
||||
import { AppRoute, AppRouter } from "@ts-rest/core";
|
||||
import { MonkeyTypes } from "../types/types";
|
||||
|
||||
type RequestAuthenticationOptions = {
|
||||
isPublic?: boolean;
|
||||
|
|
|
@ -4,7 +4,6 @@ import { Response, NextFunction } from "express";
|
|||
import { RateLimiterMemory } from "rate-limiter-flexible";
|
||||
import rateLimit, { Options } from "express-rate-limit";
|
||||
import { isDevEnvironment } from "../utils/misc";
|
||||
import { MonkeyTypes } from "../types/types";
|
||||
|
||||
const REQUEST_MULTIPLIER = isDevEnvironment() ? 100 : 1;
|
||||
|
||||
|
|
26
backend/src/types/types.d.ts
vendored
26
backend/src/types/types.d.ts
vendored
|
@ -1,10 +1,8 @@
|
|||
import { AppRoute, AppRouter, Prettify } from "@ts-rest/core";
|
||||
import { TsRestRequest } from "@ts-rest/express";
|
||||
import { Router } from "express";
|
||||
|
||||
type ObjectId = import("mongodb").ObjectId;
|
||||
|
||||
type ExpressRequest = import("express").Request;
|
||||
type TsRestRequest = import("@ts-rest/express").TsRestRequest<any>;
|
||||
type AppRoute = import("@ts-rest/core").AppRoute;
|
||||
type AppRouter = import("@ts-rest/core").AppRouter;
|
||||
|
||||
declare namespace MonkeyTypes {
|
||||
type DecodedToken = {
|
||||
|
@ -18,21 +16,21 @@ declare namespace MonkeyTypes {
|
|||
decodedToken: DecodedToken;
|
||||
};
|
||||
|
||||
type Request2<TBody = never, TQuery = never, TParams = never> = {
|
||||
body: Readonly<TBody>;
|
||||
query: Readonly<TQuery>;
|
||||
params: TParams;
|
||||
ctx: Readonly<Context>;
|
||||
raw: TsRestRequest<any>;
|
||||
};
|
||||
|
||||
type Request = {
|
||||
ctx: Readonly<Context>;
|
||||
} & ExpressRequest;
|
||||
|
||||
type Request2<TBody = any, TQuery = any, TParams = any> = {
|
||||
body: Readonly<TBody>;
|
||||
query: Readonly<TQuery>;
|
||||
params: TParams;
|
||||
ctx: Readonly<Context>;
|
||||
raw: TsRestRequest;
|
||||
};
|
||||
|
||||
type RequestTsRest<T extends AppRoute | AppRouter = any> = {
|
||||
ctx: Readonly<Context>;
|
||||
} & TsRestRequest<T>;
|
||||
} & TsRestRequest;
|
||||
|
||||
type DBUser = Omit<
|
||||
SharedTypes.User,
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { v4 as uuidv4 } from "uuid";
|
||||
import { isDevEnvironment } from "./misc";
|
||||
import { MonkeyStatusAware } from "./monkey-response";
|
||||
import { MonkeyErrorType } from "../api/schemas/common.contract";
|
||||
import { MonkeyErrorType } from "@shared/contract/common.contract";
|
||||
|
||||
class MonkeyError extends Error implements MonkeyStatusAware, MonkeyErrorType {
|
||||
status: number;
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import _ from "lodash";
|
||||
import uaparser from "ua-parser-js";
|
||||
import { ExpressRequest, MonkeyTypes } from "../types/types";
|
||||
import { TsRestExpressOptions, TsRestRequest } from "@ts-rest/express";
|
||||
|
||||
//todo split this file into smaller util files (grouped by functionality)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { Response } from "express";
|
||||
import { isCustomCode } from "../constants/monkey-status-codes";
|
||||
import { MonkeyResonseType as MonkeyResponseType } from "../api/schemas/common.contract";
|
||||
import { MonkeyResonseType as MonkeyResponseType } from "@shared/contract/common.contract";
|
||||
|
||||
export interface MonkeyStatusAware {
|
||||
status: number;
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import "dotenv/config";
|
||||
import { Counter, Histogram, Gauge } from "prom-client";
|
||||
import { ExpressRequest, MonkeyTypes } from "../types/types";
|
||||
import { TsRestRequest } from "@ts-rest/express";
|
||||
|
||||
const auth = new Counter({
|
||||
|
|
|
@ -19,18 +19,14 @@
|
|||
"noFallthroughCasesInSwitch": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"paths": {
|
||||
"@shared/*": ["../shared-types/*"]
|
||||
"@shared/*": ["../shared/*"]
|
||||
}
|
||||
},
|
||||
"ts-node": {
|
||||
"files": true
|
||||
},
|
||||
"files": [
|
||||
"./src/types/types.d.ts",
|
||||
"../shared-types/types.d.ts",
|
||||
"../shared-types/config.d.ts"
|
||||
],
|
||||
"include": ["./src/**/*", "../shared-types/**/*.d.ts"],
|
||||
"files": ["./src/types/types.d.ts"],
|
||||
"include": ["./src/**/*", "../shared/**/*"],
|
||||
"exclude": [
|
||||
"node_modules",
|
||||
"build",
|
||||
|
|
|
@ -20,9 +20,5 @@
|
|||
"files": true
|
||||
},
|
||||
"files": ["../src/ts/types/types.d.ts", "vitest.d.ts"],
|
||||
"include": [
|
||||
"./**/*.spec.ts",
|
||||
"./setup-tests.ts",
|
||||
"../../shared-types/**/*.d.ts"
|
||||
]
|
||||
"include": ["./**/*.spec.ts", "./setup-tests.ts", "../../shared/**/*.d.ts"]
|
||||
}
|
||||
|
|
60
frontend/src/ts/ape/endpoints/configsV2.ts
Normal file
60
frontend/src/ts/ape/endpoints/configsV2.ts
Normal file
|
@ -0,0 +1,60 @@
|
|||
import { initClient } from "@ts-rest/core";
|
||||
import {
|
||||
GetConfig,
|
||||
configContract,
|
||||
} from "./../../../../../shared/contract/config.contract";
|
||||
import { getAuthenticatedUser, isAuthenticated } from "../../firebase";
|
||||
import { getIdToken } from "firebase/auth";
|
||||
import { Axios, AxiosError, AxiosResponse, Method, isAxiosError } from "axios";
|
||||
|
||||
export default class Users {
|
||||
private client;
|
||||
|
||||
constructor(baseUrl: string, axios: Axios) {
|
||||
this.client = initClient(configContract, {
|
||||
baseUrl,
|
||||
jsonQuery: true,
|
||||
//TODO extract
|
||||
api: async ({ path, method, headers, body }) => {
|
||||
const token = isAuthenticated()
|
||||
? await getIdToken(getAuthenticatedUser())
|
||||
: "";
|
||||
try {
|
||||
const result = await axios.request({
|
||||
method: method as Method,
|
||||
url: path,
|
||||
headers: {
|
||||
...headers,
|
||||
Authorization: `Bearer ${token}`,
|
||||
},
|
||||
data: body,
|
||||
});
|
||||
return {
|
||||
status: result.status,
|
||||
body: result.data,
|
||||
headers: result.headers,
|
||||
};
|
||||
} catch (e: Error | AxiosError | unknown) {
|
||||
if (isAxiosError(e)) {
|
||||
const error = e as AxiosError;
|
||||
const response = error.response as AxiosResponse;
|
||||
return {
|
||||
status: response.status,
|
||||
body: response.data,
|
||||
headers: response.headers,
|
||||
};
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
async get(): Promise<GetConfig> {
|
||||
return (await this.client.get()).body;
|
||||
}
|
||||
|
||||
getClient() {
|
||||
return this.client;
|
||||
}
|
||||
}
|
|
@ -9,6 +9,7 @@ import ApeKeys from "./ape-keys";
|
|||
import Public from "./public";
|
||||
import Configuration from "./configuration";
|
||||
import UsersV2 from "./usersV2";
|
||||
import ConfigsV2 from "./configsV2";
|
||||
|
||||
export default {
|
||||
Configs,
|
||||
|
@ -22,4 +23,5 @@ export default {
|
|||
ApeKeys,
|
||||
Configuration,
|
||||
UsersV2,
|
||||
ConfigsV2,
|
||||
};
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
import { initClient } from "@ts-rest/core";
|
||||
import { GetUserType, userContract } from "../../contract-temp/user.contract";
|
||||
import {
|
||||
GetUserType,
|
||||
userContract,
|
||||
} from "./../../../../../shared/contract/user.contract";
|
||||
import { getAuthenticatedUser, isAuthenticated } from "../../firebase";
|
||||
import { getIdToken } from "firebase/auth";
|
||||
import { Axios, AxiosError, AxiosResponse, Method, isAxiosError } from "axios";
|
||||
|
@ -11,8 +14,8 @@ export default class Users {
|
|||
this.client = initClient(userContract, {
|
||||
baseUrl,
|
||||
jsonQuery: true,
|
||||
//TODO extract
|
||||
api: async ({ path, method, headers, body }) => {
|
||||
console.log("####", { path, method, headers, body });
|
||||
const token = isAuthenticated()
|
||||
? await getIdToken(getAuthenticatedUser())
|
||||
: "";
|
||||
|
@ -31,7 +34,7 @@ export default class Users {
|
|||
body: result.data,
|
||||
headers: result.headers,
|
||||
};
|
||||
} catch (e: Error | AxiosError | any) {
|
||||
} catch (e: Error | AxiosError | unknown) {
|
||||
if (isAxiosError(e)) {
|
||||
const error = e as AxiosError;
|
||||
const response = error.response as AxiosResponse;
|
||||
|
@ -50,4 +53,8 @@ export default class Users {
|
|||
async getData(): Promise<GetUserType> {
|
||||
return (await this.client.get()).body;
|
||||
}
|
||||
|
||||
getClient() {
|
||||
return this.client;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,7 +25,8 @@ const Ape = {
|
|||
publicStats: new endpoints.Public(httpClient),
|
||||
apeKeys: new endpoints.ApeKeys(httpClient),
|
||||
configuration: new endpoints.Configuration(httpClient),
|
||||
usersV2: new endpoints.UsersV2(BASE_URL, axiosClient),
|
||||
usersV2: new endpoints.UsersV2(BASE_URL, axiosClient).getClient(),
|
||||
configsV2: new endpoints.ConfigsV2(BASE_URL, axiosClient).getClient(),
|
||||
};
|
||||
|
||||
export default Ape;
|
||||
|
|
|
@ -1,14 +0,0 @@
|
|||
import { z } from "zod";
|
||||
|
||||
export const MonkeyResponseSchema = z.object({
|
||||
message: z.string(),
|
||||
status: z.number().int(),
|
||||
});
|
||||
export type MonkeyResonseType = z.infer<typeof MonkeyResponseSchema>;
|
||||
|
||||
export const MonkeyErrorSchema = z.object({
|
||||
status: z.number().int(),
|
||||
errorId: z.string(),
|
||||
uid: z.string().optional(),
|
||||
});
|
||||
export type MonkeyErrorType = z.infer<typeof MonkeyErrorSchema>;
|
|
@ -1,51 +0,0 @@
|
|||
import { initContract } from "@ts-rest/core";
|
||||
import { z } from "zod";
|
||||
import { MonkeyResponseSchema } from "./common.contract";
|
||||
|
||||
const c = initContract();
|
||||
|
||||
const ConfigSchema = z.object({
|
||||
test: z.string().readonly(),
|
||||
});
|
||||
export type ConfigType = z.infer<typeof ConfigSchema>;
|
||||
|
||||
const GetConfigSchema = MonkeyResponseSchema.extend({ data: ConfigSchema });
|
||||
export type GetConfig = z.infer<typeof GetConfigSchema>;
|
||||
|
||||
const GetTestConfigParamsSchema = z.object({
|
||||
id: z.string(),
|
||||
});
|
||||
export type GetTestConfigParams = z.infer<typeof GetTestConfigParamsSchema>;
|
||||
|
||||
const GetTestConfigQuerySchema = z.object({
|
||||
noCache: z.boolean().optional().default(false),
|
||||
includes: z
|
||||
.array(z.enum(["server", "client"] as const))
|
||||
.optional()
|
||||
.default(["server"]),
|
||||
});
|
||||
export type GetTestConfigQuery = z.infer<typeof GetTestConfigQuerySchema>;
|
||||
export const configContract = c.router(
|
||||
{
|
||||
get: {
|
||||
method: "GET",
|
||||
path: "/",
|
||||
responses: {
|
||||
200: GetConfigSchema,
|
||||
},
|
||||
},
|
||||
getTest: {
|
||||
method: "GET",
|
||||
path: "/test/:id/",
|
||||
pathParams: GetTestConfigParamsSchema,
|
||||
query: GetTestConfigQuerySchema,
|
||||
responses: {
|
||||
200: GetConfigSchema,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
pathPrefix: "/v2/configs",
|
||||
strictStatusCodes: true,
|
||||
}
|
||||
);
|
|
@ -1,10 +0,0 @@
|
|||
import { initContract } from "@ts-rest/core";
|
||||
import { userContract } from "./user.contract";
|
||||
import { configContract } from "./config.contract";
|
||||
|
||||
const c = initContract();
|
||||
|
||||
export const contract = c.router({
|
||||
users: userContract,
|
||||
configs: configContract,
|
||||
});
|
|
@ -1,49 +0,0 @@
|
|||
import { initContract } from "@ts-rest/core";
|
||||
import { z } from "zod";
|
||||
import { MonkeyResponseSchema, MonkeyErrorSchema } from "./common.contract";
|
||||
|
||||
const c = initContract();
|
||||
|
||||
const UserSchema = z.object({
|
||||
uid: z.string().readonly(),
|
||||
name: z.string(),
|
||||
email: z.string().email(),
|
||||
});
|
||||
export type UserType = z.infer<typeof UserSchema>;
|
||||
|
||||
const UserCreateSchema = UserSchema.pick({
|
||||
name: true,
|
||||
email: true,
|
||||
}).extend({
|
||||
captcha: z.string(),
|
||||
});
|
||||
export type UserCreateType = z.infer<typeof UserCreateSchema>;
|
||||
|
||||
const GetUserSchema = MonkeyResponseSchema.extend({ data: UserSchema });
|
||||
export type GetUserType = z.infer<typeof GetUserSchema>;
|
||||
|
||||
export const userContract = c.router(
|
||||
{
|
||||
signup: {
|
||||
method: "POST",
|
||||
path: "/signup",
|
||||
body: UserCreateSchema,
|
||||
responses: {
|
||||
200: MonkeyResponseSchema,
|
||||
400: MonkeyErrorSchema,
|
||||
},
|
||||
},
|
||||
get: {
|
||||
method: "GET",
|
||||
path: "/",
|
||||
responses: {
|
||||
200: GetUserSchema,
|
||||
//404: MonkeyErrorSchema,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
pathPrefix: "/v2/users",
|
||||
strictStatusCodes: true,
|
||||
}
|
||||
);
|
|
@ -53,6 +53,16 @@ export async function initSnapshot(): Promise<
|
|||
const snap = { ...defaultSnap };
|
||||
try {
|
||||
if (!isAuthenticated()) return false;
|
||||
//EXAMPLE call
|
||||
const testConfig = await Ape.configsV2.getTest({
|
||||
params: { id: "456" },
|
||||
query: {
|
||||
includes: ["client", "server"],
|
||||
noCache: true,
|
||||
},
|
||||
});
|
||||
|
||||
console.log("####", testConfig.body);
|
||||
// if (ActivePage.get() === "loading") {
|
||||
// LoadingPage.updateBar(22.5);
|
||||
// } else {
|
||||
|
@ -61,8 +71,8 @@ export async function initSnapshot(): Promise<
|
|||
// LoadingPage.updateText("Downloading user...");
|
||||
|
||||
const [userResponse, configResponse, presetsResponse] = await Promise.all([
|
||||
Ape.usersV2.getData(),
|
||||
Ape.configs.get(),
|
||||
Ape.usersV2.get(),
|
||||
Ape.configsV2.get(),
|
||||
Ape.presets.get(),
|
||||
]);
|
||||
|
||||
|
@ -70,14 +80,14 @@ export async function initSnapshot(): Promise<
|
|||
if (userResponse.status !== 200) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-throw-literal
|
||||
throw {
|
||||
message: `${userResponse.message} (user)`,
|
||||
message: `${userResponse.body.message} (user)`,
|
||||
responseCode: userResponse.status,
|
||||
};
|
||||
}
|
||||
if (configResponse.status !== 200) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-throw-literal
|
||||
throw {
|
||||
message: `${configResponse.message} (config)`,
|
||||
message: `${configResponse.body.message} (config)`,
|
||||
responseCode: configResponse.status,
|
||||
};
|
||||
}
|
||||
|
@ -89,8 +99,8 @@ export async function initSnapshot(): Promise<
|
|||
};
|
||||
}
|
||||
|
||||
const userData = userResponse.data;
|
||||
const configData = configResponse.data;
|
||||
const userData = userResponse.body.data as any; //TODO
|
||||
const configData = configResponse.body.data;
|
||||
const presetsData = presetsResponse.data;
|
||||
|
||||
if (userData === null) {
|
||||
|
|
|
@ -33,9 +33,9 @@
|
|||
"allowUnreachableCode": false,
|
||||
"skipLibCheck": false,
|
||||
"paths": {
|
||||
"@shared/*": ["../shared-types/*"]
|
||||
"@shared/*": ["../shared/*"]
|
||||
}
|
||||
},
|
||||
"include": ["./src/**/*.ts", "../shared-types/**/*.d.ts"],
|
||||
"include": ["./src/**/*.ts", "../shared/**/*.d.ts"],
|
||||
"exclude": ["node_modules", "build", "setup-tests.ts", "**/*.spec.ts"]
|
||||
}
|
||||
|
|
|
@ -9,24 +9,19 @@
|
|||
"path": "frontend"
|
||||
},
|
||||
{
|
||||
"name": "shared-types",
|
||||
"path": "shared-types"
|
||||
},
|
||||
{
|
||||
"name": "contract",
|
||||
"path": "contract"
|
||||
"name": "shared",
|
||||
"path": "shared"
|
||||
},
|
||||
{
|
||||
"name": "root",
|
||||
"path": "./"
|
||||
"path": "."
|
||||
}
|
||||
],
|
||||
"settings": {
|
||||
"files.exclude": {
|
||||
"frontend": true,
|
||||
"backend": true,
|
||||
"shared-types": true,
|
||||
"contract": true
|
||||
"shared": true
|
||||
},
|
||||
"search.exclude": {
|
||||
//defaults
|
||||
|
|
|
@ -7,8 +7,6 @@ const c = initContract();
|
|||
const ConfigSchema = z.object({
|
||||
test: z.string().readonly(),
|
||||
});
|
||||
export type ConfigType = z.infer<typeof ConfigSchema>;
|
||||
|
||||
const GetConfigSchema = MonkeyResponseSchema.extend({ data: ConfigSchema });
|
||||
export type GetConfig = z.infer<typeof GetConfigSchema>;
|
||||
|
35
shared/package-lock.json
generated
Normal file
35
shared/package-lock.json
generated
Normal file
|
@ -0,0 +1,35 @@
|
|||
{
|
||||
"name": "contract",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "contract",
|
||||
"dependencies": {
|
||||
"@ts-rest/core": "3.45.2",
|
||||
"zod": "3.23.8"
|
||||
}
|
||||
},
|
||||
"node_modules/@ts-rest/core": {
|
||||
"version": "3.45.2",
|
||||
"resolved": "https://registry.npmjs.org/@ts-rest/core/-/core-3.45.2.tgz",
|
||||
"integrity": "sha512-Eiv+Sa23MbsAd1Gx9vNJ+IFCDyLZNdJ+UuGMKbFvb+/NmgcBR1VL1UIVtEkd5DJxpYMMd8SLvW91RgB2TS8iPw==",
|
||||
"peerDependencies": {
|
||||
"zod": "^3.22.3"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"zod": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/zod": {
|
||||
"version": "3.23.8",
|
||||
"resolved": "https://registry.npmjs.org/zod/-/zod-3.23.8.tgz",
|
||||
"integrity": "sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==",
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/colinhacks"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
15
shared/package.json
Normal file
15
shared/package.json
Normal file
|
@ -0,0 +1,15 @@
|
|||
{
|
||||
"name": "contract",
|
||||
"types": "./dist/index.d.ts",
|
||||
"exports": {
|
||||
".": "./dist/index.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@ts-rest/core": "3.45.2",
|
||||
"zod": "3.23.8"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "tsc",
|
||||
"dev": "tsc --watch"
|
||||
}
|
||||
}
|
17
shared/tsconfig.json
Normal file
17
shared/tsconfig.json
Normal file
|
@ -0,0 +1,17 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"esModuleInterop": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"isolatedModules": true,
|
||||
"module": "ESNext", //TODO CommonJS
|
||||
"moduleResolution": "Bundler", //TODO remove?
|
||||
"preserveWatchOutput": true,
|
||||
"skipLibCheck": true,
|
||||
"strict": true,
|
||||
"rootDir": ".",
|
||||
"outDir": "dist",
|
||||
"types": ["node"],
|
||||
"declaration": true
|
||||
},
|
||||
"exclude": ["node_modules", "./dist/**/*"]
|
||||
}
|
Loading…
Reference in a new issue