@msom/http
Version:
@msom/http
858 lines (841 loc) • 28.1 kB
JavaScript
import cors from "cors";
import express, { Router } from "express";
import http from "http";
import https from "https";
import net from "net";
import { Db as Db$1, MongoClient as MongoClient$1 } from "mongodb";
import { assert, createJsonRequestJson } from "@msom/common";
import bodyParser from "body-parser";
//#region src/http/http-proxy.ts
/**
* 创建代理中间件
*
* @param {ProxyOptions} options - 代理配置选项
* @returns Express 中间件函数
*/
function createProxyMiddleware(options) {
return (req, res, next) => {
if (options.bypass) {
const bypassResult = options.bypass(req);
if (bypassResult === false) return next();
}
const targetUrl = new URL(options.target);
let rewrittenPath = req.path;
if (options.pathRewrite) if (typeof options.pathRewrite === "function") rewrittenPath = options.pathRewrite(req.path);else
for (const [pattern, replacement] of Object.entries(options.pathRewrite)) {
const regex = new RegExp(pattern);
rewrittenPath = rewrittenPath.replace(regex, replacement);
}
const requestOptions = {
hostname: targetUrl.hostname,
port: targetUrl.port || (targetUrl.protocol === "https:" ? 443 : 80),
path: rewrittenPath + (req.url.includes("?") ? `?${req.url.split("?")[1]}` : ""),
method: req.method,
headers: { ...req.headers }
};
if (options.changeOrigin !== false) requestOptions.headers["host"] = targetUrl.host;
const requestModule = targetUrl.protocol === "https:" ? https : http;
const proxyReq = requestModule.request(requestOptions, (proxyRes) => {
res.status(proxyRes.statusCode || 500);
Object.entries(proxyRes.headers).forEach(([key, value]) => {
if (value) res.setHeader(key, value);
});
proxyRes.pipe(res);
});
proxyReq.on("error", (err) => {
if (options.onError) options.onError(err, req, res);else
{
console.error(`Proxy error: ${err.message}`);
res.status(500).send("Proxy error");
}
});
if (req.body && Object.keys(req.body).length > 0) proxyReq.write(JSON.stringify(req.body));
req.pipe(proxyReq);
};
}
/**
* 创建 WebSocket 代理中间件
*
* @param options - 代理配置选项
* @returns Express 中间件函数
*/
function createWebSocketProxy(options) {
return (req, res, next) => {
if (req.headers.upgrade !== "websocket") return next();
const targetUrl = new URL(options.target);
const proxySocket = net.connect(+targetUrl.port || (targetUrl.protocol === "https:" ? 443 : 80), targetUrl.hostname, () => {
const headers = [
`GET ${req.url} HTTP/1.1`,
`Host: ${options.changeOrigin !== false ? targetUrl.host : req.headers.host}`,
`Connection: Upgrade`,
`Upgrade: websocket`,
`Sec-WebSocket-Version: ${req.headers["sec-websocket-version"]}`,
`Sec-WebSocket-Key: ${req.headers["sec-websocket-key"]}`];
proxySocket.write(headers.join("\r\n") + "\r\n\r\n");
});
const clientSocket = req.socket;
clientSocket.pipe(proxySocket);
proxySocket.pipe(clientSocket);
clientSocket.on("error", () => proxySocket.destroy());
proxySocket.on("error", () => clientSocket.destroy());
};
}
/**
* 创建代理服务器
*
* @param app - Express 应用实例
* @param proxyRules - 代理规则配置
* @example
// 示例使用
const app = express();
app.use(express.json());
// 配置代理规则
const proxyConfig: ProxyRules = {
"/api": {
target: "http://localhost:3001",
changeOrigin: true,
pathRewrite: { "^/api": "" },
ws: true,
bypass: (req) => {
// 绕过 POST 请求
return req.method === "POST" ? false : undefined;
},
onError: (err, req, res) => {
console.error(`API Proxy Error: ${err.message}`);
res.status(502).json({ error: "Bad Gateway" });
},
},
"/external": {
target: "https://jsonplaceholder.typicode.com",
changeOrigin: true,
pathRewrite: (path) => path.replace(/^\/external/, ""),
secure: false, // 开发环境忽略 SSL 错误
},
"/images": "http://localhost:3002", // 简写形式
};
// 设置代理
setupProxy(app, proxyConfig);
// 启动服务器
const PORT = 3000;
app.listen(PORT, () => {
console.log(`Proxy server running at http://localhost:${PORT}`);
console.log("Available proxies:");
console.log(" /api -> http://localhost:3001");
console.log(" /external -> https://jsonplaceholder.typicode.com");
console.log(" /images -> http://localhost:3002");
});
* }
*/
function setupProxy(app, proxyRules) {
Object.entries(proxyRules).forEach(([path, rule]) => {
const options = typeof rule === "string" ? { target: rule } : rule;
const proxyMiddleware = createProxyMiddleware({
...options,
target: options.target
});
app.use(path, proxyMiddleware);
if (options.ws) {
const wsProxy = createWebSocketProxy(options);
app.use(path, wsProxy);
}
});
}
//#endregion
//#region src/http/print-proxy.ts
const NO_PROXY = "No proxy rules configured";
const Available_Proxies = "Available Proxies:";
/**
* 生成详细代理规则报告(对齐格式)
* @param proxyRules 代理规则配置
* @returns 格式化的代理规则描述数组
*/
function generateAlignedProxyReport(proxyRules) {
if (!proxyRules || Object.keys(proxyRules).length === 0) return [NO_PROXY];
const maxPathLength = Math.max(...Object.keys(proxyRules).map((path) => {
const formattedPath = path.endsWith("/") ? path : `${path}/`;
return formattedPath.length;
}));
return Object.entries(proxyRules).map(([path, rule]) => {
const formattedPath = path.endsWith("/") ? path : `${path}/`;
const target = typeof rule === "string" ? rule : rule.target;
const baseLine = ` ${formattedPath.padEnd(maxPathLength)} -> ${target}`;
if (typeof rule !== "string") {
const options = [];
if (rule.changeOrigin !== void 0) options.push(`changeOrigin: ${rule.changeOrigin}`);
if (rule.secure !== void 0) options.push(`secure: ${rule.secure}`);
if (rule.ws) options.push(`ws: true`);
if (rule.pathRewrite) options.push(`pathRewrite: ${typeof rule.pathRewrite}`);
if (rule.bypass) options.push(`bypass: function`);
if (options.length > 0) {
const optionIndent = " ".repeat(maxPathLength + 6);
const optionLines = options.map((opt, i) => i === 0 ? `[${opt}` : `${optionIndent} ${opt}`);
optionLines[optionLines.length - 1] += "]";
return `${baseLine} ${optionLines.join("\n" + optionIndent)}`;
}
}
return baseLine;
});
}
/**
* 打印对齐的代理服务器信息
* @param port 服务器端口
* @param proxyRules 代理规则配置
*/
function printAlignedProxyServerInfo(port, proxyRules, printer = console.log.bind(console)) {
if (proxyRules == void 0) return;
printer(`Proxy server running at http://localhost:${port}`);
const rules = generateAlignedProxyReport(proxyRules);
if (rules[0] !== NO_PROXY) printer(Available_Proxies);
rules.forEach((rule) => printer(rule));
}
//#endregion
//#region src/http/createServer.ts
/**
*
* @param port
* @param option
* @returns
* @example
createServer(8088, {
routes: [
{
path: "/api",
children: [
{
path: "/userCreate",
method: "post",
handlers: [
express.json(),
(request, response) => {
console.log("aaa");
response.send({ aaa: 1 });
},
],
},
],
},
],
createHandle: () => {
console.log("userServer ready");
},
});
*/
function createServer(port, option = {}) {
const server = express();
const { createHandle, routes, middles, proxy } = option;
[
cors({ origin: "*" }),
express.json(),
middles || []].
flat().reduce((a, b) => a.use(b), server);
if (routes) {
const parseRoute = (routes$1, parentPath) => {
for (const route of routes$1) {
let { path, children, method, handlers = [] } = route;
path = parentPath + path;
if (method) {
const requestF = server[method].bind(server);
requestF(path, ...handlers);
}
if (children) parseRoute(children, path);
}
};
parseRoute(routes, "");
}
if (proxy) setupProxy(server, proxy);
server.listen(port, () => {
typeof createHandle === "function" && createHandle({ port });
option.printProxy !== false && printAlignedProxyServerInfo(port, proxy);
});
return server;
}
function staticMiddle(path) {
return express.static(path);
}
//#endregion
//#region src/DB/index.ts
var MongoClient = class extends MongoClient$1 {
db(dbName, options) {
return new Db(this, dbName, options);
}
};
var Db = class extends Db$1 {
get metaCollection() {
return super.collection("__meta");
}
collection(name, options, meta) {
const _collection = super.collection(name, options);
const metas = this.getCollectionMetaData();
metas.then((metas$1) => {
if (meta && !metas$1.some((c) => c.collectionName === name)) this.setCollectionMetaData(meta);
});
return _collection;
}
async createCollection(name, options, meta) {
const _meta = await this.getCollectionMetaData(name);
if (!_meta && meta) {
if (!(await this.setCollectionMetaData({
...meta,
collectionName: name
}))) throw new Error("set meta Error");
}
return super.createCollection(name, options);
}
async getCollectionMetaData(collectionName) {
if (!collectionName) return await this.metaCollection.find().toArray();else
return await this.metaCollection.findOne({ collectionName: { $eq: collectionName } });
}
async setCollectionMetaData(meta) {
const res = await this.metaCollection.updateOne({ collectionName: meta.collectionName }, { $set: meta }, { upsert: true });
return !!(res.matchedCount + res.modifiedCount + res.upsertedCount);
}
async __update(sourceCollectionName, metaKey, getKey, news) {
const meta = await this.getCollectionMetaData(sourceCollectionName);
if (!meta) return this.setCollectionMetaData({
collectionName: sourceCollectionName,
[metaKey]: news
});else
{
const newIndexs = this.check(news, getKey);
const length = meta[metaKey].length;
for (let i = 0; i < length; i++) {
const k = getKey(meta[metaKey][i], i);
const newIndex = newIndexs.get(k);
if (newIndex != void 0) {
meta[metaKey].splice(i, 1, news[newIndex]);
newIndexs.delete(k);
}
}
newIndexs.forEach((newIndex) => {
meta[metaKey].push(news[newIndex]);
});
return this.setCollectionMetaData(meta);
}
}
updateRelates(sourceCollectionName, ...relates) {
return this.__update(sourceCollectionName, "relates", ({ relateName }) => relateName, relates);
}
updateProps(sourceCollectionName, ...props) {
return this.__update(sourceCollectionName, "props", ({ prop }) => prop.name, props);
}
updateExtends(sourceCollectionName, ..._extends) {
return this.__update(sourceCollectionName, "extends", ({ collectionName }) => collectionName, _extends);
}
fillMate(meta) {
return {
props: [],
extends: [],
relates: [],
collectionName: meta.collectionName
};
}
check(props, getKey) {
const propIndexs = /* @__PURE__ */new Map();
for (let index = 0; index < props.length; index++) {
const key = getKey(props[index], index);
if (propIndexs.has(key)) throw Error("has repeat propName!");
propIndexs.set(key, index);
}
return propIndexs;
}
};
//#endregion
//#region src/result/CodeResult.ts
var CodeResultConstructor = class {
constructor(code, message, payload) {
this.code = code;
if (payload) {
if (typeof message === "object" && message !== null) throw Error();
if (message != void 0) this.message = message;
this.payload = payload;
} else if (message != void 0) if (typeof message === "object") this.payload = message;else
this.message = message;
}
};
//#endregion
//#region src/mongo-proxy/interfaces.ts
var RelationType;
(function (RelationType$1) {
RelationType$1["ONE"] = "One";
RelationType$1["MANY"] = "Many";
})(RelationType || (RelationType = {}));
var ConditionType;
(function (ConditionType$1) {
ConditionType$1["COMP"] = "comp";
ConditionType$1["AND"] = "and";
ConditionType$1["OR"] = "or";
})(ConditionType || (ConditionType = {}));
var CompCondition = class CompCondition {
static is(condition) {
return condition.type === ConditionType.COMP;
}
static CompHandle = {
"!=": (modelValue, targetValue) => modelValue !== targetValue,
"=": (modelValue, targetValue) => modelValue === targetValue,
">": (modelValue, targetValue) => modelValue > targetValue,
"<": (modelValue, targetValue) => modelValue < targetValue,
"<=": (modelValue, targetValue) => modelValue <= targetValue,
">=": (modelValue, targetValue) => modelValue >= targetValue,
in: (modelValue, targetValue) => targetValue.includes(modelValue),
nin: (modelValue, targetValue) => !targetValue.includes(modelValue),
exist: (model, propKey) => Reflect.has(model, propKey)
};
constructor(compType, propKey, value) {
this.type = ConditionType.COMP;
this.compType = compType;
this.propKey = propKey;
this.value = value;
}
clone() {
return new CompCondition(this.compType, this.propKey, this.value);
}
filter(model) {
const { compType, propKey, value } = this;
const h = CompCondition.CompHandle[compType];
assert(h, "未知比较运算符");
if (compType === "exist") return h(model, propKey);
return h(model[propKey], value);
}
};
var AndCondition = class AndCondition {
static is(condition) {
return condition.type === ConditionType.AND;
}
constructor(conditions) {
this.type = ConditionType.AND;
this.conditions = conditions;
}
clone() {
return new AndCondition(this.conditions.map((v) => v.clone()));
}
filter(model) {
return this.conditions.every((condition) => condition.filter(model));
}
};
var OrCondition = class OrCondition {
static is(condition) {
return condition.type === ConditionType.OR;
}
constructor(conditions) {
this.type = ConditionType.OR;
this.conditions = conditions;
}
clone() {
return new OrCondition(this.conditions.map((v) => v.clone()));
}
filter(model) {
return this.conditions.some((condition) => condition.filter(model));
}
};
//#endregion
//#region src/mongo-proxy/QueryProtocolBuilder.ts
var ModelType;
(function (ModelType$1) {
ModelType$1["RELATE"] = "relate";
ModelType$1["MODEL"] = "model";
})(ModelType || (ModelType = {}));
var Model = class {
type;
conditions;
relates;
children;
condition(condition) {
this.conditions = condition;
return this;
}
relate(relateName, callback) {
const model = new RelateModel(relateName);
callback?.(model);
return this;
}
};
var QueryModel = class extends Model {
constructor(modelName) {
super();
this.type = ModelType.MODEL;
this.modelName = modelName;
}
static is(model) {
return model.type === ModelType.MODEL;
}
};
var RelateModel = class RelateModel extends Model {
constructor(relateName) {
super();
this.type = ModelType.RELATE;
this.relateName = relateName;
}
recursive(count) {
let that = this;
for (let i = 1; i < count; i++) {
const model = new RelateModel(this.relateName);
model.conditions = that.conditions?.clone();
that.relates[this.relateName] = model;
that = model;
}
return this;
}
static is(model) {
return model.type === ModelType.RELATE;
}
};
var QueryProtocolBuilder = class {
startModel;
rootModel;
currentModel;
constructor(startModel) {
this.startModel = startModel;
this.currentModel = this.rootModel = new QueryModel(startModel);
}
model(modelName, callback) {
if (!modelName) callback?.(this.rootModel);
return this;
}
relate(relateName, callback) {
const model = new RelateModel(relateName);
const relate = this.relate.bind(this);
model.recursive = function (count) {
for (let i = 1; i < count; i++) relate(relateName);
return this;
};
this.currentModel.children = model;
this.currentModel = model;
callback?.(model);
return this;
}
protocol() {
return {
start: this.startModel,
option: this.rootModel
};
}
};
function comp(compType, propKey, value) {
return new CompCondition(compType, propKey, value);
}
function and(...conditions) {
return new AndCondition(conditions);
}
function or(...conditions) {
return new OrCondition(conditions);
}
//#endregion
//#region src/mongo-proxy/Client.ts
var Client = class {
constructor(option = {}) {
const { host = "localhost", protocol = "http", api = "" } = option;
let port = option.port;
if (typeof port !== "number" || Math.min(Math.max(0, port), 65535) !== port) port = 5174;
Object.assign(this, {
host,
port,
protocol,
api
});
}
get requestHref() {
const { protocol, host, port, api } = this;
return `${protocol}://${host}:${port}${api}`;
}
createQuery(protocol) {
return createJsonRequestJson(this.requestHref + "/query", { body: JSON.stringify({ protocol }) });
}
};
//#endregion
//#region src/mongo-proxy/DBContext.ts
const MODEL_METADATA_COLLECTION = "__model_metas__";
var DBContext = class {
constructor(uri, option = {}) {
this.client = new MongoClient$1(uri, {
minPoolSize: 5,
maxPoolSize: 50,
connectTimeoutMS: 5e3,
serverSelectionTimeoutMS: 5e3,
...option
});
this.modelMetas = /* @__PURE__ */new Map();
this.isConnected = false;
}
async connect(dbName) {
const { client } = this;
try {
await client.connect();
this.db = client.db(dbName);
await this.loadModelMetas();
this.isConnected = true;
console.log(`✅ Connected to MongoDB database: ${dbName}`);
} catch (error) {
this.isConnected = false;
console.error("❌ MongoDB connection error:", error);
throw error;
}
}
async disconnect() {
if (this.client) {
await this.client.close(true);
this.isConnected = false;
console.log("🔌 Disconnected from MongoDB");
}
}
async checkConnection() {
try {
if (!this.db) return false;
await this.db.command({ ping: 1 });
return true;
} catch (error) {
return false;
}
}
async loadModelMetas() {
if (!this.db) throw new Error("Database not connected");
try {
const collection = this.db.collection(MODEL_METADATA_COLLECTION);
const metas = await collection.find().toArray();
this.modelMetas.clear();
for (const meta of metas) this.modelMetas.set(meta.modelName, meta);
console.log(`📚 Loaded ${metas.length} model metadata definitions`);
} catch (error) {
console.error("Failed to load model metadata:", error);
}
}
async saveModelMeta(meta) {
if (!this.db) throw new Error("Database not connected");
try {
const collection = this.db.collection(MODEL_METADATA_COLLECTION);
await collection.updateOne({ modelName: meta.modelName }, { $set: meta }, { upsert: true });
this.modelMetas.set(meta.modelName, meta);
console.log(`💾 Saved model metadata for: ${meta.modelName}`);
} catch (error) {
console.error(`Failed to save model metadata for ${meta.modelName}:`, error);
throw error;
}
}
getModelMeta(modelName) {
return this.modelMetas.get(modelName);
}
getAllModelNames() {
return Array.from(this.modelMetas.keys());
}
getCollection(modelName) {
if (!this.db) throw new Error("Database not connected");
return this.db.collection(modelName);
}
};
//#endregion
//#region src/mongo-proxy/QueryExecutor.ts
const FilterTypeMap = {
"!=": "$ne",
"=": "$eq",
"<": "$lt",
"<=": "$lte",
">": "$gt",
">=": "$gte",
in: "$in",
nin: "$nin",
exist: "$exist"
};
var QueryExecutor = class {
cache = /* @__PURE__ */new Map();
constructor(option) {
Object.assign(option);
}
async clearCache() {
this.cache.clear();
}
async execute(protocol) {
const cacheKey = this.generateCacheKey(protocol);
const cache = this.cache.get(cacheKey);
if (cache) return cache;
const result = this.processProtocol(protocol);
this.cache.set(cacheKey, result);
return result;
}
resolveCondition(condition) {
if (!condition) return {};
if (CompCondition.is(condition)) return { [condition.propKey]: { [FilterTypeMap[condition.compType]]: condition.compType === "exist" ? true : condition.value } };
return { [AndCondition.is(condition) ? "$and" : "$or"]: condition.conditions.map(this.resolveCondition) };
}
async processProtocol(protocol) {
const process$1 = async (option) => {
const { modelName, conditions: condition } = option;
const collection = this.dbContext.getCollection(modelName);
const models = (await collection.find(this.resolveCondition(condition)).toArray()).map((_model) => {
const { _id, ...model } = _model;
return {
_id,
model,
relates: {}
};
});
/**
* TODO
* 判断查询条件有没有关系,即relates是否为空对象
* 否,则直接返回models
* 有关系查询,则找到对应模型的meta元数据,处理meta.relations中存在的搞关系
* 在meta.relating中找到对应关系,根据实例id去找到关联的实例id
* 并生成比对id的condition和查询条件中对应的RelateModel的condition合并
* 生成新的QueryModel,包含对应RelateModel的relates和meta中对应关系的modelName和合并后的condition
* 递归处理新的QueryModel,将返回结果添加在当前model实例的relates中
*/
const relateKeys = Reflect.ownKeys(option.relates);
if (relateKeys.length === 0) return models;
const relateHandles = models.map(async ({ _id, relates }) => {
const handles = relateKeys.map((relationName) => {
const meta = this.dbContext.getModelMeta(modelName);
assert(meta, "unknown modelName: " + modelName);
if (!Reflect.has(meta.relations, relationName) || !Reflect.has(meta.relating, relationName)) return;
const relationMeta = Reflect.get(meta.relations, relationName, meta.relations);
if (!relationMeta) return;
const relating = meta.relating[relationName].get(_id);
if (!relating) return;
const relateModel = option.relates[relationName];
const { correspondingModel } = relationMeta;
const newOption = new QueryModel(correspondingModel);
newOption.relates = relateModel.relates;
newOption.conditions = and(...[relateModel.conditions, comp("in", "_id", relating)].filter(Boolean));
return process$1(newOption).then((relations) => {
relates[relationName] = relations;
});
}).filter(Boolean);
return Promise.all(handles);
});
await Promise.all(relateHandles);
return models;
};
return await process$1(protocol.option);
}
generateCacheKey(protocol) {
return JSON.stringify(protocol);
}
};
//#endregion
//#region src/mongo-proxy/DatabaseProxyService.ts
var DatabaseProxyService = class {
dbContext;
constructor(dbContext, option) {
this.dbContext = dbContext;
this.app = express();
this.queryExecutor = new QueryExecutor({ dbContext });
this.router = Router();
this.setupMiddleware();
this.setupRoutes();
this.setupApp();
this.base = "";
Object.assign(this, option || {});
}
setupMiddleware() {
this.app.use(bodyParser.json());
this.app.use((req, res, next) => {
console.log(`${(/* @__PURE__ */new Date()).toLocaleTimeString()} - ${req.method} ${req.path}`);
next();
});
}
setupApp() {
this.router.route(this.base);
this.app.use(this.router);
}
setupRoutes() {
this.router;
this.router.post("/query", async (req, res) => {
try {
const { protocol } = req.body;
if (!protocol || !protocol.start) return this.sendError(res, 400, "Invalid query protocol");
const result = await this.queryExecutor.execute(protocol);
this.sendSuccess(res, result);
} catch (error) {
this.sendError(res, 500, error.message || "Query execution failed");
}
});
this.router.post("/model-meta", async (req, res) => {
try {
const meta = req.body;
if (!meta || !meta.modelName) return this.sendError(res, 400, "Invalid model metadata");
await this.dbContext.saveModelMeta(meta);
this.sendSuccess(res, { success: true });
} catch (error) {
this.sendError(res, 500, error.message || "Failed to save model metadata");
}
});
this.router.get("/model-meta/:modelName", async (req, res) => {
try {
const modelName = req.params.modelName;
const meta = this.dbContext.getModelMeta(modelName);
if (!meta) return this.sendError(res, 404, `Model metadata not found for: ${modelName}`);
this.sendSuccess(res, meta);
} catch (error) {
this.sendError(res, 500, error.message || "Failed to get model metadata");
}
});
this.router.get("/models", async (req, res) => {
try {
const modelNames = this.dbContext.getAllModelNames();
this.sendSuccess(res, modelNames);
} catch (error) {
this.sendError(res, 500, error.message || "Failed to get model names");
}
});
this.router.get("/health", async (req, res) => {
try {
const dbStatus = (await this.dbContext.checkConnection()) ? "connected" : "disconnected";
const response = {
status: "ok",
timestamp: (/* @__PURE__ */new Date()).toISOString(),
uptime: process.uptime(),
dbStatus
};
res.json(response);
} catch (error) {
const response = {
status: "error",
timestamp: (/* @__PURE__ */new Date()).toISOString(),
uptime: process.uptime(),
dbStatus: "error"
};
res.status(500).json(response);
}
});
this.router.post("/clear-cache", async (req, res) => {
try {
this.queryExecutor.clearCache();
this.sendSuccess(res, { message: "Cache cleared successfully" });
} catch (error) {
this.sendError(res, 500, error.message || "Failed to clear cache");
}
});
}
sendSuccess(res, data, message) {
res.json(createSuccessResponse(data, message));
}
sendError(res, status, message, details) {
res.status(status).json(createErrorResponse(message, details));
}
start(port = 3e3) {
this.app.listen(port, () => {
console.log(`\n🚀 Database proxy service running on port ${port}`);
console.log(`📊 Query endpoint: POST http://localhost:${port}/query`);
console.log(`📝 Model meta endpoint: POST http://localhost:${port}/model-meta`);
console.log(`📋 Model meta endpoint: GET http://localhost:${port}/model-meta/:modelName`);
console.log(`📚 Models endpoint: GET http://localhost:${port}/models`);
console.log(`🧹 Cache endpoint: POST http://localhost:${port}/clear-cache`);
console.log(`❤️ Health check: GET http://localhost:${port}/health\n`);
});
}
};
function createSuccessResponse(data, message) {
return {
code: 0,
success: true,
data,
message
};
}
function createErrorResponse(error, details) {
return {
code: 1,
error,
details
};
}
//#endregion
export { AndCondition, Client, CodeResultConstructor as CodeResult, CompCondition, ConditionType, DBContext, DatabaseProxyService, Db, Model, ModelType, MongoClient, OrCondition, QueryExecutor, QueryModel, QueryProtocolBuilder, RelateModel, RelationType, and, comp, createErrorResponse, createProxyMiddleware, createServer, createSuccessResponse, createWebSocketProxy, generateAlignedProxyReport, or, printAlignedProxyServerInfo, setupProxy, staticMiddle };
//# sourceMappingURL=index.js.map