@heyhru/app-dms-server 0.7.0 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.js +55 -27
  2. package/package.json +7 -6
package/dist/index.js CHANGED
@@ -1,3 +1,33 @@
1
+ // src/otel.ts
2
+ import { initOtel } from "@heyhru/server-plugin-otel";
3
+
4
+ // src/config.ts
5
+ if (!process.env.DATABASE_URL) {
6
+ throw new Error("DATABASE_URL environment variable is required");
7
+ }
8
+ var config = {
9
+ port: Number(process.env.PORT) || 3001,
10
+ jwtSecret: process.env.JWT_SECRET || "dev-secret-change-in-production",
11
+ jwtExpiresIn: "24h",
12
+ encryptionKey: process.env.ENCRYPTION_KEY || "dev-encryption-key-32-bytes-long!",
13
+ dbUrl: process.env.DATABASE_URL,
14
+ dbSsl: process.env.DATABASE_SSL === "true",
15
+ dbPoolMin: Number(process.env.DATABASE_POOL_MIN) || 2,
16
+ dbPoolMax: Number(process.env.DATABASE_POOL_MAX) || 10,
17
+ dbIdleTimeoutMs: Number(process.env.DATABASE_IDLE_TIMEOUT) || 1e4,
18
+ nodeEnv: process.env.NODE_ENV || "development",
19
+ logDir: process.env.LOG_DIR || "",
20
+ otelEndpoint: process.env.OTEL_EXPORTER_OTLP_ENDPOINT || "http://localhost:4317",
21
+ otelEnabled: process.env.OTEL_ENABLED === "true"
22
+ };
23
+
24
+ // src/otel.ts
25
+ initOtel({
26
+ serviceName: "app-dms-server",
27
+ endpoint: config.otelEndpoint,
28
+ enabled: config.otelEnabled
29
+ });
30
+
1
31
  // src/index.ts
2
32
  import { createPgDb } from "@heyhru/server-plugin-pg";
3
33
 
