@cartanova/qgrid-cli 1.5.2 → 1.5.4

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 (42) hide show
  1. package/bundle/dist/application/qgrid/qgrid.frame.js +16 -3
  2. package/bundle/dist/application/queries.generated.js +2 -1
  3. package/bundle/dist/application/request-log/request-log.model.js +9 -2
  4. package/bundle/dist/application/sonamu.generated.js +5 -3
  5. package/bundle/dist/application/sonamu.generated.sso.js +3 -2
  6. package/bundle/dist/i18n/sd.generated.js +2 -1
  7. package/bundle/dist/migrations/20260421223627_alter_request_logs_add1_alter1.js +16 -0
  8. package/bundle/src/application/qgrid/qgrid.frame.ts +15 -9
  9. package/bundle/src/application/queries.generated.ts +3 -0
  10. package/bundle/src/application/request-log/request-log.entity.json +9 -2
  11. package/bundle/src/application/request-log/request-log.model.ts +16 -7
  12. package/bundle/src/application/sonamu.generated.http +8 -1
  13. package/bundle/src/application/sonamu.generated.sso.ts +1 -0
  14. package/bundle/src/application/sonamu.generated.ts +3 -1
  15. package/bundle/src/i18n/sd.generated.ts +1 -0
  16. package/bundle/src/migrations/20260421223627_alter_request_logs_add1_alter1.ts +15 -0
  17. package/bundle/web-dist/client/assets/cost-DE_8cLD-.js +1 -0
  18. package/bundle/web-dist/client/assets/{index-C8rLkdK0.js → index-CiLfNFWG.js} +3 -3
  19. package/bundle/web-dist/client/assets/index-kQRqXaWM.css +1 -0
  20. package/bundle/web-dist/client/assets/logs-9Q-LQWWo.js +1 -0
  21. package/bundle/web-dist/client/assets/routes-MR1DKizN.js +5 -0
  22. package/bundle/web-dist/client/assets/{sd.generated-CkJCx4Bp.js → sd.generated-DXtkTTGn.js} +1 -1
  23. package/bundle/web-dist/client/assets/{services.generated-1X7EKUWg.js → services.generated-C0OpNm5q.js} +1 -1
  24. package/bundle/web-dist/client/assets/{show-QSjdjp8w.js → show-DaKh4LaA.js} +1 -1
  25. package/bundle/web-dist/client/assets/tokens-FnhMN5oT.js +1 -0
  26. package/bundle/web-dist/client/index.html +3 -3
  27. package/bundle/web-dist/server/assets/{copy-C9YkjJVm.js → copy-GKsNP-2_.js} +1 -1
  28. package/bundle/web-dist/server/assets/cost-D0Ta7MJa.js +14 -0
  29. package/bundle/web-dist/server/assets/{lazyRouteComponent-Dyl_0WZs.js → lazyRouteComponent-B78WDGgM.js} +1 -1
  30. package/bundle/web-dist/server/assets/{logs-bLRMIO1J.js → logs-Dcv1XCUK.js} +38 -21
  31. package/bundle/web-dist/server/assets/{routes-qwzTPLE2.js → routes-B5FkWLUe.js} +26 -17
  32. package/bundle/web-dist/server/assets/{sd.generated-BeEKgSOs.js → sd.generated-Mnbmi4YR.js} +1 -0
  33. package/bundle/web-dist/server/assets/{services.generated-DjxCLdMu.js → services.generated-DjdxFvCg.js} +20 -1
  34. package/bundle/web-dist/server/assets/{show-CvoILmu3.js → show-BqSxVXai.js} +4 -4
  35. package/bundle/web-dist/server/assets/{tokens-BWmL4GfT.js → tokens-BGaTdsEb.js} +7 -5
  36. package/bundle/web-dist/server/entry-server.generated.js +6 -6
  37. package/package.json +1 -1
  38. package/bundle/web-dist/client/assets/index-BVj-Wxnl.css +0 -1
  39. package/bundle/web-dist/client/assets/logs-BhPrkIxX.js +0 -1
  40. package/bundle/web-dist/client/assets/routes-C8VZv8Ii.js +0 -5
  41. package/bundle/web-dist/client/assets/tokens-BX0VO0Os.js +0 -1
  42. /package/bundle/web-dist/client/assets/{copy-dnxfhGiF.js → copy-DdGJDXSK.js} +0 -0
@@ -9,9 +9,12 @@ import {
9
9
  } from "sonamu";
10
10
 
11
11
  import { SD } from "../../i18n/sd.generated";
12
- import type { RequestLogSubsetKey, RequestLogSubsetMapping } from "../sonamu.generated";
12
+ import { type RequestLogSubsetKey, type RequestLogSubsetMapping } from "../sonamu.generated";
13
13
  import { requestLogLoaderQueries, requestLogSubsetQueries } from "../sonamu.generated.sso";
14
- import type { RequestLogListParams, RequestLogSaveParams } from "./request-log.types";
14
+ import { type RequestLogListParams, type RequestLogSaveParams } from "./request-log.types";
15
+
16
+ // cost_usd는 정수 micro-USD로 저장. 실제 USD = cost_usd / MICRO_USD.
17
+ export const MICRO_USD = 1_000_000;
15
18
 
