@downcity/services 0.1.67 → 0.1.69

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 (55) hide show
  1. package/bin/accounts/index.d.ts +1 -5
  2. package/bin/accounts/index.d.ts.map +1 -1
  3. package/bin/accounts/index.js +1 -4
  4. package/bin/accounts/index.js.map +1 -1
  5. package/bin/balance/index.d.ts +1 -1
  6. package/bin/balance/index.d.ts.map +1 -1
  7. package/bin/balance/index.js +1 -1
  8. package/bin/balance/index.js.map +1 -1
  9. package/bin/balance/service.d.ts +0 -4
  10. package/bin/balance/service.d.ts.map +1 -1
  11. package/bin/balance/service.js +0 -6
  12. package/bin/balance/service.js.map +1 -1
  13. package/bin/billing/index.d.ts +1 -1
  14. package/bin/billing/index.d.ts.map +1 -1
  15. package/bin/billing/index.js +1 -1
  16. package/bin/billing/index.js.map +1 -1
  17. package/bin/billing/service.d.ts +0 -4
  18. package/bin/billing/service.d.ts.map +1 -1
  19. package/bin/billing/service.js +0 -6
  20. package/bin/billing/service.js.map +1 -1
  21. package/bin/index.d.ts +6 -6
  22. package/bin/index.d.ts.map +1 -1
  23. package/bin/index.js +5 -5
  24. package/bin/index.js.map +1 -1
  25. package/bin/payment/helpers.d.ts +68 -0
  26. package/bin/payment/helpers.d.ts.map +1 -0
  27. package/bin/payment/helpers.js +148 -0
  28. package/bin/payment/helpers.js.map +1 -0
  29. package/bin/payment/index.d.ts +10 -28
  30. package/bin/payment/index.d.ts.map +1 -1
  31. package/bin/payment/index.js +9 -890
  32. package/bin/payment/index.js.map +1 -1
  33. package/bin/payment/providers.d.ts +25 -0
  34. package/bin/payment/providers.d.ts.map +1 -0
  35. package/bin/payment/providers.js +415 -0
  36. package/bin/payment/providers.js.map +1 -0
  37. package/bin/payment/routes.d.ts +29 -0
  38. package/bin/payment/routes.d.ts.map +1 -0
  39. package/bin/payment/routes.js +394 -0
  40. package/bin/payment/routes.js.map +1 -0
  41. package/bin/payment/service.d.ts +448 -0
  42. package/bin/payment/service.d.ts.map +1 -0
  43. package/bin/payment/service.js +72 -0
  44. package/bin/payment/service.js.map +1 -0
  45. package/bin/payment/types.d.ts +11 -18
  46. package/bin/payment/types.d.ts.map +1 -1
  47. package/bin/usage/index.d.ts +3 -174
  48. package/bin/usage/index.d.ts.map +1 -1
  49. package/bin/usage/index.js +2 -117
  50. package/bin/usage/index.js.map +1 -1
  51. package/bin/usage/service.d.ts +353 -0
  52. package/bin/usage/service.d.ts.map +1 -0
  53. package/bin/usage/service.js +140 -0
  54. package/bin/usage/service.js.map +1 -0
  55. package/package.json +2 -2
