@downcity/services 0.1.67 → 0.1.71

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 (79) 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 +3 -3
  6. package/bin/balance/index.d.ts.map +1 -1
  7. package/bin/balance/index.js +2 -2
  8. package/bin/balance/index.js.map +1 -1
  9. package/bin/balance/routes.d.ts.map +1 -1
  10. package/bin/balance/routes.js +36 -0
  11. package/bin/balance/routes.js.map +1 -1
  12. package/bin/balance/schema.d.ts +161 -0
  13. package/bin/balance/schema.d.ts.map +1 -1
  14. package/bin/balance/schema.js +38 -0
  15. package/bin/balance/schema.js.map +1 -1
  16. package/bin/balance/service.d.ts +171 -5
  17. package/bin/balance/service.d.ts.map +1 -1
  18. package/bin/balance/service.js +77 -11
  19. package/bin/balance/service.js.map +1 -1
  20. package/bin/balance/types.d.ts +81 -1
  21. package/bin/balance/types.d.ts.map +1 -1
  22. package/bin/balance/utils.d.ts +5 -1
  23. package/bin/balance/utils.d.ts.map +1 -1
  24. package/bin/balance/utils.js +17 -0
  25. package/bin/balance/utils.js.map +1 -1
  26. package/bin/index.d.ts +8 -10
  27. package/bin/index.d.ts.map +1 -1
  28. package/bin/index.js +6 -7
  29. package/bin/index.js.map +1 -1
  30. package/bin/payment/helpers.d.ts +68 -0
  31. package/bin/payment/helpers.d.ts.map +1 -0
  32. package/bin/payment/helpers.js +148 -0
  33. package/bin/payment/helpers.js.map +1 -0
  34. package/bin/payment/index.d.ts +10 -28
  35. package/bin/payment/index.d.ts.map +1 -1
  36. package/bin/payment/index.js +9 -890
  37. package/bin/payment/index.js.map +1 -1
  38. package/bin/payment/providers.d.ts +25 -0
  39. package/bin/payment/providers.d.ts.map +1 -0
  40. package/bin/payment/providers.js +415 -0
  41. package/bin/payment/providers.js.map +1 -0
  42. package/bin/payment/routes.d.ts +29 -0
  43. package/bin/payment/routes.d.ts.map +1 -0
  44. package/bin/payment/routes.js +394 -0
  45. package/bin/payment/routes.js.map +1 -0
  46. package/bin/{billing → payment}/service.d.ts +99 -278
  47. package/bin/payment/service.d.ts.map +1 -0
  48. package/bin/payment/service.js +72 -0
  49. package/bin/payment/service.js.map +1 -0
  50. package/bin/payment/types.d.ts +11 -18
  51. package/bin/payment/types.d.ts.map +1 -1
  52. package/bin/usage/index.d.ts +3 -174
  53. package/bin/usage/index.d.ts.map +1 -1
  54. package/bin/usage/index.js +2 -117
  55. package/bin/usage/index.js.map +1 -1
  56. package/bin/usage/service.d.ts +353 -0
  57. package/bin/usage/service.d.ts.map +1 -0
  58. package/bin/usage/service.js +140 -0
  59. package/bin/usage/service.js.map +1 -0
  60. package/package.json +2 -2
  61. package/bin/billing/index.d.ts +0 -7
  62. package/bin/billing/index.d.ts.map +0 -1
  63. package/bin/billing/index.js +0 -6
  64. package/bin/billing/index.js.map +0 -1
  65. package/bin/billing/routes.d.ts +0 -14
  66. package/bin/billing/routes.d.ts.map +0 -1
  67. package/bin/billing/routes.js +0 -61
  68. package/bin/billing/routes.js.map +0 -1
  69. package/bin/billing/schema.d.ts +0 -582
  70. package/bin/billing/schema.d.ts.map +0 -1
  71. package/bin/billing/schema.js +0 -81
  72. package/bin/billing/schema.js.map +0 -1
  73. package/bin/billing/service.d.ts.map +0 -1
  74. package/bin/billing/service.js +0 -492
  75. package/bin/billing/service.js.map +0 -1
  76. package/bin/billing/types.d.ts +0 -226
  77. package/bin/billing/types.d.ts.map +0 -1
  78. package/bin/billing/types.js +0 -10
  79. package/bin/billing/types.js.map +0 -1