@@ -43,26 +73,6 @@ function refreshPoolMetrics() {
43
73
 
44
74
  // src/auth/auth.middleware.ts
45
75
  import { verifyToken as jwtVerify } from "@heyhru/server-plugin-jwt";
46
-
47
- // src/config.ts
48
- if (!process.env.DATABASE_URL) {
49
- throw new Error("DATABASE_URL environment variable is required");
50
- }
51
- var config = {
52
- port: Number(process.env.PORT) || 3001,
53
- jwtSecret: process.env.JWT_SECRET || "dev-secret-change-in-production",
54
- jwtExpiresIn: "24h",
55
- encryptionKey: process.env.ENCRYPTION_KEY || "dev-encryption-key-32-bytes-long!",
56
- dbUrl: process.env.DATABASE_URL,
57
- dbSsl: process.env.DATABASE_SSL === "true",
58
- dbPoolMin: Number(process.env.DATABASE_POOL_MIN) || 2,
59
- dbPoolMax: Number(process.env.DATABASE_POOL_MAX) || 10,
60
- dbIdleTimeoutMs: Number(process.env.DATABASE_IDLE_TIMEOUT) || 1e4,
61
- nodeEnv: process.env.NODE_ENV || "development",
62
- logDir: process.env.LOG_DIR || ""
63
- };
64
-
65
- // src/auth/auth.middleware.ts
66
76
  function verifyToken(token) {
67
77
  return jwtVerify(token, config.jwtSecret);
68
78
  }
@@ -252,20 +262,28 @@ function postSqlParse(req, reply) {
252
262
  return reply.send({ category: sqlParse(sql) });
253
263
  }
254
264
  async function postSqlExecute(req, reply) {
255
- const { dataSourceId, database, sql } = req.body ?? {};
265
+ const body = req.body ?? {};
266
+ const { dataSourceId, database, sql } = body;
256
267
  if (!dataSourceId || !sql) {
257
268
  return reply.code(400).send({ error: "\u6570\u636E\u6E90 ID \u548C SQL \u4E0D\u80FD\u4E3A\u7A7A" });
258
269
  }
270
+ const page = typeof body.page === "number" ? body.page : 1;
271
+ const pageSize = typeof body.pageSize === "number" ? body.pageSize : 50;
259
272
  const ip = req.headers["x-forwarded-for"] ?? req.headers["x-real-ip"] ?? "unknown";
260
273
  try {
261
- const rows = await sqlExecute({ dataSourceId, database, sql, userId: req.user.id, ip });
262
- return reply.send({ rows });
274
+ const result = await sqlExecute({ dataSourceId, database, sql, userId: req.user.id, ip, page, pageSize });
275
+ return reply.send(result);
263
276
  } catch (err) {
264
277
  req.log.error(err, "SQL execute failed (user=%s, ds=%s)", req.user.id, dataSourceId);
265
278
  return reply.code(400).send({ error: err instanceof Error ? err.message : String(err) });
266
279
  }
267
280
  }
268
- async function sqlExecute({ dataSourceId, database, sql, userId, ip }) {
281
+ async function fetchCountQuery(pool, sql) {
282
+ const countSql = `SELECT COUNT(*) AS total FROM (${sql}) AS _count_t`;
283
+ const rows = await pool.execute(countSql);
284
+ return Number(rows[0]?.total ?? 0);
285
+ }
286
+ async function sqlExecute({ dataSourceId, database, sql, userId, ip, page, pageSize }) {
269
287
  const category = sqlParse(sql);
270
288
  if (category !== "select") {
271
289
  throw new Error("\u4EC5\u5141\u8BB8\u76F4\u63A5\u6267\u884C SELECT \u8BED\u53E5");
@@ -275,10 +293,20 @@ async function sqlExecute({ dataSourceId, database, sql, userId, ip }) {
275
293
  return ds ? getPool(ds) : null;
276
294
  })();
277
295
  if (!pool) throw new Error("\u6570\u636E\u6E90\u672A\u627E\u5230");
296
+ const hasLimit = /\bLIMIT\b/i.test(sql);
297
+ const dataSql = hasLimit ? sql : `${sql} LIMIT ${pageSize} OFFSET ${(page - 1) * pageSize}`;
278
298
  const end = sqlDuration.startTimer({ data_source_id: dataSourceId, sql_type: category });
279
299
  let rows;
300
+ let total;
280
301
  try {
281
- rows = await pool.execute(sql);
302
+ if (hasLimit) {
303
+ rows = await pool.execute(dataSql);
304
+ total = rows.length;
305
+ } else {
306
+ const [rawRows, count] = await Promise.all([pool.execute(dataSql), fetchCountQuery(pool, sql)]);
307
+ rows = rawRows;
308
+ total = count;
309
+ }
282
310
  end({ status: "success" });
283
311
  } catch (err) {
284
312
  end({ status: "failed" });
@@ -289,10 +317,10 @@ async function sqlExecute({ dataSourceId, database, sql, userId, ip }) {
289
317
  dataSourceId,
290
318
  action: "SELECT",
291
319
  sqlText: sql,
292
- resultSummary: `${rows.length} rows`,
320
+ resultSummary: `${total} total rows`,
293
321
  ipAddress: ip
294
322
  });
295
- return rows;
323
+ return { rows, total, page, pageSize };
296
324
  }
297
325
  async function postSqlDatabases(req, reply) {
298
326
  const { dataSourceId } = req.body ?? {};
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "publishConfig": {
4
4
  "access": "public"
5
5
  },
6
- "version": "0.7.0",
6
+ "version": "0.9.0",
7
7
  "description": "DMS backend API server built on Fastify",
8
8
  "type": "module",
9
9
  "main": "./dist/index.mjs",
@@ -19,15 +19,16 @@
19
19
  },
20
20
  "dependencies": {
21
21
  "@fastify/cors": "^11.2.0",
22
- "@heyhru/business-dms-approval": "0.6.1",
22
+ "@heyhru/business-dms-approval": "0.6.3",
23
23
  "@heyhru/business-dms-audit": "0.6.1",
24
- "@heyhru/business-dms-datasource": "0.7.0",
24
+ "@heyhru/business-dms-datasource": "0.7.2",
25
25
  "@heyhru/business-dms-saved-sql": "0.6.1",
26
26
  "@heyhru/business-dms-user": "0.6.1",
27
27
  "@heyhru/common-util-logger": "0.6.0",
28
28
  "@heyhru/server-plugin-jwt": "0.6.0",
29
- "@heyhru/server-plugin-metrics": "0.7.0",
30
- "@heyhru/server-plugin-mysql": "0.7.0",
29
+ "@heyhru/server-plugin-metrics": "0.7.1",
30
+ "@heyhru/server-plugin-mysql": "0.7.1",
31
+ "@heyhru/server-plugin-otel": "0.7.0",
31
32
  "@heyhru/server-plugin-pg": "0.7.0",
32
33
  "@heyhru/server-util-crypto": "0.6.0",
33
34
  "fastify": "^5.8.4",
@@ -42,5 +43,5 @@
42
43
  "typescript": "^6.0.2",
43
44
  "vitest": "^4.1.4"
44
45
  },
45
- "gitHead": "b9097b9ad29ac4c0c3610a39cb0db83f74a11fb8"
46
+ "gitHead": "c38ab5dee711b502d5811978ddb1329289bd9d25"
46
47
  }