16
19
  /*
17
20
  RequestLog Model
@@ -61,7 +64,6 @@ class RequestLogModelClass extends BaseModelClass<
61
64
  subset: T,
62
65
  rawParams?: LP,
63
66
  ): Promise<ListResult<LP, RequestLogSubsetMapping[T]>> {
64
- // params with defaults
65
67
  const params = {
66
68
  num: 24,
67
69
  page: 1,
@@ -70,20 +72,16 @@ class RequestLogModelClass extends BaseModelClass<
70
72
  ...rawParams,
71
73
  } satisfies RequestLogListParams;
72
74
 
73
- // build queries
74
75
  const { qb, onSubset: _ } = this.getSubsetQueries(subset);
75
76
 
76
- // id
77
77
  if (params.id) {
78
78
  qb.whereIn("request_logs.id", asArray(params.id));
79
79
  }
80
80
 
81
- // token_name filter — prefix 매칭 (DongSeon → DongSeon-1, DongSeon-2, ...)
82
81
  if (params.token_name) {
83
82
  qb.where("request_logs.token_name", "like", `${params.token_name}-%`);
84
83
  }
85
84
 
86
- // search-keyword
87
85
  if (params.search && params.keyword && params.keyword.length > 0) {
88
86
  if (params.search === "id") {
89
87
  qb.where("request_logs.id", Number(params.keyword));
@@ -139,6 +137,17 @@ class RequestLogModelClass extends BaseModelClass<
139
137
  });
140
138
  }
141
139
 
140
+ // Sonamu findMany는 subset 전체 컬럼(text 포함)을 페치해서 aggregate엔 너무 무거움 → raw sum 사용.
141
+ async totalCost(params: { token_name?: string } = {}): Promise<number> {
142
+ const qb = this.getDB("r")("request_logs");
143
+ if (params.token_name) {
144
+ qb.where("token_name", "like", `${params.token_name}-%`);
145
+ }
146
+ // knex는 pg에서 numeric aggregate를 string으로 반환.
147
+ const row = (await qb.sum({ sum: "cost_usd" }).first()) as { sum: string | null } | undefined;
148
+ return Number(row?.sum ?? 0) / MICRO_USD;
149
+ }
150
+
142
151
  @api({ httpMethod: "POST", clients: ["axios", "tanstack-mutation"] })
143
152
  async del(ids: number[]): Promise<number> {
144
153
  const wdb = this.getPuri("w");
@@ -103,7 +103,8 @@ Content-Type: application/json
103
103
  "output_tokens": 0,
104
104
  "cache_read_tokens": 0,
105
105
  "cache_creation_tokens": 0,
106
- "duration_ms": 0
106
+ "duration_ms": 0,
107
+ "cost_usd": null
107
108
  }
108
109
  ]
109
110
  }
@@ -138,6 +139,12 @@ Content-Type: application/json
138
139
 
139
140
  ###
140
141
 
142
+ GET {{baseUrl}}/api/qgrid/totalCost
143
+ ?tokenName=TOKENNAME
144
+ Content-Type: application/json
145
+
146
+ ###
147
+
141
148
  POST {{baseUrl}}/api/qgrid/addToken
142
149
  Content-Type: application/json
143
150
 
@@ -25,6 +25,7 @@ export const requestLogSubsetQueries = {
25
25
  cache_read_tokens: "request_logs.cache_read_tokens",
26
26
  cache_creation_tokens: "request_logs.cache_creation_tokens",
27
27
  duration_ms: "request_logs.duration_ms",
28
+ cost_usd: "request_logs.cost_usd",
28
29
  });
29
30
  },
30
31
  };
@@ -37,9 +37,10 @@ export const RequestLogBaseSchema = z.object({
37
37
  cache_read_tokens: z.int(),
38
38
  cache_creation_tokens: z.int(),
39
39
  duration_ms: z.int(),
40
+ cost_usd: z.int().nullable(),
40
41
  });
41
42
  export type RequestLogBaseSchema = z.infer<typeof RequestLogBaseSchema> & {
42
- readonly __hasDefault__: readonly ["created_at", "id"];
43
+ readonly __hasDefault__: readonly ["created_at", "cost_usd", "id"];
43
44
  };
44
45
 
45
46
  // BaseSchema: Token
@@ -110,6 +111,7 @@ export const RequestLogSubsetA = z.object({
110
111
  cache_read_tokens: z.int(),
111
112
  cache_creation_tokens: z.int(),
112
113
  duration_ms: z.int(),
114
+ cost_usd: z.int().nullable(),
113
115
  });
114
116
  export type RequestLogSubsetA = z.infer<typeof RequestLogSubsetA>;
115
117
  export type RequestLogSubsetMapping = {
@@ -220,6 +220,7 @@ const entityLabels = {
220
220
  "entity.RequestLog.cache_read_tokens": "캐시 읽기 토큰",
221
221
  "entity.RequestLog.cache_creation_tokens": "캐시 생성 토큰",
222
222
  "entity.RequestLog.duration_ms": "응답 소요시간(ms)",
223
+ "entity.RequestLog.cost_usd": "API 비용",
223
224
  "enum.RequestLogOrderBy.id-desc": "ID최신순",
224
225
  "enum.RequestLogSearchField.id": "ID",
225
226
  "enum.RequestLogSearchField.token_name": "토큰이름",
@@ -0,0 +1,15 @@
1
+ import { Knex } from "knex";
2
+
3
+ export async function up(knex: Knex): Promise<void> {
4
+ await knex.schema.alterTable("request_logs", (table) => {
5
+ // add
6
+ table.integer("cost_usd").nullable();
7
+ });
8
+ }
9
+
10
+ export async function down(knex: Knex): Promise<void> {
11
+ await knex.schema.alterTable("request_logs", (table) => {
12
+ // rollback - add
13
+ table.dropColumns("cost_usd");
14
+ });
15
+ }
@@ -0,0 +1 @@
1
+ var e=1e6,t=4;function n(t){return t/e}function r(e){return`$${e.toFixed(t)}`}function i(e){return r(n(e))}export{r as n,i as t};