@downcity/city 0.2.92 → 0.2.94
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/bin/federation/federation-router.d.ts.map +1 -1
- package/bin/federation/federation-router.js +41 -24
- package/bin/federation/federation-router.js.map +1 -1
- package/bin/index.d.ts +2 -0
- package/bin/index.d.ts.map +1 -1
- package/bin/index.js +1 -0
- package/bin/index.js.map +1 -1
- package/bin/service/ai/ai-service.d.ts +1 -1
- package/bin/service/ai/ai-service.d.ts.map +1 -1
- package/bin/service/ai/ai-service.js +31 -12
- package/bin/service/ai/ai-service.js.map +1 -1
- package/bin/service/ai/job-types.d.ts +4 -28
- package/bin/service/ai/job-types.d.ts.map +1 -1
- package/bin/service/ai/job-types.js +2 -2
- package/bin/service/{ai → async-job}/schema.d.ts +139 -31
- package/bin/service/async-job/schema.d.ts.map +1 -0
- package/bin/service/{ai → async-job}/schema.js +26 -14
- package/bin/service/async-job/schema.js.map +1 -0
- package/bin/service/installable-service.d.ts +39 -8
- package/bin/service/installable-service.d.ts.map +1 -1
- package/bin/service/installable-service.js +19 -2
- package/bin/service/installable-service.js.map +1 -1
- package/bin/service/service.d.ts +36 -0
- package/bin/service/service.d.ts.map +1 -1
- package/bin/service/service.js +30 -0
- package/bin/service/service.js.map +1 -1
- package/bin/types/AsyncJob.d.ts +42 -0
- package/bin/types/AsyncJob.d.ts.map +1 -0
- package/bin/types/AsyncJob.js +8 -0
- package/bin/types/AsyncJob.js.map +1 -0
- package/package.json +2 -2
- package/bin/service/ai/schema.d.ts.map +0 -1
- package/bin/service/ai/schema.js.map +0 -1
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* 通用异步任务数据库 schema 模块。
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
4
|
+
* async_jobs 是 City 的统一异步任务表,用于图片生成、视频生成、
|
|
5
|
+
* 文件处理等需要跨请求恢复或轮询的任务。
|
|
6
6
|
*/
|
|
7
7
|
/**
|
|
8
|
-
* 默认 SQLite
|
|
8
|
+
* 默认 SQLite 异步任务表。
|
|
9
9
|
*/
|
|
10
|
-
export declare const
|
|
11
|
-
name: "
|
|
10
|
+
export declare const sqliteAsyncJobs: import("drizzle-orm/sqlite-core").SQLiteTableWithColumns<{
|
|
11
|
+
name: "async_jobs";
|
|
12
12
|
schema: undefined;
|
|
13
13
|
columns: {
|
|
14
14
|
job_id: import("drizzle-orm/sqlite-core").SQLiteColumn<{
|
|
15
15
|
name: "job_id";
|
|
16
|
-
tableName: "
|
|
16
|
+
tableName: "async_jobs";
|
|
17
17
|
dataType: "string";
|
|
18
18
|
columnType: "SQLiteText";
|
|
19
19
|
data: string;
|
|
@@ -30,9 +30,28 @@ export declare const sqliteAIImageJobs: import("drizzle-orm/sqlite-core").SQLite
|
|
|
30
30
|
}, {}, {
|
|
31
31
|
length: number | undefined;
|
|
32
32
|
}>;
|
|
33
|
+
job_type: import("drizzle-orm/sqlite-core").SQLiteColumn<{
|
|
34
|
+
name: "job_type";
|
|
35
|
+
tableName: "async_jobs";
|
|
36
|
+
dataType: "string";
|
|
37
|
+
columnType: "SQLiteText";
|
|
38
|
+
data: string;
|
|
39
|
+
driverParam: string;
|
|
40
|
+
notNull: true;
|
|
41
|
+
hasDefault: false;
|
|
42
|
+
isPrimaryKey: false;
|
|
43
|
+
isAutoincrement: false;
|
|
44
|
+
hasRuntimeDefault: false;
|
|
45
|
+
enumValues: [string, ...string[]];
|
|
46
|
+
baseColumn: never;
|
|
47
|
+
identity: undefined;
|
|
48
|
+
generated: undefined;
|
|
49
|
+
}, {}, {
|
|
50
|
+
length: number | undefined;
|
|
51
|
+
}>;
|
|
33
52
|
status: import("drizzle-orm/sqlite-core").SQLiteColumn<{
|
|
34
53
|
name: "status";
|
|
35
|
-
tableName: "
|
|
54
|
+
tableName: "async_jobs";
|
|
36
55
|
dataType: "string";
|
|
37
56
|
columnType: "SQLiteText";
|
|
38
57
|
data: string;
|
|
@@ -51,7 +70,7 @@ export declare const sqliteAIImageJobs: import("drizzle-orm/sqlite-core").SQLite
|
|
|
51
70
|
}>;
|
|
52
71
|
input_json: import("drizzle-orm/sqlite-core").SQLiteColumn<{
|
|
53
72
|
name: "input_json";
|
|
54
|
-
tableName: "
|
|
73
|
+
tableName: "async_jobs";
|
|
55
74
|
dataType: "string";
|
|
56
75
|
columnType: "SQLiteText";
|
|
57
76
|
data: string;
|
|
@@ -68,9 +87,28 @@ export declare const sqliteAIImageJobs: import("drizzle-orm/sqlite-core").SQLite
|
|
|
68
87
|
}, {}, {
|
|
69
88
|
length: number | undefined;
|
|
70
89
|
}>;
|
|
90
|
+
state_json: import("drizzle-orm/sqlite-core").SQLiteColumn<{
|
|
91
|
+
name: "state_json";
|
|
92
|
+
tableName: "async_jobs";
|
|
93
|
+
dataType: "string";
|
|
94
|
+
columnType: "SQLiteText";
|
|
95
|
+
data: string;
|
|
96
|
+
driverParam: string;
|
|
97
|
+
notNull: false;
|
|
98
|
+
hasDefault: false;
|
|
99
|
+
isPrimaryKey: false;
|
|
100
|
+
isAutoincrement: false;
|
|
101
|
+
hasRuntimeDefault: false;
|
|
102
|
+
enumValues: [string, ...string[]];
|
|
103
|
+
baseColumn: never;
|
|
104
|
+
identity: undefined;
|
|
105
|
+
generated: undefined;
|
|
106
|
+
}, {}, {
|
|
107
|
+
length: number | undefined;
|
|
108
|
+
}>;
|
|
71
109
|
result_json: import("drizzle-orm/sqlite-core").SQLiteColumn<{
|
|
72
110
|
name: "result_json";
|
|
73
|
-
tableName: "
|
|
111
|
+
tableName: "async_jobs";
|
|
74
112
|
dataType: "string";
|
|
75
113
|
columnType: "SQLiteText";
|
|
76
114
|
data: string;
|
|
@@ -89,7 +127,7 @@ export declare const sqliteAIImageJobs: import("drizzle-orm/sqlite-core").SQLite
|
|
|
89
127
|
}>;
|
|
90
128
|
error: import("drizzle-orm/sqlite-core").SQLiteColumn<{
|
|
91
129
|
name: "error";
|
|
92
|
-
tableName: "
|
|
130
|
+
tableName: "async_jobs";
|
|
93
131
|
dataType: "string";
|
|
94
132
|
columnType: "SQLiteText";
|
|
95
133
|
data: string;
|
|
@@ -108,7 +146,7 @@ export declare const sqliteAIImageJobs: import("drizzle-orm/sqlite-core").SQLite
|
|
|
108
146
|
}>;
|
|
109
147
|
message: import("drizzle-orm/sqlite-core").SQLiteColumn<{
|
|
110
148
|
name: "message";
|
|
111
|
-
tableName: "
|
|
149
|
+
tableName: "async_jobs";
|
|
112
150
|
dataType: "string";
|
|
113
151
|
columnType: "SQLiteText";
|
|
114
152
|
data: string;
|
|
@@ -127,7 +165,7 @@ export declare const sqliteAIImageJobs: import("drizzle-orm/sqlite-core").SQLite
|
|
|
127
165
|
}>;
|
|
128
166
|
city_id: import("drizzle-orm/sqlite-core").SQLiteColumn<{
|
|
129
167
|
name: "city_id";
|
|
130
|
-
tableName: "
|
|
168
|
+
tableName: "async_jobs";
|
|
131
169
|
dataType: "string";
|
|
132
170
|
columnType: "SQLiteText";
|
|
133
171
|
data: string;
|
|
@@ -146,7 +184,26 @@ export declare const sqliteAIImageJobs: import("drizzle-orm/sqlite-core").SQLite
|
|
|
146
184
|
}>;
|
|
147
185
|
user_id: import("drizzle-orm/sqlite-core").SQLiteColumn<{
|
|
148
186
|
name: "user_id";
|
|
149
|
-
tableName: "
|
|
187
|
+
tableName: "async_jobs";
|
|
188
|
+
dataType: "string";
|
|
189
|
+
columnType: "SQLiteText";
|
|
190
|
+
data: string;
|
|
191
|
+
driverParam: string;
|
|
192
|
+
notNull: false;
|
|
193
|
+
hasDefault: false;
|
|
194
|
+
isPrimaryKey: false;
|
|
195
|
+
isAutoincrement: false;
|
|
196
|
+
hasRuntimeDefault: false;
|
|
197
|
+
enumValues: [string, ...string[]];
|
|
198
|
+
baseColumn: never;
|
|
199
|
+
identity: undefined;
|
|
200
|
+
generated: undefined;
|
|
201
|
+
}, {}, {
|
|
202
|
+
length: number | undefined;
|
|
203
|
+
}>;
|
|
204
|
+
service_id: import("drizzle-orm/sqlite-core").SQLiteColumn<{
|
|
205
|
+
name: "service_id";
|
|
206
|
+
tableName: "async_jobs";
|
|
150
207
|
dataType: "string";
|
|
151
208
|
columnType: "SQLiteText";
|
|
152
209
|
data: string;
|
|
@@ -165,7 +222,7 @@ export declare const sqliteAIImageJobs: import("drizzle-orm/sqlite-core").SQLite
|
|
|
165
222
|
}>;
|
|
166
223
|
model_id: import("drizzle-orm/sqlite-core").SQLiteColumn<{
|
|
167
224
|
name: "model_id";
|
|
168
|
-
tableName: "
|
|
225
|
+
tableName: "async_jobs";
|
|
169
226
|
dataType: "string";
|
|
170
227
|
columnType: "SQLiteText";
|
|
171
228
|
data: string;
|
|
@@ -184,7 +241,7 @@ export declare const sqliteAIImageJobs: import("drizzle-orm/sqlite-core").SQLite
|
|
|
184
241
|
}>;
|
|
185
242
|
created_at: import("drizzle-orm/sqlite-core").SQLiteColumn<{
|
|
186
243
|
name: "created_at";
|
|
187
|
-
tableName: "
|
|
244
|
+
tableName: "async_jobs";
|
|
188
245
|
dataType: "string";
|
|
189
246
|
columnType: "SQLiteText";
|
|
190
247
|
data: string;
|
|
@@ -203,7 +260,7 @@ export declare const sqliteAIImageJobs: import("drizzle-orm/sqlite-core").SQLite
|
|
|
203
260
|
}>;
|
|
204
261
|
updated_at: import("drizzle-orm/sqlite-core").SQLiteColumn<{
|
|
205
262
|
name: "updated_at";
|
|
206
|
-
tableName: "
|
|
263
|
+
tableName: "async_jobs";
|
|
207
264
|
dataType: "string";
|
|
208
265
|
columnType: "SQLiteText";
|
|
209
266
|
data: string;
|
|
@@ -224,15 +281,15 @@ export declare const sqliteAIImageJobs: import("drizzle-orm/sqlite-core").SQLite
|
|
|
224
281
|
dialect: "sqlite";
|
|
225
282
|
}>;
|
|
226
283
|
/**
|
|
227
|
-
* 默认 Postgres
|
|
284
|
+
* 默认 Postgres 异步任务表。
|
|
228
285
|
*/
|
|
229
|
-
export declare const
|
|
230
|
-
name: "
|
|
286
|
+
export declare const pgAsyncJobs: import("drizzle-orm/pg-core").PgTableWithColumns<{
|
|
287
|
+
name: "async_jobs";
|
|
231
288
|
schema: undefined;
|
|
232
289
|
columns: {
|
|
233
290
|
job_id: import("drizzle-orm/pg-core").PgColumn<{
|
|
234
291
|
name: "job_id";
|
|
235
|
-
tableName: "
|
|
292
|
+
tableName: "async_jobs";
|
|
236
293
|
dataType: "string";
|
|
237
294
|
columnType: "PgText";
|
|
238
295
|
data: string;
|
|
@@ -247,9 +304,26 @@ export declare const pgAIImageJobs: import("drizzle-orm/pg-core").PgTableWithCol
|
|
|
247
304
|
identity: undefined;
|
|
248
305
|
generated: undefined;
|
|
249
306
|
}, {}, {}>;
|
|
307
|
+
job_type: import("drizzle-orm/pg-core").PgColumn<{
|
|
308
|
+
name: "job_type";
|
|
309
|
+
tableName: "async_jobs";
|
|
310
|
+
dataType: "string";
|
|
311
|
+
columnType: "PgText";
|
|
312
|
+
data: string;
|
|
313
|
+
driverParam: string;
|
|
314
|
+
notNull: true;
|
|
315
|
+
hasDefault: false;
|
|
316
|
+
isPrimaryKey: false;
|
|
317
|
+
isAutoincrement: false;
|
|
318
|
+
hasRuntimeDefault: false;
|
|
319
|
+
enumValues: [string, ...string[]];
|
|
320
|
+
baseColumn: never;
|
|
321
|
+
identity: undefined;
|
|
322
|
+
generated: undefined;
|
|
323
|
+
}, {}, {}>;
|
|
250
324
|
status: import("drizzle-orm/pg-core").PgColumn<{
|
|
251
325
|
name: "status";
|
|
252
|
-
tableName: "
|
|
326
|
+
tableName: "async_jobs";
|
|
253
327
|
dataType: "string";
|
|
254
328
|
columnType: "PgText";
|
|
255
329
|
data: string;
|
|
@@ -266,7 +340,7 @@ export declare const pgAIImageJobs: import("drizzle-orm/pg-core").PgTableWithCol
|
|
|
266
340
|
}, {}, {}>;
|
|
267
341
|
input_json: import("drizzle-orm/pg-core").PgColumn<{
|
|
268
342
|
name: "input_json";
|
|
269
|
-
tableName: "
|
|
343
|
+
tableName: "async_jobs";
|
|
270
344
|
dataType: "string";
|
|
271
345
|
columnType: "PgText";
|
|
272
346
|
data: string;
|
|
@@ -281,9 +355,26 @@ export declare const pgAIImageJobs: import("drizzle-orm/pg-core").PgTableWithCol
|
|
|
281
355
|
identity: undefined;
|
|
282
356
|
generated: undefined;
|
|
283
357
|
}, {}, {}>;
|
|
358
|
+
state_json: import("drizzle-orm/pg-core").PgColumn<{
|
|
359
|
+
name: "state_json";
|
|
360
|
+
tableName: "async_jobs";
|
|
361
|
+
dataType: "string";
|
|
362
|
+
columnType: "PgText";
|
|
363
|
+
data: string;
|
|
364
|
+
driverParam: string;
|
|
365
|
+
notNull: false;
|
|
366
|
+
hasDefault: false;
|
|
367
|
+
isPrimaryKey: false;
|
|
368
|
+
isAutoincrement: false;
|
|
369
|
+
hasRuntimeDefault: false;
|
|
370
|
+
enumValues: [string, ...string[]];
|
|
371
|
+
baseColumn: never;
|
|
372
|
+
identity: undefined;
|
|
373
|
+
generated: undefined;
|
|
374
|
+
}, {}, {}>;
|
|
284
375
|
result_json: import("drizzle-orm/pg-core").PgColumn<{
|
|
285
376
|
name: "result_json";
|
|
286
|
-
tableName: "
|
|
377
|
+
tableName: "async_jobs";
|
|
287
378
|
dataType: "string";
|
|
288
379
|
columnType: "PgText";
|
|
289
380
|
data: string;
|
|
@@ -300,7 +391,7 @@ export declare const pgAIImageJobs: import("drizzle-orm/pg-core").PgTableWithCol
|
|
|
300
391
|
}, {}, {}>;
|
|
301
392
|
error: import("drizzle-orm/pg-core").PgColumn<{
|
|
302
393
|
name: "error";
|
|
303
|
-
tableName: "
|
|
394
|
+
tableName: "async_jobs";
|
|
304
395
|
dataType: "string";
|
|
305
396
|
columnType: "PgText";
|
|
306
397
|
data: string;
|
|
@@ -317,7 +408,7 @@ export declare const pgAIImageJobs: import("drizzle-orm/pg-core").PgTableWithCol
|
|
|
317
408
|
}, {}, {}>;
|
|
318
409
|
message: import("drizzle-orm/pg-core").PgColumn<{
|
|
319
410
|
name: "message";
|
|
320
|
-
tableName: "
|
|
411
|
+
tableName: "async_jobs";
|
|
321
412
|
dataType: "string";
|
|
322
413
|
columnType: "PgText";
|
|
323
414
|
data: string;
|
|
@@ -334,7 +425,7 @@ export declare const pgAIImageJobs: import("drizzle-orm/pg-core").PgTableWithCol
|
|
|
334
425
|
}, {}, {}>;
|
|
335
426
|
city_id: import("drizzle-orm/pg-core").PgColumn<{
|
|
336
427
|
name: "city_id";
|
|
337
|
-
tableName: "
|
|
428
|
+
tableName: "async_jobs";
|
|
338
429
|
dataType: "string";
|
|
339
430
|
columnType: "PgText";
|
|
340
431
|
data: string;
|
|
@@ -351,7 +442,24 @@ export declare const pgAIImageJobs: import("drizzle-orm/pg-core").PgTableWithCol
|
|
|
351
442
|
}, {}, {}>;
|
|
352
443
|
user_id: import("drizzle-orm/pg-core").PgColumn<{
|
|
353
444
|
name: "user_id";
|
|
354
|
-
tableName: "
|
|
445
|
+
tableName: "async_jobs";
|
|
446
|
+
dataType: "string";
|
|
447
|
+
columnType: "PgText";
|
|
448
|
+
data: string;
|
|
449
|
+
driverParam: string;
|
|
450
|
+
notNull: false;
|
|
451
|
+
hasDefault: false;
|
|
452
|
+
isPrimaryKey: false;
|
|
453
|
+
isAutoincrement: false;
|
|
454
|
+
hasRuntimeDefault: false;
|
|
455
|
+
enumValues: [string, ...string[]];
|
|
456
|
+
baseColumn: never;
|
|
457
|
+
identity: undefined;
|
|
458
|
+
generated: undefined;
|
|
459
|
+
}, {}, {}>;
|
|
460
|
+
service_id: import("drizzle-orm/pg-core").PgColumn<{
|
|
461
|
+
name: "service_id";
|
|
462
|
+
tableName: "async_jobs";
|
|
355
463
|
dataType: "string";
|
|
356
464
|
columnType: "PgText";
|
|
357
465
|
data: string;
|
|
@@ -368,7 +476,7 @@ export declare const pgAIImageJobs: import("drizzle-orm/pg-core").PgTableWithCol
|
|
|
368
476
|
}, {}, {}>;
|
|
369
477
|
model_id: import("drizzle-orm/pg-core").PgColumn<{
|
|
370
478
|
name: "model_id";
|
|
371
|
-
tableName: "
|
|
479
|
+
tableName: "async_jobs";
|
|
372
480
|
dataType: "string";
|
|
373
481
|
columnType: "PgText";
|
|
374
482
|
data: string;
|
|
@@ -385,7 +493,7 @@ export declare const pgAIImageJobs: import("drizzle-orm/pg-core").PgTableWithCol
|
|
|
385
493
|
}, {}, {}>;
|
|
386
494
|
created_at: import("drizzle-orm/pg-core").PgColumn<{
|
|
387
495
|
name: "created_at";
|
|
388
|
-
tableName: "
|
|
496
|
+
tableName: "async_jobs";
|
|
389
497
|
dataType: "string";
|
|
390
498
|
columnType: "PgText";
|
|
391
499
|
data: string;
|
|
@@ -402,7 +510,7 @@ export declare const pgAIImageJobs: import("drizzle-orm/pg-core").PgTableWithCol
|
|
|
402
510
|
}, {}, {}>;
|
|
403
511
|
updated_at: import("drizzle-orm/pg-core").PgColumn<{
|
|
404
512
|
name: "updated_at";
|
|
405
|
-
tableName: "
|
|
513
|
+
tableName: "async_jobs";
|
|
406
514
|
dataType: "string";
|
|
407
515
|
columnType: "PgText";
|
|
408
516
|
data: string;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../../src/service/async-job/schema.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAOH;;GAEG;AACH,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA6B1B,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA6BtB,CAAC"}
|
|
@@ -1,23 +1,27 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* 通用异步任务数据库 schema 模块。
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
4
|
+
* async_jobs 是 City 的统一异步任务表,用于图片生成、视频生成、
|
|
5
|
+
* 文件处理等需要跨请求恢复或轮询的任务。
|
|
6
6
|
*/
|
|
7
7
|
import { pgTable, text as pgText } from "drizzle-orm/pg-core";
|
|
8
8
|
import { sqliteTable, text as sqliteText } from "drizzle-orm/sqlite-core";
|
|
9
|
-
const
|
|
9
|
+
const DEFAULT_ASYNC_JOBS_TABLE = "async_jobs";
|
|
10
10
|
/**
|
|
11
|
-
* 默认 SQLite
|
|
11
|
+
* 默认 SQLite 异步任务表。
|
|
12
12
|
*/
|
|
13
|
-
export const
|
|
14
|
-
/**
|
|
13
|
+
export const sqliteAsyncJobs = sqliteTable(DEFAULT_ASYNC_JOBS_TABLE, {
|
|
14
|
+
/** City 内部生成的异步任务 ID。 */
|
|
15
15
|
job_id: sqliteText("job_id").primaryKey(),
|
|
16
|
+
/** 任务类型,例如 `ai.image.generate`。 */
|
|
17
|
+
job_type: sqliteText("job_type").notNull(),
|
|
16
18
|
/** 任务状态:queued / running / succeeded / failed。 */
|
|
17
19
|
status: sqliteText("status").notNull(),
|
|
18
|
-
/**
|
|
20
|
+
/** 原始任务输入,JSON 字符串。 */
|
|
19
21
|
input_json: sqliteText("input_json").notNull(),
|
|
20
|
-
/**
|
|
22
|
+
/** 可恢复任务中间状态,JSON 字符串。 */
|
|
23
|
+
state_json: sqliteText("state_json"),
|
|
24
|
+
/** 成功后的业务结果,JSON 字符串。 */
|
|
21
25
|
result_json: sqliteText("result_json"),
|
|
22
26
|
/** 失败时给客户端展示的错误消息。 */
|
|
23
27
|
error: sqliteText("error"),
|
|
@@ -27,6 +31,8 @@ export const sqliteAIImageJobs = sqliteTable(DEFAULT_IMAGE_JOBS_TABLE, {
|
|
|
27
31
|
city_id: sqliteText("city_id"),
|
|
28
32
|
/** 当前终端用户 ID。 */
|
|
29
33
|
user_id: sqliteText("user_id"),
|
|
34
|
+
/** 创建该任务的 Service ID。 */
|
|
35
|
+
service_id: sqliteText("service_id"),
|
|
30
36
|
/** 本次任务解析到的模型 ID。 */
|
|
31
37
|
model_id: sqliteText("model_id"),
|
|
32
38
|
/** 创建时间。 */
|
|
@@ -35,16 +41,20 @@ export const sqliteAIImageJobs = sqliteTable(DEFAULT_IMAGE_JOBS_TABLE, {
|
|
|
35
41
|
updated_at: sqliteText("updated_at").notNull(),
|
|
36
42
|
});
|
|
37
43
|
/**
|
|
38
|
-
* 默认 Postgres
|
|
44
|
+
* 默认 Postgres 异步任务表。
|
|
39
45
|
*/
|
|
40
|
-
export const
|
|
41
|
-
/**
|
|
46
|
+
export const pgAsyncJobs = pgTable(DEFAULT_ASYNC_JOBS_TABLE, {
|
|
47
|
+
/** City 内部生成的异步任务 ID。 */
|
|
42
48
|
job_id: pgText("job_id").primaryKey(),
|
|
49
|
+
/** 任务类型,例如 `ai.image.generate`。 */
|
|
50
|
+
job_type: pgText("job_type").notNull(),
|
|
43
51
|
/** 任务状态:queued / running / succeeded / failed。 */
|
|
44
52
|
status: pgText("status").notNull(),
|
|
45
|
-
/**
|
|
53
|
+
/** 原始任务输入,JSON 字符串。 */
|
|
46
54
|
input_json: pgText("input_json").notNull(),
|
|
47
|
-
/**
|
|
55
|
+
/** 可恢复任务中间状态,JSON 字符串。 */
|
|
56
|
+
state_json: pgText("state_json"),
|
|
57
|
+
/** 成功后的业务结果,JSON 字符串。 */
|
|
48
58
|
result_json: pgText("result_json"),
|
|
49
59
|
/** 失败时给客户端展示的错误消息。 */
|
|
50
60
|
error: pgText("error"),
|
|
@@ -54,6 +64,8 @@ export const pgAIImageJobs = pgTable(DEFAULT_IMAGE_JOBS_TABLE, {
|
|
|
54
64
|
city_id: pgText("city_id"),
|
|
55
65
|
/** 当前终端用户 ID。 */
|
|
56
66
|
user_id: pgText("user_id"),
|
|
67
|
+
/** 创建该任务的 Service ID。 */
|
|
68
|
+
service_id: pgText("service_id"),
|
|
57
69
|
/** 本次任务解析到的模型 ID。 */
|
|
58
70
|
model_id: pgText("model_id"),
|
|
59
71
|
/** 创建时间。 */
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../../../src/service/async-job/schema.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,OAAO,EAAE,IAAI,IAAI,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAC9D,OAAO,EAAE,WAAW,EAAE,IAAI,IAAI,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAE1E,MAAM,wBAAwB,GAAG,YAAY,CAAC;AAE9C;;GAEG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,WAAW,CAAC,wBAAwB,EAAE;IACnE,yBAAyB;IACzB,MAAM,EAAE,UAAU,CAAC,QAAQ,CAAC,CAAC,UAAU,EAAE;IACzC,mCAAmC;IACnC,QAAQ,EAAE,UAAU,CAAC,UAAU,CAAC,CAAC,OAAO,EAAE;IAC1C,kDAAkD;IAClD,MAAM,EAAE,UAAU,CAAC,QAAQ,CAAC,CAAC,OAAO,EAAE;IACtC,uBAAuB;IACvB,UAAU,EAAE,UAAU,CAAC,YAAY,CAAC,CAAC,OAAO,EAAE;IAC9C,0BAA0B;IAC1B,UAAU,EAAE,UAAU,CAAC,YAAY,CAAC;IACpC,yBAAyB;IACzB,WAAW,EAAE,UAAU,CAAC,aAAa,CAAC;IACtC,sBAAsB;IACtB,KAAK,EAAE,UAAU,CAAC,OAAO,CAAC;IAC1B,2BAA2B;IAC3B,OAAO,EAAE,UAAU,CAAC,SAAS,CAAC;IAC9B,iCAAiC;IACjC,OAAO,EAAE,UAAU,CAAC,SAAS,CAAC;IAC9B,iBAAiB;IACjB,OAAO,EAAE,UAAU,CAAC,SAAS,CAAC;IAC9B,yBAAyB;IACzB,UAAU,EAAE,UAAU,CAAC,YAAY,CAAC;IACpC,qBAAqB;IACrB,QAAQ,EAAE,UAAU,CAAC,UAAU,CAAC;IAChC,YAAY;IACZ,UAAU,EAAE,UAAU,CAAC,YAAY,CAAC,CAAC,OAAO,EAAE;IAC9C,YAAY;IACZ,UAAU,EAAE,UAAU,CAAC,YAAY,CAAC,CAAC,OAAO,EAAE;CAC/C,CAAC,CAAC;AAEH;;GAEG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,OAAO,CAAC,wBAAwB,EAAE;IAC3D,yBAAyB;IACzB,MAAM,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC,UAAU,EAAE;IACrC,mCAAmC;IACnC,QAAQ,EAAE,MAAM,CAAC,UAAU,CAAC,CAAC,OAAO,EAAE;IACtC,kDAAkD;IAClD,MAAM,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC,OAAO,EAAE;IAClC,uBAAuB;IACvB,UAAU,EAAE,MAAM,CAAC,YAAY,CAAC,CAAC,OAAO,EAAE;IAC1C,0BAA0B;IAC1B,UAAU,EAAE,MAAM,CAAC,YAAY,CAAC;IAChC,yBAAyB;IACzB,WAAW,EAAE,MAAM,CAAC,aAAa,CAAC;IAClC,sBAAsB;IACtB,KAAK,EAAE,MAAM,CAAC,OAAO,CAAC;IACtB,2BAA2B;IAC3B,OAAO,EAAE,MAAM,CAAC,SAAS,CAAC;IAC1B,iCAAiC;IACjC,OAAO,EAAE,MAAM,CAAC,SAAS,CAAC;IAC1B,iBAAiB;IACjB,OAAO,EAAE,MAAM,CAAC,SAAS,CAAC;IAC1B,yBAAyB;IACzB,UAAU,EAAE,MAAM,CAAC,YAAY,CAAC;IAChC,qBAAqB;IACrB,QAAQ,EAAE,MAAM,CAAC,UAAU,CAAC;IAC5B,YAAY;IACZ,UAAU,EAAE,MAAM,CAAC,YAAY,CAAC,CAAC,OAAO,EAAE;IAC1C,YAAY;IACZ,UAAU,EAAE,MAAM,CAAC,YAAY,CAAC,CAAC,OAAO,EAAE;CAC3C,CAAC,CAAC"}
|
|
@@ -2,21 +2,16 @@
|
|
|
2
2
|
* 可安装服务桥接模块。
|
|
3
3
|
*
|
|
4
4
|
* 提供 `InstallableService` 基类,把带 `install(ctx)` 生命周期的服务
|
|
5
|
-
* 统一桥接到
|
|
5
|
+
* 统一桥接到 Downcity action route 与原生 HTTP route 体系。
|
|
6
6
|
*/
|
|
7
|
-
import { Service, type Context, type EnvRequirement } from "./service.js";
|
|
7
|
+
import { Service, type Context, type EnvRequirement, type ServiceNativeRouteHandler, type ServiceRouteMethod } from "./service.js";
|
|
8
8
|
import { Hook } from "./hook.js";
|
|
9
9
|
import type { CityTableApi } from "../store/table-api.js";
|
|
10
10
|
import type { CreateUserTokenInput, UserTokenIssueResult, RuntimeUser } from "../federation/auth/types.js";
|
|
11
11
|
import type { InstructionDefinition } from "./instruction.js";
|
|
12
12
|
export interface ServiceInstallContext {
|
|
13
13
|
table<TRow extends Record<string, unknown> = Record<string, unknown>>(name: string): CityTableApi<TRow>;
|
|
14
|
-
route(config:
|
|
15
|
-
method: "GET" | "POST";
|
|
16
|
-
path: string;
|
|
17
|
-
auth?: Array<"user" | "admin">;
|
|
18
|
-
handler: (ctx: ServiceRouteContext) => Promise<Response> | Response;
|
|
19
|
-
}): void;
|
|
14
|
+
route(config: ServiceActionRouteConfig | ServiceNativeRouteConfig): void;
|
|
20
15
|
hook: {
|
|
21
16
|
before(fn: (ctx: Context) => Promise<void> | void): void;
|
|
22
17
|
after(fn: (ctx: Context) => Promise<void> | void): void;
|
|
@@ -25,6 +20,42 @@ export interface ServiceInstallContext {
|
|
|
25
20
|
createUserToken(input: CreateUserTokenInput): Promise<UserTokenIssueResult>;
|
|
26
21
|
env(key: string): string | undefined;
|
|
27
22
|
}
|
|
23
|
+
export interface ServiceActionRouteConfig {
|
|
24
|
+
method: "GET" | "POST";
|
|
25
|
+
path: string;
|
|
26
|
+
auth?: Array<"user" | "admin">;
|
|
27
|
+
/**
|
|
28
|
+
* 是否公开访问。
|
|
29
|
+
*
|
|
30
|
+
* 关键说明(中文)
|
|
31
|
+
* - `true` 等价于 `auth: []`
|
|
32
|
+
* - 仅影响 Downcity Action 路由的鉴权要求
|
|
33
|
+
*/
|
|
34
|
+
public?: boolean;
|
|
35
|
+
handler: (ctx: ServiceRouteContext) => Promise<Response> | Response;
|
|
36
|
+
}
|
|
37
|
+
export interface ServiceNativeRouteConfig {
|
|
38
|
+
method: ServiceRouteMethod;
|
|
39
|
+
path: string;
|
|
40
|
+
/**
|
|
41
|
+
* 是否公开访问。
|
|
42
|
+
*
|
|
43
|
+
* 关键说明(中文)
|
|
44
|
+
* - `true` 等价于 `auth: []`
|
|
45
|
+
* - native HTTP route 不进入 action/hook 管线,但仍可声明 route 级鉴权
|
|
46
|
+
*/
|
|
47
|
+
public?: boolean;
|
|
48
|
+
auth?: Array<"user" | "admin">;
|
|
49
|
+
handler: {
|
|
50
|
+
/**
|
|
51
|
+
* 原生 HTTP 请求处理器。
|
|
52
|
+
*
|
|
53
|
+
* 适用于 OAuth callback、第三方 webhook、better-auth 等需要完整
|
|
54
|
+
* `Request` / `Response` 语义的协议入口。
|
|
55
|
+
*/
|
|
56
|
+
request: ServiceNativeRouteHandler;
|
|
57
|
+
};
|
|
58
|
+
}
|
|
28
59
|
export interface ServiceRouteContext {
|
|
29
60
|
/** 当前 user_token 解析出的用户;免登录或 admin 请求时可能为空 */
|
|
30
61
|
user?: RuntimeUser;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"installable-service.d.ts","sourceRoot":"","sources":["../../src/service/installable-service.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,OAAO,EAAE,KAAK,OAAO,EAAE,KAAK,cAAc,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"installable-service.d.ts","sourceRoot":"","sources":["../../src/service/installable-service.ts"],"names":[],"mappings":"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"}
|
|
@@ -2,11 +2,19 @@
|
|
|
2
2
|
* 可安装服务桥接模块。
|
|
3
3
|
*
|
|
4
4
|
* 提供 `InstallableService` 基类,把带 `install(ctx)` 生命周期的服务
|
|
5
|
-
* 统一桥接到
|
|
5
|
+
* 统一桥接到 Downcity action route 与原生 HTTP route 体系。
|
|
6
6
|
*/
|
|
7
7
|
import { Service } from "./service.js";
|
|
8
8
|
import { Hook } from "./hook.js";
|
|
9
9
|
import { TableApi } from "../store/table-api.js";
|
|
10
|
+
function is_native_route_config(config) {
|
|
11
|
+
return typeof config.handler === "object" && config.handler !== null && "request" in config.handler;
|
|
12
|
+
}
|
|
13
|
+
function resolve_route_auth(config) {
|
|
14
|
+
if (config.public === true)
|
|
15
|
+
return [];
|
|
16
|
+
return config.auth;
|
|
17
|
+
}
|
|
10
18
|
// ===========================================================================
|
|
11
19
|
// InstallableService 基类
|
|
12
20
|
// ===========================================================================
|
|
@@ -37,6 +45,15 @@ export class InstallableService extends Service {
|
|
|
37
45
|
return new TableApi(self._db, table);
|
|
38
46
|
},
|
|
39
47
|
route(config) {
|
|
48
|
+
if (is_native_route_config(config)) {
|
|
49
|
+
self._registerNativeRoute({
|
|
50
|
+
method: config.method,
|
|
51
|
+
path: config.path,
|
|
52
|
+
auth: resolve_route_auth(config),
|
|
53
|
+
handler: config.handler.request,
|
|
54
|
+
});
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
40
57
|
// 去掉前导 /,与 client ServiceClient.action() 的 normalizeName 对齐
|
|
41
58
|
const actionId = config.path.replace(/^\/+/, "");
|
|
42
59
|
self.action(actionId, async (svcCtx) => {
|
|
@@ -50,7 +67,7 @@ export class InstallableService extends Service {
|
|
|
50
67
|
status, headers: { "content-type": "application/json" },
|
|
51
68
|
}),
|
|
52
69
|
});
|
|
53
|
-
}, { method: config.method, auth: config
|
|
70
|
+
}, { method: config.method, auth: resolve_route_auth(config) });
|
|
54
71
|
},
|
|
55
72
|
hook: {
|
|
56
73
|
before(fn) { self.globalHook.before(fn); },
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"installable-service.js","sourceRoot":"","sources":["../../src/service/installable-service.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,OAAO,
|
|
1
|
+
{"version":3,"file":"installable-service.js","sourceRoot":"","sources":["../../src/service/installable-service.ts"],"names":[],"mappings":"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"}
|
package/bin/service/service.d.ts
CHANGED
|
@@ -90,6 +90,29 @@ export interface ActionOptions {
|
|
|
90
90
|
/** 允许访问该 action 的身份集合;默认 `["user"]`,传 `[]` 表示免登录 */
|
|
91
91
|
auth?: RouteAuth;
|
|
92
92
|
}
|
|
93
|
+
/** Service route 支持的 HTTP 方法。 */
|
|
94
|
+
export type ServiceRouteMethod = "GET" | "POST" | "OPTIONS" | "ALL";
|
|
95
|
+
/**
|
|
96
|
+
* 原生 HTTP route 处理器。
|
|
97
|
+
*
|
|
98
|
+
* 关键说明(中文)
|
|
99
|
+
* - 处理器拿到完整 `Request`,并直接返回 `Response`
|
|
100
|
+
* - 适用于 OAuth callback、第三方 webhook、better-auth 等外部协议入口
|
|
101
|
+
*/
|
|
102
|
+
export type ServiceNativeRouteHandler = (request: Request) => Promise<Response> | Response;
|
|
103
|
+
/**
|
|
104
|
+
* Service 拥有的原生 HTTP route 定义。
|
|
105
|
+
*/
|
|
106
|
+
export interface ServiceNativeRouteDefinition {
|
|
107
|
+
/** HTTP 方法,`ALL` 表示匹配所有方法。 */
|
|
108
|
+
method: ServiceRouteMethod;
|
|
109
|
+
/** Service namespace 内的路径,例如 `/auth/*`。 */
|
|
110
|
+
path: string;
|
|
111
|
+
/** 允许访问该 route 的身份集合;空数组表示公开。 */
|
|
112
|
+
auth: RouteAuth;
|
|
113
|
+
/** 原生 HTTP route 处理器。 */
|
|
114
|
+
handler: ServiceNativeRouteHandler;
|
|
115
|
+
}
|
|
93
116
|
/**
|
|
94
117
|
* 归一化 action 鉴权配置。
|
|
95
118
|
*
|
|
@@ -110,6 +133,8 @@ export declare class Service {
|
|
|
110
133
|
instruction?: InstructionDefinition;
|
|
111
134
|
/** Action 注册表 */
|
|
112
135
|
private actionMap;
|
|
136
|
+
/** 原生 HTTP route 注册表 */
|
|
137
|
+
private nativeRouteMap;
|
|
113
138
|
_db?: Database;
|
|
114
139
|
_client?: {
|
|
115
140
|
$client: DbClient;
|
|
@@ -142,6 +167,17 @@ export declare class Service {
|
|
|
142
167
|
method: "GET" | "POST";
|
|
143
168
|
auth: RouteAuth;
|
|
144
169
|
}>;
|
|
170
|
+
/**
|
|
171
|
+
* 注册原生 HTTP route(Federation 内部使用)。
|
|
172
|
+
*/
|
|
173
|
+
_registerNativeRoute(definition: {
|
|
174
|
+
method: ServiceRouteMethod;
|
|
175
|
+
path: string;
|
|
176
|
+
auth?: RouteAuth;
|
|
177
|
+
handler: ServiceNativeRouteHandler;
|
|
178
|
+
}): void;
|
|
179
|
+
/** 列出原生 HTTP route 及其元数据(Federation 内部使用)。 */
|
|
180
|
+
_listNativeRouteDefs(): ServiceNativeRouteDefinition[];
|
|
145
181
|
/**
|
|
146
182
|
* 返回 instruction 聚合时使用的动作定义。
|
|
147
183
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../src/service/service.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../src/service/service.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAC9D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACtD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,MAAM,EAAE,KAAK,QAAQ,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAC1D,OAAO,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AACzD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAC;AAC/D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qCAAqC,CAAC;AACzE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAC5D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACxD,OAAO,KAAK,EAAE,2BAA2B,EAAE,kBAAkB,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAC;AAC/G,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAM5D,oBAAoB;AACpB,MAAM,MAAM,aAAa,GAAG,OAAO,GAAG,MAAM,GAAG,OAAO,CAAC;AACvD,iCAAiC;AACjC,MAAM,MAAM,SAAS,GAAG,KAAK,CAAC,OAAO,CAAC,aAAa,EAAE,OAAO,CAAC,CAAC,CAAC;AAM/D,MAAM,WAAW,OAAO;IACtB,8BAA8B;IAC9B,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC/B,qCAAqC;IACrC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAChC,kDAAkD;IAClD,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,uCAAuC;IACvC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,8BAA8B;IAC9B,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,+BAA+B;IAC/B,IAAI,CAAC,EAAE,WAAW,CAAC;IACnB,aAAa;IACb,QAAQ,CAAC,EAAE;QAAE,IAAI,EAAE,aAAa,CAAA;KAAE,CAAC;IACnC,cAAc;IACd,IAAI,CAAC,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IAC3C,sDAAsD;IACtD,OAAO,CAAC,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KAAE,CAAC;IACvE,6CAA6C;IAC7C,QAAQ,CAAC,EAAE,eAAe,CAAC;IAC3B,0BAA0B;IAC1B,UAAU,CAAC,EAAE,IAAI,CAAC;IAClB,0BAA0B;IAC1B,QAAQ,CAAC,EAAE,IAAI,CAAC;IAChB,mCAAmC;IACnC,KAAK,CAAC,EAAE,KAAK,CAAC;IACd,iBAAiB;IACjB,OAAO,CAAC,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IACvC,gBAAgB;IAChB,MAAM,CAAC,EAAE;QAAE,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC;IACxB,gBAAgB;IAChB,EAAE,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;IACjC,kBAAkB;IAClB,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;IACrC;;;;;;OAMG;IACH,SAAS,CAAC,CAAC,OAAO,EAAE,OAAO,CAAC,OAAO,CAAC,GAAG,IAAI,CAAC;CAC7C;AAMD,MAAM,WAAW,cAAc;IAC7B,GAAG,EAAE,MAAM,CAAC;IACZ,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,OAAO,CAAC;CACnB;AAMD,MAAM,WAAW,aAAa;IAC5B,sBAAsB;IACtB,MAAM,CAAC,EAAE,KAAK,GAAG,MAAM,CAAC;IACxB,oDAAoD;IACpD,IAAI,CAAC,EAAE,SAAS,CAAC;CAClB;AAED,iCAAiC;AACjC,MAAM,MAAM,kBAAkB,GAAG,KAAK,GAAG,MAAM,GAAG,SAAS,GAAG,KAAK,CAAC;AAEpE;;;;;;GAMG;AACH,MAAM,MAAM,yBAAyB,GAAG,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC,QAAQ,CAAC,GAAG,QAAQ,CAAC;AAE3F;;GAEG;AACH,MAAM,WAAW,4BAA4B;IAC3C,8BAA8B;IAC9B,MAAM,EAAE,kBAAkB,CAAC;IAC3B,2CAA2C;IAC3C,IAAI,EAAE,MAAM,CAAC;IACb,iCAAiC;IACjC,IAAI,EAAE,SAAS,CAAC;IAChB,yBAAyB;IACzB,OAAO,EAAE,yBAAyB,CAAC;CACpC;AAED;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,CAAC,EAAE,SAAS,GAAG,SAAS,CAG9D;AAMD,qBAAa,OAAO;IAClB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,6CAA6C;IAC7C,QAAQ,CAAC,IAAI,OAAc;IAC3B,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,GAAG,UAAU,CAAC,CAAC;IAC9D,QAAQ,CAAC,GAAG,CAAC,EAAE,cAAc,EAAE,CAAC;IAChC,mBAAmB;IACnB,WAAW,CAAC,EAAE,qBAAqB,CAAC;IAEpC,iBAAiB;IACjB,OAAO,CAAC,SAAS,CAAkF;IACnG,wBAAwB;IACxB,OAAO,CAAC,cAAc,CAAmD;IAIzE,GAAG,CAAC,EAAE,QAAQ,CAAC;IACf,OAAO,CAAC,EAAE;QAAE,OAAO,EAAE,QAAQ,CAAA;KAAE,CAAC;IAChC,cAAc,CAAC,EAAE,aAAa,CAAC;IAC/B,IAAI,CAAC,EAAE,WAAW,CAAC;IACnB,UAAU,CAAC,EAAE,SAAS,CAAC;IAEvB,qCAAqC;IACrC,IAAI,CAAC,EAAE,OAAO,CAAC;IAEf,eAAe;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;gBAEN,OAAO,EAAE;QACnB,EAAE,EAAE,MAAM,CAAC;QACX,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,GAAG,UAAU,CAAC,CAAC;QACrD,GAAG,CAAC,EAAE,cAAc,EAAE,CAAC;KACxB;IASK,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAI9B;;OAEG;IACH,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,QAAQ,EAAE,IAAI,CAAC,EAAE,aAAa,GAAG,MAAM;IAa9D,oBAAoB;IACpB,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAInC,sBAAsB;IACtB,IAAI,IAAI,MAAM,EAAE;IAIhB,uCAAuC;IACvC,eAAe,IAAI,KAAK,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,KAAK,GAAG,MAAM,CAAC;QAAC,IAAI,EAAE,SAAS,CAAA;KAAE,CAAC;IAIrF;;OAEG;IACH,oBAAoB,CAAC,UAAU,EAAE;QAC/B,MAAM,EAAE,kBAAkB,CAAC;QAC3B,IAAI,EAAE,MAAM,CAAC;QACb,IAAI,CAAC,EAAE,SAAS,CAAC;QACjB,OAAO,EAAE,yBAAyB,CAAC;KACpC,GAAG,IAAI;IAeR,8CAA8C;IAC9C,oBAAoB,IAAI,4BAA4B,EAAE;IAItD;;OAEG;IACH,uBAAuB,IAAI,2BAA2B,EAAE;CAOzD;AAED,MAAM,MAAM,kBAAkB,GAAG,OAAO,GAAG,kBAAkB,CAAC"}
|