@@ -0,0 +1,353 @@
1
+ /**
2
+ * Downcity 官方 Usage 服务。
3
+ *
4
+ * 通过全局 hook 记录 service 调用事件。
5
+ * 兼容 Node.js 和 Cloudflare Workers(使用 Web Crypto API)。
6
+ */
7
+ import { InstallableService, type ServiceInstallContext } from "@downcity/city";
8
+ /**
9
+ * Usage 服务配置。
10
+ */
11
+ export interface UsageServiceOptions {
12
+ /**
13
+ * 是否记录失败的用户侧 service 调用。
14
+ *
15
+ * 默认只记录成功调用;开启后会通过 error hook 记录失败事件。
16
+ */
17
+ record_errors?: boolean;
18
+ }
19
+ /**
20
+ * Usage 事件表。
21
+ */
22
+ export declare const usageEvents: import("drizzle-orm/sqlite-core").SQLiteTableWithColumns<{
23
+ name: "service_usage_events";
24
+ schema: undefined;
25
+ columns: {
26
+ event_id: import("drizzle-orm/sqlite-core").SQLiteColumn<{
27
+ name: "event_id";
28
+ tableName: "service_usage_events";
29
+ dataType: "string";
30
+ columnType: "SQLiteText";
31
+ data: string;
32
+ driverParam: string;
33
+ notNull: true;
34
+ hasDefault: false;
35
+ isPrimaryKey: true;
36
+ isAutoincrement: false;
37
+ hasRuntimeDefault: false;
38
+ enumValues: [string, ...string[]];
39
+ baseColumn: never;
40
+ identity: undefined;
41
+ generated: undefined;
42
+ }, {}, {
43
+ length: number | undefined;
44
+ }>;
45
+ town_id: import("drizzle-orm/sqlite-core").SQLiteColumn<{
46
+ name: "town_id";
47
+ tableName: "service_usage_events";
48
+ dataType: "string";
49
+ columnType: "SQLiteText";
50
+ data: string;
51
+ driverParam: string;
52
+ notNull: true;
53
+ hasDefault: false;
54
+ isPrimaryKey: false;
55
+ isAutoincrement: false;
56
+ hasRuntimeDefault: false;
57
+ enumValues: [string, ...string[]];
58
+ baseColumn: never;
59
+ identity: undefined;
60
+ generated: undefined;
61
+ }, {}, {
62
+ length: number | undefined;
63
+ }>;
64
+ user_id: import("drizzle-orm/sqlite-core").SQLiteColumn<{
65
+ name: "user_id";
66
+ tableName: "service_usage_events";
67
+ dataType: "string";
68
+ columnType: "SQLiteText";
69
+ data: string;
70
+ driverParam: string;
71
+ notNull: true;
72
+ hasDefault: false;
73
+ isPrimaryKey: false;
74
+ isAutoincrement: false;
75
+ hasRuntimeDefault: false;
76
+ enumValues: [string, ...string[]];
77
+ baseColumn: never;
78
+ identity: undefined;
79
+ generated: undefined;
80
+ }, {}, {
81
+ length: number | undefined;
82
+ }>;
83
+ service: import("drizzle-orm/sqlite-core").SQLiteColumn<{
84
+ name: "service";
85
+ tableName: "service_usage_events";
86
+ dataType: "string";
87
+ columnType: "SQLiteText";
88
+ data: string;
89
+ driverParam: string;
90
+ notNull: true;
91
+ hasDefault: false;
92
+ isPrimaryKey: false;
93
+ isAutoincrement: false;
94
+ hasRuntimeDefault: false;
95
+ enumValues: [string, ...string[]];
96
+ baseColumn: never;
97
+ identity: undefined;
98
+ generated: undefined;
99
+ }, {}, {
100
+ length: number | undefined;
101
+ }>;
102
+ model_id: import("drizzle-orm/sqlite-core").SQLiteColumn<{
103
+ name: "model_id";
104
+ tableName: "service_usage_events";
105
+ dataType: "string";
106
+ columnType: "SQLiteText";
107
+ data: string;
108
+ driverParam: string;
109
+ notNull: true;
110
+ hasDefault: false;
111
+ isPrimaryKey: false;
112
+ isAutoincrement: false;
113
+ hasRuntimeDefault: false;
114
+ enumValues: [string, ...string[]];
115
+ baseColumn: never;
116
+ identity: undefined;
117
+ generated: undefined;
118
+ }, {}, {
119
+ length: number | undefined;
120
+ }>;
121
+ status: import("drizzle-orm/sqlite-core").SQLiteColumn<{
122
+ name: "status";
123
+ tableName: "service_usage_events";
124
+ dataType: "string";
125
+ columnType: "SQLiteText";
126
+ data: string;
127
+ driverParam: string;
128
+ notNull: true;
129
+ hasDefault: false;
130
+ isPrimaryKey: false;
131
+ isAutoincrement: false;
132
+ hasRuntimeDefault: false;
133
+ enumValues: [string, ...string[]];
134
+ baseColumn: never;
135
+ identity: undefined;
136
+ generated: undefined;
137
+ }, {}, {
138
+ length: number | undefined;
139
+ }>;
140
+ metadata_json: import("drizzle-orm/sqlite-core").SQLiteColumn<{
141
+ name: "metadata_json";
142
+ tableName: "service_usage_events";
143
+ dataType: "string";
144
+ columnType: "SQLiteText";
145
+ data: string;
146
+ driverParam: string;
147
+ notNull: true;
148
+ hasDefault: false;
149
+ isPrimaryKey: false;
150
+ isAutoincrement: false;
151
+ hasRuntimeDefault: false;
152
+ enumValues: [string, ...string[]];
153
+ baseColumn: never;
154
+ identity: undefined;
155
+ generated: undefined;
156
+ }, {}, {
157
+ length: number | undefined;
158
+ }>;
159
+ created_at: import("drizzle-orm/sqlite-core").SQLiteColumn<{
160
+ name: "created_at";
161
+ tableName: "service_usage_events";
162
+ dataType: "string";
163
+ columnType: "SQLiteText";
164
+ data: string;
165
+ driverParam: string;
166
+ notNull: true;
167
+ hasDefault: false;
168
+ isPrimaryKey: false;
169
+ isAutoincrement: false;
170
+ hasRuntimeDefault: false;
171
+ enumValues: [string, ...string[]];
172
+ baseColumn: never;
173
+ identity: undefined;
174
+ generated: undefined;
175
+ }, {}, {
176
+ length: number | undefined;
177
+ }>;
178
+ };
179
+ dialect: "sqlite";
180
+ }>;
181
+ /**
182
+ * Usage 服务实例。
183
+ */
184
+ export declare class UsageService extends InstallableService {
185
+ private readonly options;
186
+ readonly id = "usage";
187
+ readonly name = "Usage";
188
+ readonly version = "0.1.0";
189
+ readonly schema: {
190
+ events: import("drizzle-orm/sqlite-core").SQLiteTableWithColumns<{
191
+ name: "service_usage_events";
192
+ schema: undefined;
193
+ columns: {
194
+ event_id: import("drizzle-orm/sqlite-core").SQLiteColumn<{
195
+ name: "event_id";
196
+ tableName: "service_usage_events";
197
+ dataType: "string";
198
+ columnType: "SQLiteText";
199
+ data: string;
200
+ driverParam: string;
201
+ notNull: true;
202
+ hasDefault: false;
203
+ isPrimaryKey: true;
204
+ isAutoincrement: false;
205
+ hasRuntimeDefault: false;
206
+ enumValues: [string, ...string[]];
207
+ baseColumn: never;
208
+ identity: undefined;
209
+ generated: undefined;
210
+ }, {}, {
211
+ length: number | undefined;
212
+ }>;
213
+ town_id: import("drizzle-orm/sqlite-core").SQLiteColumn<{
214
+ name: "town_id";
215
+ tableName: "service_usage_events";
216
+ dataType: "string";
217
+ columnType: "SQLiteText";
218
+ data: string;
219
+ driverParam: string;
220
+ notNull: true;
221
+ hasDefault: false;
222
+ isPrimaryKey: false;
223
+ isAutoincrement: false;
224
+ hasRuntimeDefault: false;
225
+ enumValues: [string, ...string[]];
226
+ baseColumn: never;
227
+ identity: undefined;
228
+ generated: undefined;
229
+ }, {}, {
230
+ length: number | undefined;
231
+ }>;
232
+ user_id: import("drizzle-orm/sqlite-core").SQLiteColumn<{
233
+ name: "user_id";
234
+ tableName: "service_usage_events";
235
+ dataType: "string";
236
+ columnType: "SQLiteText";
237
+ data: string;
238
+ driverParam: string;
239
+ notNull: true;
240
+ hasDefault: false;
241
+ isPrimaryKey: false;
242
+ isAutoincrement: false;
243
+ hasRuntimeDefault: false;
244
+ enumValues: [string, ...string[]];
245
+ baseColumn: never;
246
+ identity: undefined;
247
+ generated: undefined;
248
+ }, {}, {
249
+ length: number | undefined;
250
+ }>;
251
+ service: import("drizzle-orm/sqlite-core").SQLiteColumn<{
252
+ name: "service";
253
+ tableName: "service_usage_events";
254
+ dataType: "string";
255
+ columnType: "SQLiteText";
256
+ data: string;
257
+ driverParam: string;
258
+ notNull: true;
259
+ hasDefault: false;
260
+ isPrimaryKey: false;
261
+ isAutoincrement: false;
262
+ hasRuntimeDefault: false;
263
+ enumValues: [string, ...string[]];
264
+ baseColumn: never;
265
+ identity: undefined;
266
+ generated: undefined;
267
+ }, {}, {
268
+ length: number | undefined;
269
+ }>;
270
+ model_id: import("drizzle-orm/sqlite-core").SQLiteColumn<{
271
+ name: "model_id";
272
+ tableName: "service_usage_events";
273
+ dataType: "string";
274
+ columnType: "SQLiteText";
275
+ data: string;
276
+ driverParam: string;
277
+ notNull: true;
278
+ hasDefault: false;
279
+ isPrimaryKey: false;
280
+ isAutoincrement: false;
281
+ hasRuntimeDefault: false;
282
+ enumValues: [string, ...string[]];
283
+ baseColumn: never;
284
+ identity: undefined;
285
+ generated: undefined;
286
+ }, {}, {
287
+ length: number | undefined;
288
+ }>;
289
+ status: import("drizzle-orm/sqlite-core").SQLiteColumn<{
290
+ name: "status";
291
+ tableName: "service_usage_events";
292
+ dataType: "string";
293
+ columnType: "SQLiteText";
294
+ data: string;
295
+ driverParam: string;
296
+ notNull: true;
297
+ hasDefault: false;
298
+ isPrimaryKey: false;
299
+ isAutoincrement: false;
300
+ hasRuntimeDefault: false;
301
+ enumValues: [string, ...string[]];
302
+ baseColumn: never;
303
+ identity: undefined;
304
+ generated: undefined;
305
+ }, {}, {
306
+ length: number | undefined;
307
+ }>;
308
+ metadata_json: import("drizzle-orm/sqlite-core").SQLiteColumn<{
309
+ name: "metadata_json";
310
+ tableName: "service_usage_events";
311
+ dataType: "string";
312
+ columnType: "SQLiteText";
313
+ data: string;
314
+ driverParam: string;
315
+ notNull: true;
316
+ hasDefault: false;
317
+ isPrimaryKey: false;
318
+ isAutoincrement: false;
319
+ hasRuntimeDefault: false;
320
+ enumValues: [string, ...string[]];
321
+ baseColumn: never;
322
+ identity: undefined;
323
+ generated: undefined;
324
+ }, {}, {
325
+ length: number | undefined;
326
+ }>;
327
+ created_at: import("drizzle-orm/sqlite-core").SQLiteColumn<{
328
+ name: "created_at";
329
+ tableName: "service_usage_events";
330
+ dataType: "string";
331
+ columnType: "SQLiteText";
332
+ data: string;
333
+ driverParam: string;
334
+ notNull: true;
335
+ hasDefault: false;
336
+ isPrimaryKey: false;
337
+ isAutoincrement: false;
338
+ hasRuntimeDefault: false;
339
+ enumValues: [string, ...string[]];
340
+ baseColumn: never;
341
+ identity: undefined;
342
+ generated: undefined;
343
+ }, {}, {
344
+ length: number | undefined;
345
+ }>;
346
+ };
347
+ dialect: "sqlite";
348
+ }>;
349
+ };
350
+ constructor(options?: UsageServiceOptions);
351
+ install(ctx: ServiceInstallContext): void;
352
+ }
353
+ //# sourceMappingURL=service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../src/usage/service.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EAAE,kBAAkB,EAAE,KAAK,qBAAqB,EAAgB,MAAM,gBAAgB,CAAC;AAE9F;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC;;;;OAIG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAED;;GAEG;AACH,eAAO,MAAM,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAStB,CAAC;AAEH;;GAEG;AACH,qBAAa,YAAa,SAAQ,kBAAkB;IAMtC,OAAO,CAAC,QAAQ,CAAC,OAAO;IALpC,QAAQ,CAAC,EAAE,WAAW;IACtB,QAAQ,CAAC,IAAI,WAAW;IACxB,QAAQ,CAAC,OAAO,WAAW;IAC3B,QAAQ,CAAC,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;MAA2B;gBAEb,OAAO,GAAE,mBAAwB;IAS9D,OAAO,CAAC,GAAG,EAAE,qBAAqB,GAAG,IAAI;CAiD1C"}
@@ -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.71",
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.80",
54
54
  "better-auth": "^1.6.12",