@@ -0,0 +1,140 @@
1
+ /**
2
+ * Downcity 官方 Usage 服务。
3
+ *
4
+ * 通过全局 hook 记录 service 调用事件。
5
+ * 兼容 Node.js 和 Cloudflare Workers(使用 Web Crypto API)。
6
+ */
7
+ import { sqliteTable, text } from "drizzle-orm/sqlite-core";
8
+ import { InstallableService } from "@downcity/city";
9
+ /**
10
+ * Usage 事件表。
11
+ */
12
+ export const usageEvents = sqliteTable("service_usage_events", {
13
+ event_id: text("event_id").primaryKey(),
14
+ town_id: text("town_id").notNull(),
15
+ user_id: text("user_id").notNull(),
16
+ service: text("service").notNull(),
17
+ model_id: text("model_id").notNull(),
18
+ status: text("status").notNull(),
19
+ metadata_json: text("metadata_json").notNull(),
20
+ created_at: text("created_at").notNull(),
21
+ });
22
+ /**
23
+ * Usage 服务实例。
24
+ */
25
+ export class UsageService extends InstallableService {
26
+ options;
27
+ id = "usage";
28
+ name = "Usage";
29
+ version = "0.1.0";
30
+ schema = { events: usageEvents };
31
+ constructor(options = {}) {
32
+ super();
33
+ this.options = options;
34
+ this.instruction = [
35
+ "通过全局 hook 记录真实用户侧 service 调用事件。",
36
+ "默认只记录成功调用;record_errors=true 时也会记录失败调用。",
37
+ "常用读取方式是管理端查看 events/summary,用户侧查看 me。",
38
+ ].join("\n");
39
+ }
40
+ install(ctx) {
41
+ const events = ctx.table("events");
42
+ ctx.hook.after(async (serviceCtx) => {
43
+ if (!shouldRecordUsage(serviceCtx))
44
+ return;
45
+ await events.insert(createUsageEvent(serviceCtx, "success"));
46
+ });
47
+ if (this.options.record_errors) {
48
+ ctx.hook.onError(async (serviceCtx) => {
49
+ if (!shouldRecordUsage(serviceCtx))
50
+ return;
51
+ await events.insert(createUsageEvent(serviceCtx, "error"));
52
+ });
53
+ }
54
+ ctx.route({
55
+ method: "GET",
56
+ path: "/events",
57
+ auth: ["admin"],
58
+ async handler(requestCtx) {
59
+ return requestCtx.jsonResponse({ items: await events.select() });
60
+ },
61
+ });
62
+ ctx.route({
63
+ method: "GET",
64
+ path: "/summary",
65
+ auth: ["admin"],
66
+ async handler(requestCtx) {
67
+ return requestCtx.jsonResponse({
68
+ items: summarizeUsage(await events.select()),
69
+ });
70
+ },
71
+ });
72
+ ctx.route({
73
+ method: "GET",
74
+ path: "/me",
75
+ auth: ["user"],
76
+ async handler(requestCtx) {
77
+ return requestCtx.jsonResponse({
78
+ items: await events.select({
79
+ user_id: requestCtx.user?.user_id ?? "",
80
+ town_id: requestCtx.town?.town_id ?? "",
81
+ }),
82
+ });
83
+ },
84
+ });
85
+ }
86
+ }
87
+ /**
88
+ * 只记录真实用户侧调用。
89
+ *
90
+ * 管理端操作没有 user/town 上下文,usage 服务自己的查询也不应反过来
91
+ * 产生 usage 事件,否则统计接口会污染自身结果。
92
+ */
93
+ function shouldRecordUsage(ctx) {
94
+ return Boolean(ctx.user?.user_id && ctx.town?.town_id && ctx.service?.id !== "usage");
95
+ }
96
+ /**
97
+ * 创建 usage 事件记录。
98
+ */
99
+ function createUsageEvent(ctx, status) {
100
+ return {
101
+ event_id: `usage_${randomId()}`,
102
+ town_id: ctx.town?.town_id ?? "",
103
+ user_id: ctx.user?.user_id ?? "",
104
+ service: ctx.service?.id ?? "",
105
+ model_id: ctx.variant?.id ?? "",
106
+ status,
107
+ metadata_json: JSON.stringify({
108
+ variant: ctx.variant?.id,
109
+ started_at: ctx.started_at?.toISOString(),
110
+ ended_at: ctx.ended_at?.toISOString(),
111
+ error: ctx.error?.message,
112
+ }),
113
+ created_at: new Date().toISOString(),
114
+ };
115
+ }
116
+ /**
117
+ * 汇总 usage 事件。
118
+ */
119
+ function summarizeUsage(rows) {
120
+ const byKey = new Map();
121
+ for (const row of rows) {
122
+ const key = `${row.town_id}\u0000${row.service}\u0000${row.status}`;
123
+ const current = byKey.get(key) ?? { town_id: row.town_id, service: row.service, status: row.status, count: 0 };
124
+ current.count += 1;
125
+ byKey.set(key, current);
126
+ }
127
+ return [...byKey.values()].sort((a, b) => `${a.town_id}:${a.service}:${a.status}`.localeCompare(`${b.town_id}:${b.service}:${b.status}`));
128
+ }
129
+ /**
130
+ * 生成随机 ID(兼容 Node 和 Workers)。
131
+ */
132
+ function randomId() {
133
+ const buf = new Uint8Array(12);
134
+ crypto.getRandomValues(buf);
135
+ return btoa(String.fromCharCode(...buf))
136
+ .replace(/\+/g, "-")
137
+ .replace(/\//g, "_")
138
+ .replace(/=+$/u, "");
139
+ }
140
+ //# sourceMappingURL=service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"service.js","sourceRoot":"","sources":["../../src/usage/service.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@downcity/services",
3
- "version": "0.1.67",
3
+ "version": "0.1.69",
4
4
  "description": "Downcity public services package for accounts, balance, usage, Stripe, Creem, Dodo, and Waffo payment flows.",
5
5
  "type": "module",
6
6
  "main": "./bin/index.js",
@@ -50,7 +50,7 @@
50
50
  },
51
51
  "dependencies": {
52
52
  "@waffo/pancake-ts": "^0.11.0",
53
- "@downcity/city": "0.2.75",
53
+ "@downcity/city": "0.2.78",
54
54
  "better-auth": "^1.6.12",
55
55
  "dodopayments": "^2.36.0",
56
56
  "drizzle-orm": "^0.45.2"