@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.
- package/bundle/dist/application/qgrid/qgrid.frame.js +16 -3
- package/bundle/dist/application/queries.generated.js +2 -1
- package/bundle/dist/application/request-log/request-log.model.js +9 -2
- package/bundle/dist/application/sonamu.generated.js +5 -3
- package/bundle/dist/application/sonamu.generated.sso.js +3 -2
- package/bundle/dist/i18n/sd.generated.js +2 -1
- package/bundle/dist/migrations/20260421223627_alter_request_logs_add1_alter1.js +16 -0
- package/bundle/src/application/qgrid/qgrid.frame.ts +15 -9
- package/bundle/src/application/queries.generated.ts +3 -0
- package/bundle/src/application/request-log/request-log.entity.json +9 -2
- package/bundle/src/application/request-log/request-log.model.ts +16 -7
- package/bundle/src/application/sonamu.generated.http +8 -1
- package/bundle/src/application/sonamu.generated.sso.ts +1 -0
- package/bundle/src/application/sonamu.generated.ts +3 -1
- package/bundle/src/i18n/sd.generated.ts +1 -0
- package/bundle/src/migrations/20260421223627_alter_request_logs_add1_alter1.ts +15 -0
- package/bundle/web-dist/client/assets/cost-DE_8cLD-.js +1 -0
- package/bundle/web-dist/client/assets/{index-C8rLkdK0.js → index-CiLfNFWG.js} +3 -3
- package/bundle/web-dist/client/assets/index-kQRqXaWM.css +1 -0
- package/bundle/web-dist/client/assets/logs-9Q-LQWWo.js +1 -0
- package/bundle/web-dist/client/assets/routes-MR1DKizN.js +5 -0
- package/bundle/web-dist/client/assets/{sd.generated-CkJCx4Bp.js → sd.generated-DXtkTTGn.js} +1 -1
- package/bundle/web-dist/client/assets/{services.generated-1X7EKUWg.js → services.generated-C0OpNm5q.js} +1 -1
- package/bundle/web-dist/client/assets/{show-QSjdjp8w.js → show-DaKh4LaA.js} +1 -1
- package/bundle/web-dist/client/assets/tokens-FnhMN5oT.js +1 -0
- package/bundle/web-dist/client/index.html +3 -3
- package/bundle/web-dist/server/assets/{copy-C9YkjJVm.js → copy-GKsNP-2_.js} +1 -1
- package/bundle/web-dist/server/assets/cost-D0Ta7MJa.js +14 -0
- package/bundle/web-dist/server/assets/{lazyRouteComponent-Dyl_0WZs.js → lazyRouteComponent-B78WDGgM.js} +1 -1
- package/bundle/web-dist/server/assets/{logs-bLRMIO1J.js → logs-Dcv1XCUK.js} +38 -21
- package/bundle/web-dist/server/assets/{routes-qwzTPLE2.js → routes-B5FkWLUe.js} +26 -17
- package/bundle/web-dist/server/assets/{sd.generated-BeEKgSOs.js → sd.generated-Mnbmi4YR.js} +1 -0
- package/bundle/web-dist/server/assets/{services.generated-DjxCLdMu.js → services.generated-DjdxFvCg.js} +20 -1
- package/bundle/web-dist/server/assets/{show-CvoILmu3.js → show-BqSxVXai.js} +4 -4
- package/bundle/web-dist/server/assets/{tokens-BWmL4GfT.js → tokens-BGaTdsEb.js} +7 -5
- package/bundle/web-dist/server/entry-server.generated.js +6 -6
- package/package.json +1 -1
- package/bundle/web-dist/client/assets/index-BVj-Wxnl.css +0 -1
- package/bundle/web-dist/client/assets/logs-BhPrkIxX.js +0 -1
- package/bundle/web-dist/client/assets/routes-C8VZv8Ii.js +0 -5
- package/bundle/web-dist/client/assets/tokens-BX0VO0Os.js +0 -1
- /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
|
|
12
|
+
import { type RequestLogSubsetKey, type RequestLogSubsetMapping } from "../sonamu.generated";
|
|
13
13
|
import { requestLogLoaderQueries, requestLogSubsetQueries } from "../sonamu.generated.sso";
|
|
14
|
-
import type
|
|
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
|
|
|
@@ -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};
|