55
55
  "dodopayments": "^2.36.0",
56
56
  "drizzle-orm": "^0.45.2"
@@ -1,7 +0,0 @@
1
- /**
2
- * billing 服务子模块公共入口。
3
- */
4
- export { BillingService, billingService } from "./service.js";
5
- export { billingCharges, billingPricingRules } from "./schema.js";
6
- export type { BillingBalanceBridge, BillingChargeInput, BillingCharge, BillingChargeQuery, BillingChargeStatus, BillingPricingRule, BillingPricingRuleInput, BillingPricingRuleQuery, BillingPricingRuleStatus, BillingServiceOptions, } from "./types.js";
7
- //# sourceMappingURL=index.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/billing/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9D,OAAO,EAAE,cAAc,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAClE,YAAY,EACV,oBAAoB,EACpB,kBAAkB,EAClB,aAAa,EACb,kBAAkB,EAClB,mBAAmB,EACnB,kBAAkB,EAClB,uBAAuB,EACvB,uBAAuB,EACvB,wBAAwB,EACxB,qBAAqB,GACtB,MAAM,YAAY,CAAC"}
@@ -1,6 +0,0 @@
1
- /**
2
- * billing 服务子模块公共入口。
3
- */
4
- export { BillingService, billingService } from "./service.js";
5
- export { billingCharges, billingPricingRules } from "./schema.js";
6
- //# sourceMappingURL=index.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/billing/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9D,OAAO,EAAE,cAAc,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC"}
@@ -1,14 +0,0 @@
1
- /**
2
- * Billing 服务 HTTP 路由装配模块。
3
- *
4
- * 关键说明(中文)
5
- * - 管理端维护 pricing rule 和查看全量 charge
6
- * - 用户侧只查看自己的 charge
7
- */
8
- import type { ServiceInstallContext } from "@downcity/city";
9
- import type { BillingService } from "./service.js";
10
- /**
11
- * 注册 Billing 服务 HTTP 路由。
12
- */
13
- export declare function registerBillingRoutes(service: BillingService, ctx: ServiceInstallContext): void;
14
- //# sourceMappingURL=routes.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"routes.d.ts","sourceRoot":"","sources":["../../src/billing/routes.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,qBAAqB,EAAuB,MAAM,gBAAgB,CAAC;AACjF,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAGnD;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,cAAc,EAAE,GAAG,EAAE,qBAAqB,GAAG,IAAI,CA2C/F"}
@@ -1,61 +0,0 @@
1
- /**
2
- * Billing 服务 HTTP 路由装配模块。
3
- *
4
- * 关键说明(中文)
5
- * - 管理端维护 pricing rule 和查看全量 charge
6
- * - 用户侧只查看自己的 charge
7
- */
8
- /**
9
- * 注册 Billing 服务 HTTP 路由。
10
- */
11
- export function registerBillingRoutes(service, ctx) {
12
- ctx.route({
13
- method: "GET",
14
- path: "/pricing",
15
- auth: ["admin"],
16
- handler: async (c) => {
17
- const input = await c.json();
18
- return c.jsonResponse({ items: await service.listPricingRules(input) });
19
- },
20
- });
21
- ctx.route({
22
- method: "POST",
23
- path: "/pricing/upsert",
24
- auth: ["admin"],
25
- handler: async (c) => c.jsonResponse(await service.upsertPricingRule(await c.json())),
26
- });
27
- ctx.route({
28
- method: "GET",
29
- path: "/charges",
30
- auth: ["admin"],
31
- handler: async (c) => {
32
- const input = await c.json();
33
- return c.jsonResponse({ items: await service.listCharges(input) });
34
- },
35
- });
36
- ctx.route({
37
- method: "GET",
38
- path: "/me",
39
- auth: ["user"],
40
- handler: async (c) => {
41
- const input = await c.json();
42
- return c.jsonResponse({
43
- items: await service.listCharges({
44
- ...input,
45
- user_id: readUserId(c),
46
- town_id: c.town?.town_id,
47
- }),
48
- });
49
- },
50
- });
51
- }
52
- /**
53
- * 读取当前 user_id。
54
- */
55
- function readUserId(ctx) {
56
- const user_id = String(ctx.user?.user_id ?? "").trim();
57
- if (!user_id)
58
- throw new TypeError("user_id is required");
59
- return user_id;
60
- }
61
- //# sourceMappingURL=routes.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"routes.js","sourceRoot":"","sources":["../../src/billing/routes.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAMH;;GAEG;AACH,MAAM,UAAU,qBAAqB,CAAC,OAAuB,EAAE,GAA0B;IACvF,GAAG,CAAC,KAAK,CAAC;QACR,MAAM,EAAE,KAAK;QACb,IAAI,EAAE,UAAU;QAChB,IAAI,EAAE,CAAC,OAAO,CAAC;QACf,OAAO,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE;YACnB,MAAM,KAAK,GAAG,MAAM,CAAC,CAAC,IAAI,EAA+B,CAAC;YAC1D,OAAO,CAAC,CAAC,YAAY,CAAC,EAAE,KAAK,EAAE,MAAM,OAAO,CAAC,gBAAgB,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAC1E,CAAC;KACF,CAAC,CAAC;IAEH,GAAG,CAAC,KAAK,CAAC;QACR,MAAM,EAAE,MAAM;QACd,IAAI,EAAE,iBAAiB;QACvB,IAAI,EAAE,CAAC,OAAO,CAAC;QACf,OAAO,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,YAAY,CAAC,MAAM,OAAO,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAAC,IAAI,EAA2B,CAAC,CAAC;KAC/G,CAAC,CAAC;IAEH,GAAG,CAAC,KAAK,CAAC;QACR,MAAM,EAAE,KAAK;QACb,IAAI,EAAE,UAAU;QAChB,IAAI,EAAE,CAAC,OAAO,CAAC;QACf,OAAO,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE;YACnB,MAAM,KAAK,GAAG,MAAM,CAAC,CAAC,IAAI,EAAsB,CAAC;YACjD,OAAO,CAAC,CAAC,YAAY,CAAC,EAAE,KAAK,EAAE,MAAM,OAAO,CAAC,WAAW,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QACrE,CAAC;KACF,CAAC,CAAC;IAEH,GAAG,CAAC,KAAK,CAAC;QACR,MAAM,EAAE,KAAK;QACb,IAAI,EAAE,KAAK;QACX,IAAI,EAAE,CAAC,MAAM,CAAC;QACd,OAAO,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE;YACnB,MAAM,KAAK,GAAG,MAAM,CAAC,CAAC,IAAI,EAAsB,CAAC;YACjD,OAAO,CAAC,CAAC,YAAY,CAAC;gBACpB,KAAK,EAAE,MAAM,OAAO,CAAC,WAAW,CAAC;oBAC/B,GAAG,KAAK;oBACR,OAAO,EAAE,UAAU,CAAC,CAAC,CAAC;oBACtB,OAAO,EAAE,CAAC,CAAC,IAAI,EAAE,OAAO;iBACzB,CAAC;aACH,CAAC,CAAC;QACL,CAAC;KACF,CAAC,CAAC;AACL,CAAC;AAED;;GAEG;AACH,SAAS,UAAU,CAAC,GAAwB;IAC1C,MAAM,OAAO,GAAG,MAAM,CAAC,GAAG,CAAC,IAAI,EAAE,OAAO,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IACvD,IAAI,CAAC,OAAO;QAAE,MAAM,IAAI,SAAS,CAAC,qBAAqB,CAAC,CAAC;IACzD,OAAO,OAAO,CAAC;AACjB,CAAC"}